//////////////////////////////////////////////////////////////////////////////// // Copyright © 2022 xx foundation // // // // Use of this source code is governed by a license that can be found in the // // LICENSE file. // //////////////////////////////////////////////////////////////////////////////// package single import ( "gitlab.com/elixxir/client/cmix" "gitlab.com/elixxir/client/cmix/identity/receptionID" "gitlab.com/elixxir/client/cmix/message" "gitlab.com/elixxir/client/cmix/rounds" "gitlab.com/elixxir/comms/network" "gitlab.com/elixxir/primitives/format" "gitlab.com/xx_network/comms/connect" "gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/id/ephemeral" "sync" "testing" "time" ) //////////////////////////////////////////////////////////////////////////////// // Mock cMix // //////////////////////////////////////////////////////////////////////////////// // Tests that mockCmix adheres to the Cmix interface. var _ Cmix = (*mockCmix)(nil) type mockCmixHandler struct { fingerprints map[id.ID]map[format.Fingerprint]message.Processor services map[id.ID]map[string]message.Processor sends []send sync.Mutex } func newMockCmixHandler() *mockCmixHandler { return &mockCmixHandler{ fingerprints: make(map[id.ID]map[format.Fingerprint]message.Processor), services: make(map[id.ID]map[string]message.Processor), sends: []send{}, } } type mockCmix struct { myID *id.ID numPrimeBytes int addressSpaceSize uint8 health bool instance *network.Instance handler *mockCmixHandler t testing.TB sync.Mutex } type send struct { myID *id.ID recipient *id.ID ms message.Service msg format.Message } func newMockCmix(myID *id.ID, handler *mockCmixHandler, t testing.TB) *mockCmix { comms := &connect.ProtoComms{Manager: connect.NewManagerTesting(t)} def := getNDF() instance, err := network.NewInstanceTesting(comms, def, def, nil, nil, t) if err != nil { panic(err) } return &mockCmix{ myID: myID, numPrimeBytes: 1024, addressSpaceSize: 18, health: true, instance: instance, handler: handler, t: t, } } func (m *mockCmix) IsHealthy() bool { return m.health } func (m *mockCmix) GetMaxMessageLength() int { msg := format.NewMessage(m.numPrimeBytes) return msg.ContentsSize() } func (m *mockCmix) GetAddressSpace() uint8 { return m.addressSpaceSize } func (m *mockCmix) DeleteClientFingerprints(identity *id.ID) { m.handler.Lock() defer m.handler.Unlock() delete(m.handler.fingerprints, *identity) } func (m *mockCmix) AddFingerprint( identity *id.ID, fp format.Fingerprint, mp message.Processor) error { m.handler.Lock() defer m.handler.Unlock() if _, exists := m.handler.fingerprints[*identity]; !exists { m.handler.fingerprints[*identity] = map[format.Fingerprint]message.Processor{fp: mp} } else { m.handler.fingerprints[*identity][fp] = mp } return nil } func (m *mockCmix) AddIdentity(*id.ID, time.Time, bool) {} func (m *mockCmix) Send(recipient *id.ID, fp format.Fingerprint, ms message.Service, payload, mac []byte, _ cmix.CMIXParams) ( rounds.Round, ephemeral.Id, error) { msg := format.NewMessage(m.numPrimeBytes) msg.SetMac(mac) msg.SetKeyFP(fp) msg.SetContents(payload) m.handler.Lock() defer m.handler.Unlock() var sent bool if _, exists := m.handler.fingerprints[*recipient]; exists { if mp, exists := m.handler.fingerprints[*recipient][fp]; exists { sent = true go mp.Process( msg, receptionID.EphemeralIdentity{Source: m.myID}, rounds.Round{}) } } if _, exists := m.handler.services[*recipient]; exists { if mp, exists := m.handler.services[*recipient][serviceKey(ms)]; exists { sent = true go mp.Process( msg, receptionID.EphemeralIdentity{Source: m.myID}, rounds.Round{}) } } if !sent { m.handler.sends = append(m.handler.sends, send{ myID: m.myID, recipient: recipient, ms: ms, msg: msg, }) } return rounds.Round{}, ephemeral.Id{}, nil } func serviceKey(ms message.Service) string { return string(append(ms.Identifier, []byte(ms.Tag)...)) } func (m *mockCmix) AddService(clientID *id.ID, ms message.Service, mp message.Processor) { m.handler.Lock() defer m.handler.Unlock() if _, exists := m.handler.services[*clientID]; !exists { m.handler.services[*clientID] = map[string]message.Processor{ serviceKey(ms): mp} } else { m.handler.services[*clientID][serviceKey(ms)] = mp } } func (m *mockCmix) DeleteService(clientID *id.ID, ms message.Service, _ message.Processor) { m.handler.Lock() defer m.handler.Unlock() if _, exists := m.handler.services[*clientID]; exists { delete(m.handler.services[*clientID], serviceKey(ms)) } } func (m *mockCmix) GetInstance() *network.Instance { return m.instance } func (m *mockCmix) CheckInProgressMessages() { m.handler.Lock() defer m.handler.Unlock() var newSends []send for _, s := range m.handler.sends { var sent bool if _, exists := m.handler.fingerprints[*s.recipient]; exists { if mp, exists := m.handler.fingerprints[*s.recipient][s.msg.GetKeyFP()]; exists { sent = true go mp.Process( s.msg, receptionID.EphemeralIdentity{Source: s.myID}, rounds.Round{}) } } if _, exists := m.handler.services[*s.recipient]; exists { if mp, exists := m.handler.services[*s.recipient][serviceKey(s.ms)]; exists { sent = true go mp.Process( s.msg, receptionID.EphemeralIdentity{Source: s.myID}, rounds.Round{}) } } if !sent { newSends = append(newSends, s) } } m.handler.sends = newSends }