PKGBUILD/pkg/repository/repository_test.go

542 lines
16 KiB
Go

package repository_test
import (
"bytes"
"context"
"encoding/json"
"fmt"
"math/rand"
"net/url"
"os"
"path/filepath"
"testing"
"time"
"git.cryptic.systems/volker.raschek/dockerutils"
"git.cryptic.systems/volker.raschek/flucky/pkg/repository"
"git.cryptic.systems/volker.raschek/flucky/pkg/types"
"git.cryptic.systems/volker.raschek/go-logger"
uuid "github.com/satori/go.uuid"
"github.com/stretchr/testify/require"
_ "github.com/golang-migrate/migrate/v4/database/postgres"
_ "github.com/golang-migrate/migrate/v4/database/sqlite3"
_ "github.com/lib/pq"
_ "github.com/mattn/go-sqlite3"
)
func TestPostgresBackend(t *testing.T) {
require := require.New(t)
dockerClient, err := dockerutils.New()
require.NoError(err)
rand.Seed(time.Now().Unix())
postgresDBPasswort := "postgres"
postgresContainerID, err := dockerClient.NewBuilder("postgres:13-alpine").
AddEnv("PGTZ", "Europe/Berlin").
AddEnv("POSTGRES_PASSWORD", postgresDBPasswort).
AddEnv("TZ", "Europe/Berlin").
Mount("/etc/localtime", "/etc/localtime").
Pull().
Start(context.Background())
cleanup := func() {
dockerClient.ContainerRemoveByIDs(context.Background(), postgresContainerID)
}
t.Cleanup(cleanup)
require.NoError(err)
time.Sleep(time.Second * 10)
// inspect container to get his container ip
cjson, err := dockerClient.ContainerInspect(context.Background(), postgresContainerID)
require.NoError(err)
// postgres://[user]:[password]@[host]:[port]/[path]?[query]
dsnURL, err := url.Parse(fmt.Sprintf("postgres://postgres:%v@%v:5432?sslmode=disable", postgresDBPasswort, cjson.NetworkSettings.IPAddress))
require.NoError(err)
repo, err := repository.New(dsnURL, logger.NewLogger(logger.LogLevelDebug))
require.NoError(err)
testBackend(t, repo)
}
func TestSQLiteBackend(t *testing.T) {
require := require.New(t)
workspace := filepath.Join(os.TempDir(), uuid.NewV4().String())
err := os.MkdirAll(workspace, 0755)
require.NoError(err)
t.Cleanup(func() { os.RemoveAll(workspace) })
dsnURL, err := url.Parse(fmt.Sprintf("sqlite3://%v/test.db", workspace))
require.NoError(err)
repo, err := repository.New(dsnURL, logger.NewLogger(logger.LogLevelDebug))
require.NoError(err)
testBackend(t, repo)
}
func testBackend(t *testing.T, repo repository.Repository) {
ctx := context.Background()
require := require.New(t)
location := uuid.NewV4().String()
expectedDevices := []*types.Device{
{
ID: "39b8f150-8abf-4539-9f16-7f68cedb1649",
Name: "62e3978f-2198-4aa9-9d6f-cdc91a468b00",
Location: &location,
CreationDate: *timeNow(require),
},
{
ID: "ec0be3ab-d26d-4f9b-a96e-23ae5c577f8f",
Name: "f2b245eb-b15f-40e1-9212-9a645907b710",
Location: &location,
CreationDate: *timeNow(require),
},
}
// Test: AddDevice
err := repo.AddDevices(ctx, expectedDevices...)
require.NoError(err)
// Test: GetDevices
devices, err := repo.GetDevices(ctx)
require.NoError(err)
require.Len(devices, len(expectedDevices))
require.JSONEq(jsonEncoder(expectedDevices), jsonEncoder(devices))
// Test: GetDeviceByID
device, err := repo.GetDeviceByID(ctx, expectedDevices[0].ID)
require.NoError(err)
require.JSONEq(jsonEncoder(expectedDevices[0]), jsonEncoder(device))
// Test: GetDeviceByName
device, err = repo.GetDeviceByName(ctx, expectedDevices[0].Name)
require.NoError(err)
require.JSONEq(jsonEncoder(expectedDevices[0]), jsonEncoder(device))
// Test: RemoveDevicesByIDs
err = repo.RemoveDevicesByIDs(ctx, expectedDevices[0].ID)
require.NoError(err)
devices, err = repo.GetDevices(ctx)
require.NoError(err)
require.Len(devices, 1)
device, err = repo.GetDeviceByID(ctx, expectedDevices[0].ID)
require.NoError(err)
require.Nil(device)
// Test: RemoveDevicesByNames
err = repo.RemoveDevicesByNames(ctx, expectedDevices[0].Name)
require.NoError(err)
devices, err = repo.GetDevices(ctx)
require.NoError(err)
require.Len(devices, 1)
device, err = repo.GetDeviceByID(ctx, expectedDevices[0].ID)
require.NoError(err)
require.Nil(device)
err = repo.AddDevices(ctx, expectedDevices[0])
require.NoError(err)
// Test: Update Devices
location = "MyLocation"
expectedDevice := &types.Device{
ID: "ec0be3ab-d26d-4f9b-a96e-23ae5c577f8f",
Name: "Hello World",
Location: &location,
CreationDate: *timeNow(require),
}
err = repo.UpdateDevices(ctx, expectedDevice)
require.NoError(err)
device, err = repo.GetDeviceByID(ctx, expectedDevice.ID)
require.NoError(err)
require.NotEmpty(device)
require.Equal(expectedDevice.ID, device.ID)
require.Equal(expectedDevice.Name, device.Name)
require.Equal(expectedDevice.Location, device.Location)
// Test: AddOrUpdateDevices
location = "MySweetLocation"
expectedDevice = &types.Device{
ID: "9d8c59a5-7927-4a7c-ad48-dbf5405ffd68",
Name: "MySweetDevice",
Location: &location,
CreationDate: *timeNow(require),
}
err = repo.AddOrUpdateDevices(ctx, expectedDevice)
require.NoError(err)
// time.Sleep(time.Minute * 10)
device, err = repo.GetDeviceByID(ctx, expectedDevice.ID)
require.NoError(err)
require.NotEmpty(device)
require.Equal(expectedDevice.ID, device.ID)
require.Equal(expectedDevice.Name, device.Name)
require.Equal(expectedDevice.Location, device.Location)
location = "MyUglyLocation"
expectedDevice = &types.Device{
ID: "9d8c59a5-7927-4a7c-ad48-dbf5405ffd68",
Name: "MyUglyDevice",
Location: &location,
CreationDate: *timeNow(require),
}
err = repo.AddOrUpdateDevices(ctx, expectedDevice)
require.NoError(err)
device, err = repo.GetDeviceByID(ctx, expectedDevice.ID)
require.NoError(err)
require.NotEmpty(device)
require.Equal(expectedDevice.ID, device.ID)
require.Equal(expectedDevice.Name, device.Name)
require.Equal(expectedDevice.Location, device.Location)
var (
wireID = "50473fdc-f6ef-4227-b3c4-484d8e9c1323"
i2cBus = 1
i2cAddress uint8 = 76
expectedSensors = []*types.Sensor{
{
ID: "0f8b88b0-c20d-42b2-ab51-b09ca99c0752",
Name: "01fbdbe9-cebf-42ed-8065-bf4882ccf76b",
Location: "6d5b5450-1f87-47cb-b185-f64c35fae3c1",
GPIONumber: "GPIO14",
Model: "DHT11",
Enabled: true,
TickDuration: "1m",
DeviceID: "ec0be3ab-d26d-4f9b-a96e-23ae5c577f8f",
CreationDate: *timeNow(require),
},
{
ID: "80b1c4bd-abec-4ff0-afb4-bd70aeed0c83",
Name: "544365ee-ece9-44ea-911d-5d920a68d4ba",
Location: "7ae2d05e-9e6b-4d2d-b26a-cb4acca83778",
WireID: &wireID,
Model: "DS18B20",
Enabled: true,
TickDuration: "5m",
DeviceID: "ec0be3ab-d26d-4f9b-a96e-23ae5c577f8f",
CreationDate: *timeNow(require),
},
{
ID: "8c74397f-8e60-4c9d-960d-3197747cef9a",
Name: "4b808675-de02-4866-893d-1c77f23b9304",
Location: "8a085c0f-dd3c-447f-8c4e-c4c1d869c7b6",
I2CBus: &i2cBus,
I2CAddress: &i2cAddress,
Model: "BME280",
Enabled: false,
TickDuration: "10m",
DeviceID: "39b8f150-8abf-4539-9f16-7f68cedb1649",
CreationDate: *timeNow(require),
},
}
)
// Test: AddSensors
err = repo.AddSensors(ctx, expectedSensors...)
require.NoError(err)
// Test: GetSensors
sensors, err := repo.GetSensors(ctx)
require.NoError(err)
require.Len(sensors, len(expectedSensors))
// Test: GetSensorsByNames
sensors, err = repo.GetSensorsByNames(ctx, "01fbdbe9-cebf-42ed-8065-bf4882ccf76b")
require.NoError(err)
require.Len(sensors, 1)
require.JSONEq(jsonEncoder(expectedSensors[0]), jsonEncoder(sensors[0]))
// Test: GetSensorsByModels
sensors, err = repo.GetSensorsByModels(ctx, "BME280")
require.NoError(err)
require.Len(sensors, 1)
require.JSONEq(jsonEncoder(expectedSensors[2]), jsonEncoder(sensors[0]))
sensors, err = repo.GetSensorsByModels(ctx, "DS18B20")
require.NoError(err)
require.Len(sensors, 1)
require.JSONEq(jsonEncoder(expectedSensors[1]), jsonEncoder(sensors[0]))
sensors, err = repo.GetSensorsByModels(ctx, "DHT11")
require.NoError(err)
require.Len(sensors, 1)
require.JSONEq(jsonEncoder(expectedSensors[0]), jsonEncoder(sensors[0]))
sensors, err = repo.GetSensorsByModels(ctx, "DHT11", "DS18B20")
require.NoError(err)
require.Len(sensors, 2)
require.JSONEq(jsonEncoder(expectedSensors[0:2]), jsonEncoder(sensors[0:2]))
// Test: GetSensorByID
sensor, err := repo.GetSensorByID(ctx, expectedSensors[0].ID)
require.NoError(err)
require.JSONEq(jsonEncoder(expectedSensors[0]), jsonEncoder(sensor))
// Test: GetSensorsByDeviceID
sensors, err = repo.GetSensorsByDeviceIDs(ctx, "ec0be3ab-d26d-4f9b-a96e-23ae5c577f8f")
require.NoError(err)
require.Len(sensors, 2)
require.JSONEq(jsonEncoder(expectedSensors[0:2]), jsonEncoder(sensors))
// Test: RemoveSensorsByIDs
err = repo.RemoveSensorsByIDs(ctx, expectedSensors[0].ID)
require.NoError(err)
sensors, err = repo.GetSensors(ctx)
require.NoError(err)
require.Len(sensors, 2)
sensors, err = repo.GetSensorsByDeviceIDs(ctx, "ec0be3ab-d26d-4f9b-a96e-23ae5c577f8f")
require.NoError(err)
require.Len(sensors, 1)
sensor, err = repo.GetSensorByID(ctx, expectedSensors[0].ID)
require.NoError(err)
require.Nil(sensor)
// Test: RemoveSensorsByNames
err = repo.RemoveSensorsByNames(ctx, expectedSensors[1].Name)
require.NoError(err)
sensors, err = repo.GetSensors(ctx)
require.NoError(err)
require.Len(sensors, 1)
sensor, err = repo.GetSensorByID(ctx, expectedSensors[1].ID)
require.NoError(err)
require.Nil(sensor)
// Test: UpdateSensors
expectedSensor := &types.Sensor{
ID: "8c74397f-8e60-4c9d-960d-3197747cef9a",
Name: "4b808675-de02-4866-893d-1c77f23b9304",
Location: "Ãœber den Wolken muss die Freiheit wohl grenzenlos sein...",
I2CBus: nil,
I2CAddress: nil,
Model: "SDS011",
Enabled: true,
TickDuration: "6h",
DeviceID: "39b8f150-8abf-4539-9f16-7f68cedb1649",
CreationDate: *timeNow(require),
}
err = repo.UpdateSensors(ctx, expectedSensor)
require.NoError(err)
sensor, err = repo.GetSensorByID(ctx, expectedSensor.ID)
require.NoError(err)
require.NotNil(sensor)
// require.JSONEq(jsonEncoder(expectedSensor), jsonEncoder(sensor))
// Test: AddOrUpdateSensors
expectedSensor = &types.Sensor{
ID: "9bba0e0a-e996-4242-966f-db21bab6752f",
Name: "b4ac3d0f-cef6-4e93-bd7b-e821ae5ab593",
Location: "HelloWorld",
I2CBus: nil,
I2CAddress: nil,
Model: "SDS011",
Enabled: true,
TickDuration: "6h",
DeviceID: "39b8f150-8abf-4539-9f16-7f68cedb1649",
CreationDate: *timeNow(require),
}
err = repo.AddOrUpdateSensors(ctx, expectedSensor)
require.NoError(err)
sensor, err = repo.GetSensorByID(ctx, expectedSensor.ID)
require.NoError(err)
require.NotEmpty(sensor)
require.Equal(expectedSensor.ID, sensor.ID)
require.Equal(expectedSensor.Name, sensor.Name)
require.Equal(expectedSensor.Location, sensor.Location)
require.Equal(expectedSensor.I2CBus, sensor.I2CBus)
require.Equal(expectedSensor.I2CAddress, sensor.I2CAddress)
require.Equal(expectedSensor.Model, sensor.Model)
require.Equal(expectedSensor.Enabled, sensor.Enabled)
require.Equal(expectedSensor.TickDuration, sensor.TickDuration)
require.Equal(expectedSensor.DeviceID, sensor.DeviceID)
expectedSensor = &types.Sensor{
ID: "9bba0e0a-e996-4242-966f-db21bab6752f",
Name: "MySweetSensor",
Location: "MySweetLocation",
I2CBus: nil,
I2CAddress: nil,
Model: "Jap",
Enabled: false,
TickDuration: "8h",
DeviceID: "39b8f150-8abf-4539-9f16-7f68cedb1649",
CreationDate: *timeNow(require),
}
err = repo.AddOrUpdateSensors(ctx, expectedSensor)
require.NoError(err)
sensor, err = repo.GetSensorByID(ctx, expectedSensor.ID)
require.NoError(err)
require.NotEmpty(sensor)
require.Equal(expectedSensor.ID, sensor.ID)
require.Equal(expectedSensor.Name, sensor.Name)
require.Equal(expectedSensor.Location, sensor.Location)
require.Equal(expectedSensor.I2CBus, sensor.I2CBus)
require.Equal(expectedSensor.I2CAddress, sensor.I2CAddress)
require.Equal(expectedSensor.Model, sensor.Model)
require.Equal(expectedSensor.Enabled, sensor.Enabled)
require.Equal(expectedSensor.TickDuration, sensor.TickDuration)
require.Equal(expectedSensor.DeviceID, sensor.DeviceID)
var (
expectedMeasuredValues = []*types.MeasuredValue{
{
ID: "2e5a297a-3da0-46ae-89d2-0fcab0f1d5f7",
Value: 32,
ValueType: types.Humidity,
Date: *timeNow(require),
SensorID: "8c74397f-8e60-4c9d-960d-3197747cef9a",
CreationDate: *timeNow(require),
UpdateDate: nil,
},
{
ID: "d69f1b62-0c6c-4058-b42c-4a2821bd220c",
Value: 38,
ValueType: types.Pressure,
Date: *timeNow(require),
SensorID: "8c74397f-8e60-4c9d-960d-3197747cef9a",
CreationDate: *timeNow(require),
UpdateDate: nil,
},
{
ID: "ea945ae0-412b-4561-a191-1f8f1f909fa4",
Value: 35.4,
ValueType: types.Temperature,
Date: *timeNow(require),
SensorID: "8c74397f-8e60-4c9d-960d-3197747cef9a",
CreationDate: *timeNow(require),
UpdateDate: nil,
},
}
)
// Test: AddMeasuredValues
err = repo.AddMeasuredValues(ctx, expectedMeasuredValues...)
require.NoError(err)
for i := range expectedMeasuredValues {
var (
err error
measuredValue *types.MeasuredValue
)
switch expectedMeasuredValues[i].ValueType {
case types.Humidity:
measuredValue, err = repo.GetHumidityByID(ctx, expectedMeasuredValues[i].ID)
require.NoError(err)
require.NotNil(measuredValue)
case types.Pressure:
measuredValue, err = repo.GetPressureByID(ctx, expectedMeasuredValues[i].ID)
require.NoError(err)
require.NotNil(measuredValue)
case types.Temperature:
measuredValue, err = repo.GetTemperatureByID(ctx, expectedMeasuredValues[i].ID)
require.NoError(err)
require.NotNil(measuredValue)
}
require.Equal(expectedMeasuredValues[i].ID, measuredValue.ID)
require.Equal(expectedMeasuredValues[i].Value, measuredValue.Value)
require.Equal(expectedMeasuredValues[i].ValueType, measuredValue.ValueType)
require.Equal(expectedMeasuredValues[i].SensorID, measuredValue.SensorID)
}
// Test: AddOrUpdateMeasuredValues
expectedMeasuredValues = []*types.MeasuredValue{
{
ID: "2e5a297a-3da0-46ae-89d2-0fcab0f1d5f7",
Value: 35,
ValueType: types.Humidity,
Date: *timeNow(require),
SensorID: "8c74397f-8e60-4c9d-960d-3197747cef9a",
CreationDate: *timeNow(require),
UpdateDate: timeNow(require),
},
{
ID: "d69f1b62-0c6c-4058-b42c-4a2821bd220c",
Value: 37,
ValueType: types.Pressure,
Date: *timeNow(require),
SensorID: "8c74397f-8e60-4c9d-960d-3197747cef9a",
CreationDate: *timeNow(require),
UpdateDate: timeNow(require),
},
{
ID: "ea945ae0-412b-4561-a191-1f8f1f909fa4",
Value: 35.4,
ValueType: types.Temperature,
Date: *timeNow(require),
SensorID: "8c74397f-8e60-4c9d-960d-3197747cef9a",
CreationDate: *timeNow(require),
UpdateDate: timeNow(require),
},
}
err = repo.AddOrUpdateMeasuredValues(ctx, expectedMeasuredValues...)
require.NoError(err)
for i := range expectedMeasuredValues {
var (
err error
measuredValue *types.MeasuredValue
)
switch expectedMeasuredValues[i].ValueType {
case types.Humidity:
measuredValue, err = repo.GetHumidityByID(ctx, expectedMeasuredValues[i].ID)
require.NoError(err)
require.NotNil(measuredValue)
case types.Pressure:
measuredValue, err = repo.GetPressureByID(ctx, expectedMeasuredValues[i].ID)
require.NoError(err)
require.NotNil(measuredValue)
case types.Temperature:
measuredValue, err = repo.GetTemperatureByID(ctx, expectedMeasuredValues[i].ID)
require.NoError(err)
require.NotNil(measuredValue)
}
require.Equal(expectedMeasuredValues[i].ID, measuredValue.ID)
require.Equal(expectedMeasuredValues[i].Value, measuredValue.Value)
require.Equal(expectedMeasuredValues[i].ValueType, measuredValue.ValueType)
require.Equal(expectedMeasuredValues[i].SensorID, measuredValue.SensorID)
}
}
func jsonEncoder(v interface{}) string {
body := make([]byte, 0)
buffer := bytes.NewBuffer(body)
jsonEncoder := json.NewEncoder(buffer)
jsonEncoder.SetIndent("", " ")
jsonEncoder.Encode(v)
return buffer.String()
}
func timeNow(require *require.Assertions) *time.Time {
now, err := time.Parse("2006-01-02 15:04:05.999999-07", time.Now().Format("2006-01-02 15:04:05.999999-07"))
require.NoError(err)
return &now
}