mirror of
https://github.com/sipeed/picoclaw.git
synced 2026-06-12 18:08:54 +00:00
141 lines
3.4 KiB
Go
141 lines
3.4 KiB
Go
//go:build linux || darwin
|
|
|
|
package hardwaretools
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func stubUnixSerialIO(t *testing.T, now *time.Time) {
|
|
t.Helper()
|
|
|
|
prevNow := unixSerialNow
|
|
prevOpen := unixSerialOpenPort
|
|
prevClose := unixSerialClosePort
|
|
prevPollRead := unixSerialPollRead
|
|
prevPollWrite := unixSerialPollWrite
|
|
|
|
unixSerialNow = func() time.Time {
|
|
return *now
|
|
}
|
|
unixSerialOpenPort = func(cfg serialConfig) (int, error) {
|
|
return 42, nil
|
|
}
|
|
unixSerialClosePort = func(fd int) error {
|
|
return nil
|
|
}
|
|
unixSerialPollRead = prevPollRead
|
|
unixSerialPollWrite = prevPollWrite
|
|
|
|
t.Cleanup(func() {
|
|
unixSerialNow = prevNow
|
|
unixSerialOpenPort = prevOpen
|
|
unixSerialClosePort = prevClose
|
|
unixSerialPollRead = prevPollRead
|
|
unixSerialPollWrite = prevPollWrite
|
|
})
|
|
}
|
|
|
|
func TestSerialReadWaitsPastEmptyPollsUntilDeadline(t *testing.T) {
|
|
now := time.Unix(0, 0)
|
|
stubUnixSerialIO(t, &now)
|
|
|
|
pollCalls := 0
|
|
unixSerialPollRead = func(fd int, dst []byte, timeout time.Duration) (int, error) {
|
|
pollCalls++
|
|
if timeout > serialPollInterval {
|
|
t.Fatalf("poll timeout = %v, want <= %v", timeout, serialPollInterval)
|
|
}
|
|
now = now.Add(timeout)
|
|
if pollCalls < 4 {
|
|
return 0, nil
|
|
}
|
|
return copy(dst, []byte("OK")), nil
|
|
}
|
|
|
|
got, err := serialRead(context.Background(), serialConfig{}, 2, 500*time.Millisecond)
|
|
if err != nil {
|
|
t.Fatalf("serialRead() error = %v", err)
|
|
}
|
|
if string(got) != "OK" {
|
|
t.Fatalf("serialRead() = %q, want %q", got, "OK")
|
|
}
|
|
if pollCalls != 4 {
|
|
t.Fatalf("poll calls = %d, want 4", pollCalls)
|
|
}
|
|
}
|
|
|
|
func TestSerialReadReturnsPromptlyOnContextCancelBetweenPolls(t *testing.T) {
|
|
now := time.Unix(0, 0)
|
|
stubUnixSerialIO(t, &now)
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
pollCalls := 0
|
|
unixSerialPollRead = func(fd int, dst []byte, timeout time.Duration) (int, error) {
|
|
pollCalls++
|
|
now = now.Add(timeout)
|
|
cancel()
|
|
return 0, nil
|
|
}
|
|
|
|
_, err := serialRead(ctx, serialConfig{}, 1, time.Second)
|
|
if !errors.Is(err, context.Canceled) {
|
|
t.Fatalf("serialRead() error = %v, want context canceled", err)
|
|
}
|
|
if pollCalls != 1 {
|
|
t.Fatalf("poll calls = %d, want 1", pollCalls)
|
|
}
|
|
}
|
|
|
|
func TestSerialWriteWaitsPastEmptyPollsUntilReady(t *testing.T) {
|
|
now := time.Unix(0, 0)
|
|
stubUnixSerialIO(t, &now)
|
|
|
|
pollCalls := 0
|
|
unixSerialPollWrite = func(fd int, src []byte, timeout time.Duration) (int, error) {
|
|
pollCalls++
|
|
if timeout > serialPollInterval {
|
|
t.Fatalf("poll timeout = %v, want <= %v", timeout, serialPollInterval)
|
|
}
|
|
now = now.Add(timeout)
|
|
switch pollCalls {
|
|
case 1, 2:
|
|
return 0, nil
|
|
default:
|
|
return 1, nil
|
|
}
|
|
}
|
|
|
|
written, err := serialWrite(context.Background(), serialConfig{}, []byte("OK"), 500*time.Millisecond)
|
|
if err != nil {
|
|
t.Fatalf("serialWrite() error = %v", err)
|
|
}
|
|
if written != 2 {
|
|
t.Fatalf("serialWrite() wrote %d bytes, want 2", written)
|
|
}
|
|
if pollCalls != 4 {
|
|
t.Fatalf("poll calls = %d, want 4", pollCalls)
|
|
}
|
|
}
|
|
|
|
func TestSerialWriteTimesOutAfterRepeatedEmptyPolls(t *testing.T) {
|
|
now := time.Unix(0, 0)
|
|
stubUnixSerialIO(t, &now)
|
|
|
|
unixSerialPollWrite = func(fd int, src []byte, timeout time.Duration) (int, error) {
|
|
now = now.Add(timeout)
|
|
return 0, nil
|
|
}
|
|
|
|
written, err := serialWrite(context.Background(), serialConfig{}, []byte("A"), 250*time.Millisecond)
|
|
if err == nil || err.Error() != "timeout while writing serial data" {
|
|
t.Fatalf("serialWrite() error = %v, want timeout", err)
|
|
}
|
|
if written != 0 {
|
|
t.Fatalf("serialWrite() wrote %d bytes, want 0", written)
|
|
}
|
|
}
|