package idempotency_test import ( "testing" "github.com/break/junhong_cmp_fiber/pkg/idempotency" ) func TestFingerprintIgnoresTransportFieldsAndNormalizesObjectOrder(t *testing.T) { t.Parallel() left, err := idempotency.Fingerprint(map[string]any{ "amount": 100, "remark": " 月度充值 ", "token": "token-a", "nested": map[string]any{"enabled": true, "count": 2}, }) if err != nil { t.Fatalf("计算第一个请求指纹失败:%v", err) } right, err := idempotency.Fingerprint(map[string]any{ "nested": map[string]any{"count": 2, "enabled": true}, "timestamp": 1720000000, "remark": "月度充值", "amount": 100, }) if err != nil { t.Fatalf("计算第二个请求指纹失败:%v", err) } if left.Algorithm != idempotency.FingerprintAlgorithmV1 { t.Fatalf("算法版本不正确:%s", left.Algorithm) } if left.Value != right.Value { t.Fatalf("仅传输字段或对象顺序变化不应改变指纹:%s != %s", left.Value, right.Value) } } func TestClassifyReplayDistinguishesScopeAndConflict(t *testing.T) { t.Parallel() original := idempotency.Record{ Scope: idempotency.Scope{Subject: "account:7", Operation: "agent-recharge.create"}, RequestID: "request-1", Fingerprint: idempotency.FingerprintValue{Algorithm: idempotency.FingerprintAlgorithmV1, Value: "abc"}, } if got := idempotency.Classify(original, original.Scope, "request-1", original.Fingerprint); got != idempotency.ReplaySame { t.Fatalf("相同命令应识别为重放,得到:%s", got) } if got := idempotency.Classify(original, original.Scope, "request-1", idempotency.FingerprintValue{Algorithm: idempotency.FingerprintAlgorithmV1, Value: "def"}); got != idempotency.ReplayConflict { t.Fatalf("同作用域同请求 ID 的不同内容应冲突,得到:%s", got) } otherScope := idempotency.Scope{Subject: "account:8", Operation: original.Scope.Operation} if got := idempotency.Classify(original, otherScope, "request-1", original.Fingerprint); got != idempotency.ReplayUnrelated { t.Fatalf("不同主体不应相互污染,得到:%s", got) } }