1
0
mirror of https://github.com/hybridgroup/gobot.git synced 2025-04-26 13:48:49 +08:00
hybridgroup.gobot/drivers/i2c/pca9501_driver_test.go
2022-12-10 13:10:23 +01:00

425 lines
10 KiB
Go

package i2c
import (
"errors"
"strings"
"testing"
"gobot.io/x/gobot"
"gobot.io/x/gobot/gobottest"
)
// this ensures that the implementation is based on i2c.Driver, which implements the gobot.Driver
// and tests all implementations, so no further tests needed here for gobot.Driver interface
var _ gobot.Driver = (*PCA9501Driver)(nil)
var (
pinVal = map[string]interface{}{
"pin": uint8(7),
"val": uint8(0),
}
pin = map[string]interface{}{
"pin": uint8(7),
}
addressVal = map[string]interface{}{
"address": uint8(15),
"val": uint8(7),
}
address = map[string]interface{}{
"address": uint8(15),
}
)
func initPCA9501WithStubbedAdaptor() (*PCA9501Driver, *i2cTestAdaptor) {
a := newI2cTestAdaptor()
d := NewPCA9501Driver(a)
if err := d.Start(); err != nil {
panic(err)
}
return d, a
}
func TestNewPCA9501Driver(t *testing.T) {
// arrange, act
var di interface{} = NewPCA9501Driver(newI2cTestAdaptor())
// assert
d, ok := di.(*PCA9501Driver)
if !ok {
t.Errorf("NewPCA9501Driver() should have returned a *PCA9501Driver")
}
gobottest.Refute(t, d.Driver, nil)
gobottest.Assert(t, strings.HasPrefix(d.Name(), "PCA9501"), true)
gobottest.Assert(t, d.defaultAddress, 0x3f)
}
func TestPCA9501Options(t *testing.T) {
// This is a general test, that options are applied in constructor by using the common WithBus() option and
// least one of this driver. Further tests for options can also be done by call of "WithOption(val)(d)".
d := NewPCA9501Driver(newI2cTestAdaptor(), WithBus(2))
gobottest.Assert(t, d.GetBusOrDefault(1), 2)
}
func TestPCA9501CommandsWriteGPIO(t *testing.T) {
// arrange
d, a := initPCA9501WithStubbedAdaptor()
a.i2cReadImpl = func(b []byte) (int, error) {
return len(b), nil
}
a.i2cWriteImpl = func([]byte) (int, error) {
return 0, nil
}
// act
result := d.Command("WriteGPIO")(pinVal)
// assert
gobottest.Assert(t, result.(map[string]interface{})["err"], nil)
}
func TestPCA9501CommandsReadGPIO(t *testing.T) {
// arrange
d, a := initPCA9501WithStubbedAdaptor()
a.i2cReadImpl = func(b []byte) (int, error) {
return len(b), nil
}
// act
result := d.Command("ReadGPIO")(pin)
// assert
gobottest.Assert(t, result.(map[string]interface{})["err"], nil)
}
func TestPCA9501CommandsWriteEEPROM(t *testing.T) {
// arrange
d, a := initPCA9501WithStubbedAdaptor()
a.i2cWriteImpl = func([]byte) (int, error) {
return 0, nil
}
// act
result := d.Command("WriteEEPROM")(addressVal)
// assert
gobottest.Assert(t, result.(map[string]interface{})["err"], nil)
}
func TestPCA9501CommandsReadEEPROM(t *testing.T) {
// arrange
d, a := initPCA9501WithStubbedAdaptor()
a.i2cWriteImpl = func([]byte) (int, error) {
return 0, nil
}
a.i2cReadImpl = func(b []byte) (int, error) {
return len(b), nil
}
// act
result := d.Command("ReadEEPROM")(address)
// assert
gobottest.Assert(t, result.(map[string]interface{})["err"], nil)
}
func TestPCA9501WriteGPIO(t *testing.T) {
var tests = map[string]struct {
setVal uint8
ioDirAllInput uint8
ioStateAllInput uint8
pin uint8
wantPin uint8
wantState uint8
}{
"clear_bit": {
setVal: 0,
ioDirAllInput: 0xF1,
ioStateAllInput: 0xF2,
pin: 6,
wantPin: 0xB1,
wantState: 0xB2,
},
"set_bit": {
setVal: 2,
ioDirAllInput: 0x1F,
ioStateAllInput: 0x20,
pin: 3,
wantPin: 0x17,
wantState: 0x28,
},
}
for name, tc := range tests {
t.Run(name, func(t *testing.T) {
// arrange
d, a := initPCA9501WithStubbedAdaptor()
// prepare all reads
numCallsRead := 0
a.i2cReadImpl = func(b []byte) (int, error) {
numCallsRead++
if numCallsRead == 1 {
// first call read current io direction of all pins
b[0] = tc.ioDirAllInput
}
if numCallsRead == 2 {
// second call read current state of all pins
b[0] = tc.ioStateAllInput
}
return len(b), nil
}
// act
err := d.WriteGPIO(tc.pin, tc.setVal)
// assert
gobottest.Assert(t, err, nil)
gobottest.Assert(t, numCallsRead, 2)
gobottest.Assert(t, len(a.written), 2)
gobottest.Assert(t, a.written[0], tc.wantPin)
gobottest.Assert(t, a.written[1], tc.wantState)
})
}
}
func TestPCA9501WriteGPIOErrorAtWriteDirection(t *testing.T) {
// arrange
d, a := initPCA9501WithStubbedAdaptor()
wantErr := errors.New("write error")
// prepare all reads
numCallsRead := 0
a.i2cReadImpl = func(b []byte) (int, error) {
numCallsRead++
return len(b), nil
}
// prepare all writes
numCallsWrite := 0
a.i2cWriteImpl = func([]byte) (int, error) {
numCallsWrite++
if numCallsWrite == 1 {
// first call writes the CTRL register for port direction
return 0, wantErr
}
return 0, nil
}
// act
err := d.WriteGPIO(7, 0)
// assert
gobottest.Assert(t, err, wantErr)
gobottest.Assert(t, numCallsRead < 2, true)
gobottest.Assert(t, numCallsWrite, 1)
}
func TestPCA9501WriteGPIOErrorAtWriteValue(t *testing.T) {
// arrange
d, a := initPCA9501WithStubbedAdaptor()
wantErr := errors.New("write error")
// prepare all reads
a.i2cReadImpl = func(b []byte) (int, error) {
return len(b), nil
}
// prepare all writes
numCallsWrite := 0
a.i2cWriteImpl = func([]byte) (int, error) {
numCallsWrite++
if numCallsWrite == 2 {
// second call writes the value to IO port
return 0, wantErr
}
return 0, nil
}
// act
err := d.WriteGPIO(7, 0)
// assert
gobottest.Assert(t, err, wantErr)
gobottest.Assert(t, numCallsWrite, 2)
}
func TestPCA9501ReadGPIO(t *testing.T) {
var tests = map[string]struct {
ctrlState uint8
want uint8
}{
"pin_is_set": {ctrlState: 0x80, want: 1},
"pin_is_not_set": {ctrlState: 0x7F, want: 0},
}
for name, tc := range tests {
t.Run(name, func(t *testing.T) {
// arrange
const (
pin = uint8(7)
wantCtrlState = uint8(0x80)
)
d, a := initPCA9501WithStubbedAdaptor()
// prepare all reads
numCallsRead := 0
a.i2cReadImpl = func(b []byte) (int, error) {
numCallsRead++
if numCallsRead == 1 {
// current state of io
b[0] = 0x00
}
if numCallsRead == 2 {
b[0] = tc.ctrlState
}
return len(b), nil
}
// act
got, err := d.ReadGPIO(pin)
// assert
gobottest.Assert(t, err, nil)
gobottest.Assert(t, got, tc.want)
gobottest.Assert(t, numCallsRead, 2)
gobottest.Assert(t, len(a.written), 1)
gobottest.Assert(t, a.written[0], wantCtrlState)
})
}
}
func TestPCA9501ReadGPIOErrorAtReadDirection(t *testing.T) {
// arrange
d, a := initPCA9501WithStubbedAdaptor()
wantErr := errors.New("read error")
// prepare all reads
numCallsRead := 0
a.i2cReadImpl = func(b []byte) (int, error) {
numCallsRead++
if numCallsRead == 1 {
// first read gets the CTRL register for pin direction
return 0, wantErr
}
return len(b), nil
}
// prepare all writes
numCallsWrite := 0
a.i2cWriteImpl = func([]byte) (int, error) {
numCallsWrite++
return 0, nil
}
// act
_, err := d.ReadGPIO(1)
// assert
gobottest.Assert(t, err, wantErr)
gobottest.Assert(t, numCallsRead, 1)
gobottest.Assert(t, numCallsWrite, 0)
}
func TestPCA9501ReadGPIOErrorAtReadValue(t *testing.T) {
// arrange
d, a := initPCA9501WithStubbedAdaptor()
wantErr := errors.New("read error")
// prepare all reads
numCallsRead := 0
a.i2cReadImpl = func(b []byte) (int, error) {
numCallsRead++
if numCallsRead == 2 {
// second read gets the value from IO port
return 0, wantErr
}
return len(b), nil
}
// prepare all writes
numCallsWrite := 0
a.i2cWriteImpl = func([]byte) (int, error) {
numCallsWrite++
return 0, nil
}
// act
_, err := d.ReadGPIO(2)
// assert
gobottest.Assert(t, err, wantErr)
gobottest.Assert(t, numCallsWrite, 1)
}
func TestPCA9501WriteEEPROM(t *testing.T) {
// arrange
const (
addressEEPROM = uint8(0x52)
want = uint8(0x25)
)
d, a := initPCA9501WithStubbedAdaptor()
// prepare all writes
numCallsWrite := 0
a.i2cWriteImpl = func([]byte) (int, error) {
numCallsWrite++
return 0, nil
}
// act
err := d.WriteEEPROM(addressEEPROM, want)
// assert
gobottest.Assert(t, err, nil)
gobottest.Assert(t, numCallsWrite, 1)
gobottest.Assert(t, a.written[0], addressEEPROM)
gobottest.Assert(t, a.written[1], want)
}
func TestPCA9501ReadEEPROM(t *testing.T) {
// arrange
const (
addressEEPROM = uint8(51)
want = uint8(0x44)
)
d, a := initPCA9501WithStubbedAdaptor()
// prepare all writes
numCallsWrite := 0
a.i2cWriteImpl = func(b []byte) (int, error) {
numCallsWrite++
return 0, nil
}
// prepare all reads
numCallsRead := 0
a.i2cReadImpl = func(b []byte) (int, error) {
numCallsRead++
b[0] = want
return len(b), nil
}
// act
val, err := d.ReadEEPROM(addressEEPROM)
// assert
gobottest.Assert(t, err, nil)
gobottest.Assert(t, val, want)
gobottest.Assert(t, numCallsWrite, 1)
gobottest.Assert(t, a.written[0], addressEEPROM)
gobottest.Assert(t, numCallsRead, 1)
}
func TestPCA9501ReadEEPROMErrorWhileWriteAddress(t *testing.T) {
// arrange
d, a := initPCA9501WithStubbedAdaptor()
wantErr := errors.New("error while write")
// prepare all writes
a.i2cWriteImpl = func([]byte) (int, error) {
return 0, wantErr
}
// prepare all reads
numCallsRead := 0
a.i2cReadImpl = func(b []byte) (int, error) {
numCallsRead++
return len(b), nil
}
// act
_, err := d.ReadEEPROM(15)
// assert
gobottest.Assert(t, err, wantErr)
gobottest.Assert(t, numCallsRead, 0)
}
func TestPCA9501ReadEEPROMErrorWhileReadValue(t *testing.T) {
// arrange
d, a := initPCA9501WithStubbedAdaptor()
wantErr := errors.New("error while read")
// prepare all writes
numCallsWrite := 0
a.i2cWriteImpl = func([]byte) (int, error) {
numCallsWrite++
return 0, nil
}
// prepare all reads
a.i2cReadImpl = func(b []byte) (int, error) {
return len(b), wantErr
}
// act
_, err := d.ReadEEPROM(15)
// assert
gobottest.Assert(t, numCallsWrite, 1)
gobottest.Assert(t, err, wantErr)
}
func TestPCA9501_initialize(t *testing.T) {
// arrange
const want = 0x7f
d, a := initPCA9501WithStubbedAdaptor()
// act
err := d.initialize()
// assert
gobottest.Assert(t, err, nil)
gobottest.Assert(t, a.address, want)
}