sliding-sync/internal/roomname_test.go
2023-10-19 11:19:28 +01:00

306 lines
6.4 KiB
Go

package internal
import "testing"
func TestCalculateRoomName(t *testing.T) {
testCases := []struct {
roomName string
canonicalAlias string
heroes []Hero
joinedCount int
invitedCount int
maxNumNamesPerRoom int
wantRoomName string
wantCalculated bool
}{
// Room name takes precedence
{
roomName: "My Room Name",
canonicalAlias: "#alias:localhost",
joinedCount: 5,
invitedCount: 1,
maxNumNamesPerRoom: 3,
heroes: []Hero{
{
ID: "@alice:localhost",
Name: "Alice",
},
{
ID: "@bob:localhost",
Name: "Bob",
},
},
wantRoomName: "My Room Name",
},
// Alias takes precedence if room name is missing
{
canonicalAlias: "#alias:localhost",
joinedCount: 5,
invitedCount: 1,
maxNumNamesPerRoom: 3,
heroes: []Hero{
{
ID: "@alice:localhost",
Name: "Alice",
},
{
ID: "@bob:localhost",
Name: "Bob",
},
},
wantRoomName: "#alias:localhost",
},
// ... and N others (large group chat)
{
joinedCount: 5,
invitedCount: 1,
maxNumNamesPerRoom: 3,
heroes: []Hero{
{
ID: "@alice:localhost",
Name: "Alice",
},
{
ID: "@bob:localhost",
Name: "Bob",
},
},
wantRoomName: "Alice, Bob and 3 others",
wantCalculated: true,
},
// Small group chat
{
joinedCount: 4,
invitedCount: 0,
maxNumNamesPerRoom: 3,
heroes: []Hero{
{
ID: "@alice:localhost",
Name: "Alice",
},
{
ID: "@bob:localhost",
Name: "Bob",
},
{
ID: "@charlie:localhost",
Name: "Charlie",
},
},
wantRoomName: "Alice, Bob and Charlie",
wantCalculated: true,
},
// DM room
{
joinedCount: 2,
invitedCount: 0,
maxNumNamesPerRoom: 3,
heroes: []Hero{
{
ID: "@alice:localhost",
Name: "Alice",
},
},
wantRoomName: "Alice",
wantCalculated: true,
},
// 3-way room
{
joinedCount: 3,
invitedCount: 0,
maxNumNamesPerRoom: 3,
heroes: []Hero{
{
ID: "@alice:localhost",
Name: "Alice",
},
{
ID: "@bob:localhost",
Name: "Bob",
},
},
wantRoomName: "Alice and Bob",
wantCalculated: true,
},
// 3-way room, one person invited with no display name
{
joinedCount: 2,
invitedCount: 1,
maxNumNamesPerRoom: 3,
heroes: []Hero{
{
ID: "@alice:localhost",
Name: "Alice",
},
{
ID: "@bob:localhost",
},
},
wantRoomName: "Alice and @bob:localhost",
wantCalculated: true,
},
// 3-way room, no display names
{
joinedCount: 2,
invitedCount: 1,
maxNumNamesPerRoom: 3,
heroes: []Hero{
{
ID: "@alice:localhost",
},
{
ID: "@bob:localhost",
},
},
wantRoomName: "@alice:localhost and @bob:localhost",
wantCalculated: true,
},
// disambiguation all
{
joinedCount: 10,
invitedCount: 0,
maxNumNamesPerRoom: 3,
heroes: []Hero{
{
ID: "@alice:localhost",
Name: "Alice",
},
{
ID: "@bob:localhost",
Name: "Alice",
},
{
ID: "@charlie:localhost",
Name: "Alice",
},
},
wantRoomName: "Alice (@alice:localhost), Alice (@bob:localhost), Alice (@charlie:localhost) and 6 others",
wantCalculated: true,
},
// disambiguation some
{
joinedCount: 10,
invitedCount: 0,
maxNumNamesPerRoom: 3,
heroes: []Hero{
{
ID: "@alice:localhost",
Name: "Alice",
},
{
ID: "@bob:localhost",
Name: "Bob",
},
{
ID: "@charlie:localhost",
Name: "Alice",
},
},
wantRoomName: "Alice (@alice:localhost), Bob, Alice (@charlie:localhost) and 6 others",
wantCalculated: true,
},
// disambiguation, faking user IDs as display names
{
joinedCount: 3,
invitedCount: 0,
maxNumNamesPerRoom: 3,
heroes: []Hero{
{
ID: "@evil:localhost",
Name: "@alice:localhost",
},
{
ID: "@alice:localhost",
},
},
wantRoomName: "@alice:localhost (@evil:localhost) and @alice:localhost (@alice:localhost)",
wantCalculated: true,
},
// left room
{
joinedCount: 1,
invitedCount: 0,
maxNumNamesPerRoom: 3,
heroes: []Hero{
{
ID: "@alice:localhost",
Name: "Alice",
},
{
ID: "@bob:localhost",
Name: "Bob",
},
},
wantRoomName: "Empty Room (was Alice and Bob)",
wantCalculated: true,
},
// empty room
{
joinedCount: 1,
invitedCount: 0,
maxNumNamesPerRoom: 3,
heroes: []Hero{},
wantRoomName: "Empty Room",
},
}
for _, tc := range testCases {
gotName, gotCalculated := CalculateRoomName(&RoomMetadata{
NameEvent: tc.roomName,
CanonicalAlias: tc.canonicalAlias,
Heroes: tc.heroes,
JoinCount: tc.joinedCount,
InviteCount: tc.invitedCount,
}, tc.maxNumNamesPerRoom)
if gotName != tc.wantRoomName {
t.Errorf("got %s want %s for test case: %+v", gotName, tc.wantRoomName, tc)
}
if gotCalculated != tc.wantCalculated {
t.Errorf("got %v want %v for test case: %+v", gotCalculated, tc.wantCalculated, tc)
}
}
}
func TestCopyHeroes(t *testing.T) {
const alice = "@alice:test"
const bob = "@bob:test"
const chris = "@chris:test"
m1 := RoomMetadata{Heroes: []Hero{
{ID: alice},
{ID: bob},
{ID: chris},
}}
m2 := m1.DeepCopy()
// Uncomment this to see why CopyHeroes is necessary!
//m2 := m1
t.Logf("Compare heroes:\n\tm1=%v\n\tm2=%v", m1.Heroes, m2.Heroes)
t.Log("Remove chris from m1")
m1.RemoveHero(chris)
t.Logf("Compare heroes:\n\tm1=%v\n\tm2=%v", m1.Heroes, m2.Heroes)
assertSliceIDs(t, "m1.Heroes", m1.Heroes, []string{alice, bob})
assertSliceIDs(t, "m2.Heroes", m2.Heroes, []string{alice, bob, chris})
t.Log("Remove alice from m1")
m1.RemoveHero(alice)
t.Logf("Compare heroes:\n\tm1=%v\n\tm2=%v", m1.Heroes, m2.Heroes)
assertSliceIDs(t, "m1.Heroes", m1.Heroes, []string{bob})
assertSliceIDs(t, "m2.Heroes", m2.Heroes, []string{alice, bob, chris})
}
func assertSliceIDs(t *testing.T, desc string, h []Hero, ids []string) {
if len(h) != len(ids) {
t.Errorf("%s has length %d, expected %d", desc, len(h), len(ids))
}
for index, id := range ids {
if h[index].ID != id {
t.Errorf("%s[%d] ID is %s, expected %s", desc, index, h[index].ID, id)
}
}
}