gobot.io/x/gobot/v2@v2.1.0/drivers/i2c/mcp23017_driver_test.go (about) 1 package i2c 2 3 import ( 4 "errors" 5 "strings" 6 "testing" 7 8 "gobot.io/x/gobot/v2" 9 "gobot.io/x/gobot/v2/gobottest" 10 ) 11 12 // this ensures that the implementation is based on i2c.Driver, which implements the gobot.Driver 13 // and tests all implementations, so no further tests needed here for gobot.Driver interface 14 var _ gobot.Driver = (*MCP23017Driver)(nil) 15 16 var pinValPort = map[string]interface{}{ 17 "pin": uint8(7), 18 "val": uint8(0), 19 "port": "A", 20 } 21 22 var pinPort = map[string]interface{}{ 23 "pin": uint8(7), 24 "port": "A", 25 } 26 27 func initTestMCP23017(b uint8) (driver *MCP23017Driver) { 28 // create the driver without starting it 29 a := newI2cTestAdaptor() 30 d := NewMCP23017Driver(a, WithMCP23017Bank(b)) 31 return d 32 } 33 34 func initTestMCP23017WithStubbedAdaptor(b uint8) (*MCP23017Driver, *i2cTestAdaptor) { 35 // create the driver, ready to use for tests 36 a := newI2cTestAdaptor() 37 d := NewMCP23017Driver(a, WithMCP23017Bank(b)) 38 d.Start() 39 return d, a 40 } 41 42 func TestNewMCP23017Driver(t *testing.T) { 43 var di interface{} = NewMCP23017Driver(newI2cTestAdaptor()) 44 d, ok := di.(*MCP23017Driver) 45 if !ok { 46 t.Errorf("NewMCP23017Driver() should have returned a *MCP23017Driver") 47 } 48 gobottest.Refute(t, d.Driver, nil) 49 gobottest.Assert(t, strings.HasPrefix(d.Name(), "MCP23017"), true) 50 gobottest.Assert(t, d.defaultAddress, 0x20) 51 gobottest.Refute(t, d.mcpConf, nil) 52 gobottest.Refute(t, d.mcpBehav, nil) 53 } 54 55 func TestWithMCP23017Bank(t *testing.T) { 56 b := NewMCP23017Driver(newI2cTestAdaptor(), WithMCP23017Bank(1)) 57 gobottest.Assert(t, b.mcpConf.bank, uint8(1)) 58 } 59 60 func TestWithMCP23017Mirror(t *testing.T) { 61 b := NewMCP23017Driver(newI2cTestAdaptor(), WithMCP23017Mirror(1)) 62 gobottest.Assert(t, b.mcpConf.mirror, uint8(1)) 63 } 64 65 func TestWithMCP23017Seqop(t *testing.T) { 66 b := NewMCP23017Driver(newI2cTestAdaptor(), WithMCP23017Seqop(1)) 67 gobottest.Assert(t, b.mcpConf.seqop, uint8(1)) 68 } 69 70 func TestWithMCP23017Disslw(t *testing.T) { 71 b := NewMCP23017Driver(newI2cTestAdaptor(), WithMCP23017Disslw(1)) 72 gobottest.Assert(t, b.mcpConf.disslw, uint8(1)) 73 } 74 75 func TestWithMCP23017Haen(t *testing.T) { 76 b := NewMCP23017Driver(newI2cTestAdaptor(), WithMCP23017Haen(1)) 77 gobottest.Assert(t, b.mcpConf.haen, uint8(1)) 78 } 79 80 func TestWithMCP23017Odr(t *testing.T) { 81 b := NewMCP23017Driver(newI2cTestAdaptor(), WithMCP23017Odr(1)) 82 gobottest.Assert(t, b.mcpConf.odr, uint8(1)) 83 } 84 85 func TestWithMCP23017Intpol(t *testing.T) { 86 b := NewMCP23017Driver(newI2cTestAdaptor(), WithMCP23017Intpol(1)) 87 gobottest.Assert(t, b.mcpConf.intpol, uint8(1)) 88 } 89 90 func TestWithMCP23017ForceRefresh(t *testing.T) { 91 b := NewMCP23017Driver(newI2cTestAdaptor(), WithMCP23017ForceRefresh(1)) 92 gobottest.Assert(t, b.mcpBehav.forceRefresh, true) 93 } 94 95 func TestWithMCP23017AutoIODirOff(t *testing.T) { 96 b := NewMCP23017Driver(newI2cTestAdaptor(), WithMCP23017AutoIODirOff(1)) 97 gobottest.Assert(t, b.mcpBehav.autoIODirOff, true) 98 } 99 100 func TestMCP23017CommandsWriteGPIO(t *testing.T) { 101 // arrange 102 d, _ := initTestMCP23017WithStubbedAdaptor(0) 103 // act 104 result := d.Command("WriteGPIO")(pinValPort) 105 // assert 106 gobottest.Assert(t, result.(map[string]interface{})["err"], nil) 107 } 108 109 func TestMCP23017CommandsReadGPIO(t *testing.T) { 110 // arrange 111 d, _ := initTestMCP23017WithStubbedAdaptor(0) 112 // act 113 result := d.Command("ReadGPIO")(pinPort) 114 // assert 115 gobottest.Assert(t, result.(map[string]interface{})["err"], nil) 116 } 117 118 func TestMCP23017WriteGPIO(t *testing.T) { 119 // sequence to write (we force the refresh by preset with inverse bit state): 120 // * read current state of IODIR (write reg, read val) => see also SetPinMode() 121 // * set IODIR of pin to input (manipulate val, write reg, write val) => see also SetPinMode() 122 // * read current state of OLAT (write reg, read val) 123 // * write OLAT (manipulate val, write reg, write val) 124 // arrange 125 d, a := initTestMCP23017WithStubbedAdaptor(0) 126 for bitState := 0; bitState <= 1; bitState++ { 127 a.written = []byte{} // reset writes of Start() and former test 128 // arrange some values 129 testPort := "A" 130 testPin := uint8(7) 131 wantReg1 := uint8(0x00) // IODIRA 132 wantReg2 := uint8(0x14) // OLATA 133 returnRead := []uint8{0xFF, 0xFF} // emulate all IO's are inputs, emulate bit is on 134 wantReg1Val := returnRead[0] & 0x7F // IODIRA: bit 7 reset, all other untouched 135 wantReg2Val := returnRead[1] & 0x7F // OLATA: bit 7 reset, all other untouched 136 if bitState == 1 { 137 returnRead[1] = 0x7F // emulate bit is off 138 wantReg2Val = returnRead[1] | 0x80 // OLATA: bit 7 set, all other untouched 139 } 140 // arrange reads 141 numCallsRead := 0 142 a.i2cReadImpl = func(b []byte) (int, error) { 143 numCallsRead++ 144 b[len(b)-1] = returnRead[numCallsRead-1] 145 return len(b), nil 146 } 147 // act 148 err := d.WriteGPIO(testPin, testPort, uint8(bitState)) 149 // assert 150 gobottest.Assert(t, err, nil) 151 gobottest.Assert(t, len(a.written), 6) 152 gobottest.Assert(t, a.written[0], wantReg1) 153 gobottest.Assert(t, a.written[1], wantReg1) 154 gobottest.Assert(t, a.written[2], wantReg1Val) 155 gobottest.Assert(t, a.written[3], wantReg2) 156 gobottest.Assert(t, a.written[4], wantReg2) 157 gobottest.Assert(t, a.written[5], wantReg2Val) 158 gobottest.Assert(t, numCallsRead, 2) 159 } 160 } 161 162 func TestMCP23017WriteGPIONoRefresh(t *testing.T) { 163 // sequence to write with take advantage of refresh optimization (see forceRefresh): 164 // * read current state of IODIR (write reg, read val) => by SetPinMode() 165 // * read current state of OLAT (write reg, read val) 166 // arrange 167 d, a := initTestMCP23017WithStubbedAdaptor(0) 168 for bitState := 0; bitState <= 1; bitState++ { 169 a.written = []byte{} // reset writes of Start() and former test 170 // arrange some values 171 testPort := "B" 172 testPin := uint8(3) 173 wantReg1 := uint8(0x01) // IODIRB 174 wantReg2 := uint8(0x15) // OLATB 175 returnRead := []uint8{0xF7, 0xF7} // emulate all IO's are inputs except pin 3, emulate bit is already off 176 if bitState == 1 { 177 returnRead[1] = 0x08 // emulate bit is already on 178 } 179 // arrange reads 180 numCallsRead := 0 181 a.i2cReadImpl = func(b []byte) (int, error) { 182 numCallsRead++ 183 b[len(b)-1] = returnRead[numCallsRead-1] 184 return len(b), nil 185 } 186 // act 187 err := d.WriteGPIO(testPin, testPort, uint8(bitState)) 188 // assert 189 gobottest.Assert(t, err, nil) 190 gobottest.Assert(t, len(a.written), 2) 191 gobottest.Assert(t, a.written[0], wantReg1) 192 gobottest.Assert(t, a.written[1], wantReg2) 193 gobottest.Assert(t, numCallsRead, 2) 194 } 195 } 196 197 func TestMCP23017WriteGPIONoAutoDir(t *testing.T) { 198 // sequence to write with suppressed automatic setting of IODIR: 199 // * read current state of OLAT (write reg, read val) 200 // * write OLAT (manipulate val, write reg, write val) 201 // arrange 202 d, a := initTestMCP23017WithStubbedAdaptor(0) 203 d.mcpBehav.autoIODirOff = true 204 for bitState := 0; bitState <= 1; bitState++ { 205 a.written = []byte{} // reset writes of Start() and former test 206 // arrange some values 207 testPort := "A" 208 testPin := uint8(7) 209 wantReg := uint8(0x14) // OLATA 210 returnRead := uint8(0xFF) // emulate bit is on 211 wantRegVal := returnRead & 0x7F // OLATA: bit 7 reset, all other untouched 212 if bitState == 1 { 213 returnRead = 0x7F // emulate bit is off 214 wantRegVal = returnRead | 0x80 // OLATA: bit 7 set, all other untouched 215 } 216 // arrange reads 217 numCallsRead := 0 218 a.i2cReadImpl = func(b []byte) (int, error) { 219 numCallsRead++ 220 b[len(b)-1] = returnRead 221 return len(b), nil 222 } 223 // act 224 err := d.WriteGPIO(testPin, testPort, uint8(bitState)) 225 // assert 226 gobottest.Assert(t, err, nil) 227 gobottest.Assert(t, len(a.written), 3) 228 gobottest.Assert(t, a.written[0], wantReg) 229 gobottest.Assert(t, a.written[1], wantReg) 230 gobottest.Assert(t, a.written[2], wantRegVal) 231 gobottest.Assert(t, numCallsRead, 1) 232 } 233 } 234 235 func TestMCP23017CommandsWriteGPIOErrIODIR(t *testing.T) { 236 // arrange 237 d, a := initTestMCP23017WithStubbedAdaptor(0) 238 a.i2cWriteImpl = func([]byte) (int, error) { 239 return 0, errors.New("write error") 240 } 241 // act 242 err := d.WriteGPIO(7, "A", 0) 243 // assert 244 gobottest.Assert(t, err, errors.New("MCP write-read: MCP write-ReadByteData(reg=0): write error")) 245 } 246 247 func TestMCP23017CommandsWriteGPIOErrOLAT(t *testing.T) { 248 // arrange 249 d, a := initTestMCP23017WithStubbedAdaptor(0) 250 numCalls := 1 251 a.i2cWriteImpl = func([]byte) (int, error) { 252 if numCalls == 2 { 253 return 0, errors.New("write error") 254 } 255 numCalls++ 256 return 0, nil 257 } 258 // act 259 err := d.WriteGPIO(7, "A", 0) 260 // assert 261 gobottest.Assert(t, err, errors.New("MCP write-read: MCP write-ReadByteData(reg=20): write error")) 262 } 263 264 func TestMCP23017ReadGPIO(t *testing.T) { 265 // sequence to read: 266 // * read current state of IODIR (write reg, read val) => see also SetPinMode() 267 // * set IODIR of pin to input (manipulate val, write reg, write val) => see also SetPinMode() 268 // * read GPIO (write reg, read val) 269 // arrange 270 d, a := initTestMCP23017WithStubbedAdaptor(0) 271 for bitState := 0; bitState <= 1; bitState++ { 272 a.written = []byte{} // reset writes of Start() and former test 273 // arrange some values 274 testPort := "A" 275 testPin := uint8(7) 276 wantReg1 := uint8(0x00) // IODIRA 277 wantReg2 := uint8(0x12) // GPIOA 278 returnRead := []uint8{0x00, 0x7F} // emulate all IO's are outputs, emulate bit is off 279 wantReg1Val := returnRead[0] | 0x80 // IODIRA: bit 7 set, all other untouched 280 if bitState == 1 { 281 returnRead[1] = 0xFF // emulate bit is set 282 } 283 // arrange reads 284 numCallsRead := 0 285 a.i2cReadImpl = func(b []byte) (int, error) { 286 numCallsRead++ 287 b[len(b)-1] = returnRead[numCallsRead-1] 288 return len(b), nil 289 } 290 // act 291 val, err := d.ReadGPIO(testPin, testPort) 292 // assert 293 gobottest.Assert(t, err, nil) 294 gobottest.Assert(t, numCallsRead, 2) 295 gobottest.Assert(t, len(a.written), 4) 296 gobottest.Assert(t, a.written[0], wantReg1) 297 gobottest.Assert(t, a.written[1], wantReg1) 298 gobottest.Assert(t, a.written[2], wantReg1Val) 299 gobottest.Assert(t, a.written[3], wantReg2) 300 gobottest.Assert(t, val, uint8(bitState)) 301 } 302 } 303 304 func TestMCP23017ReadGPIONoRefresh(t *testing.T) { 305 // sequence to read with take advantage of refresh optimization (see forceRefresh): 306 // * read current state of IODIR (write reg, read val) => by SetPinMode() 307 // * read GPIO (write reg, read val) 308 // arrange 309 d, a := initTestMCP23017WithStubbedAdaptor(0) 310 for bitState := 0; bitState <= 1; bitState++ { 311 a.written = []byte{} // reset writes of Start() and former test 312 // arrange some values 313 testPort := "A" 314 testPin := uint8(7) 315 wantReg1 := uint8(0x00) // IODIRA 316 wantReg2 := uint8(0x12) // GPIOA 317 returnRead := []uint8{0x80, 0x7F} // emulate all IO's are outputs except pin 7, emulate bit is off 318 if bitState == 1 { 319 returnRead[1] = 0xFF // emulate bit is set 320 } 321 // arrange reads 322 numCallsRead := 0 323 a.i2cReadImpl = func(b []byte) (int, error) { 324 numCallsRead++ 325 b[len(b)-1] = returnRead[numCallsRead-1] 326 return len(b), nil 327 } 328 // act 329 val, err := d.ReadGPIO(testPin, testPort) 330 // assert 331 gobottest.Assert(t, err, nil) 332 gobottest.Assert(t, numCallsRead, 2) 333 gobottest.Assert(t, len(a.written), 2) 334 gobottest.Assert(t, a.written[0], wantReg1) 335 gobottest.Assert(t, a.written[1], wantReg2) 336 gobottest.Assert(t, val, uint8(bitState)) 337 } 338 } 339 340 func TestMCP23017ReadGPIONoAutoDir(t *testing.T) { 341 // sequence to read with suppressed automatic setting of IODIR: 342 // * read GPIO (write reg, read val) 343 // arrange 344 d, a := initTestMCP23017WithStubbedAdaptor(0) 345 d.mcpBehav.autoIODirOff = true 346 for bitState := 0; bitState <= 1; bitState++ { 347 a.written = []byte{} // reset writes of Start() and former test 348 // arrange some values 349 testPort := "A" 350 testPin := uint8(7) 351 wantReg2 := uint8(0x12) // GPIOA 352 returnRead := uint8(0x7F) // emulate bit is off 353 if bitState == 1 { 354 returnRead = 0xFF // emulate bit is set 355 } 356 // arrange reads 357 numCallsRead := 0 358 a.i2cReadImpl = func(b []byte) (int, error) { 359 numCallsRead++ 360 b[len(b)-1] = returnRead 361 return len(b), nil 362 } 363 // act 364 val, err := d.ReadGPIO(testPin, testPort) 365 // assert 366 gobottest.Assert(t, err, nil) 367 gobottest.Assert(t, numCallsRead, 1) 368 gobottest.Assert(t, len(a.written), 1) 369 gobottest.Assert(t, a.written[0], wantReg2) 370 gobottest.Assert(t, val, uint8(bitState)) 371 } 372 } 373 374 func TestMCP23017ReadGPIOErr(t *testing.T) { 375 // arrange 376 d, a := initTestMCP23017WithStubbedAdaptor(0) 377 // arrange reads 378 a.i2cReadImpl = func(b []byte) (int, error) { 379 return len(b), errors.New("read error") 380 } 381 // act 382 _, err := d.ReadGPIO(7, "A") 383 // assert 384 gobottest.Assert(t, err, errors.New("MCP write-read: MCP write-ReadByteData(reg=0): read error")) 385 } 386 387 func TestMCP23017SetPinMode(t *testing.T) { 388 // sequence for setting pin direction: 389 // * read current state of IODIR (write reg, read val) 390 // * set IODIR of pin to input or output (manipulate val, write reg, write val) 391 // TODO: can be optimized by not writing, when value is already fine 392 // arrange 393 d, a := initTestMCP23017WithStubbedAdaptor(0) 394 for bitState := 0; bitState <= 1; bitState++ { 395 a.written = []byte{} // reset writes of Start() and former test 396 // arrange some values 397 testPort := "A" 398 testPin := uint8(7) 399 wantReg := uint8(0x00) // IODIRA 400 returnRead := uint8(0xFF) // emulate all ports are inputs 401 wantRegVal := returnRead & 0x7F // bit 7 reset, all other untouched 402 if bitState == 1 { 403 returnRead = 0x00 // emulate all ports are outputs 404 wantRegVal = returnRead | 0x80 // bit 7 set, all other untouched 405 } 406 // arrange reads 407 numCallsRead := 0 408 a.i2cReadImpl = func(b []byte) (int, error) { 409 numCallsRead++ 410 b[len(b)-1] = returnRead 411 return len(b), nil 412 } 413 // act 414 err := d.SetPinMode(testPin, testPort, uint8(bitState)) 415 // assert 416 gobottest.Assert(t, err, nil) 417 gobottest.Assert(t, len(a.written), 3) 418 gobottest.Assert(t, a.written[0], wantReg) 419 gobottest.Assert(t, a.written[1], wantReg) 420 gobottest.Assert(t, a.written[2], wantRegVal) 421 gobottest.Assert(t, numCallsRead, 1) 422 } 423 } 424 425 func TestMCP23017SetPinModeErr(t *testing.T) { 426 // arrange 427 d, a := initTestMCP23017WithStubbedAdaptor(0) 428 a.i2cWriteImpl = func([]byte) (int, error) { 429 return 0, errors.New("write error") 430 } 431 // act 432 err := d.SetPinMode(7, "A", 0) 433 // assert 434 gobottest.Assert(t, err, errors.New("MCP write-read: MCP write-ReadByteData(reg=0): write error")) 435 } 436 437 func TestMCP23017SetPullUp(t *testing.T) { 438 // sequence for setting input pin pull up: 439 // * read current state of GPPU (write reg, read val) 440 // * set GPPU of pin to target state (manipulate val, write reg, write val) 441 // TODO: can be optimized by not writing, when value is already fine 442 // arrange 443 d, a := initTestMCP23017WithStubbedAdaptor(0) 444 for bitState := 0; bitState <= 1; bitState++ { 445 a.written = []byte{} // reset writes of Start() 446 // arrange some values 447 testPort := "A" 448 wantReg := uint8(0x0C) // GPPUA 449 testPin := uint8(5) 450 returnRead := uint8(0xFF) // emulate all I's with pull up 451 wantSetVal := returnRead & 0xDF // bit 5 cleared, all other unchanged 452 if bitState == 1 { 453 returnRead = uint8(0x00) // emulate all I's without pull up 454 wantSetVal = returnRead | 0x20 // bit 5 set, all other unchanged 455 } 456 // arrange reads 457 numCallsRead := 0 458 a.i2cReadImpl = func(b []byte) (int, error) { 459 numCallsRead++ 460 b[len(b)-1] = returnRead 461 return len(b), nil 462 } 463 // act 464 err := d.SetPullUp(testPin, testPort, uint8(bitState)) 465 // assert 466 gobottest.Assert(t, err, nil) 467 gobottest.Assert(t, len(a.written), 3) 468 gobottest.Assert(t, a.written[0], wantReg) 469 gobottest.Assert(t, a.written[1], wantReg) 470 gobottest.Assert(t, a.written[2], wantSetVal) 471 gobottest.Assert(t, numCallsRead, 1) 472 } 473 } 474 475 func TestMCP23017SetPullUpErr(t *testing.T) { 476 // arrange 477 d, a := initTestMCP23017WithStubbedAdaptor(0) 478 a.i2cWriteImpl = func([]byte) (int, error) { 479 return 0, errors.New("write error") 480 } 481 // act 482 err := d.SetPullUp(7, "A", 0) 483 // assert 484 gobottest.Assert(t, err, errors.New("MCP write-read: MCP write-ReadByteData(reg=12): write error")) 485 } 486 487 func TestMCP23017SetGPIOPolarity(t *testing.T) { 488 // sequence for setting input pin polarity: 489 // * read current state of IPOL (write reg, read val) 490 // * set IPOL of pin to target state (manipulate val, write reg, write val) 491 // TODO: can be optimized by not writing, when value is already fine 492 // arrange 493 d, a := initTestMCP23017WithStubbedAdaptor(0) 494 for bitState := 0; bitState <= 1; bitState++ { 495 a.written = []byte{} // reset writes of Start() 496 // arrange some values 497 testPort := "B" 498 wantReg := uint8(0x03) // IPOLB 499 testPin := uint8(6) 500 returnRead := uint8(0xFF) // emulate all I's negotiated 501 wantSetVal := returnRead & 0xBF // bit 6 cleared, all other unchanged 502 if bitState == 1 { 503 returnRead = uint8(0x00) // emulate all I's not negotiated 504 wantSetVal = returnRead | 0x40 // bit 6 set, all other unchanged 505 } 506 // arrange reads 507 numCallsRead := 0 508 a.i2cReadImpl = func(b []byte) (int, error) { 509 numCallsRead++ 510 b[len(b)-1] = returnRead 511 return len(b), nil 512 } 513 // act 514 err := d.SetGPIOPolarity(testPin, testPort, uint8(bitState)) 515 // assert 516 gobottest.Assert(t, err, nil) 517 gobottest.Assert(t, len(a.written), 3) 518 gobottest.Assert(t, a.written[0], wantReg) 519 gobottest.Assert(t, a.written[1], wantReg) 520 gobottest.Assert(t, a.written[2], wantSetVal) 521 gobottest.Assert(t, numCallsRead, 1) 522 } 523 } 524 525 func TestMCP23017SetGPIOPolarityErr(t *testing.T) { 526 // arrange 527 d, a := initTestMCP23017WithStubbedAdaptor(0) 528 a.i2cWriteImpl = func([]byte) (int, error) { 529 return 0, errors.New("write error") 530 } 531 // act 532 err := d.SetGPIOPolarity(7, "A", 0) 533 // assert 534 gobottest.Assert(t, err, errors.New("MCP write-read: MCP write-ReadByteData(reg=2): write error")) 535 } 536 537 func TestMCP23017_write(t *testing.T) { 538 // clear bit 539 d, _ := initTestMCP23017WithStubbedAdaptor(0) 540 port := d.getPort("A") 541 err := d.write(port.IODIR, uint8(7), 0) 542 gobottest.Assert(t, err, nil) 543 544 // set bit 545 d, _ = initTestMCP23017WithStubbedAdaptor(0) 546 port = d.getPort("B") 547 err = d.write(port.IODIR, uint8(7), 1) 548 gobottest.Assert(t, err, nil) 549 550 // write error 551 d, a := initTestMCP23017WithStubbedAdaptor(0) 552 a.i2cWriteImpl = func([]byte) (int, error) { 553 return 0, errors.New("write error") 554 } 555 err = d.write(port.IODIR, uint8(7), 0) 556 gobottest.Assert(t, err, errors.New("MCP write-read: MCP write-ReadByteData(reg=1): write error")) 557 558 // read error 559 d, a = initTestMCP23017WithStubbedAdaptor(0) 560 a.i2cReadImpl = func(b []byte) (int, error) { 561 return len(b), errors.New("read error") 562 } 563 err = d.write(port.IODIR, uint8(7), 0) 564 gobottest.Assert(t, err, errors.New("MCP write-read: MCP write-ReadByteData(reg=1): read error")) 565 a.i2cReadImpl = func(b []byte) (int, error) { 566 return len(b), nil 567 } 568 err = d.write(port.IODIR, uint8(7), 1) 569 gobottest.Assert(t, err, nil) 570 } 571 572 func TestMCP23017_read(t *testing.T) { 573 // read 574 d, a := initTestMCP23017WithStubbedAdaptor(0) 575 port := d.getPort("A") 576 a.i2cReadImpl = func(b []byte) (int, error) { 577 copy(b, []byte{255}) 578 return 1, nil 579 } 580 val, _ := d.read(port.IODIR) 581 gobottest.Assert(t, val, uint8(255)) 582 583 // read error 584 d, a = initTestMCP23017WithStubbedAdaptor(0) 585 a.i2cReadImpl = func(b []byte) (int, error) { 586 return len(b), errors.New("read error") 587 } 588 589 val, err := d.read(port.IODIR) 590 gobottest.Assert(t, val, uint8(0)) 591 gobottest.Assert(t, err, errors.New("MCP write-ReadByteData(reg=0): read error")) 592 593 // read 594 d, a = initTestMCP23017WithStubbedAdaptor(0) 595 port = d.getPort("A") 596 a.i2cReadImpl = func(b []byte) (int, error) { 597 copy(b, []byte{255}) 598 return 1, nil 599 } 600 val, _ = d.read(port.IODIR) 601 gobottest.Assert(t, val, uint8(255)) 602 } 603 604 func TestMCP23017_getPort(t *testing.T) { 605 // port A 606 d := initTestMCP23017(0) 607 expectedPort := mcp23017GetBank(0).portA 608 actualPort := d.getPort("A") 609 gobottest.Assert(t, expectedPort, actualPort) 610 611 // port B 612 d = initTestMCP23017(0) 613 expectedPort = mcp23017GetBank(0).portB 614 actualPort = d.getPort("B") 615 gobottest.Assert(t, expectedPort, actualPort) 616 617 // default 618 d = initTestMCP23017(0) 619 expectedPort = mcp23017GetBank(0).portA 620 actualPort = d.getPort("") 621 gobottest.Assert(t, expectedPort, actualPort) 622 623 // port A bank 1 624 d = initTestMCP23017(1) 625 expectedPort = mcp23017GetBank(1).portA 626 actualPort = d.getPort("") 627 gobottest.Assert(t, expectedPort, actualPort) 628 }