New test packages: - config/loader_test.go: 5 tests (valid, minimal, missing file, pulsar-only, defaults) - serial/serial_test.go: 6 tests (interface, read, EOF, close, empty) - app/app_test.go: 5 tests (New, dispatch store/send, error handling, ctx cancellation) Enhanced test packages: - storage/store_test.go: +3 tests (concurrent insert, close/reopen, init clears) - telegram/parser_test.go: +5 tests (concurrency, rawLog, empty, multiline, removeEmpty) - transport/transport_test.go: +7 tests, +fixes Fixes: - app.go: store field type *storage.Store -> storage.Repository (supports mocking) - transport_test: fix net.Pipe() sync deadlock in SetConnClosesPrevious - transport_test: fix MultiSender_ErrorPropagation expectations Results: 6 packages, 30+ tests, all pass with -race
100 lines
2.0 KiB
Go
100 lines
2.0 KiB
Go
package serial
|
|
|
|
import (
|
|
"errors"
|
|
"testing"
|
|
)
|
|
|
|
// mockSerialPort implements a fake serial port for testing.
|
|
type mockSerialPort struct {
|
|
lines []string
|
|
index int
|
|
closed bool
|
|
}
|
|
|
|
func (m *mockSerialPort) ReadLine() (string, error) {
|
|
if m.closed {
|
|
return "", errors.New("port closed")
|
|
}
|
|
if m.index >= len(m.lines) {
|
|
return "", errors.New("EOF")
|
|
}
|
|
line := m.lines[m.index]
|
|
m.index++
|
|
return line, nil
|
|
}
|
|
|
|
func (m *mockSerialPort) Close() error {
|
|
m.closed = true
|
|
return nil
|
|
}
|
|
|
|
func (m *mockSerialPort) IsOpen() bool {
|
|
return !m.closed
|
|
}
|
|
|
|
func TestMockReader_ImplementsInterface(t *testing.T) {
|
|
var r Reader = &mockSerialPort{lines: []string{"hello"}}
|
|
_ = r
|
|
}
|
|
|
|
func TestMockReader_ReadLine(t *testing.T) {
|
|
m := &mockSerialPort{lines: []string{"line1", "line2", "line3"}}
|
|
|
|
line, err := m.ReadLine()
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if line != "line1" {
|
|
t.Errorf("expected line1, got %s", line)
|
|
}
|
|
|
|
line, _ = m.ReadLine()
|
|
if line != "line2" {
|
|
t.Errorf("expected line2, got %s", line)
|
|
}
|
|
|
|
line, _ = m.ReadLine()
|
|
if line != "line3" {
|
|
t.Errorf("expected line3, got %s", line)
|
|
}
|
|
}
|
|
|
|
func TestMockReader_EOF(t *testing.T) {
|
|
m := &mockSerialPort{lines: []string{"only"}}
|
|
m.ReadLine() // consume the only line
|
|
_, err := m.ReadLine()
|
|
if err == nil {
|
|
t.Error("expected EOF error")
|
|
}
|
|
}
|
|
|
|
func TestMockReader_Close(t *testing.T) {
|
|
m := &mockSerialPort{lines: []string{"hello"}}
|
|
if !m.IsOpen() {
|
|
t.Error("expected open before Close")
|
|
}
|
|
if err := m.Close(); err != nil {
|
|
t.Fatalf("Close() failed: %v", err)
|
|
}
|
|
if m.IsOpen() {
|
|
t.Error("expected closed after Close")
|
|
}
|
|
_, err := m.ReadLine()
|
|
if err == nil {
|
|
t.Error("expected error reading from closed port")
|
|
}
|
|
}
|
|
|
|
func TestMockReader_Empty(t *testing.T) {
|
|
m := &mockSerialPort{}
|
|
_, err := m.ReadLine()
|
|
if err == nil {
|
|
t.Error("expected EOF on empty port")
|
|
}
|
|
}
|
|
|
|
func TestReaderInterface_Satisfied(t *testing.T) {
|
|
// Compile-time check: *mockSerialPort implements Reader
|
|
var _ Reader = (*mockSerialPort)(nil)
|
|
} |