gobot.io/x/gobot/v2@v2.1.0/drivers/i2c/pca9501_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 = (*PCA9501Driver)(nil)
    15  
    16  var (
    17  	pinVal = map[string]interface{}{
    18  		"pin": uint8(7),
    19  		"val": uint8(0),
    20  	}
    21  	pin = map[string]interface{}{
    22  		"pin": uint8(7),
    23  	}
    24  	addressVal = map[string]interface{}{
    25  		"address": uint8(15),
    26  		"val":     uint8(7),
    27  	}
    28  	address = map[string]interface{}{
    29  		"address": uint8(15),
    30  	}
    31  )
    32  
    33  func initPCA9501WithStubbedAdaptor() (*PCA9501Driver, *i2cTestAdaptor) {
    34  	a := newI2cTestAdaptor()
    35  	d := NewPCA9501Driver(a)
    36  	if err := d.Start(); err != nil {
    37  		panic(err)
    38  	}
    39  	return d, a
    40  }
    41  
    42  func TestNewPCA9501Driver(t *testing.T) {
    43  	// arrange, act
    44  	var di interface{} = NewPCA9501Driver(newI2cTestAdaptor())
    45  	// assert
    46  	d, ok := di.(*PCA9501Driver)
    47  	if !ok {
    48  		t.Errorf("NewPCA9501Driver() should have returned a *PCA9501Driver")
    49  	}
    50  	gobottest.Refute(t, d.Driver, nil)
    51  	gobottest.Assert(t, strings.HasPrefix(d.Name(), "PCA9501"), true)
    52  	gobottest.Assert(t, d.defaultAddress, 0x3f)
    53  }
    54  
    55  func TestPCA9501Options(t *testing.T) {
    56  	// This is a general test, that options are applied in constructor by using the common WithBus() option and
    57  	// least one of this driver. Further tests for options can also be done by call of "WithOption(val)(d)".
    58  	d := NewPCA9501Driver(newI2cTestAdaptor(), WithBus(2))
    59  	gobottest.Assert(t, d.GetBusOrDefault(1), 2)
    60  }
    61  
    62  func TestPCA9501CommandsWriteGPIO(t *testing.T) {
    63  	// arrange
    64  	d, a := initPCA9501WithStubbedAdaptor()
    65  	a.i2cReadImpl = func(b []byte) (int, error) {
    66  		return len(b), nil
    67  	}
    68  	a.i2cWriteImpl = func([]byte) (int, error) {
    69  		return 0, nil
    70  	}
    71  	// act
    72  	result := d.Command("WriteGPIO")(pinVal)
    73  	// assert
    74  	gobottest.Assert(t, result.(map[string]interface{})["err"], nil)
    75  }
    76  
    77  func TestPCA9501CommandsReadGPIO(t *testing.T) {
    78  	// arrange
    79  	d, a := initPCA9501WithStubbedAdaptor()
    80  	a.i2cReadImpl = func(b []byte) (int, error) {
    81  		return len(b), nil
    82  	}
    83  	// act
    84  	result := d.Command("ReadGPIO")(pin)
    85  	// assert
    86  	gobottest.Assert(t, result.(map[string]interface{})["err"], nil)
    87  }
    88  
    89  func TestPCA9501CommandsWriteEEPROM(t *testing.T) {
    90  	// arrange
    91  	d, a := initPCA9501WithStubbedAdaptor()
    92  	a.i2cWriteImpl = func([]byte) (int, error) {
    93  		return 0, nil
    94  	}
    95  	// act
    96  	result := d.Command("WriteEEPROM")(addressVal)
    97  	// assert
    98  	gobottest.Assert(t, result.(map[string]interface{})["err"], nil)
    99  }
   100  
   101  func TestPCA9501CommandsReadEEPROM(t *testing.T) {
   102  	// arrange
   103  	d, a := initPCA9501WithStubbedAdaptor()
   104  	a.i2cWriteImpl = func([]byte) (int, error) {
   105  		return 0, nil
   106  	}
   107  	a.i2cReadImpl = func(b []byte) (int, error) {
   108  		return len(b), nil
   109  	}
   110  	// act
   111  	result := d.Command("ReadEEPROM")(address)
   112  	// assert
   113  	gobottest.Assert(t, result.(map[string]interface{})["err"], nil)
   114  }
   115  
   116  func TestPCA9501WriteGPIO(t *testing.T) {
   117  	var tests = map[string]struct {
   118  		setVal          uint8
   119  		ioDirAllInput   uint8
   120  		ioStateAllInput uint8
   121  		pin             uint8
   122  		wantPin         uint8
   123  		wantState       uint8
   124  	}{
   125  		"clear_bit": {
   126  			setVal:          0,
   127  			ioDirAllInput:   0xF1,
   128  			ioStateAllInput: 0xF2,
   129  			pin:             6,
   130  			wantPin:         0xB1,
   131  			wantState:       0xB2,
   132  		},
   133  		"set_bit": {
   134  			setVal:          2,
   135  			ioDirAllInput:   0x1F,
   136  			ioStateAllInput: 0x20,
   137  			pin:             3,
   138  			wantPin:         0x17,
   139  			wantState:       0x28,
   140  		},
   141  	}
   142  	for name, tc := range tests {
   143  		t.Run(name, func(t *testing.T) {
   144  			// arrange
   145  			d, a := initPCA9501WithStubbedAdaptor()
   146  			// prepare all reads
   147  			numCallsRead := 0
   148  			a.i2cReadImpl = func(b []byte) (int, error) {
   149  				numCallsRead++
   150  				if numCallsRead == 1 {
   151  					// first call read current io direction of all pins
   152  					b[0] = tc.ioDirAllInput
   153  				}
   154  				if numCallsRead == 2 {
   155  					// second call read current state of all pins
   156  					b[0] = tc.ioStateAllInput
   157  				}
   158  				return len(b), nil
   159  			}
   160  			// act
   161  			err := d.WriteGPIO(tc.pin, tc.setVal)
   162  			// assert
   163  			gobottest.Assert(t, err, nil)
   164  			gobottest.Assert(t, numCallsRead, 2)
   165  			gobottest.Assert(t, len(a.written), 2)
   166  			gobottest.Assert(t, a.written[0], tc.wantPin)
   167  			gobottest.Assert(t, a.written[1], tc.wantState)
   168  		})
   169  	}
   170  }
   171  
   172  func TestPCA9501WriteGPIOErrorAtWriteDirection(t *testing.T) {
   173  	// arrange
   174  	d, a := initPCA9501WithStubbedAdaptor()
   175  	wantErr := errors.New("write error")
   176  	// prepare all reads
   177  	numCallsRead := 0
   178  	a.i2cReadImpl = func(b []byte) (int, error) {
   179  		numCallsRead++
   180  		return len(b), nil
   181  	}
   182  	// prepare all writes
   183  	numCallsWrite := 0
   184  	a.i2cWriteImpl = func([]byte) (int, error) {
   185  		numCallsWrite++
   186  		if numCallsWrite == 1 {
   187  			// first call writes the CTRL register for port direction
   188  			return 0, wantErr
   189  		}
   190  		return 0, nil
   191  	}
   192  	// act
   193  	err := d.WriteGPIO(7, 0)
   194  	// assert
   195  	gobottest.Assert(t, err, wantErr)
   196  	gobottest.Assert(t, numCallsRead < 2, true)
   197  	gobottest.Assert(t, numCallsWrite, 1)
   198  }
   199  
   200  func TestPCA9501WriteGPIOErrorAtWriteValue(t *testing.T) {
   201  	// arrange
   202  	d, a := initPCA9501WithStubbedAdaptor()
   203  	wantErr := errors.New("write error")
   204  	// prepare all reads
   205  	a.i2cReadImpl = func(b []byte) (int, error) {
   206  		return len(b), nil
   207  	}
   208  	// prepare all writes
   209  	numCallsWrite := 0
   210  	a.i2cWriteImpl = func([]byte) (int, error) {
   211  		numCallsWrite++
   212  		if numCallsWrite == 2 {
   213  			// second call writes the value to IO port
   214  			return 0, wantErr
   215  		}
   216  		return 0, nil
   217  	}
   218  	// act
   219  	err := d.WriteGPIO(7, 0)
   220  	// assert
   221  	gobottest.Assert(t, err, wantErr)
   222  	gobottest.Assert(t, numCallsWrite, 2)
   223  }
   224  
   225  func TestPCA9501ReadGPIO(t *testing.T) {
   226  	var tests = map[string]struct {
   227  		ctrlState uint8
   228  		want      uint8
   229  	}{
   230  		"pin_is_set":     {ctrlState: 0x80, want: 1},
   231  		"pin_is_not_set": {ctrlState: 0x7F, want: 0},
   232  	}
   233  	for name, tc := range tests {
   234  		t.Run(name, func(t *testing.T) {
   235  			// arrange
   236  			const (
   237  				pin           = uint8(7)
   238  				wantCtrlState = uint8(0x80)
   239  			)
   240  			d, a := initPCA9501WithStubbedAdaptor()
   241  			// prepare all reads
   242  			numCallsRead := 0
   243  			a.i2cReadImpl = func(b []byte) (int, error) {
   244  				numCallsRead++
   245  				if numCallsRead == 1 {
   246  					// current state of io
   247  					b[0] = 0x00
   248  				}
   249  				if numCallsRead == 2 {
   250  					b[0] = tc.ctrlState
   251  				}
   252  				return len(b), nil
   253  			}
   254  			// act
   255  			got, err := d.ReadGPIO(pin)
   256  			// assert
   257  			gobottest.Assert(t, err, nil)
   258  			gobottest.Assert(t, got, tc.want)
   259  			gobottest.Assert(t, numCallsRead, 2)
   260  			gobottest.Assert(t, len(a.written), 1)
   261  			gobottest.Assert(t, a.written[0], wantCtrlState)
   262  		})
   263  	}
   264  }
   265  
   266  func TestPCA9501ReadGPIOErrorAtReadDirection(t *testing.T) {
   267  	// arrange
   268  	d, a := initPCA9501WithStubbedAdaptor()
   269  	wantErr := errors.New("read error")
   270  	// prepare all reads
   271  	numCallsRead := 0
   272  	a.i2cReadImpl = func(b []byte) (int, error) {
   273  		numCallsRead++
   274  		if numCallsRead == 1 {
   275  			// first read gets the CTRL register for pin direction
   276  			return 0, wantErr
   277  		}
   278  		return len(b), nil
   279  	}
   280  	// prepare all writes
   281  	numCallsWrite := 0
   282  	a.i2cWriteImpl = func([]byte) (int, error) {
   283  		numCallsWrite++
   284  		return 0, nil
   285  	}
   286  	// act
   287  	_, err := d.ReadGPIO(1)
   288  	// assert
   289  	gobottest.Assert(t, err, wantErr)
   290  	gobottest.Assert(t, numCallsRead, 1)
   291  	gobottest.Assert(t, numCallsWrite, 0)
   292  }
   293  
   294  func TestPCA9501ReadGPIOErrorAtReadValue(t *testing.T) {
   295  	// arrange
   296  	d, a := initPCA9501WithStubbedAdaptor()
   297  	wantErr := errors.New("read error")
   298  	// prepare all reads
   299  	numCallsRead := 0
   300  	a.i2cReadImpl = func(b []byte) (int, error) {
   301  		numCallsRead++
   302  		if numCallsRead == 2 {
   303  			// second read gets the value from IO port
   304  			return 0, wantErr
   305  		}
   306  		return len(b), nil
   307  	}
   308  	// prepare all writes
   309  	numCallsWrite := 0
   310  	a.i2cWriteImpl = func([]byte) (int, error) {
   311  		numCallsWrite++
   312  		return 0, nil
   313  	}
   314  	// act
   315  	_, err := d.ReadGPIO(2)
   316  	// assert
   317  	gobottest.Assert(t, err, wantErr)
   318  	gobottest.Assert(t, numCallsWrite, 1)
   319  }
   320  
   321  func TestPCA9501WriteEEPROM(t *testing.T) {
   322  	// arrange
   323  	const (
   324  		addressEEPROM = uint8(0x52)
   325  		want          = uint8(0x25)
   326  	)
   327  	d, a := initPCA9501WithStubbedAdaptor()
   328  	// prepare all writes
   329  	numCallsWrite := 0
   330  	a.i2cWriteImpl = func([]byte) (int, error) {
   331  		numCallsWrite++
   332  		return 0, nil
   333  	}
   334  	// act
   335  	err := d.WriteEEPROM(addressEEPROM, want)
   336  	// assert
   337  	gobottest.Assert(t, err, nil)
   338  	gobottest.Assert(t, numCallsWrite, 1)
   339  	gobottest.Assert(t, a.written[0], addressEEPROM)
   340  	gobottest.Assert(t, a.written[1], want)
   341  }
   342  
   343  func TestPCA9501ReadEEPROM(t *testing.T) {
   344  	// arrange
   345  	const (
   346  		addressEEPROM = uint8(51)
   347  		want          = uint8(0x44)
   348  	)
   349  	d, a := initPCA9501WithStubbedAdaptor()
   350  	// prepare all writes
   351  	numCallsWrite := 0
   352  	a.i2cWriteImpl = func(b []byte) (int, error) {
   353  		numCallsWrite++
   354  		return 0, nil
   355  	}
   356  	// prepare all reads
   357  	numCallsRead := 0
   358  	a.i2cReadImpl = func(b []byte) (int, error) {
   359  		numCallsRead++
   360  		b[0] = want
   361  		return len(b), nil
   362  	}
   363  	// act
   364  	val, err := d.ReadEEPROM(addressEEPROM)
   365  	// assert
   366  	gobottest.Assert(t, err, nil)
   367  	gobottest.Assert(t, val, want)
   368  	gobottest.Assert(t, numCallsWrite, 1)
   369  	gobottest.Assert(t, a.written[0], addressEEPROM)
   370  	gobottest.Assert(t, numCallsRead, 1)
   371  }
   372  
   373  func TestPCA9501ReadEEPROMErrorWhileWriteAddress(t *testing.T) {
   374  	// arrange
   375  	d, a := initPCA9501WithStubbedAdaptor()
   376  	wantErr := errors.New("error while write")
   377  	// prepare all writes
   378  	a.i2cWriteImpl = func([]byte) (int, error) {
   379  		return 0, wantErr
   380  	}
   381  	// prepare all reads
   382  	numCallsRead := 0
   383  	a.i2cReadImpl = func(b []byte) (int, error) {
   384  		numCallsRead++
   385  		return len(b), nil
   386  	}
   387  	// act
   388  	_, err := d.ReadEEPROM(15)
   389  	// assert
   390  	gobottest.Assert(t, err, wantErr)
   391  	gobottest.Assert(t, numCallsRead, 0)
   392  }
   393  
   394  func TestPCA9501ReadEEPROMErrorWhileReadValue(t *testing.T) {
   395  	// arrange
   396  	d, a := initPCA9501WithStubbedAdaptor()
   397  	wantErr := errors.New("error while read")
   398  	// prepare all writes
   399  	numCallsWrite := 0
   400  	a.i2cWriteImpl = func([]byte) (int, error) {
   401  		numCallsWrite++
   402  		return 0, nil
   403  	}
   404  	// prepare all reads
   405  	a.i2cReadImpl = func(b []byte) (int, error) {
   406  		return len(b), wantErr
   407  	}
   408  	// act
   409  	_, err := d.ReadEEPROM(15)
   410  	// assert
   411  	gobottest.Assert(t, numCallsWrite, 1)
   412  	gobottest.Assert(t, err, wantErr)
   413  }
   414  
   415  func TestPCA9501_initialize(t *testing.T) {
   416  	// arrange
   417  	const want = 0x7f
   418  	d, a := initPCA9501WithStubbedAdaptor()
   419  	// act
   420  	err := d.initialize()
   421  	// assert
   422  	gobottest.Assert(t, err, nil)
   423  	gobottest.Assert(t, a.address, want)
   424  }