gobot.io/x/gobot/v2@v2.1.0/platforms/intel-iot/edison/edison_adaptor_test.go (about)

     1  package edison
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  	"testing"
     7  
     8  	"gobot.io/x/gobot/v2"
     9  	"gobot.io/x/gobot/v2/drivers/aio"
    10  	"gobot.io/x/gobot/v2/drivers/gpio"
    11  	"gobot.io/x/gobot/v2/drivers/i2c"
    12  	"gobot.io/x/gobot/v2/gobottest"
    13  	"gobot.io/x/gobot/v2/system"
    14  )
    15  
    16  // make sure that this Adaptor fulfills all the required interfaces
    17  var _ gobot.Adaptor = (*Adaptor)(nil)
    18  var _ gobot.DigitalPinnerProvider = (*Adaptor)(nil)
    19  var _ gobot.PWMPinnerProvider = (*Adaptor)(nil)
    20  var _ gpio.DigitalReader = (*Adaptor)(nil)
    21  var _ gpio.DigitalWriter = (*Adaptor)(nil)
    22  var _ aio.AnalogReader = (*Adaptor)(nil)
    23  var _ gpio.PwmWriter = (*Adaptor)(nil)
    24  var _ i2c.Connector = (*Adaptor)(nil)
    25  
    26  var testPinFiles = []string{
    27  	"/sys/bus/iio/devices/iio:device1/in_voltage0_raw",
    28  	"/sys/kernel/debug/gpio_debug/gpio111/current_pinmux",
    29  	"/sys/kernel/debug/gpio_debug/gpio115/current_pinmux",
    30  	"/sys/kernel/debug/gpio_debug/gpio114/current_pinmux",
    31  	"/sys/kernel/debug/gpio_debug/gpio109/current_pinmux",
    32  	"/sys/kernel/debug/gpio_debug/gpio131/current_pinmux",
    33  	"/sys/kernel/debug/gpio_debug/gpio129/current_pinmux",
    34  	"/sys/kernel/debug/gpio_debug/gpio40/current_pinmux",
    35  	"/sys/kernel/debug/gpio_debug/gpio13/current_pinmux",
    36  	"/sys/kernel/debug/gpio_debug/gpio28/current_pinmux",
    37  	"/sys/kernel/debug/gpio_debug/gpio27/current_pinmux",
    38  	"/sys/class/pwm/pwmchip0/export",
    39  	"/sys/class/pwm/pwmchip0/unexport",
    40  	"/sys/class/pwm/pwmchip0/pwm1/duty_cycle",
    41  	"/sys/class/pwm/pwmchip0/pwm1/period",
    42  	"/sys/class/pwm/pwmchip0/pwm1/enable",
    43  	"/sys/class/gpio/export",
    44  	"/sys/class/gpio/unexport",
    45  	"/sys/class/gpio/gpio13/value",
    46  	"/sys/class/gpio/gpio13/direction",
    47  	"/sys/class/gpio/gpio40/value",
    48  	"/sys/class/gpio/gpio40/direction",
    49  	"/sys/class/gpio/gpio128/value",
    50  	"/sys/class/gpio/gpio128/direction",
    51  	"/sys/class/gpio/gpio221/value",
    52  	"/sys/class/gpio/gpio221/direction",
    53  	"/sys/class/gpio/gpio243/value",
    54  	"/sys/class/gpio/gpio243/direction",
    55  	"/sys/class/gpio/gpio229/value",
    56  	"/sys/class/gpio/gpio229/direction",
    57  	"/sys/class/gpio/gpio253/value",
    58  	"/sys/class/gpio/gpio253/direction",
    59  	"/sys/class/gpio/gpio261/value",
    60  	"/sys/class/gpio/gpio261/direction",
    61  	"/sys/class/gpio/gpio214/value",
    62  	"/sys/class/gpio/gpio214/direction",
    63  	"/sys/class/gpio/gpio14/direction",
    64  	"/sys/class/gpio/gpio14/value",
    65  	"/sys/class/gpio/gpio165/direction",
    66  	"/sys/class/gpio/gpio165/value",
    67  	"/sys/class/gpio/gpio212/direction",
    68  	"/sys/class/gpio/gpio212/value",
    69  	"/sys/class/gpio/gpio213/direction",
    70  	"/sys/class/gpio/gpio213/value",
    71  	"/sys/class/gpio/gpio236/direction",
    72  	"/sys/class/gpio/gpio236/value",
    73  	"/sys/class/gpio/gpio237/direction",
    74  	"/sys/class/gpio/gpio237/value",
    75  	"/sys/class/gpio/gpio204/direction",
    76  	"/sys/class/gpio/gpio204/value",
    77  	"/sys/class/gpio/gpio205/direction",
    78  	"/sys/class/gpio/gpio205/value",
    79  	"/sys/class/gpio/gpio263/direction",
    80  	"/sys/class/gpio/gpio263/value",
    81  	"/sys/class/gpio/gpio262/direction",
    82  	"/sys/class/gpio/gpio262/value",
    83  	"/sys/class/gpio/gpio240/direction",
    84  	"/sys/class/gpio/gpio240/value",
    85  	"/sys/class/gpio/gpio241/direction",
    86  	"/sys/class/gpio/gpio241/value",
    87  	"/sys/class/gpio/gpio242/direction",
    88  	"/sys/class/gpio/gpio242/value",
    89  	"/sys/class/gpio/gpio218/direction",
    90  	"/sys/class/gpio/gpio218/value",
    91  	"/sys/class/gpio/gpio250/direction",
    92  	"/sys/class/gpio/gpio250/value",
    93  	"/dev/i2c-6",
    94  }
    95  
    96  var pwmMockPathsMux13Arduino = []string{
    97  	"/sys/class/gpio/export",
    98  	"/sys/class/gpio/unexport",
    99  	"/sys/kernel/debug/gpio_debug/gpio13/current_pinmux",
   100  	"/sys/kernel/debug/gpio_debug/gpio40/current_pinmux",
   101  	"/sys/kernel/debug/gpio_debug/gpio109/current_pinmux",
   102  	"/sys/kernel/debug/gpio_debug/gpio111/current_pinmux",
   103  	"/sys/kernel/debug/gpio_debug/gpio114/current_pinmux",
   104  	"/sys/kernel/debug/gpio_debug/gpio115/current_pinmux",
   105  	"/sys/kernel/debug/gpio_debug/gpio129/current_pinmux",
   106  	"/sys/kernel/debug/gpio_debug/gpio131/current_pinmux",
   107  	"/sys/class/gpio/gpio13/direction",
   108  	"/sys/class/gpio/gpio13/value",
   109  	"/sys/class/gpio/gpio214/direction",
   110  	"/sys/class/gpio/gpio214/value",
   111  	"/sys/class/gpio/gpio221/direction",
   112  	"/sys/class/gpio/gpio221/value",
   113  	"/sys/class/gpio/gpio240/direction",
   114  	"/sys/class/gpio/gpio240/value",
   115  	"/sys/class/gpio/gpio241/direction",
   116  	"/sys/class/gpio/gpio241/value",
   117  	"/sys/class/gpio/gpio242/direction",
   118  	"/sys/class/gpio/gpio242/value",
   119  	"/sys/class/gpio/gpio243/direction",
   120  	"/sys/class/gpio/gpio243/value",
   121  	"/sys/class/gpio/gpio253/direction",
   122  	"/sys/class/gpio/gpio253/value",
   123  	"/sys/class/gpio/gpio262/direction",
   124  	"/sys/class/gpio/gpio262/value",
   125  	"/sys/class/gpio/gpio263/direction",
   126  	"/sys/class/gpio/gpio263/value",
   127  }
   128  
   129  var pwmMockPathsMux13ArduinoI2c = []string{
   130  	"/dev/i2c-6",
   131  	"/sys/class/gpio/export",
   132  	"/sys/class/gpio/unexport",
   133  	"/sys/kernel/debug/gpio_debug/gpio13/current_pinmux",
   134  	"/sys/kernel/debug/gpio_debug/gpio27/current_pinmux",
   135  	"/sys/kernel/debug/gpio_debug/gpio28/current_pinmux",
   136  	"/sys/kernel/debug/gpio_debug/gpio40/current_pinmux",
   137  	"/sys/kernel/debug/gpio_debug/gpio109/current_pinmux",
   138  	"/sys/kernel/debug/gpio_debug/gpio111/current_pinmux",
   139  	"/sys/kernel/debug/gpio_debug/gpio114/current_pinmux",
   140  	"/sys/kernel/debug/gpio_debug/gpio115/current_pinmux",
   141  	"/sys/kernel/debug/gpio_debug/gpio129/current_pinmux",
   142  	"/sys/kernel/debug/gpio_debug/gpio131/current_pinmux",
   143  	"/sys/class/gpio/gpio13/direction",
   144  	"/sys/class/gpio/gpio13/value",
   145  	"/sys/class/gpio/gpio14/direction",
   146  	"/sys/class/gpio/gpio14/value",
   147  	"/sys/class/gpio/gpio28/direction",
   148  	"/sys/class/gpio/gpio28/value",
   149  	"/sys/class/gpio/gpio165/direction",
   150  	"/sys/class/gpio/gpio165/value",
   151  	"/sys/class/gpio/gpio212/direction",
   152  	"/sys/class/gpio/gpio212/value",
   153  	"/sys/class/gpio/gpio213/direction",
   154  	"/sys/class/gpio/gpio213/value",
   155  	"/sys/class/gpio/gpio214/direction",
   156  	"/sys/class/gpio/gpio214/value",
   157  	"/sys/class/gpio/gpio221/direction",
   158  	"/sys/class/gpio/gpio221/value",
   159  	"/sys/class/gpio/gpio236/direction",
   160  	"/sys/class/gpio/gpio236/value",
   161  	"/sys/class/gpio/gpio237/direction",
   162  	"/sys/class/gpio/gpio237/value",
   163  	"/sys/class/gpio/gpio204/value",
   164  	"/sys/class/gpio/gpio204/direction",
   165  	"/sys/class/gpio/gpio205/value",
   166  	"/sys/class/gpio/gpio205/direction",
   167  	"/sys/class/gpio/gpio240/direction",
   168  	"/sys/class/gpio/gpio240/value",
   169  	"/sys/class/gpio/gpio241/direction",
   170  	"/sys/class/gpio/gpio241/value",
   171  	"/sys/class/gpio/gpio242/direction",
   172  	"/sys/class/gpio/gpio242/value",
   173  	"/sys/class/gpio/gpio243/direction",
   174  	"/sys/class/gpio/gpio243/value",
   175  	"/sys/class/gpio/gpio253/direction",
   176  	"/sys/class/gpio/gpio253/value",
   177  	"/sys/class/gpio/gpio262/direction",
   178  	"/sys/class/gpio/gpio262/value",
   179  	"/sys/class/gpio/gpio263/direction",
   180  	"/sys/class/gpio/gpio263/value",
   181  }
   182  
   183  var pwmMockPathsMux13 = []string{
   184  	"/sys/kernel/debug/gpio_debug/gpio13/current_pinmux",
   185  	"/sys/class/gpio/export",
   186  	"/sys/class/gpio/gpio13/direction",
   187  	"/sys/class/gpio/gpio13/value",
   188  	"/sys/class/gpio/gpio221/direction",
   189  	"/sys/class/gpio/gpio221/value",
   190  	"/sys/class/gpio/gpio253/direction",
   191  	"/sys/class/gpio/gpio253/value",
   192  	"/sys/class/pwm/pwmchip0/export",
   193  	"/sys/class/pwm/pwmchip0/unexport",
   194  	"/sys/class/pwm/pwmchip0/pwm1/duty_cycle",
   195  	"/sys/class/pwm/pwmchip0/pwm1/period",
   196  	"/sys/class/pwm/pwmchip0/pwm1/enable",
   197  }
   198  
   199  var pwmMockPathsMux40 = []string{
   200  	"/sys/kernel/debug/gpio_debug/gpio40/current_pinmux",
   201  	"/sys/class/gpio/export",
   202  	"/sys/class/gpio/unexport",
   203  	"/sys/class/gpio/gpio40/value",
   204  	"/sys/class/gpio/gpio40/direction",
   205  	"/sys/class/gpio/gpio229/value", // resistor
   206  	"/sys/class/gpio/gpio229/direction",
   207  	"/sys/class/gpio/gpio243/value",
   208  	"/sys/class/gpio/gpio243/direction",
   209  	"/sys/class/gpio/gpio261/value", // level shifter
   210  	"/sys/class/gpio/gpio261/direction",
   211  }
   212  
   213  func initTestAdaptorWithMockedFilesystem(boardType string) (*Adaptor, *system.MockFilesystem) {
   214  	a := NewAdaptor(boardType)
   215  	fs := a.sys.UseMockFilesystem(testPinFiles)
   216  	fs.Files["/sys/class/pwm/pwmchip0/pwm1/period"].Contents = "5000"
   217  	if err := a.Connect(); err != nil {
   218  		panic(err)
   219  	}
   220  	return a, fs
   221  }
   222  
   223  func TestName(t *testing.T) {
   224  	a := NewAdaptor()
   225  
   226  	gobottest.Assert(t, strings.HasPrefix(a.Name(), "Edison"), true)
   227  	a.SetName("NewName")
   228  	gobottest.Assert(t, a.Name(), "NewName")
   229  }
   230  
   231  func TestConnect(t *testing.T) {
   232  	a, _ := initTestAdaptorWithMockedFilesystem("arduino")
   233  
   234  	gobottest.Assert(t, a.DefaultI2cBus(), 6)
   235  	gobottest.Assert(t, a.board, "arduino")
   236  	gobottest.Assert(t, a.Connect(), nil)
   237  }
   238  
   239  func TestArduinoSetupFail263(t *testing.T) {
   240  	a, fs := initTestAdaptorWithMockedFilesystem("arduino")
   241  	delete(fs.Files, "/sys/class/gpio/gpio263/direction")
   242  
   243  	err := a.arduinoSetup()
   244  	gobottest.Assert(t, strings.Contains(err.Error(), "/sys/class/gpio/gpio263/direction: no such file"), true)
   245  }
   246  
   247  func TestArduinoSetupFail240(t *testing.T) {
   248  	a, fs := initTestAdaptorWithMockedFilesystem("arduino")
   249  	delete(fs.Files, "/sys/class/gpio/gpio240/direction")
   250  
   251  	err := a.arduinoSetup()
   252  	gobottest.Assert(t, strings.Contains(err.Error(), "/sys/class/gpio/gpio240/direction: no such file"), true)
   253  }
   254  
   255  func TestArduinoSetupFail111(t *testing.T) {
   256  	a, fs := initTestAdaptorWithMockedFilesystem("arduino")
   257  	delete(fs.Files, "/sys/kernel/debug/gpio_debug/gpio111/current_pinmux")
   258  
   259  	err := a.arduinoSetup()
   260  	gobottest.Assert(t, strings.Contains(err.Error(), "/sys/kernel/debug/gpio_debug/gpio111/current_pinmux: no such file"), true)
   261  }
   262  
   263  func TestArduinoSetupFail131(t *testing.T) {
   264  	a, fs := initTestAdaptorWithMockedFilesystem("arduino")
   265  	delete(fs.Files, "/sys/kernel/debug/gpio_debug/gpio131/current_pinmux")
   266  
   267  	err := a.arduinoSetup()
   268  	gobottest.Assert(t, strings.Contains(err.Error(), "/sys/kernel/debug/gpio_debug/gpio131/current_pinmux: no such file"), true)
   269  }
   270  
   271  func TestArduinoI2CSetupFailTristate(t *testing.T) {
   272  	a, fs := initTestAdaptorWithMockedFilesystem("arduino")
   273  	gobottest.Assert(t, a.arduinoSetup(), nil)
   274  
   275  	fs.WithWriteError = true
   276  	err := a.arduinoI2CSetup()
   277  	gobottest.Assert(t, err, fmt.Errorf("write error"))
   278  }
   279  
   280  func TestArduinoI2CSetupFail14(t *testing.T) {
   281  	a, fs := initTestAdaptorWithMockedFilesystem("arduino")
   282  
   283  	gobottest.Assert(t, a.arduinoSetup(), nil)
   284  	delete(fs.Files, "/sys/class/gpio/gpio14/direction")
   285  
   286  	err := a.arduinoI2CSetup()
   287  	gobottest.Assert(t, strings.Contains(err.Error(), "/sys/class/gpio/gpio14/direction: no such file"), true)
   288  }
   289  
   290  func TestArduinoI2CSetupUnexportFail(t *testing.T) {
   291  	a, fs := initTestAdaptorWithMockedFilesystem("arduino")
   292  
   293  	gobottest.Assert(t, a.arduinoSetup(), nil)
   294  	delete(fs.Files, "/sys/class/gpio/unexport")
   295  
   296  	err := a.arduinoI2CSetup()
   297  	gobottest.Assert(t, strings.Contains(err.Error(), "/sys/class/gpio/unexport: no such file"), true)
   298  }
   299  
   300  func TestArduinoI2CSetupFail236(t *testing.T) {
   301  	a, fs := initTestAdaptorWithMockedFilesystem("arduino")
   302  
   303  	gobottest.Assert(t, a.arduinoSetup(), nil)
   304  	delete(fs.Files, "/sys/class/gpio/gpio236/direction")
   305  
   306  	err := a.arduinoI2CSetup()
   307  	gobottest.Assert(t, strings.Contains(err.Error(), "/sys/class/gpio/gpio236/direction: no such file"), true)
   308  }
   309  
   310  func TestArduinoI2CSetupFail28(t *testing.T) {
   311  	a, fs := initTestAdaptorWithMockedFilesystem("arduino")
   312  
   313  	gobottest.Assert(t, a.arduinoSetup(), nil)
   314  	delete(fs.Files, "/sys/kernel/debug/gpio_debug/gpio28/current_pinmux")
   315  
   316  	err := a.arduinoI2CSetup()
   317  	gobottest.Assert(t, strings.Contains(err.Error(), "/sys/kernel/debug/gpio_debug/gpio28/current_pinmux: no such file"), true)
   318  }
   319  
   320  func TestConnectArduinoError(t *testing.T) {
   321  	a, fs := initTestAdaptorWithMockedFilesystem("arduino")
   322  	fs.WithWriteError = true
   323  
   324  	err := a.Connect()
   325  	gobottest.Assert(t, strings.Contains(err.Error(), "write error"), true)
   326  }
   327  
   328  func TestConnectArduinoWriteError(t *testing.T) {
   329  	a, fs := initTestAdaptorWithMockedFilesystem("arduino")
   330  	fs.WithWriteError = true
   331  
   332  	err := a.Connect()
   333  	gobottest.Assert(t, strings.Contains(err.Error(), "write error"), true)
   334  }
   335  
   336  func TestConnectSparkfun(t *testing.T) {
   337  	a, _ := initTestAdaptorWithMockedFilesystem("sparkfun")
   338  
   339  	gobottest.Assert(t, a.Connect(), nil)
   340  	gobottest.Assert(t, a.DefaultI2cBus(), 1)
   341  	gobottest.Assert(t, a.board, "sparkfun")
   342  }
   343  
   344  func TestConnectMiniboard(t *testing.T) {
   345  	a, _ := initTestAdaptorWithMockedFilesystem("miniboard")
   346  
   347  	gobottest.Assert(t, a.Connect(), nil)
   348  	gobottest.Assert(t, a.DefaultI2cBus(), 1)
   349  	gobottest.Assert(t, a.board, "miniboard")
   350  }
   351  
   352  func TestConnectUnknown(t *testing.T) {
   353  	a := NewAdaptor("wha")
   354  
   355  	err := a.Connect()
   356  	gobottest.Assert(t, strings.Contains(err.Error(), "Unknown board type: wha"), true)
   357  }
   358  
   359  func TestFinalize(t *testing.T) {
   360  	a, fs := initTestAdaptorWithMockedFilesystem("arduino")
   361  
   362  	a.DigitalWrite("3", 1)
   363  	a.PwmWrite("5", 100)
   364  
   365  	a.GetI2cConnection(0xff, 6)
   366  	gobottest.Assert(t, a.Finalize(), nil)
   367  
   368  	// assert that finalize after finalize is working
   369  	gobottest.Assert(t, a.Finalize(), nil)
   370  
   371  	// assert that re-connect is working
   372  	a.Connect()
   373  	// remove one file to force Finalize error
   374  	delete(fs.Files, "/sys/class/gpio/unexport")
   375  	err := a.Finalize()
   376  	gobottest.Assert(t, strings.Contains(err.Error(), "1 error occurred"), true)
   377  	gobottest.Assert(t, strings.Contains(err.Error(), "/sys/class/gpio/unexport"), true)
   378  }
   379  
   380  func TestFinalizeError(t *testing.T) {
   381  	a, fs := initTestAdaptorWithMockedFilesystem("arduino")
   382  
   383  	a.PwmWrite("5", 100)
   384  
   385  	fs.WithWriteError = true
   386  	err := a.Finalize()
   387  	gobottest.Assert(t, strings.Contains(err.Error(), "6 errors occurred"), true)
   388  	gobottest.Assert(t, strings.Contains(err.Error(), "write error"), true)
   389  	gobottest.Assert(t, strings.Contains(err.Error(), "SetEnabled(false) failed for id 1 with write error"), true)
   390  	gobottest.Assert(t, strings.Contains(err.Error(), "Unexport() failed for id 1 with write error"), true)
   391  }
   392  
   393  func TestDigitalIO(t *testing.T) {
   394  	a, fs := initTestAdaptorWithMockedFilesystem("arduino")
   395  
   396  	a.DigitalWrite("13", 1)
   397  	gobottest.Assert(t, fs.Files["/sys/class/gpio/gpio40/value"].Contents, "1")
   398  
   399  	a.DigitalWrite("2", 0)
   400  	i, err := a.DigitalRead("2")
   401  	gobottest.Assert(t, err, nil)
   402  	gobottest.Assert(t, i, 0)
   403  }
   404  
   405  func TestDigitalPinInFileError(t *testing.T) {
   406  	a := NewAdaptor()
   407  	fs := a.sys.UseMockFilesystem(pwmMockPathsMux40)
   408  	delete(fs.Files, "/sys/class/gpio/gpio40/value")
   409  	delete(fs.Files, "/sys/class/gpio/gpio40/direction")
   410  	a.Connect()
   411  
   412  	_, err := a.DigitalPin("13")
   413  	gobottest.Assert(t, strings.Contains(err.Error(), "no such file"), true)
   414  
   415  }
   416  
   417  func TestDigitalPinInResistorFileError(t *testing.T) {
   418  	a := NewAdaptor()
   419  	fs := a.sys.UseMockFilesystem(pwmMockPathsMux40)
   420  	delete(fs.Files, "/sys/class/gpio/gpio229/value")
   421  	delete(fs.Files, "/sys/class/gpio/gpio229/direction")
   422  	a.Connect()
   423  
   424  	_, err := a.DigitalPin("13")
   425  	gobottest.Assert(t, strings.Contains(err.Error(), "no such file"), true)
   426  }
   427  
   428  func TestDigitalPinInLevelShifterFileError(t *testing.T) {
   429  	a := NewAdaptor()
   430  	fs := a.sys.UseMockFilesystem(pwmMockPathsMux40)
   431  	delete(fs.Files, "/sys/class/gpio/gpio261/value")
   432  	delete(fs.Files, "/sys/class/gpio/gpio261/direction")
   433  	a.Connect()
   434  
   435  	_, err := a.DigitalPin("13")
   436  	gobottest.Assert(t, strings.Contains(err.Error(), "no such file"), true)
   437  }
   438  
   439  func TestDigitalPinInMuxFileError(t *testing.T) {
   440  	a := NewAdaptor()
   441  	fs := a.sys.UseMockFilesystem(pwmMockPathsMux40)
   442  	delete(fs.Files, "/sys/class/gpio/gpio243/value")
   443  	delete(fs.Files, "/sys/class/gpio/gpio243/direction")
   444  	a.Connect()
   445  
   446  	_, err := a.DigitalPin("13")
   447  	gobottest.Assert(t, strings.Contains(err.Error(), "no such file"), true)
   448  }
   449  
   450  func TestDigitalWriteError(t *testing.T) {
   451  	a, fs := initTestAdaptorWithMockedFilesystem("arduino")
   452  	fs.WithWriteError = true
   453  
   454  	err := a.DigitalWrite("13", 1)
   455  	gobottest.Assert(t, err, fmt.Errorf("write error"))
   456  }
   457  
   458  func TestDigitalReadWriteError(t *testing.T) {
   459  	a, fs := initTestAdaptorWithMockedFilesystem("arduino")
   460  	fs.WithWriteError = true
   461  
   462  	_, err := a.DigitalRead("13")
   463  	gobottest.Assert(t, err, fmt.Errorf("write error"))
   464  }
   465  
   466  func TestPwm(t *testing.T) {
   467  	a, fs := initTestAdaptorWithMockedFilesystem("arduino")
   468  
   469  	err := a.PwmWrite("5", 100)
   470  	gobottest.Assert(t, err, nil)
   471  	gobottest.Assert(t, fs.Files["/sys/class/pwm/pwmchip0/pwm1/duty_cycle"].Contents, "1960")
   472  
   473  	err = a.PwmWrite("7", 100)
   474  	gobottest.Assert(t, err, fmt.Errorf("'7' is not a valid id for a PWM pin"))
   475  }
   476  
   477  func TestPwmExportError(t *testing.T) {
   478  	a := NewAdaptor()
   479  	fs := a.sys.UseMockFilesystem(pwmMockPathsMux13Arduino)
   480  	delete(fs.Files, "/sys/class/pwm/pwmchip0/export")
   481  	err := a.Connect()
   482  	gobottest.Assert(t, err, nil)
   483  
   484  	err = a.PwmWrite("5", 100)
   485  	gobottest.Assert(t, strings.Contains(err.Error(), "/sys/class/pwm/pwmchip0/export: no such file"), true)
   486  }
   487  
   488  func TestPwmEnableError(t *testing.T) {
   489  	a := NewAdaptor()
   490  	fs := a.sys.UseMockFilesystem(pwmMockPathsMux13)
   491  	delete(fs.Files, "/sys/class/pwm/pwmchip0/pwm1/enable")
   492  	a.Connect()
   493  
   494  	err := a.PwmWrite("5", 100)
   495  	gobottest.Assert(t, strings.Contains(err.Error(), "/sys/class/pwm/pwmchip0/pwm1/enable: no such file"), true)
   496  }
   497  
   498  func TestPwmWritePinError(t *testing.T) {
   499  	a, fs := initTestAdaptorWithMockedFilesystem("arduino")
   500  	fs.WithWriteError = true
   501  
   502  	err := a.PwmWrite("5", 100)
   503  	gobottest.Assert(t, err, fmt.Errorf("write error"))
   504  }
   505  
   506  func TestPwmWriteError(t *testing.T) {
   507  	a, fs := initTestAdaptorWithMockedFilesystem("arduino")
   508  	fs.WithWriteError = true
   509  
   510  	err := a.PwmWrite("5", 100)
   511  	gobottest.Assert(t, strings.Contains(err.Error(), "write error"), true)
   512  }
   513  
   514  func TestPwmReadError(t *testing.T) {
   515  	a, fs := initTestAdaptorWithMockedFilesystem("arduino")
   516  	fs.WithReadError = true
   517  
   518  	err := a.PwmWrite("5", 100)
   519  	gobottest.Assert(t, strings.Contains(err.Error(), "read error"), true)
   520  }
   521  
   522  func TestAnalog(t *testing.T) {
   523  	a, fs := initTestAdaptorWithMockedFilesystem("arduino")
   524  	fs.Files["/sys/bus/iio/devices/iio:device1/in_voltage0_raw"].Contents = "1000\n"
   525  
   526  	i, _ := a.AnalogRead("0")
   527  	gobottest.Assert(t, i, 250)
   528  }
   529  
   530  func TestAnalogError(t *testing.T) {
   531  	a, fs := initTestAdaptorWithMockedFilesystem("arduino")
   532  	fs.WithReadError = true
   533  
   534  	_, err := a.AnalogRead("0")
   535  	gobottest.Assert(t, err, fmt.Errorf("read error"))
   536  }
   537  
   538  func TestI2cWorkflow(t *testing.T) {
   539  	a, _ := initTestAdaptorWithMockedFilesystem("arduino")
   540  	a.sys.UseMockSyscall()
   541  
   542  	con, err := a.GetI2cConnection(0xff, 6)
   543  	gobottest.Assert(t, err, nil)
   544  
   545  	_, err = con.Write([]byte{0x00, 0x01})
   546  	gobottest.Assert(t, err, nil)
   547  
   548  	data := []byte{42, 42}
   549  	_, err = con.Read(data)
   550  	gobottest.Assert(t, err, nil)
   551  	gobottest.Assert(t, data, []byte{0x00, 0x01})
   552  
   553  	gobottest.Assert(t, a.Finalize(), nil)
   554  }
   555  
   556  func TestI2cFinalizeWithErrors(t *testing.T) {
   557  	// arrange
   558  	a := NewAdaptor()
   559  	a.sys.UseMockSyscall()
   560  	fs := a.sys.UseMockFilesystem(pwmMockPathsMux13ArduinoI2c)
   561  	gobottest.Assert(t, a.Connect(), nil)
   562  	con, err := a.GetI2cConnection(0xff, 6)
   563  	gobottest.Assert(t, err, nil)
   564  	_, err = con.Write([]byte{0x0A})
   565  	gobottest.Assert(t, err, nil)
   566  	fs.WithCloseError = true
   567  	// act
   568  	err = a.Finalize()
   569  	// assert
   570  	gobottest.Refute(t, err, nil)
   571  	gobottest.Assert(t, strings.Contains(err.Error(), "close error"), true)
   572  
   573  }
   574  
   575  func Test_validateI2cBusNumber(t *testing.T) {
   576  	var tests = map[string]struct {
   577  		board   string
   578  		busNr   int
   579  		wantErr error
   580  	}{
   581  		"arduino_number_negative_error": {
   582  			busNr:   -1,
   583  			wantErr: fmt.Errorf("Unsupported I2C bus '-1'"),
   584  		},
   585  		"arduino_number_1_error": {
   586  			busNr:   1,
   587  			wantErr: fmt.Errorf("Unsupported I2C bus '1'"),
   588  		},
   589  		"arduino_number_6_ok": {
   590  			busNr: 6,
   591  		},
   592  		"sparkfun_number_negative_error": {
   593  			board:   "sparkfun",
   594  			busNr:   -1,
   595  			wantErr: fmt.Errorf("Unsupported I2C bus '-1'"),
   596  		},
   597  		"sparkfun_number_1_ok": {
   598  			board: "sparkfun",
   599  			busNr: 1,
   600  		},
   601  		"miniboard_number_6_error": {
   602  			board:   "miniboard",
   603  			busNr:   6,
   604  			wantErr: fmt.Errorf("Unsupported I2C bus '6'"),
   605  		},
   606  	}
   607  	for name, tc := range tests {
   608  		t.Run(name, func(t *testing.T) {
   609  			// arrange
   610  			a := NewAdaptor(tc.board)
   611  			a.sys.UseMockFilesystem(pwmMockPathsMux13ArduinoI2c)
   612  			a.Connect()
   613  			// act
   614  			err := a.validateAndSetupI2cBusNumber(tc.busNr)
   615  			// assert
   616  			gobottest.Assert(t, err, tc.wantErr)
   617  		})
   618  	}
   619  }