src.dualinventive.com/go/cp3000-interface/internal/device/device_test.go

482 lines
15 KiB
Go

package device
import (
"fmt"
"testing"
"github.com/stretchr/testify/require"
"src.dualinventive.com/go/cp3000-interface/internal/storage"
"src.dualinventive.com/go/cp3000-interface/internal/testenv"
"src.dualinventive.com/go/dinet"
"src.dualinventive.com/go/dinet/rpc"
"src.dualinventive.com/go/lib/cp3000"
)
func registerCP3000Device(t *testing.T, td *testenv.TestData, newFunc createDeviceFunc) {
base, err := newBaseDevice(td.Cp3000Router, td.Repo, "v2.0", 2)
require.Nil(t, err)
dev := newFunc(base)
require.NotNil(t, dev)
base.dev = dinet.NewChildDevice(dev, td.ServiceDev)
dev.construct()
err = dev.RegisterCallbacks()
require.Nil(t, err)
}
func TestRegister(t *testing.T) {
testData := testenv.CreateTestData(t)
testCases := []struct {
LegacyDevType int
DeviceType rpc.DeviceType
ExpectedType Device
ExpectRetrSwitch bool
}{
{0, rpc.DeviceTypeZKL3000, &Zkl3000{}, false},
{19, rpc.DeviceTypeZKL3000, &Zkl3000{}, false},
{47, rpc.DeviceTypeZKL3000, &Zkl3000{}, false},
{66, rpc.DeviceTypeZKL3000, &Zkl3000{}, false},
{2, rpc.DeviceTypeZKL3000RC, &Zkl3000Rc{}, true},
{27, rpc.DeviceTypeZKL3000RC, &Zkl3000Rc{}, true},
{33, rpc.DeviceTypeZKL3000RC, &Zkl3000Rc{}, true},
{35, rpc.DeviceTypeZKL3000RC, &Zkl3000Rc{}, true},
{49, rpc.DeviceTypeZKL3000RC, &Zkl3000Rc{}, true},
{61, rpc.DeviceTypeZKL3000RC, &Zkl3000Rc{}, true},
{71, rpc.DeviceTypeZKL3000RC, &Zkl3000Rc{}, true},
{25, rpc.DeviceTypeZKL3000RCC, &Zkl3000Rc{}, true},
{26, rpc.DeviceTypeZKL3000RCC, &Zkl3000Rc{}, true},
{64, rpc.DeviceTypeZKL3000RCC, &Zkl3000Rc{}, true},
{36, rpc.DeviceTypeCRTMGateway, &CrtmGateway{}, false},
{59, rpc.DeviceTypeGRB3000, &CrtmGateway{}, false},
{31, rpc.DeviceTypeCRTMSensor, &CrtmSensor{}, false},
{55, rpc.DeviceTypeCRTMSensor, &CrtmSensor{}, false},
{60, rpc.DeviceTypeCRTMSensor, &CrtmSensor{}, false},
{63, rpc.DeviceTypeCRTMSensor, &CrtmSensor{}, false},
}
for id, tc := range testCases {
imei := fmt.Sprintf("imei_%d", tc.LegacyDevType)
testData.Repo.Devices[imei] = &storage.Device{
ID: id,
Type: tc.LegacyDevType,
IMEI: imei,
HWVersion: fmt.Sprintf("hw_%d", tc.LegacyDevType),
}
}
for _, tc := range testCases {
// Transfer tc to local variable for fixing schope
tc := tc
t.Run(fmt.Sprintf("Dev: %d", tc.LegacyDevType), func(t *testing.T) {
if tc.ExpectRetrSwitch {
testZkl3000RequestSwitchInfoAssertReqRep(testData)
testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{
Type: cp3000.TypeCommand,
Command: cp3000.CommandRetrieve,
Params: []string{"SWITCH"},
}, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{"01008F14"}})
}
d, err := Register(testData.ServiceDev, testData.Repo, testData.Cp3000Router,
fmt.Sprintf("imei_%d", tc.LegacyDevType))
require.Nil(t, err)
require.IsType(t, tc.ExpectedType, d)
testData.Cp3000Connection.WaitForEmptyQueue()
})
}
testData.Finish()
}
func TestDeviceInfo(t *testing.T) {
testCases := []struct {
newFunc createDeviceFunc
devType rpc.DeviceType
hwKey rpc.VersionKey
versions []string
keys []rpc.VersionKey
}{
{
newFunc: newZkl3000,
devType: rpc.DeviceTypeZKL3000,
hwKey: rpc.VersionKeyHwZKLMain,
versions: []string{"FW-MCU", "FW-WCPU"},
keys: []rpc.VersionKey{rpc.VersionKeyFwZKLMain, rpc.VersionKeyFwZKLWcpu},
}, {
newFunc: newZkl3000Rc,
devType: rpc.DeviceTypeZKL3000RC,
hwKey: rpc.VersionKeyHwZKLRCMain,
versions: []string{"FW-MCU", "FW-WCPU", "FW-SW3000-M", "FW-SW3000-D"},
keys: []rpc.VersionKey{
rpc.VersionKeyFwZKLRCMain,
rpc.VersionKeyFwZKLRCWcpu,
rpc.VersionKeyFwZKLRCSwitchMeas,
rpc.VersionKeyFwZKLRCSwitchDrive,
},
}, {
newFunc: newZkl3000Rcc,
devType: rpc.DeviceTypeZKL3000RCC,
hwKey: rpc.VersionKeyHwZKLRCMain,
versions: []string{"FW-MCU", "FW-WCPU", "FW-SW3000-M", "FW-SW3000-D"},
keys: []rpc.VersionKey{
rpc.VersionKeyFwZKLRCMain,
rpc.VersionKeyFwZKLRCWcpu,
rpc.VersionKeyFwZKLRCSwitchMeas,
rpc.VersionKeyFwZKLRCSwitchDrive,
},
}, {
newFunc: newCrtmGateway,
devType: rpc.DeviceTypeCRTMGateway,
hwKey: rpc.VersionKeyHwGateway,
versions: []string{"FW-WCPU"},
keys: []rpc.VersionKey{rpc.VersionKeyFwGateway},
}, {
newFunc: newGreenHub,
devType: rpc.DeviceTypeGRB3000,
hwKey: rpc.VersionKeyHwGRB,
versions: []string{"FW-WCPU"},
keys: []rpc.VersionKey{rpc.VersionKeyFwGRB},
}, {
newFunc: newCrtmSensor,
devType: rpc.DeviceTypeCRTMSensor,
hwKey: rpc.VersionKeyHwCRTM,
versions: []string{"FW-MCU"},
keys: []rpc.VersionKey{rpc.VersionKeyFwCRTM},
},
}
for _, tc := range testCases {
// Transfer tc to local variable for fixing schope
tc := tc
t.Run(string(tc.devType), func(t *testing.T) {
testData := testenv.CreateTestData(t)
for i, cmd := range tc.versions {
testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{
Type: cp3000.TypeCommand,
Command: cp3000.CommandRetrieve,
Params: []string{fmt.Sprintf("VERSION[%s]", cmd)},
}, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{fmt.Sprintf("v1.%d", i)}})
}
registerCP3000Device(t, testData, tc.newFunc)
response := testData.ReqRep(rpc.ClassMethodDeviceInfo)
require.Nil(t, response.Error)
var information []rpc.DeviceInfo
require.Nil(t, response.Result.Unmarshal(&information))
require.Len(t, information, 1)
require.Equal(t, tc.devType, information[0].Type)
vMap := rpc.VersionMap{tc.hwKey: "v2.0"}
for i, key := range tc.keys {
vMap[key] = fmt.Sprintf("v1.%d", i)
}
require.Equal(t, vMap, information[0].Version)
testData.Finish()
})
}
}
func TestConnectionInfo(t *testing.T) {
testCases := []struct {
newFunc createDeviceFunc
devType rpc.DeviceType
timeout uint32
transport rpc.ConnectionTransport
}{
{
newFunc: newZkl3000,
devType: rpc.DeviceTypeZKL3000,
timeout: 60,
transport: rpc.ConnectionTransportCP3000,
}, {
newFunc: newZkl3000Rc,
devType: rpc.DeviceTypeZKL3000RC,
timeout: 60,
transport: rpc.ConnectionTransportCP3000,
}, {
newFunc: newZkl3000Rcc,
devType: rpc.DeviceTypeZKL3000RCC,
timeout: 60,
transport: rpc.ConnectionTransportCP3000,
}, {
newFunc: newCrtmGateway,
devType: rpc.DeviceTypeCRTMGateway,
timeout: 60,
transport: rpc.ConnectionTransportCP3000,
}, {
newFunc: newGreenHub,
devType: rpc.DeviceTypeGRB3000,
timeout: 60,
transport: rpc.ConnectionTransportCP3000,
}, {
newFunc: newCrtmSensor,
devType: rpc.DeviceTypeCRTMSensor,
timeout: 60,
transport: rpc.ConnectionTransportXBee,
},
}
for _, tc := range testCases {
// Transfer tc to local variable for fixing schope
tc := tc
t.Run(string(tc.devType), func(t *testing.T) {
testData := testenv.CreateTestData(t)
if tc.transport == rpc.ConnectionTransportCP3000 {
testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{
Type: cp3000.TypeCommand,
Command: cp3000.CommandRetrieve,
Params: []string{"VERSION[IMSI]"},
}, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{"imsi"}})
testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{
Type: cp3000.TypeCommand,
Command: cp3000.CommandRetrieve,
Params: []string{"VERSION[SIM]"},
}, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{"sim"}})
testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{
Type: cp3000.TypeCommand,
Command: cp3000.CommandRetrieve,
Params: []string{"VERSION[IMEI]"},
}, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{"imei"}})
testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{
Type: cp3000.TypeCommand,
Command: cp3000.CommandRetrieve,
Params: []string{"DBSERVER"},
}, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{"dbserver"}})
testData.Cp3000Connection.AssertReqRep(&cp3000.Msg{
Type: cp3000.TypeCommand,
Command: cp3000.CommandRetrieve,
Params: []string{"GPRS"},
}, &cp3000.Msg{Type: cp3000.TypeReply, Command: cp3000.Command("00"), Params: []string{"gprs"}})
}
registerCP3000Device(t, testData, tc.newFunc)
response := testData.ReqRep(rpc.ClassMethodConnectionInfo)
require.Nil(t, response.Error)
var information []rpc.ConnectionInfo
require.Nil(t, response.Result.Unmarshal(&information))
require.Len(t, information, 1)
require.Equal(t, tc.timeout, information[0].Timeout)
require.Equal(t, tc.transport, information[0].Transport)
require.Nil(t, information[0].Service)
require.Nil(t, information[0].Can)
require.Nil(t, information[0].Cellular)
require.Nil(t, information[0].LoRa)
if tc.transport == rpc.ConnectionTransportCP3000 {
require.Nil(t, information[0].XBee)
require.NotNil(t, information[0].CP3000)
require.Equal(t, rpc.ConnectionInfoCP3000{
DatabaseID: 2,
Imsi: "imsi",
Iccid: "sim",
Imei: "imei",
GPRSApn: "gprs",
Endpoint: "dbserver",
}, *information[0].CP3000)
} else if tc.transport == rpc.ConnectionTransportXBee {
require.Nil(t, information[0].CP3000)
require.NotNil(t, information[0].XBee)
require.Equal(t, rpc.ConnectionInfoXBee{}, *information[0].XBee)
}
testData.Finish()
})
}
}
func TestConfigInfoSensorInfo(t *testing.T) {
// nolint: dupl
testCases := []struct {
newFunc createDeviceFunc
devType rpc.DeviceType
configs []rpc.ResultConfigInfoItem
sensors []rpc.ResultInfoItem
}{
{
newFunc: newZkl3000,
devType: rpc.DeviceTypeZKL3000,
configs: []rpc.ResultConfigInfoItem{rpc.ConfigEndpoint.Info()},
sensors: []rpc.ResultInfoItem{
rpc.SensorBattery1Voltage.Info(),
rpc.SensorBattery1State.Info(),
rpc.SensorBattery2Voltage.Info(),
rpc.SensorBattery2State.Info(),
rpc.SensorGPS.Info(),
rpc.SensorRSSI.Info(),
rpc.SensorBER.Info(),
rpc.ZKLSensorDetectionQuality.Info(),
rpc.ZKLSensorDetection.Info(),
rpc.ZKLSensorMeasurement.Info(),
rpc.ZKLSensorBa.Info(),
rpc.ZKLSensorFrequency.Info(),
rpc.ZKLSensorRMS.Info(),
rpc.ZKLSensorBAAutocal.Info(),
rpc.ZKLSensorTempOnboard.Info(),
rpc.ZKLSensorTempNTC.Info(),
},
}, {
newFunc: newZkl3000Rc,
devType: rpc.DeviceTypeZKL3000RC,
configs: []rpc.ResultConfigInfoItem{rpc.ConfigEndpoint.Info(), rpc.ConfigToken.Info(), rpc.ConfigActive.Info()},
sensors: []rpc.ResultInfoItem{
rpc.SensorBattery1Voltage.Info(),
rpc.SensorBattery1State.Info(),
rpc.SensorBattery2Voltage.Info(),
rpc.SensorBattery2State.Info(),
rpc.SensorCharger1State.Info(),
rpc.SensorGPS.Info(),
rpc.SensorRSSI.Info(),
rpc.SensorBER.Info(),
rpc.ZKLSensorDetectionQuality.Info(),
rpc.ZKLSensorDetection.Info(),
rpc.ZKLSensorMeasurement.Info(),
rpc.ZKLSensorBa.Info(),
rpc.ZKLSensorFrequency.Info(),
rpc.ZKLSensorRMS.Info(),
rpc.ZKLSensorBAAutocal.Info(),
rpc.ZKLSensorTempOnboard.Info(),
rpc.ZKLSensorTempNTC.Info(),
rpc.ZKLRCSensorSectionsShort.Info(),
rpc.ZKLRCSensorSectionsBattery.Info(),
rpc.ZKLRCSensorSwitchShort.Info(),
rpc.ZKLRCSensorKeySwitch.Info(),
},
}, {
newFunc: newZkl3000Rcc,
devType: rpc.DeviceTypeZKL3000RCC,
configs: []rpc.ResultConfigInfoItem{rpc.ConfigEndpoint.Info(), rpc.ConfigToken.Info(), rpc.ConfigActive.Info()},
sensors: []rpc.ResultInfoItem{
rpc.SensorBattery1Voltage.Info(),
rpc.SensorBattery1State.Info(),
rpc.SensorBattery2Voltage.Info(),
rpc.SensorBattery2State.Info(),
rpc.SensorCharger1State.Info(),
rpc.SensorGPS.Info(),
rpc.SensorRSSI.Info(),
rpc.SensorBER.Info(),
rpc.ZKLSensorDetectionQuality.Info(),
rpc.ZKLSensorDetection.Info(),
rpc.ZKLSensorMeasurement.Info(),
rpc.ZKLSensorBa.Info(),
rpc.ZKLSensorFrequency.Info(),
rpc.ZKLSensorRMS.Info(),
rpc.ZKLSensorBAAutocal.Info(),
rpc.ZKLSensorTempOnboard.Info(),
rpc.ZKLSensorTempNTC.Info(),
rpc.ZKLRCSensorSectionsShort.Info(),
rpc.ZKLRCSensorSectionsBattery.Info(),
rpc.ZKLRCSensorSwitchShort.Info(),
rpc.ZKLRCSensorKeySwitch.Info(),
},
}, {
newFunc: newCrtmGateway,
devType: rpc.DeviceTypeCRTMGateway,
configs: []rpc.ResultConfigInfoItem{rpc.ConfigEndpoint.Info()},
sensors: []rpc.ResultInfoItem{
rpc.SensorBattery1Voltage.Info(),
rpc.SensorBattery1State.Info(),
rpc.SensorRSSI.Info(),
rpc.SensorBER.Info(),
rpc.GatewaySensorTemperature1.Info(),
},
}, {
newFunc: newGreenHub,
devType: rpc.DeviceTypeGRB3000,
configs: []rpc.ResultConfigInfoItem{rpc.ConfigEndpoint.Info()},
sensors: []rpc.ResultInfoItem{
rpc.SensorBattery1Voltage.Info(),
rpc.SensorBattery1State.Info(),
rpc.SensorRSSI.Info(),
rpc.SensorBER.Info(),
rpc.GatewaySensorTemperature1.Info(),
},
}, {
newFunc: newCrtmSensor,
devType: rpc.DeviceTypeCRTMSensor,
configs: []rpc.ResultConfigInfoItem{rpc.ConfigEndpoint.Info()},
sensors: []rpc.ResultInfoItem{
rpc.SensorBattery1Voltage.Info(),
rpc.SensorBattery1State.Info(),
rpc.SensorRSSI.Info(),
rpc.SensorBER.Info(),
rpc.CRTMSensorTemperature1.Info(),
rpc.CRTMSensorTemperature2.Info(),
rpc.CRTMSensorRailContact.Info(),
rpc.CRTMSensorRailContactSleep.Info(),
rpc.CRTMSensorAcceleration.Info(),
},
},
}
for _, tc := range testCases {
// Transfer tc to local variable for fixing schope
tc := tc
classmethodTestCase := []struct {
classMethod rpc.ClassMethod
expect interface{}
unmarshal interface{}
}{
{rpc.ClassMethodConfigInfo, tc.configs, &[]rpc.ResultConfigInfoItem{}},
{rpc.ClassMethodSensorInfo, tc.sensors, &[]rpc.ResultInfoItem{}},
}
for _, classmethod := range classmethodTestCase {
// Transfer tc to local variable for fixing schope
classmethod := classmethod
t.Run(fmt.Sprintf("%s - %s", tc.devType, classmethod.classMethod), func(t *testing.T) {
testData := testenv.CreateTestData(t)
registerCP3000Device(t, testData, tc.newFunc)
response := testData.ReqRep(classmethod.classMethod)
require.Nil(t, response.Error)
require.Nil(t, response.Result.Unmarshal(classmethod.unmarshal))
switch data := classmethod.unmarshal.(type) {
case *[]rpc.ResultConfigInfoItem:
require.ElementsMatch(t, classmethod.expect, *data)
case *[]rpc.ResultInfoItem:
require.ElementsMatch(t, classmethod.expect, *data)
}
testData.Finish()
})
}
}
}
func TestNotSupportedOperations(t *testing.T) {
testCases := []struct {
newFunc createDeviceFunc
devType rpc.DeviceType
}{
{
newFunc: newZkl3000,
devType: rpc.DeviceTypeZKL3000,
}, {
newFunc: newZkl3000Rc,
devType: rpc.DeviceTypeZKL3000RC,
}, {
newFunc: newZkl3000Rcc,
devType: rpc.DeviceTypeZKL3000RCC,
}, {
newFunc: newCrtmGateway,
devType: rpc.DeviceTypeCRTMGateway,
}, {
newFunc: newGreenHub,
devType: rpc.DeviceTypeGRB3000,
}, {
newFunc: newCrtmSensor,
devType: rpc.DeviceTypeCRTMSensor,
},
}
for _, tc := range testCases {
// Transfer tc to local variable for fixing schope
tc := tc
t.Run(string(tc.devType), func(t *testing.T) {
testData := testenv.CreateTestData(t)
registerCP3000Device(t, testData, tc.newFunc)
response := testData.ReqRep(rpc.ClassMethodActionInfo)
require.NotNil(t, response.Error)
testData = testenv.CreateTestData(t)
registerCP3000Device(t, testData, tc.newFunc)
response = testData.ReqRep(rpc.ClassMethodNotifyInfo)
require.NotNil(t, response.Error)
})
}
}