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 }