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  }