1
0
mirror of https://github.com/hybridgroup/gobot.git synced 2025-04-24 13:48:49 +08:00

system(syscall): switch to x/sys (#963)

This commit is contained in:
Thomas Kohler 2023-06-19 16:06:44 +02:00
parent 0648f66ef8
commit bc3d7d4194
12 changed files with 61 additions and 51 deletions

View File

@ -32,7 +32,7 @@ linters:
# currently active linters:
#
#INFO [lintersdb] Active 35 linters: [asasalint asciicheck bidichk contextcheck decorder depguard durationcheck errcheck exportloopref
# gocheckcompilerdirectives gomoddirectives gomodguard goprintffuncname gosimple govet grouper importas ineffassign mirror musttag
# gocheckcompilerdirectives gomoddirectives gomodguard goprintffuncname gosimple govet grouper ineffassign mirror musttag
# nilerr nilnil nolintlint nosprintfhostport prealloc reassign revive staticcheck tagalign tenv testableexamples tparallel typecheck unused wastedassign]
enable-all: true
@ -62,6 +62,7 @@ linters:
- goerr113 # not used (we allow error creation at return statement)
- gofumpt # not used (we use "go fmt" or "gofmt" not gofumpt"
- gosmopolitan # not needed (report i18n/l10n anti-patterns)
- importas # not needed (there is no alias rule at the moment)
- ireturn # not used (we allow return interfaces)
- loggercheck # not needed (relates to kitlog, klog, logr, zap)
- paralleltest # not used

View File

@ -16,7 +16,7 @@ including_except := $(shell go list ./... | grep -v platforms/opencv)
# Run tests on nearly all directories without test cache
test:
go test -count=1 -v $(including_except)
go test -failfast -count=1 -v $(including_except)
# Run tests with race detection
test_race:

View File

@ -7,7 +7,6 @@ import (
"errors"
"testing"
"syscall"
"unsafe"
"gobot.io/x/gobot/v2"
@ -17,13 +16,13 @@ import (
const dev = "/dev/i2c-1"
func getSyscallFuncImpl(errorMask byte) func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) {
func getSyscallFuncImpl(errorMask byte) func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err system.SyscallErrno) {
// bit 0: error on function query
// bit 1: error on set address
// bit 2: error on command
return func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) {
return func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err system.SyscallErrno) {
// function query
if (trap == syscall.SYS_IOCTL) && (a2 == system.I2C_FUNCS) {
if (trap == system.Syscall_SYS_IOCTL) && (a2 == system.I2C_FUNCS) {
if errorMask&0x01 == 0x01 {
return 0, 0, 1
}
@ -35,13 +34,13 @@ func getSyscallFuncImpl(errorMask byte) func(trap, a1, a2, a3 uintptr) (r1, r2 u
system.I2C_FUNC_SMBUS_WRITE_WORD_DATA
}
// set address
if (trap == syscall.SYS_IOCTL) && (a2 == system.I2C_SLAVE) {
if (trap == system.Syscall_SYS_IOCTL) && (a2 == system.I2C_SLAVE) {
if errorMask&0x02 == 0x02 {
return 0, 0, 1
}
}
// command
if (trap == syscall.SYS_IOCTL) && (a2 == system.I2C_SMBUS) {
if (trap == system.Syscall_SYS_IOCTL) && (a2 == system.I2C_SMBUS) {
if errorMask&0x04 == 0x04 {
return 0, 0, 1
}

View File

@ -7,7 +7,6 @@ import (
"log"
"os"
"strconv"
"syscall"
"time"
"gobot.io/x/gobot/v2"
@ -92,7 +91,7 @@ func (d *digitalPinSysfs) Unexport() error {
if err != nil {
// If EINVAL then the pin is reserved in the system and can't be unexported
e, ok := err.(*os.PathError)
if !ok || e.Err != syscall.EINVAL {
if !ok || e.Err != Syscall_EINVAL {
return err
}
}
@ -126,7 +125,7 @@ func (d *digitalPinSysfs) reconfigure() error {
if err != nil {
// If EBUSY then the pin has already been exported
e, ok := err.(*os.PathError)
if !ok || e.Err != syscall.EBUSY {
if !ok || e.Err != Syscall_EBUSY {
return err
}
}

View File

@ -3,7 +3,6 @@ package system
import (
"errors"
"os"
"syscall"
"testing"
"gobot.io/x/gobot/v2"
@ -63,7 +62,7 @@ func TestDigitalPin(t *testing.T) {
gobottest.Assert(t, data, 0)
writeFile = func(File, []byte) (int, error) {
return 0, &os.PathError{Err: syscall.EINVAL}
return 0, &os.PathError{Err: Syscall_EINVAL}
}
err = pin.Unexport()
@ -81,7 +80,7 @@ func TestDigitalPin(t *testing.T) {
writeFile = func(File, []byte) (int, error) {
cnt++
if cnt == 1 {
return 0, &os.PathError{Err: syscall.EBUSY}
return 0, &os.PathError{Err: Syscall_EBUSY}
}
return 0, nil
}
@ -104,7 +103,7 @@ func TestDigitalPinExportError(t *testing.T) {
pin, _ := initTestDigitalPinSysFsWithMockedFilesystem(mockPaths)
writeFile = func(File, []byte) (int, error) {
return 0, &os.PathError{Err: syscall.EBUSY}
return 0, &os.PathError{Err: Syscall_EBUSY}
}
err := pin.Export()
@ -118,7 +117,7 @@ func TestDigitalPinUnexportError(t *testing.T) {
pin, _ := initTestDigitalPinSysFsWithMockedFilesystem(mockPaths)
writeFile = func(File, []byte) (int, error) {
return 0, &os.PathError{Err: syscall.EBUSY}
return 0, &os.PathError{Err: Syscall_EBUSY}
}
err := pin.Unexport()

View File

@ -5,7 +5,6 @@ import (
"log"
"os"
"sync"
"syscall"
"unsafe"
)
@ -375,7 +374,7 @@ func (d *i2cDevice) syscallIoctl(signal uintptr, payload unsafe.Pointer, sender
if err := d.openFileLazy(sender); err != nil {
return err
}
if _, _, errno := d.sys.syscall(syscall.SYS_IOCTL, d.file, signal, payload); errno != 0 {
if _, _, errno := d.sys.syscall(Syscall_SYS_IOCTL, d.file, signal, payload); errno != 0 {
return fmt.Errorf("%s failed with syscall.Errno %v", sender, errno)
}

View File

@ -3,7 +3,6 @@ package system
import (
"errors"
"os"
"syscall"
"testing"
"unsafe"
@ -13,13 +12,13 @@ import (
const dev = "/dev/i2c-1"
func getSyscallFuncImpl(errorMask byte) func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) {
func getSyscallFuncImpl(errorMask byte) func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err SyscallErrno) {
// bit 0: error on function query
// bit 1: error on set address
// bit 2: error on command
return func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) {
return func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err SyscallErrno) {
// function query
if (trap == syscall.SYS_IOCTL) && (a2 == I2C_FUNCS) {
if (trap == Syscall_SYS_IOCTL) && (a2 == I2C_FUNCS) {
if errorMask&0x01 == 0x01 {
return 0, 0, 1
}
@ -31,13 +30,13 @@ func getSyscallFuncImpl(errorMask byte) func(trap, a1, a2, a3 uintptr) (r1, r2 u
I2C_FUNC_SMBUS_WRITE_WORD_DATA
}
// set address
if (trap == syscall.SYS_IOCTL) && (a2 == I2C_SLAVE) {
if (trap == Syscall_SYS_IOCTL) && (a2 == I2C_SLAVE) {
if errorMask&0x02 == 0x02 {
return 0, 0, 1
}
}
// command
if (trap == syscall.SYS_IOCTL) && (a2 == I2C_SMBUS) {
if (trap == Syscall_SYS_IOCTL) && (a2 == I2C_SMBUS) {
if errorMask&0x04 == 0x04 {
return 0, 0, 1
}
@ -117,7 +116,7 @@ func TestWriteRead(t *testing.T) {
func TestReadByte(t *testing.T) {
var tests = map[string]struct {
funcs uint64
syscallImpl func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno)
syscallImpl func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err SyscallErrno)
wantErr string
}{
"read_byte_ok": {
@ -161,7 +160,7 @@ func TestReadByte(t *testing.T) {
func TestReadByteData(t *testing.T) {
var tests = map[string]struct {
funcs uint64
syscallImpl func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno)
syscallImpl func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err SyscallErrno)
wantErr string
}{
"read_byte_data_ok": {
@ -208,7 +207,7 @@ func TestReadByteData(t *testing.T) {
func TestReadWordData(t *testing.T) {
var tests = map[string]struct {
funcs uint64
syscallImpl func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno)
syscallImpl func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err SyscallErrno)
wantErr string
}{
"read_word_data_ok": {
@ -272,7 +271,7 @@ func TestReadBlockData(t *testing.T) {
)
var tests = map[string]struct {
funcs uint64
syscallImpl func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno)
syscallImpl func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err SyscallErrno)
wantErr string
}{
"read_block_data_ok": {
@ -317,7 +316,7 @@ func TestReadBlockData(t *testing.T) {
func TestWriteByte(t *testing.T) {
var tests = map[string]struct {
funcs uint64
syscallImpl func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno)
syscallImpl func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err SyscallErrno)
wantErr string
}{
"write_byte_ok": {
@ -359,7 +358,7 @@ func TestWriteByte(t *testing.T) {
func TestWriteByteData(t *testing.T) {
var tests = map[string]struct {
funcs uint64
syscallImpl func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno)
syscallImpl func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err SyscallErrno)
wantErr string
}{
"write_byte_data_ok": {
@ -406,7 +405,7 @@ func TestWriteByteData(t *testing.T) {
func TestWriteWordData(t *testing.T) {
var tests = map[string]struct {
funcs uint64
syscallImpl func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno)
syscallImpl func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err SyscallErrno)
wantErr string
}{
"write_word_data_ok": {
@ -471,7 +470,7 @@ func TestWriteBlockData(t *testing.T) {
)
var tests = map[string]struct {
funcs uint64
syscallImpl func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno)
syscallImpl func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err SyscallErrno)
wantErr string
}{
"write_block_data_ok": {
@ -533,7 +532,7 @@ func Test_queryFunctionality(t *testing.T) {
var tests = map[string]struct {
requested uint64
dev string
syscallImpl func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno)
syscallImpl func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err SyscallErrno)
wantErr string
wantFile bool
wantFuncs uint64

View File

@ -6,7 +6,6 @@ import (
"os"
"path"
"strconv"
"syscall"
"time"
)
@ -50,7 +49,7 @@ func (p *pwmPinSysFs) Export() error {
if err != nil {
// If EBUSY then the pin has already been exported
e, ok := err.(*os.PathError)
if !ok || e.Err != syscall.EBUSY {
if !ok || e.Err != Syscall_EBUSY {
return fmt.Errorf(pwmPinErrorPattern, "Export", p.pin, err)
}
}

View File

@ -2,7 +2,6 @@ package system
import (
"os"
"syscall"
"testing"
"gobot.io/x/gobot/v2"
@ -85,7 +84,7 @@ func TestPwmPinAlreadyExported(t *testing.T) {
pin, _ := initTestPWMPinSysFsWithMockedFilesystem(mockedPaths)
pin.write = func(filesystem, string, []byte) (int, error) {
return 0, &os.PathError{Err: syscall.EBUSY}
return 0, &os.PathError{Err: Syscall_EBUSY}
}
// no error indicates that the pin was already exported
@ -103,7 +102,7 @@ func TestPwmPinExportError(t *testing.T) {
pin, _ := initTestPWMPinSysFsWithMockedFilesystem(mockedPaths)
pin.write = func(filesystem, string, []byte) (int, error) {
return 0, &os.PathError{Err: syscall.EFAULT}
return 0, &os.PathError{Err: Syscall_EFAULT}
}
// no error indicates that the pin was already exported
@ -122,7 +121,7 @@ func TestPwmPinUnxportError(t *testing.T) {
pin, _ := initTestPWMPinSysFsWithMockedFilesystem(mockedPaths)
pin.write = func(filesystem, string, []byte) (int, error) {
return 0, &os.PathError{Err: syscall.EBUSY}
return 0, &os.PathError{Err: Syscall_EBUSY}
}
err := pin.Unexport()
@ -140,7 +139,7 @@ func TestPwmPinPeriodError(t *testing.T) {
pin, _ := initTestPWMPinSysFsWithMockedFilesystem(mockedPaths)
pin.read = func(filesystem, string) ([]byte, error) {
return nil, &os.PathError{Err: syscall.EBUSY}
return nil, &os.PathError{Err: Syscall_EBUSY}
}
_, err := pin.Period()
@ -158,7 +157,7 @@ func TestPwmPinPolarityError(t *testing.T) {
pin, _ := initTestPWMPinSysFsWithMockedFilesystem(mockedPaths)
pin.read = func(filesystem, string) ([]byte, error) {
return nil, &os.PathError{Err: syscall.EBUSY}
return nil, &os.PathError{Err: Syscall_EBUSY}
}
_, err := pin.Polarity()
@ -176,7 +175,7 @@ func TestPwmPinDutyCycleError(t *testing.T) {
pin, _ := initTestPWMPinSysFsWithMockedFilesystem(mockedPaths)
pin.read = func(filesystem, string) ([]byte, error) {
return nil, &os.PathError{Err: syscall.EBUSY}
return nil, &os.PathError{Err: Syscall_EBUSY}
}
_, err := pin.DutyCycle()

View File

@ -1,14 +1,32 @@
package system
import (
"syscall"
"unsafe"
"golang.org/x/sys/unix"
)
// SyscallErrno wraps the "unix.Errno"
type SyscallErrno unix.Errno
// wrapping for used constants of unix package
const (
Syscall_SYS_IOCTL = unix.SYS_IOCTL
Syscall_EINVAL = unix.EINVAL
Syscall_EBUSY = unix.EBUSY
Syscall_EFAULT = unix.EFAULT
)
// nativeSyscall represents the native Syscall
type nativeSyscall struct{}
// Syscall calls the native syscall.Syscall, implements the SystemCaller interface
func (sys *nativeSyscall) syscall(trap uintptr, f File, signal uintptr, payload unsafe.Pointer) (r1, r2 uintptr, err syscall.Errno) {
return syscall.Syscall(trap, f.Fd(), signal, uintptr(payload))
// Syscall calls the native unix.Syscall, implements the SystemCaller interface
func (sys *nativeSyscall) syscall(trap uintptr, f File, signal uintptr, payload unsafe.Pointer) (r1, r2 uintptr, err SyscallErrno) {
r1, r2, errNo := unix.Syscall(trap, f.Fd(), signal, uintptr(payload))
return r1, r2, SyscallErrno(errNo)
}
// Error implements the error interface. It wraps the "unix.Errno.Error()".
func (e SyscallErrno) Error() string {
return unix.Errno(e).Error()
}

View File

@ -1,7 +1,6 @@
package system
import (
"syscall"
"unsafe"
)
@ -14,11 +13,11 @@ type mockSyscall struct {
smbus *i2cSmbusIoctlData
sliceSize uint8
dataSlice []byte
Impl func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno)
Impl func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err SyscallErrno)
}
// Syscall calls the user defined implementation, used for tests, implements the SystemCaller interface
func (sys *mockSyscall) syscall(trap uintptr, f File, signal uintptr, payload unsafe.Pointer) (r1, r2 uintptr, err syscall.Errno) {
func (sys *mockSyscall) syscall(trap uintptr, f File, signal uintptr, payload unsafe.Pointer) (r1, r2 uintptr, err SyscallErrno) {
sys.lastTrap = trap // points to the used syscall (e.g. "SYS_IOCTL")
sys.lastFile = f // a character device file (e.g. file to path "/dev/i2c-1")
sys.lastSignal = signal // points to used function type (e.g. I2C_SMBUS, I2C_RDWR)

View File

@ -2,7 +2,6 @@ package system
import (
"os"
"syscall"
"unsafe"
"gobot.io/x/gobot/v2"
@ -33,7 +32,7 @@ type filesystem interface {
// systemCaller represents unexposed Syscall interface to allow the switch between native and mocked implementation
// Prevent unsafe call, since go 1.15, see "Pattern 4" in: https://go101.org/article/unsafe.html
type systemCaller interface {
syscall(trap uintptr, f File, signal uintptr, payload unsafe.Pointer) (r1, r2 uintptr, err syscall.Errno)
syscall(trap uintptr, f File, signal uintptr, payload unsafe.Pointer) (r1, r2 uintptr, err SyscallErrno)
}
// digitalPinAccesser represents unexposed interface to allow the switch between different implementations and