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) }