chore: 并入 iotlcm-admin-svr 历史到 admin-svr/(原提交 49818c6)

This commit is contained in:
MiFaZhan
2026-11-02 13:27:59 +08:00
1250 changed files with 154111 additions and 0 deletions
@@ -0,0 +1,139 @@
package upstream
import (
"context"
"encoding/json"
"errors"
"net/http"
"net/http/httptest"
"strings"
"testing"
"github.com/gogf/gf/v2/errors/gcode"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gcfg"
"git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/model"
)
func TestTestChannelPostsOneTenantBoundRequestToGateway(t *testing.T) {
const gatewayBody = `{"code":0,"message":"success","data":{"items":[{"key":"simStatus","name":"卡状态","status":"success"}]}}`
var requestBody model.UpstreamChannelTestRequest
requestCount := 0
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/internal/channel/test" || r.Method != http.MethodPost {
t.Fatalf("unexpected request: %s %s", r.Method, r.URL.Path)
}
requestCount++
if r.Header.Get("X-Internal-Token") != "" {
t.Errorf("unexpected internal token header")
}
if err := json.NewDecoder(r.Body).Decode(&requestBody); err != nil {
t.Fatal(err)
}
_, _ = w.Write([]byte(gatewayBody))
}))
defer server.Close()
oldAdapter := g.Cfg().GetAdapter()
adapter, err := gcfg.NewAdapterContent(`upstream:
gateway:
address: "` + strings.TrimPrefix(server.URL, "http://") + `"
timeout: 1s
`)
if err != nil {
t.Fatal(err)
}
g.Cfg().SetAdapter(adapter)
t.Cleanup(func() { g.Cfg().SetAdapter(oldAdapter) })
output, err := NewUpstreamChan().TestChannel(context.Background(), &model.UpstreamChannelTestRequest{
ChannelID: 42, TenantID: "tenant-a", InputMode: "complete",
ICCID: "iccid", IMSI: "imsi", MSISDN: "msisdn", Items: []string{"simStatus"},
})
if err != nil {
t.Fatal(err)
}
if requestCount != 1 {
t.Fatalf("request count=%d, want one", requestCount)
}
if requestBody.ChannelID != 42 || requestBody.TenantID != "tenant-a" || len(requestBody.Items) != 1 {
t.Fatalf("unexpected request body: %+v", requestBody)
}
if output == nil || len(output.Items) != 1 || output.Items[0].Status != "success" {
t.Fatalf("unexpected output: %+v", output)
}
if output.GatewayResponseRaw != gatewayBody {
t.Fatalf("raw response=%q, want %q", output.GatewayResponseRaw, gatewayBody)
}
}
func TestTestChannelPreservesGatewayErrorResponses(t *testing.T) {
responseBody := ""
responseStatus := http.StatusOK
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(responseStatus)
_, _ = w.Write([]byte(responseBody))
}))
defer server.Close()
oldAdapter := g.Cfg().GetAdapter()
adapter, err := gcfg.NewAdapterContent(`upstream:
gateway:
address: "` + strings.TrimPrefix(server.URL, "http://") + `"
timeout: 1s
`)
if err != nil {
t.Fatal(err)
}
g.Cfg().SetAdapter(adapter)
t.Cleanup(func() { g.Cfg().SetAdapter(oldAdapter) })
for _, tc := range []struct {
name string
body string
status int
wantMessage string
}{
{"business error", `{"code":13000,"message":"系统忙","data":{"items":[]}}`, http.StatusOK, "系统忙"},
{"completion error", `{"code":50,"message":"carrier did not return complete card identifiers","data":null}`, http.StatusOK, "carrier did not return complete card identifiers"},
{"empty message", `{"code":50,"message":"","data":null}`, http.StatusOK, "上游通道测试失败"},
{"HTTP error", `{"code":13000,"message":"网关故障"}`, http.StatusBadGateway, "网关故障"},
{"invalid JSON", `gateway unavailable`, http.StatusOK, "解析上游通道测试响应失败"},
{"schema mismatch", `{"code":0,"data":{"items":"invalid"}}`, http.StatusOK, "解析上游通道测试响应失败"},
} {
t.Run(tc.name, func(t *testing.T) {
responseBody = tc.body
responseStatus = tc.status
output, err := NewUpstreamChan().TestChannel(context.Background(), &model.UpstreamChannelTestRequest{
ChannelID: 42, TenantID: "tenant-a", InputMode: "complete",
ICCID: "iccid", IMSI: "imsi", MSISDN: "msisdn",
})
if err == nil || output != nil {
t.Fatalf("failure must remain an error: output=%+v err=%v", output, err)
}
var diagnostic *model.TSimChannelsTestError
if !errors.As(err, &diagnostic) || diagnostic.GatewayResponseRaw != tc.body {
t.Fatalf("missing raw error response: %+v", err)
}
if !strings.Contains(err.Error(), tc.wantMessage) || gerror.Code(err) != gcode.CodeNil {
t.Fatalf("original error changed: %v code=%v", err, gerror.Code(err))
}
if err.Error() != diagnostic.Err.Error() || !errors.Is(err, diagnostic.Err) {
t.Fatalf("original error chain changed: %v", err)
}
})
}
t.Run("individual failures remain results", func(t *testing.T) {
responseStatus = http.StatusOK
responseBody = `{"code":0,"message":"success","data":{"items":[{"key":"simStatus","status":"failed","errorCode":9999,"message":"carrier rejected"},{"key":"simSession","status":"timeout","message":"channel test item timed out"}]}}`
output, err := NewUpstreamChan().TestChannel(context.Background(), &model.UpstreamChannelTestRequest{ChannelID: 42, TenantID: "tenant-a"})
if err != nil || output == nil {
t.Fatalf("single-item failures must not fail the whole request: %v", err)
}
if output.GatewayResponseRaw != responseBody || len(output.Items) != 2 || output.Items[0].ErrorCode != 9999 || output.Items[0].Message != "carrier rejected" || output.Items[1].Status != "timeout" {
t.Fatalf("item results changed: %+v", output)
}
})
}