gobot.io/x/gobot@v1.16.0/platforms/raspi/raspi_adaptor_test.go (about)

     1  package raspi
     2  
     3  import (
     4  	"errors"
     5  	"strings"
     6  	"testing"
     7  
     8  	"runtime"
     9  	"strconv"
    10  	"sync"
    11  
    12  	"gobot.io/x/gobot"
    13  	"gobot.io/x/gobot/drivers/gpio"
    14  	"gobot.io/x/gobot/drivers/i2c"
    15  	"gobot.io/x/gobot/drivers/spi"
    16  	"gobot.io/x/gobot/gobottest"
    17  	"gobot.io/x/gobot/sysfs"
    18  )
    19  
    20  // make sure that this Adaptor fullfills all the required interfaces
    21  var _ gobot.Adaptor = (*Adaptor)(nil)
    22  var _ gpio.DigitalReader = (*Adaptor)(nil)
    23  var _ gpio.DigitalWriter = (*Adaptor)(nil)
    24  var _ gpio.PwmWriter = (*Adaptor)(nil)
    25  var _ gpio.ServoWriter = (*Adaptor)(nil)
    26  var _ sysfs.DigitalPinnerProvider = (*Adaptor)(nil)
    27  var _ sysfs.PWMPinnerProvider = (*Adaptor)(nil)
    28  var _ i2c.Connector = (*Adaptor)(nil)
    29  var _ spi.Connector = (*Adaptor)(nil)
    30  
    31  func initTestAdaptor() *Adaptor {
    32  	readFile = func() ([]byte, error) {
    33  		return []byte(`
    34  Hardware        : BCM2708
    35  Revision        : 0010
    36  Serial          : 000000003bc748ea
    37  `), nil
    38  	}
    39  	a := NewAdaptor()
    40  	a.Connect()
    41  	return a
    42  }
    43  
    44  func TestRaspiAdaptorName(t *testing.T) {
    45  	a := initTestAdaptor()
    46  	gobottest.Assert(t, strings.HasPrefix(a.Name(), "RaspberryPi"), true)
    47  	a.SetName("NewName")
    48  	gobottest.Assert(t, a.Name(), "NewName")
    49  }
    50  
    51  func TestAdaptor(t *testing.T) {
    52  	readFile = func() ([]byte, error) {
    53  		return []byte(`
    54  Hardware        : BCM2708
    55  Revision        : 0010
    56  Serial          : 000000003bc748ea
    57  `), nil
    58  	}
    59  	a := NewAdaptor()
    60  	gobottest.Assert(t, strings.HasPrefix(a.Name(), "RaspberryPi"), true)
    61  	gobottest.Assert(t, a.i2cDefaultBus, 1)
    62  	gobottest.Assert(t, a.revision, "3")
    63  
    64  	readFile = func() ([]byte, error) {
    65  		return []byte(`
    66  Hardware        : BCM2708
    67  Revision        : 000D
    68  Serial          : 000000003bc748ea
    69  `), nil
    70  	}
    71  	a = NewAdaptor()
    72  	gobottest.Assert(t, a.i2cDefaultBus, 1)
    73  	gobottest.Assert(t, a.revision, "2")
    74  
    75  	readFile = func() ([]byte, error) {
    76  		return []byte(`
    77  Hardware        : BCM2708
    78  Revision        : 0002
    79  Serial          : 000000003bc748ea
    80  `), nil
    81  	}
    82  	a = NewAdaptor()
    83  	gobottest.Assert(t, a.i2cDefaultBus, 0)
    84  	gobottest.Assert(t, a.revision, "1")
    85  
    86  }
    87  
    88  func TestAdaptorFinalize(t *testing.T) {
    89  	a := initTestAdaptor()
    90  
    91  	fs := sysfs.NewMockFilesystem([]string{
    92  		"/sys/class/gpio/export",
    93  		"/sys/class/gpio/unexport",
    94  		"/dev/pi-blaster",
    95  		"/dev/i2c-1",
    96  		"/dev/i2c-0",
    97  		"/dev/spidev0.0",
    98  		"/dev/spidev0.1",
    99  	})
   100  
   101  	sysfs.SetFilesystem(fs)
   102  	sysfs.SetSyscall(&sysfs.MockSyscall{})
   103  
   104  	a.DigitalWrite("3", 1)
   105  	a.PwmWrite("7", 255)
   106  
   107  	a.GetConnection(0xff, 0)
   108  	gobottest.Assert(t, a.Finalize(), nil)
   109  }
   110  
   111  func TestAdaptorDigitalPWM(t *testing.T) {
   112  	a := initTestAdaptor()
   113  	a.PiBlasterPeriod = 20000000
   114  
   115  	gobottest.Assert(t, a.PwmWrite("7", 4), nil)
   116  
   117  	fs := sysfs.NewMockFilesystem([]string{
   118  		"/dev/pi-blaster",
   119  	})
   120  	sysfs.SetFilesystem(fs)
   121  
   122  	pin, _ := a.PWMPin("7")
   123  	period, _ := pin.Period()
   124  	gobottest.Assert(t, period, uint32(20000000))
   125  
   126  	gobottest.Assert(t, a.PwmWrite("7", 255), nil)
   127  
   128  	gobottest.Assert(t, strings.Split(fs.Files["/dev/pi-blaster"].Contents, "\n")[0], "4=1")
   129  
   130  	gobottest.Assert(t, a.ServoWrite("11", 90), nil)
   131  
   132  	gobottest.Assert(t, strings.Split(fs.Files["/dev/pi-blaster"].Contents, "\n")[0], "17=0.5")
   133  
   134  	gobottest.Assert(t, a.PwmWrite("notexist", 1), errors.New("Not a valid pin"))
   135  	gobottest.Assert(t, a.ServoWrite("notexist", 1), errors.New("Not a valid pin"))
   136  
   137  	pin, _ = a.PWMPin("12")
   138  	period, _ = pin.Period()
   139  	gobottest.Assert(t, period, uint32(20000000))
   140  
   141  	gobottest.Assert(t, pin.SetDutyCycle(1.5*1000*1000), nil)
   142  
   143  	gobottest.Assert(t, strings.Split(fs.Files["/dev/pi-blaster"].Contents, "\n")[0], "18=0.075")
   144  }
   145  
   146  func TestAdaptorDigitalIO(t *testing.T) {
   147  	a := initTestAdaptor()
   148  	fs := sysfs.NewMockFilesystem([]string{
   149  		"/sys/class/gpio/export",
   150  		"/sys/class/gpio/unexport",
   151  		"/sys/class/gpio/gpio4/value",
   152  		"/sys/class/gpio/gpio4/direction",
   153  		"/sys/class/gpio/gpio27/value",
   154  		"/sys/class/gpio/gpio27/direction",
   155  	})
   156  
   157  	sysfs.SetFilesystem(fs)
   158  
   159  	a.DigitalWrite("7", 1)
   160  	gobottest.Assert(t, fs.Files["/sys/class/gpio/gpio4/value"].Contents, "1")
   161  
   162  	a.DigitalWrite("13", 1)
   163  	i, _ := a.DigitalRead("13")
   164  	gobottest.Assert(t, i, 1)
   165  
   166  	gobottest.Assert(t, a.DigitalWrite("notexist", 1), errors.New("Not a valid pin"))
   167  
   168  	fs.WithReadError = true
   169  	_, err := a.DigitalRead("13")
   170  	gobottest.Assert(t, err, errors.New("read error"))
   171  
   172  	fs.WithWriteError = true
   173  	_, err = a.DigitalRead("7")
   174  	gobottest.Assert(t, err, errors.New("write error"))
   175  }
   176  
   177  func TestAdaptorI2c(t *testing.T) {
   178  	a := initTestAdaptor()
   179  	fs := sysfs.NewMockFilesystem([]string{
   180  		"/dev/i2c-1",
   181  	})
   182  	sysfs.SetFilesystem(fs)
   183  	sysfs.SetSyscall(&sysfs.MockSyscall{})
   184  
   185  	con, err := a.GetConnection(0xff, 1)
   186  	gobottest.Assert(t, err, nil)
   187  
   188  	con.Write([]byte{0x00, 0x01})
   189  	data := []byte{42, 42}
   190  	con.Read(data)
   191  	gobottest.Assert(t, data, []byte{0x00, 0x01})
   192  
   193  	_, err = a.GetConnection(0xff, 51)
   194  	gobottest.Assert(t, err, errors.New("Bus number 51 out of range"))
   195  
   196  	gobottest.Assert(t, a.GetDefaultBus(), 1)
   197  }
   198  
   199  func TestAdaptorSPI(t *testing.T) {
   200  	a := initTestAdaptor()
   201  	fs := sysfs.NewMockFilesystem([]string{
   202  		"/dev/spidev0.1",
   203  	})
   204  	sysfs.SetFilesystem(fs)
   205  	sysfs.SetSyscall(&sysfs.MockSyscall{})
   206  
   207  	gobottest.Assert(t, a.GetSpiDefaultBus(), 0)
   208  	gobottest.Assert(t, a.GetSpiDefaultChip(), 0)
   209  	gobottest.Assert(t, a.GetSpiDefaultMode(), 0)
   210  	gobottest.Assert(t, a.GetSpiDefaultMaxSpeed(), int64(500000))
   211  
   212  	_, err := a.GetSpiConnection(10, 0, 0, 8, 500000)
   213  	gobottest.Assert(t, err.Error(), "Bus number 10 out of range")
   214  
   215  	// TODO: test tx/rx here...
   216  }
   217  
   218  func TestAdaptorDigitalPinConcurrency(t *testing.T) {
   219  
   220  	oldProcs := runtime.GOMAXPROCS(0)
   221  	runtime.GOMAXPROCS(8)
   222  
   223  	for retry := 0; retry < 20; retry++ {
   224  
   225  		a := initTestAdaptor()
   226  		var wg sync.WaitGroup
   227  
   228  		for i := 0; i < 20; i++ {
   229  			wg.Add(1)
   230  			pinAsString := strconv.Itoa(i)
   231  			go func(pin string) {
   232  				defer wg.Done()
   233  				a.DigitalPin(pin, sysfs.IN)
   234  			}(pinAsString)
   235  		}
   236  
   237  		wg.Wait()
   238  	}
   239  
   240  	runtime.GOMAXPROCS(oldProcs)
   241  
   242  }
   243  
   244  func TestAdaptorPWMPin(t *testing.T) {
   245  	a := initTestAdaptor()
   246  
   247  	gobottest.Assert(t, len(a.pwmPins), 0)
   248  
   249  	firstSysPin, err := a.PWMPin("35")
   250  
   251  	gobottest.Assert(t, err, nil)
   252  	gobottest.Assert(t, len(a.pwmPins), 1)
   253  
   254  	secondSysPin, err := a.PWMPin("35")
   255  
   256  	gobottest.Assert(t, err, nil)
   257  	gobottest.Assert(t, len(a.pwmPins), 1)
   258  	gobottest.Assert(t, firstSysPin, secondSysPin)
   259  
   260  	otherSysPin, err := a.PWMPin("36")
   261  
   262  	gobottest.Assert(t, err, nil)
   263  	gobottest.Assert(t, len(a.pwmPins), 2)
   264  	gobottest.Refute(t, firstSysPin, otherSysPin)
   265  }