sync: 同步生产版 v1.0.4 并脱敏

This commit is contained in:
MiFaZhan
2026-10-29 15:03:39 +08:00
parent fed9459244
commit 2d045591b7
32 changed files with 695 additions and 80 deletions
+122
View File
@@ -1,12 +1,134 @@
package cmd
import (
"context"
"crypto/sha256"
"encoding/json"
"fmt"
"net/url"
"os"
"strings"
"testing"
"time"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
"github.com/gogf/gf/v2/os/gcfg"
v1 "git.5iot.com/iotlcm-public/iotlcm-upstream-proxy/api/cardquery/v1"
_ "git.5iot.com/iotlcm-public/iotlcm-upstream-proxy/internal/logic/simKeyFill"
"git.5iot.com/iotlcm-public/iotlcm-upstream-proxy/internal/logic/upstreamapi"
"git.5iot.com/iotlcm-public/iotlcm-upstream-proxy/internal/logic/upstreamimpl"
"git.5iot.com/iotlcm-public/iotlcm-upstream-proxy/internal/model"
"git.5iot.com/iotlcm-public/iotlcm-upstream-proxy/internal/service"
)
func TestAPNHTTPHarness(t *testing.T) {
if os.Getenv("APN_HTTP_CHAIN_HELPER") != "1" {
t.Skip("未启用本机HTTP模拟链")
}
gateway, err := url.Parse(os.Getenv("APN_HTTP_CHAIN_CHAN"))
if err != nil || gateway.Scheme != "http" || gateway.Hostname() != "127.0.0.1" || gateway.Port() == "" {
t.Fatal("只允许本机模拟chan")
}
adapter, err := gcfg.NewAdapterContent(fmt.Sprintf(`{"gateway":{"address":%q,"timeout":"2s"}}`, gateway.Host))
if err != nil {
t.Fatal(err)
}
g.Cfg().SetAdapter(adapter)
api := upstreamapi.NewUpstreamAPI()
api.RegisterChan("fake-channel", "1", &model.SimCardChannelCache{Instance: upstreamimpl.NewSimYD()})
service.RegisterUpstreamAPI(api)
server := ghttp.GetServer(t.Name())
server.SetAddr("127.0.0.1:0")
bindHTTPRoutes(server)
stop := make(chan struct{})
server.BindHandler("POST:/__test/stop", func(r *ghttp.Request) { close(stop) })
if err := server.Start(); err != nil {
t.Fatal(err)
}
defer server.Shutdown()
fmt.Printf("APN_CHAIN_READY=http://127.0.0.1:%d\n", server.GetListenedPort())
select {
case <-stop:
case <-time.After(3 * time.Minute):
t.Error("HTTP模拟链未正常结束")
}
}
type apnBindingTestFill struct {
service.ISimKeyFill
captured chan model.SimBaseReqJson
}
func (s *apnBindingTestFill) SimKeyFill(_ context.Context, input *model.SimBaseReqJson) (model.SimBaseResJson, error) {
s.captured <- *input
return model.SimBaseResJson{}, nil
}
func TestAPNProductionHTTPBindingPreservesRawPayload(t *testing.T) {
old := service.SimKeyFill()
capture := &apnBindingTestFill{ISimKeyFill: old, captured: make(chan model.SimBaseReqJson, 1)}
service.RegisterSimKeyFill(capture)
t.Cleanup(func() { service.RegisterSimKeyFill(old) })
server := ghttp.GetServer(t.Name())
server.SetAddr("127.0.0.1:0")
bindHTTPRoutes(server)
server.BindHandler("POST:/__test/legacy-binding", func(r *ghttp.Request) {
var req v1.SimBaseReq
if err := r.Parse(&req); err != nil {
t.Error(err)
r.Response.WriteStatus(400)
return
}
capture.captured <- req.SimBaseReqJson
})
if err := server.Start(); err != nil {
t.Fatal(err)
}
t.Cleanup(func() { _ = server.Shutdown() })
for _, data := range []string{
`{"operationId":"frozen-operation","submitOnly":true,"operType":"1","apnName":"CMIOT"}`,
`{"operationId":"frozen-operation","queryJobId":"saved-job","operType":"1","apnName":"CMIOT"}`,
`{"operationId":"frozen-operation","recoverOnly":true,"operType":"1","apnName":"CMIOT"}`,
} {
for _, path := range []string{"/sim/change/sim-apn", "/sim/query/sim-apn-capability", "/sim/query/sim-session"} {
input := model.SimBaseReqJson{SimKeys: []*model.SimKey{{ChanKey: "fake", ICCID: "fake-card", MSISDN: "frozen-number"}}, ReqData: json.RawMessage(data)}
response, err := g.Client().ContentJson().Post(context.Background(), fmt.Sprintf("http://127.0.0.1:%d%s", server.GetListenedPort(), path), input)
if err != nil {
t.Fatal(err)
}
body := response.ReadAll()
_ = response.Close()
select {
case got := <-capture.captured:
var wantData, gotData map[string]any
_ = json.Unmarshal(input.ReqData, &wantData)
_ = json.Unmarshal(got.ReqData, &gotData)
wantJSON, _ := json.Marshal(wantData)
gotJSON, _ := json.Marshal(gotData)
if path == "/sim/query/sim-session" {
baselineResponse, err := g.Client().ContentJson().Post(context.Background(), fmt.Sprintf("http://127.0.0.1:%d/__test/legacy-binding", server.GetListenedPort()), input)
if err != nil {
t.Fatal(err)
}
_ = baselineResponse.Close()
baseline := <-capture.captured
if string(got.ReqData) != string(baseline.ReqData) {
t.Fatalf("非APN旧绑定行为改变:got=%q baseline=%q", got.ReqData, baseline.ReqData)
}
} else if sha256.Sum256(wantJSON) != sha256.Sum256(gotJSON) {
t.Fatalf("APN冻结请求摘要改变:path=%s want=%s got=%s", path, wantJSON, gotJSON)
}
if len(got.SimKeys) != 1 || *got.SimKeys[0] != *input.SimKeys[0] {
t.Fatalf("代理生产绑定丢字段:%+v", got)
}
default:
t.Fatalf("未经过生产代理controller:%s", body)
}
}
}
}
func TestBindHTTPRoutesRegistersChannelControlRoutes(t *testing.T) {
server := ghttp.GetServer("proxy-channel-refresh-route-test")
server.SetAddr("127.0.0.1:0")