503 lines
11 KiB
Go
503 lines
11 KiB
Go
package sensors
|
|
|
|
import (
|
|
"errors"
|
|
"testing"
|
|
"time"
|
|
|
|
"go.uber.org/mock/gomock"
|
|
)
|
|
|
|
func setup(t *testing.T) (*Service, *MockRepository) {
|
|
ctrl := gomock.NewController(t)
|
|
q := NewMockRepository(ctrl)
|
|
s := NewService(q)
|
|
return s, q
|
|
}
|
|
|
|
func Test_RegisterSensor(t *testing.T) {
|
|
type testCase struct {
|
|
name string
|
|
given Sensor
|
|
setupMock func(q *MockRepository, params Sensor)
|
|
expecErr bool
|
|
expectErr error
|
|
}
|
|
|
|
tests := []testCase{
|
|
{
|
|
name: "success - registers new sensor",
|
|
given: Sensor{
|
|
SensorID: "temp-001",
|
|
SensorType: Temperature,
|
|
SamplingInterval: ptr(time.Minute),
|
|
ThresholdAbove: ptr(100.0),
|
|
ThresholdBelow: ptr(0.0),
|
|
},
|
|
setupMock: func(q *MockRepository, params Sensor) {
|
|
q.EXPECT().CreateSensor(params).Return(nil)
|
|
},
|
|
expecErr: false,
|
|
},
|
|
{
|
|
name: "error - sensor already exists",
|
|
given: Sensor{
|
|
SensorID: "temp-001",
|
|
SensorType: Temperature,
|
|
SamplingInterval: ptr(time.Minute),
|
|
ThresholdAbove: ptr(100.0),
|
|
ThresholdBelow: ptr(0.0),
|
|
},
|
|
setupMock: func(q *MockRepository, params Sensor) {
|
|
q.EXPECT().CreateSensor(params).Return(errors.New("duplicate key value"))
|
|
},
|
|
expecErr: true,
|
|
expectErr: ErrSensorAlreadyExists,
|
|
},
|
|
{
|
|
name: "error - some db error",
|
|
given: Sensor{
|
|
SensorID: "temp-001",
|
|
SensorType: Temperature,
|
|
SamplingInterval: ptr(time.Minute),
|
|
ThresholdAbove: ptr(100.0),
|
|
ThresholdBelow: ptr(0.0),
|
|
},
|
|
setupMock: func(q *MockRepository, params Sensor) {
|
|
q.EXPECT().CreateSensor(params).Return(errors.New("some db error"))
|
|
},
|
|
expecErr: true,
|
|
expectErr: ErrRegisteringSensor,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
s, q := setup(t)
|
|
|
|
tt.setupMock(q, tt.given)
|
|
|
|
err := s.RegisterSensor(tt.given)
|
|
|
|
if tt.expecErr && err == nil {
|
|
t.Error("expected error, got nil")
|
|
return
|
|
}
|
|
|
|
if !tt.expecErr && err != nil {
|
|
t.Errorf("expected no error, got %v", err)
|
|
return
|
|
}
|
|
|
|
if tt.expecErr && tt.expectErr != nil && err != tt.expectErr {
|
|
t.Errorf("expected error %v, got %v", tt.expectErr, err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func Test_RegisterSensorData(t *testing.T) {
|
|
type testCase struct {
|
|
name string
|
|
given SensorData
|
|
setupMock func(q *MockRepository, params SensorData)
|
|
expecErr bool
|
|
}
|
|
|
|
timestamp := time.Now()
|
|
value := 25.5
|
|
|
|
tests := []testCase{
|
|
{
|
|
name: "success - registers sensor data",
|
|
given: SensorData{
|
|
SensorID: "temp-001",
|
|
Value: &value,
|
|
Timestamp: ×tamp,
|
|
},
|
|
setupMock: func(q *MockRepository, params SensorData) {
|
|
q.EXPECT().CreateSensorData(params).Return(nil)
|
|
},
|
|
expecErr: false,
|
|
},
|
|
{
|
|
name: "error - database error",
|
|
given: SensorData{
|
|
SensorID: "temp-001",
|
|
Value: &value,
|
|
Timestamp: ×tamp,
|
|
},
|
|
setupMock: func(q *MockRepository, params SensorData) {
|
|
q.EXPECT().CreateSensorData(params).Return(errors.New("database error"))
|
|
},
|
|
expecErr: true,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
s, q := setup(t)
|
|
|
|
tt.setupMock(q, tt.given)
|
|
|
|
err := s.RegisterSensorData(tt.given)
|
|
|
|
if tt.expecErr && err == nil {
|
|
t.Error("expected error, got nil")
|
|
return
|
|
}
|
|
|
|
if !tt.expecErr && err != nil {
|
|
t.Errorf("expected no error, got %v", err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func Test_UpdateSensor(t *testing.T) {
|
|
type testCase struct {
|
|
name string
|
|
given Sensor
|
|
setupMock func(q *MockRepository, params Sensor)
|
|
expecErr bool
|
|
expectErr error
|
|
}
|
|
|
|
tests := []testCase{
|
|
{
|
|
name: "success - updates sensor",
|
|
given: Sensor{
|
|
SensorID: "temp-001",
|
|
SensorType: Temperature,
|
|
SamplingInterval: ptr(time.Minute * 2),
|
|
ThresholdAbove: ptr(120.0),
|
|
ThresholdBelow: ptr(10.0),
|
|
},
|
|
setupMock: func(q *MockRepository, params Sensor) {
|
|
q.EXPECT().UpdateSensor(params).Return(nil)
|
|
},
|
|
expecErr: false,
|
|
},
|
|
{
|
|
name: "error - sensor already exists (duplicate)",
|
|
given: Sensor{
|
|
SensorID: "temp-002",
|
|
SensorType: Temperature,
|
|
SamplingInterval: ptr(time.Minute),
|
|
ThresholdAbove: ptr(100.0),
|
|
ThresholdBelow: ptr(0.0),
|
|
},
|
|
setupMock: func(q *MockRepository, params Sensor) {
|
|
q.EXPECT().UpdateSensor(params).Return(errors.New("duplicate key value"))
|
|
},
|
|
expecErr: true,
|
|
expectErr: ErrSensorAlreadyExists,
|
|
},
|
|
{
|
|
name: "error - general database error",
|
|
given: Sensor{
|
|
SensorID: "temp-001",
|
|
SensorType: Temperature,
|
|
SamplingInterval: ptr(time.Minute),
|
|
ThresholdAbove: ptr(100.0),
|
|
ThresholdBelow: ptr(0.0),
|
|
},
|
|
setupMock: func(q *MockRepository, params Sensor) {
|
|
q.EXPECT().UpdateSensor(params).Return(errors.New("connection failed"))
|
|
},
|
|
expecErr: true,
|
|
expectErr: ErrUpdatingSensor,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
s, q := setup(t)
|
|
|
|
tt.setupMock(q, tt.given)
|
|
|
|
err := s.UpdateSensor(tt.given)
|
|
|
|
if tt.expecErr && err == nil {
|
|
t.Error("expected error, got nil")
|
|
return
|
|
}
|
|
|
|
if !tt.expecErr && err != nil {
|
|
t.Errorf("expected no error, got %v", err)
|
|
return
|
|
}
|
|
|
|
if tt.expecErr && tt.expectErr != nil && err != tt.expectErr {
|
|
t.Errorf("expected error %v, got %v", tt.expectErr, err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func Test_GetSensor(t *testing.T) {
|
|
type testCase struct {
|
|
name string
|
|
given SensorRequest
|
|
setupMock func(q *MockRepository, sensorID string)
|
|
expected Sensor
|
|
expecErr bool
|
|
}
|
|
|
|
tests := []testCase{
|
|
{
|
|
name: "success - retrieves sensor",
|
|
given: SensorRequest{
|
|
SensorID: "temp-001",
|
|
},
|
|
setupMock: func(q *MockRepository, sensorID string) {
|
|
q.EXPECT().ReadSensor(sensorID).Return(Sensor{
|
|
SensorID: "temp-001",
|
|
SensorType: Temperature,
|
|
SamplingInterval: ptr(time.Minute),
|
|
ThresholdAbove: ptr(100.0),
|
|
ThresholdBelow: ptr(0.0),
|
|
}, nil)
|
|
},
|
|
expected: Sensor{
|
|
SensorID: "temp-001",
|
|
SensorType: Temperature,
|
|
SamplingInterval: ptr(time.Minute),
|
|
ThresholdAbove: ptr(100.0),
|
|
ThresholdBelow: ptr(0.0),
|
|
},
|
|
expecErr: false,
|
|
},
|
|
{
|
|
name: "error - sensor not found",
|
|
given: SensorRequest{
|
|
SensorID: "temp-999",
|
|
},
|
|
setupMock: func(q *MockRepository, sensorID string) {
|
|
q.EXPECT().ReadSensor(sensorID).Return(Sensor{}, ErrSensorNotFound)
|
|
},
|
|
expected: Sensor{},
|
|
expecErr: true,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
s, q := setup(t)
|
|
|
|
tt.setupMock(q, tt.given.SensorID)
|
|
|
|
result, err := s.GetSensor(tt.given)
|
|
|
|
if tt.expecErr && err == nil {
|
|
t.Error("expected error, got nil")
|
|
return
|
|
}
|
|
|
|
if !tt.expecErr && err != nil {
|
|
t.Errorf("expected no error, got %v", err)
|
|
return
|
|
}
|
|
|
|
if !tt.expecErr {
|
|
if result.SensorID != tt.expected.SensorID {
|
|
t.Errorf("expected sensor_id %q, got %q", tt.expected.SensorID, result.SensorID)
|
|
}
|
|
if result.SensorType != tt.expected.SensorType {
|
|
t.Errorf("expected sensor_type %q, got %q", tt.expected.SensorType, result.SensorType)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func Test_GetValues(t *testing.T) {
|
|
type testCase struct {
|
|
name string
|
|
given SensorDataRequest
|
|
setupMock func(q *MockRepository, sensorID string, from, to time.Time)
|
|
expected []SensorData
|
|
expecErr bool
|
|
}
|
|
|
|
now := time.Now()
|
|
weekAgo := now.AddDate(0, 0, -7)
|
|
fromStr := weekAgo.Format(time.RFC3339)
|
|
toStr := now.Format(time.RFC3339)
|
|
|
|
value1 := 25.5
|
|
value2 := 26.0
|
|
|
|
tests := []testCase{
|
|
{
|
|
name: "success - retrieves sensor data",
|
|
given: SensorDataRequest{
|
|
SensorID: "temp-001",
|
|
From: &fromStr,
|
|
To: &toStr,
|
|
},
|
|
setupMock: func(q *MockRepository, sensorID string, from, to time.Time) {
|
|
q.EXPECT().ReadSensorValues(sensorID, from, to).Return([]SensorData{
|
|
{
|
|
SensorID: "temp-001",
|
|
Value: &value1,
|
|
Timestamp: &weekAgo,
|
|
},
|
|
{
|
|
SensorID: "temp-001",
|
|
Value: &value2,
|
|
Timestamp: &now,
|
|
},
|
|
}, nil)
|
|
},
|
|
expected: []SensorData{
|
|
{
|
|
SensorID: "temp-001",
|
|
Value: &value1,
|
|
Timestamp: &weekAgo,
|
|
},
|
|
{
|
|
SensorID: "temp-001",
|
|
Value: &value2,
|
|
Timestamp: &now,
|
|
},
|
|
},
|
|
expecErr: false,
|
|
},
|
|
{
|
|
name: "error - database error",
|
|
given: SensorDataRequest{
|
|
SensorID: "temp-001",
|
|
From: &fromStr,
|
|
To: &toStr,
|
|
},
|
|
setupMock: func(q *MockRepository, sensorID string, from, to time.Time) {
|
|
q.EXPECT().ReadSensorValues(sensorID, from, to).Return([]SensorData{}, errors.New("database error"))
|
|
},
|
|
expected: []SensorData{},
|
|
expecErr: true,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
s, q := setup(t)
|
|
|
|
from, _ := time.Parse(time.RFC3339, *tt.given.From)
|
|
to, _ := time.Parse(time.RFC3339, *tt.given.To)
|
|
|
|
tt.setupMock(q, tt.given.SensorID, from, to)
|
|
|
|
result, err := s.GetValues(tt.given)
|
|
|
|
if tt.expecErr && err == nil {
|
|
t.Error("expected error, got nil")
|
|
return
|
|
}
|
|
|
|
if !tt.expecErr && err != nil {
|
|
t.Errorf("expected no error, got %v", err)
|
|
return
|
|
}
|
|
|
|
if !tt.expecErr {
|
|
if len(result) != len(tt.expected) {
|
|
t.Errorf("expected %d values, got %d", len(tt.expected), len(result))
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func Test_ListSensors(t *testing.T) {
|
|
type testCase struct {
|
|
name string
|
|
setupMock func(q *MockRepository)
|
|
expected []Sensor
|
|
expecErr bool
|
|
}
|
|
|
|
tests := []testCase{
|
|
{
|
|
name: "success - retrieves all sensors",
|
|
setupMock: func(q *MockRepository) {
|
|
q.EXPECT().ReadAllSensors().Return([]Sensor{
|
|
{
|
|
SensorID: "temp-001",
|
|
SensorType: Temperature,
|
|
SamplingInterval: ptr(time.Minute),
|
|
ThresholdAbove: ptr(100.0),
|
|
ThresholdBelow: ptr(0.0),
|
|
},
|
|
{
|
|
SensorID: "hum-001",
|
|
SensorType: Humidity,
|
|
SamplingInterval: ptr(time.Minute * 2),
|
|
ThresholdAbove: ptr(80.0),
|
|
ThresholdBelow: ptr(20.0),
|
|
},
|
|
}, nil)
|
|
},
|
|
expected: []Sensor{
|
|
{
|
|
SensorID: "temp-001",
|
|
SensorType: Temperature,
|
|
SamplingInterval: ptr(time.Minute),
|
|
ThresholdAbove: ptr(100.0),
|
|
ThresholdBelow: ptr(0.0),
|
|
},
|
|
{
|
|
SensorID: "hum-001",
|
|
SensorType: Humidity,
|
|
SamplingInterval: ptr(time.Minute * 2),
|
|
ThresholdAbove: ptr(80.0),
|
|
ThresholdBelow: ptr(20.0),
|
|
},
|
|
},
|
|
expecErr: false,
|
|
},
|
|
{
|
|
name: "success - empty list when no sensors",
|
|
setupMock: func(q *MockRepository) {
|
|
q.EXPECT().ReadAllSensors().Return([]Sensor{}, nil)
|
|
},
|
|
expected: []Sensor{},
|
|
expecErr: false,
|
|
},
|
|
{
|
|
name: "error - database error",
|
|
setupMock: func(q *MockRepository) {
|
|
q.EXPECT().ReadAllSensors().Return([]Sensor{}, errors.New("database error"))
|
|
},
|
|
expected: []Sensor{},
|
|
expecErr: true,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
s, q := setup(t)
|
|
|
|
tt.setupMock(q)
|
|
|
|
result, err := s.ListSensors()
|
|
|
|
if tt.expecErr && err == nil {
|
|
t.Error("expected error, got nil")
|
|
return
|
|
}
|
|
|
|
if !tt.expecErr && err != nil {
|
|
t.Errorf("expected no error, got %v", err)
|
|
return
|
|
}
|
|
|
|
if !tt.expecErr {
|
|
if len(result) != len(tt.expected) {
|
|
t.Errorf("expected %d sensors, got %d", len(tt.expected), len(result))
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|