fix: implement repository test

changes:
- Implement repository test for the sqlite backend
- Add testutils package to start container images
- Remove deprecated till_date in measured values
- Renamed columns of the table humidities, pressures and temperatures
This commit is contained in:
2020-06-01 00:52:54 +02:00
parent 11717679bc
commit 43e9d00dcb
37 changed files with 1073 additions and 267 deletions

View File

@ -146,7 +146,7 @@ func (postgres *Postgres) InsertMeasuredValues(ctx context.Context, measuredValu
defer stmt.Close()
for _, measuredValue := range measuredValues {
_, err := stmt.Exec(&measuredValue.ID, &measuredValue.Value, &measuredValue.FromDate, &measuredValue.TillDate, &measuredValue.SensorID, &measuredValue.CreationDate, &measuredValue.UpdateDate)
_, err := stmt.Exec(&measuredValue.ID, &measuredValue.Value, &measuredValue.SensorID, &measuredValue.CreationDate)
if err != nil {
return fmt.Errorf("Failed to execute statement: %v", err)
}

View File

@ -144,9 +144,8 @@ func (sqlite *SQLite) InsertMeasuredValues(ctx context.Context, measuredValues .
_, err := stmt.Exec(
&measuredValue.ID,
&measuredValue.Value,
&measuredValue.FromDate,
&measuredValue.TillDate,
&measuredValue.SensorID,
&measuredValue.Date,
&measuredValue.CreationDate,
&measuredValue.UpdateDate,
)
@ -214,6 +213,7 @@ func (sqlite *SQLite) InsertSensors(ctx context.Context, sensors ...*types.Senso
&sensor.GPIONumber,
&sensor.Model,
&sensor.Enabled,
&sensor.TickDuration,
&sensor.DeviceID,
&sensor.CreationDate,
)
@ -266,6 +266,10 @@ func (sqlite *SQLite) SelectDevice(ctx context.Context, id string) (*types.Devic
return nil, err
}
if len(devices) == 0 {
return nil, nil
}
return devices[0], nil
}
@ -282,7 +286,7 @@ func (sqlite *SQLite) SelectDevices(ctx context.Context) ([]*types.Device, error
return nil, fmt.Errorf("Failed to begin new transaction: %v", err)
}
devices, err := sqlite.selectDevices(tx, query, nil)
devices, err := sqlite.selectDevices(tx, query)
if err != nil {
return nil, err
}
@ -302,7 +306,7 @@ func (sqlite *SQLite) selectDevices(tx *sql.Tx, query string, args ...interface{
}
defer stmt.Close()
rows, err := stmt.Query()
rows, err := stmt.Query(args...)
if err != nil {
return nil, fmt.Errorf("Failed to query statement: %v", err)
}
@ -405,21 +409,22 @@ func (sqlite *SQLite) selectMeasuredValue(tx *sql.Tx, query string, args ...inte
measuredValues := make([]*types.MeasuredValue, 0)
for rows.Next() {
measuredValues := new(types.MeasuredValue)
measuredValue := new(types.MeasuredValue)
err := rows.Scan(
&measuredValues.ID,
&measuredValues.Value,
&measuredValues.FromDate,
&measuredValues.TillDate,
&measuredValues.SensorID,
&measuredValues.CreationDate,
&measuredValues.UpdateDate,
&measuredValue.ID,
&measuredValue.Value,
&measuredValue.SensorID,
&measuredValue.Date,
&measuredValue.CreationDate,
&measuredValue.UpdateDate,
)
if err != nil {
tx.Rollback()
return nil, err
}
measuredValues = append(measuredValues, measuredValue)
}
return measuredValues, nil
@ -502,7 +507,7 @@ func (sqlite *SQLite) SelectSensor(ctx context.Context, id string) (*types.Senso
return nil, fmt.Errorf("Failed to begin new transaction: %v", err)
}
sensors, err := sqlite.selectSensors(tx, query, nil)
sensors, err := sqlite.selectSensors(tx, query, id)
if err != nil {
return nil, err
}
@ -512,6 +517,10 @@ func (sqlite *SQLite) SelectSensor(ctx context.Context, id string) (*types.Senso
return nil, fmt.Errorf("Failed to commit transaction: %v", err)
}
if len(sensors) == 0 {
return nil, nil
}
return sensors[0], nil
}
@ -528,7 +537,7 @@ func (sqlite *SQLite) SelectSensors(ctx context.Context) ([]*types.Sensor, error
return nil, fmt.Errorf("Failed to begin new transaction: %v", err)
}
sensors, err := sqlite.selectSensors(tx, query, nil)
sensors, err := sqlite.selectSensors(tx, query)
if err != nil {
return nil, err
}
@ -548,7 +557,7 @@ func (sqlite *SQLite) selectSensors(tx *sql.Tx, query string, args ...interface{
}
defer stmt.Close()
rows, err := stmt.Query()
rows, err := stmt.Query(args...)
if err != nil {
return nil, fmt.Errorf("Failed to query statement: %v", err)
}
@ -566,6 +575,7 @@ func (sqlite *SQLite) selectSensors(tx *sql.Tx, query string, args ...interface{
&sensor.GPIONumber,
&sensor.Model,
&sensor.Enabled,
&sensor.TickDuration,
&sensor.DeviceID,
&sensor.CreationDate,
)
@ -709,6 +719,7 @@ func (sqlite *SQLite) UpdateSensors(ctx context.Context, sensors ...*types.Senso
&sensor.GPIONumber,
&sensor.Model,
&sensor.Enabled,
&sensor.TickDuration,
&sensor.DeviceID,
&sensor.CreationDate,
&sensor.ID,

View File

@ -1,8 +1,7 @@
CREATE TABLE IF NOT EXISTS humidities (
humidity_id CHAR(37) PRIMARY KEY,
humidity_value NUMERIC(10,3) NOT NULL,
humidity_from_date TIMESTAMP NOT NULL,
humidity_till_date TIMESTAMP,
id CHAR(37) PRIMARY KEY,
value NUMERIC(10,3) NOT NULL,
date TIMESTAMP NOT NULL,
sensor_id CHAR(37) NOT NULL,
creation_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
update_date TIMESTAMP,

View File

@ -1,8 +1,7 @@
CREATE TABLE IF NOT EXISTS pressures (
pressure_id CHAR(37) PRIMARY KEY,
pressure_value NUMERIC(10,3) NOT NULL,
pressure_from_date TIMESTAMP NOT NULL,
pressure_till_date TIMESTAMP,
id CHAR(37) PRIMARY KEY,
value NUMERIC(10,3) NOT NULL,
date TIMESTAMP NOT NULL,
sensor_id CHAR(37) NOT NULL,
creation_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
update_date TIMESTAMP,

View File

@ -8,6 +8,7 @@ CREATE TABLE IF NOT EXISTS sensors (
gpio_number VARCHAR(6),
sensor_model VARCHAR(16) NOT NULL,
sensor_enabled INTEGER(1) DEFAULT 1 NOT NULL,
tick_duration VARCHAR(6) NOT NULL,
device_id CHAR(37) NOT NULL,
creation_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY(device_id) REFERENCES devices(device_id)

View File

@ -1,10 +1,9 @@
CREATE TABLE IF NOT EXISTS temperatures (
temperature_id CHAR(37) PRIMARY KEY,
temperature_value NUMERIC(10,3) NOT NULL,
temperature_from_date TIMESTAMP NOT NULL,
temperature_till_date TIMESTAMP,
sensor_id CHAR(37) NOT NULL,
creation_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
id CHAR(37) PRIMARY KEY,
value NUMERIC(10,3) NOT NULL,
date TIMESTAMP NOT NULL,
sensor_id CHAR(37) NOT NULL,
creation_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
update_date TIMESTAMP,
FOREIGN KEY(sensor_id) REFERENCES sensors(sensor_id)
);

View File

@ -1,2 +1,2 @@
DELETE FROM sensors
DELETE FROM devices
WHERE device_id = $1;

View File

@ -1,10 +1,9 @@
INSERT INTO humidities (
humidity_id,
humidity_value,
humidity_from_date,
humidity_till_date,
id,
value,
date,
sensor_id,
creation_date,
update_date
)
VALUES ($1, $2, $3, $4, $5, $6, $7);
VALUES ($1, $2, $3, $4, $5, $6);

View File

@ -1,10 +1,9 @@
INSERT INTO pressures (
pressure_id,
pressure_value,
pressure_from_date,
pressure_till_date,
id,
value,
date,
sensor_id,
creation_date,
update_date
)
VALUES ($1, $2, $3, $4, $5, $6, $7);
VALUES ($1, $2, $3, $4, $5, $6);

View File

@ -8,7 +8,8 @@ INSERT INTO sensors (
gpio_number,
sensor_model,
sensor_enabled,
tick_duration,
device_id,
creation_date
)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11);
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12);

View File

@ -1,10 +1,9 @@
INSERT INTO temperatures (
temperature_id,
temperature_value,
temperature_from_date,
temperature_till_date,
id,
value,
date,
sensor_id,
creation_date,
update_date
)
VALUES ($1, $2, $3, $4, $5, $6, $7);
VALUES ($1, $2, $3, $4, $5, $6);

View File

@ -1,8 +1,7 @@
SELECT
humidity_id,
humidity_value,
humidity_from_date,
humidity_till_date,
id,
value,
date,
sensor_id,
creation_date,
update_date

View File

@ -1,8 +1,7 @@
SELECT
humidity_id,
humidity_value,
humidity_from_date,
humidity_till_date,
id,
value,
date,
sensor_id,
creation_date,
update_date

View File

@ -1,8 +1,7 @@
SELECT
pressure_id,
pressure_value,
pressure_from_date,
pressure_till_date,
id,
value,
date,
sensor_id,
creation_date,
update_date

View File

@ -1,8 +1,7 @@
SELECT
pressure_id,
pressure_value,
pressure_from_date,
pressure_till_date,
id,
value,
date,
sensor_id,
creation_date,
update_date

View File

@ -8,6 +8,7 @@ SELECT
gpio_number,
sensor_model,
sensor_enabled,
tick_duration,
device_id,
creation_date
FROM

View File

@ -8,7 +8,10 @@ SELECT
gpio_number,
sensor_model,
sensor_enabled,
tick_duration,
device_id,
creation_date
FROM
sensors;
sensors
ORDER BY
sensor_id;

View File

@ -1,8 +1,7 @@
SELECT
temperature_id,
temperature_value,
temperature_from_date,
temperature_till_date,
id,
value,
date,
sensor_id,
creation_date,
update_date

View File

@ -1,8 +1,7 @@
SELECT
temperature_id,
temperature_value,
temperature_from_date,
temperature_till_date,
id,
value,
date,
sensor_id,
creation_date,
update_date

View File

@ -1,7 +1,7 @@
UPDATE device
UPDATE devices
SET
device_name = $1,
device_location = $2,
creation_date = $3
WHERE
device_id = $4,
device_id = $4

View File

@ -8,7 +8,8 @@ SET
gpio_number = $6,
sensor_model = $7,
sensor_enabled = $8,
device_id = $9,
creation_date = $10
tick_duration = $9,
device_id = $10,
creation_date = $11
WHERE
sensor_id = $11;
sensor_id = $12;

View File

@ -110,7 +110,7 @@ func (repo *Repository) GetSensorsByDeviceID(deviceID string) ([]*types.Sensor,
}
}
return sensors, nil
return cachedSensors, nil
}
// RemoveDevices removes devices by their ids from the repository. Additional

View File

@ -0,0 +1,309 @@
package repository_test
import (
"context"
"fmt"
"math/rand"
"net/url"
"os"
"path/filepath"
"testing"
"time"
uuid "github.com/satori/go.uuid"
"github.com/stretchr/testify/require"
"github.com/volker-raschek/flucky/pkg/repository"
"github.com/volker-raschek/flucky/pkg/testutils/dockerutils"
"github.com/volker-raschek/flucky/pkg/types"
"github.com/volker-raschek/go-logger/pkg/logger"
)
func TestPostgresBackend(t *testing.T) {
t.Skip("Database backend postgres not completly implemented")
require := require.New(t)
dockerClient, err := dockerutils.New()
require.NoError(err)
rand.Seed(time.Now().Unix())
postgresHostPort := rand.Intn(10024-1024) + 1024
postgresDBPasswort := "postgres"
postgresContainerID, err := dockerClient.NewBuilder("postgres:latest").
Port(fmt.Sprintf("%v:5432/tcp", postgresHostPort)).
Pull().
AddEnv("PGTZ", "Europe/Berlin").
AddEnv("POSTGRES_PASSWORD", postgresDBPasswort).
AddEnv("TZ", "Europe/Berlin").
Mount("/etc/localtime", "/etc/localtime").
Start(context.Background())
cleanup := func() {
dockerClient.ContainerRemoveByIDs(context.Background(), postgresContainerID)
}
t.Cleanup(cleanup)
require.NoError(err)
// postgres://[user]:[password]@[host]:[port]/[path]?[query]
storageEndpoint, err := url.Parse(fmt.Sprintf("postgres://postgres:%v@localhost:%v", postgresDBPasswort, postgresHostPort))
require.NoError(err)
repo, err := repository.New(storageEndpoint, logger.NewDefaultLogger(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)
defer os.RemoveAll(workspace)
storageEndpoint, err := url.Parse(fmt.Sprintf("sqlite3://%v/test.db", workspace))
require.NoError(err)
repo, err := repository.New(storageEndpoint, logger.NewDefaultLogger(logger.LogLevelDebug))
require.NoError(err)
testBackend(t, repo)
}
func testBackend(t *testing.T, repo *repository.Repository) {
require := require.New(t)
location := uuid.NewV4().String()
expectedDevices := []*types.Device{
{
ID: "ec0be3ab-d26d-4f9b-a96e-23ae5c577f8f",
Name: "f2b245eb-b15f-40e1-9212-9a645907b710",
Location: &location,
CreationDate: *timeNow(require),
},
{
ID: "39b8f150-8abf-4539-9f16-7f68cedb1649",
Name: "62e3978f-2198-4aa9-9d6f-cdc91a468b00",
Location: &location,
CreationDate: *timeNow(require),
},
}
// Test: AddDevice
err := repo.AddDevices(expectedDevices...)
require.NoError(err)
// Test: GetDevices
devices, err := repo.GetDevices()
require.NoError(err)
require.Len(devices, len(expectedDevices))
require.EqualValues(expectedDevices, devices)
// Test: GetDevice
device, err := repo.GetDevice(expectedDevices[0].ID)
require.NoError(err)
require.EqualValues(expectedDevices[0], device)
// Test: RemoveDevice
err = repo.RemoveDevices(expectedDevices[1].ID)
require.NoError(err)
devices, err = repo.GetDevices()
require.NoError(err)
require.Len(devices, 1)
device, err = repo.GetDevice(expectedDevices[1].ID)
require.NoError(err)
require.Nil(device)
// 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(expectedDevice)
require.NoError(err)
device, err = repo.GetDevice(expectedDevice.ID)
require.NoError(err)
require.EqualValues(expectedDevice, device)
var (
wireID = "50473fdc-f6ef-4227-b3c4-484d8e9c1323"
i2cBus = 1
i2cAddress uint8 = 76
expectedSensors = []*types.Sensor{
{
ID: "0f8b88b0-c20d-42b2-ab51-b09ca99c0752",
Name: "e1fbdbe9-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(expectedSensors...)
require.NoError(err)
// Test: GetSensors
sensors, err := repo.GetSensors()
require.NoError(err)
require.Len(sensors, len(expectedSensors))
require.Equal(expectedSensors, sensors)
// Test: GetSensor
sensor, err := repo.GetSensor(expectedSensors[0].ID)
require.NoError(err)
require.Equal(expectedSensors[0], sensor)
// Test: GetSensorsByDeviceID
sensors, err = repo.GetSensorsByDeviceID("ec0be3ab-d26d-4f9b-a96e-23ae5c577f8f")
require.NoError(err)
require.Len(sensors, 2)
require.Equal(expectedSensors[0:2], sensors)
// Test: RemoveSensors
err = repo.RemoveSensors(expectedSensors[0].ID)
require.NoError(err)
sensors, err = repo.GetSensors()
require.NoError(err)
require.Len(sensors, 2)
sensors, err = repo.GetSensorsByDeviceID("ec0be3ab-d26d-4f9b-a96e-23ae5c577f8f")
require.NoError(err)
require.Len(sensors, 1)
sensor, err = repo.GetSensor(expectedSensors[0].ID)
require.NoError(err)
require.Nil(sensor)
// Test: RemoveSensorsByNames
err = repo.RemoveSensorsByNames(expectedSensors[1].Name)
require.NoError(err)
sensors, err = repo.GetSensors()
require.NoError(err)
require.Len(sensors, 1)
sensor, err = repo.GetSensor(expectedSensors[1].ID)
require.NoError(err)
require.Nil(sensor)
// Test: RenameSensor
err = repo.RenameSensors(expectedSensors[2].Name, "Hello")
require.NoError(err)
sensor, err = repo.GetSensor(expectedSensors[2].ID)
require.Equal("Hello", sensor.Name)
require.NotNil(sensor)
// Test: DisableSensorsByNames
err = repo.DisableSensorsByNames("Hello")
require.NoError(err)
sensor, err = repo.GetSensor(expectedSensors[2].ID)
require.False(sensor.Enabled)
require.NotNil(sensor)
// Test: EnableSensorsByName
err = repo.EnableSensorsByNames("Hello")
require.NoError(err)
sensor, err = repo.GetSensor(expectedSensors[2].ID)
require.True(sensor.Enabled)
require.NotNil(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(expectedSensor)
require.NoError(err)
sensor, err = repo.GetSensor(expectedSensor.ID)
require.NoError(err)
require.NotNil(sensor)
require.EqualValues(expectedSensor, sensor)
var (
expectedMeasuredValues = []*types.MeasuredValue{
{
ID: "2e5a297a-3da0-46ae-89d2-0fcab0f1d5f7",
Value: 32,
ValueType: "temperature",
Date: *timeNow(require),
SensorID: "8c74397f-8e60-4c9d-960d-3197747cef9a",
CreationDate: timeNow(require),
UpdateDate: nil,
},
{
ID: "d69f1b62-0c6c-4058-b42c-4a2821bd220c",
Value: 38,
ValueType: "temperature",
Date: *timeNow(require),
SensorID: "8c74397f-8e60-4c9d-960d-3197747cef9a",
CreationDate: timeNow(require),
UpdateDate: nil,
},
{
ID: "ea945ae0-412b-4561-a191-1f8f1f909fa4",
Value: 35.4,
ValueType: "temperature",
Date: *timeNow(require),
SensorID: "8c74397f-8e60-4c9d-960d-3197747cef9a",
CreationDate: timeNow(require),
UpdateDate: nil,
},
}
)
// Test: AddMeasuredValues
err = repo.AddMeasuredValues(expectedMeasuredValues...)
require.NoError(err)
}
func timeNow(require *require.Assertions) *time.Time {
now, err := time.Parse("2006-01-02 15:04:05", time.Now().Format("2006-01-02 15:04:05"))
require.NoError(err)
return &now
}