package jetson import ( "errors" "strings" "testing" "runtime" "strconv" "sync" "gobot.io/x/gobot" "gobot.io/x/gobot/drivers/gpio" "gobot.io/x/gobot/drivers/i2c" "gobot.io/x/gobot/drivers/spi" "gobot.io/x/gobot/gobottest" "gobot.io/x/gobot/system" ) // make sure that this Adaptor fulfills all the required interfaces var _ gobot.Adaptor = (*Adaptor)(nil) var _ gobot.DigitalPinnerProvider = (*Adaptor)(nil) var _ gobot.PWMPinnerProvider = (*Adaptor)(nil) var _ gpio.DigitalReader = (*Adaptor)(nil) var _ gpio.DigitalWriter = (*Adaptor)(nil) var _ i2c.Connector = (*Adaptor)(nil) var _ spi.Connector = (*Adaptor)(nil) func initTestAdaptorWithMockedFilesystem(mockPaths []string) (*Adaptor, *system.MockFilesystem) { a := NewAdaptor() fs := a.sys.UseMockFilesystem(mockPaths) if err := a.Connect(); err != nil { panic(err) } return a, fs } func TestNewAdaptor(t *testing.T) { a := NewAdaptor() gobottest.Assert(t, strings.HasPrefix(a.Name(), "JetsonNano"), true) gobottest.Assert(t, a.GetDefaultBus(), 1) a.SetName("NewName") gobottest.Assert(t, a.Name(), "NewName") } func TestFinalize(t *testing.T) { mockPaths := []string{ "/sys/class/gpio/export", "/sys/class/gpio/unexport", "/dev/i2c-1", "/dev/i2c-0", "/dev/spidev0.0", "/dev/spidev0.1", } a, _ := initTestAdaptorWithMockedFilesystem(mockPaths) a.DigitalWrite("3", 1) a.GetConnection(0xff, 0) gobottest.Assert(t, a.Finalize(), nil) } func TestPWMPinsConnect(t *testing.T) { a := NewAdaptor() gobottest.Assert(t, a.pwmPins, (map[string]gobot.PWMPinner)(nil)) err := a.PwmWrite("33", 1) gobottest.Assert(t, err.Error(), "not connected") err = a.Connect() gobottest.Assert(t, err, nil) gobottest.Refute(t, a.pwmPins, (map[string]gobot.PWMPinner)(nil)) gobottest.Assert(t, len(a.pwmPins), 0) } func TestPWMPinsReConnect(t *testing.T) { // arrange mockPaths := []string{ "/sys/class/pwm/pwmchip0/export", "/sys/class/pwm/pwmchip0/unexport", "/sys/class/pwm/pwmchip0/pwm2/duty_cycle", "/sys/class/pwm/pwmchip0/pwm2/period", "/sys/class/pwm/pwmchip0/pwm2/enable", } a, _ := initTestAdaptorWithMockedFilesystem(mockPaths) gobottest.Assert(t, len(a.pwmPins), 0) gobottest.Assert(t, a.PwmWrite("33", 1), nil) gobottest.Assert(t, len(a.pwmPins), 1) gobottest.Assert(t, a.Finalize(), nil) // act err := a.Connect() // assert gobottest.Assert(t, err, nil) gobottest.Assert(t, len(a.pwmPins), 0) } func TestDigitalIO(t *testing.T) { mockPaths := []string{ "/sys/class/gpio/export", "/sys/class/gpio/unexport", "/sys/class/gpio/gpio216/value", "/sys/class/gpio/gpio216/direction", "/sys/class/gpio/gpio14/value", "/sys/class/gpio/gpio14/direction", } a, fs := initTestAdaptorWithMockedFilesystem(mockPaths) err := a.DigitalWrite("7", 1) gobottest.Assert(t, err, nil) gobottest.Assert(t, fs.Files["/sys/class/gpio/gpio216/value"].Contents, "1") err = a.DigitalWrite("13", 1) gobottest.Assert(t, err, nil) i, err := a.DigitalRead("13") gobottest.Assert(t, err, nil) gobottest.Assert(t, i, 1) gobottest.Assert(t, a.DigitalWrite("notexist", 1), errors.New("'notexist' is not a valid id for a digital pin")) gobottest.Assert(t, a.Finalize(), nil) } func TestI2c(t *testing.T) { a, _ := initTestAdaptorWithMockedFilesystem([]string{"/dev/i2c-1"}) a.sys.UseMockSyscall() con, err := a.GetConnection(0xff, 1) gobottest.Assert(t, err, nil) _, err = con.Write([]byte{0x00, 0x01}) gobottest.Assert(t, err, nil) data := []byte{42, 42} _, err = con.Read(data) gobottest.Assert(t, err, nil) gobottest.Assert(t, data, []byte{0x00, 0x01}) _, err = a.GetConnection(0xff, 51) gobottest.Assert(t, err, errors.New("Bus number 51 out of range")) gobottest.Assert(t, a.GetDefaultBus(), 1) } func TestSPI(t *testing.T) { a := NewAdaptor() gobottest.Assert(t, a.GetSpiDefaultBus(), 0) gobottest.Assert(t, a.GetSpiDefaultChip(), 0) gobottest.Assert(t, a.GetSpiDefaultMode(), 0) gobottest.Assert(t, a.GetSpiDefaultMaxSpeed(), int64(10000000)) _, err := a.GetSpiConnection(10, 0, 0, 8, 10000000) gobottest.Assert(t, err.Error(), "Bus number 10 out of range") // TODO: tests for real connection currently not possible, because not using system.Accessor using // TODO: test tx/rx here... } func TestDigitalPinConcurrency(t *testing.T) { oldProcs := runtime.GOMAXPROCS(0) runtime.GOMAXPROCS(8) defer runtime.GOMAXPROCS(oldProcs) for retry := 0; retry < 20; retry++ { a := NewAdaptor() var wg sync.WaitGroup for i := 0; i < 20; i++ { wg.Add(1) pinAsString := strconv.Itoa(i) go func(pin string) { defer wg.Done() a.DigitalPin(pin) }(pinAsString) } wg.Wait() } }