Apple2-IO-RPi/RaspberryPi/apple2driver/a2io/mockio.go
2024-01-02 19:54:35 -08:00

113 lines
3.3 KiB
Go

// Copyright Terence J. Boldt (c)2021-2024
// Use of this source code is governed by an MIT
// license that can be found in the LICENSE file.
// This file is used for mocking the GPIO code so that unit tests can be run
// on any machine and not just a Raspberry Pi
package a2io
import (
"errors"
"strings"
)
// MockIoData is used to verify tests were successful
type MockIoData struct {
BytesToRead []byte
BytesWritten []byte
NumberBytesRead int
NumberBytesWritten int
ErrorToThrow error
}
// MockIo implements A2Io to allow unit tests to run without needing GPIO functioning
type MockIo struct {
Data *MockIoData
}
// Init is only here to complete A2Io interface
func (mockIo MockIo) Init() {
}
// WriteByte mocks writing a byte to the Apple II
func (mockIo MockIo) WriteByte(data byte) error {
mockIo.Data.BytesWritten[mockIo.Data.NumberBytesWritten] = data
mockIo.Data.NumberBytesWritten++
return mockIo.Data.ErrorToThrow
}
// WriteString mocks writing a string to the Apple II
func (mockIo MockIo) WriteString(outString string) error {
for i, b := range outString {
mockIo.Data.BytesWritten[i+mockIo.Data.NumberBytesWritten] = byte(b)
}
mockIo.Data.NumberBytesWritten += len(outString)
return mockIo.Data.ErrorToThrow
}
// WriteBlock mocks writing a block to the Apple II
func (mockIo MockIo) WriteBlock(buffer []byte) error {
for i, b := range buffer {
mockIo.Data.BytesWritten[i+mockIo.Data.NumberBytesWritten] = b
}
mockIo.Data.NumberBytesWritten += len(buffer)
return mockIo.Data.ErrorToThrow
}
// WriteBuffer mocks writing a buffer to the Apple II
func (mockIo MockIo) WriteBuffer(buffer []byte) error {
for i, b := range buffer {
mockIo.Data.BytesWritten[i+mockIo.Data.NumberBytesWritten] = b
}
mockIo.Data.NumberBytesWritten += len(buffer)
return mockIo.Data.ErrorToThrow
}
// ReadByte mocks reading a byte from the Apple II
func (mockIo MockIo) ReadByte(noDelay ...bool) (byte, error) {
b := mockIo.Data.BytesToRead[mockIo.Data.NumberBytesRead]
mockIo.Data.NumberBytesRead++
return b, mockIo.Data.ErrorToThrow
}
// ReadString mocks reading a null terminated string from the Apple II
func (mockIo MockIo) ReadString() (string, error) {
builder := strings.Builder{}
for {
if mockIo.Data.NumberBytesRead > len(mockIo.Data.BytesToRead) {
return "", errors.New("read more data than available")
}
builder.WriteByte(mockIo.Data.BytesToRead[mockIo.Data.NumberBytesRead])
mockIo.Data.NumberBytesRead++
if mockIo.Data.BytesToRead[mockIo.Data.NumberBytesRead] == 0 {
mockIo.Data.NumberBytesRead++
break
}
}
return builder.String(), mockIo.Data.ErrorToThrow
}
// ReadBlock mocks reading a 512 byte block from the Apple II
func (mockIo MockIo) ReadBlock(buffer []byte) error {
if mockIo.Data.NumberBytesRead+512 > len(mockIo.Data.BytesToRead) {
return errors.New("read more data than available")
}
for i := 0; i < 512; i++ {
buffer[i] = mockIo.Data.BytesToRead[mockIo.Data.NumberBytesRead]
mockIo.Data.NumberBytesRead++
}
return mockIo.Data.ErrorToThrow
}
// SendCharacter is a pass-through to vt100 implementation
func (mockIo MockIo) SendCharacter(character byte) {
sendCharacter(mockIo, character)
}
// ReadCharacter is a pass-through to vt100 implementation
func (mockIo MockIo) ReadCharacter() (string, error) {
return readCharacter(mockIo)
}