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.
devices/matrixorbital/lk2047t_test.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{}