mirror of https://github.com/periph/devices
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
192 lines
4.3 KiB
Go
192 lines
4.3 KiB
Go
// Copyright 2024 The Periph Authors. All rights reserved.
|
|
// Use of this source code is governed under the Apache License, Version 2.0
|
|
// that can be found in the LICENSE file.
|
|
|
|
package matrixorbital
|
|
|
|
import (
|
|
"fmt"
|
|
"hash"
|
|
"hash/crc32"
|
|
"io"
|
|
"math/rand"
|
|
"sync/atomic"
|
|
"testing"
|
|
"time"
|
|
|
|
"periph.io/x/conn/v3/display"
|
|
"periph.io/x/conn/v3/display/displaytest"
|
|
)
|
|
|
|
type mockReadWriterCloser struct {
|
|
closed bool
|
|
bytesWritten int
|
|
bytesRead int
|
|
readChars string
|
|
hash hash.Hash32
|
|
// TODO: Add CRC32 verification of written bytes...
|
|
}
|
|
|
|
func (mr *mockReadWriterCloser) Read(p []byte) (n int, err error) {
|
|
if mr.closed {
|
|
err = io.EOF
|
|
}
|
|
cPos := rand.Intn(len(mr.readChars))
|
|
p[0] = byte(mr.readChars[cPos])
|
|
n = 1
|
|
mr.bytesRead += 1
|
|
return
|
|
}
|
|
|
|
func (mr *mockReadWriterCloser) Write(p []byte) (n int, err error) {
|
|
if mr.closed {
|
|
err = io.EOF
|
|
return
|
|
}
|
|
n = len(p)
|
|
mr.hash.Write(p)
|
|
mr.bytesWritten += n
|
|
return
|
|
}
|
|
|
|
func (mr *mockReadWriterCloser) Close() error {
|
|
mr.closed = true
|
|
return nil
|
|
}
|
|
|
|
// Shutdown accepts an expected hash. If expectedHash doesn't match the hash of
|
|
// the stream written to the mock, it writes an error to t. If the test changes,
|
|
// or the implementation of the device changes, you'll have to update the
|
|
// expectedHash value in the Shutdown() call.
|
|
func (mr *mockReadWriterCloser) Shutdown(t *testing.T, expectedHash uint32) {
|
|
finalHash := mr.hash.Sum32()
|
|
if expectedHash == 0 {
|
|
t.Logf("Mock Reader: Final Hash=0x%x", finalHash)
|
|
} else if finalHash != expectedHash {
|
|
t.Errorf("Incorrect hash. Expected: 0x%x, received 0x%x", expectedHash, finalHash)
|
|
}
|
|
}
|
|
|
|
// getDisplay returns an LCD display constructed with a mock read/writer for
|
|
// testing.
|
|
func getDisplay() (*LK2047T, *mockReadWriterCloser) {
|
|
|
|
wr := &mockReadWriterCloser{readChars: "ABCDEGH", hash: crc32.NewIEEE()}
|
|
|
|
return NewWriterLK2047T(wr, 4, 20), wr
|
|
}
|
|
|
|
func TestTextDisplay(t *testing.T) {
|
|
fmt.Println("beginning tests")
|
|
dev, mock := getDisplay()
|
|
defer mock.Shutdown(t, 0x4b8e39ef)
|
|
wrTest := "abcdef"
|
|
nWritten, err := dev.WriteString(wrTest)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
if nWritten != len(wrTest) || mock.bytesWritten != len(wrTest) {
|
|
t.Errorf("write string error wrote %d bytes expected %d", mock.bytesWritten, len(wrTest))
|
|
}
|
|
}
|
|
|
|
func TestInterface(t *testing.T) {
|
|
dev, mock := getDisplay()
|
|
defer mock.Shutdown(t, 0x1d42cd75)
|
|
errors := displaytest.TestTextDisplay(dev, false)
|
|
for _, err := range errors {
|
|
if err != display.ErrNotImplemented {
|
|
t.Error(err)
|
|
}
|
|
}
|
|
if mock.bytesWritten == 27 {
|
|
t.Error("27")
|
|
}
|
|
}
|
|
|
|
func TestLEDs(t *testing.T) {
|
|
dev, mock := getDisplay()
|
|
defer mock.Shutdown(t, 0x3d9030ea)
|
|
for ix := range 3 {
|
|
for color := Off; color <= Yellow; color++ {
|
|
err := dev.LED(ix, color)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Peform a basic test on optional interface methods.
|
|
func TestContrastBacklight(t *testing.T) {
|
|
dev, mock := getDisplay()
|
|
defer mock.Shutdown(t, 0x93097842)
|
|
if err := dev.Contrast(0); err != nil {
|
|
t.Error(err)
|
|
}
|
|
if err := dev.Contrast(100); err != nil {
|
|
t.Error(err)
|
|
}
|
|
if err := dev.Backlight(0); err != nil {
|
|
t.Error(err)
|
|
}
|
|
if err := dev.Backlight(50); err != nil {
|
|
t.Error(err)
|
|
}
|
|
if err := dev.KeypadBacklight(true); err != nil {
|
|
t.Error(err)
|
|
}
|
|
if err := dev.KeypadBacklight(false); err != nil {
|
|
t.Error(err)
|
|
}
|
|
}
|
|
|
|
func TestPins(t *testing.T) {
|
|
dev, _ := getDisplay()
|
|
for ix, pin := range dev.Pins {
|
|
if len(pin.String()) == 0 {
|
|
t.Errorf("pin %d return empty string", ix)
|
|
}
|
|
if pin.Number() != ix+1 {
|
|
t.Errorf("Pin %d, unexpected pin # %d", ix, pin.Number())
|
|
}
|
|
if len(pin.Name()) == 0 {
|
|
t.Errorf("pin %d returned empty name!", ix)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestKeypad(t *testing.T) {
|
|
dev, _ := getDisplay()
|
|
ch, err := dev.ReadKeypad()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if ch == nil {
|
|
t.Fatal("ReadKeypad() returned nil channel!")
|
|
}
|
|
received := atomic.Int32{}
|
|
expected := int32(10)
|
|
go func() {
|
|
for {
|
|
if received.Load() >= expected {
|
|
|
|
if err := dev.Halt(); err != nil {
|
|
t.Error(err)
|
|
}
|
|
return
|
|
}
|
|
time.Sleep(time.Millisecond)
|
|
}
|
|
}()
|
|
for c := range ch {
|
|
t.Logf("received %s", string(c))
|
|
received.Add(1)
|
|
time.Sleep(5 * time.Millisecond)
|
|
}
|
|
}
|
|
|
|
var _ io.Reader = &mockReadWriterCloser{}
|
|
var _ io.Writer = &mockReadWriterCloser{}
|
|
var _ io.Closer = &mockReadWriterCloser{}
|