Skip to content
This repository was archived by the owner on Mar 27, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Build
name: build

on: [push, pull_request]

Expand Down
9 changes: 3 additions & 6 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,8 @@ jobs:
- name: check out code
uses: actions/checkout@v2

- name: download mod
run: go mod download

- name: run functional tests
run: ./scripts/functional-tests.sh
- name: run mqtt tests
run: ./scripts/mqtt-tests.sh

- name: run auth tests
run: go test -v ./auth
run: go test -v ./auth
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,10 @@ See [API](./API.md)

## Functional tests

This type of tests are executed all locally and you need to configure a dedicated docker container:
- `docker pull guerra1994/go-mqtt-docker-env`
- follow the steps [here](https://hub.docker.com/r/guerra1994/go-mqtt-docker-env) to run it
- run mosquitto broker in background mode using `mosquitto > /dev/null 2>&1 &`
These tests can be executed locally. To do that, you need to configure a dedicated docker container:
- get the image `docker pull guerra1994/go-docker-mqtt-ubuntu-env`
- enter the container `docker run -it -v $(pwd):/home --privileged --name gmd guerra1994/go-docker-mqtt-ubuntu-env`
- run the mosquitto MQTT broker in background mode `mosquitto > /dev/null 2>&1 &`
- then run your test, for example `go test -v --tags=functional --run="TestDockerPsApi"`


Expand Down
16 changes: 5 additions & 11 deletions handlers_apt_repositories.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//
// This file is part of arduino-connector
//
// Copyright (C) 2017-2018 Arduino AG (http://www.arduino.cc/)
// Copyright (C) 2017-2020 Arduino AG (http://www.arduino.cc/)
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -28,25 +28,19 @@ import (

// AptRepositoryListEvent sends a list of available repositories
func (s *Status) AptRepositoryListEvent(client mqtt.Client, msg mqtt.Message) {
// Get packages from system
all, err := apt.ParseAPTConfigFolder("/etc/apt")
if err != nil {
s.Error("/apt/repos/list", fmt.Errorf("Retrieving repositories: %s", err))
return
}

// Send result
data, err := json.Marshal(all)
if err != nil {
s.Error("/apt/repos/list", fmt.Errorf("Json marshal result: %s", err))
return
}

//var out bytes.Buffer
//json.Indent(&out, data, "", " ")
//fmt.Println(string(out.Bytes()))

s.Info("/apt/repos/list", string(data))
s.SendInfo(s.topicPertinence+"/apt/repos/list", string(data))
}

// AptRepositoryAddEvent adds a repository to the apt configuration
Expand All @@ -66,7 +60,7 @@ func (s *Status) AptRepositoryAddEvent(client mqtt.Client, msg mqtt.Message) {
return
}

s.Info("/apt/repos/add", "OK")
s.SendInfo(s.topicPertinence+"/apt/repos/add", "OK")
}

// AptRepositoryRemoveEvent removes a repository from the apt configuration
Expand All @@ -86,7 +80,7 @@ func (s *Status) AptRepositoryRemoveEvent(client mqtt.Client, msg mqtt.Message)
return
}

s.Info("/apt/repos/remove", "OK")
s.SendInfo(s.topicPertinence+"/apt/repos/remove", "OK")
}

// AptRepositoryEditEvent modifies a repository definition in the apt configuration
Expand All @@ -107,5 +101,5 @@ func (s *Status) AptRepositoryEditEvent(client mqtt.Client, msg mqtt.Message) {
return
}

s.Info("/apt/repos/edit", "OK")
s.SendInfo(s.topicPertinence+"/apt/repos/edit", "OK")
}
253 changes: 253 additions & 0 deletions handlers_apt_repositories_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,253 @@
package main

import (
"encoding/json"
"fmt"
"log"
"strings"
"testing"
"time"

apt "github.com/arduino/go-apt-client"
mqtt "github.com/eclipse/paho.mqtt.golang"
"github.com/stretchr/testify/assert"
)

func TestAptList(t *testing.T) {
ui := NewMqttTestClientLocal()
defer ui.Close()

s := NewStatus(program{}.Config, nil, nil, "")
s.mqttClient = mqtt.NewClient(mqtt.NewClientOptions().AddBroker("tcp://localhost:1883").SetClientID("arduino-connector"))
if token := s.mqttClient.Connect(); token.Wait() && token.Error() != nil {
log.Fatal(token.Error())
}
defer s.mqttClient.Disconnect(100)

subscribeTopic(s.mqttClient, "0", "/apt/repos/list/post", s, s.AptRepositoryListEvent, false)

resp := ui.MqttSendAndReceiveTimeout(t, "/apt/repos/list", "{}", 1*time.Second)

assert.NotEmpty(t, resp)
}

