sync: 同步 v1.0.4 开源代码并脱敏
This commit is contained in:
@@ -2,6 +2,7 @@ package upstreamimpl
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
@@ -14,6 +15,196 @@ import (
|
||||
"git.5iot.com/iotlcm-public/iotlcm-upstream-chan/internal/model/entity"
|
||||
)
|
||||
|
||||
func TestYdLegacyPollingHardDeadlineCancelsInflightRequest(t *testing.T) {
|
||||
defer shortenYdBatchPoll(50 * time.Millisecond)()
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
select {
|
||||
case <-r.Context().Done():
|
||||
case <-time.After(time.Second):
|
||||
_, _ = w.Write([]byte(`{"status":"0","result":[{"jobStatus":"1"}]}`))
|
||||
}
|
||||
}))
|
||||
defer server.Close()
|
||||
started := time.Now()
|
||||
result := queryBatchResultYD(context.Background(), newYdApnChannelWithServer(server), "deadline-job")
|
||||
if result.finished || time.Since(started) > 500*time.Millisecond || !strings.Contains(result.reason, "deadline") {
|
||||
t.Fatalf("轮询没有硬截止:elapsed=%s result=%+v", time.Since(started), result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestYdAsyncCheckpointFailureStopsFurtherCarrierWrites(t *testing.T) {
|
||||
for _, tc := range []struct {
|
||||
name string
|
||||
keys []*model.SimKey
|
||||
firstPath string
|
||||
firstLen int
|
||||
}{
|
||||
{name: "single_then_single", keys: ydSimKeysWithMsisdn(2), firstPath: ydCommunicationServicePath, firstLen: 1},
|
||||
{name: "batch_then_single", keys: func() []*model.SimKey {
|
||||
keys := ydSimKeysWithMsisdn(11)
|
||||
keys[10].MSISDN = ""
|
||||
return keys
|
||||
}(), firstPath: ydCommunicationFunctionBatchPath, firstLen: 10},
|
||||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
capture := &ydApnCapture{}
|
||||
channel, closeServer := newYdApnTestChannel(capture)
|
||||
defer closeServer()
|
||||
sentinel := errors.New("checkpoint unavailable")
|
||||
checkpoints := 0
|
||||
ctx := context.WithValue(context.Background(), model.ApnOperationCheckpointKey{}, func(output model.SimCardOperateChangeApnOutput) error {
|
||||
checkpoints++
|
||||
if len(output) != tc.firstLen {
|
||||
t.Errorf("checkpoint contains %d results, want %d", len(output), tc.firstLen)
|
||||
}
|
||||
return sentinel
|
||||
})
|
||||
items, err := changeSimApnFunctionYD(ctx, channel, &model.SimCardOperateChangeApnInput{
|
||||
SimKeys: tc.keys, ReqData: model.SimCardOperateChangeApnInputItem{OperType: "0", SubmitOnly: true, OperationID: "test-operation"},
|
||||
})
|
||||
if !errors.Is(err, sentinel) || checkpoints != 1 || len(items) != tc.firstLen {
|
||||
t.Fatalf("checkpoint failure not propagated: err=%v checkpoints=%d items=%d", err, checkpoints, len(items))
|
||||
}
|
||||
if len(capture.paths) != 1 || !strings.HasSuffix(capture.paths[0], tc.firstPath) {
|
||||
t.Fatalf("wrote another carrier request after checkpoint failure: %v", capture.paths)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestYdAsyncSubmitReturnsJobWithoutQuery(t *testing.T) {
|
||||
capture := &ydApnCapture{}
|
||||
channel, closeServer := newYdApnTestChannel(capture)
|
||||
defer closeServer()
|
||||
checkpoints := 0
|
||||
ctx := context.WithValue(context.Background(), model.ApnOperationCheckpointKey{}, func(output model.SimCardOperateChangeApnOutput) error {
|
||||
checkpoints++
|
||||
if output[0].ResData.OrderNum != "JOB1" {
|
||||
t.Fatal("checkpoint缺少jobId")
|
||||
}
|
||||
return nil
|
||||
})
|
||||
items, err := changeSimApnFunctionYD(ctx, channel, &model.SimCardOperateChangeApnInput{
|
||||
SimKeys: ydSimKeysWithMsisdn(100),
|
||||
ReqData: model.SimCardOperateChangeApnInputItem{OperType: "1", SubmitOnly: true},
|
||||
})
|
||||
if checkpoints != 1 {
|
||||
t.Fatalf("拿jobId后未立即持久化:%d", checkpoints)
|
||||
}
|
||||
if err != nil || len(items) != 100 || len(capture.paths) != 1 {
|
||||
t.Fatalf("提交应仅调用一次,items=%d paths=%v err=%v", len(items), capture.paths, err)
|
||||
}
|
||||
for _, item := range items {
|
||||
if !item.ResData.Pending || item.ResData.OrderNum != "JOB1" || item.ResData.Uncertain {
|
||||
t.Fatalf("受理状态错误:%+v", item)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestYdAsyncQueryOnlyOnceAndPreservesReason(t *testing.T) {
|
||||
for _, body := range []string{
|
||||
`{"status":"13012","message":"查询限流"}`,
|
||||
`{"status":"0","result":[{"jobStatus":"1"}]}`,
|
||||
`invalid-json`,
|
||||
`{"status":"0","result":[]}`,
|
||||
} {
|
||||
t.Run(body, func(t *testing.T) {
|
||||
calls := 0
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
calls++
|
||||
if !strings.Contains(r.URL.Path, "sim-batch-result") || r.URL.Query().Get("jobId") != "persisted-job" {
|
||||
t.Errorf("不应重新提交:%s", r.URL.String())
|
||||
}
|
||||
_, _ = w.Write([]byte(body))
|
||||
}))
|
||||
defer server.Close()
|
||||
items, err := changeSimApnFunctionYD(context.Background(), newYdApnChannelWithServer(server), &model.SimCardOperateChangeApnInput{
|
||||
SimKeys: ydSimKeysWithMsisdn(10), ReqData: model.SimCardOperateChangeApnInputItem{QueryJobID: "persisted-job"},
|
||||
})
|
||||
if err != nil || calls != 1 || len(items) != 10 {
|
||||
t.Fatalf("查询次数错误:calls=%d err=%v", calls, err)
|
||||
}
|
||||
for _, item := range items {
|
||||
if !item.ResData.Pending || item.Message == "" || item.ResData.OrderNum != "persisted-job" {
|
||||
t.Fatalf("应保留待查状态和具体原因:%+v", item)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestYdAsyncSubmitUnknownIsNotConfirmedFailure(t *testing.T) {
|
||||
for _, body := range []string{`{"status":"0","result":[]}`, `not-json`, `{}`, `{"status":"bad"}`} {
|
||||
t.Run(body, func(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
_, _ = w.Write([]byte(body))
|
||||
}))
|
||||
defer server.Close()
|
||||
items, err := changeSimApnFunctionYD(context.Background(), newYdApnChannelWithServer(server), &model.SimCardOperateChangeApnInput{
|
||||
SimKeys: ydSimKeysWithMsisdn(10), ReqData: model.SimCardOperateChangeApnInputItem{OperType: "1", SubmitOnly: true},
|
||||
})
|
||||
if err != nil || len(items) != 10 {
|
||||
t.Fatalf("未知提交结果应逐卡返回:%v", err)
|
||||
}
|
||||
for _, item := range items {
|
||||
if !item.ResData.Uncertain || item.Message == "" {
|
||||
t.Fatalf("提交结果未知不得确认办理失败:%+v", item)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestYdAsyncQueryTerminalResults(t *testing.T) {
|
||||
keys := ydSimKeysWithMsisdn(10)
|
||||
for _, tc := range []struct{ status, want string }{{"2", "0"}, {"3", "4001"}, {"4", "failed"}} {
|
||||
t.Run(tc.status, func(t *testing.T) {
|
||||
calls := 0
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
calls++
|
||||
if !strings.Contains(r.URL.Path, "sim-batch-result") {
|
||||
t.Error("查询不得提交")
|
||||
}
|
||||
_, _ = fmt.Fprintf(w, `{"status":"0","message":"任务完成","result":[{"jobStatus":%q,"resultList":[{"resultId":%q,"status":%q,"message":"逐卡结果"}]}]}`, tc.status, keys[0].MSISDN, tc.want)
|
||||
}))
|
||||
defer server.Close()
|
||||
items, err := newYdApnChannelWithServer(server).QuerySimApnFunctionResult(context.Background(), &model.SimCardOperateChangeApnInput{SimKeys: keys, ReqData: model.SimCardOperateChangeApnInputItem{QueryJobID: "job"}})
|
||||
if err != nil || calls != 1 || len(items) != 10 {
|
||||
t.Fatalf("终态查询错误:%v", err)
|
||||
}
|
||||
if items[0].ResData.Pending || items[0].ResData.Uncertain {
|
||||
t.Fatalf("已确认结果仍标未知:%+v", items[0])
|
||||
}
|
||||
if tc.status == "2" && items[0].Code != 0 {
|
||||
t.Fatal("成功结果未映射")
|
||||
}
|
||||
if tc.status == "3" && items[0].Code != 4001 {
|
||||
t.Fatal("逐卡失败原因未映射")
|
||||
}
|
||||
if tc.status == "4" && items[0].Code == 0 {
|
||||
t.Fatal("任务失败误报成功")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestYdAsyncMalformedCardStatusIsUnconfirmed(t *testing.T) {
|
||||
keys := ydSimKeysWithMsisdn(1)
|
||||
cards := toYdBatchCardMap([]ydBatchResultItem{{ResultId: keys[0].MSISDN, Status: "invalid", Message: "bad status"}})
|
||||
items := mapYdQueryResult(keys, "job", ydBatchQueryResult{finished: true, cards: cards})
|
||||
if !items[0].ResData.Uncertain || items[0].Code == 0 || !strings.Contains(items[0].Message, "invalid") {
|
||||
t.Fatalf("无效状态不能按成功处理:%+v", items[0])
|
||||
}
|
||||
}
|
||||
|
||||
func TestYdAsyncMissingCardRemainsUnconfirmed(t *testing.T) {
|
||||
keys := ydSimKeysWithMsisdn(2)
|
||||
items := mapYdQueryResult(keys, "job", ydBatchQueryResult{finished: true, cards: map[string]ydBatchCardResult{keys[0].MSISDN: {code: 0}}})
|
||||
if items[0].Code != 0 || !items[1].ResData.Uncertain || items[1].ResData.OrderNum != "job" {
|
||||
t.Fatalf("缺失结果应待核对:%+v", items)
|
||||
}
|
||||
}
|
||||
|
||||
func TestYdCommunicationBusinessType(t *testing.T) {
|
||||
for _, tc := range []struct {
|
||||
in string
|
||||
|
||||
Reference in New Issue
Block a user