1
0
mirror of https://github.com/hybridgroup/gobot.git synced 2025-04-27 13:48:56 +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: # currently active linters:
# #
#INFO [lintersdb] Active 35 linters: [asasalint asciicheck bidichk contextcheck decorder depguard durationcheck errcheck exportloopref #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] # nilerr nilnil nolintlint nosprintfhostport prealloc reassign revive staticcheck tagalign tenv testableexamples tparallel typecheck unused wastedassign]
enable-all: true enable-all: true
@ -62,6 +62,7 @@ linters:
- goerr113 # not used (we allow error creation at return statement) - goerr113 # not used (we allow error creation at return statement)
- gofumpt # not used (we use "go fmt" or "gofmt" not gofumpt" - gofumpt # not used (we use "go fmt" or "gofmt" not gofumpt"
- gosmopolitan # not needed (report i18n/l10n anti-patterns) - 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) - ireturn # not used (we allow return interfaces)
- loggercheck # not needed (relates to kitlog, klog, logr, zap) - loggercheck # not needed (relates to kitlog, klog, logr, zap)
- paralleltest # not used - 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 # Run tests on nearly all directories without test cache
test: test:
go test -count=1 -v $(including_except) go test -failfast -count=1 -v $(including_except)
# Run tests with race detection # Run tests with race detection
test_race: test_race:

View File

@ -7,7 +7,6 @@ import (
"errors" "errors"
"testing" "testing"
"syscall"
"unsafe" "unsafe"
"gobot.io/x/gobot/v2" "gobot.io/x/gobot/v2"
@ -17,13 +16,13 @@ import (
const dev = "/dev/i2c-1" 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 0: error on function query
// bit 1: error on set address // bit 1: error on set address
// bit 2: error on command // 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 // 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 { if errorMask&0x01 == 0x01 {
return 0, 0, 1 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 system.I2C_FUNC_SMBUS_WRITE_WORD_DATA
} }
// set address // 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 { if errorMask&0x02 == 0x02 {
return 0, 0, 1 return 0, 0, 1
} }
} }
// command // command
if (trap == syscall.SYS_IOCTL) && (a2 == system.I2C_SMBUS) { if (trap == system.Syscall_SYS_IOCTL) && (a2 == system.I2C_SMBUS) {
if errorMask&0x04 == 0x04 { if errorMask&0x04 == 0x04 {
return 0, 0, 1 return 0, 0, 1
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,14 +1,32 @@
package system package system
import ( import (
"syscall"
"unsafe" "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 // nativeSyscall represents the native Syscall
type nativeSyscall struct{} type nativeSyscall struct{}
// Syscall calls the native syscall.Syscall, implements the SystemCaller interface // 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 syscall.Errno) { func (sys *nativeSyscall) syscall(trap uintptr, f File, signal uintptr, payload unsafe.Pointer) (r1, r2 uintptr, err SyscallErrno) {
return syscall.Syscall(trap, f.Fd(), signal, uintptr(payload)) 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 package system
import ( import (
"syscall"
"unsafe" "unsafe"
) )
@ -14,11 +13,11 @@ type mockSyscall struct {
smbus *i2cSmbusIoctlData smbus *i2cSmbusIoctlData
sliceSize uint8 sliceSize uint8
dataSlice []byte 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 // 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.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.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) sys.lastSignal = signal // points to used function type (e.g. I2C_SMBUS, I2C_RDWR)

View File

@ -2,7 +2,6 @@ package system
import ( import (
"os" "os"
"syscall"
"unsafe" "unsafe"
"gobot.io/x/gobot/v2" "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 // 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 // Prevent unsafe call, since go 1.15, see "Pattern 4" in: https://go101.org/article/unsafe.html
type systemCaller interface { 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 // digitalPinAccesser represents unexposed interface to allow the switch between different implementations and