func TestAptAddError(t *testing.T) {
ui := NewMqttTestClientLocal()
defer ui.Close()

s := NewStatus(program{}.Config, nil, nil, "")
s.mqttClient = mqtt.NewClient(mqtt.NewClientOptions().AddBroker("tcp://localhost:1883").SetClientID("arduino-connector"))
if token := s.mqttClient.Connect(); token.Wait() && token.Error() != nil {
log.Fatal(token.Error())
}
defer s.mqttClient.Disconnect(100)

subscribeTopic(s.mqttClient, "0", "/apt/repos/add/post", s, s.AptRepositoryAddEvent, true)

resp := ui.MqttSendAndReceiveTimeout(t, "/apt/repos/add", "{test}", 1*time.Second)

assert.True(t, strings.HasPrefix(resp, "ERROR"))
assert.True(t, strings.Contains(resp, "Unmarshal"))
}

func TestAptAdd(t *testing.T) {
ui := NewMqttTestClientLocal()
defer ui.Close()

s := NewStatus(program{}.Config, nil, nil, "")
s.mqttClient = mqtt.NewClient(mqtt.NewClientOptions().AddBroker("tcp://localhost:1883").SetClientID("arduino-connector"))
if token := s.mqttClient.Connect(); token.Wait() && token.Error() != nil {
log.Fatal(token.Error())
}
defer s.mqttClient.Disconnect(100)

subscribeTopic(s.mqttClient, "0", "/apt/repos/add/post", s, s.AptRepositoryAddEvent, true)

var params struct {
Repository *apt.Repository `json:"repository"`
}

params.Repository = &apt.Repository{
Enabled: false,
SourceRepo: true,
URI: "http://ppa.launchpad.net/test/ubuntu",
Distribution: "zesty",
Components: "main",
Comment: "",
}

data, err := json.Marshal(params)
if err != nil {
t.Error(err)
}

resp := ui.MqttSendAndReceiveTimeout(t, "/apt/repos/add", string(data), 1*time.Second)
assert.Equal(t, "INFO: OK\n", resp)

defer func() {
err = apt.RemoveRepository(params.Repository, "/etc/apt")
if err != nil {
t.Error(err)
}
}()

all, err := apt.ParseAPTConfigFolder("/etc/apt")
if err != nil {
s.Error("/apt/repos/list", fmt.Errorf("Retrieving repositories: %s", err))
return
}

assert.True(t, all.Contains(params.Repository))
}

func TestAptRemoveError(t *testing.T) {
ui := NewMqttTestClientLocal()
defer ui.Close()

s := NewStatus(program{}.Config, nil, nil, "")
s.mqttClient = mqtt.NewClient(mqtt.NewClientOptions().AddBroker("tcp://localhost:1883").SetClientID("arduino-connector"))
if token := s.mqttClient.Connect(); token.Wait() && token.Error() != nil {
log.Fatal(token.Error())
}
defer s.mqttClient.Disconnect(100)

subscribeTopic(s.mqttClient, "0", "/apt/repos/remove/post", s, s.AptRepositoryRemoveEvent, true)

resp := ui.MqttSendAndReceiveTimeout(t, "/apt/repos/remove", "{test}", 1*time.Second)

assert.True(t, strings.HasPrefix(resp, "ERROR"))
assert.True(t, strings.Contains(resp, "Unmarshal"))
}

func TestAptRemove(t *testing.T) {
ui := NewMqttTestClientLocal()
defer ui.Close()

s := NewStatus(program{}.Config, nil, nil, "")
s.mqttClient = mqtt.NewClient(mqtt.NewClientOptions().AddBroker("tcp://localhost:1883").SetClientID("arduino-connector"))
if token := s.mqttClient.Connect(); token.Wait() && token.Error() != nil {
log.Fatal(token.Error())
}
defer s.mqttClient.Disconnect(100)

subscribeTopic(s.mqttClient, "0", "/apt/repos/remove/post", s, s.AptRepositoryRemoveEvent, true)

var params struct {
Repository *apt.Repository `json:"repository"`
}

params.Repository = &apt.Repository{
Enabled: false,
SourceRepo: true,
URI: "http://ppa.launchpad.net/test/ubuntu",
Distribution: "zesty",
Components: "main",
Comment: "",
}

errAdd := apt.AddRepository(params.Repository, "/etc/apt")
if errAdd != nil {
t.Error(errAdd)
}

data, err := json.Marshal(params)
if err != nil {
t.Error(err)
}

resp := ui.MqttSendAndReceiveTimeout(t, "/apt/repos/remove", string(data), 1*time.Second)
assert.Equal(t, "INFO: OK\n", resp)

all, err := apt.ParseAPTConfigFolder("/etc/apt")
if err != nil {
s.Error("/apt/repos/list", fmt.Errorf("Retrieving repositories: %s", err))
return
}

assert.False(t, all.Contains(params.Repository))
}

