From 81705cd5e2f83320b292f52823b9f921cabcbc14 Mon Sep 17 00:00:00 2001 From: Andreas Linde Date: Thu, 4 Jan 2024 14:10:27 +0100 Subject: [PATCH] Add tests for service --- logging/log.go | 2 + logging/mocks/Logging.go | 84 ++++++++++++++++++++ service/hub.go | 123 ++++++++++++++++------------- service/hub_test.go | 30 +++---- service/mock_hub_test.go | 149 ++++++++++++++++++++++++++++++++++- service/mock_service_test.go | 108 +++++++++++++++++++++++++ service/service.go | 25 +++--- service/service_test.go | 147 ++++++++++++++++++++++++++++++++++ 8 files changed, 588 insertions(+), 80 deletions(-) create mode 100644 logging/mocks/Logging.go create mode 100644 service/mock_service_test.go create mode 100644 service/service_test.go diff --git a/logging/log.go b/logging/log.go index e65ab284..7ddb1611 100644 --- a/logging/log.go +++ b/logging/log.go @@ -1,5 +1,7 @@ package logging +//go:generate mockery --name=Logging + // Logging needs to be implemented, if the internal logs should be printed type Logging interface { Trace(args ...interface{}) diff --git a/logging/mocks/Logging.go b/logging/mocks/Logging.go new file mode 100644 index 00000000..d88ff663 --- /dev/null +++ b/logging/mocks/Logging.go @@ -0,0 +1,84 @@ +// Code generated by mockery v2.39.1. DO NOT EDIT. + +package mocks + +import mock "github.com/stretchr/testify/mock" + +// Logging is an autogenerated mock type for the Logging type +type Logging struct { + mock.Mock +} + +// Debug provides a mock function with given fields: args +func (_m *Logging) Debug(args ...interface{}) { + var _ca []interface{} + _ca = append(_ca, args...) + _m.Called(_ca...) +} + +// Debugf provides a mock function with given fields: format, args +func (_m *Logging) Debugf(format string, args ...interface{}) { + var _ca []interface{} + _ca = append(_ca, format) + _ca = append(_ca, args...) + _m.Called(_ca...) +} + +// Error provides a mock function with given fields: args +func (_m *Logging) Error(args ...interface{}) { + var _ca []interface{} + _ca = append(_ca, args...) + _m.Called(_ca...) +} + +// Errorf provides a mock function with given fields: format, args +func (_m *Logging) Errorf(format string, args ...interface{}) { + var _ca []interface{} + _ca = append(_ca, format) + _ca = append(_ca, args...) + _m.Called(_ca...) +} + +// Info provides a mock function with given fields: args +func (_m *Logging) Info(args ...interface{}) { + var _ca []interface{} + _ca = append(_ca, args...) + _m.Called(_ca...) +} + +// Infof provides a mock function with given fields: format, args +func (_m *Logging) Infof(format string, args ...interface{}) { + var _ca []interface{} + _ca = append(_ca, format) + _ca = append(_ca, args...) + _m.Called(_ca...) +} + +// Trace provides a mock function with given fields: args +func (_m *Logging) Trace(args ...interface{}) { + var _ca []interface{} + _ca = append(_ca, args...) + _m.Called(_ca...) +} + +// Tracef provides a mock function with given fields: format, args +func (_m *Logging) Tracef(format string, args ...interface{}) { + var _ca []interface{} + _ca = append(_ca, format) + _ca = append(_ca, args...) + _m.Called(_ca...) +} + +// NewLogging creates a new instance of Logging. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewLogging(t interface { + mock.TestingT + Cleanup(func()) +}) *Logging { + mock := &Logging{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/service/hub.go b/service/hub.go index 3ef0c91a..2b2a73ce 100644 --- a/service/hub.go +++ b/service/hub.go @@ -40,7 +40,7 @@ var connectionInitiationDelayTimeRanges = []connectionInitiationDelayTimeRange{ {min: 10, max: 20}, } -//go:generate mockgen -destination=mock_hub_test.go -package=service github.com/enbility/eebus-go/service ServiceProvider +//go:generate mockgen -destination=mock_hub_test.go -package=service github.com/enbility/eebus-go/service ServiceProvider,ConnectionsHub // interface for reporting data from connectionsHub to the EEBUSService type ServiceProvider interface { @@ -64,8 +64,21 @@ type ServiceProvider interface { AllowWaitingForTrust(ski string) bool } +type ConnectionsHub interface { + PairingDetailForSki(ski string) *ConnectionStateDetail + StartBrowseMdnsSearch() + StopBrowseMdnsSearch() + Start() + Shutdown() + ServiceForSKI(ski string) *ServiceDetails + RegisterRemoteSKI(ski string, enable bool) + InitiatePairingWithSKI(ski string) + CancelPairingWithSKI(ski string) + DisconnectSKI(ski string, reason string) +} + // handling all connections to remote services -type connectionsHub struct { +type connectionsHubImpl struct { connections map[string]*ship.ShipConnection // which attempt is it to initate an connection to the remote SKI @@ -98,8 +111,8 @@ type connectionsHub struct { muxMdns sync.Mutex } -func newConnectionsHub(serviceProvider ServiceProvider, mdns MdnsService, spineLocalDevice *spine.DeviceLocalImpl, configuration *Configuration, localService *ServiceDetails) *connectionsHub { - hub := &connectionsHub{ +func newConnectionsHub(serviceProvider ServiceProvider, mdns MdnsService, spineLocalDevice *spine.DeviceLocalImpl, configuration *Configuration, localService *ServiceDetails) ConnectionsHub { + hub := &connectionsHubImpl{ connections: make(map[string]*ship.ShipConnection), connectionAttemptCounter: make(map[string]int), connectionAttemptRunning: make(map[string]bool), @@ -115,8 +128,8 @@ func newConnectionsHub(serviceProvider ServiceProvider, mdns MdnsService, spineL return hub } -// start the ConnectionsHub with all its services -func (h *connectionsHub) start() { +// Start the ConnectionsHub with all its services +func (h *connectionsHubImpl) Start() { // start the websocket server if err := h.startWebsocketServer(); err != nil { logging.Log.Debug("error during websocket server starting:", err) @@ -131,17 +144,17 @@ func (h *connectionsHub) start() { h.checkRestartMdnsSearch() } -var _ ship.ShipServiceDataProvider = (*connectionsHub)(nil) +var _ ship.ShipServiceDataProvider = (*connectionsHubImpl)(nil) // Returns if the provided SKI is from a registered service -func (h *connectionsHub) IsRemoteServiceForSKIPaired(ski string) bool { - service := h.serviceForSKI(ski) +func (h *connectionsHubImpl) IsRemoteServiceForSKIPaired(ski string) bool { + service := h.ServiceForSKI(ski) return service.Trusted } // The connection was closed, we need to clean up -func (h *connectionsHub) HandleConnectionClosed(connection *ship.ShipConnection, handshakeCompleted bool) { +func (h *connectionsHubImpl) HandleConnectionClosed(connection *ship.ShipConnection, handshakeCompleted bool) { // only remove this connection if it is the registered one for the ski! // as we can have double connections but only one can be registered if existingC := h.connectionForSKI(connection.RemoteSKI); existingC != nil { @@ -160,7 +173,7 @@ func (h *connectionsHub) HandleConnectionClosed(connection *ship.ShipConnection, h.serviceProvider.RemoteSKIDisconnected(connection.RemoteSKI) // Do not automatically reconnect if handshake failed and not already paired - remoteService := h.serviceForSKI(connection.RemoteSKI) + remoteService := h.ServiceForSKI(connection.RemoteSKI) if !handshakeCompleted && !remoteService.Trusted { return } @@ -169,7 +182,7 @@ func (h *connectionsHub) HandleConnectionClosed(connection *ship.ShipConnection, } // return the number of paired services -func (h *connectionsHub) numberPairedServices() int { +func (h *connectionsHubImpl) numberPairedServices() int { amount := 0 h.muxReg.Lock() @@ -184,7 +197,7 @@ func (h *connectionsHub) numberPairedServices() int { } // startup mDNS if a paired service is not connected -func (h *connectionsHub) checkRestartMdnsSearch() { +func (h *connectionsHubImpl) checkRestartMdnsSearch() { countPairedServices := h.numberPairedServices() h.muxCon.Lock() countConnections := len(h.connections) @@ -200,26 +213,26 @@ func (h *connectionsHub) checkRestartMdnsSearch() { } } -func (h *connectionsHub) StartBrowseMdnsSearch() { +func (h *connectionsHubImpl) StartBrowseMdnsSearch() { // TODO: this currently collides with searching for a specific SKI h.mdns.RegisterMdnsSearch(h) } -func (h *connectionsHub) StopBrowseMdnsSearch() { +func (h *connectionsHubImpl) StopBrowseMdnsSearch() { // TODO: this currently collides with searching for a specific SKI h.mdns.UnregisterMdnsSearch(h) } // Provides the SHIP ID the remote service reported during the handshake process -func (h *connectionsHub) ReportServiceShipID(ski string, shipdID string) { +func (h *connectionsHubImpl) ReportServiceShipID(ski string, shipdID string) { h.serviceProvider.RemoteSKIConnected(ski) h.serviceProvider.ServiceShipIDUpdate(ski, shipdID) } // return if the user is still able to trust the connection -func (h *connectionsHub) AllowWaitingForTrust(ski string) bool { - if service := h.serviceForSKI(ski); service != nil { +func (h *connectionsHubImpl) AllowWaitingForTrust(ski string) bool { + if service := h.ServiceForSKI(ski); service != nil { if service.Trusted { return true } @@ -229,7 +242,7 @@ func (h *connectionsHub) AllowWaitingForTrust(ski string) bool { } // Provides the current ship message exchange state for a given SKI and the corresponding error if state is error -func (h *connectionsHub) HandleShipHandshakeStateUpdate(ski string, state ship.ShipState) { +func (h *connectionsHubImpl) HandleShipHandshakeStateUpdate(ski string, state ship.ShipState) { // overwrite service Paired value if state.State == ship.SmeHelloStateOk { h.RegisterRemoteSKI(ski, true) @@ -242,7 +255,7 @@ func (h *connectionsHub) HandleShipHandshakeStateUpdate(ski string, state ship.S pairingDetail := NewConnectionStateDetail(pairingState, state.Error) - service := h.serviceForSKI(ski) + service := h.ServiceForSKI(ski) existingDetails := service.ConnectionStateDetail if existingDetails.State() != pairingState || existingDetails.Error() != state.Error { @@ -258,8 +271,8 @@ func (h *connectionsHub) HandleShipHandshakeStateUpdate(ski string, state ship.S // // ErrNotPaired if the SKI is not in the (to be) paired list // ErrNoConnectionFound if no connection for the SKI was found -func (h *connectionsHub) PairingDetailForSki(ski string) *ConnectionStateDetail { - service := h.serviceForSKI(ski) +func (h *connectionsHubImpl) PairingDetailForSki(ski string) *ConnectionStateDetail { + service := h.ServiceForSKI(ski) if conn := h.connectionForSKI(ski); conn != nil { shipState, shipError := conn.ShipHandshakeState() @@ -271,7 +284,7 @@ func (h *connectionsHub) PairingDetailForSki(ski string) *ConnectionStateDetail } // maps ShipMessageExchangeState to PairingState -func (h *connectionsHub) mapShipMessageExchangeState(state ship.ShipMessageExchangeState, ski string) ConnectionState { +func (h *connectionsHubImpl) mapShipMessageExchangeState(state ship.ShipMessageExchangeState, ski string) ConnectionState { var connState ConnectionState // map the SHIP states to a public gState @@ -311,7 +324,7 @@ func (h *connectionsHub) mapShipMessageExchangeState(state ship.ShipMessageExcha // Disconnect a connection to an SKI, used by a service implementation // e.g. if heartbeats go wrong -func (h *connectionsHub) DisconnectSKI(ski string, reason string) { +func (h *connectionsHubImpl) DisconnectSKI(ski string, reason string) { h.muxCon.Lock() defer h.muxCon.Unlock() @@ -325,14 +338,14 @@ func (h *connectionsHub) DisconnectSKI(ski string, reason string) { } // register a new ship Connection -func (h *connectionsHub) registerConnection(connection *ship.ShipConnection) { +func (h *connectionsHubImpl) registerConnection(connection *ship.ShipConnection) { h.muxCon.Lock() h.connections[connection.RemoteSKI] = connection h.muxCon.Unlock() } // return the connection for a specific SKI -func (h *connectionsHub) connectionForSKI(ski string) *ship.ShipConnection { +func (h *connectionsHubImpl) connectionForSKI(ski string) *ship.ShipConnection { h.muxCon.Lock() defer h.muxCon.Unlock() @@ -344,7 +357,7 @@ func (h *connectionsHub) connectionForSKI(ski string) *ship.ShipConnection { } // close all connections -func (h *connectionsHub) shutdown() { +func (h *connectionsHubImpl) Shutdown() { h.mdns.ShutdownMdnsService() for _, c := range h.connections { c.CloseConnection(false, 0, "") @@ -352,7 +365,7 @@ func (h *connectionsHub) shutdown() { } // return if there is a connection for a SKI -func (h *connectionsHub) isSkiConnected(ski string) bool { +func (h *connectionsHubImpl) isSkiConnected(ski string) bool { h.muxCon.Lock() defer h.muxCon.Unlock() @@ -364,7 +377,7 @@ func (h *connectionsHub) isSkiConnected(ski string) bool { // Websocket connection handling // start the ship websocket server -func (h *connectionsHub) startWebsocketServer() error { +func (h *connectionsHubImpl) startWebsocketServer() error { addr := fmt.Sprintf(":%d", h.configuration.port) logging.Log.Debug("starting websocket server on", addr) @@ -410,7 +423,7 @@ func (h *connectionsHub) startWebsocketServer() error { // Connection Handling // HTTP Server callback for handling incoming connection requests -func (h *connectionsHub) ServeHTTP(w http.ResponseWriter, r *http.Request) { +func (h *connectionsHubImpl) ServeHTTP(w http.ResponseWriter, r *http.Request) { upgrader := websocket.Upgrader{ ReadBufferSize: ship.MaxMessageSize, WriteBufferSize: ship.MaxMessageSize, @@ -450,7 +463,7 @@ func (h *connectionsHub) ServeHTTP(w http.ResponseWriter, r *http.Request) { logging.Log.Debug("incoming connection request from", remoteService.SKI) // Check if the remote service is paired - service := h.serviceForSKI(remoteService.SKI) + service := h.ServiceForSKI(remoteService.SKI) if service.ConnectionStateDetail.State() == ConnectionStateQueued { service.ConnectionStateDetail.SetState(ConnectionStateReceivedPairingRequest) h.serviceProvider.ServicePairingDetailUpdate(ski, service.ConnectionStateDetail) @@ -475,7 +488,7 @@ func (h *connectionsHub) ServeHTTP(w http.ResponseWriter, r *http.Request) { // Connect to another EEBUS service // // returns error contains a reason for failing the connection or nil if no further tries should be processed -func (h *connectionsHub) connectFoundService(remoteService *ServiceDetails, host, port string) error { +func (h *connectionsHubImpl) connectFoundService(remoteService *ServiceDetails, host, port string) error { if h.isSkiConnected(remoteService.SKI) { return nil } @@ -544,7 +557,7 @@ func (h *connectionsHub) connectFoundService(remoteService *ServiceDetails, host // // returns true if this connection is fine to be continue // returns false if this connection should not be established or kept -func (h *connectionsHub) keepThisConnection(conn *websocket.Conn, incomingRequest bool, remoteService *ServiceDetails) bool { +func (h *connectionsHubImpl) keepThisConnection(conn *websocket.Conn, incomingRequest bool, remoteService *ServiceDetails) bool { // SHIP 12.2.2 defines: // prevent double connections with SKI Comparison // the node with the hight SKI value kees the most recent connection and @@ -588,7 +601,7 @@ func (h *connectionsHub) keepThisConnection(conn *websocket.Conn, incomingReques } // return the service for a given SKI or an error if not found -func (h *connectionsHub) serviceForSKI(ski string) *ServiceDetails { +func (h *connectionsHubImpl) ServiceForSKI(ski string) *ServiceDetails { h.muxReg.Lock() defer h.muxReg.Unlock() @@ -605,8 +618,8 @@ func (h *connectionsHub) serviceForSKI(ski string) *ServiceDetails { // Sets the SKI as being paired or not // Should be used for services which completed the pairing process and // which were stored as having the process completed -func (h *connectionsHub) RegisterRemoteSKI(ski string, enable bool) { - service := h.serviceForSKI(ski) +func (h *connectionsHubImpl) RegisterRemoteSKI(ski string, enable bool) { + service := h.ServiceForSKI(ski) service.Trusted = enable if enable { @@ -626,7 +639,7 @@ func (h *connectionsHub) RegisterRemoteSKI(ski string, enable bool) { } // Triggers the pairing process for a SKI -func (h *connectionsHub) InitiatePairingWithSKI(ski string) { +func (h *connectionsHubImpl) InitiatePairingWithSKI(ski string) { conn := h.connectionForSKI(ski) // remotely initiated @@ -637,7 +650,7 @@ func (h *connectionsHub) InitiatePairingWithSKI(ski string) { } // locally initiated - service := h.serviceForSKI(ski) + service := h.ServiceForSKI(ski) service.ConnectionStateDetail.SetState(ConnectionStateQueued) h.serviceProvider.ServicePairingDetailUpdate(ski, service.ConnectionStateDetail) @@ -649,14 +662,14 @@ func (h *connectionsHub) InitiatePairingWithSKI(ski string) { } // Cancels the pairing process for a SKI -func (h *connectionsHub) CancelPairingWithSKI(ski string) { +func (h *connectionsHubImpl) CancelPairingWithSKI(ski string) { h.removeConnectionAttemptCounter(ski) if existingC := h.connectionForSKI(ski); existingC != nil { existingC.AbortPendingHandshake() } - service := h.serviceForSKI(ski) + service := h.ServiceForSKI(ski) service.ConnectionStateDetail.SetState(ConnectionStateNone) service.Trusted = false @@ -664,7 +677,7 @@ func (h *connectionsHub) CancelPairingWithSKI(ski string) { } // Process reported mDNS services -func (h *connectionsHub) ReportMdnsEntries(entries map[string]*MdnsEntry) { +func (h *connectionsHubImpl) ReportMdnsEntries(entries map[string]*MdnsEntry) { h.muxMdns.Lock() defer h.muxMdns.Unlock() @@ -679,7 +692,7 @@ func (h *connectionsHub) ReportMdnsEntries(entries map[string]*MdnsEntry) { } // Check if the remote service is paired or queued for connection - service := h.serviceForSKI(ski) + service := h.ServiceForSKI(ski) if !h.IsRemoteServiceForSKIPaired(ski) && service.ConnectionStateDetail.State() != ConnectionStateQueued { continue @@ -709,7 +722,7 @@ func (h *connectionsHub) ReportMdnsEntries(entries map[string]*MdnsEntry) { } // coordinate connection initiation attempts to a remove service -func (h *connectionsHub) coordinateConnectionInitations(ski string, entry *MdnsEntry) { +func (h *connectionsHubImpl) coordinateConnectionInitations(ski string, entry *MdnsEntry) { if h.isConnectionAttemptRunning(ski) { return } @@ -718,7 +731,7 @@ func (h *connectionsHub) coordinateConnectionInitations(ski string, entry *MdnsE counter, duration := h.getConnectionInitiationDelayTime(ski) - service := h.serviceForSKI(ski) + service := h.ServiceForSKI(ski) if service.ConnectionStateDetail.State() == ConnectionStateQueued { go h.prepareConnectionInitation(ski, counter, entry) return @@ -738,7 +751,7 @@ func (h *connectionsHub) coordinateConnectionInitations(ski string, entry *MdnsE // invoked by coordinateConnectionInitations either with a delay or directly // when initating a pairing process -func (h *connectionsHub) prepareConnectionInitation(ski string, counter int, entry *MdnsEntry) { +func (h *connectionsHubImpl) prepareConnectionInitation(ski string, counter int, entry *MdnsEntry) { h.setConnectionAttemptRunning(ski, false) // check if the current counter is still the same, otherwise this counter is irrelevant @@ -749,7 +762,7 @@ func (h *connectionsHub) prepareConnectionInitation(ski string, counter int, ent // connection attempt is not relevant if the device is no longer paired // or it is not queued for pairing - pairingState := h.serviceForSKI(ski).ConnectionStateDetail.State() + pairingState := h.ServiceForSKI(ski).ConnectionStateDetail.State() if !h.IsRemoteServiceForSKIPaired(ski) && pairingState != ConnectionStateQueued { return } @@ -761,7 +774,7 @@ func (h *connectionsHub) prepareConnectionInitation(ski string, counter int, ent // now initiate the connection // check if the remoteService still exists - service := h.serviceForSKI(ski) + service := h.ServiceForSKI(ski) if success := h.initateConnection(service, entry); !success { h.checkRestartMdnsSearch() @@ -770,14 +783,14 @@ func (h *connectionsHub) prepareConnectionInitation(ski string, counter int, ent // attempt to establish a connection to a remote service // returns true if successful -func (h *connectionsHub) initateConnection(remoteService *ServiceDetails, entry *MdnsEntry) bool { +func (h *connectionsHubImpl) initateConnection(remoteService *ServiceDetails, entry *MdnsEntry) bool { var err error // try connecting via an IP address first for _, address := range entry.Addresses { // connection attempt is not relevant if the device is no longer paired // or it is not queued for pairing - pairingState := h.serviceForSKI(remoteService.SKI).ConnectionStateDetail.State() + pairingState := h.ServiceForSKI(remoteService.SKI).ConnectionStateDetail.State() if !h.IsRemoteServiceForSKIPaired(remoteService.SKI) && pairingState != ConnectionStateQueued { return false } @@ -806,7 +819,7 @@ func (h *connectionsHub) initateConnection(remoteService *ServiceDetails, entry } // increase the connection attempt counter for the given ski -func (h *connectionsHub) increaseConnectionAttemptCounter(ski string) int { +func (h *connectionsHubImpl) increaseConnectionAttemptCounter(ski string) int { h.muxConAttempt.Lock() defer h.muxConAttempt.Unlock() @@ -825,7 +838,7 @@ func (h *connectionsHub) increaseConnectionAttemptCounter(ski string) int { } // remove the connection attempt counter for the given ski -func (h *connectionsHub) removeConnectionAttemptCounter(ski string) { +func (h *connectionsHubImpl) removeConnectionAttemptCounter(ski string) { h.muxConAttempt.Lock() defer h.muxConAttempt.Unlock() @@ -833,7 +846,7 @@ func (h *connectionsHub) removeConnectionAttemptCounter(ski string) { } // get the current attempt counter -func (h *connectionsHub) getCurrentConnectionAttemptCounter(ski string) (int, bool) { +func (h *connectionsHubImpl) getCurrentConnectionAttemptCounter(ski string) (int, bool) { h.muxConAttempt.Lock() defer h.muxConAttempt.Unlock() @@ -844,7 +857,7 @@ func (h *connectionsHub) getCurrentConnectionAttemptCounter(ski string) (int, bo // get the connection initiation delay time range for a given ski // returns the current counter and the duration -func (h *connectionsHub) getConnectionInitiationDelayTime(ski string) (int, time.Duration) { +func (h *connectionsHubImpl) getConnectionInitiationDelayTime(ski string) (int, time.Duration) { counter := h.increaseConnectionAttemptCounter(ski) h.muxConAttempt.Lock() @@ -872,7 +885,7 @@ func (h *connectionsHub) getConnectionInitiationDelayTime(ski string) (int, time } // set if a connection attempt is running/in progress -func (h *connectionsHub) setConnectionAttemptRunning(ski string, active bool) { +func (h *connectionsHubImpl) setConnectionAttemptRunning(ski string, active bool) { h.muxConAttempt.Lock() defer h.muxConAttempt.Unlock() @@ -880,7 +893,7 @@ func (h *connectionsHub) setConnectionAttemptRunning(ski string, active bool) { } // return if a connection attempt is runnning/in progress -func (h *connectionsHub) isConnectionAttemptRunning(ski string) bool { +func (h *connectionsHubImpl) isConnectionAttemptRunning(ski string) bool { h.muxConAttempt.Lock() defer h.muxConAttempt.Unlock() diff --git a/service/hub_test.go b/service/hub_test.go index 17ec46dd..06b32818 100644 --- a/service/hub_test.go +++ b/service/hub_test.go @@ -72,11 +72,11 @@ func (s *HubSuite) Test_NewConnectionsHub() { hub := newConnectionsHub(s.serviceProvider, s.mdnsService, nil, configuration, localService) assert.NotNil(s.T(), hub) - hub.start() + hub.Start() } func (s *HubSuite) Test_IsRemoteSKIPaired() { - sut := connectionsHub{ + sut := connectionsHubImpl{ connections: make(map[string]*ship.ShipConnection), connectionAttemptCounter: make(map[string]int), remoteServices: make(map[string]*ServiceDetails), @@ -105,7 +105,7 @@ func (s *HubSuite) Test_IsRemoteSKIPaired() { } func (s *HubSuite) Test_HandleConnecitonClosed() { - sut := connectionsHub{ + sut := connectionsHubImpl{ connections: make(map[string]*ship.ShipConnection), connectionAttemptCounter: make(map[string]int), remoteServices: make(map[string]*ServiceDetails), @@ -130,7 +130,7 @@ func (s *HubSuite) Test_Mdns() { localService := ServiceDetails{ DeviceType: model.DeviceTypeTypeElectricitySupplySystem, } - sut := connectionsHub{ + sut := connectionsHubImpl{ connections: make(map[string]*ship.ShipConnection), connectionAttemptCounter: make(map[string]int), remoteServices: make(map[string]*ServiceDetails), @@ -160,7 +160,7 @@ func (s *HubSuite) Test_Ship() { localService := ServiceDetails{ DeviceType: model.DeviceTypeTypeElectricitySupplySystem, } - sut := connectionsHub{ + sut := connectionsHubImpl{ connections: make(map[string]*ship.ShipConnection), connectionAttemptCounter: make(map[string]int), remoteServices: make(map[string]*ServiceDetails), @@ -201,7 +201,7 @@ func (s *HubSuite) Test_Ship() { } func (s *HubSuite) Test_MapShipMessageExchangeState() { - sut := connectionsHub{} + sut := connectionsHubImpl{} ski := "test" @@ -240,7 +240,7 @@ func (s *HubSuite) Test_MapShipMessageExchangeState() { } func (s *HubSuite) Test_DisconnectSKI() { - sut := connectionsHub{ + sut := connectionsHubImpl{ connections: make(map[string]*ship.ShipConnection), } ski := "test" @@ -251,7 +251,7 @@ func (s *HubSuite) Test_RegisterConnection() { ski := "12af9e" localService := NewServiceDetails(ski) - sut := connectionsHub{ + sut := connectionsHubImpl{ connections: make(map[string]*ship.ShipConnection), mdns: s.mdnsService, localService: localService, @@ -270,7 +270,7 @@ func (s *HubSuite) Test_RegisterConnection() { func (s *HubSuite) Test_IncreaseConnectionAttemptCounter() { // we just need a dummy for this test - sut := connectionsHub{ + sut := connectionsHubImpl{ connectionAttemptCounter: make(map[string]int), } ski := "test" @@ -291,7 +291,7 @@ func (s *HubSuite) Test_IncreaseConnectionAttemptCounter() { func (s *HubSuite) Test_RemoveConnectionAttemptCounter() { // we just need a dummy for this test - sut := connectionsHub{ + sut := connectionsHubImpl{ connectionAttemptCounter: make(map[string]int), } ski := "test" @@ -307,7 +307,7 @@ func (s *HubSuite) Test_RemoveConnectionAttemptCounter() { func (s *HubSuite) Test_GetCurrentConnectionAttemptCounter() { // we just need a dummy for this test - sut := connectionsHub{ + sut := connectionsHubImpl{ connectionAttemptCounter: make(map[string]int), } ski := "test" @@ -326,7 +326,7 @@ func (s *HubSuite) Test_GetConnectionInitiationDelayTime() { // we just need a dummy for this test ski := "12af9e" localService := NewServiceDetails(ski) - sut := connectionsHub{ + sut := connectionsHubImpl{ localService: localService, connectionAttemptCounter: make(map[string]int), } @@ -340,7 +340,7 @@ func (s *HubSuite) Test_GetConnectionInitiationDelayTime() { func (s *HubSuite) Test_ConnectionAttemptRunning() { // we just need a dummy for this test ski := "test" - sut := connectionsHub{ + sut := connectionsHubImpl{ connectionAttemptRunning: make(map[string]bool), } @@ -354,7 +354,7 @@ func (s *HubSuite) Test_ConnectionAttemptRunning() { func (s *HubSuite) Test_InitiatePairingWithSKI() { ski := "test" - sut := connectionsHub{ + sut := connectionsHubImpl{ connections: make(map[string]*ship.ShipConnection), connectionAttemptRunning: make(map[string]bool), remoteServices: make(map[string]*ServiceDetails), @@ -375,7 +375,7 @@ func (s *HubSuite) Test_InitiatePairingWithSKI() { func (s *HubSuite) Test_CancelPairingWithSKI() { ski := "test" - sut := connectionsHub{ + sut := connectionsHubImpl{ connections: make(map[string]*ship.ShipConnection), connectionAttemptRunning: make(map[string]bool), remoteServices: make(map[string]*ServiceDetails), diff --git a/service/mock_hub_test.go b/service/mock_hub_test.go index 99f8b912..fddaaff5 100644 --- a/service/mock_hub_test.go +++ b/service/mock_hub_test.go @@ -1,5 +1,5 @@ // Code generated by MockGen. DO NOT EDIT. -// Source: github.com/enbility/eebus-go/service (interfaces: ServiceProvider) +// Source: github.com/enbility/eebus-go/service (interfaces: ServiceProvider,ConnectionsHub) // Package service is a generated GoMock package. package service @@ -106,3 +106,150 @@ func (mr *MockServiceProviderMockRecorder) VisibleMDNSRecordsUpdated(arg0 interf mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "VisibleMDNSRecordsUpdated", reflect.TypeOf((*MockServiceProvider)(nil).VisibleMDNSRecordsUpdated), arg0) } + +// MockConnectionsHub is a mock of ConnectionsHub interface. +type MockConnectionsHub struct { + ctrl *gomock.Controller + recorder *MockConnectionsHubMockRecorder +} + +// MockConnectionsHubMockRecorder is the mock recorder for MockConnectionsHub. +type MockConnectionsHubMockRecorder struct { + mock *MockConnectionsHub +} + +// NewMockConnectionsHub creates a new mock instance. +func NewMockConnectionsHub(ctrl *gomock.Controller) *MockConnectionsHub { + mock := &MockConnectionsHub{ctrl: ctrl} + mock.recorder = &MockConnectionsHubMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockConnectionsHub) EXPECT() *MockConnectionsHubMockRecorder { + return m.recorder +} + +// CancelPairingWithSKI mocks base method. +func (m *MockConnectionsHub) CancelPairingWithSKI(arg0 string) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "CancelPairingWithSKI", arg0) +} + +// CancelPairingWithSKI indicates an expected call of CancelPairingWithSKI. +func (mr *MockConnectionsHubMockRecorder) CancelPairingWithSKI(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CancelPairingWithSKI", reflect.TypeOf((*MockConnectionsHub)(nil).CancelPairingWithSKI), arg0) +} + +// DisconnectSKI mocks base method. +func (m *MockConnectionsHub) DisconnectSKI(arg0, arg1 string) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "DisconnectSKI", arg0, arg1) +} + +// DisconnectSKI indicates an expected call of DisconnectSKI. +func (mr *MockConnectionsHubMockRecorder) DisconnectSKI(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DisconnectSKI", reflect.TypeOf((*MockConnectionsHub)(nil).DisconnectSKI), arg0, arg1) +} + +// InitiatePairingWithSKI mocks base method. +func (m *MockConnectionsHub) InitiatePairingWithSKI(arg0 string) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "InitiatePairingWithSKI", arg0) +} + +// InitiatePairingWithSKI indicates an expected call of InitiatePairingWithSKI. +func (mr *MockConnectionsHubMockRecorder) InitiatePairingWithSKI(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InitiatePairingWithSKI", reflect.TypeOf((*MockConnectionsHub)(nil).InitiatePairingWithSKI), arg0) +} + +// PairingDetailForSki mocks base method. +func (m *MockConnectionsHub) PairingDetailForSki(arg0 string) *ConnectionStateDetail { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "PairingDetailForSki", arg0) + ret0, _ := ret[0].(*ConnectionStateDetail) + return ret0 +} + +// PairingDetailForSki indicates an expected call of PairingDetailForSki. +func (mr *MockConnectionsHubMockRecorder) PairingDetailForSki(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PairingDetailForSki", reflect.TypeOf((*MockConnectionsHub)(nil).PairingDetailForSki), arg0) +} + +// RegisterRemoteSKI mocks base method. +func (m *MockConnectionsHub) RegisterRemoteSKI(arg0 string, arg1 bool) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RegisterRemoteSKI", arg0, arg1) +} + +// RegisterRemoteSKI indicates an expected call of RegisterRemoteSKI. +func (mr *MockConnectionsHubMockRecorder) RegisterRemoteSKI(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterRemoteSKI", reflect.TypeOf((*MockConnectionsHub)(nil).RegisterRemoteSKI), arg0, arg1) +} + +// ServiceForSKI mocks base method. +func (m *MockConnectionsHub) ServiceForSKI(arg0 string) *ServiceDetails { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ServiceForSKI", arg0) + ret0, _ := ret[0].(*ServiceDetails) + return ret0 +} + +// ServiceForSKI indicates an expected call of ServiceForSKI. +func (mr *MockConnectionsHubMockRecorder) ServiceForSKI(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ServiceForSKI", reflect.TypeOf((*MockConnectionsHub)(nil).ServiceForSKI), arg0) +} + +// Shutdown mocks base method. +func (m *MockConnectionsHub) Shutdown() { + m.ctrl.T.Helper() + m.ctrl.Call(m, "Shutdown") +} + +// Shutdown indicates an expected call of Shutdown. +func (mr *MockConnectionsHubMockRecorder) Shutdown() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Shutdown", reflect.TypeOf((*MockConnectionsHub)(nil).Shutdown)) +} + +// Start mocks base method. +func (m *MockConnectionsHub) Start() { + m.ctrl.T.Helper() + m.ctrl.Call(m, "Start") +} + +// Start indicates an expected call of Start. +func (mr *MockConnectionsHubMockRecorder) Start() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Start", reflect.TypeOf((*MockConnectionsHub)(nil).Start)) +} + +// StartBrowseMdnsSearch mocks base method. +func (m *MockConnectionsHub) StartBrowseMdnsSearch() { + m.ctrl.T.Helper() + m.ctrl.Call(m, "StartBrowseMdnsSearch") +} + +// StartBrowseMdnsSearch indicates an expected call of StartBrowseMdnsSearch. +func (mr *MockConnectionsHubMockRecorder) StartBrowseMdnsSearch() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StartBrowseMdnsSearch", reflect.TypeOf((*MockConnectionsHub)(nil).StartBrowseMdnsSearch)) +} + +// StopBrowseMdnsSearch mocks base method. +func (m *MockConnectionsHub) StopBrowseMdnsSearch() { + m.ctrl.T.Helper() + m.ctrl.Call(m, "StopBrowseMdnsSearch") +} + +// StopBrowseMdnsSearch indicates an expected call of StopBrowseMdnsSearch. +func (mr *MockConnectionsHubMockRecorder) StopBrowseMdnsSearch() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StopBrowseMdnsSearch", reflect.TypeOf((*MockConnectionsHub)(nil).StopBrowseMdnsSearch)) +} diff --git a/service/mock_service_test.go b/service/mock_service_test.go new file mode 100644 index 00000000..9741f384 --- /dev/null +++ b/service/mock_service_test.go @@ -0,0 +1,108 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: github.com/enbility/eebus-go/service (interfaces: EEBUSServiceHandler) + +// Package service is a generated GoMock package. +package service + +import ( + reflect "reflect" + + gomock "github.com/golang/mock/gomock" +) + +// MockEEBUSServiceHandler is a mock of EEBUSServiceHandler interface. +type MockEEBUSServiceHandler struct { + ctrl *gomock.Controller + recorder *MockEEBUSServiceHandlerMockRecorder +} + +// MockEEBUSServiceHandlerMockRecorder is the mock recorder for MockEEBUSServiceHandler. +type MockEEBUSServiceHandlerMockRecorder struct { + mock *MockEEBUSServiceHandler +} + +// NewMockEEBUSServiceHandler creates a new mock instance. +func NewMockEEBUSServiceHandler(ctrl *gomock.Controller) *MockEEBUSServiceHandler { + mock := &MockEEBUSServiceHandler{ctrl: ctrl} + mock.recorder = &MockEEBUSServiceHandlerMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockEEBUSServiceHandler) EXPECT() *MockEEBUSServiceHandlerMockRecorder { + return m.recorder +} + +// AllowWaitingForTrust mocks base method. +func (m *MockEEBUSServiceHandler) AllowWaitingForTrust(arg0 string) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "AllowWaitingForTrust", arg0) + ret0, _ := ret[0].(bool) + return ret0 +} + +// AllowWaitingForTrust indicates an expected call of AllowWaitingForTrust. +func (mr *MockEEBUSServiceHandlerMockRecorder) AllowWaitingForTrust(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AllowWaitingForTrust", reflect.TypeOf((*MockEEBUSServiceHandler)(nil).AllowWaitingForTrust), arg0) +} + +// RemoteSKIConnected mocks base method. +func (m *MockEEBUSServiceHandler) RemoteSKIConnected(arg0 *EEBUSService, arg1 string) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RemoteSKIConnected", arg0, arg1) +} + +// RemoteSKIConnected indicates an expected call of RemoteSKIConnected. +func (mr *MockEEBUSServiceHandlerMockRecorder) RemoteSKIConnected(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoteSKIConnected", reflect.TypeOf((*MockEEBUSServiceHandler)(nil).RemoteSKIConnected), arg0, arg1) +} + +// RemoteSKIDisconnected mocks base method. +func (m *MockEEBUSServiceHandler) RemoteSKIDisconnected(arg0 *EEBUSService, arg1 string) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RemoteSKIDisconnected", arg0, arg1) +} + +// RemoteSKIDisconnected indicates an expected call of RemoteSKIDisconnected. +func (mr *MockEEBUSServiceHandlerMockRecorder) RemoteSKIDisconnected(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoteSKIDisconnected", reflect.TypeOf((*MockEEBUSServiceHandler)(nil).RemoteSKIDisconnected), arg0, arg1) +} + +// ServicePairingDetailUpdate mocks base method. +func (m *MockEEBUSServiceHandler) ServicePairingDetailUpdate(arg0 string, arg1 *ConnectionStateDetail) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "ServicePairingDetailUpdate", arg0, arg1) +} + +// ServicePairingDetailUpdate indicates an expected call of ServicePairingDetailUpdate. +func (mr *MockEEBUSServiceHandlerMockRecorder) ServicePairingDetailUpdate(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ServicePairingDetailUpdate", reflect.TypeOf((*MockEEBUSServiceHandler)(nil).ServicePairingDetailUpdate), arg0, arg1) +} + +// ServiceShipIDUpdate mocks base method. +func (m *MockEEBUSServiceHandler) ServiceShipIDUpdate(arg0, arg1 string) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "ServiceShipIDUpdate", arg0, arg1) +} + +// ServiceShipIDUpdate indicates an expected call of ServiceShipIDUpdate. +func (mr *MockEEBUSServiceHandlerMockRecorder) ServiceShipIDUpdate(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ServiceShipIDUpdate", reflect.TypeOf((*MockEEBUSServiceHandler)(nil).ServiceShipIDUpdate), arg0, arg1) +} + +// VisibleRemoteServicesUpdated mocks base method. +func (m *MockEEBUSServiceHandler) VisibleRemoteServicesUpdated(arg0 *EEBUSService, arg1 []RemoteService) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "VisibleRemoteServicesUpdated", arg0, arg1) +} + +// VisibleRemoteServicesUpdated indicates an expected call of VisibleRemoteServicesUpdated. +func (mr *MockEEBUSServiceHandlerMockRecorder) VisibleRemoteServicesUpdated(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "VisibleRemoteServicesUpdated", reflect.TypeOf((*MockEEBUSServiceHandler)(nil).VisibleRemoteServicesUpdated), arg0, arg1) +} diff --git a/service/service.go b/service/service.go index 15ea9359..299872c4 100644 --- a/service/service.go +++ b/service/service.go @@ -2,6 +2,7 @@ package service import ( "crypto/x509" + "errors" "fmt" "sync" @@ -19,6 +20,8 @@ type RemoteService struct { Model string `json:"model"` } +//go:generate mockgen -destination=mock_service_test.go -package=service github.com/enbility/eebus-go/service EEBUSServiceHandler + // interface for receiving data for specific events type EEBUSServiceHandler interface { // report all currently visible EEBUS services @@ -53,7 +56,7 @@ type EEBUSService struct { LocalService *ServiceDetails // Connection Registrations - connectionsHub *connectionsHub + connectionsHub ConnectionsHub // The SPINE specific device definition spineLocalDevice *spine.DeviceLocalImpl @@ -113,16 +116,16 @@ func (s *EEBUSService) ServicePairingDetailUpdate(ski string, detail *Connection s.serviceHandler.ServicePairingDetailUpdate(ski, detail) } -// Get the current pairing details for a given SKI -func (s *EEBUSService) PairingDetailForSki(ski string) *ConnectionStateDetail { - return s.connectionsHub.PairingDetailForSki(ski) -} - // return if the user is still able to trust the connection func (s *EEBUSService) AllowWaitingForTrust(ski string) bool { return s.serviceHandler.AllowWaitingForTrust(ski) } +// Get the current pairing details for a given SKI +func (s *EEBUSService) PairingDetailForSki(ski string) *ConnectionStateDetail { + return s.connectionsHub.PairingDetailForSki(ski) +} + // Starts browsing for any EEBUS mDNS entry func (s *EEBUSService) StartBrowseMdnsEntries() { s.connectionsHub.StartBrowseMdnsSearch() @@ -150,6 +153,10 @@ func (s *EEBUSService) Setup() error { sd := s.Configuration + if len(sd.certificate.Certificate) == 0 { + return errors.New("missing certificate") + } + leaf, err := x509.ParseCertificate(sd.certificate.Certificate[0]) if err != nil { return err @@ -220,14 +227,14 @@ func (s *EEBUSService) Setup() error { // Starts the service func (s *EEBUSService) Start() { s.startOnce.Do(func() { - s.connectionsHub.start() + s.connectionsHub.Start() }) } // Shutdown all services and stop the server. func (s *EEBUSService) Shutdown() { // Shut down all running connections - s.connectionsHub.shutdown() + s.connectionsHub.Shutdown() } func (s *EEBUSService) LocalDevice() *spine.DeviceLocalImpl { @@ -236,7 +243,7 @@ func (s *EEBUSService) LocalDevice() *spine.DeviceLocalImpl { // Returns the Service detail of a given remote SKI func (s *EEBUSService) RemoteServiceForSKI(ski string) *ServiceDetails { - return s.connectionsHub.serviceForSKI(ski) + return s.connectionsHub.ServiceForSKI(ski) } // Sets the SKI as being paired or not diff --git a/service/service_test.go b/service/service_test.go new file mode 100644 index 00000000..26de9761 --- /dev/null +++ b/service/service_test.go @@ -0,0 +1,147 @@ +package service + +import ( + "crypto/tls" + "testing" + "time" + + "github.com/enbility/eebus-go/logging" + "github.com/enbility/eebus-go/logging/mocks" + "github.com/enbility/eebus-go/spine/model" + gomock "github.com/golang/mock/gomock" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/suite" +) + +func TestServiceSuite(t *testing.T) { + suite.Run(t, new(ServiceSuite)) +} + +type ServiceSuite struct { + suite.Suite + + config *Configuration + + sut *EEBUSService + + serviceHandler *MockEEBUSServiceHandler + conHub *MockConnectionsHub + logging *mocks.Logging +} + +func (s *ServiceSuite) SetupSuite() {} +func (s *ServiceSuite) TearDownTest() {} + +func (s *ServiceSuite) BeforeTest(suiteName, testName string) { + ctrl := gomock.NewController(s.T()) + + s.serviceHandler = NewMockEEBUSServiceHandler(ctrl) + + s.conHub = NewMockConnectionsHub(ctrl) + + s.logging = mocks.NewLogging(s.T()) + s.logging.On("Info", mock.Anything, mock.Anything).Maybe() + + certificate := tls.Certificate{} + s.config, _ = NewConfiguration( + "vendor", "brand", "model", "serial", model.DeviceTypeTypeEnergyManagementSystem, + []model.EntityTypeType{model.EntityTypeTypeCEM}, 4729, certificate, 230.0, time.Second*4) + + s.sut = NewEEBUSService(s.config, s.serviceHandler) +} + +func (s *ServiceSuite) Test_EEBUSHandler() { + testSki := "test" + + entry := &MdnsEntry{ + Ski: testSki, + } + + entries := []*MdnsEntry{entry} + s.serviceHandler.EXPECT().VisibleRemoteServicesUpdated(gomock.Any(), gomock.Any()) + s.sut.VisibleMDNSRecordsUpdated(entries) + + s.serviceHandler.EXPECT().RemoteSKIConnected(gomock.Any(), gomock.Any()) + s.sut.RemoteSKIConnected(testSki) + + s.serviceHandler.EXPECT().RemoteSKIDisconnected(gomock.Any(), gomock.Any()) + s.sut.RemoteSKIDisconnected(testSki) + + s.serviceHandler.EXPECT().ServiceShipIDUpdate(gomock.Any(), gomock.Any()) + s.sut.ServiceShipIDUpdate(testSki, "shipid") + + s.serviceHandler.EXPECT().ServicePairingDetailUpdate(gomock.Any(), gomock.Any()) + detail := &ConnectionStateDetail{} + s.sut.ServicePairingDetailUpdate(testSki, detail) + + s.serviceHandler.EXPECT().AllowWaitingForTrust(gomock.Any()).Return(true) + result := s.sut.AllowWaitingForTrust(testSki) + assert.Equal(s.T(), true, result) + +} + +func (s *ServiceSuite) Test_ConnectionsHub() { + testSki := "test" + + s.sut.connectionsHub = s.conHub + + s.conHub.EXPECT().PairingDetailForSki(gomock.Any()) + s.sut.PairingDetailForSki(testSki) + + s.conHub.EXPECT().StartBrowseMdnsSearch() + s.sut.StartBrowseMdnsEntries() + + s.conHub.EXPECT().StopBrowseMdnsSearch() + s.sut.StopBrowseMdnsEntries() + + s.conHub.EXPECT().ServiceForSKI(gomock.Any()) + details := s.sut.RemoteServiceForSKI(testSki) + assert.Nil(s.T(), details) + + s.conHub.EXPECT().RegisterRemoteSKI(gomock.Any(), gomock.Any()) + s.sut.RegisterRemoteSKI(testSki, true) + + s.conHub.EXPECT().InitiatePairingWithSKI(gomock.Any()) + s.sut.InitiatePairingWithSKI(testSki) + + s.conHub.EXPECT().CancelPairingWithSKI(gomock.Any()) + s.sut.CancelPairingWithSKI(testSki) + + s.conHub.EXPECT().DisconnectSKI(gomock.Any(), gomock.Any()) + s.sut.DisconnectSKI(testSki, "reason") +} + +func (s *ServiceSuite) Test_SetLogging() { + s.sut.SetLogging(nil) + assert.Equal(s.T(), &logging.NoLogging{}, logging.Log) + + s.sut.SetLogging(s.logging) + assert.Equal(s.T(), s.logging, logging.Log) + + s.sut.SetLogging(nil) +} + +func (s *ServiceSuite) Test_Setup() { + + err := s.sut.Setup() + assert.NotNil(s.T(), err) + + s.config.certificate, err = CreateCertificate("unit", "org", "de", "cn") + assert.Nil(s.T(), err) + + err = s.sut.Setup() + assert.Nil(s.T(), err) + + s.sut.connectionsHub = s.conHub + s.conHub.EXPECT().Start() + s.sut.Start() + + time.Sleep(time.Millisecond * 200) + + s.conHub.EXPECT().Shutdown() + s.sut.Shutdown() + + device := s.sut.LocalDevice() + assert.NotNil(s.T(), device) +}