Add more tests for configuring / using multiple URLs.

This commit is contained in:
Joachim Bauch 2025-07-17 11:43:52 +02:00
commit 9fea05769f
No known key found for this signature in database
GPG key ID: 77C1D22D53E15F02
3 changed files with 310 additions and 1 deletions

View file

@ -26,6 +26,7 @@ import (
"net/url"
"reflect"
"sort"
"strings"
"testing"
"github.com/dlintw/goconf"
@ -611,3 +612,166 @@ func TestBackendCommonSecret(t *testing.T) {
assert.Equal(string(testBackendSecret), string(b2.Secret()))
}
}
func TestBackendChangeUrls(t *testing.T) {
t.Parallel()
CatchLogForTest(t)
require := require.New(t)
assert := assert.New(t)
u1, err := url.Parse("http://domain1.invalid/")
require.NoError(err)
u2, err := url.Parse("http://domain2.invalid/")
require.NoError(err)
original_config := goconf.NewConfigFile()
original_config.AddOption("backend", "backends", "backend1,backend2")
original_config.AddOption("backend", "secret", string(testBackendSecret))
original_config.AddOption("backend1", "urls", u1.String())
original_config.AddOption("backend2", "urls", u2.String())
cfg, err := NewBackendConfiguration(original_config, nil)
require.NoError(err)
if b1 := cfg.GetBackend(u1); assert.NotNil(b1) {
assert.Equal("backend1", b1.Id())
assert.Equal(string(testBackendSecret), string(b1.Secret()))
assert.Equal([]string{u1.String()}, b1.Urls())
}
if b2 := cfg.GetBackend(u2); assert.NotNil(b2) {
assert.Equal("backend2", b2.Id())
assert.Equal(string(testBackendSecret), string(b2.Secret()))
assert.Equal([]string{u2.String()}, b2.Urls())
}
// Add url.
updated_config := goconf.NewConfigFile()
updated_config.AddOption("backend", "backends", "backend1")
updated_config.AddOption("backend", "secret", string(testBackendSecret))
updated_config.AddOption("backend1", "secret", string(testBackendSecret)+"-backend1")
updated_config.AddOption("backend1", "urls", strings.Join([]string{u1.String(), u2.String()}, ","))
cfg.Reload(updated_config)
if b1 := cfg.GetBackend(u1); assert.NotNil(b1) {
assert.Equal("backend1", b1.Id())
assert.Equal(string(testBackendSecret)+"-backend1", string(b1.Secret()))
assert.Equal([]string{u1.String(), u2.String()}, b1.Urls())
}
if b1 := cfg.GetBackend(u2); assert.NotNil(b1) {
assert.Equal("backend1", b1.Id())
assert.Equal(string(testBackendSecret)+"-backend1", string(b1.Secret()))
assert.Equal([]string{u1.String(), u2.String()}, b1.Urls())
}
// No change reload.
cfg.Reload(updated_config)
if b1 := cfg.GetBackend(u1); assert.NotNil(b1) {
assert.Equal("backend1", b1.Id())
assert.Equal(string(testBackendSecret)+"-backend1", string(b1.Secret()))
assert.Equal([]string{u1.String(), u2.String()}, b1.Urls())
}
if b1 := cfg.GetBackend(u2); assert.NotNil(b1) {
assert.Equal("backend1", b1.Id())
assert.Equal(string(testBackendSecret)+"-backend1", string(b1.Secret()))
assert.Equal([]string{u1.String(), u2.String()}, b1.Urls())
}
// Remove url.
updated_config = goconf.NewConfigFile()
updated_config.AddOption("backend", "backends", "backend1")
updated_config.AddOption("backend", "secret", string(testBackendSecret))
updated_config.AddOption("backend1", "urls", u2.String())
cfg.Reload(updated_config)
if b1 := cfg.GetBackend(u2); assert.NotNil(b1) {
assert.Equal("backend1", b1.Id())
assert.Equal(string(testBackendSecret), string(b1.Secret()))
assert.Equal([]string{u2.String()}, b1.Urls())
}
}
func TestBackendConfiguration_EtcdChangeUrls(t *testing.T) {
t.Parallel()
CatchLogForTest(t)
require := require.New(t)
assert := assert.New(t)
etcd, client := NewEtcdClientForTest(t)
url1 := "https://domain1.invalid/foo"
initialSecret1 := string(testBackendSecret) + "-backend1-initial"
secret1 := string(testBackendSecret) + "-backend1"
SetEtcdValue(etcd, "/backends/1_one", []byte("{\"urls\":[\""+url1+"\"],\"secret\":\""+initialSecret1+"\"}"))
config := goconf.NewConfigFile()
config.AddOption("backend", "backendtype", "etcd")
config.AddOption("backend", "backendprefix", "/backends")
cfg, err := NewBackendConfiguration(config, client)
require.NoError(err)
defer cfg.Close()
storage := cfg.storage.(*backendStorageEtcd)
ch := storage.getWakeupChannelForTesting()
ctx, cancel := context.WithTimeout(context.Background(), testTimeout)
defer cancel()
require.NoError(storage.WaitForInitialized(ctx))
if backends := sortBackends(cfg.GetBackends()); assert.Len(backends, 1) &&
assert.Equal([]string{url1}, backends[0].Urls()) &&
assert.Equal(initialSecret1, string(backends[0].Secret())) {
if backend := cfg.GetBackend(mustParse(url1)); assert.NotNil(backend) {
assert.Equal(backends[0], backend)
}
}
url2 := "https://domain1.invalid/bar"
drainWakeupChannel(ch)
SetEtcdValue(etcd, "/backends/1_one", []byte("{\"urls\":[\""+url1+"\",\""+url2+"\"],\"secret\":\""+secret1+"\"}"))
<-ch
if backends := sortBackends(cfg.GetBackends()); assert.Len(backends, 1) &&
assert.Equal([]string{url2, url1}, backends[0].Urls()) &&
assert.Equal(secret1, string(backends[0].Secret())) {
if backend := cfg.GetBackend(mustParse(url1)); assert.NotNil(backend) {
assert.Equal(backends[0], backend)
}
if backend := cfg.GetBackend(mustParse(url2)); assert.NotNil(backend) {
assert.Equal(backends[0], backend)
}
}
url3 := "https://domain2.invalid/foo"
secret3 := string(testBackendSecret) + "-backend3"
drainWakeupChannel(ch)
SetEtcdValue(etcd, "/backends/3_three", []byte("{\"urls\":[\""+url3+"\"],\"secret\":\""+secret3+"\"}"))
<-ch
if backends := sortBackends(cfg.GetBackends()); assert.Len(backends, 2) &&
assert.Equal([]string{url2, url1}, backends[0].Urls()) &&
assert.Equal(secret1, string(backends[0].Secret())) &&
assert.Equal([]string{url3}, backends[1].Urls()) &&
assert.Equal(secret3, string(backends[1].Secret())) {
if backend := cfg.GetBackend(mustParse(url1)); assert.NotNil(backend) {
assert.Equal(backends[0], backend)
} else if backend := cfg.GetBackend(mustParse(url2)); assert.NotNil(backend) {
assert.Equal(backends[0], backend)
} else if backend := cfg.GetBackend(mustParse(url3)); assert.NotNil(backend) {
assert.Equal(backends[1], backend)
}
}
drainWakeupChannel(ch)
DeleteEtcdValue(etcd, "/backends/1_one")
<-ch
if backends := sortBackends(cfg.GetBackends()); assert.Len(backends, 1) {
assert.Equal([]string{url3}, backends[0].Urls())
assert.Equal(secret3, string(backends[0].Secret()))
}
drainWakeupChannel(ch)
DeleteEtcdValue(etcd, "/backends/3_three")
<-ch
_, found := storage.backends["domain1.invalid"]
assert.False(found, "Should have removed host information")
}

