| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320 |
- package foodgroup
- import (
- "context"
- "testing"
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/mock"
- "github.com/mk6i/open-oscar-server/state"
- "github.com/mk6i/open-oscar-server/wire"
- )
- func TestBuddyService_RightsQuery(t *testing.T) {
- svc := NewBuddyService(nil, nil, nil, nil, nil, newMockContactPreAuthorizer(t))
- want := wire.SNACMessage{
- Frame: wire.SNACFrame{
- FoodGroup: wire.Buddy,
- SubGroup: wire.BuddyRightsReply,
- RequestID: 1234,
- },
- Body: wire.SNAC_0x03_0x03_BuddyRightsReply{
- TLVRestBlock: wire.TLVRestBlock{
- TLVList: wire.TLVList{
- wire.NewTLVBE(wire.BuddyTLVTagsParmMaxBuddies, uint16(100)),
- wire.NewTLVBE(wire.BuddyTLVTagsParmMaxWatchers, uint16(100)),
- wire.NewTLVBE(wire.BuddyTLVTagsParmMaxIcqBroad, uint16(100)),
- wire.NewTLVBE(wire.BuddyTLVTagsParmMaxTempBuddies, uint16(100)),
- },
- },
- },
- }
- have := svc.RightsQuery(context.TODO(), wire.SNACFrame{RequestID: 1234})
- assert.Equal(t, want, have)
- }
- func TestBuddyService_AddBuddies(t *testing.T) {
- tests := []struct {
- // name is the name of the test
- name string
- // instance is the client session
- instance *state.SessionInstance
- // bodyIn is the input SNAC
- bodyIn wire.SNAC_0x03_0x04_BuddyAddBuddies
- // mockParams is the list of params sent to mocks that satisfy this
- // method's dependencies
- mockParams mockParams
- // wantSNAC is the expected SNAC returned when buddies are rejected
- wantSNAC *wire.SNACMessage
- // wantErr is the expected error
- wantErr error
- }{
- {
- name: "add 2 buddies, sign-on complete",
- instance: newTestInstance("user_screen_name", sessOptSignonComplete),
- bodyIn: wire.SNAC_0x03_0x04_BuddyAddBuddies{
- Buddies: []struct {
- ScreenName string `oscar:"len_prefix=uint8"`
- }{
- {
- ScreenName: "buddy_1_online",
- },
- {
- ScreenName: "buddy_2_offline",
- },
- },
- },
- mockParams: mockParams{
- clientSideBuddyListManagerParams: clientSideBuddyListManagerParams{
- addBuddyParams: addBuddyParams{
- {
- me: state.NewIdentScreenName("user_screen_name"),
- them: state.NewIdentScreenName("buddy_1_online"),
- },
- {
- me: state.NewIdentScreenName("user_screen_name"),
- them: state.NewIdentScreenName("buddy_2_offline"),
- },
- },
- },
- buddyBroadcasterParams: buddyBroadcasterParams{
- broadcastVisibilityParams: broadcastVisibilityParams{
- {
- from: state.NewIdentScreenName("user_screen_name"),
- filter: []state.IdentScreenName{
- state.NewIdentScreenName("buddy_1_online"),
- state.NewIdentScreenName("buddy_2_offline"),
- },
- },
- },
- },
- },
- },
- {
- name: "add 2 buddies, sign-on not complete",
- instance: newTestInstance("user_screen_name"),
- bodyIn: wire.SNAC_0x03_0x04_BuddyAddBuddies{
- Buddies: []struct {
- ScreenName string `oscar:"len_prefix=uint8"`
- }{
- {
- ScreenName: "buddy_1_online",
- },
- {
- ScreenName: "buddy_2_offline",
- },
- },
- },
- mockParams: mockParams{
- clientSideBuddyListManagerParams: clientSideBuddyListManagerParams{
- addBuddyParams: addBuddyParams{
- {
- me: state.NewIdentScreenName("user_screen_name"),
- them: state.NewIdentScreenName("buddy_1_online"),
- },
- {
- me: state.NewIdentScreenName("user_screen_name"),
- them: state.NewIdentScreenName("buddy_2_offline"),
- },
- },
- },
- },
- },
- {
- name: "UIN blocked by pre-authorization",
- instance: newTestInstance("100002", sessOptSignonComplete),
- bodyIn: wire.SNAC_0x03_0x04_BuddyAddBuddies{
- Buddies: []struct {
- ScreenName string `oscar:"len_prefix=uint8"`
- }{
- {ScreenName: "100001"},
- },
- },
- mockParams: mockParams{
- contactPreAuthorizerParams: contactPreAuthorizerParams{
- requiresAuthorizationParams: requiresAuthorizationParams{
- {
- owner: state.NewIdentScreenName("100001"),
- requester: state.NewIdentScreenName("100002"),
- result: true,
- },
- },
- },
- },
- wantSNAC: &wire.SNACMessage{
- Frame: wire.SNACFrame{
- FoodGroup: wire.Buddy,
- SubGroup: wire.BuddyRejectNotification,
- RequestID: 42,
- },
- Body: wire.SNAC_0x03_0x0A_BuddyRejectNotification{
- Buddies: []struct {
- ScreenName string `oscar:"len_prefix=uint8"`
- }{
- {ScreenName: "100001"},
- },
- },
- },
- },
- {
- name: "AIM session rejects ICQ UIN on client-side buddy path",
- instance: newTestInstance("aimuser", sessOptSignonComplete),
- bodyIn: wire.SNAC_0x03_0x04_BuddyAddBuddies{
- Buddies: []struct {
- ScreenName string `oscar:"len_prefix=uint8"`
- }{
- {ScreenName: "100001"},
- },
- },
- wantSNAC: &wire.SNACMessage{
- Frame: wire.SNACFrame{
- FoodGroup: wire.Buddy,
- SubGroup: wire.BuddyRejectNotification,
- RequestID: 42,
- },
- Body: wire.SNAC_0x03_0x0A_BuddyRejectNotification{
- Buddies: []struct {
- ScreenName string `oscar:"len_prefix=uint8"`
- }{
- {ScreenName: "100001"},
- },
- },
- },
- },
- {
- name: "AIM session rejects ICQ UIN but adds non-UIN buddy in same batch",
- instance: newTestInstance("aimuser", sessOptSignonComplete),
- bodyIn: wire.SNAC_0x03_0x04_BuddyAddBuddies{
- Buddies: []struct {
- ScreenName string `oscar:"len_prefix=uint8"`
- }{
- {ScreenName: "100001"},
- {ScreenName: "buddyalice"},
- },
- },
- mockParams: mockParams{
- clientSideBuddyListManagerParams: clientSideBuddyListManagerParams{
- addBuddyParams: addBuddyParams{
- {
- me: state.NewIdentScreenName("aimuser"),
- them: state.NewIdentScreenName("buddyalice"),
- },
- },
- },
- buddyBroadcasterParams: buddyBroadcasterParams{
- broadcastVisibilityParams: broadcastVisibilityParams{
- {
- from: state.NewIdentScreenName("aimuser"),
- filter: []state.IdentScreenName{state.NewIdentScreenName("buddyalice")},
- },
- },
- },
- },
- wantSNAC: &wire.SNACMessage{
- Frame: wire.SNACFrame{
- FoodGroup: wire.Buddy,
- SubGroup: wire.BuddyRejectNotification,
- RequestID: 42,
- },
- Body: wire.SNAC_0x03_0x0A_BuddyRejectNotification{
- Buddies: []struct {
- ScreenName string `oscar:"len_prefix=uint8"`
- }{
- {ScreenName: "100001"},
- },
- },
- },
- },
- {
- name: "non-UIN skips pre-auth check",
- instance: newTestInstance("100002", sessOptSignonComplete),
- bodyIn: wire.SNAC_0x03_0x04_BuddyAddBuddies{
- Buddies: []struct {
- ScreenName string `oscar:"len_prefix=uint8"`
- }{
- {ScreenName: "somebody"},
- },
- },
- mockParams: mockParams{
- clientSideBuddyListManagerParams: clientSideBuddyListManagerParams{
- addBuddyParams: addBuddyParams{
- {
- me: state.NewIdentScreenName("100002"),
- them: state.NewIdentScreenName("somebody"),
- },
- },
- },
- buddyBroadcasterParams: buddyBroadcasterParams{
- broadcastVisibilityParams: broadcastVisibilityParams{
- {
- from: state.NewIdentScreenName("100002"),
- filter: []state.IdentScreenName{state.NewIdentScreenName("somebody")},
- },
- },
- },
- },
- },
- {
- name: "partial batch, UIN blocked",
- instance: newTestInstance("100002", sessOptSignonComplete),
- bodyIn: wire.SNAC_0x03_0x04_BuddyAddBuddies{
- Buddies: []struct {
- ScreenName string `oscar:"len_prefix=uint8"`
- }{
- {ScreenName: "100001"},
- {ScreenName: "100003"},
- },
- },
- mockParams: mockParams{
- contactPreAuthorizerParams: contactPreAuthorizerParams{
- requiresAuthorizationParams: requiresAuthorizationParams{
- {
- owner: state.NewIdentScreenName("100001"),
- requester: state.NewIdentScreenName("100002"),
- result: true,
- },
- {
- owner: state.NewIdentScreenName("100003"),
- requester: state.NewIdentScreenName("100002"),
- result: false,
- },
- },
- },
- clientSideBuddyListManagerParams: clientSideBuddyListManagerParams{
- addBuddyParams: addBuddyParams{
- {
- me: state.NewIdentScreenName("100002"),
- them: state.NewIdentScreenName("100003"),
- },
- },
- },
- buddyBroadcasterParams: buddyBroadcasterParams{
- broadcastVisibilityParams: broadcastVisibilityParams{
- {
- from: state.NewIdentScreenName("100002"),
- filter: []state.IdentScreenName{state.NewIdentScreenName("100003")},
- },
- },
- },
- },
- wantSNAC: &wire.SNACMessage{
- Frame: wire.SNACFrame{
- FoodGroup: wire.Buddy,
- SubGroup: wire.BuddyRejectNotification,
- RequestID: 42,
- },
- Body: wire.SNAC_0x03_0x0A_BuddyRejectNotification{
- Buddies: []struct {
- ScreenName string `oscar:"len_prefix=uint8"`
- }{
- {ScreenName: "100001"},
- },
- },
- },
- },
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- clientSideBuddyListManager := newMockClientSideBuddyListManager(t)
- for _, params := range tt.mockParams.addBuddyParams {
- clientSideBuddyListManager.EXPECT().
- AddBuddy(matchContext(), params.me, params.them).
- Return(params.err)
- }
- mockBuddyBroadcaster := newMockbuddyBroadcaster(t)
- for _, params := range tt.mockParams.broadcastVisibilityParams {
- mockBuddyBroadcaster.EXPECT().
- BroadcastVisibility(matchContext(), matchSession(params.from), params.filter, true).
- Return(params.err)
- }
- contactPreAuth := newMockContactPreAuthorizer(t)
- for _, params := range tt.mockParams.requiresAuthorizationParams {
- contactPreAuth.EXPECT().RequiresAuthorization(matchContext(), params.owner, params.requester).Return(params.result, params.err)
- }
- svc := BuddyService{
- clientSideBuddyListManager: clientSideBuddyListManager,
- buddyBroadcaster: mockBuddyBroadcaster,
- contactPreAuthorizer: contactPreAuth,
- }
- rejectSNAC, haveErr := svc.AddBuddies(context.Background(), tt.instance, wire.SNACFrame{RequestID: 42}, tt.bodyIn)
- assert.Equal(t, tt.wantSNAC, rejectSNAC)
- assert.ErrorIs(t, haveErr, tt.wantErr)
- assert.True(t, tt.instance.ContactsInit(), "AddBuddies marks client-side buddy list loaded")
- })
- }
- }
- func TestBuddyService_DelBuddies(t *testing.T) {
- tests := []struct {
- // name is the name of the test
- name string
- // instance is the client session
- instance *state.SessionInstance
- // bodyIn is the input SNAC
- bodyIn wire.SNAC_0x03_0x05_BuddyDelBuddies
- // mockParams is the list of params sent to mocks that satisfy this
- // method's dependencies
- mockParams mockParams
- // wantErr is the expected error
- wantErr error
- }{
- {
- name: "delete 2 buddies",
- instance: newTestInstance("user_screen_name", sessOptSignonComplete),
- bodyIn: wire.SNAC_0x03_0x05_BuddyDelBuddies{
- Buddies: []struct {
- ScreenName string `oscar:"len_prefix=uint8"`
- }{
- {
- ScreenName: "buddy_1_online",
- },
- {
- ScreenName: "buddy_2_offline",
- },
- },
- },
- mockParams: mockParams{
- buddyBroadcasterParams: buddyBroadcasterParams{
- broadcastVisibilityParams: broadcastVisibilityParams{
- {
- from: state.NewIdentScreenName("user_screen_name"),
- filter: []state.IdentScreenName{
- state.NewIdentScreenName("buddy_1_online"),
- state.NewIdentScreenName("buddy_2_offline"),
- },
- },
- },
- },
- clientSideBuddyListManagerParams: clientSideBuddyListManagerParams{
- deleteBuddyParams: deleteBuddyParams{
- {
- me: state.NewIdentScreenName("user_screen_name"),
- them: state.NewIdentScreenName("buddy_1_online"),
- },
- {
- me: state.NewIdentScreenName("user_screen_name"),
- them: state.NewIdentScreenName("buddy_2_offline"),
- },
- },
- },
- },
- },
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- mockBuddyBroadcaster := newMockbuddyBroadcaster(t)
- for _, params := range tt.mockParams.broadcastVisibilityParams {
- mockBuddyBroadcaster.EXPECT().
- BroadcastVisibility(matchContext(), matchSession(params.from), params.filter, true).
- Return(params.err)
- }
- clientSideBuddyListManager := newMockClientSideBuddyListManager(t)
- for _, params := range tt.mockParams.deleteBuddyParams {
- clientSideBuddyListManager.EXPECT().
- RemoveBuddy(matchContext(), params.me, params.them).
- Return(params.err)
- }
- svc := BuddyService{
- buddyBroadcaster: mockBuddyBroadcaster,
- clientSideBuddyListManager: clientSideBuddyListManager,
- }
- assert.ErrorIs(t, tt.wantErr, svc.DelBuddies(context.Background(), tt.instance, tt.bodyIn))
- })
- }
- }
- func TestBuddyService_AddTempBuddies(t *testing.T) {
- tests := []struct {
- // name is the name of the test
- name string
- // instance is the client session
- instance *state.SessionInstance
- // bodyIn is the input SNAC
- bodyIn wire.SNAC_0x03_0x0F_BuddyAddTempBuddies
- // mockParams is the list of params sent to mocks that satisfy this
- // method's dependencies
- mockParams mockParams
- // wantErr is the expected error
- wantErr error
- }{
- {
- name: "add 2 buddies, sign-on complete",
- instance: newTestInstance("user_screen_name", sessOptSignonComplete),
- bodyIn: wire.SNAC_0x03_0x0F_BuddyAddTempBuddies{
- Buddies: []struct {
- ScreenName string `oscar:"len_prefix=uint8"`
- }{
- {
- ScreenName: "buddy_1_online",
- },
- {
- ScreenName: "buddy_2_offline",
- },
- },
- },
- mockParams: mockParams{
- clientSideBuddyListManagerParams: clientSideBuddyListManagerParams{
- addBuddyParams: addBuddyParams{
- {
- me: state.NewIdentScreenName("user_screen_name"),
- them: state.NewIdentScreenName("buddy_1_online"),
- },
- {
- me: state.NewIdentScreenName("user_screen_name"),
- them: state.NewIdentScreenName("buddy_2_offline"),
- },
- },
- },
- buddyBroadcasterParams: buddyBroadcasterParams{
- broadcastVisibilityParams: broadcastVisibilityParams{
- {
- from: state.NewIdentScreenName("user_screen_name"),
- filter: []state.IdentScreenName{
- state.NewIdentScreenName("buddy_1_online"),
- state.NewIdentScreenName("buddy_2_offline"),
- },
- },
- },
- },
- },
- },
- {
- name: "add 2 buddies, sign-on not complete",
- instance: newTestInstance("user_screen_name"),
- bodyIn: wire.SNAC_0x03_0x0F_BuddyAddTempBuddies{
- Buddies: []struct {
- ScreenName string `oscar:"len_prefix=uint8"`
- }{
- {
- ScreenName: "buddy_1_online",
- },
- {
- ScreenName: "buddy_2_offline",
- },
- },
- },
- mockParams: mockParams{
- clientSideBuddyListManagerParams: clientSideBuddyListManagerParams{
- addBuddyParams: addBuddyParams{
- {
- me: state.NewIdentScreenName("user_screen_name"),
- them: state.NewIdentScreenName("buddy_1_online"),
- },
- {
- me: state.NewIdentScreenName("user_screen_name"),
- them: state.NewIdentScreenName("buddy_2_offline"),
- },
- },
- },
- },
- },
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- clientSideBuddyListManager := newMockClientSideBuddyListManager(t)
- for _, params := range tt.mockParams.addBuddyParams {
- clientSideBuddyListManager.EXPECT().
- AddBuddy(matchContext(), params.me, params.them).
- Return(params.err)
- }
- mockBuddyBroadcaster := newMockbuddyBroadcaster(t)
- for _, params := range tt.mockParams.broadcastVisibilityParams {
- mockBuddyBroadcaster.EXPECT().
- BroadcastVisibility(matchContext(), matchSession(params.from), params.filter, true).
- Return(params.err)
- }
- contactPreAuth := newMockContactPreAuthorizer(t)
- for _, params := range tt.mockParams.requiresAuthorizationParams {
- contactPreAuth.EXPECT().RequiresAuthorization(matchContext(), params.owner, params.requester).Return(params.result, params.err)
- }
- svc := BuddyService{
- clientSideBuddyListManager: clientSideBuddyListManager,
- buddyBroadcaster: mockBuddyBroadcaster,
- contactPreAuthorizer: contactPreAuth,
- }
- rejectSNAC, haveErr := svc.AddTempBuddies(context.Background(), tt.instance, wire.SNACFrame{RequestID: 42}, tt.bodyIn)
- assert.Nil(t, rejectSNAC)
- assert.ErrorIs(t, haveErr, tt.wantErr)
- })
- }
- }
- func TestBuddyService_DelTempBuddies(t *testing.T) {
- tests := []struct {
- // name is the name of the test
- name string
- // instance is the client session
- instance *state.SessionInstance
- // bodyIn is the input SNAC
- bodyIn wire.SNAC_0x03_0x10_BuddyDelTempBuddies
- // mockParams is the list of params sent to mocks that satisfy this
- // method's dependencies
- mockParams mockParams
- // wantErr is the expected error
- wantErr error
- }{
- {
- name: "delete 2 buddies",
- instance: newTestInstance("user_screen_name", sessOptSignonComplete),
- bodyIn: wire.SNAC_0x03_0x10_BuddyDelTempBuddies{
- Buddies: []struct {
- ScreenName string `oscar:"len_prefix=uint8"`
- }{
- {
- ScreenName: "buddy_1_online",
- },
- {
- ScreenName: "buddy_2_offline",
- },
- },
- },
- mockParams: mockParams{
- buddyBroadcasterParams: buddyBroadcasterParams{
- broadcastVisibilityParams: broadcastVisibilityParams{
- {
- from: state.NewIdentScreenName("user_screen_name"),
- filter: []state.IdentScreenName{
- state.NewIdentScreenName("buddy_1_online"),
- state.NewIdentScreenName("buddy_2_offline"),
- },
- },
- },
- },
- clientSideBuddyListManagerParams: clientSideBuddyListManagerParams{
- deleteBuddyParams: deleteBuddyParams{
- {
- me: state.NewIdentScreenName("user_screen_name"),
- them: state.NewIdentScreenName("buddy_1_online"),
- },
- {
- me: state.NewIdentScreenName("user_screen_name"),
- them: state.NewIdentScreenName("buddy_2_offline"),
- },
- },
- },
- },
- },
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- mockBuddyBroadcaster := newMockbuddyBroadcaster(t)
- for _, params := range tt.mockParams.broadcastVisibilityParams {
- mockBuddyBroadcaster.EXPECT().
- BroadcastVisibility(matchContext(), matchSession(params.from), params.filter, true).
- Return(params.err)
- }
- clientSideBuddyListManager := newMockClientSideBuddyListManager(t)
- for _, params := range tt.mockParams.deleteBuddyParams {
- clientSideBuddyListManager.EXPECT().
- RemoveBuddy(matchContext(), params.me, params.them).
- Return(params.err)
- }
- svc := BuddyService{
- buddyBroadcaster: mockBuddyBroadcaster,
- clientSideBuddyListManager: clientSideBuddyListManager,
- }
- assert.ErrorIs(t, tt.wantErr, svc.DelTempBuddies(context.Background(), tt.instance, tt.bodyIn))
- })
- }
- }
- func TestBuddyNotifier_BroadcastBuddyArrived(t *testing.T) {
- cases := []struct {
- // name is the unit test name
- name string
- // screenName is the user screen name
- screenName state.IdentScreenName
- // userInfo is the user info passed to BroadcastBuddyArrived
- userInfo wire.TLVUserInfo
- // mockParams is the list of params sent to mocks that satisfy this
- // method's dependencies
- mockParams mockParams
- }{
- {
- name: "happy path",
- screenName: state.NewIdentScreenName("me"),
- userInfo: wire.TLVUserInfo{ScreenName: "me"},
- mockParams: mockParams{
- relationshipFetcherParams: relationshipFetcherParams{
- allRelationshipsParams: allRelationshipsParams{
- {
- screenName: state.NewIdentScreenName("me"),
- filter: nil,
- result: []state.Relationship{
- {
- User: state.NewIdentScreenName("friend1-visible"),
- BlocksYou: false,
- YouBlock: false,
- IsOnYourList: true,
- IsOnTheirList: true,
- },
- {
- User: state.NewIdentScreenName("friend2-visible"),
- BlocksYou: false,
- YouBlock: false,
- IsOnYourList: true,
- IsOnTheirList: true,
- },
- {
- User: state.NewIdentScreenName("friend3-you-block"),
- BlocksYou: false,
- YouBlock: true,
- IsOnYourList: true,
- IsOnTheirList: true,
- },
- {
- User: state.NewIdentScreenName("friend4-blocks-you"),
- BlocksYou: true,
- YouBlock: false,
- IsOnYourList: true,
- IsOnTheirList: true,
- },
- {
- User: state.NewIdentScreenName("friend5-not-on-list"),
- BlocksYou: false,
- YouBlock: false,
- IsOnYourList: true,
- IsOnTheirList: false,
- },
- },
- },
- },
- },
- messageRelayerParams: messageRelayerParams{
- relayToScreenNamesParams: relayToScreenNamesParams{
- {
- screenNames: []state.IdentScreenName{
- state.NewIdentScreenName("friend1-visible"),
- state.NewIdentScreenName("friend2-visible"),
- },
- message: wire.SNACMessage{
- Frame: wire.SNACFrame{
- FoodGroup: wire.Buddy,
- SubGroup: wire.BuddyArrived,
- RequestID: wire.ReqIDFromServer,
- },
- Body: wire.SNAC_0x03_0x0B_BuddyArrived{
- TLVUserInfo: wire.TLVUserInfo{ScreenName: "me"},
- },
- },
- },
- },
- },
- },
- },
- {
- name: "user invisible, don't send notification",
- screenName: state.NewIdentScreenName("me"),
- userInfo: wire.TLVUserInfo{
- ScreenName: "me",
- TLVBlock: wire.TLVBlock{
- TLVList: wire.TLVList{
- wire.NewTLVBE(wire.OServiceUserInfoStatus, wire.OServiceUserStatusInvisible),
- },
- },
- },
- mockParams: mockParams{
- relationshipFetcherParams: relationshipFetcherParams{
- allRelationshipsParams: allRelationshipsParams{}, // don't look up relationships
- },
- messageRelayerParams: messageRelayerParams{
- relayToScreenNamesParams: relayToScreenNamesParams{}, // don't send notification
- },
- },
- },
- }
- for _, tc := range cases {
- t.Run(tc.name, func(t *testing.T) {
- relationshipFetcher := newMockRelationshipFetcher(t)
- for _, params := range tc.mockParams.allRelationshipsParams {
- relationshipFetcher.EXPECT().
- AllRelationships(matchContext(), params.screenName, params.filter).
- Return(params.result, params.err)
- }
- messageRelayer := newMockMessageRelayer(t)
- for _, params := range tc.mockParams.relayToScreenNamesParams {
- messageRelayer.EXPECT().
- RelayToScreenNames(matchContext(), params.screenNames, params.message)
- }
- svc := buddyNotifier{
- relationshipFetcher: relationshipFetcher,
- messageRelayer: messageRelayer,
- }
- err := svc.BroadcastBuddyArrived(context.Background(), tc.screenName, tc.userInfo)
- assert.NoError(t, err)
- })
- }
- }
- func TestBuddyService_BroadcastDeparture(t *testing.T) {
- cases := []struct {
- // name is the unit test name
- name string
- // screenName is the user that departed
- screenName state.IdentScreenName
- // mockParams is the list of params sent to mocks that satisfy this
- // method's dependencies
- mockParams mockParams
- }{
- {
- name: "happy path",
- screenName: state.NewIdentScreenName("me"),
- mockParams: mockParams{
- relationshipFetcherParams: relationshipFetcherParams{
- allRelationshipsParams: allRelationshipsParams{
- {
- screenName: state.NewIdentScreenName("me"),
- filter: nil,
- result: []state.Relationship{
- {
- User: state.NewIdentScreenName("friend1-visible"),
- BlocksYou: false,
- YouBlock: false,
- IsOnYourList: true,
- IsOnTheirList: true,
- },
- {
- User: state.NewIdentScreenName("friend2-visible"),
- BlocksYou: false,
- YouBlock: false,
- IsOnYourList: true,
- IsOnTheirList: true,
- },
- {
- User: state.NewIdentScreenName("friend3-you-block"),
- BlocksYou: false,
- YouBlock: true,
- IsOnYourList: true,
- IsOnTheirList: true,
- },
- {
- User: state.NewIdentScreenName("friend4-blocks-you"),
- BlocksYou: true,
- YouBlock: false,
- IsOnYourList: true,
- IsOnTheirList: true,
- },
- {
- User: state.NewIdentScreenName("friend5-not-on-list"),
- BlocksYou: false,
- YouBlock: false,
- IsOnYourList: true,
- IsOnTheirList: false,
- },
- },
- },
- },
- },
- messageRelayerParams: messageRelayerParams{
- relayToScreenNamesParams: relayToScreenNamesParams{
- {
- screenNames: []state.IdentScreenName{
- state.NewIdentScreenName("friend1-visible"),
- state.NewIdentScreenName("friend2-visible"),
- },
- message: wire.SNACMessage{
- Frame: wire.SNACFrame{
- FoodGroup: wire.Buddy,
- SubGroup: wire.BuddyDeparted,
- RequestID: wire.ReqIDFromServer,
- },
- Body: wire.SNAC_0x03_0x0C_BuddyDeparted{
- TLVUserInfo: wire.TLVUserInfo{
- ScreenName: "me",
- WarningLevel: 0,
- TLVBlock: wire.TLVBlock{
- TLVList: wire.TLVList{
- wire.NewTLVBE(wire.OServiceUserInfoUserFlags, uint16(0)),
- },
- },
- },
- },
- },
- },
- },
- },
- },
- },
- }
- for _, tc := range cases {
- t.Run(tc.name, func(t *testing.T) {
- relationshipFetcher := newMockRelationshipFetcher(t)
- for _, params := range tc.mockParams.allRelationshipsParams {
- relationshipFetcher.EXPECT().
- AllRelationships(matchContext(), params.screenName, params.filter).
- Return(params.result, params.err)
- }
- messageRelayer := newMockMessageRelayer(t)
- for _, params := range tc.mockParams.relayToScreenNamesParams {
- messageRelayer.EXPECT().
- RelayToScreenNames(matchContext(), params.screenNames, params.message)
- }
- svc := buddyNotifier{
- relationshipFetcher: relationshipFetcher,
- messageRelayer: messageRelayer,
- }
- err := svc.BroadcastBuddyDeparted(context.Background(), tc.screenName)
- assert.NoError(t, err)
- })
- }
- }
- func Test_buddyNotifier_BroadcastVisibility(t *testing.T) {
- cases := []struct {
- // name is the unit test name
- name string
- // instance is the session of the user
- instance *state.SessionInstance
- // filter limits specific users that can be notified
- filter []state.IdentScreenName
- // doSendDepartures indicates whether departure messages should be sent
- doSendDepartures bool
- // mockParams is the list of params sent to mocks that satisfy this
- // method's dependencies
- mockParams mockParams
- }{
- {
- name: "happy path",
- instance: newTestInstance("me"),
- mockParams: mockParams{
- relationshipFetcherParams: relationshipFetcherParams{
- allRelationshipsParams: allRelationshipsParams{
- {
- screenName: state.NewIdentScreenName("me"),
- filter: nil,
- result: []state.Relationship{
- {
- User: state.NewIdentScreenName("friend1-blocks-you"),
- BlocksYou: true,
- YouBlock: false,
- IsOnYourList: true,
- IsOnTheirList: true,
- },
- {
- User: state.NewIdentScreenName("friend2-visible-on-their-list"),
- BlocksYou: false,
- YouBlock: false,
- IsOnYourList: false,
- IsOnTheirList: true,
- },
- {
- User: state.NewIdentScreenName("friend3-visible-on-your-list"),
- BlocksYou: false,
- YouBlock: false,
- IsOnYourList: true,
- IsOnTheirList: false,
- },
- {
- User: state.NewIdentScreenName("friend4-visible-on-both-lists"),
- BlocksYou: false,
- YouBlock: false,
- IsOnYourList: true,
- IsOnTheirList: true,
- },
- {
- User: state.NewIdentScreenName("friend5-blocked-on-their-list"),
- BlocksYou: false,
- YouBlock: true,
- IsOnYourList: false,
- IsOnTheirList: true,
- },
- {
- User: state.NewIdentScreenName("friend6-blocked-on-your-list"),
- BlocksYou: false,
- YouBlock: true,
- IsOnYourList: true,
- IsOnTheirList: false,
- },
- {
- User: state.NewIdentScreenName("friend7-blocked-on-both-lists"),
- BlocksYou: false,
- YouBlock: true,
- IsOnYourList: true,
- IsOnTheirList: true,
- },
- {
- User: state.NewIdentScreenName("friend7-visible-offline"),
- BlocksYou: false,
- YouBlock: false,
- IsOnYourList: true,
- IsOnTheirList: true,
- },
- },
- },
- },
- },
- messageRelayerParams: messageRelayerParams{
- relayToScreenNameParams: relayToScreenNameParams{
- {
- screenName: state.NewIdentScreenName("friend2-visible-on-their-list"),
- message: newBuddyArrivedNotif("me"),
- },
- {
- screenName: state.NewIdentScreenName("me"),
- message: newBuddyArrivedNotif("friend3-visible-on-your-list"),
- },
- {
- screenName: state.NewIdentScreenName("friend4-visible-on-both-lists"),
- message: newBuddyArrivedNotif("me"),
- },
- {
- screenName: state.NewIdentScreenName("me"),
- message: newBuddyArrivedNotif("friend4-visible-on-both-lists"),
- },
- {
- screenName: state.NewIdentScreenName("friend5-blocked-on-their-list"),
- message: newBuddyDepartedNotif("me"),
- },
- {
- screenName: state.NewIdentScreenName("me"),
- message: newBuddyDepartedNotif("friend6-blocked-on-your-list"),
- },
- {
- screenName: state.NewIdentScreenName("me"),
- message: newBuddyDepartedNotif("friend7-blocked-on-both-lists"),
- },
- {
- screenName: state.NewIdentScreenName("friend7-blocked-on-both-lists"),
- message: newBuddyDepartedNotif("me"),
- },
- },
- },
- sessionRetrieverParams: sessionRetrieverParams{
- retrieveSessionParams: retrieveSessionParams{
- {
- screenName: state.NewIdentScreenName("friend2-visible-on-their-list"),
- result: newTestInstance("friend2-visible-on-their-list").Session(),
- },
- {
- screenName: state.NewIdentScreenName("friend3-visible-on-your-list"),
- result: newTestInstance("friend3-visible-on-your-list").Session(),
- },
- {
- screenName: state.NewIdentScreenName("friend4-visible-on-both-lists"),
- result: newTestInstance("friend4-visible-on-both-lists").Session(),
- },
- {
- screenName: state.NewIdentScreenName("friend5-blocked-on-their-list"),
- result: newTestInstance("friend5-blocked-on-their-list").Session(),
- },
- {
- screenName: state.NewIdentScreenName("friend6-blocked-on-your-list"),
- result: newTestInstance("friend6-blocked-on-your-list").Session(),
- },
- {
- screenName: state.NewIdentScreenName("friend7-blocked-on-both-lists"),
- result: newTestInstance("friend7-blocked-on-both-lists").Session(),
- },
- {
- screenName: state.NewIdentScreenName("friend7-visible-offline"),
- result: nil,
- },
- },
- },
- },
- doSendDepartures: true,
- },
- {
- name: "user invisible, don't send notification to buddies",
- instance: newTestInstance("me", sessOptInvisible),
- mockParams: mockParams{
- relationshipFetcherParams: relationshipFetcherParams{
- allRelationshipsParams: allRelationshipsParams{
- {
- screenName: state.NewIdentScreenName("me"),
- filter: nil,
- result: []state.Relationship{
- {
- User: state.NewIdentScreenName("friend1-blocks-you"),
- BlocksYou: true,
- YouBlock: false,
- IsOnYourList: true,
- IsOnTheirList: true,
- },
- {
- User: state.NewIdentScreenName("friend2-visible-on-their-list"),
- BlocksYou: false,
- YouBlock: false,
- IsOnYourList: false,
- IsOnTheirList: true,
- },
- {
- User: state.NewIdentScreenName("friend3-visible-on-your-list"),
- BlocksYou: false,
- YouBlock: false,
- IsOnYourList: true,
- IsOnTheirList: false,
- },
- {
- User: state.NewIdentScreenName("friend4-visible-on-both-lists"),
- BlocksYou: false,
- YouBlock: false,
- IsOnYourList: true,
- IsOnTheirList: true,
- },
- {
- User: state.NewIdentScreenName("friend5-blocked-on-their-list"),
- BlocksYou: false,
- YouBlock: true,
- IsOnYourList: false,
- IsOnTheirList: true,
- },
- {
- User: state.NewIdentScreenName("friend6-blocked-on-your-list"),
- BlocksYou: false,
- YouBlock: true,
- IsOnYourList: true,
- IsOnTheirList: false,
- },
- {
- User: state.NewIdentScreenName("friend7-blocked-on-both-lists"),
- BlocksYou: false,
- YouBlock: true,
- IsOnYourList: true,
- IsOnTheirList: true,
- },
- {
- User: state.NewIdentScreenName("friend7-visible-offline"),
- BlocksYou: false,
- YouBlock: false,
- IsOnYourList: true,
- IsOnTheirList: true,
- },
- },
- },
- },
- },
- messageRelayerParams: messageRelayerParams{
- relayToScreenNameParams: relayToScreenNameParams{
- {
- screenName: state.NewIdentScreenName("me"),
- message: newBuddyArrivedNotif("friend3-visible-on-your-list"),
- },
- {
- screenName: state.NewIdentScreenName("me"),
- message: newBuddyArrivedNotif("friend4-visible-on-both-lists"),
- },
- {
- screenName: state.NewIdentScreenName("friend5-blocked-on-their-list"),
- message: newBuddyDepartedNotif("me"),
- },
- {
- screenName: state.NewIdentScreenName("me"),
- message: newBuddyDepartedNotif("friend6-blocked-on-your-list"),
- },
- {
- screenName: state.NewIdentScreenName("me"),
- message: newBuddyDepartedNotif("friend7-blocked-on-both-lists"),
- },
- {
- screenName: state.NewIdentScreenName("friend7-blocked-on-both-lists"),
- message: newBuddyDepartedNotif("me"),
- },
- },
- },
- sessionRetrieverParams: sessionRetrieverParams{
- retrieveSessionParams: retrieveSessionParams{
- {
- screenName: state.NewIdentScreenName("friend2-visible-on-their-list"),
- result: newTestInstance("friend2-visible-on-their-list").Session(),
- },
- {
- screenName: state.NewIdentScreenName("friend3-visible-on-your-list"),
- result: newTestInstance("friend3-visible-on-your-list").Session(),
- },
- {
- screenName: state.NewIdentScreenName("friend4-visible-on-both-lists"),
- result: newTestInstance("friend4-visible-on-both-lists").Session(),
- },
- {
- screenName: state.NewIdentScreenName("friend5-blocked-on-their-list"),
- result: newTestInstance("friend5-blocked-on-their-list").Session(),
- },
- {
- screenName: state.NewIdentScreenName("friend6-blocked-on-your-list"),
- result: newTestInstance("friend6-blocked-on-your-list").Session(),
- },
- {
- screenName: state.NewIdentScreenName("friend7-blocked-on-both-lists"),
- result: newTestInstance("friend7-blocked-on-both-lists").Session(),
- },
- {
- screenName: state.NewIdentScreenName("friend7-visible-offline"),
- result: nil,
- },
- },
- },
- },
- doSendDepartures: true,
- },
- {
- name: "don't send departure notifications",
- instance: newTestInstance("me"),
- mockParams: mockParams{
- relationshipFetcherParams: relationshipFetcherParams{
- allRelationshipsParams: allRelationshipsParams{
- {
- screenName: state.NewIdentScreenName("me"),
- filter: nil,
- result: []state.Relationship{
- {
- User: state.NewIdentScreenName("friend2-visible-on-their-list"),
- BlocksYou: false,
- YouBlock: false,
- IsOnYourList: false,
- IsOnTheirList: true,
- },
- {
- User: state.NewIdentScreenName("friend3-visible-on-your-list"),
- BlocksYou: false,
- YouBlock: false,
- IsOnYourList: true,
- IsOnTheirList: false,
- },
- {
- User: state.NewIdentScreenName("friend4-visible-on-both-lists"),
- BlocksYou: false,
- YouBlock: false,
- IsOnYourList: true,
- IsOnTheirList: true,
- },
- {
- User: state.NewIdentScreenName("friend7-visible-offline"),
- BlocksYou: false,
- YouBlock: false,
- IsOnYourList: true,
- IsOnTheirList: true,
- },
- },
- },
- },
- },
- messageRelayerParams: messageRelayerParams{
- relayToScreenNameParams: relayToScreenNameParams{
- {
- screenName: state.NewIdentScreenName("friend2-visible-on-their-list"),
- message: newBuddyArrivedNotif("me"),
- },
- {
- screenName: state.NewIdentScreenName("me"),
- message: newBuddyArrivedNotif("friend3-visible-on-your-list"),
- },
- {
- screenName: state.NewIdentScreenName("friend4-visible-on-both-lists"),
- message: newBuddyArrivedNotif("me"),
- },
- {
- screenName: state.NewIdentScreenName("me"),
- message: newBuddyArrivedNotif("friend4-visible-on-both-lists"),
- },
- },
- },
- sessionRetrieverParams: sessionRetrieverParams{
- retrieveSessionParams: retrieveSessionParams{
- {
- screenName: state.NewIdentScreenName("friend2-visible-on-their-list"),
- result: newTestInstance("friend2-visible-on-their-list").Session(),
- },
- {
- screenName: state.NewIdentScreenName("friend3-visible-on-your-list"),
- result: newTestInstance("friend3-visible-on-your-list").Session(),
- },
- {
- screenName: state.NewIdentScreenName("friend4-visible-on-both-lists"),
- result: newTestInstance("friend4-visible-on-both-lists").Session(),
- },
- {
- screenName: state.NewIdentScreenName("friend7-visible-offline"),
- result: nil,
- },
- },
- },
- },
- doSendDepartures: false,
- },
- }
- for _, tc := range cases {
- t.Run(tc.name, func(t *testing.T) {
- relationshipFetcher := newMockRelationshipFetcher(t)
- for _, params := range tc.mockParams.allRelationshipsParams {
- relationshipFetcher.EXPECT().
- AllRelationships(matchContext(), params.screenName, params.filter).
- Return(params.result, params.err)
- }
- messageRelayer := newMockMessageRelayer(t)
- for _, params := range tc.mockParams.relayToScreenNameParams {
- messageRelayer.EXPECT().
- RelayToScreenName(matchContext(), params.screenName, mock.MatchedBy(func(message wire.SNACMessage) bool {
- return params.message.Frame == message.Frame &&
- params.message.Body.(func(any) bool)(message.Body)
- }))
- }
- sessionRetriever := newMockSessionRetriever(t)
- for _, params := range tc.mockParams.retrieveSessionParams {
- sessionRetriever.EXPECT().
- RetrieveSession(params.screenName).
- Return(params.result)
- }
- svc := buddyNotifier{
- relationshipFetcher: relationshipFetcher,
- messageRelayer: messageRelayer,
- sessionRetriever: sessionRetriever,
- }
- err := svc.BroadcastVisibility(context.Background(), tc.instance, tc.filter, tc.doSendDepartures)
- assert.NoError(t, err)
- })
- }
- }
- func newBuddyDepartedNotif(screenName state.DisplayScreenName) wire.SNACMessage {
- return wire.SNACMessage{
- Frame: wire.SNACFrame{
- FoodGroup: wire.Buddy,
- SubGroup: wire.BuddyDeparted,
- RequestID: wire.ReqIDFromServer,
- },
- Body: func(val any) bool {
- snac, ok := val.(wire.SNAC_0x03_0x0C_BuddyDeparted)
- if !ok {
- return false
- }
- return snac.ScreenName == screenName.String()
- },
- }
- }
- func newBuddyArrivedNotif(screenName state.DisplayScreenName) wire.SNACMessage {
- return wire.SNACMessage{
- Frame: wire.SNACFrame{
- FoodGroup: wire.Buddy,
- SubGroup: wire.BuddyArrived,
- RequestID: wire.ReqIDFromServer,
- },
- Body: func(val any) bool {
- snac, ok := val.(wire.SNAC_0x03_0x0B_BuddyArrived)
- if !ok {
- return false
- }
- return snac.ScreenName == screenName.String() && len(snac.TLVList) > 0
- },
- }
- }
|