src.dualinventive.com/go/influxdb-logger/internal/influxdb/process_test.go

192 lines
5.1 KiB
Go

package influxdb
import (
"context"
"encoding/json"
"fmt"
"sync"
"testing"
"time"
client "github.com/influxdata/influxdb1-client/v2"
"github.com/stretchr/testify/require"
"src.dualinventive.com/go/dinet/ditime"
"src.dualinventive.com/go/dinet/rpc"
"src.dualinventive.com/go/dinet/rts"
"src.dualinventive.com/go/lib/kv"
)
//nolint: gochecknoglobals
var (
processDeviceUID = "01234567890123456789012345678901"
sensorDataMsg = &rpc.Msg{
Dinetrpc: 1,
DeviceUID: processDeviceUID,
ID: 1,
Time: ditime.Now(),
Type: rpc.MsgTypePublish,
ClassMethod: rpc.ClassMethodSensorData,
Result: rpc.NewResult([]map[string]interface{}{
{
"uid": float64(1),
"value": float64(1),
"time": ditime.Now(),
}, {
"uid": float64(1),
"value": float64(2),
"time": ditime.Now(),
}, {
"uid": float64(1),
"value": float64(3),
"time": ditime.Now(),
}, {
// This value will be dropped because there is no sensor:info present
// for uid 2
"uid": float64(2),
"value": float64(3),
"time": ditime.Now(),
},
}),
}
sensorDataValuesMsg = &rpc.Msg{
Dinetrpc: 1,
DeviceUID: processDeviceUID,
ID: 1,
Time: ditime.Now(),
Type: rpc.MsgTypePublish,
ClassMethod: rpc.ClassMethodSensorData,
Result: rpc.NewResult([]rpc.ResultValueItem{
{
UID: 100,
Time: ditime.Now(),
Values: &rpc.ResultValuesItem{
Interval: 312*time.Microsecond + 500*time.Nanosecond,
Samples: []float64{
10.23, 20.1, 30.25, 40.50, 50.22,
},
},
},
}),
}
notifyDataMsg = &rpc.Msg{
Dinetrpc: 1,
DeviceUID: processDeviceUID,
ID: 1,
Time: ditime.Now(),
Type: rpc.MsgTypePublish,
ClassMethod: rpc.ClassMethodNotifyData,
Result: rpc.NewResult([]map[string]interface{}{
{
"uid": float64(1),
"value": true,
"time": ditime.Now(),
},
{
"uid": float64(1),
"value": false,
"time": ditime.Now(),
},
}),
}
deviceMsg = &rpc.Msg{
Dinetrpc: 1,
DeviceUID: processDeviceUID,
ID: 1,
Time: ditime.Now(),
Type: rpc.MsgTypeReply,
ClassMethod: rpc.ClassMethodDeviceData,
Result: rpc.NewResult([]map[string]interface{}{
{
"state": "idle",
"error": true,
"errors": []interface{}{1.0, 2.0, 3.0},
},
}),
}
)
func fillCache(t *testing.T, kv kv.KV) {
require.Nil(t, kv.HSet(rts.KeyPrefixDevice+processDeviceUID, "sensor:1:info",
`{"label":"bat1-voltage","last_update":1517914855147,"time":1517914854889,"type":"number","uid":1}`))
require.Nil(t, kv.HSet(rts.KeyPrefixDevice+processDeviceUID, "sensor:100:info",
`{"label":"rvm-vibration-1","last_update":1517914855147,"time":1517914854889,"type":"numbers","uid":100}`))
require.Nil(t, kv.HSet(rts.KeyPrefixDevice+processDeviceUID, "notify:1:info",
`{"label":"du-detection","last_update":1517914855553,"time":1517914855337,"type":"bool","uid":1}`))
require.Nil(t, kv.HSet(rts.KeyPrefixDevice+processDeviceUID, string(rpc.ClassMethodDeviceInfo),
`{"last_update":1519137369375,"revision":3,"time":1519137368544,"type":"tws-3000-duu","version":"0.8.0"}`))
}
func TestSend(t *testing.T) {
testcases := []struct {
name string
msg *rpc.Msg
class rpc.Class
nrOfPoints int
}{
{name: "device:data", msg: deviceMsg, class: rpc.ClassDevice, nrOfPoints: 5},
{name: "sensor:data", msg: sensorDataMsg, class: rpc.ClassSensor, nrOfPoints: 4},
{name: "sensor:data", msg: sensorDataValuesMsg, class: rpc.ClassSensor, nrOfPoints: 6},
{name: "notify:data", msg: notifyDataMsg, class: rpc.ClassNotify, nrOfPoints: 3},
}
for _, tc := range testcases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
ramKV, err := kv.New(kv.TypeRAM, "")
require.Nil(t, err)
fillCache(t, ramKV)
i, err := New("http://127.0.0.1", "root", "root", "db", 5, ramKV, 1, time.Second)
require.Nil(t, err)
require.NotNil(t, i)
// Convert the writer is mock writer
tw := &testWriter{c: make(chan *client.Point)}
i.writer = tw
ctx, cancel := context.WithCancel(context.Background())
var wg sync.WaitGroup
wg.Add(2)
go func(cancel func()) {
defer wg.Done()
switch tc.class {
case rpc.ClassSensor:
tc.msg.ClassMethod = rpc.ClassMethodSensorData
case rpc.ClassNotify:
tc.msg.ClassMethod = rpc.ClassMethodNotifyData
}
// XXX this is the most ugly hack to satisfy the non-idiomatic rpc defereddecoder
// it is copy pasted from the rpc test transport. because rpc.Msg is unusable
// to get result when no decoder is attached
b, err := json.Marshal(tc.msg)
require.Nil(t, err)
msg := &rpc.Msg{}
err = json.Unmarshal(b, msg)
require.Nil(t, err)
fmt.Println(msg)
err = i.Send(msg)
require.Nil(t, err)
cancel()
}(cancel)
go func() {
defer wg.Done()
for i := 0; i < tc.nrOfPoints; i++ {
pt := <-tw.c
fmt.Printf("%+v\n", pt)
}
select {
case pt := <-tw.c:
require.Fail(t, "expected no other point", pt.String())
default:
}
}()
i.Process(ctx, time.Second)
wg.Wait()
})
}
}