package gateway import ( "context" "encoding/json" "net/http" "net/http/httptest" "strings" "testing" ) func TestGetDeviceInfo_ByCardNo_Success(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { resp := GatewayResponse{ Code: 200, Msg: "成功", Data: json.RawMessage(`{"imei":"123456789012345","onlineStatus":1,"signalLevel":25,"wifiSsid":"TestWiFi","wifiEnabled":1,"uploadSpeed":100,"downloadSpeed":500}`), } w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(resp) })) defer server.Close() client := NewClient(server.URL, "testAppID", "testSecret") ctx := context.Background() result, err := client.GetDeviceInfo(ctx, &DeviceInfoReq{ CardNo: "898608070422D0010269", }) if err != nil { t.Fatalf("GetDeviceInfo() error = %v", err) } if result.IMEI != "123456789012345" { t.Errorf("IMEI = %s, want 123456789012345", result.IMEI) } if result.OnlineStatus != 1 { t.Errorf("OnlineStatus = %d, want 1", result.OnlineStatus) } if result.SignalLevel != 25 { t.Errorf("SignalLevel = %d, want 25", result.SignalLevel) } if result.WiFiSSID != "TestWiFi" { t.Errorf("WiFiSSID = %s, want TestWiFi", result.WiFiSSID) } } func TestGetDeviceInfo_ByDeviceID_Success(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { resp := GatewayResponse{ Code: 200, Msg: "成功", Data: json.RawMessage(`{"imei":"123456789012345","onlineStatus":0,"signalLevel":0}`), } json.NewEncoder(w).Encode(resp) })) defer server.Close() client := NewClient(server.URL, "testAppID", "testSecret") ctx := context.Background() result, err := client.GetDeviceInfo(ctx, &DeviceInfoReq{ DeviceID: "123456789012345", }) if err != nil { t.Fatalf("GetDeviceInfo() error = %v", err) } if result.IMEI != "123456789012345" { t.Errorf("IMEI = %s, want 123456789012345", result.IMEI) } if result.OnlineStatus != 0 { t.Errorf("OnlineStatus = %d, want 0", result.OnlineStatus) } } func TestGetDeviceInfo_MissingParams(t *testing.T) { client := NewClient("https://test.example.com", "testAppID", "testSecret") ctx := context.Background() _, err := client.GetDeviceInfo(ctx, &DeviceInfoReq{}) if err == nil { t.Fatal("GetDeviceInfo() expected validation error") } if !strings.Contains(err.Error(), "至少需要一个") { t.Errorf("error should contain '至少需要一个', got: %v", err) } } func TestGetDeviceInfo_InvalidResponse(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { resp := GatewayResponse{ Code: 200, Msg: "成功", Data: json.RawMessage(`invalid json`), } json.NewEncoder(w).Encode(resp) })) defer server.Close() client := NewClient(server.URL, "testAppID", "testSecret") ctx := context.Background() _, err := client.GetDeviceInfo(ctx, &DeviceInfoReq{CardNo: "test"}) if err == nil { t.Fatal("GetDeviceInfo() expected JSON parse error") } if !strings.Contains(err.Error(), "解析") { t.Errorf("error should contain '解析', got: %v", err) } } func TestGetSlotInfo_Success(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { resp := GatewayResponse{ Code: 200, Msg: "成功", Data: json.RawMessage(`{"imei":"123456789012345","slots":[{"slotNo":1,"iccid":"898608070422D0010269","cardStatus":"正常","isActive":1},{"slotNo":2,"iccid":"898608070422D0010270","cardStatus":"停机","isActive":0}]}`), } json.NewEncoder(w).Encode(resp) })) defer server.Close() client := NewClient(server.URL, "testAppID", "testSecret") ctx := context.Background() result, err := client.GetSlotInfo(ctx, &DeviceInfoReq{ DeviceID: "123456789012345", }) if err != nil { t.Fatalf("GetSlotInfo() error = %v", err) } if result.IMEI != "123456789012345" { t.Errorf("IMEI = %s, want 123456789012345", result.IMEI) } if len(result.Slots) != 2 { t.Errorf("len(Slots) = %d, want 2", len(result.Slots)) } if result.Slots[0].SlotNo != 1 { t.Errorf("Slots[0].SlotNo = %d, want 1", result.Slots[0].SlotNo) } if result.Slots[0].ICCID != "898608070422D0010269" { t.Errorf("Slots[0].ICCID = %s, want 898608070422D0010269", result.Slots[0].ICCID) } if result.Slots[0].IsActive != 1 { t.Errorf("Slots[0].IsActive = %d, want 1", result.Slots[0].IsActive) } } func TestGetSlotInfo_MissingParams(t *testing.T) { client := NewClient("https://test.example.com", "testAppID", "testSecret") ctx := context.Background() _, err := client.GetSlotInfo(ctx, &DeviceInfoReq{}) if err == nil { t.Fatal("GetSlotInfo() expected validation error") } if !strings.Contains(err.Error(), "至少需要一个") { t.Errorf("error should contain '至少需要一个', got: %v", err) } } func TestSetSpeedLimit_Success(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { resp := GatewayResponse{Code: 200, Msg: "成功"} json.NewEncoder(w).Encode(resp) })) defer server.Close() client := NewClient(server.URL, "testAppID", "testSecret") ctx := context.Background() err := client.SetSpeedLimit(ctx, &SpeedLimitReq{ DeviceID: "123456789012345", UploadSpeed: 100, DownloadSpeed: 500, }) if err != nil { t.Fatalf("SetSpeedLimit() error = %v", err) } } func TestSetSpeedLimit_WithExtend(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { resp := GatewayResponse{Code: 200, Msg: "成功"} json.NewEncoder(w).Encode(resp) })) defer server.Close() client := NewClient(server.URL, "testAppID", "testSecret") ctx := context.Background() err := client.SetSpeedLimit(ctx, &SpeedLimitReq{ DeviceID: "123456789012345", UploadSpeed: 100, DownloadSpeed: 500, Extend: "test-extend", }) if err != nil { t.Fatalf("SetSpeedLimit() error = %v", err) } } func TestSetSpeedLimit_BusinessError(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { resp := GatewayResponse{Code: 500, Msg: "设置失败"} json.NewEncoder(w).Encode(resp) })) defer server.Close() client := NewClient(server.URL, "testAppID", "testSecret") ctx := context.Background() err := client.SetSpeedLimit(ctx, &SpeedLimitReq{ DeviceID: "123456789012345", UploadSpeed: 100, DownloadSpeed: 500, }) if err == nil { t.Fatal("SetSpeedLimit() expected business error") } if !strings.Contains(err.Error(), "业务错误") { t.Errorf("error should contain '业务错误', got: %v", err) } } func TestSetWiFi_Success(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { resp := GatewayResponse{Code: 200, Msg: "成功"} json.NewEncoder(w).Encode(resp) })) defer server.Close() client := NewClient(server.URL, "testAppID", "testSecret") ctx := context.Background() err := client.SetWiFi(ctx, &WiFiReq{ DeviceID: "123456789012345", SSID: "TestWiFi", Password: "password123", Enabled: 1, }) if err != nil { t.Fatalf("SetWiFi() error = %v", err) } } func TestSetWiFi_WithExtend(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { resp := GatewayResponse{Code: 200, Msg: "成功"} json.NewEncoder(w).Encode(resp) })) defer server.Close() client := NewClient(server.URL, "testAppID", "testSecret") ctx := context.Background() err := client.SetWiFi(ctx, &WiFiReq{ DeviceID: "123456789012345", SSID: "TestWiFi", Password: "password123", Enabled: 0, Extend: "test-extend", }) if err != nil { t.Fatalf("SetWiFi() error = %v", err) } } func TestSwitchCard_Success(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { resp := GatewayResponse{Code: 200, Msg: "成功"} json.NewEncoder(w).Encode(resp) })) defer server.Close() client := NewClient(server.URL, "testAppID", "testSecret") ctx := context.Background() err := client.SwitchCard(ctx, &SwitchCardReq{ DeviceID: "123456789012345", TargetICCID: "898608070422D0010270", }) if err != nil { t.Fatalf("SwitchCard() error = %v", err) } } func TestSwitchCard_BusinessError(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { resp := GatewayResponse{Code: 404, Msg: "目标卡不存在"} json.NewEncoder(w).Encode(resp) })) defer server.Close() client := NewClient(server.URL, "testAppID", "testSecret") ctx := context.Background() err := client.SwitchCard(ctx, &SwitchCardReq{ DeviceID: "123456789012345", TargetICCID: "invalid", }) if err == nil { t.Fatal("SwitchCard() expected business error") } } func TestResetDevice_Success(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { resp := GatewayResponse{Code: 200, Msg: "成功"} json.NewEncoder(w).Encode(resp) })) defer server.Close() client := NewClient(server.URL, "testAppID", "testSecret") ctx := context.Background() err := client.ResetDevice(ctx, &DeviceOperationReq{ DeviceID: "123456789012345", }) if err != nil { t.Fatalf("ResetDevice() error = %v", err) } } func TestResetDevice_WithExtend(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { resp := GatewayResponse{Code: 200, Msg: "成功"} json.NewEncoder(w).Encode(resp) })) defer server.Close() client := NewClient(server.URL, "testAppID", "testSecret") ctx := context.Background() err := client.ResetDevice(ctx, &DeviceOperationReq{ DeviceID: "123456789012345", Extend: "test-extend", }) if err != nil { t.Fatalf("ResetDevice() error = %v", err) } } func TestRebootDevice_Success(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { resp := GatewayResponse{Code: 200, Msg: "成功"} json.NewEncoder(w).Encode(resp) })) defer server.Close() client := NewClient(server.URL, "testAppID", "testSecret") ctx := context.Background() err := client.RebootDevice(ctx, &DeviceOperationReq{ DeviceID: "123456789012345", }) if err != nil { t.Fatalf("RebootDevice() error = %v", err) } } func TestRebootDevice_BusinessError(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { resp := GatewayResponse{Code: 500, Msg: "设备离线"} json.NewEncoder(w).Encode(resp) })) defer server.Close() client := NewClient(server.URL, "testAppID", "testSecret") ctx := context.Background() err := client.RebootDevice(ctx, &DeviceOperationReq{ DeviceID: "123456789012345", }) if err == nil { t.Fatal("RebootDevice() expected business error") } if !strings.Contains(err.Error(), "业务错误") { t.Errorf("error should contain '业务错误', got: %v", err) } }