From e61aafeb15d8556967a6f035c7be017c676746a9 Mon Sep 17 00:00:00 2001 From: Maarten de Kruijf Date: Tue, 12 Mar 2024 20:26:50 +0100 Subject: [PATCH 01/12] Updated fin protocol with name field --- docs/content/en/docs/soarca-extentions/fin-protocol.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/docs/content/en/docs/soarca-extentions/fin-protocol.md b/docs/content/en/docs/soarca-extentions/fin-protocol.md index fd74fc51..4e2f73d5 100644 --- a/docs/content/en/docs/soarca-extentions/fin-protocol.md +++ b/docs/content/en/docs/soarca-extentions/fin-protocol.md @@ -14,7 +14,9 @@ The goal of the protocol is to provide a simple and robust way to communicate be ## MQTT To allow for dynamic communication MQTT is used to provide the backbone for the fin communication. SOARCA can be configured using the environment to use MQTT or just run stand alone. -The Fin will use the protocol to register itself to SOARCA via the register message. Once register it will communicate over the channel new channel designated by the capability UUID. +The Fin will use the protocol to register itself to SOARCA via the register message. Once register it will communicate over the channel new channel designated by the fin UUID. + +Commands to a specific capability will be communicated of the capability UUID channel. ## Messages Messages defined in the protocol @@ -84,7 +86,8 @@ The message is used to register a fin to SOARCA. It has the following payload. | ----------------- | --------------------- | ----------------- | ----------- | |type |register |string |The register message type |message_id |UUID |string |Message UUID -|fin_id |UUID |string |Fin uuid of the separate form the capability +|fin_id |UUID |string |Fin uuid separate form the capability id +|Name |Name |string |Fin name |protocol_version |version |string |Version information of the protocol in [semantic version](https://semver.org) schema e.g. 1.2.4-beta |security |security information |[Security](#security) |Security information for protocol see security structure |capabilities |list of capability structure |list of [capability structure](#capability-structure) |Capability structure information for protocol see security structure @@ -129,6 +132,7 @@ The message is used to register a fin to SOARCA. It has the following payload. "type": "register", "message_id": "uuid", "fin_id" : "uuid", + "name": "Fin name", "protocol_version": "", "security": { "version": "0.0.0", @@ -153,7 +157,7 @@ The message is used to register a fin to SOARCA. It has the following payload. "agent" : { "soarca-fin--": { "type": "soarca-fin", - "name": "soarca-fin---" + "name": "soarca-fin---" } } From 9db05eb4b85b8c136a5767aa4fb0793b4e8c1c4b Mon Sep 17 00:00:00 2001 From: Maarten de Kruijf Date: Tue, 12 Mar 2024 20:27:15 +0100 Subject: [PATCH 02/12] Updated fin struct with name field and id --- models/fin/fin.go | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/models/fin/fin.go b/models/fin/fin.go index ddf722df..e36f6eed 100644 --- a/models/fin/fin.go +++ b/models/fin/fin.go @@ -36,19 +36,20 @@ type Register struct { Type string `json:"type"` MessageId string `json:"message_id"` FinID string `json:"fin_id"` + Name string `json:"fin_name"` ProtocolVersion string `json:"protocol_version"` Security Security `json:"security"` Capabilities []Capability `json:"capabilities"` - Meta Meta `json:"meta"` + Meta Meta `json:"meta, omitempty"` } // Capability register message substructure type Capability struct { - CapabilityId string `json:"capability_id"` - Name string `json:"name"` - Version string `json:"version"` - Step map[string]Step `json:"step"` - Agent map[string]cacao.AgentTarget `json:"agent"` + Id string `json:"capability_id"` + Name string `json:"name"` + Version string `json:"version"` + Step map[string]Step `json:"step, omitempty"` + Agent map[string]cacao.AgentTarget `json:"agent, omitempty"` } // Step structure as example to the executor @@ -63,11 +64,11 @@ type Step struct { // Unregister command structure type Unregister struct { - Type string `json:"type"` - MessageId string `json:"message_id"` - CapabilityId string `json:"capability_id"` - FinID string `json:"fin_id"` - All string `json:"all"` + Type string `json:"type"` + MessageId string `json:"message_id"` + Id string `json:"capability_id"` + FinID string `json:"fin_id"` + All string `json:"all"` } // Command @@ -140,7 +141,8 @@ type Meta struct { } type Message struct { - Type string `json:"type"` + Type string `json:"type"` + MessageId string `json:"message_id"` } func NewCommand() Command { From a058ab86e2beaced96a934ea7d971dff589b92a4 Mon Sep 17 00:00:00 2001 From: Maarten de Kruijf Date: Tue, 12 Mar 2024 20:27:34 +0100 Subject: [PATCH 03/12] Added Ack and Nack construction functions --- models/fin/fin.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/models/fin/fin.go b/models/fin/fin.go index e36f6eed..776aec69 100644 --- a/models/fin/fin.go +++ b/models/fin/fin.go @@ -154,6 +154,16 @@ func NewCommand() Command { return instance } +func NewAck(messageId string) Ack { + ack := Ack{Type: MessageTypeAck, MessageId: messageId} + return ack +} + +func NewNack(messageId string) Nack { + nack := Nack{Type: MessageTypeNack, MessageId: messageId} + return nack +} + func Decode(data []byte, object any) error { return json.Unmarshal(data, object) } From f46bcfd62ebb165d3528e55c76ef011df94126bb Mon Sep 17 00:00:00 2001 From: Maarten de Kruijf Date: Tue, 12 Mar 2024 20:28:00 +0100 Subject: [PATCH 04/12] Added fin controller --- internal/capability/controller/controller.go | 175 ++++++++++++++++++ .../capability/controller/controller_test.go | 66 +++++++ 2 files changed, 241 insertions(+) create mode 100644 internal/capability/controller/controller.go create mode 100644 test/unittest/capability/controller/controller_test.go diff --git a/internal/capability/controller/controller.go b/internal/capability/controller/controller.go new file mode 100644 index 00000000..d83efdbe --- /dev/null +++ b/internal/capability/controller/controller.go @@ -0,0 +1,175 @@ +package controller + +import ( + "errors" + "fmt" + "reflect" + "soarca/internal/fin/protocol" + "soarca/logger" + "soarca/models/fin" + + mqtt "github.com/eclipse/paho.mqtt.golang" +) + +type Empty struct{} + +var component = reflect.TypeOf(Empty{}).PkgPath() +var log *logger.Log + +func init() { + log = logger.Logger(component, logger.Info, "", logger.Json) +} + +type CapabilityDetails struct { + Name string + Id string + FinId string +} + +const clientId = "soarca" + +type IFinController interface { + GetRegisteredCapabilities() map[string]CapabilityDetails +} + +type FinController struct { + registeredCapabilities map[string]CapabilityDetails + mqttClient mqtt.Client + channel chan []byte +} + +func (finController *FinController) GetRegisteredCapabilities() map[string]CapabilityDetails { + return finController.registeredCapabilities +} + +func New(client mqtt.Client) *FinController { + controllerQueue := make(chan []byte, 10) + return &FinController{registeredCapabilities: make(map[string]CapabilityDetails), mqttClient: client, channel: controllerQueue} +} + +func NewClient(url protocol.Broker, port int) *mqtt.Client { + options := mqtt.NewClientOptions() + options.AddBroker(fmt.Sprintf("mqtt://%s:%d", url, port)) + options.SetClientID(clientId) + options.SetUsername("soarca") + options.SetPassword("password") + client := mqtt.NewClient(options) + return &client +} + +// This function will only return on a fatal error +func (finController *FinController) Start(broker string, port int) error { + if finController.mqttClient == nil { + return errors.New("fincontroller mqtt cilent is nil") + } + + if token := finController.mqttClient.Connect(); token.Wait() && token.Error() != nil { + err := token.Error() + log.Error(err) + return err + } + + token := finController.mqttClient.Subscribe(string("soarca"), 1, finController.Handler) + token.Wait() + + for { + select { + case result := <-finController.channel: + finController.Handle(result) + } + + } + + return nil +} + +// Handle goroutine call from mqtt stack +func (finController *FinController) Handler(client mqtt.Client, msg mqtt.Message) { + if msg.Topic() != string("soarca") { + log.Trace("message was receive in wrong topic: " + msg.Topic()) + } + payload := msg.Payload() + log.Trace(string(payload)) + finController.channel <- payload + +} + +func (finController *FinController) SendAck(topic string, messageId string) error { + json, _ := fin.Encode(fin.NewAck(messageId)) + log.Trace("Sending ack for message id: ", messageId) + token := finController.mqttClient.Publish(topic, 1, false, json) + token.Wait() + if err := token.Error(); err != nil { + log.Error(err) + return err + } + return nil +} + +func (finController *FinController) Handle(payload []byte) { + message := fin.Message{} + fin.Decode(payload, &message) + switch message.Type { + case fin.MessageTypeAck: + finController.HandleAck(payload) + case fin.MessageTypeRegister: + finController.HandleRegister(payload) + case fin.MessageTypeNack: + finController.HandleNack(payload) + } +} + +func (finController *FinController) SendNack(topic string, messageId string) error { + json, _ := fin.Encode(fin.NewNack(messageId)) + log.Trace("Sending nack for message id: ", messageId) + token := finController.mqttClient.Publish(topic, 1, false, json) + token.Wait() + if err := token.Error(); err != nil { + log.Error(err) + return err + } + return nil +} + +func (finController *FinController) HandleAck(payload []byte) { + ack := fin.Ack{} + fin.Decode(payload, ack) + + // ignore for now + +} + +func (finController *FinController) HandleNack(payload []byte) { + ack := fin.Ack{} + fin.Decode(payload, ack) + + // ignore for now + +} + +func (finController *FinController) HandleRegister(payload []byte) { + register := fin.Register{} + err := fin.Decode(payload, ®ister) + if err != nil { + log.Error("Message", err) + finController.SendNack("soarca", register.MessageId) + return + } + + for _, capability := range register.Capabilities { + if _, ok := finController.registeredCapabilities[capability.Id]; ok { + finController.SendNack(register.FinID, register.MessageId) + log.Error("this capability UUID is already registered") + return + } + token := finController.mqttClient.Subscribe(capability.Id, 1, finController.Handler) + token.Wait() + + detail := CapabilityDetails{Name: capability.Name, Id: capability.Id, FinId: register.FinID} + finController.registeredCapabilities[capability.Id] = detail + + } + + finController.SendAck(register.FinID, register.MessageId) + +} diff --git a/test/unittest/capability/controller/controller_test.go b/test/unittest/capability/controller/controller_test.go new file mode 100644 index 00000000..b8dfb304 --- /dev/null +++ b/test/unittest/capability/controller/controller_test.go @@ -0,0 +1,66 @@ +package controller_test + +import ( + "encoding/json" + "soarca/internal/capability/controller" + "soarca/models/fin" + "soarca/test/unittest/mocks/mock_mqtt" + "testing" + + "github.com/go-playground/assert/v2" + "github.com/google/uuid" + "github.com/stretchr/testify/mock" +) + +func TestGetRegisteredc(t *testing.T) { + mqtt := new(mock_mqtt.Mock_MqttClient) + token := mock_mqtt.Mock_MqttToken{} + token2 := mock_mqtt.Mock_MqttToken{} + capabiltyController := controller.New(mqtt) + fins := capabiltyController.GetRegisteredCapabilities() + + assert.Equal(t, len(fins), 0) + + messageId := uuid.New() + + capability := fin.Capability{Name: "cap1", Id: "id1", Version: "1.0.0"} + capabilities := make([]fin.Capability, 0) + capabilities = append(capabilities, capability) + + meta := fin.Meta{} + + incommingRegisterMessage := fin.Register{Type: fin.MessageTypeRegister, + MessageId: messageId.String(), + FinID: "Fin", + ProtocolVersion: "1.0.0", + Security: fin.Security{Version: "0.0.0", ChannelSecurity: ""}, + Capabilities: capabilities, + Meta: meta, + } + + object, err := json.Marshal(incommingRegisterMessage) + if err != nil { + t.Fail() + } + + token.On("Wait").Return(true) + mqtt.On("Subscribe", "id1", uint8(1), mock.Anything).Return(&token) + + expectedAck := fin.NewAck(messageId.String()) + json, _ := fin.Encode(expectedAck) + token2.On("Wait").Return(true) + mqtt.On("Publish", "Fin", uint8(1), false, json).Return(&token2) + token2.On("Error").Return(nil) + + capabiltyController.Handle(object) + + newFins := capabiltyController.GetRegisteredCapabilities() + + assert.Equal(t, len(newFins), 1) + assert.Equal(t, newFins["id1"].Id, "id1") + assert.Equal(t, newFins["id1"].Name, "cap1") + mqtt.AssertExpectations(t) + token.AssertExpectations(t) + token2.AssertExpectations(t) + +} From 76f028d8a4e0fa9a43f04028d09d3e017191fbf1 Mon Sep 17 00:00:00 2001 From: Maarten de Kruijf Date: Tue, 12 Mar 2024 20:28:10 +0100 Subject: [PATCH 05/12] Added manual fin controller test --- .../capability/capability_controller_test.go | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 test/manual/capability/capability_controller_test.go diff --git a/test/manual/capability/capability_controller_test.go b/test/manual/capability/capability_controller_test.go new file mode 100644 index 00000000..bba14988 --- /dev/null +++ b/test/manual/capability/capability_controller_test.go @@ -0,0 +1,32 @@ +package capability_controller_test + +import ( + "fmt" + "soarca/internal/capability/controller" + "testing" + + mqtt "github.com/eclipse/paho.mqtt.golang" +) + +func TestConnect(t *testing.T) { + // used for manual testing + + // var executionId, _ = uuid.Parse("6ba7b810-9dad-11d1-80b4-00c04fd430c8") + // var playbookId = "playbook--d09351a2-a075-40c8-8054-0b7c423db83f" + // var stepId = "step--81eff59f-d084-4324-9e0a-59e353dbd28f" + // guid := new(guid.Guid) + // prot := protocol.FinProtocol{Guid: guid, Topic: protocol.Topic("testing"), Broker: "localhost", Port: 1883} + + options := mqtt.NewClientOptions() + options.AddBroker(fmt.Sprintf("mqtt://localhost:1883")) + options.SetClientID("soarca") + options.SetUsername("public") + options.SetPassword("password") + + client := mqtt.NewClient(options) + + finController := controller.New(client) + err := finController.Start("localhost", 1883) + fmt.Print(err) + +} From 70b4411d70776548ca30de5e7aa657c3d11a034c Mon Sep 17 00:00:00 2001 From: Maarten de Kruijf Date: Wed, 13 Mar 2024 10:17:04 +0100 Subject: [PATCH 06/12] Removed space in json validation syntax --- models/fin/fin.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/models/fin/fin.go b/models/fin/fin.go index 776aec69..38178465 100644 --- a/models/fin/fin.go +++ b/models/fin/fin.go @@ -40,7 +40,7 @@ type Register struct { ProtocolVersion string `json:"protocol_version"` Security Security `json:"security"` Capabilities []Capability `json:"capabilities"` - Meta Meta `json:"meta, omitempty"` + Meta Meta `json:"meta,omitempty"` } // Capability register message substructure @@ -48,8 +48,8 @@ type Capability struct { Id string `json:"capability_id"` Name string `json:"name"` Version string `json:"version"` - Step map[string]Step `json:"step, omitempty"` - Agent map[string]cacao.AgentTarget `json:"agent, omitempty"` + Step map[string]Step `json:"step,omitempty"` + Agent map[string]cacao.AgentTarget `json:"agent,omitempty"` } // Step structure as example to the executor From 37ffa1ac3b92aa10e0160e8b6023faa1897eadcf Mon Sep 17 00:00:00 2001 From: Maarten de Kruijf Date: Wed, 13 Mar 2024 10:47:16 +0100 Subject: [PATCH 07/12] Fixt lint issue --- test/manual/capability/capability_controller_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/manual/capability/capability_controller_test.go b/test/manual/capability/capability_controller_test.go index bba14988..1ed2e555 100644 --- a/test/manual/capability/capability_controller_test.go +++ b/test/manual/capability/capability_controller_test.go @@ -18,7 +18,7 @@ func TestConnect(t *testing.T) { // prot := protocol.FinProtocol{Guid: guid, Topic: protocol.Topic("testing"), Broker: "localhost", Port: 1883} options := mqtt.NewClientOptions() - options.AddBroker(fmt.Sprintf("mqtt://localhost:1883")) + options.AddBroker("mqtt://localhost:1883") options.SetClientID("soarca") options.SetUsername("public") options.SetPassword("password") From a3658396c84184059b2332735871f394de496e10 Mon Sep 17 00:00:00 2001 From: Maarten de Kruijf Date: Wed, 13 Mar 2024 10:59:27 +0100 Subject: [PATCH 08/12] Fixed linting issues --- internal/capability/controller/controller.go | 33 +++++++++++++------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/internal/capability/controller/controller.go b/internal/capability/controller/controller.go index d83efdbe..32a18569 100644 --- a/internal/capability/controller/controller.go +++ b/internal/capability/controller/controller.go @@ -73,14 +73,10 @@ func (finController *FinController) Start(broker string, port int) error { token.Wait() for { - select { - case result := <-finController.channel: - finController.Handle(result) - } + result := <-finController.channel + finController.Handle(result) } - - return nil } // Handle goroutine call from mqtt stack @@ -108,7 +104,10 @@ func (finController *FinController) SendAck(topic string, messageId string) erro func (finController *FinController) Handle(payload []byte) { message := fin.Message{} - fin.Decode(payload, &message) + if err := fin.Decode(payload, &message); err != nil { + log.Error(err) + return + } switch message.Type { case fin.MessageTypeAck: finController.HandleAck(payload) @@ -133,7 +132,9 @@ func (finController *FinController) SendNack(topic string, messageId string) err func (finController *FinController) HandleAck(payload []byte) { ack := fin.Ack{} - fin.Decode(payload, ack) + if err := fin.Decode(payload, ack); err != nil { + log.Error(err) + } // ignore for now @@ -141,7 +142,9 @@ func (finController *FinController) HandleAck(payload []byte) { func (finController *FinController) HandleNack(payload []byte) { ack := fin.Ack{} - fin.Decode(payload, ack) + if err := fin.Decode(payload, ack); err != nil { + log.Error(err) + } // ignore for now @@ -152,13 +155,17 @@ func (finController *FinController) HandleRegister(payload []byte) { err := fin.Decode(payload, ®ister) if err != nil { log.Error("Message", err) - finController.SendNack("soarca", register.MessageId) + if err := finController.SendNack("soarca", register.MessageId); err != nil { + log.Error(err) + } return } for _, capability := range register.Capabilities { if _, ok := finController.registeredCapabilities[capability.Id]; ok { - finController.SendNack(register.FinID, register.MessageId) + if err := finController.SendNack(register.FinID, register.MessageId); err != nil { + log.Error(err) + } log.Error("this capability UUID is already registered") return } @@ -170,6 +177,8 @@ func (finController *FinController) HandleRegister(payload []byte) { } - finController.SendAck(register.FinID, register.MessageId) + if err := finController.SendAck(register.FinID, register.MessageId); err != nil { + log.Error(err) + } } From 34f889731983dd0446e5d5bb2ee7786d50bcfb1d Mon Sep 17 00:00:00 2001 From: Maarten de Kruijf Date: Wed, 13 Mar 2024 10:59:48 +0100 Subject: [PATCH 09/12] Added sample docker compose config moquitto --- docker/mqtt/config/mosquitto.conf | 9 +++++++ docker/mqtt/data/.gitkeep | 0 docker/mqtt/docker-compose.yml | 44 +++++++++++++++++++++++++++++++ docker/mqtt/log/.gitkeep | 0 4 files changed, 53 insertions(+) create mode 100644 docker/mqtt/config/mosquitto.conf create mode 100644 docker/mqtt/data/.gitkeep create mode 100644 docker/mqtt/docker-compose.yml create mode 100644 docker/mqtt/log/.gitkeep diff --git a/docker/mqtt/config/mosquitto.conf b/docker/mqtt/config/mosquitto.conf new file mode 100644 index 00000000..024452f6 --- /dev/null +++ b/docker/mqtt/config/mosquitto.conf @@ -0,0 +1,9 @@ +listener 1883 +persistence true +persistence_location /mosquitto/data/ +log_dest file /mosquitto/log/mosquitto.log + +## Authentication ## +# By default, Mosquitto >=2.0 allows only authenticated connections. Change to true to enable anonymous connections. +allow_anonymous true +# password_file /mosquitto/config/password.txt \ No newline at end of file diff --git a/docker/mqtt/data/.gitkeep b/docker/mqtt/data/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/docker/mqtt/docker-compose.yml b/docker/mqtt/docker-compose.yml new file mode 100644 index 00000000..ee67139a --- /dev/null +++ b/docker/mqtt/docker-compose.yml @@ -0,0 +1,44 @@ +version: '3.7' +services: + mosquitto: + image: eclipse-mosquitto + container_name: mosquitto + volumes: + - type: volume + source: mosquitto_config + target: /mosquitto/config + - type: volume + source: mosquitto_data + target: /mosquitto/data + - type: volume + source: mosquitto_log + target: /mosquitto/log + ports: + - target: 1883 + published: 1883 + protocol: tcp + mode: host + - target: 9001 + published: 9001 + protocol: tcp + mode: host + +volumes: + mosquitto_config: + driver: local # Define the driver and options under the volume name + driver_opts: + type: none + device: ./config + o: bind + mosquitto_data: + driver: local # Define the driver and options under the volume name + driver_opts: + type: none + device: ./data + o: bind + mosquitto_log: + driver: local # Define the driver and options under the volume name + driver_opts: + type: none + device: ./log + o: bind diff --git a/docker/mqtt/log/.gitkeep b/docker/mqtt/log/.gitkeep new file mode 100644 index 00000000..e69de29b From 41fafa5fb9723aa842ceb609f937bb17f307f59c Mon Sep 17 00:00:00 2001 From: Maarten de Kruijf Date: Thu, 14 Mar 2024 09:33:58 +0100 Subject: [PATCH 10/12] Moved go routine into the class and removed unused arguments --- internal/capability/controller/controller.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/internal/capability/controller/controller.go b/internal/capability/controller/controller.go index 32a18569..ba980f5f 100644 --- a/internal/capability/controller/controller.go +++ b/internal/capability/controller/controller.go @@ -58,7 +58,7 @@ func NewClient(url protocol.Broker, port int) *mqtt.Client { } // This function will only return on a fatal error -func (finController *FinController) Start(broker string, port int) error { +func (finController *FinController) Start() error { if finController.mqttClient == nil { return errors.New("fincontroller mqtt cilent is nil") } @@ -71,7 +71,14 @@ func (finController *FinController) Start(broker string, port int) error { token := finController.mqttClient.Subscribe(string("soarca"), 1, finController.Handler) token.Wait() + if err := token.Error(); err != nil { + return err + } + go finController.loop() + return nil +} +func (finController *FinController) loop() { for { result := <-finController.channel finController.Handle(result) From 1cde4bda1f809f429d6450a4f47cdaabeaf456ea Mon Sep 17 00:00:00 2001 From: Maarten de Kruijf Date: Thu, 14 Mar 2024 10:02:07 +0100 Subject: [PATCH 11/12] Moved Connect and Subscribe to new function and added test --- internal/capability/controller/controller.go | 8 +++----- .../capability/capability_controller_test.go | 8 ++++++-- .../capability/controller/controller_test.go | 16 ++++++++++++++++ 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/internal/capability/controller/controller.go b/internal/capability/controller/controller.go index ba980f5f..99396e10 100644 --- a/internal/capability/controller/controller.go +++ b/internal/capability/controller/controller.go @@ -57,8 +57,7 @@ func NewClient(url protocol.Broker, port int) *mqtt.Client { return &client } -// This function will only return on a fatal error -func (finController *FinController) Start() error { +func (finController *FinController) ConnectAndSubscribe() error { if finController.mqttClient == nil { return errors.New("fincontroller mqtt cilent is nil") } @@ -74,15 +73,14 @@ func (finController *FinController) Start() error { if err := token.Error(); err != nil { return err } - go finController.loop() return nil } -func (finController *FinController) loop() { +// This function will only return on a fatal error +func (finController *FinController) Run() { for { result := <-finController.channel finController.Handle(result) - } } diff --git a/test/manual/capability/capability_controller_test.go b/test/manual/capability/capability_controller_test.go index 1ed2e555..f5e27fd5 100644 --- a/test/manual/capability/capability_controller_test.go +++ b/test/manual/capability/capability_controller_test.go @@ -26,7 +26,11 @@ func TestConnect(t *testing.T) { client := mqtt.NewClient(options) finController := controller.New(client) - err := finController.Start("localhost", 1883) - fmt.Print(err) + + if err := finController.ConnectAndSubscribe(); err != nil { + fmt.Print(err) + t.Fail() + } + finController.Run() } diff --git a/test/unittest/capability/controller/controller_test.go b/test/unittest/capability/controller/controller_test.go index b8dfb304..4d673f96 100644 --- a/test/unittest/capability/controller/controller_test.go +++ b/test/unittest/capability/controller/controller_test.go @@ -64,3 +64,19 @@ func TestGetRegisteredc(t *testing.T) { token2.AssertExpectations(t) } + +func TestConnectAndSubsribe(t *testing.T) { + mqtt := new(mock_mqtt.Mock_MqttClient) + token := mock_mqtt.Mock_MqttToken{} + capabiltyController := controller.New(mqtt) + + token.On("Wait").Return(true) + token.On("Error").Return(nil) + mqtt.On("Connect").Return(&token) + token.On("Wait").Return(true) + token.On("Error").Return(nil) + mqtt.On("Subscribe", "soarca", uint8(1), mock.Anything).Return(&token) + capabiltyController.ConnectAndSubscribe() + mqtt.AssertExpectations(t) + token.AssertExpectations(t) +} From bcd3292974a4253f4070ca8fecbe906a6c356f9d Mon Sep 17 00:00:00 2001 From: Maarten de Kruijf Date: Thu, 14 Mar 2024 10:05:38 +0100 Subject: [PATCH 12/12] Assert return is nil --- test/unittest/capability/controller/controller_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/unittest/capability/controller/controller_test.go b/test/unittest/capability/controller/controller_test.go index 4d673f96..823df29e 100644 --- a/test/unittest/capability/controller/controller_test.go +++ b/test/unittest/capability/controller/controller_test.go @@ -76,7 +76,8 @@ func TestConnectAndSubsribe(t *testing.T) { token.On("Wait").Return(true) token.On("Error").Return(nil) mqtt.On("Subscribe", "soarca", uint8(1), mock.Anything).Return(&token) - capabiltyController.ConnectAndSubscribe() + err := capabiltyController.ConnectAndSubscribe() + assert.Equal(t, err, nil) mqtt.AssertExpectations(t) token.AssertExpectations(t) }