package camera import ( "context" "errors" "net" "testing" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" ) // MockConn 模拟 net.Conn type MockConn struct { mock.Mock } func (m *MockConn) Read(b []byte) (n int, err error) { args := m.Called(b) return args.Int(0), args.Error(1) } func (m *MockConn) Write(b []byte) (n int, err error) { args := m.Called(b) return args.Int(0), args.Error(1) } func (m *MockConn) Close() error { args := m.Called() return args.Error(0) } func (m *MockConn) LocalAddr() net.Addr { return nil } func (m *MockConn) RemoteAddr() net.Addr { return nil } func (m *MockConn) SetDeadline(t time.Time) error { return nil } func (m *MockConn) SetReadDeadline(t time.Time) error { return nil } func (m *MockConn) SetWriteDeadline(t time.Time) error { return nil } // MockDialer 模拟 DialTimeout type MockDialer func(network, address string, timeout time.Duration) (net.Conn, error) var mockDial MockDialer func init() { mockDial = func(network, address string, timeout time.Duration) (net.Conn, error) { return nil, nil } } var dialTimeout = net.DialTimeout func mockDialFunc(f MockDialer) { old := dialTimeout dialTimeout = f defer func() { dialTimeout = old }() } func TestConnect_SendCommands_ReadResponses(t *testing.T) { // 创建客户端 client := NewClient("192.168.88.52:8600") // 1. 测试连接 err := client.Connect() assert.NoError(t, err) assert.NotNil(t, client.conn) //// 2. 发送 T1 命令 resp1, err := client.SendCommand("T1") assert.NoError(t, err) assert.Contains(t, string(resp1), "T1") time.Sleep(100 * time.Millisecond) // 3. 发送 GM,2,0 命令,验证是否收到 GM,0,... 格式回复 resp2, err := client.SendCommand("GM,2,0") assert.NoError(t, err) assert.Regexp(t, `^GM,0,.*`, string(resp2)) t.Logf("收到指令 GM,2,0 的回复: %s", resp2) client.Close() } func TestNewClient(t *testing.T) { client := NewClient("127.0.0.1:8080") assert.Equal(t, "127.0.0.1:8080", client.addr) assert.Equal(t, 5*time.Second, client.timeout) client2 := NewClient("127.0.0.1:8080", 10*time.Second) assert.Equal(t, 10*time.Second, client2.timeout) } func TestConnect_Success(t *testing.T) { mockDialFunc(func(network, address string, timeout time.Duration) (net.Conn, error) { return &MockConn{}, nil }) client := NewClient("127.0.0.1:8080") err := client.Connect() assert.NoError(t, err) assert.NotNil(t, client.conn) } func TestConnect_Failure(t *testing.T) { mockDialFunc(func(network, address string, timeout time.Duration) (net.Conn, error) { return nil, errors.New("connection refused") }) client := NewClient("127.0.0.1:8080") err := client.Connect() assert.Error(t, err) assert.Nil(t, client.conn) } func TestConnectWithRetry_SuccessOnSecondTry(t *testing.T) { attempts := 0 mockDialFunc(func(network, address string, timeout time.Duration) (net.Conn, error) { attempts++ if attempts == 1 { return nil, errors.New("first fail") } return &MockConn{}, nil }) client := NewClient("127.0.0.1:8080") err := client.ConnectWithRetry(2, 100*time.Millisecond) assert.NoError(t, err) assert.Equal(t, 2, attempts) } func TestIsConnected(t *testing.T) { client := NewClient("127.0.0.1:8080") assert.False(t, client.IsConnected()) client.conn = &MockConn{} assert.True(t, client.IsConnected()) } func TestReconnect(t *testing.T) { mockConn := new(MockConn) mockConn.On("Close").Return(nil) mockDialFunc(func(network, address string, timeout time.Duration) (net.Conn, error) { return mockConn, nil }) client := NewClient("127.0.0.1:8080") client.conn = mockConn err := client.Reconnect() assert.NoError(t, err) mockConn.AssertExpectations(t) } func TestSendCommand_NotConnected(t *testing.T) { client := NewClient("127.0.0.1:8080") _, err := client.SendCommand("CMD") assert.Error(t, err) assert.Equal(t, "未建立连接", err.Error()) } func TestSendCommand_WriteError(t *testing.T) { mockConn := new(MockConn) mockConn.On("Write", mock.Anything).Return(0, errors.New("write error")) client := NewClient("127.0.0.1:8080") client.conn = mockConn _, err := client.SendCommand("CMD") assert.Error(t, err) assert.Contains(t, err.Error(), "发送指令失败") } func TestReadResponse_Success(t *testing.T) { conn := new(MockConn) conn.On("SetReadDeadline", mock.Anything).Return(nil) conn.On("Read", mock.Anything).Return(0, nil) client := NewClient("127.0.0.1:8080") client.conn = conn resp, err := client.readResponse() assert.NoError(t, err) assert.Equal(t, []byte("RESPONSE\r\n"), resp) } func TestSendCommandWithContext_Cancel(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) cancel() client := NewClient("127.0.0.1:8080") resp, err := client.SendCommandWithContext(ctx, "CMD") assert.Error(t, err) assert.Equal(t, context.Canceled, err) assert.Nil(t, resp) } func TestTakePhoto(t *testing.T) { mockConn := new(MockConn) mockConn.On("Write", mock.Anything).Return(0, nil) client := NewClient("127.0.0.1:8080") client.conn = mockConn err := client.TakePhoto() assert.NoError(t, err) } func TestGetDetectionResult(t *testing.T) { mockConn := new(MockConn) mockConn.On("Write", mock.Anything).Return(0, nil) mockConn.On("Read", mock.Anything).Return(0, nil) client := NewClient("127.0.0.1:8080") client.conn = mockConn resp, err := client.GetDetectionResult() assert.NoError(t, err) assert.Empty(t, resp) } func TestClose(t *testing.T) { mockConn := new(MockConn) mockConn.On("Close").Return(nil) client := NewClient("127.0.0.1:8080") client.conn = mockConn client.Close() assert.Nil(t, client.conn) mockConn.AssertExpectations(t) }