1
0
mirror of https://github.com/hybridgroup/gobot.git synced 2025-04-26 13:48:49 +08:00
hybridgroup.gobot/drivers/aio/analog_actuator_driver_test.go
2023-11-23 19:01:42 +01:00

165 lines
5.7 KiB
Go

//nolint:forcetypeassert // ok here
package aio
import (
"strings"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestNewAnalogActuatorDriver(t *testing.T) {
// arrange
const pin = "47"
a := newAioTestAdaptor()
// act
d := NewAnalogActuatorDriver(a, pin)
// assert: driver attributes
assert.IsType(t, &AnalogActuatorDriver{}, d)
assert.NotNil(t, d.driverCfg)
assert.True(t, strings.HasPrefix(d.Name(), "AnalogActuator"))
assert.Equal(t, a, d.Connection())
require.NoError(t, d.afterStart())
require.NoError(t, d.beforeHalt())
assert.NotNil(t, d.Commander)
assert.NotNil(t, d.mutex)
// assert: actuator attributes
assert.Equal(t, pin, d.Pin())
assert.InDelta(t, 0.0, d.lastValue, 0, 0)
assert.Equal(t, 0, d.lastRawValue)
require.NotNil(t, d.actuatorCfg)
assert.NotNil(t, d.actuatorCfg.scale)
}
func TestNewAnalogActuatorDriver_options(t *testing.T) {
// This is a general test, that options are applied in constructor by using the common WithName() option, least one
// option of this driver and one of another driver (which should lead to panic). Further tests for options can also
// be done by call of "WithOption(val).apply(cfg)".
// arrange
myName := "relay 1"
myScaler := func(input float64) int { return int(2 * input) }
panicFunc := func() {
NewAnalogActuatorDriver(newAioTestAdaptor(), "1", WithName("crazy"), WithSensorCyclicRead(10*time.Millisecond))
}
// act
d := NewAnalogActuatorDriver(newAioTestAdaptor(), "1", WithName(myName), WithActuatorScaler(myScaler))
// assert
assert.Equal(t, myName, d.Name())
assert.Equal(t, 3, d.actuatorCfg.scale(1.5))
assert.PanicsWithValue(t, "'read interval option for analog sensors' can not be applied on 'crazy'", panicFunc)
}
func TestAnalogActuatorWriteRaw(t *testing.T) {
tests := map[string]struct {
inputVal int
simulateWriteErr bool
wantWritten int
wantErr string
}{
"write_raw": {inputVal: 100, wantWritten: 100},
"error_write": {inputVal: 12345, wantWritten: 12345, simulateWriteErr: true, wantErr: "write error"},
}
for name, tc := range tests {
t.Run(name, func(t *testing.T) {
// arrange
const pin = "47"
a := newAioTestAdaptor()
d := NewAnalogActuatorDriver(a, pin)
a.simulateWriteError = tc.simulateWriteErr
a.written = nil // reset previous writes
// act
err := d.WriteRaw(tc.inputVal)
// assert
if tc.wantErr != "" {
require.EqualError(t, err, tc.wantErr)
assert.Empty(t, a.written)
} else {
require.NoError(t, err)
assert.Len(t, a.written, 1)
assert.Equal(t, pin, a.written[0].pin)
assert.Equal(t, tc.wantWritten, a.written[0].val)
}
})
}
}
func TestAnalogActuatorWriteRaw_AnalogWriteNotSupported(t *testing.T) {
// arrange
d := NewAnalogActuatorDriver(newAioTestAdaptor(), "1")
d.connection = &aioTestBareAdaptor{}
// act & assert
require.EqualError(t, d.WriteRaw(3), "AnalogWrite is not supported by the platform 'bare'")
}
func TestAnalogActuatorWrite_SetScaler(t *testing.T) {
tests := map[string]struct {
fromMin float64
fromMax float64
input float64
wantWritten int
}{
"byte_range_min": {fromMin: 0, fromMax: 255, input: 0, wantWritten: 0},
"byte_range_max": {fromMin: 0, fromMax: 255, input: 255, wantWritten: 255},
"signed_percent_range_min": {fromMin: -100, fromMax: 100, input: -100, wantWritten: 0},
"signed_percent_range_mid": {fromMin: -100, fromMax: 100, input: 0, wantWritten: 127},
"signed_percent_range_max": {fromMin: -100, fromMax: 100, input: 100, wantWritten: 255},
"voltage_range_min": {fromMin: 0, fromMax: 5.1, input: 0, wantWritten: 0},
"voltage_range_nearmin": {fromMin: 0, fromMax: 5.1, input: 0.02, wantWritten: 1},
"voltage_range_mid": {fromMin: 0, fromMax: 5.1, input: 2.55, wantWritten: 127},
"voltage_range_nearmax": {fromMin: 0, fromMax: 5.1, input: 5.08, wantWritten: 254},
"voltage_range_max": {fromMin: 0, fromMax: 5.1, input: 5.1, wantWritten: 255},
"upscale": {fromMin: 0, fromMax: 24, input: 12, wantWritten: 127},
"below_min": {fromMin: -10, fromMax: 10, input: -11, wantWritten: 0},
"exceed_max": {fromMin: 0, fromMax: 20, input: 21, wantWritten: 255},
}
const pin = "7"
a := newAioTestAdaptor()
d := NewAnalogActuatorDriver(a, pin)
for name, tc := range tests {
t.Run(name, func(t *testing.T) {
// arrange
d.SetScaler(AnalogActuatorLinearScaler(tc.fromMin, tc.fromMax, 0, 255))
a.written = nil // reset previous writes
// act
err := d.Write(tc.input)
// assert
require.NoError(t, err)
assert.Len(t, a.written, 1)
assert.Equal(t, pin, a.written[0].pin)
assert.Equal(t, tc.wantWritten, a.written[0].val)
})
}
}
func TestAnalogActuatorCommands_WithActuatorScaler(t *testing.T) {
// arrange
const pin = "8"
a := newAioTestAdaptor()
d := NewAnalogActuatorDriver(a, pin, WithActuatorScaler(func(input float64) int { return int((input + 3) / 2.5) }))
a.written = nil // reset previous writes
// act & assert: WriteRaw
err := d.Command("WriteRaw")(map[string]interface{}{"val": "100"})
assert.Nil(t, err)
assert.Len(t, a.written, 1)
assert.Equal(t, pin, a.written[0].pin)
assert.Equal(t, 100, a.written[0].val)
assert.Equal(t, 100, d.RawValue())
assert.InDelta(t, 0.0, d.Value(), 0.0)
// act & assert: Write
err = d.Command("Write")(map[string]interface{}{"val": "247.0"})
assert.Nil(t, err)
assert.Len(t, a.written, 2)
assert.Equal(t, pin, a.written[1].pin)
assert.Equal(t, 100, a.written[1].val)
assert.Equal(t, 100, d.RawValue())
assert.InDelta(t, 247.0, d.Value(), 0.0)
// arrange & act & assert: Write with error
a.simulateWriteError = true
err = d.Command("Write")(map[string]interface{}{"val": "247.0"})
require.EqualError(t, err.(error), "write error")
}