gobot.io/x/gobot/v2@v2.1.0/platforms/chip/chip_adaptor_test.go (about)

     1  package chip
     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/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 _ gpio.PwmWriter = (*Adaptor)(nil)
    23  var _ gpio.ServoWriter = (*Adaptor)(nil)
    24  var _ i2c.Connector = (*Adaptor)(nil)
    25  
    26  var mockPaths = []string{
    27  	"/sys/class/gpio/export",
    28  	"/sys/class/gpio/unexport",
    29  	"/sys/class/gpio/gpio50/value",
    30  	"/sys/class/gpio/gpio50/direction",
    31  	"/sys/class/gpio/gpio139/value",
    32  	"/sys/class/gpio/gpio139/direction",
    33  	"/sys/class/pwm/pwmchip0/export",
    34  	"/sys/class/pwm/pwmchip0/unexport",
    35  	"/sys/class/pwm/pwmchip0/pwm0/enable",
    36  	"/sys/class/pwm/pwmchip0/pwm0/duty_cycle",
    37  	"/sys/class/pwm/pwmchip0/pwm0/polarity",
    38  	"/sys/class/pwm/pwmchip0/pwm0/period",
    39  }
    40  
    41  func initTestAdaptorWithMockedFilesystem() (*Adaptor, *system.MockFilesystem) {
    42  	a := NewAdaptor()
    43  	fs := a.sys.UseMockFilesystem(mockPaths)
    44  	if err := a.Connect(); err != nil {
    45  		panic(err)
    46  	}
    47  	return a, fs
    48  }
    49  
    50  func initTestProAdaptorWithMockedFilesystem() (*Adaptor, *system.MockFilesystem) {
    51  	a := NewProAdaptor()
    52  	fs := a.sys.UseMockFilesystem(mockPaths)
    53  	if err := a.Connect(); err != nil {
    54  		panic(err)
    55  	}
    56  	return a, fs
    57  }
    58  
    59  func TestName(t *testing.T) {
    60  	a := NewAdaptor()
    61  	gobottest.Assert(t, strings.HasPrefix(a.Name(), "CHIP"), true)
    62  	a.SetName("NewName")
    63  	gobottest.Assert(t, a.Name(), "NewName")
    64  }
    65  
    66  func TestNewProAdaptor(t *testing.T) {
    67  	a := NewProAdaptor()
    68  	gobottest.Assert(t, strings.HasPrefix(a.Name(), "CHIP Pro"), true)
    69  }
    70  
    71  func TestFinalizeErrorAfterGPIO(t *testing.T) {
    72  	a, fs := initTestAdaptorWithMockedFilesystem()
    73  	gobottest.Assert(t, a.Connect(), nil)
    74  	gobottest.Assert(t, a.DigitalWrite("CSID7", 1), nil)
    75  
    76  	fs.WithWriteError = true
    77  
    78  	err := a.Finalize()
    79  	gobottest.Assert(t, strings.Contains(err.Error(), "write error"), true)
    80  }
    81  
    82  func TestFinalizeErrorAfterPWM(t *testing.T) {
    83  	a, fs := initTestAdaptorWithMockedFilesystem()
    84  	gobottest.Assert(t, a.Connect(), nil)
    85  	gobottest.Assert(t, a.PwmWrite("PWM0", 100), nil)
    86  
    87  	fs.WithWriteError = true
    88  
    89  	err := a.Finalize()
    90  	gobottest.Assert(t, strings.Contains(err.Error(), "write error"), true)
    91  }
    92  
    93  func TestDigitalIO(t *testing.T) {
    94  	a, fs := initTestAdaptorWithMockedFilesystem()
    95  	a.Connect()
    96  
    97  	a.DigitalWrite("CSID7", 1)
    98  	gobottest.Assert(t, fs.Files["/sys/class/gpio/gpio139/value"].Contents, "1")
    99  
   100  	fs.Files["/sys/class/gpio/gpio50/value"].Contents = "1"
   101  	i, _ := a.DigitalRead("TWI2-SDA")
   102  	gobottest.Assert(t, i, 1)
   103  
   104  	gobottest.Assert(t, a.DigitalWrite("XIO-P10", 1), errors.New("'XIO-P10' is not a valid id for a digital pin"))
   105  	gobottest.Assert(t, a.Finalize(), nil)
   106  }
   107  
   108  func TestProDigitalIO(t *testing.T) {
   109  	a, fs := initTestProAdaptorWithMockedFilesystem()
   110  	a.Connect()
   111  
   112  	a.DigitalWrite("CSID7", 1)
   113  	gobottest.Assert(t, fs.Files["/sys/class/gpio/gpio139/value"].Contents, "1")
   114  
   115  	fs.Files["/sys/class/gpio/gpio50/value"].Contents = "1"
   116  	i, _ := a.DigitalRead("TWI2-SDA")
   117  	gobottest.Assert(t, i, 1)
   118  
   119  	gobottest.Assert(t, a.DigitalWrite("XIO-P0", 1), errors.New("'XIO-P0' is not a valid id for a digital pin"))
   120  	gobottest.Assert(t, a.Finalize(), nil)
   121  }
   122  
   123  func TestPWM(t *testing.T) {
   124  	a, fs := initTestAdaptorWithMockedFilesystem()
   125  	a.Connect()
   126  
   127  	err := a.PwmWrite("PWM0", 100)
   128  	gobottest.Assert(t, err, nil)
   129  
   130  	gobottest.Assert(t, fs.Files["/sys/class/pwm/pwmchip0/export"].Contents, "0")
   131  	gobottest.Assert(t, fs.Files["/sys/class/pwm/pwmchip0/pwm0/enable"].Contents, "1")
   132  	gobottest.Assert(t, fs.Files["/sys/class/pwm/pwmchip0/pwm0/duty_cycle"].Contents, "3921568")
   133  	gobottest.Assert(t, fs.Files["/sys/class/pwm/pwmchip0/pwm0/polarity"].Contents, "normal")
   134  
   135  	err = a.ServoWrite("PWM0", 0)
   136  	gobottest.Assert(t, err, nil)
   137  
   138  	gobottest.Assert(t, fs.Files["/sys/class/pwm/pwmchip0/pwm0/duty_cycle"].Contents, "500000")
   139  
   140  	err = a.ServoWrite("PWM0", 180)
   141  	gobottest.Assert(t, err, nil)
   142  
   143  	gobottest.Assert(t, fs.Files["/sys/class/pwm/pwmchip0/pwm0/duty_cycle"].Contents, "2000000")
   144  	gobottest.Assert(t, a.Finalize(), nil)
   145  }
   146  
   147  func TestI2cDefaultBus(t *testing.T) {
   148  	a := NewAdaptor()
   149  	gobottest.Assert(t, a.DefaultI2cBus(), 1)
   150  }
   151  
   152  func TestI2cFinalizeWithErrors(t *testing.T) {
   153  	// arrange
   154  	a := NewAdaptor()
   155  	a.sys.UseMockSyscall()
   156  	fs := a.sys.UseMockFilesystem([]string{"/dev/i2c-2"})
   157  	gobottest.Assert(t, a.Connect(), nil)
   158  	con, err := a.GetI2cConnection(0xff, 2)
   159  	gobottest.Assert(t, err, nil)
   160  	_, err = con.Write([]byte{0xbf})
   161  	gobottest.Assert(t, err, nil)
   162  	fs.WithCloseError = true
   163  	// act
   164  	err = a.Finalize()
   165  	// assert
   166  	gobottest.Assert(t, strings.Contains(err.Error(), "close error"), true)
   167  }
   168  
   169  func Test_validateI2cBusNumber(t *testing.T) {
   170  	var tests = map[string]struct {
   171  		busNr   int
   172  		wantErr error
   173  	}{
   174  		"number_negative_error": {
   175  			busNr:   -1,
   176  			wantErr: fmt.Errorf("Bus number -1 out of range"),
   177  		},
   178  		"number_0_ok": {
   179  			busNr: 0,
   180  		},
   181  		"number_1_ok": {
   182  			busNr: 1,
   183  		},
   184  		"number_2_ok": {
   185  			busNr: 2,
   186  		},
   187  		"number_3_error": {
   188  			busNr:   3,
   189  			wantErr: fmt.Errorf("Bus number 3 out of range"),
   190  		},
   191  	}
   192  	for name, tc := range tests {
   193  		t.Run(name, func(t *testing.T) {
   194  			// arrange
   195  			a := NewAdaptor()
   196  			// act
   197  			err := a.validateI2cBusNumber(tc.busNr)
   198  			// assert
   199  			gobottest.Assert(t, err, tc.wantErr)
   200  		})
   201  	}
   202  }
   203  
   204  func Test_translatePWMPin(t *testing.T) {
   205  	var tests = map[string]struct {
   206  		usePro      bool
   207  		wantDir     string
   208  		wantChannel int
   209  		wantErr     error
   210  	}{
   211  		"PWM0": {
   212  			wantDir:     "/sys/class/pwm/pwmchip0",
   213  			wantChannel: 0,
   214  		},
   215  		"PWM1": {
   216  			usePro:      true,
   217  			wantDir:     "/sys/class/pwm/pwmchip0",
   218  			wantChannel: 1,
   219  		},
   220  		"33_1": {
   221  			wantDir:     "",
   222  			wantChannel: -1,
   223  			wantErr:     fmt.Errorf("'33_1' is not a valid id for a pin"),
   224  		},
   225  		"AP-EINT3": {
   226  			wantDir:     "",
   227  			wantChannel: -1,
   228  			wantErr:     fmt.Errorf("'AP-EINT3' is not a valid id for a PWM pin"),
   229  		},
   230  	}
   231  	for name, tc := range tests {
   232  		t.Run(name, func(t *testing.T) {
   233  			// arrange
   234  			var a *Adaptor
   235  			if tc.usePro {
   236  				a = NewProAdaptor()
   237  			} else {
   238  				a = NewAdaptor()
   239  			}
   240  			// act
   241  			dir, channel, err := a.translatePWMPin(name)
   242  			// assert
   243  			gobottest.Assert(t, err, tc.wantErr)
   244  			gobottest.Assert(t, dir, tc.wantDir)
   245  			gobottest.Assert(t, channel, tc.wantChannel)
   246  		})
   247  	}
   248  }