blob: 744d136d495b71e24597e6c9fa8f0ccf8dbd5037 [file] [log] [blame]
package sensors
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
"go.skia.org/infra/go/serial/mocks"
"go.skia.org/infra/go/skerr"
)
const invalidPingResponseVal byte = pingResponseVal - 1
func deviceFromMock(p *mocks.Port) DLPTH1C {
return DLPTH1C{
portName: "mock",
port: p,
}
}
func deviceFromFake(p *fakeSerialPort) DLPTH1C {
return DLPTH1C{
portName: "fake",
port: p,
}
}
func TestOpen_InvalidPortName_ReturnsError(t *testing.T) {
d, err := NewDLPTH1C("<Invalid Serial Port Name>")
assert.Nil(t, d)
assert.Error(t, err)
}
func TestPing_ValidDeviceResponse_Success(t *testing.T) {
fsp := (&fakeSerialPort{}).setReadData(pingResponseVal)
d := deviceFromFake(fsp)
require.NoError(t, d.Ping())
assert.Equal(t, []byte{pingCmd}, fsp.getWrittenData())
}
func TestPing_InvalidDeviceResponse_ReturnsError(t *testing.T) {
fsp := (&fakeSerialPort{}).setReadData(invalidPingResponseVal)
d := deviceFromFake(fsp)
assert.Error(t, d.Ping())
assert.Equal(t, []byte{pingCmd}, fsp.getWrittenData())
}
func TestConfirmConnection_ValidPingResponse_Success(t *testing.T) {
test := func(name string, readData []byte, maxPings int) {
t.Run(name, func(t *testing.T) {
fsp := (&fakeSerialPort{}).setReadData(readData...)
d := deviceFromFake(fsp)
err := d.ConfirmConnection(maxPings)
require.NoError(t, err)
})
}
test("FirstTime", []byte{pingResponseVal}, 1)
test("LastTime", []byte{invalidPingResponseVal, pingResponseVal}, 2)
}
func TestConfirmConnection_InvalidMaxPingCount_ReturnsError(t *testing.T) {
p := mocks.NewPort(t)
d := deviceFromMock(p)
assert.Error(t, d.ConfirmConnection(-1), "negative max pings")
assert.Error(t, d.ConfirmConnection(0), "zero max pings")
}
func TestConfirmConnection_InvalidPingResponse_ReturnsError(t *testing.T) {
test := func(name string, readData []byte, maxPings int) {
t.Run(name, func(t *testing.T) {
fsp := (&fakeSerialPort{}).setReadData(readData...)
d := deviceFromFake(fsp)
err := d.ConfirmConnection(maxPings)
require.Error(t, err)
})
}
test("FirstTime", []byte{invalidPingResponseVal}, 1)
test("LastTime", []byte{invalidPingResponseVal, invalidPingResponseVal}, 2)
}
func TestGetTemperature_ValuesInRange_Success(t *testing.T) {
test := func(name string, readData []byte, expectedTemp Temperature) {
t.Run(name, func(t *testing.T) {
fsp := (&fakeSerialPort{}).setReadData(readData...)
d := deviceFromFake(fsp)
actualTemp, err := d.GetTemperature()
require.NoError(t, err)
assert.Equal(t, expectedTemp, actualTemp)
assert.Equal(t, []byte{getTemperatureCmd}, fsp.getWrittenData())
})
}
test("MinValue", []byte{0x0, 0x0}, 0)
test("IntermediateValue", []byte{0x10, 0x68}, Temperature(42.0))
test("MaxValue", []byte{0xff, 0xff}, Temperature(655.35))
}
func TestGetHumidity_ValuesInRange_Success(t *testing.T) {
test := func(name string, readData []byte, expectedHumidity Humidity) {
t.Run(name, func(t *testing.T) {
fsp := (&fakeSerialPort{}).setReadData(readData...)
d := deviceFromFake(fsp)
actualHumidity, err := d.GetHumidity()
require.NoError(t, err)
assert.Equal(t, expectedHumidity, actualHumidity)
assert.Equal(t, []byte{getHumidityCmd}, fsp.getWrittenData())
})
}
test("MinValue", []byte{0x0, 0x0, 0x0}, 0)
test("IntermediateValue", []byte{0x0, 0xb8, 0x00}, Humidity(46.0))
test("MaxValue", []byte{0xff, 0xff, 0xff}, Humidity(16383.9990234375))
}
func TestGetHumidity_NoDeviceResponse_ReturnsError(t *testing.T) {
p := mocks.NewPort(t)
p.On("Read", mock.Anything).Return(0, skerr.Fmt("expected error"))
p.On("Write", mock.Anything).Return(1, nil).Once()
d := deviceFromMock(p)
h, err := d.GetHumidity()
assert.Error(t, err)
assert.Zero(t, h)
}
func TestGetPressure_NoDeviceResponse_ReturnsError(t *testing.T) {
p := mocks.NewPort(t)
p.On("Read", mock.Anything).Return(0, skerr.Fmt("expected error"))
p.On("Write", mock.Anything).Return(1, nil).Once()
d := deviceFromMock(p)
pressure, err := d.GetPressure()
assert.Error(t, err)
assert.Zero(t, pressure)
}
func TestGetPressure_ValuesInRange_Success(t *testing.T) {
test := func(name string, readData []byte, expectedPressure Pressure) {
t.Run(name, func(t *testing.T) {
fsp := (&fakeSerialPort{}).setReadData(readData...)
d := deviceFromFake(fsp)
actualPressure, err := d.GetPressure()
require.NoError(t, d.Close())
require.NoError(t, err)
assert.Equal(t, expectedPressure, actualPressure)
assert.Equal(t, []byte{getPressureCmd}, fsp.getWrittenData())
})
}
test("MinValue", []byte{0x0, 0x0, 0x0, 0x0}, 0)
test("IntermediateValue", []byte{0x01, 0x75, 0xd4, 0x00}, Pressure(957.0))
test("MaxValue", []byte{0xff, 0xff, 0xff, 0xff}, Pressure(167772.159))
}
func TestGetTilt_ValuesInRange_Success(t *testing.T) {
test := func(name string, readData []byte, expectedTilt Tilt) {
t.Run(name, func(t *testing.T) {
fsp := (&fakeSerialPort{}).setReadData(readData...)
d := deviceFromFake(fsp)
actualTilt, err := d.GetTilt()
require.NoError(t, d.Close())
require.NoError(t, err)
assert.Equal(t, expectedTilt, actualTilt)
assert.Equal(t, []byte{getTiltCmd}, fsp.getWrittenData())
})
}
test("ZeroValues", []byte{0x0, 0x0, 0x0}, [3]Angle{0, 0, 0})
test("PositiveValues", []byte{0x7, 0x15, 0x7f}, [3]Angle{7, 21, 127})
test("NegativeValues", []byte{0xf9, 0xeb, 0x80}, [3]Angle{-7, -21, -128})
test("MaxValues", []byte{0xff, 0xff, 0xff}, [3]Angle{-1, -1, -1})
}
func TestGetTilt_NoDeviceResponse_ReturnsError(t *testing.T) {
p := mocks.NewPort(t)
p.On("Read", mock.Anything).Return(0, skerr.Fmt("expected error"))
p.On("Write", mock.Anything).Return(1, nil)
d := deviceFromMock(p)
xyz, err := d.GetTilt()
assert.Error(t, err)
assert.Equal(t, xyz, Tilt([3]Angle{0, 0, 0}))
}
// The private readFrequencies() function is used by several public functions.
func TestReadFrequencies_ValuesInRange_Success(t *testing.T) {
test := func(name string, readData []byte, expectedFrequencies Frequencies) {
t.Run(name, func(t *testing.T) {
fsp := (&fakeSerialPort{}).setReadData(readData...)
d := deviceFromFake(fsp)
actualFrequencies, err := d.readFrequencies(getSoundCmd)
require.NoError(t, d.Close())
require.NoError(t, err)
assert.Equal(t, expectedFrequencies, actualFrequencies)
assert.Equal(t, []byte{getSoundCmd}, fsp.getWrittenData())
})
}
test("ZeroValues", make([]byte, 24), Frequencies{
Fundamental: Peak{},
Peaks: [5]Peak{},
})
// This data should return the same values in the Sound section (pg. 7)
// of the datasheet.
test("IntermediateValues", []byte{
0x04, 0x1e, 0x1c, 0xa2, // fundamental (1054 Hz, 73.3)
0x08, 0x16, 0x11, 0xed, // peak 2 (2070 Hz, 45.89)
0x01, 0x11, 0x11, 0x2e, // peak 3 (273 Hz, 43.98)
0x05, 0xa5, 0x0f, 0x6d, // peak 4 (1445 Hz, 39.49)
0x02, 0xe6, 0x0e, 0xb9, // peak 5 (742 Hz, 37.69)
0x06, 0xdd, 0x0e, 0x63, // peak 6 (1757 Hz, 36.83)
}, Frequencies{
Fundamental: Peak{Freq: 1054, Amplitude: 73.3},
Peaks: [5]Peak{
{Freq: 2070, Amplitude: 45.89},
{Freq: 273, Amplitude: 43.98},
{Freq: 1445, Amplitude: 39.49},
{Freq: 742, Amplitude: 37.69},
{Freq: 1757, Amplitude: 36.83}},
})
test("MaxValues", []byte{
0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff,
}, Frequencies{
Fundamental: Peak{Freq: 65535, Amplitude: 655.35},
Peaks: [5]Peak{
{Freq: 65535, Amplitude: 655.35},
{Freq: 65535, Amplitude: 655.35},
{Freq: 65535, Amplitude: 655.35},
{Freq: 65535, Amplitude: 655.35},
{Freq: 65535, Amplitude: 655.35}},
})
}
func TestReadFrequencies_NoDeviceResponse_ReturnsError(t *testing.T) {
p := mocks.NewPort(t)
p.On("Read", mock.Anything).Return(0, skerr.Fmt("expected error"))
p.On("Write", mock.Anything).Return(1, nil).Once()
d := deviceFromMock(p)
f, err := d.readFrequencies(getSoundCmd)
assert.Error(t, err)
assert.Zero(t, f.Fundamental.Freq)
assert.Zero(t, f.Fundamental.Amplitude)
for i := 0; i < len(f.Peaks); i++ {
assert.Zero(t, f.Peaks[i].Freq)
assert.Zero(t, f.Peaks[i].Amplitude)
}
}
func TestGetVibrationX_CorrectCommandSent(t *testing.T) {
// This function uses the common readFrequencies() function which
// is tested elsewhere. Only verify the correct command is being
// sent.
fsp := (&fakeSerialPort{}).setReadData(make([]byte, 24)...)
d := deviceFromFake(fsp)
_, err := d.GetVibrationX()
require.NoError(t, err)
assert.Equal(t, []byte{getVibrationXCmd}, fsp.getWrittenData())
}
func TestGetVibrationY_CorrectCommandSent(t *testing.T) {
// This function uses the common readFrequencies() function which
// is tested elsewhere. Only verify the correct command is being
// sent.
fsp := (&fakeSerialPort{}).setReadData(make([]byte, 24)...)
d := deviceFromFake(fsp)
_, err := d.GetVibrationY()
require.NoError(t, err)
assert.Equal(t, []byte{getVibrationYCmd}, fsp.getWrittenData())
}
func TestGetVibrationZ_CorrectCommandSent(t *testing.T) {
// This function uses the common readFrequencies() function which
// is tested elsewhere. Only verify the correct command is being
// sent.
fsp := (&fakeSerialPort{}).setReadData(make([]byte, 24)...)
d := deviceFromFake(fsp)
_, err := d.GetVibrationZ()
require.NoError(t, err)
assert.Equal(t, []byte{getVibrationZCmd}, fsp.getWrittenData())
}
func TestGetSound_CorrectCommandSent(t *testing.T) {
// This function uses the common readFrequencies() function which
// is tested elsewhere. Only verify the correct command is being
// sent.
fsp := (&fakeSerialPort{}).setReadData(make([]byte, 24)...)
d := deviceFromFake(fsp)
_, err := d.GetSound()
require.NoError(t, err)
assert.Equal(t, []byte{getSoundCmd}, fsp.getWrittenData())
}
func TestGetBroadbandSound_ValuesInRange_Success(t *testing.T) {
test := func(name string, readData []byte, expectedSoundLevel SoundLevel) {
t.Run(name, func(t *testing.T) {
fsp := (&fakeSerialPort{}).setReadData(readData...)
d := deviceFromFake(fsp)
actualSoundLevel, err := d.GetBroadbandSound()
require.NoError(t, d.Close())
require.NoError(t, err)
assert.Equal(t, expectedSoundLevel, actualSoundLevel)
assert.Equal(t, []byte{getBroadbandSoundCmd}, fsp.getWrittenData())
})
}
test("ZeroValue", []byte{0x0, 0x0}, 0)
test("PositiveValue", []byte{0x12, 0x75}, SoundLevel(47.25))
test("MaxValue", []byte{0xff, 0xff}, SoundLevel(655.35))
}
func TestGetBroadbandSound_NoDeviceResponse_ReturnsError(t *testing.T) {
p := mocks.NewPort(t)
p.On("Read", mock.Anything).Return(0, skerr.Fmt("expected error"))
p.On("Write", mock.Anything).Return(1, nil)
d := deviceFromMock(p)
s, err := d.GetBroadbandSound()
assert.Error(t, err)
assert.Zero(t, s)
}
func TestGetLight_ValuesInRange_Success(t *testing.T) {
test := func(name string, readData []byte, expected LightLevel) {
t.Run(name, func(t *testing.T) {
fsp := (&fakeSerialPort{}).setReadData(readData...)
d := deviceFromFake(fsp)
actual, err := d.GetLight()
require.NoError(t, d.Close())
require.NoError(t, err)
assert.InDelta(t, float64(expected), float64(actual), 0.01)
})
}
test("ZeroValue", []byte{0x0}, 0)
test("PositiveValue", []byte{128}, LightLevel(0.5))
test("MaxValue", []byte{0xff}, LightLevel(1.0))
}
func TestGetLight_NoDeviceResponse_ReturnsError(t *testing.T) {
p := mocks.NewPort(t)
p.On("Read", mock.Anything).Return(0, skerr.Fmt("expected error"))
p.On("Write", mock.Anything).Return(1, nil).Once()
d := deviceFromMock(p)
val, err := d.GetLight()
assert.Error(t, err)
assert.Zero(t, val)
}