roomserver/alias: Add test cases, load from DB if appserviceAPI says AliasExists

Signed-off-by: Serra Allgood <serra@allgood.dev>
This commit is contained in:
Serra Allgood 2019-06-01 17:33:32 -07:00
parent 6a7cc65cdb
commit da234d4dab
2 changed files with 149 additions and 21 deletions

View file

@ -84,6 +84,19 @@ func (r *RoomserverAliasAPI) SetRoomAlias(
return r.sendUpdatedAliasesEvent(context.TODO(), request.UserID, request.RoomID)
}
func getRoomIDFromDB(
ctx context.Context,
db RoomserverAliasAPIDatabase,
request *roomserverAPI.GetRoomIDForAliasRequest,
) (string, error) {
roomID, err := db.GetRoomIDForAlias(ctx, request.Alias)
if err != nil {
return "", err
}
return roomID, nil
}
// GetRoomIDForAlias implements alias.RoomserverAliasAPI
func (r *RoomserverAliasAPI) GetRoomIDForAlias(
ctx context.Context,
@ -91,12 +104,12 @@ func (r *RoomserverAliasAPI) GetRoomIDForAlias(
response *roomserverAPI.GetRoomIDForAliasResponse,
) error {
// Look up the room ID in the database
roomID, err := r.DB.GetRoomIDForAlias(ctx, request.Alias)
roomID, err := getRoomIDFromDB(ctx, r.DB, request)
if err != nil {
return err
}
if len(roomID) == 0 {
if roomID == "" {
// No rooms found locally, try our application services by making a call to
// the appservice component
aliasReq := appserviceAPI.RoomAliasExistsRequest{Alias: request.Alias}
@ -104,6 +117,13 @@ func (r *RoomserverAliasAPI) GetRoomIDForAlias(
if err = r.AppserviceAPI.RoomAliasExists(ctx, &aliasReq, &aliasResp); err != nil {
return err
}
if aliasResp.AliasExists {
roomID, err = getRoomIDFromDB(ctx, r.DB, request)
if err != nil {
return err
}
}
}
response.RoomID = roomID

View file

@ -1,4 +1,4 @@
// Copyright 2017 Vector Creations Ltd
// Copyright 2019 Serra Allgood
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@ -17,20 +17,21 @@ package alias
import (
"context"
"fmt"
"strings"
"testing"
appserviceAPI "github.com/matrix-org/dendrite/appservice/api"
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
)
type MockRoomserverAliasAPIDatabase struct{}
func (db MockRoomserverAliasAPIDatabase) SetRoomAlias(ctx context.Context, alias string, roomID string) error {
return nil
type MockRoomserverAliasAPIDatabase struct {
methodModes map[string]string
attempts int
}
func (db MockRoomserverAliasAPIDatabase) GetRoomIDForAlias(ctx context.Context, alias string) (string, error) {
return "123", nil
// Those methods can be essentially noop
func (db MockRoomserverAliasAPIDatabase) SetRoomAlias(ctx context.Context, alias string, roomID string) error {
return nil
}
func (db MockRoomserverAliasAPIDatabase) GetAliasesForRoomID(ctx context.Context, roomID string) ([]string, error) {
@ -42,8 +43,36 @@ func (db MockRoomserverAliasAPIDatabase) RemoveRoomAlias(ctx context.Context, al
return nil
}
type MockAppServiceQueryAPI struct{}
// This method needs to change depending on test case
func (db MockRoomserverAliasAPIDatabase) GetRoomIDForAlias(ctx context.Context, alias string) (string, error) {
switch db.methodModes["GetRoomIDForAlias"] {
case "empty":
return "", nil
case "error":
return "", fmt.Errorf("found an error from GetRoomIDForAlias")
case "found":
return "123", nil
case "emptyFound":
switch db.attempts {
case 0:
db.attempts = 1
return "", nil
case 1:
db.attempts = 0
return "123", nil
default:
return "", nil
}
default:
return "", fmt.Errorf("Unknown option used")
}
}
type MockAppServiceQueryAPI struct {
methodModes map[string]string
}
// This method can be noop
func (q MockAppServiceQueryAPI) UserIDExists(
ctx context.Context,
req *appserviceAPI.UserIDExistsRequest,
@ -57,26 +86,48 @@ func (q MockAppServiceQueryAPI) RoomAliasExists(
req *appserviceAPI.RoomAliasExistsRequest,
resp *appserviceAPI.RoomAliasExistsResponse,
) error {
return fmt.Errorf("Should not have called this")
switch q.methodModes["RoomAliasExists"] {
case "error":
return fmt.Errorf("found an error from RoomAliasExists")
case "found":
resp.AliasExists = true
return nil
case "empty":
resp.AliasExists = false
return nil
default:
return fmt.Errorf("Unknown option used")
}
}
func TestGetRoomIDForAlias(t *testing.T) {
type args struct {
type arguments struct {
ctx context.Context
request *roomserverAPI.GetRoomIDForAliasRequest
response *roomserverAPI.GetRoomIDForAliasResponse
}
args := arguments{
context.Background(),
&roomserverAPI.GetRoomIDForAliasRequest{},
&roomserverAPI.GetRoomIDForAliasResponse{},
}
setup := func(modes map[string]string) *RoomserverAliasAPI {
mockAliasAPIDB := MockRoomserverAliasAPIDatabase{modes, 0}
mockAppServiceQueryAPI := MockAppServiceQueryAPI{modes}
return &RoomserverAliasAPI{
DB: mockAliasAPIDB,
AppserviceAPI: mockAppServiceQueryAPI,
}
}
t.Run("Found local alias", func(t *testing.T) {
aliasAPI := &RoomserverAliasAPI{
DB: MockRoomserverAliasAPIDatabase{},
AppserviceAPI: MockAppServiceQueryAPI{},
}
args := args{
context.Background(),
&roomserverAPI.GetRoomIDForAliasRequest{},
&roomserverAPI.GetRoomIDForAliasResponse{},
}
methodModes := make(map[string]string)
methodModes["GetRoomIDForAlias"] = "found"
methodModes["RoomAliasExists"] = "error"
aliasAPI := setup(methodModes)
err := aliasAPI.GetRoomIDForAlias(args.ctx, args.request, args.response)
if err != nil {
@ -87,4 +138,61 @@ func TestGetRoomIDForAlias(t *testing.T) {
t.Errorf("Got %s; wanted 123", args.response.RoomID)
}
})
t.Run("found appservice alias", func(t *testing.T) {
methodModes := make(map[string]string)
methodModes["GetRoomIDForAlias"] = "emptyFound"
methodModes["RoomAliasExists"] = "found"
aliasAPI := setup(methodModes)
if err := aliasAPI.GetRoomIDForAlias(args.ctx, args.request, args.response); err != nil {
t.Fatalf("Got %s; wanted no error", err)
}
if args.response.RoomID != "123" {
t.Errorf("Got %s; wanted 123", args.response.RoomID)
}
})
t.Run("error returned from DB", func(t *testing.T) {
methodModes := make(map[string]string)
methodModes["GetRoomIDForAlias"] = "error"
aliasAPI := setup(methodModes)
err := aliasAPI.GetRoomIDForAlias(args.ctx, args.request, args.response)
if err == nil {
t.Fatalf("Got no error; wanted error from DB")
} else if !strings.Contains(err.Error(), "GetRoomIDForAlias") {
t.Errorf("Got %s; wanted error from GetRoomIDForAlias", err)
}
})
t.Run("error returned from appserviceAPI", func(t *testing.T) {
methodModes := make(map[string]string)
methodModes["GetRoomIDForAlias"] = "empty"
methodModes["RoomAliasExists"] = "error"
aliasAPI := setup(methodModes)
err := aliasAPI.GetRoomIDForAlias(args.ctx, args.request, args.response)
if err == nil {
t.Fatalf("Got no error; wanted error from appserviceAPI")
} else if !strings.Contains(err.Error(), "RoomAliasExists") {
t.Errorf("Got %s; wanted error from RoomAliasExists", err)
}
})
t.Run("no errors but no alias", func(t *testing.T) {
methodModes := make(map[string]string)
methodModes["GetRoomIDForAlias"] = "empty"
methodModes["RoomAliasExists"] = "empty"
aliasAPI := setup(methodModes)
args.response.RoomID = "Should be empty"
if err := aliasAPI.GetRoomIDForAlias(args.ctx, args.request, args.response); err != nil {
t.Fatalf("Got %s; wanted no error", err)
}
if args.response.RoomID != "" {
t.Errorf("response.RoomID should have been empty")
}
})
}