240 lines
5.6 KiB
Go
240 lines
5.6 KiB
Go
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)
|
||
|
|
}
|