192 lines
5.1 KiB
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()
|
|
})
|
|
}
|
|
}
|