| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124 |
- package icq_legacy
- import (
- "bytes"
- "encoding/binary"
- "errors"
- "fmt"
- "log/slog"
- "net"
- "testing"
- "time"
- "github.com/mk6i/open-oscar-server/config"
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/mock"
- "github.com/stretchr/testify/require"
- )
- const (
- testV3UIN = uint32(12345)
- testV3Seq = uint16(42)
- testV3Seq2 = uint16(7)
- )
- var testV3Addr = &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 4000}
- type v3HandleEnv struct {
- T *testing.T
- Sender *mockPacketSender
- Service *mockLegacyService
- Sessions *LegacySessionManager
- Session *LegacySession
- }
- type v3HandleCase struct {
- name string
- session *LegacySession
- pkt []byte
- wire func(t *testing.T) []byte
- setup func(v3HandleEnv) func(error)
- }
- func v3CaseSetup(pre func(v3HandleEnv), after func(e v3HandleEnv, err error)) func(v3HandleEnv) func(error) {
- return func(e v3HandleEnv) func(error) {
- if pre != nil {
- pre(e)
- }
- return func(err error) {
- if after != nil {
- after(e, err)
- return
- }
- assert.NoError(e.T, err)
- }
- }
- }
- func runV3HandleCases(t *testing.T, cases []v3HandleCase) {
- t.Helper()
- for _, tt := range cases {
- t.Run(tt.name, func(t *testing.T) {
- sender := newMockPacketSender(t)
- svc := newMockLegacyService(t)
- sessions := newTestLegacySessionManager()
- e := v3HandleEnv{
- T: t,
- Sender: sender,
- Service: svc,
- Sessions: sessions,
- Session: tt.session,
- }
- var check func(error)
- if tt.setup != nil {
- check = tt.setup(e)
- } else {
- check = func(err error) { assert.NoError(t, err) }
- }
- h := newTestV3Handler(t, sender, svc, sessions)
- var wire []byte
- switch {
- case tt.wire != nil:
- wire = tt.wire(t)
- case tt.pkt != nil:
- wire = tt.pkt
- default:
- t.Fatal("case must set pkt or wire")
- }
- check(h.Handle(tt.session, testV3Addr, wire))
- })
- }
- }
- func newTestV3Handler(t *testing.T, sender PacketSender, svc LegacyService, sessions *LegacySessionManager) *V3Handler {
- t.Helper()
- if sessions == nil {
- sessions = newTestLegacySessionManager()
- }
- return NewV3Handler(sessions, svc, sender, NewV3PacketBuilder(sessions, nil), slog.Default())
- }
- func newTestV3HandlerWithDispatcher(t *testing.T, sender PacketSender, svc LegacyService, sessions *LegacySessionManager) *V3Handler {
- t.Helper()
- logger := slog.Default()
- if sessions == nil {
- sessions = newTestLegacySessionManager()
- }
- v1 := NewV1Handler(sessions, svc, sender, logger)
- v2 := NewV2Handler(sessions, svc, sender, NewV2PacketBuilder(), logger)
- v3 := NewV3Handler(sessions, svc, sender, NewV3PacketBuilder(sessions, nil), logger)
- v4 := NewV4Handler(sessions, svc, sender, NewV4PacketBuilder(sessions, nil), logger)
- v5 := NewV5Handler(sessions, svc, sender, NewV5PacketBuilder(sessions, nil), logger)
- cfg := config.ICQLegacyConfig{SupportedVersions: []int{1, 2, 3, 4, 5}}
- dispatcher := NewProtocolDispatcher(v1, v2, v3, v4, v5, cfg, logger)
- v3.SetDispatcher(dispatcher)
- return v3
- }
- func v3Session(uin uint32) *LegacySession {
- s := newTestLegacySession(uin, legacySessionOptOSCARSess, func(ls *LegacySession) {
- ls.Version = ICQLegacyVersionV3
- ls.SeqNumClient = testV3Seq
- })
- return s
- }
- func v3ServerCommand(packet []byte) uint16 {
- if len(packet) < 4 {
- return 0
- }
- return binary.LittleEndian.Uint16(packet[2:4])
- }
- func expectV3NotConnected(sender *mockPacketSender) {
- sender.EXPECT().SendPacket(testV3Addr, mock.AnythingOfType("[]uint8")).
- Run(func(_ *net.UDPAddr, p []byte) {
- if got := v3ServerCommand(p); got != ICQLegacySrvNotConnected {
- panic(fmt.Sprintf("got command 0x%04X, want NOT_CONNECTED", got))
- }
- }).Return(nil).Once()
- }
- func buildV3ClientPacket(command, seq1, seq2 uint16, uin uint32, data []byte) []byte {
- buf := make([]byte, 12+len(data))
- binary.LittleEndian.PutUint16(buf[0:2], ICQLegacyVersionV3)
- binary.LittleEndian.PutUint16(buf[2:4], command)
- binary.LittleEndian.PutUint16(buf[4:6], seq1)
- binary.LittleEndian.PutUint16(buf[6:8], seq2)
- binary.LittleEndian.PutUint32(buf[8:12], uin)
- copy(buf[12:], data)
- return buf
- }
- func defaultV3Pkt(command uint16, data []byte) []byte {
- return buildV3ClientPacket(command, testV3Seq, testV3Seq2, testV3UIN, data)
- }
- func v3LoginData(password string) []byte {
- pwd := []byte(password)
- buf := make([]byte, 4+4+2+len(pwd))
- binary.LittleEndian.PutUint32(buf[0:4], 0)
- binary.LittleEndian.PutUint32(buf[4:8], 4000)
- binary.LittleEndian.PutUint16(buf[8:10], uint16(len(pwd)))
- copy(buf[10:], pwd)
- return buf
- }
- func v3GetDepsPayload(uin uint32, password string) []byte {
- pwd := []byte(password)
- buf := make([]byte, 4+2+len(pwd))
- binary.LittleEndian.PutUint32(buf[0:4], uin)
- binary.LittleEndian.PutUint16(buf[4:6], uint16(len(pwd)))
- copy(buf[6:], pwd)
- return buf
- }
- func v3GetDepsData(uin uint32, password string) []byte {
- return append(make([]byte, 4), v3GetDepsPayload(uin, password)...)
- }
- func v3TimestampPrefix(payload []byte) []byte {
- return append(make([]byte, 4), payload...)
- }
- func v3LPString(s string) []byte {
- buf := new(bytes.Buffer)
- writeLegacyString(buf, s)
- return buf.Bytes()
- }
- func v3ContactListPayload(uins []uint32) []byte {
- buf := make([]byte, 1+4*len(uins))
- buf[0] = byte(len(uins))
- for i, u := range uins {
- binary.LittleEndian.PutUint32(buf[1+4*i:], u)
- }
- return buf
- }
- func v3ContactListData(uins []uint32) []byte {
- return v3TimestampPrefix(v3ContactListPayload(uins))
- }
- func v3MessagePayload(toUIN uint32, msgType uint16, message string) []byte {
- msg := []byte(message)
- buf := make([]byte, 4+2+2+len(msg))
- binary.LittleEndian.PutUint32(buf[0:4], toUIN)
- binary.LittleEndian.PutUint16(buf[4:6], msgType)
- binary.LittleEndian.PutUint16(buf[6:8], uint16(len(msg)))
- copy(buf[8:], msg)
- return buf
- }
- func v3MessageData(toUIN uint32, msgType uint16, message string) []byte {
- return v3TimestampPrefix(v3MessagePayload(toUIN, msgType, message))
- }
- func v3TargetUINPayload(target uint32) []byte {
- buf := make([]byte, 4)
- binary.LittleEndian.PutUint32(buf, target)
- return buf
- }
- func v3TargetUINData(target uint32) []byte {
- return v3TimestampPrefix(v3TargetUINPayload(target))
- }
- func v3SetStatusData(status uint32) []byte {
- buf := make([]byte, 8)
- binary.LittleEndian.PutUint32(buf[4:8], status)
- return buf
- }
- func v3SearchUINData(targetUIN uint32) []byte {
- uinStr := fmt.Sprintf("%d", targetUIN)
- buf := make([]byte, 4+2+2+2+len(uinStr)+1)
- off := 4
- binary.LittleEndian.PutUint16(buf[off:], 0x00FF)
- off += 2
- binary.LittleEndian.PutUint16(buf[off:], 0x0002)
- off += 2
- binary.LittleEndian.PutUint16(buf[off:], uint16(len(uinStr)+1))
- off += 2
- copy(buf[off:], uinStr)
- return buf
- }
- func v3SetBasicInfoData(nick, first, last, email string) []byte {
- buf := new(bytes.Buffer)
- buf.Write(make([]byte, 4))
- writeLegacyString(buf, nick)
- writeLegacyString(buf, first)
- writeLegacyString(buf, last)
- writeLegacyString(buf, email)
- return buf.Bytes()
- }
- func v3SetNotesData(notes string) []byte {
- n := []byte(notes)
- buf := make([]byte, 4+2+len(n))
- binary.LittleEndian.PutUint16(buf[4:6], uint16(len(n)))
- copy(buf[6:], n)
- return buf
- }
- func v3SetPasswordData(password string) []byte {
- pwd := []byte(password)
- buf := make([]byte, 4+2+len(pwd))
- binary.LittleEndian.PutUint16(buf[4:6], uint16(len(pwd)))
- copy(buf[6:], pwd)
- return buf
- }
- func v3SetAuthData(authRequired bool) []byte {
- buf := make([]byte, 5)
- if authRequired {
- buf[4] = 1
- }
- return buf
- }
- func v3SetStateData(status, estatus uint32) []byte {
- buf := make([]byte, 12)
- binary.LittleEndian.PutUint32(buf[4:8], status)
- binary.LittleEndian.PutUint32(buf[8:12], estatus)
- return buf
- }
- func v3ServerPacketData(p []byte) []byte {
- if len(p) < 16 {
- return nil
- }
- return p[16:]
- }
- func TestV3Handler_Handle(t *testing.T) {
- runV3HandleCases(t, []v3HandleCase{
- {
- name: "packet too short",
- pkt: []byte{0x01, 0x02},
- setup: v3CaseSetup(nil, func(e v3HandleEnv, err error) {
- require.Error(e.T, err)
- assert.Contains(e.T, err.Error(), "packet too short")
- }),
- },
- {
- name: "nil session disallowed command",
- session: nil,
- pkt: defaultV3Pkt(ICQLegacyCmdKeepAlive, nil),
- setup: v3CaseSetup(func(e v3HandleEnv) {
- expectV3NotConnected(e.Sender)
- }, nil),
- },
- {
- name: "nil session ACK allowed",
- session: nil,
- pkt: defaultV3Pkt(ICQLegacyCmdAck, nil),
- },
- {
- name: "session state updated",
- session: v3Session(testV3UIN),
- pkt: defaultV3Pkt(ICQLegacyCmdAck, nil),
- setup: v3CaseSetup(nil, func(e v3HandleEnv, err error) {
- assert.NoError(e.T, err)
- assert.Equal(e.T, testV3Seq, e.Session.SeqNumClient)
- assert.WithinDuration(e.T, time.Now(), e.Session.GetLastActivity(), time.Second)
- }),
- },
- {
- name: "unknown command with session",
- session: v3Session(testV3UIN),
- pkt: defaultV3Pkt(0xFFFF, nil),
- setup: v3CaseSetup(func(e v3HandleEnv) {
- e.Sender.EXPECT().SendPacket(testV3Addr, mock.AnythingOfType("[]uint8")).
- Run(func(_ *net.UDPAddr, p []byte) {
- assert.Equal(e.T, ICQLegacySrvAck, v3ServerCommand(p))
- }).Return(nil).Once()
- }, nil),
- },
- })
- }
- func TestV3Handler_HandleFirstLogin(t *testing.T) {
- runV3HandleCases(t, []v3HandleCase{
- {
- name: "first login",
- session: nil,
- pkt: defaultV3Pkt(ICQLegacyCmdFirstLogin, nil),
- setup: v3CaseSetup(func(e v3HandleEnv) {
- e.Sender.EXPECT().SendPacket(testV3Addr, mock.AnythingOfType("[]uint8")).
- Run(func(_ *net.UDPAddr, p []byte) {
- assert.Equal(e.T, ICQLegacySrvAck, v3ServerCommand(p))
- }).Return(nil).Once()
- }, nil),
- },
- })
- }
- func TestV3Handler_HandleGetDeps(t *testing.T) {
- runV3HandleCases(t, []v3HandleCase{
- {
- name: "valid credentials",
- pkt: defaultV3Pkt(ICQLegacyCmdGetDeps, v3GetDepsData(testV3UIN, "secret")),
- setup: v3CaseSetup(func(e v3HandleEnv) {
- e.Service.EXPECT().ValidateCredentials(mock.Anything, testV3UIN, "secret").Return(true, nil).Once()
- e.Sender.EXPECT().SendPacket(testV3Addr, mock.AnythingOfType("[]uint8")).Return(nil).Times(2)
- }, nil),
- },
- {
- name: "invalid credentials",
- pkt: defaultV3Pkt(ICQLegacyCmdGetDeps, v3GetDepsData(testV3UIN, "wrong")),
- setup: v3CaseSetup(func(e v3HandleEnv) {
- e.Service.EXPECT().ValidateCredentials(mock.Anything, testV3UIN, "wrong").Return(false, nil).Once()
- e.Sender.EXPECT().SendPacket(testV3Addr, mock.AnythingOfType("[]uint8")).
- Run(func(_ *net.UDPAddr, p []byte) {
- assert.Equal(e.T, ICQLegacySrvWrongPasswd, v3ServerCommand(p))
- }).Return(nil).Once()
- }, nil),
- },
- {
- name: "service error",
- pkt: defaultV3Pkt(ICQLegacyCmdGetDeps, v3GetDepsData(testV3UIN, "secret")),
- setup: v3CaseSetup(func(e v3HandleEnv) {
- e.Service.EXPECT().ValidateCredentials(mock.Anything, testV3UIN, "secret").
- Return(false, errors.New("db down")).Once()
- e.Sender.EXPECT().SendPacket(testV3Addr, mock.AnythingOfType("[]uint8")).
- Run(func(_ *net.UDPAddr, p []byte) {
- assert.Equal(e.T, ICQLegacySrvWrongPasswd, v3ServerCommand(p))
- }).Return(nil).Once()
- }, nil),
- },
- })
- }
- func TestV3Handler_HandleLogin(t *testing.T) {
- runV3HandleCases(t, []v3HandleCase{
- {
- name: "auth success",
- session: nil,
- pkt: defaultV3Pkt(ICQLegacyCmdLogin, v3LoginData("secret")),
- setup: v3CaseSetup(func(e v3HandleEnv) {
- e.Sender.EXPECT().SendPacket(testV3Addr, mock.AnythingOfType("[]uint8")).Return(nil).Once()
- e.Service.EXPECT().AuthenticateUser(mock.Anything, mock.MatchedBy(func(req AuthRequest) bool {
- return req.UIN == testV3UIN && req.Password == "secret"
- })).Return(&AuthResult{Success: true, oscarSession: testAuthSuccessInstance()}, nil).Once()
- e.Service.EXPECT().NotifyUserOnline(mock.Anything, testV3UIN, mock.Anything).Return(nil).Once()
- e.Sender.EXPECT().SendToSession(mock.AnythingOfType("*icq_legacy.LegacySession"), mock.AnythingOfType("[]uint8")).Return(nil).Once()
- }, func(e v3HandleEnv, err error) {
- assert.NoError(e.T, err)
- assert.NotNil(e.T, e.Sessions.GetSession(testV3UIN))
- }),
- },
- {
- name: "bad password",
- session: nil,
- pkt: defaultV3Pkt(ICQLegacyCmdLogin, v3LoginData("wrong")),
- setup: v3CaseSetup(func(e v3HandleEnv) {
- e.Sender.EXPECT().SendPacket(testV3Addr, mock.AnythingOfType("[]uint8")).Return(nil).Once()
- e.Service.EXPECT().AuthenticateUser(mock.Anything, mock.Anything).
- Return(&AuthResult{Success: false, ErrorCode: 0x0001}, nil).Once()
- e.Sender.EXPECT().SendPacket(testV3Addr, mock.AnythingOfType("[]uint8")).
- Run(func(_ *net.UDPAddr, p []byte) {
- assert.Equal(e.T, ICQLegacySrvWrongPasswd, v3ServerCommand(p))
- }).Return(nil).Once()
- }, nil),
- },
- {
- name: "parse error",
- session: nil,
- pkt: defaultV3Pkt(ICQLegacyCmdLogin, []byte{0, 0, 0}),
- setup: v3CaseSetup(func(e v3HandleEnv) {
- e.Sender.EXPECT().SendPacket(testV3Addr, mock.AnythingOfType("[]uint8")).Return(nil).Once()
- e.Sender.EXPECT().SendPacket(testV3Addr, mock.AnythingOfType("[]uint8")).
- Run(func(_ *net.UDPAddr, p []byte) {
- assert.Equal(e.T, ICQLegacySrvWrongPasswd, v3ServerCommand(p))
- }).Return(nil).Once()
- }, nil),
- },
- })
- }
- func TestV3Handler_HandleContactList(t *testing.T) {
- runV3HandleCases(t, []v3HandleCase{
- {
- name: "valid contact list",
- session: v3Session(testV3UIN),
- pkt: defaultV3Pkt(ICQLegacyCmdContactList, v3ContactListData([]uint32{99999})),
- setup: v3CaseSetup(func(e v3HandleEnv) {
- e.Service.EXPECT().ProcessContactList(mock.Anything, mock.Anything, mock.Anything).
- Return(&ContactListResult{}, nil).Once()
- e.Sender.EXPECT().SendPacket(e.Session.Addr, mock.AnythingOfType("[]uint8")).Return(nil).Once()
- e.Sender.EXPECT().SendToSession(e.Session, mock.AnythingOfType("[]uint8")).Return(nil).Once()
- }, nil),
- },
- {
- name: "nil session",
- pkt: defaultV3Pkt(ICQLegacyCmdContactList, v3ContactListData(nil)),
- setup: v3CaseSetup(func(e v3HandleEnv) {
- expectV3NotConnected(e.Sender)
- }, nil),
- },
- })
- }
- func TestV3Handler_HandlePing(t *testing.T) {
- runV3HandleCases(t, []v3HandleCase{
- {
- name: "keep alive",
- session: v3Session(testV3UIN),
- pkt: defaultV3Pkt(ICQLegacyCmdKeepAlive, nil),
- setup: v3CaseSetup(func(e v3HandleEnv) {
- e.Sender.EXPECT().SendPacket(testV3Addr, mock.AnythingOfType("[]uint8")).
- Run(func(_ *net.UDPAddr, p []byte) {
- assert.Equal(e.T, ICQLegacySrvAck, v3ServerCommand(p))
- }).Return(nil).Once()
- }, nil),
- },
- {
- name: "keep alive 2",
- session: v3Session(testV3UIN),
- pkt: defaultV3Pkt(ICQLegacyCmdKeepAlive2, nil),
- setup: v3CaseSetup(func(e v3HandleEnv) {
- e.Sender.EXPECT().SendPacket(testV3Addr, mock.AnythingOfType("[]uint8")).
- Run(func(_ *net.UDPAddr, p []byte) {
- assert.Equal(e.T, ICQLegacySrvAck, v3ServerCommand(p))
- }).Return(nil).Once()
- }, nil),
- },
- {
- name: "nil session",
- pkt: defaultV3Pkt(ICQLegacyCmdKeepAlive, nil),
- setup: v3CaseSetup(func(e v3HandleEnv) {
- expectV3NotConnected(e.Sender)
- }, nil),
- },
- })
- }
- func TestV3Handler_HandleLogoff(t *testing.T) {
- runV3HandleCases(t, []v3HandleCase{
- {
- name: "active session",
- session: v3Session(testV3UIN),
- pkt: defaultV3Pkt(ICQLegacyCmdLogoff, nil),
- setup: v3CaseSetup(func(e v3HandleEnv) {
- registerSession(e.Sessions, e.Session)
- e.Service.EXPECT().NotifyUserOffline(mock.Anything, testV3UIN).Return(nil).Once()
- }, func(e v3HandleEnv, err error) {
- assert.NoError(e.T, err)
- assert.Nil(e.T, e.Sessions.GetSession(testV3UIN))
- }),
- },
- {
- name: "nil session",
- pkt: defaultV3Pkt(ICQLegacyCmdLogoff, nil),
- setup: v3CaseSetup(func(e v3HandleEnv) {
- expectV3NotConnected(e.Sender)
- }, nil),
- },
- })
- }
- func TestV3Handler_HandleSetStatus(t *testing.T) {
- runV3HandleCases(t, []v3HandleCase{
- {
- name: "valid status",
- session: v3Session(testV3UIN),
- pkt: defaultV3Pkt(ICQLegacyCmdSetStatus, v3SetStatusData(0x00000001)),
- setup: v3CaseSetup(func(e v3HandleEnv) {
- e.Service.EXPECT().ProcessStatusChange(mock.Anything, mock.Anything).
- Return(&StatusChangeResult{}, nil).Once()
- e.Sender.EXPECT().SendPacket(e.Session.Addr, mock.AnythingOfType("[]uint8")).Return(nil).Once()
- }, func(e v3HandleEnv, err error) {
- assert.NoError(e.T, err)
- assert.Equal(e.T, uint32(0x00000001), e.Session.GetStatus())
- }),
- },
- {
- name: "nil session",
- pkt: defaultV3Pkt(ICQLegacyCmdSetStatus, v3SetStatusData(1)),
- setup: v3CaseSetup(func(e v3HandleEnv) {
- expectV3NotConnected(e.Sender)
- }, nil),
- },
- })
- }
- func TestV3Handler_HandleMessage(t *testing.T) {
- target := v3Session(99999)
- runV3HandleCases(t, []v3HandleCase{
- {
- name: "offline stored",
- session: v3Session(testV3UIN),
- pkt: defaultV3Pkt(ICQLegacyCmdThruServer, v3MessageData(99999, 0x0001, "hi")),
- setup: v3CaseSetup(func(e v3HandleEnv) {
- e.Service.EXPECT().ProcessMessage(mock.Anything, mock.Anything, mock.Anything).
- Return(&MessageResult{StoredOffline: true}, nil).Once()
- e.Sender.EXPECT().SendPacket(e.Session.Addr, mock.AnythingOfType("[]uint8")).Return(nil).Once()
- }, nil),
- },
- {
- name: "online target",
- session: v3Session(testV3UIN),
- pkt: defaultV3Pkt(ICQLegacyCmdThruServer, v3MessageData(99999, 0x0001, "hi")),
- setup: v3CaseSetup(func(e v3HandleEnv) {
- registerSession(e.Sessions, target)
- e.Service.EXPECT().ProcessMessage(mock.Anything, mock.Anything, mock.Anything).
- Return(&MessageResult{TargetOnline: true}, nil).Once()
- e.Sender.EXPECT().SendPacket(e.Session.Addr, mock.AnythingOfType("[]uint8")).Return(nil).Once()
- e.Sender.EXPECT().SendToSession(target, mock.AnythingOfType("[]uint8")).Return(nil).Once()
- }, nil),
- },
- {
- name: "nil session",
- pkt: defaultV3Pkt(ICQLegacyCmdThruServer, v3MessageData(99999, 0x0001, "hi")),
- setup: v3CaseSetup(func(e v3HandleEnv) {
- expectV3NotConnected(e.Sender)
- }, nil),
- },
- })
- }
- func TestV3Handler_HandleAuthorize(t *testing.T) {
- runV3HandleCases(t, []v3HandleCase{
- {
- name: "authorize message",
- session: v3Session(testV3UIN),
- pkt: defaultV3Pkt(ICQLegacyCmdAuthorize, v3MessageData(99999, 0x0001, "auth")),
- setup: v3CaseSetup(func(e v3HandleEnv) {
- e.Service.EXPECT().ProcessMessage(mock.Anything, mock.Anything, mock.Anything).
- Return(&MessageResult{StoredOffline: true}, nil).Once()
- e.Sender.EXPECT().SendPacket(e.Session.Addr, mock.AnythingOfType("[]uint8")).Return(nil).Once()
- }, nil),
- },
- })
- }
- func TestV3Handler_HandleUserAdd(t *testing.T) {
- runV3HandleCases(t, []v3HandleCase{
- {
- name: "success",
- session: v3Session(testV3UIN),
- pkt: defaultV3Pkt(ICQLegacyCmdUserAdd, v3TargetUINData(99999)),
- setup: v3CaseSetup(func(e v3HandleEnv) {
- e.Service.EXPECT().ProcessUserAdd(mock.Anything, mock.Anything, mock.Anything).
- Return(&UserAddResult{}, nil).Once()
- e.Sender.EXPECT().SendPacket(e.Session.Addr, mock.AnythingOfType("[]uint8")).Return(nil).Once()
- }, func(e v3HandleEnv, err error) {
- assert.Contains(e.T, e.Session.GetContactList(), uint32(99999))
- }),
- },
- {
- name: "nil session",
- pkt: defaultV3Pkt(ICQLegacyCmdUserAdd, v3TargetUINData(99999)),
- setup: v3CaseSetup(func(e v3HandleEnv) {
- expectV3NotConnected(e.Sender)
- }, nil),
- },
- })
- }
- func TestV3Handler_HandleOfflineMsgReq(t *testing.T) {
- runV3HandleCases(t, []v3HandleCase{
- {
- name: "no messages",
- session: v3Session(testV3UIN),
- pkt: defaultV3Pkt(ICQLegacyCmdSysMsgReq, nil),
- setup: v3CaseSetup(func(e v3HandleEnv) {
- e.Service.EXPECT().GetOfflineMessages(mock.Anything, testV3UIN).
- Return([]LegacyOfflineMessage{}, nil).Once()
- e.Sender.EXPECT().SendPacket(e.Session.Addr, mock.AnythingOfType("[]uint8")).Return(nil).Once()
- e.Sender.EXPECT().SendToSession(e.Session, mock.AnythingOfType("[]uint8")).Return(nil).Once()
- }, nil),
- },
- })
- }
- func TestV3Handler_HandleSetBasicInfo(t *testing.T) {
- runV3HandleCases(t, []v3HandleCase{
- {
- name: "success",
- session: v3Session(testV3UIN),
- pkt: defaultV3Pkt(ICQLegacyCmdSetBasicInfo, v3SetBasicInfoData("nick", "first", "last", "a@b.com")),
- setup: v3CaseSetup(func(e v3HandleEnv) {
- e.Service.EXPECT().UpdateBasicInfo(mock.Anything, testV3UIN, mock.Anything).Return(nil).Once()
- e.Sender.EXPECT().SendPacket(e.Session.Addr, mock.AnythingOfType("[]uint8")).Return(nil).Once()
- e.Sender.EXPECT().SendToSession(e.Session, mock.AnythingOfType("[]uint8")).Return(nil).Once()
- }, nil),
- },
- })
- }
- func TestV3Handler_HandleSetHomeInfo(t *testing.T) {
- runV3HandleCases(t, []v3HandleCase{
- {
- name: "data too short",
- session: v3Session(testV3UIN),
- pkt: defaultV3Pkt(0x0582, []byte{0, 0, 0}),
- setup: v3CaseSetup(func(e v3HandleEnv) {
- e.Sender.EXPECT().SendPacket(e.Session.Addr, mock.AnythingOfType("[]uint8")).Return(nil).Once()
- e.Sender.EXPECT().SendToSession(e.Session, mock.AnythingOfType("[]uint8")).Return(nil).Once()
- }, nil),
- },
- {
- name: "updates profile",
- session: v3Session(testV3UIN),
- pkt: defaultV3Pkt(0x0582, v3SetBasicInfoData("addr", "city", "CA", "555")),
- setup: v3CaseSetup(func(e v3HandleEnv) {
- e.Service.EXPECT().GetFullUserInfo(mock.Anything, testV3UIN).Return(testMinimalUser(), nil).Once()
- e.Service.EXPECT().UpdateBasicInfo(mock.Anything, testV3UIN, mock.Anything).Return(nil).Once()
- e.Service.EXPECT().SetAuthMode(mock.Anything, testV3UIN, true).Return(nil).Once()
- e.Sender.EXPECT().SendPacket(e.Session.Addr, mock.AnythingOfType("[]uint8")).Return(nil).Once()
- e.Sender.EXPECT().SendToSession(e.Session, mock.AnythingOfType("[]uint8")).Return(nil).Once()
- }, nil),
- },
- })
- }
- func TestV3Handler_HandleSetHomeWeb(t *testing.T) {
- runV3HandleCases(t, []v3HandleCase{
- {
- name: "success",
- session: v3Session(testV3UIN),
- pkt: defaultV3Pkt(0x058C, append(make([]byte, 4), 0, 0, 0, 2, 0, 'h', 'p')),
- setup: v3CaseSetup(func(e v3HandleEnv) {
- e.Service.EXPECT().UpdateMoreInfo(mock.Anything, testV3UIN, mock.Anything).Return(nil).Once()
- e.Sender.EXPECT().SendPacket(e.Session.Addr, mock.AnythingOfType("[]uint8")).Return(nil).Once()
- e.Sender.EXPECT().SendToSession(e.Session, mock.AnythingOfType("[]uint8")).Return(nil).Once()
- }, nil),
- },
- })
- }
- func TestV3Handler_HandleSetWorkInfo(t *testing.T) {
- runV3HandleCases(t, []v3HandleCase{
- {
- name: "data too short",
- session: v3Session(testV3UIN),
- pkt: defaultV3Pkt(0x0578, []byte{0, 0, 0}),
- setup: v3CaseSetup(func(e v3HandleEnv) {
- e.Sender.EXPECT().SendPacket(e.Session.Addr, mock.AnythingOfType("[]uint8")).Return(nil).Once()
- e.Sender.EXPECT().SendToSession(e.Session, mock.AnythingOfType("[]uint8")).Return(nil).Once()
- }, nil),
- },
- })
- }
- func TestV3Handler_HandleSetWorkWeb(t *testing.T) {
- runV3HandleCases(t, []v3HandleCase{
- {
- name: "success",
- session: v3Session(testV3UIN),
- pkt: defaultV3Pkt(0x05BE, v3TimestampPrefix(v3LPString("http://work.example"))),
- setup: v3CaseSetup(func(e v3HandleEnv) {
- e.Service.EXPECT().GetFullUserInfo(mock.Anything, testV3UIN).Return(testMinimalUser(), nil).Once()
- e.Service.EXPECT().UpdateWorkInfo(mock.Anything, testV3UIN, mock.Anything).Return(nil).Once()
- e.Sender.EXPECT().SendPacket(e.Session.Addr, mock.AnythingOfType("[]uint8")).Return(nil).Once()
- e.Sender.EXPECT().SendToSession(e.Session, mock.AnythingOfType("[]uint8")).Return(nil).Once()
- }, nil),
- },
- })
- }
- func TestV3Handler_HandleUnknownDep(t *testing.T) {
- runV3HandleCases(t, []v3HandleCase{
- {
- name: "acks request",
- session: v3Session(testV3UIN),
- pkt: defaultV3Pkt(0x0604, nil),
- setup: v3CaseSetup(func(e v3HandleEnv) {
- e.Sender.EXPECT().SendPacket(e.Session.Addr, mock.AnythingOfType("[]uint8")).Return(nil).Once()
- }, nil),
- },
- })
- }
- func TestV3Handler_HandleVisibleList(t *testing.T) {
- runV3HandleCases(t, []v3HandleCase{
- {
- name: "acks list",
- session: v3Session(testV3UIN),
- pkt: defaultV3Pkt(0x06AE, v3ContactListData([]uint32{11111})),
- setup: v3CaseSetup(func(e v3HandleEnv) {
- e.Sender.EXPECT().SendPacket(e.Session.Addr, mock.AnythingOfType("[]uint8")).Return(nil).Once()
- }, nil),
- },
- })
- }
- func TestV3Handler_HandleInvisibleList(t *testing.T) {
- runV3HandleCases(t, []v3HandleCase{
- {
- name: "acks list",
- session: v3Session(testV3UIN),
- pkt: defaultV3Pkt(0x06A4, v3ContactListData([]uint32{22222})),
- setup: v3CaseSetup(func(e v3HandleEnv) {
- e.Sender.EXPECT().SendPacket(e.Session.Addr, mock.AnythingOfType("[]uint8")).Return(nil).Once()
- }, nil),
- },
- })
- }
- func TestV3Handler_HandleSearchStart(t *testing.T) {
- runV3HandleCases(t, []v3HandleCase{
- {
- name: "found",
- session: v3Session(testV3UIN),
- pkt: defaultV3Pkt(ICQLegacyCmdSearchStart, v3SearchUINData(99999)),
- setup: v3CaseSetup(func(e v3HandleEnv) {
- e.Service.EXPECT().SearchByUIN(mock.Anything, uint32(99999)).
- Return(&LegacyUserSearchResult{UIN: 99999, Nickname: "nick"}, nil).Once()
- e.Sender.EXPECT().SendPacket(e.Session.Addr, mock.AnythingOfType("[]uint8")).Return(nil).Once()
- e.Sender.EXPECT().SendToSession(e.Session, mock.AnythingOfType("[]uint8")).Return(nil).Times(2)
- }, nil),
- },
- {
- name: "not found",
- session: v3Session(testV3UIN),
- pkt: defaultV3Pkt(ICQLegacyCmdSearchStart, v3SearchUINData(99999)),
- setup: v3CaseSetup(func(e v3HandleEnv) {
- e.Service.EXPECT().SearchByUIN(mock.Anything, uint32(99999)).
- Return(nil, nil).Once()
- e.Sender.EXPECT().SendPacket(e.Session.Addr, mock.AnythingOfType("[]uint8")).Return(nil).Once()
- e.Sender.EXPECT().SendToSession(e.Session, mock.AnythingOfType("[]uint8")).Return(nil).Once()
- }, nil),
- },
- })
- }
- func TestV3Handler_HandleGetDeps1(t *testing.T) {
- runV3HandleCases(t, []v3HandleCase{
- {
- name: "sends deps list",
- session: v3Session(testV3UIN),
- pkt: defaultV3Pkt(ICQLegacyCmdGetDeps1, nil),
- setup: v3CaseSetup(func(e v3HandleEnv) {
- e.Sender.EXPECT().SendPacket(e.Session.Addr, mock.AnythingOfType("[]uint8")).Return(nil).Once()
- e.Sender.EXPECT().SendToSession(e.Session, mock.MatchedBy(func(p []byte) bool {
- return v3ServerCommand(p) == ICQLegacySrvUserDepsList1
- })).Return(nil).Once()
- }, nil),
- },
- })
- }
- func TestV3Handler_HandleGetNotes(t *testing.T) {
- runV3HandleCases(t, []v3HandleCase{
- {
- name: "success",
- session: v3Session(testV3UIN),
- pkt: defaultV3Pkt(0x05AA, v3TargetUINData(testV3UIN)),
- setup: v3CaseSetup(func(e v3HandleEnv) {
- e.Service.EXPECT().GetNotes(mock.Anything, testV3UIN).Return("hello notes", nil).Once()
- e.Sender.EXPECT().SendPacket(e.Session.Addr, mock.AnythingOfType("[]uint8")).Return(nil).Once()
- e.Sender.EXPECT().SendToSession(e.Session, mock.AnythingOfType("[]uint8")).Return(nil).Once()
- }, nil),
- },
- })
- }
- func TestV3Handler_HandleSetNotes(t *testing.T) {
- runV3HandleCases(t, []v3HandleCase{
- {
- name: "success",
- session: v3Session(testV3UIN),
- pkt: defaultV3Pkt(0x0596, v3SetNotesData("about me")),
- setup: v3CaseSetup(func(e v3HandleEnv) {
- e.Service.EXPECT().SetNotes(mock.Anything, testV3UIN, "about me").Return(nil).Once()
- e.Sender.EXPECT().SendPacket(e.Session.Addr, mock.AnythingOfType("[]uint8")).Return(nil).Once()
- e.Sender.EXPECT().SendToSession(e.Session, mock.AnythingOfType("[]uint8")).Return(nil).Once()
- }, nil),
- },
- })
- }
- func TestV3Handler_HandleSetPassword(t *testing.T) {
- runV3HandleCases(t, []v3HandleCase{
- {
- name: "success",
- session: v3Session(testV3UIN),
- pkt: defaultV3Pkt(ICQLegacyCmdSetPassword, v3SetPasswordData("newsecret")),
- setup: v3CaseSetup(func(e v3HandleEnv) {
- e.Service.EXPECT().SetPassword(mock.Anything, testV3UIN, "", "newsecret").Return(nil).Once()
- e.Sender.EXPECT().SendPacket(e.Session.Addr, mock.AnythingOfType("[]uint8")).Return(nil).Once()
- e.Sender.EXPECT().SendToSession(e.Session, mock.AnythingOfType("[]uint8")).Return(nil).Once()
- }, nil),
- },
- })
- }
- func TestV3Handler_HandleSetAuth(t *testing.T) {
- runV3HandleCases(t, []v3HandleCase{
- {
- name: "auth required",
- session: v3Session(testV3UIN),
- pkt: defaultV3Pkt(ICQLegacyCmdSetAuth, v3SetAuthData(true)),
- setup: v3CaseSetup(func(e v3HandleEnv) {
- e.Service.EXPECT().SetAuthMode(mock.Anything, testV3UIN, true).Return(nil).Once()
- e.Sender.EXPECT().SendPacket(e.Session.Addr, mock.AnythingOfType("[]uint8")).Return(nil).Once()
- e.Sender.EXPECT().SendToSession(e.Session, mock.AnythingOfType("[]uint8")).Return(nil).Once()
- }, nil),
- },
- })
- }
- func TestV3Handler_HandleSetState(t *testing.T) {
- runV3HandleCases(t, []v3HandleCase{
- {
- name: "updates status",
- session: v3Session(testV3UIN),
- pkt: defaultV3Pkt(0x0528, v3SetStateData(2, 1)),
- setup: v3CaseSetup(func(e v3HandleEnv) {
- e.Sender.EXPECT().SendPacket(e.Session.Addr, mock.AnythingOfType("[]uint8")).Return(nil).Once()
- }, func(e v3HandleEnv, err error) {
- assert.NoError(e.T, err)
- assert.Equal(e.T, uint32(2|1<<16), e.Session.GetStatus())
- }),
- },
- })
- }
- func TestV3Handler_HandleUsageStats(t *testing.T) {
- runV3HandleCases(t, []v3HandleCase{
- {
- name: "acks stats",
- session: v3Session(testV3UIN),
- pkt: defaultV3Pkt(0x0532, nil),
- setup: v3CaseSetup(func(e v3HandleEnv) {
- e.Sender.EXPECT().SendPacket(e.Session.Addr, mock.AnythingOfType("[]uint8")).Return(nil).Once()
- }, nil),
- },
- })
- }
- func TestV3Handler_HandleGetExternals(t *testing.T) {
- runV3HandleCases(t, []v3HandleCase{
- {
- name: "empty externals",
- session: v3Session(testV3UIN),
- pkt: defaultV3Pkt(ICQLegacyCmdGetExternals, nil),
- setup: v3CaseSetup(func(e v3HandleEnv) {
- e.Sender.EXPECT().SendPacket(e.Session.Addr, mock.AnythingOfType("[]uint8")).Return(nil).Once()
- e.Sender.EXPECT().SendToSession(e.Session, mock.AnythingOfType("[]uint8")).Return(nil).Once()
- }, nil),
- },
- })
- }
- func TestV3Handler_HandleSysAck(t *testing.T) {
- runV3HandleCases(t, []v3HandleCase{
- {
- name: "acks offline messages",
- session: v3Session(testV3UIN),
- pkt: defaultV3Pkt(ICQLegacyCmdSysMsgDoneAck, nil),
- setup: v3CaseSetup(func(e v3HandleEnv) {
- e.Service.EXPECT().AckOfflineMessages(mock.Anything, testV3UIN).Return(nil).Once()
- e.Sender.EXPECT().SendPacket(e.Session.Addr, mock.AnythingOfType("[]uint8")).Return(nil).Once()
- }, nil),
- },
- })
- }
- func TestV3Handler_HandleOnlineInfo(t *testing.T) {
- runV3HandleCases(t, []v3HandleCase{
- {
- name: "reconnect",
- session: v3Session(testV3UIN),
- pkt: defaultV3Pkt(ICQLegacyCmdReconnect, nil),
- setup: v3CaseSetup(func(e v3HandleEnv) {
- e.Sender.EXPECT().SendPacket(e.Session.Addr, mock.AnythingOfType("[]uint8")).Return(nil).Once()
- }, nil),
- },
- })
- }
- func TestV3Handler_HandleGetInfo1(t *testing.T) {
- runV3HandleCases(t, []v3HandleCase{
- {
- name: "basic info only",
- session: v3Session(testV3UIN),
- pkt: defaultV3Pkt(ICQLegacyCmdInfoReq, v3TargetUINData(99999)),
- setup: v3CaseSetup(func(e v3HandleEnv) {
- e.Service.EXPECT().GetUserInfoForProtocol(mock.Anything, uint32(99999)).
- Return(&UserInfoResult{UIN: 99999, Nickname: "nick"}, nil).Once()
- e.Sender.EXPECT().SendPacket(e.Session.Addr, mock.AnythingOfType("[]uint8")).Return(nil).Once()
- e.Sender.EXPECT().SendToSession(e.Session, mock.AnythingOfType("[]uint8")).Return(nil).Once()
- }, nil),
- },
- })
- }
- func TestV3Handler_HandleGetInfo(t *testing.T) {
- runV3HandleCases(t, []v3HandleCase{
- {
- name: "full info",
- session: v3Session(testV3UIN),
- pkt: defaultV3Pkt(ICQLegacyCmdUserGetInfo, v3TargetUINData(99999)),
- setup: v3CaseSetup(func(e v3HandleEnv) {
- e.Service.EXPECT().GetUserInfoForProtocol(mock.Anything, uint32(99999)).
- Return(&UserInfoResult{UIN: 99999, Nickname: "nick"}, nil).Once()
- e.Sender.EXPECT().SendPacket(e.Session.Addr, mock.AnythingOfType("[]uint8")).Return(nil).Once()
- e.Sender.EXPECT().SendToSession(e.Session, mock.AnythingOfType("[]uint8")).Return(nil).Times(5)
- }, nil),
- },
- })
- }
- func TestV3Handler_sendUserOnline(t *testing.T) {
- const onlineUIN = uint32(67890)
- sender := newMockPacketSender(t)
- svc := newMockLegacyService(t)
- recipient := v3Session(testV3UIN)
- status := uint32(0x00000010)
- sender.EXPECT().SendToSession(recipient, mock.MatchedBy(func(p []byte) bool {
- data := v3ServerPacketData(p)
- return v3ServerCommand(p) == ICQLegacySrvUserOnline &&
- len(data) >= 4 &&
- binary.LittleEndian.Uint32(data[0:4]) == onlineUIN
- })).Return(nil).Once()
- h := newTestV3Handler(t, sender, svc, newTestLegacySessionManager())
- require.NoError(t, h.sendUserOnline(recipient, onlineUIN, status))
- }
- func TestV3Handler_sendUserOffline(t *testing.T) {
- const offlineUIN = uint32(88888)
- sender := newMockPacketSender(t)
- svc := newMockLegacyService(t)
- recipient := v3Session(testV3UIN)
- sender.EXPECT().SendToSession(recipient, mock.MatchedBy(func(p []byte) bool {
- data := v3ServerPacketData(p)
- return v3ServerCommand(p) == ICQLegacySrvUserOffline &&
- len(data) == 4 &&
- binary.LittleEndian.Uint32(data[0:4]) == offlineUIN
- })).Return(nil).Once()
- h := newTestV3Handler(t, sender, svc, newTestLegacySessionManager())
- require.NoError(t, h.sendUserOffline(recipient, offlineUIN))
- }
- func TestV3Handler_sendUserStatus(t *testing.T) {
- const (
- changedUIN = uint32(88888)
- status = uint32(0x00010002)
- )
- sender := newMockPacketSender(t)
- svc := newMockLegacyService(t)
- recipient := v3Session(testV3UIN)
- sender.EXPECT().SendToSession(recipient, mock.MatchedBy(func(p []byte) bool {
- data := v3ServerPacketData(p)
- return v3ServerCommand(p) == ICQLegacySrvUserStatus &&
- len(data) == 8 &&
- binary.LittleEndian.Uint32(data[0:4]) == changedUIN &&
- binary.LittleEndian.Uint16(data[4:6]) == uint16(status&0xFFFF) &&
- binary.LittleEndian.Uint16(data[6:8]) == uint16(status>>16)
- })).Return(nil).Once()
- h := newTestV3Handler(t, sender, svc, newTestLegacySessionManager())
- require.NoError(t, h.sendUserStatus(recipient, changedUIN, status))
- }
- func TestV3Handler_sendOnlineMessage(t *testing.T) {
- const fromUIN = uint32(55555)
- sender := newMockPacketSender(t)
- svc := newMockLegacyService(t)
- recipient := v3Session(testV3UIN)
- sender.EXPECT().SendToSession(recipient, mock.MatchedBy(func(p []byte) bool {
- data := v3ServerPacketData(p)
- return v3ServerCommand(p) == ICQLegacySrvSysMsgOnline &&
- len(data) >= 8 &&
- binary.LittleEndian.Uint32(data[0:4]) == fromUIN
- })).Return(nil).Once()
- h := newTestV3Handler(t, sender, svc, newTestLegacySessionManager())
- require.NoError(t, h.sendOnlineMessage(recipient, fromUIN, 0x0001, "hello", testV3Seq2))
- }
- func TestV3Handler_sendSearchFound(t *testing.T) {
- sender := newMockPacketSender(t)
- svc := newMockLegacyService(t)
- session := v3Session(testV3UIN)
- sender.EXPECT().SendToSession(session, mock.MatchedBy(func(p []byte) bool {
- data := v3ServerPacketData(p)
- return v3ServerCommand(p) == 0x008C &&
- len(data) >= 4 &&
- binary.LittleEndian.Uint32(data[0:4]) == uint32(99999)
- })).Return(nil).Once()
- h := newTestV3Handler(t, sender, svc, newTestLegacySessionManager())
- require.NoError(t, h.sendSearchFound(session, testV3Seq2, 99999, "nick", "first", "last", "a@b.com", 0))
- }
- func TestV3Handler_sendSearchDone(t *testing.T) {
- sender := newMockPacketSender(t)
- svc := newMockLegacyService(t)
- session := v3Session(testV3UIN)
- sender.EXPECT().SendToSession(session, mock.MatchedBy(func(p []byte) bool {
- return v3ServerCommand(p) == 0x00A0 && len(p) == 17
- })).Return(nil).Once()
- h := newTestV3Handler(t, sender, svc, newTestLegacySessionManager())
- require.NoError(t, h.sendSearchDone(session, testV3Seq2))
- }
- func TestV3Handler_sendDeptsList1(t *testing.T) {
- sender := newMockPacketSender(t)
- svc := newMockLegacyService(t)
- session := v3Session(testV3UIN)
- sender.EXPECT().SendToSession(session, mock.MatchedBy(func(p []byte) bool {
- return v3ServerCommand(p) == ICQLegacySrvUserDepsList1
- })).Return(nil).Once()
- h := newTestV3Handler(t, sender, svc, newTestLegacySessionManager())
- require.NoError(t, h.sendDeptsList1(session, testV3Seq2))
- }
- func TestV3Handler_HandleSetStatus_notifiesContacts(t *testing.T) {
- const contactUIN = uint32(88888)
- changer := v3Session(testV3UIN)
- contact := v3Session(contactUIN)
- sender := newMockPacketSender(t)
- svc := newMockLegacyService(t)
- sessions := newTestLegacySessionManager()
- registerSession(sessions, changer)
- registerSession(sessions, contact)
- svc.EXPECT().ProcessStatusChange(mock.Anything, mock.Anything).
- Return(&StatusChangeResult{NotifyTargets: []NotifyTarget{{UIN: contactUIN}}}, nil).Once()
- sender.EXPECT().SendPacket(changer.Addr, mock.AnythingOfType("[]uint8")).Return(nil).Once()
- sender.EXPECT().SendToSession(contact, mock.MatchedBy(func(p []byte) bool {
- return v3ServerCommand(p) == ICQLegacySrvUserStatus
- })).Return(nil).Once()
- h := newTestV3Handler(t, sender, svc, sessions)
- pkt := defaultV3Pkt(ICQLegacyCmdSetStatus, v3SetStatusData(0x00000002))
- require.NoError(t, h.Handle(changer, testV3Addr, pkt))
- }
- func TestV3Handler_HandleLogoff_notifiesContacts(t *testing.T) {
- const contactUIN = uint32(88888)
- loggingOff := v3Session(testV3UIN)
- contact := v3Session(contactUIN)
- contact.SetContactList([]uint32{testV3UIN})
- sender := newMockPacketSender(t)
- svc := newMockLegacyService(t)
- sessions := newTestLegacySessionManager()
- registerSession(sessions, loggingOff)
- registerSession(sessions, contact)
- svc.EXPECT().NotifyUserOffline(mock.Anything, testV3UIN).Return(nil).Once()
- sender.EXPECT().SendToSession(contact, mock.MatchedBy(func(p []byte) bool {
- return v3ServerCommand(p) == ICQLegacySrvUserOffline
- })).Return(nil).Once()
- h := newTestV3HandlerWithDispatcher(t, sender, svc, sessions)
- pkt := defaultV3Pkt(ICQLegacyCmdLogoff, nil)
- require.NoError(t, h.Handle(loggingOff, testV3Addr, pkt))
- }
|