1
0
mirror of https://github.com/hybridgroup/gobot.git synced 2025-04-27 13:48:56 +08:00

BUGFIX: tests with sysfs mocks, ReadBlockData, WriteBlockData

This commit is contained in:
Thomas Kohler 2022-10-30 18:55:52 +01:00 committed by GitHub
commit 8cadea2a6d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 957 additions and 392 deletions

View File

@ -13,16 +13,18 @@ EXAMPLES := $(EXAMPLES_NO_GOCV)
including_except := $(shell go list ./... | grep -v platforms/opencv)
# Run tests on nearly all directories without test cache
# TODO: set back to parallel running (remove "-p 1"), when issue #878 is fixed
test:
go test -count=1 -v $(including_except)
go test -p 1 -count=1 -v $(including_except)
# Run tests with race detection
test_race:
go test -race $(including_except)
# Test, generate and show coverage in browser
# TODO: set back to parallel running (remove "-p 1"), when issue #878 is fixed
test_cover:
go test -v $(including_except) -coverprofile=coverage.txt ; \
go test -p 1 -v $(including_except) -coverprofile=coverage.txt ; \
go tool cover -html=coverage.txt ; \
robeaux:

View File

@ -13,6 +13,8 @@ import (
"gobot.io/x/gobot/sysfs"
)
const dev = "/dev/i2c-1"
func syscallImpl(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) {
if (trap == syscall.SYS_IOCTL) && (a2 == sysfs.I2C_FUNCS) {
var funcPtr *uint64 = (*uint64)(unsafe.Pointer(a3))
@ -31,38 +33,37 @@ func syscallImplFail(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errn
}
func initI2CDevice() I2cDevice {
fs := sysfs.NewMockFilesystem([]string{
"/dev/i2c-1",
})
fs := sysfs.NewMockFilesystem([]string{dev})
sysfs.SetFilesystem(fs)
sysfs.SetSyscall(&sysfs.MockSyscall{Impl: syscallImpl})
sysfs.SetSyscall(&sysfs.MockSyscall{
Impl: syscallImpl,
})
i, _ := sysfs.NewI2cDevice("/dev/i2c-1")
i, _ := sysfs.NewI2cDevice(dev)
return i
}
func initI2CDeviceAddressError() I2cDevice {
fs := sysfs.NewMockFilesystem([]string{
"/dev/i2c-1",
})
sysfs.SetFilesystem(fs)
func cleanupI2CDevice() {
sysfs.SetFilesystem(&sysfs.NativeFilesystem{})
sysfs.SetSyscall(&sysfs.NativeSyscall{})
}
sysfs.SetSyscall(&sysfs.MockSyscall{
Impl: syscallImplFail,
})
i, _ := sysfs.NewI2cDevice("/dev/i2c-1")
func initI2CDeviceAddressError() I2cDevice {
fs := sysfs.NewMockFilesystem([]string{dev})
sysfs.SetFilesystem(fs)
sysfs.SetSyscall(&sysfs.MockSyscall{Impl: syscallImplFail})
i, _ := sysfs.NewI2cDevice(dev)
return i
}
func TestI2CAddress(t *testing.T) {
c := NewConnection(initI2CDevice(), 0x66)
defer cleanupI2CDevice()
gobottest.Assert(t, c.address, 0x66)
}
func TestI2CClose(t *testing.T) {
c := NewConnection(initI2CDevice(), 0x06)
defer cleanupI2CDevice()
gobottest.Assert(t, c.Close(), nil)
}
@ -74,102 +75,119 @@ func TestI2CRead(t *testing.T) {
func TestI2CReadAddressError(t *testing.T) {
c := NewConnection(initI2CDeviceAddressError(), 0x06)
defer cleanupI2CDevice()
_, err := c.Read([]byte{})
gobottest.Assert(t, err, errors.New("Setting address failed with syscall.Errno operation not permitted"))
}
func TestI2CWrite(t *testing.T) {
c := NewConnection(initI2CDevice(), 0x06)
defer cleanupI2CDevice()
i, _ := c.Write([]byte{0x01})
gobottest.Assert(t, i, 1)
}
func TestI2CWriteAddressError(t *testing.T) {
c := NewConnection(initI2CDeviceAddressError(), 0x06)
defer cleanupI2CDevice()
_, err := c.Write([]byte{0x01})
gobottest.Assert(t, err, errors.New("Setting address failed with syscall.Errno operation not permitted"))
}
func TestI2CReadByte(t *testing.T) {
c := NewConnection(initI2CDevice(), 0x06)
defer cleanupI2CDevice()
v, _ := c.ReadByte()
gobottest.Assert(t, v, uint8(0))
gobottest.Assert(t, v, uint8(0xFC))
}
func TestI2CReadByteAddressError(t *testing.T) {
c := NewConnection(initI2CDeviceAddressError(), 0x06)
defer cleanupI2CDevice()
_, err := c.ReadByte()
gobottest.Assert(t, err, errors.New("Setting address failed with syscall.Errno operation not permitted"))
}
func TestI2CReadByteData(t *testing.T) {
c := NewConnection(initI2CDevice(), 0x06)
defer cleanupI2CDevice()
v, _ := c.ReadByteData(0x01)
gobottest.Assert(t, v, uint8(0))
gobottest.Assert(t, v, uint8(0xFD))
}
func TestI2CReadByteDataAddressError(t *testing.T) {
c := NewConnection(initI2CDeviceAddressError(), 0x06)
defer cleanupI2CDevice()
_, err := c.ReadByteData(0x01)
gobottest.Assert(t, err, errors.New("Setting address failed with syscall.Errno operation not permitted"))
}
func TestI2CReadWordData(t *testing.T) {
c := NewConnection(initI2CDevice(), 0x06)
defer cleanupI2CDevice()
v, _ := c.ReadWordData(0x01)
gobottest.Assert(t, v, uint16(0))
gobottest.Assert(t, v, uint16(0xFFFE))
}
func TestI2CReadWordDataAddressError(t *testing.T) {
c := NewConnection(initI2CDeviceAddressError(), 0x06)
defer cleanupI2CDevice()
_, err := c.ReadWordData(0x01)
gobottest.Assert(t, err, errors.New("Setting address failed with syscall.Errno operation not permitted"))
}
func TestI2CWriteByte(t *testing.T) {
c := NewConnection(initI2CDevice(), 0x06)
defer cleanupI2CDevice()
err := c.WriteByte(0x01)
gobottest.Assert(t, err, nil)
}
func TestI2CWriteByteAddressError(t *testing.T) {
c := NewConnection(initI2CDeviceAddressError(), 0x06)
defer cleanupI2CDevice()
err := c.WriteByte(0x01)
gobottest.Assert(t, err, errors.New("Setting address failed with syscall.Errno operation not permitted"))
}
func TestI2CWriteByteData(t *testing.T) {
c := NewConnection(initI2CDevice(), 0x06)
defer cleanupI2CDevice()
err := c.WriteByteData(0x01, 0x01)
gobottest.Assert(t, err, nil)
}
func TestI2CWriteByteDataAddressError(t *testing.T) {
c := NewConnection(initI2CDeviceAddressError(), 0x06)
defer cleanupI2CDevice()
err := c.WriteByteData(0x01, 0x01)
gobottest.Assert(t, err, errors.New("Setting address failed with syscall.Errno operation not permitted"))
}
func TestI2CWriteWordData(t *testing.T) {
c := NewConnection(initI2CDevice(), 0x06)
defer cleanupI2CDevice()
err := c.WriteWordData(0x01, 0x01)
gobottest.Assert(t, err, nil)
}
func TestI2CWriteWordDataAddressError(t *testing.T) {
c := NewConnection(initI2CDeviceAddressError(), 0x06)
defer cleanupI2CDevice()
err := c.WriteWordData(0x01, 0x01)
gobottest.Assert(t, err, errors.New("Setting address failed with syscall.Errno operation not permitted"))
}
func TestI2CWriteBlockData(t *testing.T) {
c := NewConnection(initI2CDevice(), 0x06)
defer cleanupI2CDevice()
err := c.WriteBlockData(0x01, []byte{0x01, 0x02})
gobottest.Assert(t, err, nil)
}
func TestI2CWriteBlockDataAddressError(t *testing.T) {
c := NewConnection(initI2CDeviceAddressError(), 0x06)
defer cleanupI2CDevice()
err := c.WriteBlockData(0x01, []byte{0x01, 0x02})
gobottest.Assert(t, err, errors.New("Setting address failed with syscall.Errno operation not permitted"))
}

View File

@ -1,9 +1,11 @@
package i2c
import (
"encoding/binary"
"fmt"
"strconv"
"sync"
"time"
"gobot.io/x/gobot"
)
@ -85,7 +87,15 @@ func (d *Driver) Halt() error {
return nil
}
// Write implements a simple write mechanism to the given register of an i2c device.
// Write writes one byte to the i2c device.
func (d *Driver) WriteByte(val byte) error {
d.mutex.Lock()
defer d.mutex.Unlock()
return d.connection.WriteByte(val)
}
// Write implements a simple write mechanism, starting from the given register of an i2c device.
func (d *Driver) Write(pin string, val int) error {
d.mutex.Lock()
defer d.mutex.Unlock()
@ -95,10 +105,77 @@ func (d *Driver) Write(pin string, val int) error {
return err
}
// TODO: create buffer from size
// currently only one byte value is supported
b := []byte{uint8(val)}
return d.connection.WriteBlockData(uint8(register), b)
if val > 0xFFFF {
buf := make([]byte, 4)
binary.LittleEndian.PutUint32(buf, uint32(val))
return d.connection.WriteBlockData(register, buf)
}
if val > 0xFF {
return d.connection.WriteWordData(register, uint16(val))
}
return d.connection.WriteByteData(register, uint8(val))
}
// WriteByteData writes the given byte value to the given register of an i2c device.
func (d *Driver) WriteByteData(pin string, val byte) error {
d.mutex.Lock()
defer d.mutex.Unlock()
register, err := driverParseRegister(pin)
if err != nil {
return err
}
return d.connection.WriteByteData(register, val)
}
// WriteWordData writes the given 16 bit value to the given register of an i2c device.
func (d *Driver) WriteWordData(pin string, val uint16) error {
d.mutex.Lock()
defer d.mutex.Unlock()
register, err := driverParseRegister(pin)
if err != nil {
return err
}
return d.connection.WriteWordData(register, val)
}
// WriteBlockData writes the given buffer to the given register of an i2c device.
func (d *Driver) WriteBlockData(pin string, data []byte) error {
d.mutex.Lock()
defer d.mutex.Unlock()
register, err := driverParseRegister(pin)
if err != nil {
return err
}
return d.connection.WriteBlockData(uint8(register), data)
}
// WriteData writes the given buffer to the given register of an i2c device.
// It uses plain write to prevent WriteBlockData(), which is sometimes not supported by adaptor.
func (d *Driver) WriteData(pin string, data []byte) error {
d.mutex.Lock()
defer d.mutex.Unlock()
register, err := driverParseRegister(pin)
if err != nil {
return err
}
buf := make([]byte, len(data)+1)
copy(buf[1:], data)
buf[0] = register
cnt, err := d.connection.Write(buf)
if cnt != len(buf) {
return fmt.Errorf("written count (%d) differ from expected (%d)", cnt, len(buf))
}
return err
}
// Read implements a simple read mechanism from the given register of an i2c device.
@ -111,14 +188,88 @@ func (d *Driver) Read(pin string) (int, error) {
return 0, err
}
// TODO: create buffer from size
// currently only one byte value is supported
b := []byte{0}
if err := d.connection.ReadBlockData(register, b); err != nil {
val, err := d.connection.ReadByteData(register)
if err != nil {
return 0, err
}
return int(b[0]), nil
return int(val), nil
}
// ReadByte reads a byte from the current register of an i2c device.
func (d *Driver) ReadByte() (byte, error) {
d.mutex.Lock()
defer d.mutex.Unlock()
return d.connection.ReadByte()
}
// ReadByteData reads a byte from the given register of an i2c device.
func (d *Driver) ReadByteData(pin string) (byte, error) {
d.mutex.Lock()
defer d.mutex.Unlock()
register, err := driverParseRegister(pin)
if err != nil {
return 0, err
}
return d.connection.ReadByteData(register)
}
// ReadWordData reads a 16 bit value starting from the given register of an i2c device.
func (d *Driver) ReadWordData(pin string) (uint16, error) {
d.mutex.Lock()
defer d.mutex.Unlock()
register, err := driverParseRegister(pin)
if err != nil {
return 0, err
}
return d.connection.ReadWordData(register)
}
// ReadBlockData fills the given buffer with reads starting from the given register of an i2c device.
func (d *Driver) ReadBlockData(pin string, data []byte) error {
d.mutex.Lock()
defer d.mutex.Unlock()
register, err := driverParseRegister(pin)
if err != nil {
return err
}
return d.connection.ReadBlockData(register, data)
}
// ReadBlockData fills the given buffer with reads from the given register of an i2c device.
// It uses plain read to prevent ReadBlockData(), which is sometimes not supported by adaptor.
func (d *Driver) ReadData(pin string, data []byte) error {
d.mutex.Lock()
defer d.mutex.Unlock()
register, err := driverParseRegister(pin)
if err != nil {
return err
}
if err := d.connection.WriteByte(register); err != nil {
return err
}
// write process needs some time, so wait at least 5ms before read a value
// when decreasing to much, the check below will fail
time.Sleep(10 * time.Millisecond)
n, err := d.connection.Read(data)
if err != nil {
return err
}
if n != len(data) {
return fmt.Errorf("Read %v bytes from device by sysfs, expected %v", n, len(data))
}
return nil
}
func driverParseRegister(pin string) (uint8, error) {

View File

@ -17,7 +17,7 @@ import (
// Wiring
// PWR Tinkerboard: 1 (+3.3V, VCC), 6, 9, 14, 20 (GND)
// I2C1 Tinkerboard: 3 (SDA), 5 (SCL)
// PCF8583 DIP package: 1 (OSCI, 50Hz), 2 (OSCO, nc), 3 (A0 - GND), 4 (VSS, +3.3V), 5 (SDA), 6 (SCL), 7 (/INT, nc), 8 (VDD, GND)
// PCF8583 DIP package: 1 (OSCI, 50Hz), 2 (OSCO, nc), 3 (A0 - GND), 4 (VSS, GND), 5 (SDA), 6 (SCL), 7 (/INT, nc), 8 (VDD, +3.3V)
func main() {
board := tinkerboard.NewAdaptor()
pcf := i2c.NewPCF8583Driver(board, i2c.WithBus(1), i2c.WithPCF8583Mode(i2c.PCF8583CtrlModeClock50))

View File

@ -17,7 +17,7 @@ import (
// Wiring
// PWR Tinkerboard: 1 (+3.3V, VCC), 6, 9, 14, 20 (GND)
// I2C1 Tinkerboard: 3 (SDA), 5 (SCL)
// PCF8583 DIP package: 1 (OSCI, event), 2 (OSCO, nc), 3 (A0 - GND), 4 (VSS, +3.3V), 5 (SDA), 6 (SCL), 7 (/INT, nc), 8 (VDD, GND)
// PCF8583 DIP package: 1 (OSCI, event), 2 (OSCO, nc), 3 (A0 - GND), 4 (VSS, GND), 5 (SDA), 6 (SCL), 7 (/INT, nc), 8 (VDD, +3.3V)
// Note: event can be created by e.g. an debounced button
func main() {
board := tinkerboard.NewAdaptor()

View File

@ -82,6 +82,7 @@ func TestBeagleboneAdaptor(t *testing.T) {
})
sysfs.SetFilesystem(fs)
defer sysfs.SetFilesystem(&sysfs.NativeFilesystem{})
a, _ := initBBBTestAdaptor()
@ -170,6 +171,7 @@ func TestBeagleboneAdaptor(t *testing.T) {
// I2c
sysfs.SetSyscall(&sysfs.MockSyscall{})
defer sysfs.SetSyscall(&sysfs.NativeSyscall{})
con, err := a.GetConnection(0xff, 2)
gobottest.Assert(t, err, nil)
@ -205,6 +207,7 @@ func TestBeagleboneAnalogReadFileError(t *testing.T) {
"/sys/devices/platform/whatever",
})
sysfs.SetFilesystem(fs)
defer sysfs.SetFilesystem(&sysfs.NativeFilesystem{})
a, _ := initBBBTestAdaptor()
@ -219,6 +222,7 @@ func TestBeagleboneDigitalPinDirectionFileError(t *testing.T) {
"/sys/devices/platform/ocp/ocp:P9_12_pinmux/state",
})
sysfs.SetFilesystem(fs)
defer sysfs.SetFilesystem(&sysfs.NativeFilesystem{})
a, _ := initBBBTestAdaptor()
@ -237,6 +241,7 @@ func TestBeagleboneDigitalPinFinalizeFileError(t *testing.T) {
"/sys/devices/platform/ocp/ocp:P9_12_pinmux/state",
})
sysfs.SetFilesystem(fs)
defer sysfs.SetFilesystem(&sysfs.NativeFilesystem{})
a, _ := initBBBTestAdaptor()

View File

@ -40,6 +40,7 @@ func initTestChipAdaptor() (*Adaptor, *sysfs.MockFilesystem) {
})
sysfs.SetFilesystem(fs)
return a, fs
}
@ -64,6 +65,10 @@ func initTestChipProAdaptor() (*Adaptor, *sysfs.MockFilesystem) {
return a, fs
}
func cleanTestChipAdaptor() {
defer sysfs.SetFilesystem(&sysfs.NativeFilesystem{})
}
func TestChipAdaptorName(t *testing.T) {
a := NewAdaptor()
gobottest.Assert(t, strings.HasPrefix(a.Name(), "CHIP"), true)
@ -81,6 +86,7 @@ func TestChipAdaptorBoard(t *testing.T) {
func TestAdaptorFinalizeErrorAfterGPIO(t *testing.T) {
a, fs := initTestChipAdaptor()
defer cleanTestChipAdaptor()
gobottest.Assert(t, a.Connect(), nil)
gobottest.Assert(t, a.DigitalWrite("CSID7", 1), nil)
@ -92,6 +98,7 @@ func TestAdaptorFinalizeErrorAfterGPIO(t *testing.T) {
func TestAdaptorFinalizeErrorAfterPWM(t *testing.T) {
a, fs := initTestChipAdaptor()
defer cleanTestChipAdaptor()
gobottest.Assert(t, a.Connect(), nil)
gobottest.Assert(t, a.PwmWrite("PWM0", 100), nil)
@ -103,6 +110,7 @@ func TestAdaptorFinalizeErrorAfterPWM(t *testing.T) {
func TestChipAdaptorDigitalIO(t *testing.T) {
a, fs := initTestChipAdaptor()
defer cleanTestChipAdaptor()
a.Connect()
a.DigitalWrite("CSID7", 1)
@ -118,6 +126,7 @@ func TestChipAdaptorDigitalIO(t *testing.T) {
func TestChipProAdaptorDigitalIO(t *testing.T) {
a, fs := initTestChipProAdaptor()
defer cleanTestChipAdaptor()
a.Connect()
a.DigitalWrite("CSID7", 1)
@ -133,6 +142,7 @@ func TestChipProAdaptorDigitalIO(t *testing.T) {
func TestAdaptorDigitalWriteError(t *testing.T) {
a, fs := initTestChipAdaptor()
defer cleanTestChipAdaptor()
fs.WithWriteError = true
err := a.DigitalWrite("CSID7", 1)
@ -141,6 +151,7 @@ func TestAdaptorDigitalWriteError(t *testing.T) {
func TestAdaptorDigitalReadWriteError(t *testing.T) {
a, fs := initTestChipAdaptor()
defer cleanTestChipAdaptor()
fs.WithWriteError = true
_, err := a.DigitalRead("CSID7")
@ -156,6 +167,7 @@ func TestChipAdaptorI2c(t *testing.T) {
})
sysfs.SetFilesystem(fs)
sysfs.SetSyscall(&sysfs.MockSyscall{})
defer sysfs.SetSyscall(&sysfs.NativeSyscall{})
con, err := a.GetConnection(0xff, 1)
gobottest.Assert(t, err, nil)
@ -170,6 +182,7 @@ func TestChipAdaptorI2c(t *testing.T) {
func TestChipAdaptorInvalidPWMPin(t *testing.T) {
a, _ := initTestChipAdaptor()
defer cleanTestChipAdaptor()
a.Connect()
err := a.PwmWrite("LCD-D2", 42)
@ -181,6 +194,7 @@ func TestChipAdaptorInvalidPWMPin(t *testing.T) {
func TestChipAdaptorPWM(t *testing.T) {
a, fs := initTestChipAdaptor()
defer cleanTestChipAdaptor()
a.Connect()
err := a.PwmWrite("PWM0", 100)
@ -205,6 +219,7 @@ func TestChipAdaptorPWM(t *testing.T) {
func TestAdaptorPwmWriteError(t *testing.T) {
a, fs := initTestChipAdaptor()
defer cleanTestChipAdaptor()
fs.WithWriteError = true
err := a.PwmWrite("PWM0", 100)
@ -213,6 +228,7 @@ func TestAdaptorPwmWriteError(t *testing.T) {
func TestAdaptorPwmReadError(t *testing.T) {
a, fs := initTestChipAdaptor()
defer cleanTestChipAdaptor()
fs.WithReadError = true
err := a.PwmWrite("PWM0", 100)
@ -221,11 +237,13 @@ func TestAdaptorPwmReadError(t *testing.T) {
func TestChipDefaultBus(t *testing.T) {
a, _ := initTestChipAdaptor()
defer cleanTestChipAdaptor()
gobottest.Assert(t, a.GetDefaultBus(), 1)
}
func TestChipGetConnectionInvalidBus(t *testing.T) {
a, _ := initTestChipAdaptor()
defer cleanTestChipAdaptor()
_, err := a.GetConnection(0x01, 99)
gobottest.Assert(t, err, errors.New("Bus number 99 out of range"))
}

View File

@ -45,6 +45,7 @@ func TestDragonBoardAdaptorDigitalIO(t *testing.T) {
})
sysfs.SetFilesystem(fs)
defer sysfs.SetFilesystem(&sysfs.NativeFilesystem{})
_ = a.DigitalWrite("GPIO_B", 1)
gobottest.Assert(t, fs.Files["/sys/class/gpio/gpio12/value"].Contents, "1")
@ -63,7 +64,9 @@ func TestDragonBoardAdaptorI2c(t *testing.T) {
"/dev/i2c-1",
})
sysfs.SetFilesystem(fs)
defer sysfs.SetFilesystem(&sysfs.NativeFilesystem{})
sysfs.SetSyscall(&sysfs.MockSyscall{})
defer sysfs.SetSyscall(&sysfs.NativeSyscall{})
con, err := a.GetConnection(0xff, 1)
gobottest.Assert(t, err, nil)
@ -99,6 +102,7 @@ func TestAdaptorFinalizeErrorAfterGPIO(t *testing.T) {
})
sysfs.SetFilesystem(fs)
defer sysfs.SetFilesystem(&sysfs.NativeFilesystem{})
gobottest.Assert(t, a.Connect(), nil)
gobottest.Assert(t, a.DigitalWrite("GPIO_B", 1), nil)

View File

@ -102,8 +102,13 @@ func initTestAdaptor() (*Adaptor, *sysfs.MockFilesystem) {
return a, fs
}
func cleanTestAdaptor() {
defer sysfs.SetFilesystem(&sysfs.NativeFilesystem{})
}
func TestEdisonAdaptorName(t *testing.T) {
a, _ := initTestAdaptor()
defer cleanTestAdaptor()
gobottest.Assert(t, strings.HasPrefix(a.Name(), "Edison"), true)
a.SetName("NewName")
gobottest.Assert(t, a.Name(), "NewName")
@ -111,6 +116,7 @@ func TestEdisonAdaptorName(t *testing.T) {
func TestAdaptorConnect(t *testing.T) {
a, _ := initTestAdaptor()
defer cleanTestAdaptor()
gobottest.Assert(t, a.Connect(), nil)
gobottest.Assert(t, a.GetDefaultBus(), 6)
gobottest.Assert(t, a.Board(), "arduino")
@ -120,6 +126,7 @@ func TestAdaptorConnect(t *testing.T) {
func TestAdaptorArduinoSetupFail263(t *testing.T) {
a, fs := initTestAdaptor()
defer cleanTestAdaptor()
delete(fs.Files, "/sys/class/gpio/gpio263/direction")
err := a.arduinoSetup()
@ -128,6 +135,7 @@ func TestAdaptorArduinoSetupFail263(t *testing.T) {
func TestAdaptorArduinoSetupFail240(t *testing.T) {
a, fs := initTestAdaptor()
defer cleanTestAdaptor()
delete(fs.Files, "/sys/class/gpio/gpio240/direction")
err := a.arduinoSetup()
@ -136,6 +144,7 @@ func TestAdaptorArduinoSetupFail240(t *testing.T) {
func TestAdaptorArduinoSetupFail111(t *testing.T) {
a, fs := initTestAdaptor()
defer cleanTestAdaptor()
delete(fs.Files, "/sys/kernel/debug/gpio_debug/gpio111/current_pinmux")
err := a.arduinoSetup()
@ -144,6 +153,7 @@ func TestAdaptorArduinoSetupFail111(t *testing.T) {
func TestAdaptorArduinoSetupFail131(t *testing.T) {
a, fs := initTestAdaptor()
defer cleanTestAdaptor()
delete(fs.Files, "/sys/kernel/debug/gpio_debug/gpio131/current_pinmux")
err := a.arduinoSetup()
@ -152,6 +162,7 @@ func TestAdaptorArduinoSetupFail131(t *testing.T) {
func TestAdaptorArduinoI2CSetupFailTristate(t *testing.T) {
a, fs := initTestAdaptor()
defer cleanTestAdaptor()
gobottest.Assert(t, a.arduinoSetup(), nil)
@ -162,6 +173,7 @@ func TestAdaptorArduinoI2CSetupFailTristate(t *testing.T) {
func TestAdaptorArduinoI2CSetupFail14(t *testing.T) {
a, fs := initTestAdaptor()
defer cleanTestAdaptor()
gobottest.Assert(t, a.arduinoSetup(), nil)
delete(fs.Files, "/sys/class/gpio/gpio14/direction")
@ -172,6 +184,7 @@ func TestAdaptorArduinoI2CSetupFail14(t *testing.T) {
func TestAdaptorArduinoI2CSetupUnexportFail(t *testing.T) {
a, fs := initTestAdaptor()
defer cleanTestAdaptor()
gobottest.Assert(t, a.arduinoSetup(), nil)
delete(fs.Files, "/sys/class/gpio/unexport")
@ -182,6 +195,7 @@ func TestAdaptorArduinoI2CSetupUnexportFail(t *testing.T) {
func TestAdaptorArduinoI2CSetupFail236(t *testing.T) {
a, fs := initTestAdaptor()
defer cleanTestAdaptor()
gobottest.Assert(t, a.arduinoSetup(), nil)
delete(fs.Files, "/sys/class/gpio/gpio236/direction")
@ -192,6 +206,7 @@ func TestAdaptorArduinoI2CSetupFail236(t *testing.T) {
func TestAdaptorArduinoI2CSetupFail28(t *testing.T) {
a, fs := initTestAdaptor()
defer cleanTestAdaptor()
gobottest.Assert(t, a.arduinoSetup(), nil)
delete(fs.Files, "/sys/kernel/debug/gpio_debug/gpio28/current_pinmux")
@ -202,6 +217,7 @@ func TestAdaptorArduinoI2CSetupFail28(t *testing.T) {
func TestAdaptorConnectArduinoError(t *testing.T) {
a, _ := initTestAdaptor()
defer cleanTestAdaptor()
a.writeFile = func(string, []byte) (int, error) {
return 0, errors.New("write error")
}
@ -212,6 +228,7 @@ func TestAdaptorConnectArduinoError(t *testing.T) {
func TestAdaptorConnectArduinoWriteError(t *testing.T) {
a, fs := initTestAdaptor()
defer cleanTestAdaptor()
fs.WithWriteError = true
err := a.Connect()
gobottest.Assert(t, strings.Contains(err.Error(), "write error"), true)
@ -219,6 +236,7 @@ func TestAdaptorConnectArduinoWriteError(t *testing.T) {
func TestAdaptorConnectSparkfun(t *testing.T) {
a, _ := initTestAdaptor()
defer cleanTestAdaptor()
a.SetBoard("sparkfun")
gobottest.Assert(t, a.Connect(), nil)
gobottest.Assert(t, a.GetDefaultBus(), 1)
@ -227,6 +245,7 @@ func TestAdaptorConnectSparkfun(t *testing.T) {
func TestAdaptorConnectMiniboard(t *testing.T) {
a, _ := initTestAdaptor()
defer cleanTestAdaptor()
a.SetBoard("miniboard")
gobottest.Assert(t, a.Connect(), nil)
gobottest.Assert(t, a.GetDefaultBus(), 1)
@ -235,16 +254,19 @@ func TestAdaptorConnectMiniboard(t *testing.T) {
func TestAdaptorConnectUnknown(t *testing.T) {
a, _ := initTestAdaptor()
defer cleanTestAdaptor()
a.SetBoard("wha")
gobottest.Refute(t, a.Connect(), nil)
}
func TestAdaptorFinalize(t *testing.T) {
a, _ := initTestAdaptor()
defer cleanTestAdaptor()
a.DigitalWrite("3", 1)
a.PwmWrite("5", 100)
sysfs.SetSyscall(&sysfs.MockSyscall{})
defer sysfs.SetSyscall(&sysfs.NativeSyscall{})
a.GetConnection(0xff, 6)
gobottest.Assert(t, a.Finalize(), nil)
@ -255,6 +277,7 @@ func TestAdaptorFinalize(t *testing.T) {
func TestAdaptorFinalizeError(t *testing.T) {
a, fs := initTestAdaptor()
defer cleanTestAdaptor()
a.PwmWrite("5", 100)
fs.WithWriteError = true
@ -263,6 +286,7 @@ func TestAdaptorFinalizeError(t *testing.T) {
func TestAdaptorDigitalIO(t *testing.T) {
a, fs := initTestAdaptor()
defer cleanTestAdaptor()
a.DigitalWrite("13", 1)
gobottest.Assert(t, fs.Files["/sys/class/gpio/gpio40/value"].Contents, "1")
@ -289,6 +313,7 @@ func TestAdaptorDigitalPinInFileError(t *testing.T) {
"/sys/class/gpio/gpio261/direction",
})
sysfs.SetFilesystem(fs)
defer sysfs.SetFilesystem(&sysfs.NativeFilesystem{})
a.Connect()
@ -313,6 +338,7 @@ func TestAdaptorDigitalPinInResistorFileError(t *testing.T) {
"/sys/class/gpio/gpio261/direction",
})
sysfs.SetFilesystem(fs)
defer sysfs.SetFilesystem(&sysfs.NativeFilesystem{})
a.Connect()
@ -336,6 +362,7 @@ func TestAdaptorDigitalPinInLevelShifterFileError(t *testing.T) {
// "/sys/class/gpio/gpio261/direction",
})
sysfs.SetFilesystem(fs)
defer sysfs.SetFilesystem(&sysfs.NativeFilesystem{})
a.Connect()
@ -359,6 +386,7 @@ func TestAdaptorDigitalPinInMuxFileError(t *testing.T) {
"/sys/class/gpio/gpio261/direction",
})
sysfs.SetFilesystem(fs)
defer sysfs.SetFilesystem(&sysfs.NativeFilesystem{})
a.Connect()
@ -368,6 +396,7 @@ func TestAdaptorDigitalPinInMuxFileError(t *testing.T) {
func TestAdaptorDigitalWriteError(t *testing.T) {
a, fs := initTestAdaptor()
defer cleanTestAdaptor()
fs.WithWriteError = true
err := a.DigitalWrite("13", 1)
@ -376,6 +405,7 @@ func TestAdaptorDigitalWriteError(t *testing.T) {
func TestAdaptorDigitalReadWriteError(t *testing.T) {
a, fs := initTestAdaptor()
defer cleanTestAdaptor()
fs.WithWriteError = true
_, err := a.DigitalRead("13")
@ -384,8 +414,11 @@ func TestAdaptorDigitalReadWriteError(t *testing.T) {
func TestAdaptorI2c(t *testing.T) {
a, _ := initTestAdaptor()
defer cleanTestAdaptor()
sysfs.SetSyscall(&sysfs.MockSyscall{})
defer sysfs.SetSyscall(&sysfs.NativeSyscall{})
con, err := a.GetConnection(0xff, 6)
gobottest.Assert(t, err, nil)
@ -399,12 +432,14 @@ func TestAdaptorI2c(t *testing.T) {
func TestAdaptorI2cInvalidBus(t *testing.T) {
a, _ := initTestAdaptor()
defer cleanTestAdaptor()
_, err := a.GetConnection(0xff, 3)
gobottest.Assert(t, err, errors.New("Unsupported I2C bus"))
}
func TestAdaptorPwm(t *testing.T) {
a, fs := initTestAdaptor()
defer cleanTestAdaptor()
err := a.PwmWrite("5", 100)
gobottest.Assert(t, err, nil)
@ -432,6 +467,7 @@ func TestAdaptorPwmExportError(t *testing.T) {
"/sys/class/pwm/pwmchip0/pwm1/enable",
})
sysfs.SetFilesystem(fs)
defer sysfs.SetFilesystem(&sysfs.NativeFilesystem{})
a.Connect()
err := a.PwmWrite("5", 100)
@ -456,6 +492,7 @@ func TestAdaptorPwmEnableError(t *testing.T) {
//"/sys/class/pwm/pwmchip0/pwm1/enable",
})
sysfs.SetFilesystem(fs)
defer sysfs.SetFilesystem(&sysfs.NativeFilesystem{})
a.Connect()
err := a.PwmWrite("5", 100)
@ -464,6 +501,7 @@ func TestAdaptorPwmEnableError(t *testing.T) {
func TestAdaptorPwmWritePinError(t *testing.T) {
a, _ := initTestAdaptor()
defer cleanTestAdaptor()
a.writeFile = func(string, []byte) (int, error) {
return 0, errors.New("write error")
@ -475,6 +513,7 @@ func TestAdaptorPwmWritePinError(t *testing.T) {
func TestAdaptorPwmWriteError(t *testing.T) {
a, fs := initTestAdaptor()
defer cleanTestAdaptor()
fs.WithWriteError = true
@ -484,6 +523,7 @@ func TestAdaptorPwmWriteError(t *testing.T) {
func TestAdaptorPwmReadError(t *testing.T) {
a, fs := initTestAdaptor()
defer cleanTestAdaptor()
fs.WithReadError = true
@ -493,6 +533,7 @@ func TestAdaptorPwmReadError(t *testing.T) {
func TestAdaptorAnalog(t *testing.T) {
a, fs := initTestAdaptor()
defer cleanTestAdaptor()
fs.Files["/sys/bus/iio/devices/iio:device1/in_voltage0_raw"].Contents = "1000\n"
i, _ := a.AnalogRead("0")
@ -501,6 +542,7 @@ func TestAdaptorAnalog(t *testing.T) {
func TestAdaptorAnalogError(t *testing.T) {
a, _ := initTestAdaptor()
defer cleanTestAdaptor()
a.readFile = func(string) ([]byte, error) {
return nil, errors.New("read error")

View File

@ -88,13 +88,19 @@ func initTestAdaptor() (*Adaptor, *sysfs.MockFilesystem) {
"/dev/i2c-0",
})
sysfs.SetFilesystem(fs)
fs.Files["/sys/class/pwm/pwmchip0/pwm0/period"].Contents = "5000"
a.Connect()
return a, fs
}
func cleanTestAdaptor() {
defer sysfs.SetFilesystem(&sysfs.NativeFilesystem{})
}
func TestJouleAdaptorName(t *testing.T) {
a, _ := initTestAdaptor()
defer cleanTestAdaptor()
gobottest.Assert(t, strings.HasPrefix(a.Name(), "Joule"), true)
a.SetName("NewName")
gobottest.Assert(t, a.Name(), "NewName")
@ -102,12 +108,14 @@ func TestJouleAdaptorName(t *testing.T) {
func TestAdaptorConnect(t *testing.T) {
a, _ := initTestAdaptor()
defer cleanTestAdaptor()
gobottest.Assert(t, a.Connect(), nil)
gobottest.Assert(t, a.GetDefaultBus(), 0)
}
func TestAdaptorInvalidBus(t *testing.T) {
a, _ := initTestAdaptor()
defer cleanTestAdaptor()
gobottest.Assert(t, a.Connect(), nil)
_, err := a.GetConnection(0xff, 10)
@ -116,10 +124,13 @@ func TestAdaptorInvalidBus(t *testing.T) {
func TestAdaptorFinalize(t *testing.T) {
a, _ := initTestAdaptor()
defer cleanTestAdaptor()
a.DigitalWrite("J12_1", 1)
a.PwmWrite("J12_26", 100)
sysfs.SetSyscall(&sysfs.MockSyscall{})
defer sysfs.SetSyscall(&sysfs.NativeSyscall{})
gobottest.Assert(t, a.Finalize(), nil)
_, err := a.GetConnection(0xff, 0)
gobottest.Assert(t, err, nil)
@ -131,6 +142,7 @@ func TestAdaptorFinalize(t *testing.T) {
func TestAdaptorDigitalIO(t *testing.T) {
a, fs := initTestAdaptor()
defer cleanTestAdaptor()
a.DigitalWrite("J12_1", 1)
gobottest.Assert(t, fs.Files["/sys/class/gpio/gpio451/value"].Contents, "1")
@ -143,6 +155,7 @@ func TestAdaptorDigitalIO(t *testing.T) {
func TestAdaptorDigitalWriteError(t *testing.T) {
a, fs := initTestAdaptor()
defer cleanTestAdaptor()
fs.WithWriteError = true
err := a.DigitalWrite("13", 1)
@ -151,6 +164,7 @@ func TestAdaptorDigitalWriteError(t *testing.T) {
func TestAdaptorDigitalReadWriteError(t *testing.T) {
a, fs := initTestAdaptor()
defer cleanTestAdaptor()
fs.WithWriteError = true
_, err := a.DigitalRead("13")
@ -159,8 +173,11 @@ func TestAdaptorDigitalReadWriteError(t *testing.T) {
func TestAdaptorI2c(t *testing.T) {
a, _ := initTestAdaptor()
defer cleanTestAdaptor()
sysfs.SetSyscall(&sysfs.MockSyscall{})
defer sysfs.SetSyscall(&sysfs.NativeSyscall{})
con, err := a.GetConnection(0xff, 0)
gobottest.Assert(t, err, nil)
@ -174,6 +191,7 @@ func TestAdaptorI2c(t *testing.T) {
func TestAdaptorPwm(t *testing.T) {
a, fs := initTestAdaptor()
defer cleanTestAdaptor()
err := a.PwmWrite("J12_26", 100)
gobottest.Assert(t, err, nil)
@ -188,6 +206,7 @@ func TestAdaptorPwm(t *testing.T) {
func TestAdaptorPwmPinExportError(t *testing.T) {
a, fs := initTestAdaptor()
defer cleanTestAdaptor()
delete(fs.Files, "/sys/class/pwm/pwmchip0/export")
@ -197,6 +216,7 @@ func TestAdaptorPwmPinExportError(t *testing.T) {
func TestAdaptorPwmPinEnableError(t *testing.T) {
a, fs := initTestAdaptor()
defer cleanTestAdaptor()
delete(fs.Files, "/sys/class/pwm/pwmchip0/pwm0/enable")

View File

@ -61,7 +61,9 @@ func TestAdaptorFinalize(t *testing.T) {
})
sysfs.SetFilesystem(fs)
defer sysfs.SetFilesystem(&sysfs.NativeFilesystem{})
sysfs.SetSyscall(&sysfs.MockSyscall{})
defer sysfs.SetSyscall(&sysfs.NativeSyscall{})
a.DigitalWrite("3", 1)
@ -81,6 +83,7 @@ func TestAdaptorDigitalIO(t *testing.T) {
})
sysfs.SetFilesystem(fs)
defer sysfs.SetFilesystem(&sysfs.NativeFilesystem{})
a.DigitalWrite("7", 1)
gobottest.Assert(t, fs.Files["/sys/class/gpio/gpio216/value"].Contents, "1")
@ -106,7 +109,9 @@ func TestAdaptorI2c(t *testing.T) {
"/dev/i2c-1",
})
sysfs.SetFilesystem(fs)
defer sysfs.SetFilesystem(&sysfs.NativeFilesystem{})
sysfs.SetSyscall(&sysfs.MockSyscall{})
defer sysfs.SetSyscall(&sysfs.NativeSyscall{})
con, err := a.GetConnection(0xff, 1)
gobottest.Assert(t, err, nil)
@ -128,7 +133,9 @@ func TestAdaptorSPI(t *testing.T) {
"/dev/spidev0.1",
})
sysfs.SetFilesystem(fs)
defer sysfs.SetFilesystem(&sysfs.NativeFilesystem{})
sysfs.SetSyscall(&sysfs.MockSyscall{})
defer sysfs.SetSyscall(&sysfs.NativeSyscall{})
gobottest.Assert(t, a.GetSpiDefaultBus(), 0)
gobottest.Assert(t, a.GetSpiDefaultChip(), 0)
@ -145,6 +152,7 @@ func TestAdaptorDigitalPinConcurrency(t *testing.T) {
oldProcs := runtime.GOMAXPROCS(0)
runtime.GOMAXPROCS(8)
defer runtime.GOMAXPROCS(oldProcs)
for retry := 0; retry < 20; retry++ {
@ -162,7 +170,4 @@ func TestAdaptorDigitalPinConcurrency(t *testing.T) {
wg.Wait()
}
runtime.GOMAXPROCS(oldProcs)
}

View File

@ -23,6 +23,7 @@ func TestPwmPin(t *testing.T) {
})
sysfs.SetFilesystem(fs)
defer sysfs.SetFilesystem(&sysfs.NativeFilesystem{})
pin, err := NewPWMPin("32")
gobottest.Assert(t, pin.Export(), nil)

View File

@ -99,7 +99,9 @@ func TestAdaptorFinalize(t *testing.T) {
})
sysfs.SetFilesystem(fs)
defer sysfs.SetFilesystem(&sysfs.NativeFilesystem{})
sysfs.SetSyscall(&sysfs.MockSyscall{})
defer sysfs.SetSyscall(&sysfs.NativeSyscall{})
a.DigitalWrite("3", 1)
a.PwmWrite("7", 255)
@ -112,12 +114,13 @@ func TestAdaptorDigitalPWM(t *testing.T) {
a := initTestAdaptor()
a.PiBlasterPeriod = 20000000
gobottest.Assert(t, a.PwmWrite("7", 4), nil)
fs := sysfs.NewMockFilesystem([]string{
"/dev/pi-blaster",
})
sysfs.SetFilesystem(fs)
defer sysfs.SetFilesystem(&sysfs.NativeFilesystem{})
gobottest.Assert(t, a.PwmWrite("7", 4), nil)
pin, _ := a.PWMPin("7")
period, _ := pin.Period()
@ -155,6 +158,7 @@ func TestAdaptorDigitalIO(t *testing.T) {
})
sysfs.SetFilesystem(fs)
defer sysfs.SetFilesystem(&sysfs.NativeFilesystem{})
a.DigitalWrite("7", 1)
gobottest.Assert(t, fs.Files["/sys/class/gpio/gpio4/value"].Contents, "1")
@ -180,7 +184,9 @@ func TestAdaptorI2c(t *testing.T) {
"/dev/i2c-1",
})
sysfs.SetFilesystem(fs)
defer sysfs.SetFilesystem(&sysfs.NativeFilesystem{})
sysfs.SetSyscall(&sysfs.MockSyscall{})
defer sysfs.SetSyscall(&sysfs.NativeSyscall{})
con, err := a.GetConnection(0xff, 1)
gobottest.Assert(t, err, nil)
@ -202,7 +208,9 @@ func TestAdaptorSPI(t *testing.T) {
"/dev/spidev0.1",
})
sysfs.SetFilesystem(fs)
defer sysfs.SetFilesystem(&sysfs.NativeFilesystem{})
sysfs.SetSyscall(&sysfs.MockSyscall{})
defer sysfs.SetSyscall(&sysfs.NativeSyscall{})
gobottest.Assert(t, a.GetSpiDefaultBus(), 0)
gobottest.Assert(t, a.GetSpiDefaultChip(), 0)
@ -219,6 +227,7 @@ func TestAdaptorDigitalPinConcurrency(t *testing.T) {
oldProcs := runtime.GOMAXPROCS(0)
runtime.GOMAXPROCS(8)
defer runtime.GOMAXPROCS(oldProcs)
for retry := 0; retry < 20; retry++ {
@ -236,9 +245,6 @@ func TestAdaptorDigitalPinConcurrency(t *testing.T) {
wg.Wait()
}
runtime.GOMAXPROCS(oldProcs)
}
func TestAdaptorPWMPin(t *testing.T) {

View File

@ -87,6 +87,10 @@ func initTestTinkerboard(fs *sysfs.MockFilesystem) *Adaptor {
return a
}
func cleanTestTinkerboard() {
defer sysfs.SetFilesystem(&sysfs.NativeFilesystem{})
}
func TestTinkerboardName(t *testing.T) {
a := NewAdaptor()
gobottest.Assert(t, strings.HasPrefix(a.Name(), "Tinker Board"), true)
@ -97,6 +101,7 @@ func TestTinkerboardName(t *testing.T) {
func TestTinkerboardDigitalIO(t *testing.T) {
fs := gpioFs()
a := initTestTinkerboard(fs)
defer cleanTestTinkerboard()
a.Connect()
a.DigitalWrite("7", 1)
@ -114,6 +119,7 @@ func TestTinkerboardDigitalWriteError(t *testing.T) {
fs := gpioFs()
fs.WithWriteError = true
a := initTestTinkerboard(fs)
defer cleanTestTinkerboard()
err := a.DigitalWrite("7", 1)
gobottest.Assert(t, err, errors.New("write error"))
@ -123,6 +129,7 @@ func TestTinkerboardDigitalReadWriteError(t *testing.T) {
fs := gpioFs()
fs.WithWriteError = true
a := initTestTinkerboard(fs)
defer cleanTestTinkerboard()
_, err := a.DigitalRead("7")
gobottest.Assert(t, err, errors.New("write error"))
@ -131,6 +138,7 @@ func TestTinkerboardDigitalReadWriteError(t *testing.T) {
func TestTinkerboardInvalidPWMPin(t *testing.T) {
fs := pwmFs(t)
a := initTestTinkerboard(fs)
defer cleanTestTinkerboard()
err := a.PwmWrite("666", 42)
gobottest.Refute(t, err, nil)
@ -148,6 +156,7 @@ func TestTinkerboardInvalidPWMPin(t *testing.T) {
func TestTinkerboardPwmWrite(t *testing.T) {
fs := pwmFs(t)
a := initTestTinkerboard(fs)
defer cleanTestTinkerboard()
err := a.PwmWrite("33", 100)
gobottest.Assert(t, err, nil)
@ -174,6 +183,7 @@ func TestTinkerboardPwmWriteError(t *testing.T) {
fs := pwmFs(t)
fs.WithWriteError = true
a := initTestTinkerboard(fs)
defer cleanTestTinkerboard()
err := a.PwmWrite("33", 100)
gobottest.Assert(t, strings.Contains(err.Error(), "write error"), true)
@ -183,6 +193,7 @@ func TestTinkerboardPwmWriteReadError(t *testing.T) {
fs := pwmFs(t)
fs.WithReadError = true
a := initTestTinkerboard(fs)
defer cleanTestTinkerboard()
err := a.PwmWrite("33", 100)
gobottest.Assert(t, strings.Contains(err.Error(), "read error"), true)
@ -192,6 +203,7 @@ func TestTinkerboardSetPeriod(t *testing.T) {
// arrange
fs := pwmFs(t)
a := initTestTinkerboard(fs)
defer cleanTestTinkerboard()
newPeriod := uint32(2550000)
// act
@ -232,7 +244,9 @@ func TestTinkerboardSetPeriod(t *testing.T) {
func TestTinkerboardI2c(t *testing.T) {
fs := i2cFs()
a := initTestTinkerboard(fs)
defer cleanTestTinkerboard()
sysfs.SetSyscall(&sysfs.MockSyscall{})
defer sysfs.SetSyscall(&sysfs.NativeSyscall{})
con, err := a.GetConnection(0xff, 1)
gobottest.Assert(t, err, nil)
@ -259,6 +273,7 @@ func TestTinkerboardGetConnectionInvalidBus(t *testing.T) {
func TestTinkerboardFinalizeErrorAfterGPIO(t *testing.T) {
fs := gpioFs()
a := initTestTinkerboard(fs)
defer cleanTestTinkerboard()
gobottest.Assert(t, a.Connect(), nil)
gobottest.Assert(t, a.DigitalWrite("7", 1), nil)
@ -272,6 +287,7 @@ func TestTinkerboardFinalizeErrorAfterGPIO(t *testing.T) {
func TestTinkerboardFinalizeErrorAfterPWM(t *testing.T) {
fs := pwmFs(t)
a := initTestTinkerboard(fs)
defer cleanTestTinkerboard()
gobottest.Assert(t, a.Connect(), nil)
gobottest.Assert(t, a.PwmWrite("33", 1), nil)

View File

@ -46,6 +46,10 @@ func initTestUP2Adaptor() (*Adaptor, *sysfs.MockFilesystem) {
return a, fs
}
func cleanTestUP2Adaptor() {
defer sysfs.SetFilesystem(&sysfs.NativeFilesystem{})
}
func TestUP2AdaptorName(t *testing.T) {
a := NewAdaptor()
gobottest.Assert(t, strings.HasPrefix(a.Name(), "UP2"), true)
@ -55,6 +59,7 @@ func TestUP2AdaptorName(t *testing.T) {
func TestUP2AdaptorDigitalIO(t *testing.T) {
a, fs := initTestUP2Adaptor()
defer cleanTestUP2Adaptor()
a.Connect()
a.DigitalWrite("7", 1)
@ -76,6 +81,7 @@ func TestUP2AdaptorDigitalIO(t *testing.T) {
func TestAdaptorDigitalWriteError(t *testing.T) {
a, fs := initTestUP2Adaptor()
defer cleanTestUP2Adaptor()
fs.WithWriteError = true
err := a.DigitalWrite("7", 1)
@ -84,6 +90,7 @@ func TestAdaptorDigitalWriteError(t *testing.T) {
func TestAdaptorDigitalReadWriteError(t *testing.T) {
a, fs := initTestUP2Adaptor()
defer cleanTestUP2Adaptor()
fs.WithWriteError = true
_, err := a.DigitalRead("7")
@ -97,6 +104,7 @@ func TestUP2AdaptorI2c(t *testing.T) {
})
sysfs.SetFilesystem(fs)
sysfs.SetSyscall(&sysfs.MockSyscall{})
defer sysfs.SetSyscall(&sysfs.NativeSyscall{})
con, err := a.GetConnection(0xff, 5)
gobottest.Assert(t, err, nil)
@ -126,6 +134,7 @@ func TestAdaptorSPI(t *testing.T) {
func TestUP2AdaptorInvalidPWMPin(t *testing.T) {
a, _ := initTestUP2Adaptor()
defer cleanTestUP2Adaptor()
a.Connect()
err := a.PwmWrite("666", 42)
@ -143,6 +152,7 @@ func TestUP2AdaptorInvalidPWMPin(t *testing.T) {
func TestUP2AdaptorPWM(t *testing.T) {
a, fs := initTestUP2Adaptor()
defer cleanTestUP2Adaptor()
err := a.PwmWrite("32", 100)
gobottest.Assert(t, err, nil)
@ -166,6 +176,7 @@ func TestUP2AdaptorPWM(t *testing.T) {
func TestUP2AdaptorPwmWriteError(t *testing.T) {
a, fs := initTestUP2Adaptor()
defer cleanTestUP2Adaptor()
fs.WithWriteError = true
err := a.PwmWrite("32", 100)
@ -174,6 +185,7 @@ func TestUP2AdaptorPwmWriteError(t *testing.T) {
func TestUP2AdaptorPwmReadError(t *testing.T) {
a, fs := initTestUP2Adaptor()
defer cleanTestUP2Adaptor()
fs.WithReadError = true
err := a.PwmWrite("32", 100)
@ -182,17 +194,20 @@ func TestUP2AdaptorPwmReadError(t *testing.T) {
func TestUP2I2CDefaultBus(t *testing.T) {
a, _ := initTestUP2Adaptor()
defer cleanTestUP2Adaptor()
gobottest.Assert(t, a.GetDefaultBus(), 5)
}
func TestUP2GetConnectionInvalidBus(t *testing.T) {
a, _ := initTestUP2Adaptor()
defer cleanTestUP2Adaptor()
_, err := a.GetConnection(0x01, 99)
gobottest.Assert(t, err, errors.New("Bus number 99 out of range"))
}
func TestUP2FinalizeErrorAfterGPIO(t *testing.T) {
a, fs := initTestUP2Adaptor()
defer cleanTestUP2Adaptor()
gobottest.Assert(t, a.Connect(), nil)
gobottest.Assert(t, a.DigitalWrite("7", 1), nil)
@ -205,6 +220,7 @@ func TestUP2FinalizeErrorAfterGPIO(t *testing.T) {
func TestUP2FinalizeErrorAfterPWM(t *testing.T) {
a, fs := initTestUP2Adaptor()
defer cleanTestUP2Adaptor()
gobottest.Assert(t, a.Connect(), nil)
gobottest.Assert(t, a.PwmWrite("32", 1), nil)

39
sysfs/README.md Normal file
View File

@ -0,0 +1,39 @@
# sysfs
## I2C
### Byte order
All common libraries (smbus, digispark, firmata, i2cget) read and write I2C data in the order LSByte, MSByte.
Often the devices store its bytes in the reverse order and therefor needs to be swapped after reading.
### Linux syscall implementation
In general there are different ioctl features for I2C
* IOCTL I2C_RDWR, needs "I2C_FUNC_I2C"
* IOCTL SMBUS, needs "I2C_FUNC_SMBUS.."
* SYSFS I/O
* call of "i2c_smbus_* methods"
>The possible functions should be checked before by "I2C_FUNCS".
for further reading see:
* https://www.kernel.org/doc/Documentation/i2c/dev-interface
* https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/i2c-dev.h#L42
* https://stackoverflow.com/questions/9974592/i2c-slave-ioctl-purpose (good for understanding, but there are some small errors in the provided example)
>Qotation from kernel.org: "If possible, use the provided i2c_smbus_* methods described below instead of issuing direct ioctls." We do not do this at the moment, instead we using the "IOCTL SMBUS".
Because the syscall needs uintptr in Go, there are some known pitfalls with that. Following documents could be helpful:
* https://go101.org/article/unsafe.html
* https://stackoverflow.com/questions/51187973/how-to-create-an-array-or-a-slice-from-an-array-unsafe-pointer-in-golang
* https://stackoverflow.com/questions/59042646/whats-the-difference-between-uint-and-uintptr-in-golang
* https://go.dev/play/p/Wd7hWn9Zsu
* for go vet false positives, see: https://github.com/golang/go/issues/41205
Basically by convert to an uintptr, which is than just a number to an object existing at the moment of creation without
any other reference, the garbage collector will possible destroy the original object. Therefor uintptr should be avoided
as long as possible.

View File

@ -1,6 +1,8 @@
package sysfs
import "testing"
import (
"testing"
)
func BenchmarkDigitalRead(b *testing.B) {
fs := NewMockFilesystem([]string{
@ -11,6 +13,8 @@ func BenchmarkDigitalRead(b *testing.B) {
})
SetFilesystem(fs)
defer SetFilesystem(&NativeFilesystem{})
pin := NewDigitalPin(10)
pin.Write(1)

View File

@ -18,6 +18,7 @@ func TestDigitalPin(t *testing.T) {
})
SetFilesystem(fs)
defer SetFilesystem(&NativeFilesystem{})
pin := NewDigitalPin(10, "custom")
gobottest.Assert(t, pin.pin, "10")
@ -94,6 +95,7 @@ func TestDigitalPinExportError(t *testing.T) {
})
SetFilesystem(fs)
defer SetFilesystem(&NativeFilesystem{})
pin := NewDigitalPin(10, "custom")
writeFile = func(File, []byte) (int, error) {
@ -113,6 +115,7 @@ func TestDigitalPinUnexportError(t *testing.T) {
})
SetFilesystem(fs)
defer SetFilesystem(&NativeFilesystem{})
pin := NewDigitalPin(10, "custom")
writeFile = func(File, []byte) (int, error) {

View File

@ -30,7 +30,7 @@ const (
I2C_FUNC_SMBUS_WRITE_WORD_DATA = 0x00400000
I2C_FUNC_SMBUS_READ_BLOCK_DATA = 0x01000000
I2C_FUNC_SMBUS_WRITE_BLOCK_DATA = 0x02000000
// Transaction types
// Transaction types, also declare the transfer size (register and data)
I2C_SMBUS_BYTE = 1
I2C_SMBUS_BYTE_DATA = 2
I2C_SMBUS_WORD_DATA = 3
@ -45,7 +45,7 @@ type i2cSmbusIoctlData struct {
readWrite byte
command byte
size uint32
data uintptr
data unsafe.Pointer
}
type i2cDevice struct {
@ -69,12 +69,7 @@ func NewI2cDevice(location string) (d *i2cDevice, err error) {
}
func (d *i2cDevice) queryFunctionality() error {
_, _, errno := Syscall(
syscall.SYS_IOCTL,
d.file.Fd(),
I2C_FUNCS,
uintptr(unsafe.Pointer(&d.funcs)),
)
_, _, errno := Syscall(syscall.SYS_IOCTL, d.file, I2C_FUNCS, unsafe.Pointer(&d.funcs))
if errno != 0 {
return fmt.Errorf("Querying functionality failed with syscall.Errno %v", errno)
@ -82,13 +77,10 @@ func (d *i2cDevice) queryFunctionality() error {
return nil
}
// SetAddress sets the address of the i2c device to use.
func (d *i2cDevice) SetAddress(address int) error {
_, _, errno := Syscall(
syscall.SYS_IOCTL,
d.file.Fd(),
I2C_SLAVE,
uintptr(byte(address)),
)
// for go vet false positives, see: https://github.com/golang/go/issues/41205
_, _, errno := Syscall(syscall.SYS_IOCTL, d.file, I2C_SLAVE, unsafe.Pointer(uintptr(byte(address))))
if errno != 0 {
return fmt.Errorf("Setting address failed with syscall.Errno %v", errno)
@ -96,45 +88,52 @@ func (d *i2cDevice) SetAddress(address int) error {
return nil
}
// Close closes the character device file.
func (d *i2cDevice) Close() error {
return d.file.Close()
}
func (d *i2cDevice) ReadByte() (val byte, err error) {
// ReadByte reads a byte from the current register of an i2c device.
func (d *i2cDevice) ReadByte() (byte, error) {
if d.funcs&I2C_FUNC_SMBUS_READ_BYTE == 0 {
return 0, fmt.Errorf("SMBus read byte not supported")
}
var data uint8
err = d.smbusAccess(I2C_SMBUS_READ, 0, I2C_SMBUS_BYTE, uintptr(unsafe.Pointer(&data)))
var data uint8 = 0xFC // set value for debugging purposes
err := d.smbusAccess(I2C_SMBUS_READ, 0, I2C_SMBUS_BYTE, unsafe.Pointer(&data))
return data, err
}
// ReadByteData reads a byte from the given register of an i2c device.
func (d *i2cDevice) ReadByteData(reg uint8) (val uint8, err error) {
if d.funcs&I2C_FUNC_SMBUS_READ_BYTE_DATA == 0 {
return 0, fmt.Errorf("SMBus read byte data not supported")
}
var data uint8
err = d.smbusAccess(I2C_SMBUS_READ, reg, I2C_SMBUS_BYTE_DATA, uintptr(unsafe.Pointer(&data)))
var data uint8 = 0xFD // set value for debugging purposes
err = d.smbusAccess(I2C_SMBUS_READ, reg, I2C_SMBUS_BYTE_DATA, unsafe.Pointer(&data))
return data, err
}
// ReadWordData reads a 16 bit value starting from the given register of an i2c device.
func (d *i2cDevice) ReadWordData(reg uint8) (val uint16, err error) {
if d.funcs&I2C_FUNC_SMBUS_READ_WORD_DATA == 0 {
return 0, fmt.Errorf("SMBus read word data not supported")
}
var data uint16
err = d.smbusAccess(I2C_SMBUS_READ, reg, I2C_SMBUS_WORD_DATA, uintptr(unsafe.Pointer(&data)))
var data uint16 = 0xFFFE // set value for debugging purposes
err = d.smbusAccess(I2C_SMBUS_READ, reg, I2C_SMBUS_WORD_DATA, unsafe.Pointer(&data))
return data, err
}
// ReadBlockData fills the given buffer with reads starting from the given register of an i2c device.
func (d *i2cDevice) ReadBlockData(reg uint8, data []byte) error {
if len(data) > 32 {
lenWithReg := len(data) + 1
if lenWithReg > 33 {
return fmt.Errorf("Reading blocks larger than 32 bytes (%v) not supported", len(data))
}
data[0] = 0xFF // set value for debugging purposes
if d.funcs&I2C_FUNC_SMBUS_READ_BLOCK_DATA == 0 {
if i2cDeviceDebug {
log.Printf("SMBus read block data not supported, use fallback\n")
@ -142,37 +141,42 @@ func (d *i2cDevice) ReadBlockData(reg uint8, data []byte) error {
return d.readBlockDataFallback(reg, data)
}
return d.smbusAccess(I2C_SMBUS_READ, reg, I2C_SMBUS_BLOCK_DATA, uintptr(unsafe.Pointer(&data)))
return d.smbusAccess(I2C_SMBUS_READ, reg, uint32(lenWithReg), unsafe.Pointer(&data[0]))
}
// WriteByte writes the given byte value to the current register of an i2c device.
func (d *i2cDevice) WriteByte(val byte) error {
if d.funcs&I2C_FUNC_SMBUS_WRITE_BYTE == 0 {
return fmt.Errorf("SMBus write byte not supported")
}
return d.smbusAccess(I2C_SMBUS_WRITE, val, I2C_SMBUS_BYTE, uintptr(0))
return d.smbusAccess(I2C_SMBUS_WRITE, val, I2C_SMBUS_BYTE, nil)
}
// WriteByteData writes the given byte value to the given register of an i2c device.
func (d *i2cDevice) WriteByteData(reg uint8, val uint8) error {
if d.funcs&I2C_FUNC_SMBUS_WRITE_BYTE_DATA == 0 {
return fmt.Errorf("SMBus write byte data not supported")
}
var data = val
return d.smbusAccess(I2C_SMBUS_WRITE, reg, I2C_SMBUS_BYTE_DATA, uintptr(unsafe.Pointer(&data)))
return d.smbusAccess(I2C_SMBUS_WRITE, reg, I2C_SMBUS_BYTE_DATA, unsafe.Pointer(&data))
}
// WriteWordData writes the given 16 bit value starting from the given register of an i2c device.
func (d *i2cDevice) WriteWordData(reg uint8, val uint16) error {
if d.funcs&I2C_FUNC_SMBUS_WRITE_WORD_DATA == 0 {
return fmt.Errorf("SMBus write word data not supported")
}
var data = val
return d.smbusAccess(I2C_SMBUS_WRITE, reg, I2C_SMBUS_WORD_DATA, uintptr(unsafe.Pointer(&data)))
return d.smbusAccess(I2C_SMBUS_WRITE, reg, I2C_SMBUS_WORD_DATA, unsafe.Pointer(&data))
}
// WriteBlockData writes the given buffer starting from the given register of an i2c device.
func (d *i2cDevice) WriteBlockData(reg uint8, data []byte) error {
if len(data) > 32 {
lenWithReg := len(data) + 1
if lenWithReg > 33 {
return fmt.Errorf("Writing blocks larger than 32 bytes (%v) not supported", len(data))
}
@ -183,7 +187,7 @@ func (d *i2cDevice) WriteBlockData(reg uint8, data []byte) error {
return d.writeBlockDataFallback(reg, data)
}
return d.smbusAccess(I2C_SMBUS_WRITE, reg, I2C_SMBUS_BLOCK_DATA, uintptr(unsafe.Pointer(&data)))
return d.smbusAccess(I2C_SMBUS_WRITE, reg, uint32(lenWithReg), unsafe.Pointer(&data[0]))
}
// Read implements the io.ReadWriteCloser method by direct I2C read operations.
@ -196,20 +200,15 @@ func (d *i2cDevice) Write(b []byte) (n int, err error) {
return d.file.Write(b)
}
func (d *i2cDevice) smbusAccess(readWrite byte, command byte, size uint32, data uintptr) error {
smbus := &i2cSmbusIoctlData{
func (d *i2cDevice) smbusAccess(readWrite byte, command byte, size uint32, dataStart unsafe.Pointer) error {
smbus := i2cSmbusIoctlData{
readWrite: readWrite,
command: command,
size: size,
data: data,
data: dataStart, // the reflected value of unsafePointer equals uintptr(dataStart),
}
_, _, errno := Syscall(
syscall.SYS_IOCTL,
d.file.Fd(),
I2C_SMBUS,
uintptr(unsafe.Pointer(smbus)),
)
_, _, errno := Syscall(syscall.SYS_IOCTL, d.file, I2C_SMBUS, unsafe.Pointer(&smbus))
if errno != 0 {
return fmt.Errorf("Failed with syscall.Errno %v", errno)

View File

@ -10,340 +10,507 @@ import (
"gobot.io/x/gobot/gobottest"
)
func TestNewI2cDeviceClose(t *testing.T) {
fs := NewMockFilesystem([]string{
"/dev/i2c-1",
})
const dev = "/dev/i2c-1"
SetFilesystem(fs)
SetSyscall(&MockSyscall{})
i, err := NewI2cDevice("/dev/i2c-1")
var _ i2c.I2cDevice = i
gobottest.Assert(t, err, nil)
gobottest.Assert(t, i.Close(), nil)
func initTestI2cDeviceWithMockedSys() (*i2cDevice, *MockSyscall) {
SetFilesystem(NewMockFilesystem([]string{dev}))
msc := &MockSyscall{}
SetSyscall(msc)
d, err := NewI2cDevice(dev)
if err != nil {
panic(err)
}
return d, msc
}
func TestNewI2cDeviceQueryFuncError(t *testing.T) {
fs := NewMockFilesystem([]string{
"/dev/i2c-1",
})
SetFilesystem(fs)
SetSyscall(&MockSyscall{
Impl: func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) {
return 0, 0, 1
},
})
i, err := NewI2cDevice("/dev/i2c-1")
var _ i2c.I2cDevice = i
gobottest.Assert(t, err, errors.New("Querying functionality failed with syscall.Errno operation not permitted"))
func cleanTestI2cDevice() {
defer SetFilesystem(&NativeFilesystem{})
defer SetSyscall(&NativeSyscall{})
}
func TestNewI2cDevice(t *testing.T) {
fs := NewMockFilesystem([]string{})
SetFilesystem(fs)
SetSyscall(&MockSyscall{})
i, err := NewI2cDevice(os.DevNull)
gobottest.Assert(t, err.Error(), " : /dev/null: No such file.")
fs = NewMockFilesystem([]string{
"/dev/i2c-1",
})
SetFilesystem(fs)
i, err = NewI2cDevice("/dev/i2c-1")
gobottest.Assert(t, err, nil)
SetSyscall(&MockSyscall{})
i, err = NewI2cDevice("/dev/i2c-1")
var _ i2c.I2cDevice = i
gobottest.Assert(t, err, nil)
gobottest.Assert(t, i.SetAddress(0xff), nil)
buf := []byte{0x01, 0x02, 0x03}
n, err := i.Write(buf)
gobottest.Assert(t, n, len(buf))
gobottest.Assert(t, err, nil)
buf = make([]byte, 4)
n, err = i.Read(buf)
gobottest.Assert(t, n, 3)
gobottest.Assert(t, err, nil)
}
func TestNewI2cDeviceReadByte(t *testing.T) {
fs := NewMockFilesystem([]string{
"/dev/i2c-1",
})
SetFilesystem(fs)
i, err := NewI2cDevice("/dev/i2c-1")
var _ i2c.I2cDevice = i
gobottest.Assert(t, err, nil)
i.SetAddress(0xff)
i.funcs = I2C_FUNC_SMBUS_READ_BYTE
val, e := i.ReadByte()
gobottest.Assert(t, val, byte(0))
gobottest.Assert(t, e, nil)
}
func TestNewI2cDeviceReadByteError(t *testing.T) {
fs := NewMockFilesystem([]string{
"/dev/i2c-1",
})
SetFilesystem(fs)
i, err := NewI2cDevice("/dev/i2c-1")
var _ i2c.I2cDevice = i
gobottest.Assert(t, err, nil)
SetSyscall(&MockSyscall{
Impl: func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) {
return 0, 0, 1
var tests = map[string]struct {
dev string
wantErr string
}{
"ok": {
dev: dev,
},
})
i.SetAddress(0xff)
i.funcs = I2C_FUNC_SMBUS_READ_BYTE
_, e := i.ReadByte()
gobottest.Refute(t, e, nil)
"null": {
dev: os.DevNull,
wantErr: " : /dev/null: No such file.",
},
}
for name, tc := range tests {
t.Run(name, func(t *testing.T) {
// arrange
SetFilesystem(NewMockFilesystem([]string{dev}))
defer SetFilesystem(&NativeFilesystem{})
SetSyscall(&MockSyscall{})
defer SetSyscall(&NativeSyscall{})
// act
i, err := NewI2cDevice(tc.dev)
var _ i2c.I2cDevice = i
if tc.wantErr != "" {
gobottest.Refute(t, err, nil)
gobottest.Assert(t, err.Error(), tc.wantErr)
} else {
gobottest.Assert(t, err, nil)
}
})
}
}
func TestNewI2cDeviceReadByteNotSupported(t *testing.T) {
SetSyscall(&MockSyscall{})
i, err := NewI2cDevice("/dev/i2c-1")
var _ i2c.I2cDevice = i
gobottest.Assert(t, err, nil)
i.SetAddress(0xff)
_, err = i.ReadByte()
gobottest.Assert(t, err.Error(), "SMBus read byte not supported")
func TestNewI2cDeviceQueryFuncError(t *testing.T) {
// arrange
SetFilesystem(NewMockFilesystem([]string{dev}))
defer SetFilesystem(&NativeFilesystem{})
SetSyscall(&MockSyscall{Impl: func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) { return 0, 0, 1 }})
defer SetSyscall(&NativeSyscall{})
// act
_, err := NewI2cDevice(dev)
// assert
gobottest.Assert(t, err, errors.New("Querying functionality failed with syscall.Errno operation not permitted"))
}
func TestNewI2cDeviceWriteByte(t *testing.T) {
fs := NewMockFilesystem([]string{
"/dev/i2c-1",
})
SetFilesystem(fs)
i, err := NewI2cDevice("/dev/i2c-1")
var _ i2c.I2cDevice = i
gobottest.Assert(t, err, nil)
i.SetAddress(0xff)
i.funcs = I2C_FUNC_SMBUS_WRITE_BYTE
e := i.WriteByte(0x01)
gobottest.Assert(t, e, nil)
func TestClose(t *testing.T) {
// arrange
d, _ := initTestI2cDeviceWithMockedSys()
defer cleanTestI2cDevice()
// act & assert
gobottest.Assert(t, d.Close(), nil)
}
func TestNewI2cDeviceWriteByteNotSupported(t *testing.T) {
SetSyscall(&MockSyscall{})
i, err := NewI2cDevice("/dev/i2c-1")
var _ i2c.I2cDevice = i
func TestSetAddress(t *testing.T) {
// arrange
d, msc := initTestI2cDeviceWithMockedSys()
defer cleanTestI2cDevice()
// act
err := d.SetAddress(0xff)
// assert
gobottest.Assert(t, err, nil)
i.SetAddress(0xff)
err = i.WriteByte(0x01)
gobottest.Assert(t, err.Error(), "SMBus write byte not supported")
gobottest.Assert(t, msc.devAddress, uintptr(0xff))
}
func TestNewI2cDeviceReadByteData(t *testing.T) {
fs := NewMockFilesystem([]string{
"/dev/i2c-1",
})
SetFilesystem(fs)
i, err := NewI2cDevice("/dev/i2c-1")
var _ i2c.I2cDevice = i
gobottest.Assert(t, err, nil)
i.SetAddress(0xff)
i.funcs = I2C_FUNC_SMBUS_READ_BYTE_DATA
v, e := i.ReadByteData(0x01)
gobottest.Assert(t, v, byte(0))
gobottest.Assert(t, e, nil)
func TestWriteRead(t *testing.T) {
// arrange
d, _ := initTestI2cDeviceWithMockedSys()
defer cleanTestI2cDevice()
wbuf := []byte{0x01, 0x02, 0x03}
rbuf := make([]byte, 4)
// act
wn, werr := d.Write(wbuf)
rn, rerr := d.Read(rbuf)
// assert
gobottest.Assert(t, werr, nil)
gobottest.Assert(t, rerr, nil)
gobottest.Assert(t, wn, len(wbuf))
gobottest.Assert(t, rn, len(wbuf)) // will read only the written values
gobottest.Assert(t, wbuf, rbuf[:len(wbuf)])
}
func TestNewI2cDeviceReadByteDataNotSupported(t *testing.T) {
SetSyscall(&MockSyscall{})
i, err := NewI2cDevice("/dev/i2c-1")
var _ i2c.I2cDevice = i
gobottest.Assert(t, err, nil)
i.SetAddress(0xff)
_, err = i.ReadByteData(0x01)
gobottest.Assert(t, err.Error(), "SMBus read byte data not supported")
func TestReadByte(t *testing.T) {
var tests = map[string]struct {
funcs uint64
syscallImpl func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno)
wantErr string
}{
"read_byte_ok": {
funcs: I2C_FUNC_SMBUS_READ_BYTE,
},
"error_syscall": {
funcs: I2C_FUNC_SMBUS_READ_BYTE,
syscallImpl: func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) { return 0, 0, 1 },
wantErr: "Failed with syscall.Errno operation not permitted",
},
"error_not_supported": {
wantErr: "SMBus read byte not supported",
},
}
for name, tc := range tests {
t.Run(name, func(t *testing.T) {
// arrange
d, msc := initTestI2cDeviceWithMockedSys()
defer cleanTestI2cDevice()
msc.Impl = tc.syscallImpl
d.funcs = tc.funcs
const want = byte(5)
msc.dataSlice = []byte{want}
// act
got, err := d.ReadByte()
// assert
if tc.wantErr != "" {
gobottest.Refute(t, err, nil)
gobottest.Assert(t, err.Error(), tc.wantErr)
} else {
gobottest.Assert(t, err, nil)
gobottest.Assert(t, got, want)
gobottest.Assert(t, msc.lastFile, d.file)
gobottest.Assert(t, msc.lastSignal, uintptr(I2C_SMBUS))
gobottest.Assert(t, msc.smbus.readWrite, byte(I2C_SMBUS_READ))
gobottest.Assert(t, msc.smbus.command, byte(0)) // register is set to 0 in that case
gobottest.Assert(t, msc.smbus.size, uint32(I2C_SMBUS_BYTE))
}
})
}
}
func TestNewI2cDeviceWriteByteData(t *testing.T) {
fs := NewMockFilesystem([]string{
"/dev/i2c-1",
})
SetFilesystem(fs)
i, err := NewI2cDevice("/dev/i2c-1")
var _ i2c.I2cDevice = i
gobottest.Assert(t, err, nil)
i.SetAddress(0xff)
i.funcs = I2C_FUNC_SMBUS_WRITE_BYTE_DATA
e := i.WriteByteData(0x01, 0x02)
gobottest.Assert(t, e, nil)
func TestReadByteData(t *testing.T) {
var tests = map[string]struct {
funcs uint64
syscallImpl func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno)
wantErr string
}{
"read_byte_data_ok": {
funcs: I2C_FUNC_SMBUS_READ_BYTE_DATA,
},
"error_syscall": {
funcs: I2C_FUNC_SMBUS_READ_BYTE_DATA,
syscallImpl: func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) { return 0, 0, 1 },
wantErr: "Failed with syscall.Errno operation not permitted",
},
"error_not_supported": {
wantErr: "SMBus read byte data not supported",
},
}
for name, tc := range tests {
t.Run(name, func(t *testing.T) {
// arrange
d, msc := initTestI2cDeviceWithMockedSys()
defer cleanTestI2cDevice()
msc.Impl = tc.syscallImpl
d.funcs = tc.funcs
const (
reg = byte(0x01)
want = byte(0x02)
)
msc.dataSlice = []byte{want}
// act
got, err := d.ReadByteData(reg)
// assert
if tc.wantErr != "" {
gobottest.Refute(t, err, nil)
gobottest.Assert(t, err.Error(), tc.wantErr)
} else {
gobottest.Assert(t, err, nil)
gobottest.Assert(t, got, want)
gobottest.Assert(t, msc.lastFile, d.file)
gobottest.Assert(t, msc.lastSignal, uintptr(I2C_SMBUS))
gobottest.Assert(t, msc.smbus.readWrite, byte(I2C_SMBUS_READ))
gobottest.Assert(t, msc.smbus.command, reg)
gobottest.Assert(t, msc.smbus.size, uint32(I2C_SMBUS_BYTE_DATA))
}
})
}
}
func TestNewI2cDeviceWriteByteDataNotSupported(t *testing.T) {
SetSyscall(&MockSyscall{})
i, err := NewI2cDevice("/dev/i2c-1")
var _ i2c.I2cDevice = i
gobottest.Assert(t, err, nil)
i.SetAddress(0xff)
err = i.WriteByteData(0x01, 0x01)
gobottest.Assert(t, err.Error(), "SMBus write byte data not supported")
func TestReadWordData(t *testing.T) {
var tests = map[string]struct {
funcs uint64
syscallImpl func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno)
wantErr string
}{
"read_word_data_ok": {
funcs: I2C_FUNC_SMBUS_READ_WORD_DATA,
},
"error_syscall": {
funcs: I2C_FUNC_SMBUS_READ_WORD_DATA,
syscallImpl: func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) { return 0, 0, 1 },
wantErr: "Failed with syscall.Errno operation not permitted",
},
"error_not_supported": {
wantErr: "SMBus read word data not supported",
},
}
for name, tc := range tests {
t.Run(name, func(t *testing.T) {
// arrange
d, msc := initTestI2cDeviceWithMockedSys()
defer cleanTestI2cDevice()
msc.Impl = tc.syscallImpl
d.funcs = tc.funcs
const (
reg = byte(0x02)
msbyte = byte(0xD4)
lsbyte = byte(0x31)
want = uint16(54321)
)
// all common drivers read LSByte first
msc.dataSlice = []byte{lsbyte, msbyte}
// act
got, err := d.ReadWordData(reg)
// assert
if tc.wantErr != "" {
gobottest.Refute(t, err, nil)
gobottest.Assert(t, err.Error(), tc.wantErr)
} else {
gobottest.Assert(t, err, nil)
gobottest.Assert(t, got, want)
gobottest.Assert(t, msc.lastFile, d.file)
gobottest.Assert(t, msc.lastSignal, uintptr(I2C_SMBUS))
gobottest.Assert(t, msc.smbus.readWrite, byte(I2C_SMBUS_READ))
gobottest.Assert(t, msc.smbus.command, reg)
gobottest.Assert(t, msc.smbus.size, uint32(I2C_SMBUS_WORD_DATA))
}
})
}
}
func TestNewI2cDeviceReadWordData(t *testing.T) {
fs := NewMockFilesystem([]string{
"/dev/i2c-1",
})
SetFilesystem(fs)
i, err := NewI2cDevice("/dev/i2c-1")
var _ i2c.I2cDevice = i
gobottest.Assert(t, err, nil)
i.SetAddress(0xff)
i.funcs = I2C_FUNC_SMBUS_READ_WORD_DATA
v, e := i.ReadWordData(0x01)
gobottest.Assert(t, v, uint16(0))
gobottest.Assert(t, e, nil)
func TestReadBlockData(t *testing.T) {
var tests = map[string]struct {
funcs uint64
syscallImpl func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno)
wantErr string
}{
"read_block_data_ok": {
funcs: I2C_FUNC_SMBUS_READ_BLOCK_DATA,
},
"error_syscall": {
funcs: I2C_FUNC_SMBUS_READ_BLOCK_DATA,
syscallImpl: func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) { return 0, 0, 1 },
wantErr: "Failed with syscall.Errno operation not permitted",
},
"error_from_used_fallback_if_not_supported": {
wantErr: "Read 1 bytes from device by sysfs, expected 3",
},
}
for name, tc := range tests {
t.Run(name, func(t *testing.T) {
// arrange
d, msc := initTestI2cDeviceWithMockedSys()
defer cleanTestI2cDevice()
msc.Impl = tc.syscallImpl
d.funcs = tc.funcs
const (
reg = byte(0x03)
wantByte0 = byte(0x11)
wantByte1 = byte(0x22)
wantByte2 = byte(0x33)
)
msc.dataSlice = []byte{wantByte0, wantByte1, wantByte2}
wantSize := uint32(len(msc.dataSlice) + 1) // register is also part of send data
buf := []byte{17, 28, 39}
// act
err := d.ReadBlockData(reg, buf)
// assert
if tc.wantErr != "" {
gobottest.Refute(t, err, nil)
gobottest.Assert(t, err.Error(), tc.wantErr)
} else {
gobottest.Assert(t, err, nil)
gobottest.Assert(t, buf, msc.dataSlice)
gobottest.Assert(t, msc.lastFile, d.file)
gobottest.Assert(t, msc.lastSignal, uintptr(I2C_SMBUS))
gobottest.Assert(t, msc.smbus.readWrite, byte(I2C_SMBUS_READ))
gobottest.Assert(t, msc.smbus.command, reg)
gobottest.Assert(t, msc.smbus.size, wantSize)
}
})
}
}
func TestNewI2cDeviceReadWordDataNotSupported(t *testing.T) {
SetSyscall(&MockSyscall{})
i, err := NewI2cDevice("/dev/i2c-1")
var _ i2c.I2cDevice = i
gobottest.Assert(t, err, nil)
i.SetAddress(0xff)
_, err = i.ReadWordData(0x01)
gobottest.Assert(t, err.Error(), "SMBus read word data not supported")
func TestWriteByte(t *testing.T) {
var tests = map[string]struct {
funcs uint64
syscallImpl func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno)
wantErr string
}{
"write_byte_ok": {
funcs: I2C_FUNC_SMBUS_WRITE_BYTE,
},
"error_syscall": {
funcs: I2C_FUNC_SMBUS_WRITE_BYTE,
syscallImpl: func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) { return 0, 0, 1 },
wantErr: "Failed with syscall.Errno operation not permitted",
},
"error_not_supported": {
wantErr: "SMBus write byte not supported",
},
}
for name, tc := range tests {
t.Run(name, func(t *testing.T) {
// arrange
d, msc := initTestI2cDeviceWithMockedSys()
defer cleanTestI2cDevice()
msc.Impl = tc.syscallImpl
d.funcs = tc.funcs
const val = byte(0x44)
// act
err := d.WriteByte(val)
// assert
if tc.wantErr != "" {
gobottest.Refute(t, err, nil)
gobottest.Assert(t, err.Error(), tc.wantErr)
} else {
gobottest.Assert(t, err, nil)
gobottest.Assert(t, msc.lastFile, d.file)
gobottest.Assert(t, msc.lastSignal, uintptr(I2C_SMBUS))
gobottest.Assert(t, msc.smbus.readWrite, byte(I2C_SMBUS_WRITE))
gobottest.Assert(t, msc.smbus.command, val) // in byte write, the register/command is used for the value
gobottest.Assert(t, msc.smbus.size, uint32(I2C_SMBUS_BYTE))
}
})
}
}
func TestNewI2cDeviceWriteWordData(t *testing.T) {
fs := NewMockFilesystem([]string{
"/dev/i2c-1",
})
SetFilesystem(fs)
i, err := NewI2cDevice("/dev/i2c-1")
var _ i2c.I2cDevice = i
gobottest.Assert(t, err, nil)
i.SetAddress(0xff)
i.funcs = I2C_FUNC_SMBUS_WRITE_WORD_DATA
e := i.WriteWordData(0x01, 0x0102)
gobottest.Assert(t, e, nil)
func TestWriteByteData(t *testing.T) {
var tests = map[string]struct {
funcs uint64
syscallImpl func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno)
wantErr string
}{
"write_byte_data_ok": {
funcs: I2C_FUNC_SMBUS_WRITE_BYTE_DATA,
},
"error_syscall": {
funcs: I2C_FUNC_SMBUS_WRITE_BYTE_DATA,
syscallImpl: func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) { return 0, 0, 1 },
wantErr: "Failed with syscall.Errno operation not permitted",
},
"error_not_supported": {
wantErr: "SMBus write byte data not supported",
},
}
for name, tc := range tests {
t.Run(name, func(t *testing.T) {
// arrange
d, msc := initTestI2cDeviceWithMockedSys()
defer cleanTestI2cDevice()
msc.Impl = tc.syscallImpl
d.funcs = tc.funcs
const (
reg = byte(0x04)
val = byte(0x55)
)
// act
err := d.WriteByteData(reg, val)
// assert
if tc.wantErr != "" {
gobottest.Refute(t, err, nil)
gobottest.Assert(t, err.Error(), tc.wantErr)
} else {
gobottest.Assert(t, err, nil)
gobottest.Assert(t, msc.lastFile, d.file)
gobottest.Assert(t, msc.lastSignal, uintptr(I2C_SMBUS))
gobottest.Assert(t, msc.smbus.readWrite, byte(I2C_SMBUS_WRITE))
gobottest.Assert(t, msc.smbus.command, reg)
gobottest.Assert(t, msc.smbus.size, uint32(I2C_SMBUS_BYTE_DATA))
gobottest.Assert(t, len(msc.dataSlice), 1)
gobottest.Assert(t, msc.dataSlice[0], val)
}
})
}
}
func TestNewI2cDeviceWriteWordDataNotSupported(t *testing.T) {
SetSyscall(&MockSyscall{})
i, err := NewI2cDevice("/dev/i2c-1")
var _ i2c.I2cDevice = i
gobottest.Assert(t, err, nil)
i.SetAddress(0xff)
err = i.WriteWordData(0x01, 0x01)
gobottest.Assert(t, err.Error(), "SMBus write word data not supported")
func TestWriteWordData(t *testing.T) {
var tests = map[string]struct {
funcs uint64
syscallImpl func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno)
wantErr string
}{
"write_word_data_ok": {
funcs: I2C_FUNC_SMBUS_WRITE_WORD_DATA,
},
"error_syscall": {
funcs: I2C_FUNC_SMBUS_WRITE_WORD_DATA,
syscallImpl: func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) { return 0, 0, 1 },
wantErr: "Failed with syscall.Errno operation not permitted",
},
"error_not_supported": {
wantErr: "SMBus write word data not supported",
},
}
for name, tc := range tests {
t.Run(name, func(t *testing.T) {
// arrange
d, msc := initTestI2cDeviceWithMockedSys()
defer cleanTestI2cDevice()
msc.Impl = tc.syscallImpl
d.funcs = tc.funcs
const (
reg = byte(0x05)
val = uint16(54321)
wantLSByte = byte(0x31)
wantMSByte = byte(0xD4)
)
// act
err := d.WriteWordData(reg, val)
// assert
if tc.wantErr != "" {
gobottest.Refute(t, err, nil)
gobottest.Assert(t, err.Error(), tc.wantErr)
} else {
gobottest.Assert(t, err, nil)
gobottest.Assert(t, msc.lastFile, d.file)
gobottest.Assert(t, msc.lastSignal, uintptr(I2C_SMBUS))
gobottest.Assert(t, msc.smbus.readWrite, byte(I2C_SMBUS_WRITE))
gobottest.Assert(t, msc.smbus.command, reg)
gobottest.Assert(t, msc.smbus.size, uint32(I2C_SMBUS_WORD_DATA))
gobottest.Assert(t, len(msc.dataSlice), 2)
// all common drivers write LSByte first
gobottest.Assert(t, msc.dataSlice[0], wantLSByte)
gobottest.Assert(t, msc.dataSlice[1], wantMSByte)
}
})
}
}
func TestNewI2cDeviceWriteBlockData(t *testing.T) {
fs := NewMockFilesystem([]string{
"/dev/i2c-1",
})
SetFilesystem(fs)
i, err := NewI2cDevice("/dev/i2c-1")
var _ i2c.I2cDevice = i
gobottest.Assert(t, err, nil)
i.SetAddress(0xff)
e := i.WriteBlockData(0x01, []byte{0x01, 0x02, 0x03})
gobottest.Assert(t, e, nil)
func TestWriteBlockData(t *testing.T) {
var tests = map[string]struct {
funcs uint64
syscallImpl func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno)
wantErr string
}{
"write_word_data_ok": {
funcs: I2C_FUNC_SMBUS_WRITE_BLOCK_DATA,
},
"error_syscall": {
funcs: I2C_FUNC_SMBUS_WRITE_BLOCK_DATA,
syscallImpl: func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) { return 0, 0, 1 },
wantErr: "Failed with syscall.Errno operation not permitted",
},
}
for name, tc := range tests {
t.Run(name, func(t *testing.T) {
// arrange
d, msc := initTestI2cDeviceWithMockedSys()
defer cleanTestI2cDevice()
msc.Impl = tc.syscallImpl
d.funcs = tc.funcs
const (
reg = byte(0x06)
byte0 = byte(0x66)
byte1 = byte(0x77)
byte2 = byte(0x88)
)
data := []byte{byte0, byte1, byte2}
wantSize := uint32(len(data) + 1) // register is also part of send data
// act
err := d.WriteBlockData(reg, data)
// assert
if tc.wantErr != "" {
gobottest.Refute(t, err, nil)
gobottest.Assert(t, err.Error(), tc.wantErr)
} else {
gobottest.Assert(t, err, nil)
gobottest.Assert(t, msc.lastFile, d.file)
gobottest.Assert(t, msc.lastSignal, uintptr(I2C_SMBUS))
gobottest.Assert(t, msc.smbus.readWrite, byte(I2C_SMBUS_WRITE))
gobottest.Assert(t, msc.smbus.command, reg)
gobottest.Assert(t, msc.smbus.size, wantSize)
gobottest.Assert(t, msc.dataSlice, data)
}
})
}
}
func TestNewI2cDeviceWriteBlockDataTooMuch(t *testing.T) {
fs := NewMockFilesystem([]string{
"/dev/i2c-1",
})
SetFilesystem(fs)
i, err := NewI2cDevice("/dev/i2c-1")
var _ i2c.I2cDevice = i
gobottest.Assert(t, err, nil)
i.SetAddress(0xff)
var data []byte
data = make([]byte, 33)
e := i.WriteBlockData(0x01, data)
gobottest.Assert(t, e, errors.New("Writing blocks larger than 32 bytes (33) not supported"))
}
func TestNewI2cDeviceWrite(t *testing.T) {
SetSyscall(&MockSyscall{})
i, err := NewI2cDevice("/dev/i2c-1")
var _ i2c.I2cDevice = i
gobottest.Assert(t, err, nil)
i.SetAddress(0xff)
buf := []byte{0x01, 0x02, 0x03}
n, err := i.Write(buf)
gobottest.Assert(t, n, len(buf))
gobottest.Assert(t, err, nil)
func TestWriteBlockDataTooMuch(t *testing.T) {
// arrange
SetFilesystem(NewMockFilesystem([]string{dev}))
defer SetFilesystem(&NativeFilesystem{})
d, _ := NewI2cDevice(dev)
// act
err := d.WriteBlockData(0x01, make([]byte, 33))
// assert
gobottest.Assert(t, err, errors.New("Writing blocks larger than 32 bytes (33) not supported"))
}

View File

@ -21,6 +21,7 @@ func TestPwmPin(t *testing.T) {
})
SetFilesystem(fs)
defer SetFilesystem(&NativeFilesystem{})
pin := NewPWMPin(10)
gobottest.Assert(t, pin.pin, "10")
@ -73,6 +74,7 @@ func TestPwmPinAlreadyExported(t *testing.T) {
})
SetFilesystem(fs)
defer SetFilesystem(&NativeFilesystem{})
pin := NewPWMPin(10)
pin.write = func(string, []byte) (int, error) {
@ -93,6 +95,7 @@ func TestPwmPinExportError(t *testing.T) {
})
SetFilesystem(fs)
defer SetFilesystem(&NativeFilesystem{})
pin := NewPWMPin(10)
pin.write = func(string, []byte) (int, error) {
@ -113,6 +116,7 @@ func TestPwmPinUnxportError(t *testing.T) {
})
SetFilesystem(fs)
defer SetFilesystem(&NativeFilesystem{})
pin := NewPWMPin(10)
pin.write = func(string, []byte) (int, error) {
@ -132,6 +136,7 @@ func TestPwmPinPeriodError(t *testing.T) {
})
SetFilesystem(fs)
defer SetFilesystem(&NativeFilesystem{})
pin := NewPWMPin(10)
pin.read = func(string) ([]byte, error) {
@ -152,6 +157,7 @@ func TestPwmPinPolarityError(t *testing.T) {
})
SetFilesystem(fs)
defer SetFilesystem(&NativeFilesystem{})
pin := NewPWMPin(10)
pin.read = func(string) ([]byte, error) {
@ -172,6 +178,7 @@ func TestPwmPinDutyCycleError(t *testing.T) {
})
SetFilesystem(fs)
defer SetFilesystem(&NativeFilesystem{})
pin := NewPWMPin(10)
pin.read = func(string) ([]byte, error) {

View File

@ -2,19 +2,27 @@ package sysfs
import (
"syscall"
"unsafe"
)
// SystemCaller represents a Syscall
// Prevent unsafe call, since go 1.15, see "Pattern 4" in: https://go101.org/article/unsafe.html
type SystemCaller interface {
Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno)
Syscall(trap uintptr, f File, signal uintptr, payload unsafe.Pointer) (r1, r2 uintptr, err syscall.Errno)
}
// NativeSyscall represents the native Syscall
type NativeSyscall struct{}
// MockSyscall represents the mock Syscall
// MockSyscall represents the mock Syscall used for unit tests
type MockSyscall struct {
Impl func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno)
lastTrap uintptr
lastFile File
lastSignal uintptr
devAddress uintptr
smbus *i2cSmbusIoctlData
dataSlice []byte
Impl func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno)
}
var sys SystemCaller = &NativeSyscall{}
@ -25,19 +33,53 @@ func SetSyscall(s SystemCaller) {
}
// Syscall calls either the NativeSyscall or user defined Syscall
func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) {
return sys.Syscall(trap, a1, a2, a3)
func Syscall(trap uintptr, f File, a2 uintptr, payload unsafe.Pointer) (r1, r2 uintptr, err syscall.Errno) {
return sys.Syscall(trap, f, a2, payload)
}
// Syscall calls syscall.Syscall
func (sys *NativeSyscall) Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) {
return syscall.Syscall(trap, a1, a2, a3)
// Syscall calls the native syscall.Syscall, implements the SystemCaller interface
func (sys *NativeSyscall) Syscall(trap uintptr, f File, signal uintptr, payload unsafe.Pointer) (r1, r2 uintptr, err syscall.Errno) {
return syscall.Syscall(trap, f.Fd(), signal, uintptr(payload))
}
// Syscall implements the SystemCaller interface
func (sys *MockSyscall) Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) {
// Syscall calls the user defined implementation, used for tests, implements the SystemCaller interface
func (sys *MockSyscall) Syscall(trap uintptr, f File, signal uintptr, payload unsafe.Pointer) (r1, r2 uintptr, err syscall.Errno) {
sys.lastTrap = trap // points to the used syscall (e.g. "SYS_IOCTL")
sys.lastFile = f // a character device file (e.g. file to path "/dev/i2c-1")
sys.lastSignal = signal // points to used function type (e.g. I2C_SMBUS, I2C_RDWR)
if signal == I2C_SLAVE {
// in this case the uintptr corresponds the address
sys.devAddress = uintptr(payload)
}
if signal == I2C_SMBUS {
// set the I2C smbus data object reference to payload and fill with some data
sys.smbus = (*i2cSmbusIoctlData)(payload)
// get the data object payload as byte slice
if sys.smbus.readWrite == I2C_SMBUS_WRITE {
if sys.smbus.data != nil {
sys.dataSlice = unsafe.Slice((*byte)(unsafe.Pointer(sys.smbus.data)), sys.smbus.size-1)
}
}
// fill data object with data from given slice to simulate reading
if sys.smbus.readWrite == I2C_SMBUS_READ {
if sys.dataSlice != nil {
dataSize := sys.smbus.size - 1
if sys.smbus.size == I2C_SMBUS_BYTE {
dataSize = 1
}
slc := unsafe.Slice((*byte)(unsafe.Pointer(sys.smbus.data)), dataSize)
copy(slc, sys.dataSlice)
}
}
}
// call mock implementation
if sys.Impl != nil {
return sys.Impl(trap, a1, a2, a3)
return sys.Impl(trap, f.Fd(), signal, uintptr(unsafe.Pointer(payload)))
}
return 0, 0, 0
}