| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051 |
- package icq_legacy
- import (
- "context"
- "log/slog"
- "strconv"
- "testing"
- "time"
- "github.com/mk6i/open-oscar-server/state"
- "github.com/mk6i/open-oscar-server/wire"
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/mock"
- )
- func TestICQLegacyService_AuthenticateUser(t *testing.T) {
- password := "secret123"
- authCookie := []byte("auth-cookie")
- screenName := state.DisplayScreenName("12345")
- serverCookie := state.ServerCookie{ScreenName: screenName}
- oscarSession := newTestOSCARInstance(screenName)
- successBlock := wire.TLVRestBlock{
- TLVList: []wire.TLV{
- wire.NewTLVBE(wire.LoginTLVTagsAuthorizationCookie, authCookie),
- },
- }
- tests := []struct {
- name string
- setupAuth func(*mockAuthService)
- req AuthRequest
- wantResult *AuthResult
- wantErr error
- }{
- {
- name: "valid credentials",
- req: AuthRequest{
- UIN: 12345,
- Password: password,
- Version: ICQLegacyVersionV5,
- },
- setupAuth: func(authSvc *mockAuthService) {
- authSvc.EXPECT().FLAPLogin(mock.Anything, mock.Anything, "").
- Return(successBlock, nil)
- authSvc.EXPECT().CrackCookie(authCookie).
- Return(serverCookie, nil)
- authSvc.EXPECT().RegisterBOSSession(mock.Anything, serverCookie, mock.Anything).
- Return(oscarSession, nil)
- },
- wantResult: &AuthResult{
- Success: true,
- ErrorCode: 0,
- },
- },
- {
- name: "bad password",
- req: AuthRequest{
- UIN: 12345,
- Password: "wrongpass",
- Version: ICQLegacyVersionV5,
- },
- setupAuth: func(authSvc *mockAuthService) {
- authSvc.EXPECT().FLAPLogin(mock.Anything, mock.Anything, "").
- Return(wire.TLVRestBlock{
- TLVList: []wire.TLV{
- wire.NewTLVBE(wire.LoginTLVTagsErrorSubcode, wire.LoginErrInvalidPassword),
- },
- }, nil)
- },
- wantResult: &AuthResult{
- Success: false,
- ErrorCode: 0x0001,
- },
- },
- {
- name: "user not found",
- req: AuthRequest{
- UIN: 99999,
- Password: password,
- Version: ICQLegacyVersionV5,
- },
- setupAuth: func(authSvc *mockAuthService) {
- authSvc.EXPECT().FLAPLogin(mock.Anything, mock.Anything, "").
- Return(wire.TLVRestBlock{
- TLVList: []wire.TLV{
- wire.NewTLVBE(wire.LoginTLVTagsErrorSubcode, wire.LoginErrICQUserErr),
- },
- }, nil)
- },
- wantResult: &AuthResult{
- Success: false,
- ErrorCode: 0x0002,
- },
- },
- {
- name: "missing UIN (UIN=0)",
- req: AuthRequest{
- UIN: 0,
- Password: password,
- },
- wantResult: &AuthResult{
- Success: false,
- ErrorCode: 0x0002,
- },
- },
- {
- name: "no password hash",
- req: AuthRequest{
- UIN: 12345,
- Password: password,
- Version: ICQLegacyVersionV5,
- },
- setupAuth: func(authSvc *mockAuthService) {
- authSvc.EXPECT().FLAPLogin(mock.Anything, mock.Anything, "").
- Return(wire.TLVRestBlock{
- TLVList: []wire.TLV{
- wire.NewTLVBE(wire.LoginTLVTagsErrorSubcode, wire.LoginErrInvalidPassword),
- },
- }, nil)
- },
- wantResult: &AuthResult{
- Success: false,
- ErrorCode: 0x0001,
- },
- },
- }
- for _, tc := range tests {
- t.Run(tc.name, func(t *testing.T) {
- authSvc := newMockAuthService(t)
- if tc.setupAuth != nil {
- tc.setupAuth(authSvc)
- }
- svc := NewICQLegacyService(
- authSvc,
- newMockUserManager(t),
- newMockAccountManager(t),
- newMockSessionRetriever(t),
- newMockMessageRelayer(t),
- newMockBuddyBroadcaster(t),
- newMockOfflineMessageManager(t),
- newMockICQUserFinder(t),
- newMockICQUserUpdater(t),
- newMockFeedbagManager(t),
- newMockRelationshipFetcher(t),
- newMockBuddyListRegistry(t),
- newMockBuddyService(t),
- newMockICBMService(t),
- &LegacySessionManager{sessions: map[uint32]*LegacySession{}},
- slog.Default(),
- )
- got, err := svc.AuthenticateUser(context.Background(), tc.req)
- if tc.wantErr != nil {
- assert.ErrorIs(t, err, tc.wantErr)
- return
- }
- assert.NoError(t, err)
- assert.Equal(t, tc.wantResult.Success, got.Success)
- assert.Equal(t, tc.wantResult.ErrorCode, got.ErrorCode)
- if tc.wantResult.Success {
- assert.NotEmpty(t, got.SessionID)
- assert.Same(t, oscarSession, got.oscarSession)
- }
- })
- }
- }
- func TestICQLegacyService_ProcessMessage(t *testing.T) {
- tests := []struct {
- name string
- sess *LegacySession
- mockParams mockParams
- req MessageRequest
- wantResult *MessageResult
- wantErr error
- legacyMgr *LegacySessionManager
- }{
- {
- name: "target online - legacy session exists",
- req: MessageRequest{
- FromUIN: 11111,
- ToUIN: 22222,
- MsgType: ICQLegacyMsgText,
- Message: "hello",
- },
- legacyMgr: &LegacySessionManager{
- sessions: map[uint32]*LegacySession{
- 22222: newTestLegacySession(22222),
- },
- },
- wantResult: &MessageResult{
- Delivered: true,
- StoredOffline: false,
- TargetOnline: true,
- TargetVersion: ICQLegacyVersionV5,
- },
- },
- {
- name: "target online - OSCAR session",
- sess: newTestLegacySession(11111, legacySessionOptOSCARSess),
- req: MessageRequest{
- FromUIN: 11111,
- ToUIN: 22222,
- MsgType: ICQLegacyMsgText,
- Message: "hello from legacy",
- },
- mockParams: mockParams{
- icbmFoodgroupParams: icbmFoodgroupParams{
- channelMsgToHostParams: channelMsgToHostParams{
- {
- screenName: state.NewIdentScreenName("11111"),
- inFrame: wire.SNACFrame{
- FoodGroup: wire.ICBM,
- SubGroup: wire.ICBMChannelMsgToHost,
- },
- inBody: wire.SNAC_0x04_0x06_ICBMChannelMsgToHost{
- ChannelID: wire.ICBMChannelICQ,
- ScreenName: "22222",
- TLVRestBlock: wire.TLVRestBlock{
- TLVList: wire.TLVList{
- wire.NewTLVLE(wire.ICBMTLVData, wire.ICBMCh4Message{
- UIN: 11111,
- MessageType: wire.ICBMMsgTypePlain,
- Message: "hello from legacy",
- }),
- wire.NewTLVBE(wire.ICBMTLVStore, []byte{}),
- },
- },
- },
- },
- },
- },
- },
- wantResult: &MessageResult{
- Delivered: true,
- StoredOffline: false,
- TargetOnline: true,
- TargetVersion: 0,
- },
- legacyMgr: &LegacySessionManager{sessions: map[uint32]*LegacySession{}},
- },
- {
- name: "target offline - stored",
- sess: newTestLegacySession(11111, legacySessionOptOSCARSess),
- req: MessageRequest{
- FromUIN: 11111,
- ToUIN: 22222,
- MsgType: ICQLegacyMsgText,
- Message: "offline msg",
- },
- mockParams: mockParams{
- icbmFoodgroupParams: icbmFoodgroupParams{
- channelMsgToHostParams: channelMsgToHostParams{
- {
- screenName: state.NewIdentScreenName("11111"),
- inFrame: wire.SNACFrame{
- FoodGroup: wire.ICBM,
- SubGroup: wire.ICBMChannelMsgToHost,
- },
- inBody: wire.SNAC_0x04_0x06_ICBMChannelMsgToHost{
- ChannelID: wire.ICBMChannelICQ,
- ScreenName: "22222",
- TLVRestBlock: wire.TLVRestBlock{
- TLVList: wire.TLVList{
- wire.NewTLVLE(wire.ICBMTLVData, wire.ICBMCh4Message{
- UIN: 11111,
- MessageType: wire.ICBMMsgTypePlain,
- Message: "offline msg",
- }),
- wire.NewTLVBE(wire.ICBMTLVStore, []byte{}),
- },
- },
- },
- result: &wire.SNACMessage{
- Frame: wire.SNACFrame{
- FoodGroup: wire.ICBM,
- SubGroup: wire.ICBMErr,
- },
- Body: wire.SNACError{
- Code: wire.ErrorCodeNotLoggedOn,
- },
- },
- },
- },
- },
- },
- wantResult: &MessageResult{
- Delivered: false,
- StoredOffline: true,
- TargetOnline: false,
- TargetVersion: 0,
- },
- legacyMgr: &LegacySessionManager{sessions: map[uint32]*LegacySession{}},
- },
- {
- name: "invalid sender UIN (0)",
- req: MessageRequest{
- FromUIN: 0,
- ToUIN: 22222,
- MsgType: ICQLegacyMsgText,
- Message: "hello",
- },
- wantResult: &MessageResult{
- Delivered: false,
- StoredOffline: false,
- TargetOnline: false,
- },
- legacyMgr: &LegacySessionManager{sessions: map[uint32]*LegacySession{}},
- },
- {
- name: "invalid target UIN (0)",
- req: MessageRequest{
- FromUIN: 11111,
- ToUIN: 0,
- MsgType: ICQLegacyMsgText,
- Message: "hello",
- },
- wantResult: &MessageResult{
- Delivered: false,
- StoredOffline: false,
- TargetOnline: false,
- },
- legacyMgr: &LegacySessionManager{sessions: map[uint32]*LegacySession{}},
- },
- }
- for _, tc := range tests {
- t.Run(tc.name, func(t *testing.T) {
- icbmSvc := newMockICBMService(t)
- for _, msg := range tc.mockParams.channelMsgToHostParams {
- icbmSvc.EXPECT().
- ChannelMsgToHost(matchContext(), matchSession(msg.screenName), msg.inFrame, msg.inBody).
- Return(msg.result, msg.err)
- }
- svc := NewICQLegacyService(
- newMockAuthService(t),
- newMockUserManager(t),
- newMockAccountManager(t),
- newMockSessionRetriever(t),
- newMockMessageRelayer(t),
- newMockBuddyBroadcaster(t),
- newMockOfflineMessageManager(t),
- newMockICQUserFinder(t),
- newMockICQUserUpdater(t),
- newMockFeedbagManager(t),
- newMockRelationshipFetcher(t),
- newMockBuddyListRegistry(t),
- newMockBuddyService(t),
- icbmSvc,
- tc.legacyMgr,
- slog.Default(),
- )
- got, err := svc.ProcessMessage(context.Background(), tc.sess, tc.req)
- if tc.wantErr != nil {
- assert.ErrorIs(t, err, tc.wantErr)
- return
- }
- assert.NoError(t, err)
- assert.Equal(t, tc.wantResult.Delivered, got.Delivered)
- assert.Equal(t, tc.wantResult.StoredOffline, got.StoredOffline)
- assert.Equal(t, tc.wantResult.TargetOnline, got.TargetOnline)
- assert.Equal(t, tc.wantResult.TargetVersion, got.TargetVersion)
- })
- }
- }
- func TestICQLegacyService_ProcessContactList(t *testing.T) {
- tests := []struct {
- name string
- mockParams mockParams
- req ContactListRequest
- legacyMgr *LegacySessionManager
- wantResult *ContactListResult
- }{
- {
- name: "mixed online/offline contacts",
- req: ContactListRequest{
- UIN: 11111,
- Contacts: []uint32{22222, 33333},
- },
- mockParams: mockParams{
- sessionRetrieverParams: sessionRetrieverParams{
- retrieveSessionParams: retrieveSessionParams{
- {
- screenName: state.NewIdentScreenName("22222"),
- result: nil, // not on OSCAR either
- },
- {
- screenName: state.NewIdentScreenName("33333"),
- result: &state.Session{}, // online via OSCAR
- },
- },
- },
- },
- legacyMgr: &LegacySessionManager{
- sessions: make(map[uint32]*LegacySession),
- },
- wantResult: &ContactListResult{
- OnlineContacts: []ContactStatus{
- {UIN: 22222, Online: false, Status: 0},
- {UIN: 33333, Online: true, Status: ICQLegacyStatusOnline},
- },
- },
- },
- {
- name: "empty list",
- req: ContactListRequest{
- UIN: 11111,
- Contacts: []uint32{},
- },
- legacyMgr: &LegacySessionManager{sessions: map[uint32]*LegacySession{}},
- wantResult: &ContactListResult{
- OnlineContacts: []ContactStatus{},
- },
- },
- }
- for _, tc := range tests {
- t.Run(tc.name, func(t *testing.T) {
- sessionRetriever := newMockSessionRetriever(t)
- for _, p := range tc.mockParams.retrieveSessionParams {
- sessionRetriever.EXPECT().
- RetrieveSession(p.screenName).
- Return(p.result)
- }
- buddySvc := newMockBuddyService(t)
- userFinder := newMockICQUserFinder(t)
- // ProcessContactList adds both forward and reverse buddy entries
- buddySvc.EXPECT().
- AddBuddies(mock.Anything, mock.Anything, mock.Anything, mock.Anything).
- Return(nil, nil).
- Maybe()
- userFinder.EXPECT().
- FindByUIN(mock.Anything, mock.Anything).
- Return(state.User{}, nil).
- Maybe()
- svc := NewICQLegacyService(
- newMockAuthService(t),
- newMockUserManager(t),
- newMockAccountManager(t),
- sessionRetriever,
- newMockMessageRelayer(t),
- newMockBuddyBroadcaster(t),
- newMockOfflineMessageManager(t),
- userFinder,
- newMockICQUserUpdater(t),
- newMockFeedbagManager(t),
- newMockRelationshipFetcher(t),
- newMockBuddyListRegistry(t),
- buddySvc,
- newMockICBMService(t),
- tc.legacyMgr,
- slog.Default(),
- )
- var instance *state.SessionInstance
- if tc.req.UIN != 0 {
- instance = newTestOSCARInstance(state.DisplayScreenName(strconv.FormatUint(uint64(tc.req.UIN), 10)))
- }
- got, err := svc.ProcessContactList(context.Background(), instance, tc.req)
- assert.NoError(t, err)
- assert.Equal(t, len(tc.wantResult.OnlineContacts), len(got.OnlineContacts))
- for i, want := range tc.wantResult.OnlineContacts {
- assert.Equal(t, want.UIN, got.OnlineContacts[i].UIN)
- assert.Equal(t, want.Online, got.OnlineContacts[i].Online)
- if want.Online {
- assert.Equal(t, want.Status, got.OnlineContacts[i].Status)
- }
- }
- })
- }
- }
- func TestICQLegacyService_ProcessStatusChange(t *testing.T) {
- tests := []struct {
- name string
- mockParams mockParams
- req StatusChangeRequest
- legacyMgr *LegacySessionManager
- wantTargets int
- }{
- {
- name: "status change with notification targets",
- req: StatusChangeRequest{
- UIN: 11111,
- OldStatus: ICQLegacyStatusOnline,
- NewStatus: ICQLegacyStatusAway,
- },
- legacyMgr: &LegacySessionManager{
- sessions: map[uint32]*LegacySession{
- 11111: newTestLegacySession(11111, legacySessionOptContactList([]uint32{22222})),
- 22222: newTestLegacySession(22222, legacySessionOptContactList([]uint32{11111})),
- },
- },
- wantTargets: 1,
- },
- {
- name: "no targets - session not found",
- req: StatusChangeRequest{
- UIN: 99999,
- OldStatus: ICQLegacyStatusOnline,
- NewStatus: ICQLegacyStatusAway,
- },
- legacyMgr: &LegacySessionManager{sessions: map[uint32]*LegacySession{}},
- wantTargets: 0,
- },
- }
- for _, tc := range tests {
- t.Run(tc.name, func(t *testing.T) {
- svc := NewICQLegacyService(
- newMockAuthService(t),
- newMockUserManager(t),
- newMockAccountManager(t),
- newMockSessionRetriever(t),
- newMockMessageRelayer(t),
- newMockBuddyBroadcaster(t),
- newMockOfflineMessageManager(t),
- newMockICQUserFinder(t),
- newMockICQUserUpdater(t),
- newMockFeedbagManager(t),
- newMockRelationshipFetcher(t),
- newMockBuddyListRegistry(t),
- newMockBuddyService(t),
- newMockICBMService(t),
- tc.legacyMgr,
- slog.Default(),
- )
- got, err := svc.ProcessStatusChange(context.Background(), tc.req)
- assert.NoError(t, err)
- assert.Len(t, got.NotifyTargets, tc.wantTargets)
- })
- }
- }
- func TestICQLegacyService_SearchByUIN(t *testing.T) {
- tests := []struct {
- name string
- mockParams mockParams
- uin uint32
- wantResult *LegacyUserSearchResult
- wantErr bool
- }{
- {
- name: "found",
- uin: 12345,
- mockParams: mockParams{
- icqUserFinderParams: icqUserFinderParams{
- findByUINParams: findByUINParams{
- {
- UIN: 12345,
- result: state.User{
- IdentScreenName: state.NewIdentScreenName("12345"),
- ICQInfo: state.ICQInfo{
- Basic: state.ICQBasicInfo{
- Nickname: "CoolUser",
- FirstName: "John",
- LastName: "Doe",
- EmailAddress: "john@example.com",
- },
- },
- },
- },
- },
- },
- sessionRetrieverParams: sessionRetrieverParams{
- retrieveSessionParams: retrieveSessionParams{
- {
- screenName: state.NewIdentScreenName("12345"),
- result: nil,
- },
- },
- },
- },
- wantResult: &LegacyUserSearchResult{
- UIN: 12345,
- Nickname: "CoolUser",
- FirstName: "John",
- LastName: "Doe",
- Email: "john@example.com",
- },
- },
- {
- name: "not found",
- uin: 99999,
- mockParams: mockParams{
- icqUserFinderParams: icqUserFinderParams{
- findByUINParams: findByUINParams{
- {
- UIN: 99999,
- err: state.ErrNoUser,
- },
- },
- },
- },
- wantErr: true,
- },
- }
- for _, tc := range tests {
- t.Run(tc.name, func(t *testing.T) {
- userFinder := newMockICQUserFinder(t)
- for _, p := range tc.mockParams.findByUINParams {
- userFinder.EXPECT().
- FindByUIN(matchContext(), p.UIN).
- Return(p.result, p.err)
- }
- sessionRetriever := newMockSessionRetriever(t)
- for _, p := range tc.mockParams.retrieveSessionParams {
- sessionRetriever.EXPECT().
- RetrieveSession(p.screenName).
- Return(p.result)
- }
- svc := NewICQLegacyService(
- newMockAuthService(t),
- newMockUserManager(t),
- newMockAccountManager(t),
- sessionRetriever,
- newMockMessageRelayer(t),
- newMockBuddyBroadcaster(t),
- newMockOfflineMessageManager(t),
- userFinder,
- newMockICQUserUpdater(t),
- newMockFeedbagManager(t),
- newMockRelationshipFetcher(t),
- newMockBuddyListRegistry(t),
- newMockBuddyService(t),
- newMockICBMService(t),
- &LegacySessionManager{sessions: map[uint32]*LegacySession{}},
- slog.Default(),
- )
- got, err := svc.SearchByUIN(context.Background(), tc.uin)
- if tc.wantErr {
- assert.Error(t, err)
- return
- }
- assert.NoError(t, err)
- assert.Equal(t, tc.wantResult.UIN, got.UIN)
- assert.Equal(t, tc.wantResult.Nickname, got.Nickname)
- assert.Equal(t, tc.wantResult.FirstName, got.FirstName)
- assert.Equal(t, tc.wantResult.LastName, got.LastName)
- assert.Equal(t, tc.wantResult.Email, got.Email)
- })
- }
- }
- func TestICQLegacyService_SearchByName(t *testing.T) {
- tests := []struct {
- name string
- mockParams mockParams
- nick string
- first string
- last string
- email string
- wantCount int
- }{
- {
- name: "matches by name",
- first: "John",
- last: "Doe",
- mockParams: mockParams{
- icqUserFinderParams: icqUserFinderParams{
- findByICQNameParams: findByICQNameParams{
- {
- firstName: "John",
- lastName: "Doe",
- nickName: "",
- result: []state.User{
- {
- IdentScreenName: state.NewIdentScreenName("12345"),
- ICQInfo: state.ICQInfo{
- Basic: state.ICQBasicInfo{
- Nickname: "JD",
- FirstName: "John",
- LastName: "Doe",
- },
- },
- },
- },
- },
- },
- },
- sessionRetrieverParams: sessionRetrieverParams{
- retrieveSessionParams: retrieveSessionParams{
- {
- screenName: state.NewIdentScreenName("12345"),
- result: nil,
- },
- },
- },
- },
- wantCount: 1,
- },
- {
- name: "matches by email",
- email: "john@example.com",
- mockParams: mockParams{
- icqUserFinderParams: icqUserFinderParams{
- findByICQEmailParams: findByICQEmailParams{
- {
- email: "john@example.com",
- result: state.User{
- IdentScreenName: state.NewIdentScreenName("12345"),
- ICQInfo: state.ICQInfo{
- Basic: state.ICQBasicInfo{
- Nickname: "JD",
- EmailAddress: "john@example.com",
- },
- },
- },
- },
- },
- },
- sessionRetrieverParams: sessionRetrieverParams{
- retrieveSessionParams: retrieveSessionParams{
- {
- screenName: state.NewIdentScreenName("12345"),
- result: nil,
- },
- },
- },
- },
- wantCount: 1,
- },
- }
- for _, tc := range tests {
- t.Run(tc.name, func(t *testing.T) {
- userFinder := newMockICQUserFinder(t)
- for _, p := range tc.mockParams.findByICQNameParams {
- userFinder.EXPECT().
- FindByICQName(matchContext(), p.firstName, p.lastName, p.nickName).
- Return(p.result, p.err)
- }
- for _, p := range tc.mockParams.findByICQEmailParams {
- userFinder.EXPECT().
- FindByICQEmail(matchContext(), p.email).
- Return(p.result, p.err)
- }
- sessionRetriever := newMockSessionRetriever(t)
- for _, p := range tc.mockParams.retrieveSessionParams {
- sessionRetriever.EXPECT().
- RetrieveSession(p.screenName).
- Return(p.result)
- }
- svc := NewICQLegacyService(
- newMockAuthService(t),
- newMockUserManager(t),
- newMockAccountManager(t),
- sessionRetriever,
- newMockMessageRelayer(t),
- newMockBuddyBroadcaster(t),
- newMockOfflineMessageManager(t),
- userFinder,
- newMockICQUserUpdater(t),
- newMockFeedbagManager(t),
- newMockRelationshipFetcher(t),
- newMockBuddyListRegistry(t),
- newMockBuddyService(t),
- newMockICBMService(t),
- &LegacySessionManager{sessions: map[uint32]*LegacySession{}},
- slog.Default(),
- )
- got, err := svc.SearchByName(context.Background(), tc.nick, tc.first, tc.last, tc.email)
- assert.NoError(t, err)
- assert.Len(t, got, tc.wantCount)
- })
- }
- }
- func TestICQLegacyService_GetOfflineMessages(t *testing.T) {
- fixedTime := time.Date(2024, 1, 15, 10, 30, 0, 0, time.UTC)
- tests := []struct {
- name string
- mockParams mockParams
- uin uint32
- wantCount int
- }{
- {
- name: "messages exist",
- uin: 12345,
- mockParams: mockParams{
- offlineMessageManagerParams: offlineMessageManagerParams{
- retrieveMessagesParams: retrieveMessagesParams{
- {
- recip: state.NewIdentScreenName("12345"),
- messages: []state.OfflineMessage{
- {
- Sender: state.NewIdentScreenName("99999"),
- Recipient: state.NewIdentScreenName("12345"),
- Sent: fixedTime,
- Message: wire.SNAC_0x04_0x06_ICBMChannelMsgToHost{
- ChannelID: wire.ICBMChannelIM,
- TLVRestBlock: wire.TLVRestBlock{
- TLVList: func() wire.TLVList {
- frags, _ := wire.ICBMFragmentList("hello offline")
- return wire.TLVList{
- wire.NewTLVBE(wire.ICBMTLVAOLIMData, frags),
- }
- }(),
- },
- },
- },
- },
- },
- },
- },
- },
- wantCount: 1,
- },
- {
- name: "no messages",
- uin: 12345,
- mockParams: mockParams{
- offlineMessageManagerParams: offlineMessageManagerParams{
- retrieveMessagesParams: retrieveMessagesParams{
- {
- recip: state.NewIdentScreenName("12345"),
- messages: []state.OfflineMessage{},
- },
- },
- },
- },
- wantCount: 0,
- },
- }
- for _, tc := range tests {
- t.Run(tc.name, func(t *testing.T) {
- offlineMsgMgr := newMockOfflineMessageManager(t)
- for _, p := range tc.mockParams.retrieveMessagesParams {
- offlineMsgMgr.EXPECT().
- RetrieveMessages(matchContext(), p.recip).
- Return(p.messages, p.err)
- }
- svc := NewICQLegacyService(
- newMockAuthService(t),
- newMockUserManager(t),
- newMockAccountManager(t),
- newMockSessionRetriever(t),
- newMockMessageRelayer(t),
- newMockBuddyBroadcaster(t),
- offlineMsgMgr,
- newMockICQUserFinder(t),
- newMockICQUserUpdater(t),
- newMockFeedbagManager(t),
- newMockRelationshipFetcher(t),
- newMockBuddyListRegistry(t),
- newMockBuddyService(t),
- newMockICBMService(t),
- &LegacySessionManager{sessions: map[uint32]*LegacySession{}},
- slog.Default(),
- )
- got, err := svc.GetOfflineMessages(context.Background(), tc.uin)
- assert.NoError(t, err)
- assert.Len(t, got, tc.wantCount)
- if tc.wantCount > 0 {
- assert.Equal(t, uint32(99999), got[0].FromUIN)
- assert.Equal(t, tc.uin, got[0].ToUIN)
- }
- })
- }
- }
- func TestICQLegacyService_RegisterNewUser(t *testing.T) {
- tests := []struct {
- name string
- wantErr bool
- }{
- {
- name: "success",
- },
- }
- for _, tc := range tests {
- t.Run(tc.name, func(t *testing.T) {
- userManager := newMockUserManager(t)
- // generateNewUIN calls User() to find an available UIN.
- // Return nil (available) for the first UIN checked (100000).
- userManager.EXPECT().
- User(matchContext(), state.NewIdentScreenName(strconv.FormatUint(100000, 10))).
- Return(nil, nil)
- // InsertUser is called with the new user
- userManager.EXPECT().
- InsertUser(matchContext(), mock.Anything).
- Return(nil)
- svc := NewICQLegacyService(
- newMockAuthService(t),
- userManager,
- newMockAccountManager(t),
- newMockSessionRetriever(t),
- newMockMessageRelayer(t),
- newMockBuddyBroadcaster(t),
- newMockOfflineMessageManager(t),
- newMockICQUserFinder(t),
- newMockICQUserUpdater(t),
- newMockFeedbagManager(t),
- newMockRelationshipFetcher(t),
- newMockBuddyListRegistry(t),
- newMockBuddyService(t),
- newMockICBMService(t),
- &LegacySessionManager{sessions: map[uint32]*LegacySession{}},
- slog.Default(),
- )
- uin, err := svc.RegisterNewUser(context.Background(), "Nick", "First", "Last", "test@example.com", "password123")
- if tc.wantErr {
- assert.Error(t, err)
- return
- }
- assert.NoError(t, err)
- assert.Equal(t, uint32(100000), uin)
- })
- }
- }
- func TestICQLegacyService_DeleteUser(t *testing.T) {
- authKey := "test-auth-key"
- password := "secret123"
- passHash := wire.StrongMD5PasswordHash(password, authKey)
- tests := []struct {
- name string
- mockParams mockParams
- uin uint32
- password string
- wantErr bool
- }{
- {
- name: "success",
- uin: 12345,
- password: password,
- mockParams: mockParams{
- userManagerParams: userManagerParams{
- userParams: userParams{
- {
- screenName: state.NewIdentScreenName("12345"),
- result: &state.User{
- AuthKey: authKey,
- StrongMD5Pass: passHash,
- },
- },
- },
- deleteUserParams: deleteUserParams{
- {
- screenName: state.NewIdentScreenName("12345"),
- },
- },
- },
- },
- },
- {
- name: "wrong password",
- uin: 12345,
- password: "wrongpass",
- mockParams: mockParams{
- userManagerParams: userManagerParams{
- userParams: userParams{
- {
- screenName: state.NewIdentScreenName("12345"),
- result: &state.User{
- AuthKey: authKey,
- StrongMD5Pass: passHash,
- },
- },
- },
- },
- },
- wantErr: true,
- },
- }
- for _, tc := range tests {
- t.Run(tc.name, func(t *testing.T) {
- authSvc := newMockAuthService(t)
- if tc.wantErr {
- authSvc.EXPECT().FLAPLogin(mock.Anything, mock.Anything, "").
- Return(wire.TLVRestBlock{
- TLVList: []wire.TLV{
- wire.NewTLVBE(wire.LoginTLVTagsErrorSubcode, wire.LoginErrInvalidPassword),
- },
- }, nil)
- } else {
- authSvc.EXPECT().FLAPLogin(mock.Anything, mock.Anything, "").
- Return(wire.TLVRestBlock{}, nil)
- }
- userManager := newMockUserManager(t)
- for _, p := range tc.mockParams.deleteUserParams {
- userManager.EXPECT().
- DeleteUser(matchContext(), p.screenName).
- Return(p.err)
- }
- svc := NewICQLegacyService(
- authSvc,
- userManager,
- newMockAccountManager(t),
- newMockSessionRetriever(t),
- newMockMessageRelayer(t),
- newMockBuddyBroadcaster(t),
- newMockOfflineMessageManager(t),
- newMockICQUserFinder(t),
- newMockICQUserUpdater(t),
- newMockFeedbagManager(t),
- newMockRelationshipFetcher(t),
- newMockBuddyListRegistry(t),
- newMockBuddyService(t),
- newMockICBMService(t),
- &LegacySessionManager{sessions: map[uint32]*LegacySession{}},
- slog.Default(),
- )
- err := svc.DeleteUser(context.Background(), tc.uin, tc.password)
- if tc.wantErr {
- assert.Error(t, err)
- assert.Contains(t, err.Error(), "invalid password")
- return
- }
- assert.NoError(t, err)
- })
- }
- }
|