gobot.io/x/gobot/v2@v2.1.0/platforms/upboard/up2/adaptor_test.go (about) 1 package up2 2 3 import ( 4 "errors" 5 "fmt" 6 "strings" 7 "testing" 8 9 "gobot.io/x/gobot/v2" 10 "gobot.io/x/gobot/v2/drivers/gpio" 11 "gobot.io/x/gobot/v2/drivers/i2c" 12 "gobot.io/x/gobot/v2/drivers/spi" 13 "gobot.io/x/gobot/v2/gobottest" 14 "gobot.io/x/gobot/v2/system" 15 ) 16 17 // make sure that this Adaptor fulfills all the required interfaces 18 var _ gobot.Adaptor = (*Adaptor)(nil) 19 var _ gobot.DigitalPinnerProvider = (*Adaptor)(nil) 20 var _ gobot.PWMPinnerProvider = (*Adaptor)(nil) 21 var _ gpio.DigitalReader = (*Adaptor)(nil) 22 var _ gpio.DigitalWriter = (*Adaptor)(nil) 23 var _ gpio.PwmWriter = (*Adaptor)(nil) 24 var _ gpio.ServoWriter = (*Adaptor)(nil) 25 var _ i2c.Connector = (*Adaptor)(nil) 26 var _ spi.Connector = (*Adaptor)(nil) 27 28 var pwmMockPaths = []string{ 29 "/sys/class/pwm/pwmchip0/export", 30 "/sys/class/pwm/pwmchip0/unexport", 31 "/sys/class/pwm/pwmchip0/pwm0/enable", 32 "/sys/class/pwm/pwmchip0/pwm0/period", 33 "/sys/class/pwm/pwmchip0/pwm0/duty_cycle", 34 "/sys/class/pwm/pwmchip0/pwm0/polarity", 35 } 36 37 var gpioMockPaths = []string{ 38 "/sys/class/gpio/export", 39 "/sys/class/gpio/unexport", 40 "/sys/class/gpio/gpio462/value", 41 "/sys/class/gpio/gpio462/direction", 42 "/sys/class/gpio/gpio432/value", 43 "/sys/class/gpio/gpio432/direction", 44 "/sys/class/leds/upboard:green:/brightness", 45 } 46 47 func initTestAdaptorWithMockedFilesystem(mockPaths []string) (*Adaptor, *system.MockFilesystem) { 48 a := NewAdaptor() 49 fs := a.sys.UseMockFilesystem(mockPaths) 50 if err := a.Connect(); err != nil { 51 panic(err) 52 } 53 return a, fs 54 } 55 56 func TestName(t *testing.T) { 57 a := NewAdaptor() 58 gobottest.Assert(t, strings.HasPrefix(a.Name(), "UP2"), true) 59 a.SetName("NewName") 60 gobottest.Assert(t, a.Name(), "NewName") 61 } 62 63 func TestDigitalIO(t *testing.T) { 64 a, fs := initTestAdaptorWithMockedFilesystem(gpioMockPaths) 65 66 a.DigitalWrite("7", 1) 67 gobottest.Assert(t, fs.Files["/sys/class/gpio/gpio462/value"].Contents, "1") 68 69 fs.Files["/sys/class/gpio/gpio432/value"].Contents = "1" 70 i, _ := a.DigitalRead("13") 71 gobottest.Assert(t, i, 1) 72 73 a.DigitalWrite("green", 1) 74 gobottest.Assert(t, 75 fs.Files["/sys/class/leds/upboard:green:/brightness"].Contents, 76 "1", 77 ) 78 79 gobottest.Assert(t, a.DigitalWrite("99", 1), errors.New("'99' is not a valid id for a digital pin")) 80 gobottest.Assert(t, a.Finalize(), nil) 81 } 82 83 func TestPWM(t *testing.T) { 84 a, fs := initTestAdaptorWithMockedFilesystem(pwmMockPaths) 85 86 err := a.PwmWrite("32", 100) 87 gobottest.Assert(t, err, nil) 88 89 gobottest.Assert(t, fs.Files["/sys/class/pwm/pwmchip0/export"].Contents, "0") 90 gobottest.Assert(t, fs.Files["/sys/class/pwm/pwmchip0/pwm0/enable"].Contents, "1") 91 gobottest.Assert(t, fs.Files["/sys/class/pwm/pwmchip0/pwm0/duty_cycle"].Contents, "3921568") 92 gobottest.Assert(t, fs.Files["/sys/class/pwm/pwmchip0/pwm0/polarity"].Contents, "normal") 93 94 err = a.ServoWrite("32", 0) 95 gobottest.Assert(t, err, nil) 96 97 gobottest.Assert(t, fs.Files["/sys/class/pwm/pwmchip0/pwm0/duty_cycle"].Contents, "500000") 98 99 err = a.ServoWrite("32", 180) 100 gobottest.Assert(t, err, nil) 101 102 gobottest.Assert(t, fs.Files["/sys/class/pwm/pwmchip0/pwm0/duty_cycle"].Contents, "2000000") 103 gobottest.Assert(t, a.Finalize(), nil) 104 } 105 106 func TestFinalizeErrorAfterGPIO(t *testing.T) { 107 a, fs := initTestAdaptorWithMockedFilesystem(gpioMockPaths) 108 109 gobottest.Assert(t, a.DigitalWrite("7", 1), nil) 110 111 fs.WithWriteError = true 112 113 err := a.Finalize() 114 gobottest.Assert(t, strings.Contains(err.Error(), "write error"), true) 115 } 116 117 func TestFinalizeErrorAfterPWM(t *testing.T) { 118 a, fs := initTestAdaptorWithMockedFilesystem(pwmMockPaths) 119 120 gobottest.Assert(t, a.PwmWrite("32", 1), nil) 121 122 fs.WithWriteError = true 123 124 err := a.Finalize() 125 gobottest.Assert(t, strings.Contains(err.Error(), "write error"), true) 126 } 127 128 func TestSpiDefaultValues(t *testing.T) { 129 a := NewAdaptor() 130 131 gobottest.Assert(t, a.SpiDefaultBusNumber(), 0) 132 gobottest.Assert(t, a.SpiDefaultMode(), 0) 133 gobottest.Assert(t, a.SpiDefaultMaxSpeed(), int64(500000)) 134 } 135 136 func Test_validateSpiBusNumber(t *testing.T) { 137 var tests = map[string]struct { 138 busNr int 139 wantErr error 140 }{ 141 "number_negative_error": { 142 busNr: -1, 143 wantErr: fmt.Errorf("Bus number -1 out of range"), 144 }, 145 "number_0_ok": { 146 busNr: 0, 147 }, 148 "number_1_ok": { 149 busNr: 1, 150 }, 151 "number_2_error": { 152 busNr: 2, 153 wantErr: fmt.Errorf("Bus number 2 out of range"), 154 }, 155 } 156 for name, tc := range tests { 157 t.Run(name, func(t *testing.T) { 158 // arrange 159 a := NewAdaptor() 160 // act 161 err := a.validateSpiBusNumber(tc.busNr) 162 // assert 163 gobottest.Assert(t, err, tc.wantErr) 164 }) 165 } 166 } 167 168 func TestI2cDefaultBus(t *testing.T) { 169 a := NewAdaptor() 170 gobottest.Assert(t, a.DefaultI2cBus(), 5) 171 } 172 173 func TestI2cFinalizeWithErrors(t *testing.T) { 174 // arrange 175 a := NewAdaptor() 176 a.sys.UseMockSyscall() 177 fs := a.sys.UseMockFilesystem([]string{"/dev/i2c-5"}) 178 gobottest.Assert(t, a.Connect(), nil) 179 con, err := a.GetI2cConnection(0xff, 5) 180 gobottest.Assert(t, err, nil) 181 _, err = con.Write([]byte{0xbf}) 182 gobottest.Assert(t, err, nil) 183 fs.WithCloseError = true 184 // act 185 err = a.Finalize() 186 // assert 187 gobottest.Assert(t, strings.Contains(err.Error(), "close error"), true) 188 } 189 190 func Test_validateI2cBusNumber(t *testing.T) { 191 var tests = map[string]struct { 192 busNr int 193 wantErr error 194 }{ 195 "number_negative_error": { 196 busNr: -1, 197 wantErr: fmt.Errorf("Bus number -1 out of range"), 198 }, 199 "number_4_error": { 200 busNr: 4, 201 wantErr: fmt.Errorf("Bus number 4 out of range"), 202 }, 203 "number_5_ok": { 204 busNr: 5, 205 }, 206 "number_6_ok": { 207 busNr: 6, 208 }, 209 "number_7_error": { 210 busNr: 7, 211 wantErr: fmt.Errorf("Bus number 7 out of range"), 212 }, 213 } 214 for name, tc := range tests { 215 t.Run(name, func(t *testing.T) { 216 // arrange 217 a := NewAdaptor() 218 // act 219 err := a.validateI2cBusNumber(tc.busNr) 220 // assert 221 gobottest.Assert(t, err, tc.wantErr) 222 }) 223 } 224 } 225 226 func Test_translatePWMPin(t *testing.T) { 227 var tests = map[string]struct { 228 wantDir string 229 wantChannel int 230 wantErr error 231 }{ 232 "16": { 233 wantDir: "/sys/class/pwm/pwmchip0", 234 wantChannel: 3, 235 }, 236 "32": { 237 wantDir: "/sys/class/pwm/pwmchip0", 238 wantChannel: 0, 239 }, 240 "33": { 241 wantDir: "/sys/class/pwm/pwmchip0", 242 wantChannel: 1, 243 }, 244 "PWM0": { 245 wantDir: "", 246 wantChannel: -1, 247 wantErr: fmt.Errorf("'PWM0' is not a valid id for a pin"), 248 }, 249 "7": { 250 wantDir: "", 251 wantChannel: -1, 252 wantErr: fmt.Errorf("'7' is not a valid id for a PWM pin"), 253 }, 254 } 255 for name, tc := range tests { 256 t.Run(name, func(t *testing.T) { 257 // arrange 258 a := NewAdaptor() 259 // act 260 dir, channel, err := a.translatePWMPin(name) 261 // assert 262 gobottest.Assert(t, err, tc.wantErr) 263 gobottest.Assert(t, dir, tc.wantDir) 264 gobottest.Assert(t, channel, tc.wantChannel) 265 }) 266 } 267 }