Compare commits
No commits in common. "f5583b3cd538a195bf7c4c3ec70adcd07d7b820d" and "1f6d0a58e78359b149272a12a479ee52ca629d42" have entirely different histories.
f5583b3cd5
...
1f6d0a58e7
4
Makefile
4
Makefile
@ -30,10 +30,6 @@ migrateup:
|
|||||||
mock:
|
mock:
|
||||||
go run go.uber.org/mock/mockgen@latest -package mock -destination internal/domains/sensors/mock/querier.go $(MOD_NAME)/internal/domains/sensors Repository
|
go run go.uber.org/mock/mockgen@latest -package mock -destination internal/domains/sensors/mock/querier.go $(MOD_NAME)/internal/domains/sensors Repository
|
||||||
|
|
||||||
.PHONY: test
|
|
||||||
# Run tests
|
|
||||||
tests:
|
|
||||||
go test ./...
|
|
||||||
|
|
||||||
.PHONY: run
|
.PHONY: run
|
||||||
# Start app in development environment
|
# Start app in development environment
|
||||||
|
|||||||
@ -3,11 +3,6 @@
|
|||||||
Lectura de datos de sensores en un dispositivo IoT. Prueba técnica para optar
|
Lectura de datos de sensores en un dispositivo IoT. Prueba técnica para optar
|
||||||
por el puesto de programador Go.
|
por el puesto de programador Go.
|
||||||
|
|
||||||
## TL:DR
|
|
||||||
|
|
||||||
- make lazy-start
|
|
||||||
- abre terminal y escribe: `nats sub sensors.data.*`
|
|
||||||
|
|
||||||
## Requisitos previos
|
## Requisitos previos
|
||||||
|
|
||||||
- Docker
|
- Docker
|
||||||
@ -52,8 +47,7 @@ por el puesto de programador Go.
|
|||||||
### Obtener valores de un sensor
|
### Obtener valores de un sensor
|
||||||
|
|
||||||
- Campo obligatorio: `sensor_id`.
|
- Campo obligatorio: `sensor_id`.
|
||||||
- Campos opcionales: `from` y `to` en formato RFC3339. Si no se especifican,
|
- Campos opcionales: `from` y `to` en formato RFC3339. Si no se especifican, se toman los últimos 7 días.
|
||||||
se toman los últimos 7 días.
|
|
||||||
|
|
||||||
`nats req sensors.values.get '{
|
`nats req sensors.values.get '{
|
||||||
"sensor_id": "sensor-001",
|
"sensor_id": "sensor-001",
|
||||||
|
|||||||
@ -35,12 +35,3 @@ create table registry
|
|||||||
timescaledb.partition_column = 'created_at',
|
timescaledb.partition_column = 'created_at',
|
||||||
timescaledb.segmentby = 'sensor_id'
|
timescaledb.segmentby = 'sensor_id'
|
||||||
);
|
);
|
||||||
|
|
||||||
insert into sensors (sensor_id, sensor_type, sampling_interval, threshold_above, threshold_below)
|
|
||||||
values
|
|
||||||
('temp-001', 'temperature', 10, 100, 0),
|
|
||||||
('hum-001', 'humidity', 15, 80, 20),
|
|
||||||
('co2-001', 'carbon_dioxide', 20, 1000, 400),
|
|
||||||
('pres-001', 'pressure', 30, 1050, 950),
|
|
||||||
('prox-001', 'proximity', 5, 200, 0),
|
|
||||||
('light-001', 'light', 10, 10000, 0);
|
|
||||||
@ -195,136 +195,6 @@ func Test_SensorValidate(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_SensorData_Validate(t *testing.T) {
|
|
||||||
type testCase struct {
|
|
||||||
name string
|
|
||||||
given SensorData
|
|
||||||
expected SensorData
|
|
||||||
expecErr bool
|
|
||||||
}
|
|
||||||
|
|
||||||
timestamp := time.Now()
|
|
||||||
|
|
||||||
tests := []testCase{
|
|
||||||
{
|
|
||||||
name: "success with all fields",
|
|
||||||
given: SensorData{
|
|
||||||
SensorID: "temp-001",
|
|
||||||
Value: ptr(25.5),
|
|
||||||
Timestamp: ptr(timestamp),
|
|
||||||
},
|
|
||||||
expected: SensorData{
|
|
||||||
SensorID: "temp-001",
|
|
||||||
Value: ptr(25.5),
|
|
||||||
Timestamp: ptr(timestamp),
|
|
||||||
},
|
|
||||||
expecErr: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "error when sensor_id is empty",
|
|
||||||
given: SensorData{
|
|
||||||
SensorID: "",
|
|
||||||
Value: ptr(25.5),
|
|
||||||
},
|
|
||||||
expecErr: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "error when value is nil",
|
|
||||||
given: SensorData{
|
|
||||||
SensorID: "temp-001",
|
|
||||||
Value: nil,
|
|
||||||
},
|
|
||||||
expecErr: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "default timestamp when nil",
|
|
||||||
given: SensorData{
|
|
||||||
SensorID: "temp-001",
|
|
||||||
Value: ptr(30.0),
|
|
||||||
Timestamp: nil,
|
|
||||||
},
|
|
||||||
expected: SensorData{
|
|
||||||
SensorID: "temp-001",
|
|
||||||
Value: ptr(30.0),
|
|
||||||
Timestamp: nil, // Will be set by Validate
|
|
||||||
},
|
|
||||||
expecErr: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "zero value is preserved",
|
|
||||||
given: SensorData{
|
|
||||||
SensorID: "temp-001",
|
|
||||||
Value: ptr(0.0),
|
|
||||||
Timestamp: ptr(timestamp),
|
|
||||||
},
|
|
||||||
expected: SensorData{
|
|
||||||
SensorID: "temp-001",
|
|
||||||
Value: ptr(0.0),
|
|
||||||
Timestamp: ptr(timestamp),
|
|
||||||
},
|
|
||||||
expecErr: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "negative value is valid",
|
|
||||||
given: SensorData{
|
|
||||||
SensorID: "temp-001",
|
|
||||||
Value: ptr(-15.5),
|
|
||||||
Timestamp: ptr(timestamp),
|
|
||||||
},
|
|
||||||
expected: SensorData{
|
|
||||||
SensorID: "temp-001",
|
|
||||||
Value: ptr(-15.5),
|
|
||||||
Timestamp: ptr(timestamp),
|
|
||||||
},
|
|
||||||
expecErr: false,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
err := tt.given.Validate()
|
|
||||||
|
|
||||||
if tt.expecErr && err == nil {
|
|
||||||
t.Errorf("expected error, got nil")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if !tt.expecErr && err != nil {
|
|
||||||
t.Errorf("unexpected error: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if tt.expecErr {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if tt.given.SensorID != tt.expected.SensorID {
|
|
||||||
t.Errorf("SensorID: expected %q, got %q", tt.expected.SensorID, tt.given.SensorID)
|
|
||||||
}
|
|
||||||
|
|
||||||
if tt.given.Value == nil || tt.expected.Value == nil {
|
|
||||||
if tt.given.Value != tt.expected.Value {
|
|
||||||
t.Errorf("Value: expected %v, got %v", tt.expected.Value, tt.given.Value)
|
|
||||||
}
|
|
||||||
} else if *tt.given.Value != *tt.expected.Value {
|
|
||||||
t.Errorf("Value: expected %v, got %v", *tt.expected.Value, *tt.given.Value)
|
|
||||||
}
|
|
||||||
|
|
||||||
if tt.expected.Timestamp == nil && tt.given.Timestamp != nil {
|
|
||||||
if time.Since(*tt.given.Timestamp) > time.Minute {
|
|
||||||
t.Errorf("Timestamp: expected default to be approximately now, got %v", *tt.given.Timestamp)
|
|
||||||
}
|
|
||||||
} else if tt.given.Timestamp == nil || tt.expected.Timestamp == nil {
|
|
||||||
if tt.given.Timestamp != tt.expected.Timestamp {
|
|
||||||
t.Errorf("Timestamp: expected %v, got %v", tt.expected.Timestamp, tt.given.Timestamp)
|
|
||||||
}
|
|
||||||
} else if !tt.given.Timestamp.Equal(*tt.expected.Timestamp) {
|
|
||||||
t.Errorf("Timestamp: expected %v, got %v", *tt.expected.Timestamp, *tt.given.Timestamp)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_SensorData_IsOutOfRangeAbove(t *testing.T) {
|
func Test_SensorData_IsOutOfRangeAbove(t *testing.T) {
|
||||||
type testCase struct {
|
type testCase struct {
|
||||||
name string
|
name string
|
||||||
@ -386,16 +256,6 @@ func Test_SensorData_IsOutOfRangeAbove(t *testing.T) {
|
|||||||
},
|
},
|
||||||
expected: true,
|
expected: true,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: "nil values",
|
|
||||||
data: SensorData{
|
|
||||||
SensorID: "temp-001",
|
|
||||||
},
|
|
||||||
sensor: Sensor{
|
|
||||||
SensorID: "temp-001",
|
|
||||||
},
|
|
||||||
expected: false,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
@ -483,16 +343,6 @@ func Test_SensorData_IsOutOfRangeBelow(t *testing.T) {
|
|||||||
},
|
},
|
||||||
expected: true,
|
expected: true,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: "nil values",
|
|
||||||
data: SensorData{
|
|
||||||
SensorID: "temp-001",
|
|
||||||
},
|
|
||||||
sensor: Sensor{
|
|
||||||
SensorID: "temp-001",
|
|
||||||
},
|
|
||||||
expected: false,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user