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