View file

@ -131,6 +131,21 @@ func getTestConfigWithMultipleBackends(server *httptest.Server) (*goconf.ConfigF
return config, nil
}
func getTestConfigWithMultipleUrls(server *httptest.Server) (*goconf.ConfigFile, error) {
config, err := getTestConfig(server)
if err != nil {
return nil, err
}
config.RemoveOption("backend", "allowed")
config.RemoveOption("backend", "secret")
config.AddOption("backend", "backends", "backend1")
config.AddOption("backend1", "urls", strings.Join([]string{server.URL + "/one", server.URL + "/two/"}, ","))
config.AddOption("backend1", "secret", string(testBackendSecret))
return config, nil
}
func CreateHubForTestWithConfig(t *testing.T, getConfigFunc func(*httptest.Server) (*goconf.ConfigFile, error)) (*Hub, AsyncEvents, *mux.Router, *httptest.Server) {
require := require.New(t)
r := mux.NewRouter()
@ -173,6 +188,13 @@ func CreateHubWithMultipleBackendsForTest(t *testing.T) (*Hub, AsyncEvents, *mux
return h, events, r, server
}
func CreateHubWithMultipleUrlsForTest(t *testing.T) (*Hub, AsyncEvents, *mux.Router, *httptest.Server) {
h, events, r, server := CreateHubForTestWithConfig(t, getTestConfigWithMultipleUrls)
registerBackendHandlerUrl(t, r, "/one")
registerBackendHandlerUrl(t, r, "/two")
return h, events, r, server
}
func CreateClusteredHubsForTestWithConfig(t *testing.T, getConfigFunc func(*httptest.Server) (*goconf.ConfigFile, error)) (*Hub, *Hub, *mux.Router, *mux.Router, *httptest.Server, *httptest.Server) {
require := require.New(t)
r1 := mux.NewRouter()
@ -4442,6 +4464,59 @@ func TestNoSendBetweenSessionsOnDifferentBackends(t *testing.T) {
}
}
func TestSendBetweenDifferentUrls(t *testing.T) {
t.Parallel()
CatchLogForTest(t)
require := require.New(t)
assert := assert.New(t)
hub, _, _, server := CreateHubWithMultipleUrlsForTest(t)
ctx, cancel := context.WithTimeout(context.Background(), testTimeout)
defer cancel()
client1 := NewTestClient(t, server, hub)
defer client1.CloseWithBye()
params1 := TestBackendClientAuthParams{
UserId: "user1",
}
require.NoError(client1.SendHelloParams(server.URL+"/one", HelloVersionV1, "client", nil, params1))
hello1, err := client1.RunUntilHello(ctx)
require.NoError(err)
client2 := NewTestClient(t, server, hub)
defer client2.CloseWithBye()
params2 := TestBackendClientAuthParams{
UserId: "user2",
}
require.NoError(client2.SendHelloParams(server.URL+"/two", HelloVersionV1, "client", nil, params2))
hello2, err := client2.RunUntilHello(ctx)
require.NoError(err)
recipient1 := MessageClientMessageRecipient{
Type: "session",
SessionId: hello1.Hello.SessionId,
}
recipient2 := MessageClientMessageRecipient{
Type: "session",
SessionId: hello2.Hello.SessionId,
}
data1 := "from-1-to-2"
client1.SendMessage(recipient2, data1) // nolint
data2 := "from-2-to-1"
client2.SendMessage(recipient1, data2) // nolint
var payload string
if err := checkReceiveClientMessage(ctx, client1, "session", hello2.Hello, &payload); assert.NoError(err) {
assert.Equal(data2, payload)
}
if err := checkReceiveClientMessage(ctx, client2, "session", hello1.Hello, &payload); assert.NoError(err) {
assert.Equal(data1, payload)
}
}
func TestNoSameRoomOnDifferentBackends(t *testing.T) {
t.Parallel()
CatchLogForTest(t)
@ -4527,6 +4602,76 @@ func TestNoSameRoomOnDifferentBackends(t *testing.T) {
}
}
func TestSameRoomOnDifferentUrls(t *testing.T) {
t.Parallel()
CatchLogForTest(t)
require := require.New(t)
assert := assert.New(t)
hub, _, _, server := CreateHubWithMultipleUrlsForTest(t)
ctx, cancel := context.WithTimeout(context.Background(), testTimeout)
defer cancel()
client1 := NewTestClient(t, server, hub)
defer client1.CloseWithBye()
params1 := TestBackendClientAuthParams{
UserId: "user1",
}
require.NoError(client1.SendHelloParams(server.URL+"/one", HelloVersionV1, "client", nil, params1))
hello1, err := client1.RunUntilHello(ctx)
require.NoError(err)
client2 := NewTestClient(t, server, hub)
defer client2.CloseWithBye()
params2 := TestBackendClientAuthParams{
UserId: "user2",
}
require.NoError(client2.SendHelloParams(server.URL+"/two", HelloVersionV1, "client", nil, params2))
hello2, err := client2.RunUntilHello(ctx)
require.NoError(err)
// Join room by id.
roomId := "test-room"
roomMsg, err := client1.JoinRoom(ctx, roomId)
require.NoError(err)
require.Equal(roomId, roomMsg.Room.RoomId)
roomMsg, err = client2.JoinRoom(ctx, roomId)
require.NoError(err)
require.Equal(roomId, roomMsg.Room.RoomId)
WaitForUsersJoined(ctx, t, client1, hello1, client2, hello2)
hub.ru.RLock()
var rooms []*Room
for _, room := range hub.rooms {
defer room.Close()
rooms = append(rooms, room)
}
hub.ru.RUnlock()
assert.Len(rooms, 1)
recipient := MessageClientMessageRecipient{
Type: "room",
}
data1 := "from-1-to-2"
client1.SendMessage(recipient, data1) // nolint
data2 := "from-2-to-1"
client2.SendMessage(recipient, data2) // nolint
var payload string
if err := checkReceiveClientMessage(ctx, client1, "room", hello2.Hello, &payload); assert.NoError(err) {
assert.Equal(data2, payload)
}
if err := checkReceiveClientMessage(ctx, client2, "room", hello1.Hello, &payload); assert.NoError(err) {
assert.Equal(data1, payload)
}
}
func TestClientSendOffer(t *testing.T) {
CatchLogForTest(t)
for _, subtest := range clusteredTests {

View file

@ -126,7 +126,7 @@ func checkMessageType(message *ServerMessage, expectedType string) error {
func checkMessageSender(hub *Hub, sender *MessageServerMessageSender, senderType string, hello *HelloServerMessage) error {
if sender.Type != senderType {
return fmt.Errorf("Expected sender type %s, got %s", senderType, sender.SessionId)
return fmt.Errorf("Expected sender type %s, got %s", senderType, sender.Type)
} else if sender.SessionId != hello.SessionId {
return fmt.Errorf("Expected session id %+v, got %+v",
getPubliceSessionIdData(hub, hello.SessionId), getPubliceSessionIdData(hub, sender.SessionId))