func TestAptEditError(t *testing.T) {
ui := NewMqttTestClientLocal()
defer ui.Close()

s := NewStatus(program{}.Config, nil, nil, "")
s.mqttClient = mqtt.NewClient(mqtt.NewClientOptions().AddBroker("tcp://localhost:1883").SetClientID("arduino-connector"))
if token := s.mqttClient.Connect(); token.Wait() && token.Error() != nil {
log.Fatal(token.Error())
}
defer s.mqttClient.Disconnect(100)

subscribeTopic(s.mqttClient, "0", "/apt/repos/edit/post", s, s.AptRepositoryEditEvent, true)

resp := ui.MqttSendAndReceiveTimeout(t, "/apt/repos/edit", "{test}", 1*time.Second)

assert.True(t, strings.HasPrefix(resp, "ERROR"))
assert.True(t, strings.Contains(resp, "Unmarshal"))
}

func TestAptEdit(t *testing.T) {
ui := NewMqttTestClientLocal()
defer ui.Close()

s := NewStatus(program{}.Config, nil, nil, "")
s.mqttClient = mqtt.NewClient(mqtt.NewClientOptions().AddBroker("tcp://localhost:1883").SetClientID("arduino-connector"))
if token := s.mqttClient.Connect(); token.Wait() && token.Error() != nil {
log.Fatal(token.Error())
}
defer s.mqttClient.Disconnect(100)

subscribeTopic(s.mqttClient, "0", "/apt/repos/edit/post", s, s.AptRepositoryEditEvent, true)

var params struct {
OldRepository *apt.Repository `json:"old_repository"`
NewRepository *apt.Repository `json:"new_repository"`
}

params.OldRepository = &apt.Repository{
Enabled: false,
SourceRepo: true,
URI: "http://ppa.launchpad.net/OldTest/ubuntu",
Distribution: "zesty",
Components: "main",
Comment: "old",
}

params.NewRepository = &apt.Repository{
Enabled: false,
SourceRepo: true,
URI: "http://ppa.launchpad.net/NewTest/ubuntu",
Distribution: "zesty",
Components: "main",
Comment: "new",
}

errAdd := apt.AddRepository(params.OldRepository, "/etc/apt")
if errAdd != nil {
t.Error(errAdd)
}

defer func() {
err := apt.RemoveRepository(params.NewRepository, "/etc/apt")
if err != nil {
t.Error(err)
}
}()

data, err := json.Marshal(params)
if err != nil {
t.Error(err)
}

resp := ui.MqttSendAndReceiveTimeout(t, "/apt/repos/edit", string(data), 1*time.Second)
assert.Equal(t, "INFO: OK\n", resp)

all, err := apt.ParseAPTConfigFolder("/etc/apt")
if err != nil {
s.Error("/apt/repos/list", fmt.Errorf("Retrieving repositories: %s", err))
return
}

assert.True(t, all.Contains(params.NewRepository))
assert.False(t, all.Contains(params.OldRepository))
}
14 changes: 0 additions & 14 deletions handlers_containers_functional_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,6 @@ import (
"golang.org/x/net/context"
)

// NewMqttTestClientLocal creates mqtt client in localhost:1883
func NewMqttTestClientLocal() *MqttTestClient {
uiOptions := mqtt.NewClientOptions().AddBroker("tcp://localhost:1883").SetClientID("UI")
ui := mqtt.NewClient(uiOptions)
if token := ui.Connect(); token.Wait() && token.Error() != nil {
panic(token.Error())
}

return &MqttTestClient{
ui,
"",
}
}

type testStatus struct {
appStatus *Status
ui *MqttTestClient
Expand Down
3 changes: 2 additions & 1 deletion scripts/functional-tests.sh → scripts/mqtt-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ set -euo pipefail
trap 'kill "$(pidof mosquitto)"' EXIT

mosquitto > /dev/null &
go test -v --tags=functional --run="TestDocker"
go test -v --tags=functional --run=TestDocker
go test -v --run=TestApt
16 changes: 16 additions & 0 deletions test/go-mosquitto-ubuntu-env
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
FROM ubuntu
LABEL maintainer="guerinoni.federico@gmail.com"

RUN apt-get update
RUN apt-get -y install \
curl \
gcc \
mosquitto

RUN curl -O https://dl.google.com/go/go1.15.linux-amd64.tar.gz
RUN tar xvf go1.15.linux-amd64.tar.gz
RUN mv go /usr/local

ENV PATH=$PATH:/usr/local/go/bin

WORKDIR /home
Loading