Files
iotlcm/app/server/internal/logic/app/app_diagnosis_contract_test.go
T

104 lines
4.7 KiB
Go

package app
import (
"context"
"encoding/json"
"fmt"
"net/http"
"net/http/httptest"
"strings"
"sync"
"testing"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gcfg"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/model"
"git.5iot.com/iotlcm-public/iotlcm-app/internal/model/entity"
)
func TestAppDiagnosisUpstreamContract(t *testing.T) {
scenarios := []string{"success", "session failure with IMEI", "IMEI failure with session"}
for _, scenario := range scenarios {
t.Run(scenario, func(t *testing.T) {
var mu sync.Mutex
seen := map[string]int{}
responses := map[string]string{
"sim-basic-info": `{"simStatus":"1","iccid":"card","imsi":"imsi","msisdn":"msisdn"}`,
"sim-status": `{"cardStatus":4}`,
"sim-session": `{"status":"0","apnId":"CMIOT","ipv4":"192.0.2.10"}`,
"sim-imei": `{"imei":"latest"}`,
"sim-device-status": `{"deviceStatus":"1","operatingStatus":"1"}`,
"sim-card-bind-status": `{"bindStatus":"1","orderStatus":"0"}`,
"sim-region-limit-status": `{"regionLimitStatus":"0","orderStatus":"1"}`,
"sim-data-diagnosis": `{"status":"0","message":"正确","result":[{"APNList":{"APNInfo":[{"APNName":"CMIOT","modifyTime":"20250526140211","APNStatus":"2","APNServiceUsageState":"1"}]}}]}`,
"sim-stop-reason": `{"stopReason":"000000000000"}`,
"sim-frozen-state": `{"frozenStatus":"0"}`,
"sim-datausage": `{"dataUsage":0}`,
"sim-apn-info": `{"apnList":[{"apnName":"CMIOT","status":"0"}]}`,
}
proxy := httptest.NewServer(http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
const prefix = "/internal/app-diagnosis/sim/query/"
if !strings.HasPrefix(request.URL.Path, prefix) || request.Header.Get("X-App-Diagnosis-Token") != "test-token" {
t.Errorf("proxy contract mismatch: %s", request.URL.Path)
}
var input appUpstreamSimQueryInput
if err := json.NewDecoder(request.Body).Decode(&input); err != nil || len(input.SimKeys) != 1 || input.SimKeys[0].ICCID != "card" || input.SimKeys[0].ChanKey != "test-channel" {
t.Errorf("query key mismatch: %+v, %v", input, err)
}
endpoint := strings.TrimPrefix(request.URL.Path, prefix)
mu.Lock()
seen[endpoint]++
mu.Unlock()
writer.Header().Set("Content-Type", "application/json")
fail := scenario == "session failure with IMEI" && endpoint == "sim-session" || scenario == "IMEI failure with session" && endpoint == "sim-imei"
if fail {
_, _ = writer.Write([]byte(`{"code":0,"data":[{"code":500,"message":"query failed"}]}`))
return
}
raw, ok := responses[endpoint]
if !ok {
t.Errorf("unknown endpoint: %s", endpoint)
return
}
_, _ = fmt.Fprintf(writer, `{"code":0,"data":[{"code":0,"resData":%s}]}`, raw)
}))
defer proxy.Close()
adapter, err := gcfg.NewAdapterContent(fmt.Sprintf(`{"upstream":{"default":{"clientName":%q,"timeout":"2s"},"appDiagnosisToken":"test-token","onelinkMock":{"enabled":true}}}`, proxy.URL))
if err != nil {
t.Fatal(err)
}
previous := g.Cfg().GetAdapter()
g.Cfg().SetAdapter(adapter)
t.Cleanup(func() { g.Cfg().SetAdapter(previous) })
row := &appCardQueryRow{TSimCardInfo: entity.TSimCardInfo{Id: 1, Iccid: "card", Imsi: "imsi", Msisdn: "msisdn", ChanKey: "test-channel", BossCardStatus: 2, DataServiceStatus: 1, Imei: "local-old"}}
result, err := NewAppDiagnosis().buildDiagnosisInfo(context.Background(), row, &model.AppCardModel{})
if err != nil {
t.Fatal(err)
}
if result.Info.Status == nil || *result.Info.Status != "4" {
t.Fatal("card status did not come from sim-status")
}
if result.Info.DataStatus == nil || *result.Info.DataStatus != "0" {
t.Fatal("APN status did not come from sim-apn-info")
}
if result.Info.UsedFlowMb == nil || *result.Info.UsedFlowMb != 0 {
t.Fatal("zero usage was lost")
}
if result.Info.RateLimitStatus == nil || *result.Info.RateLimitStatus != "1" || len(result.Info.RateLimitApnDetails) != 1 {
t.Fatal("mobile APN policy response was not normalized")
}
if scenario == "session failure with IMEI" {
if result.Modules["session"].Status != "error" || result.Info.OnlineStatus != nil || result.Session.Imei == nil || *result.Session.Imei != "latest" {
t.Fatal("session failure was masked or IMEI was not independent")
}
} else if scenario == "IMEI failure with session" {
if result.Modules["imei"].Status != "error" || result.Modules["session"].Status != "success" || result.Session.Imei != nil {
t.Fatal("IMEI failure fell back to another source")
}
} else if result.Info.OnlineStatus == nil || *result.Info.OnlineStatus != "1" {
t.Fatal("online status did not come from session")
}
})
}
}