2bec257289
iotlcm-worker-svr:异步执行中枢(RabbitMQ 消费者 + 全量同步编排)。 - Go module:iotlcm-worker-svr → git.5iot.com/iotlcm-public/iotlcm-worker-svr(214 文件) - 凭据与内部标识脱敏:MySQL/Redis 凭据、私网与生产 IP、内网域名、 库名 xiujie_admin → iotlcm、哨兵名占位 - 159 处真实手机号 → 合法 11 位编造号(保留号段与后 4 位,维持互异, 不破坏「校验 MSISDN 格式」等测试断言) - 移除内部资产:CI 触发器、Jenkins 触发测试文档、预演门禁与镜像 digest 记录 - Dockerfile 改用公共基础镜像(golang:1.25-alpine → alpine:3.23), 移除写死的 git 凭据 - README 重写(架构/全量同步模型/配置/已知失败),补 Apache-2.0 LICENSE,LF 行尾 + .gitattributes 已知:3 个测试包在源仓同一提交上同样失败(client/upstream、 service/allocate、service/inbound),属既有缺陷,本仓未引入亦未修复。
142 lines
4.6 KiB
Go
142 lines
4.6 KiB
Go
package model
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestNormalizeScopeNilAndEmptyMeanFullSync(t *testing.T) {
|
|
for name, scope := range map[string]*SyncScope{
|
|
"nil": nil,
|
|
"no channels": {},
|
|
"empty slice": {Channels: []string{}},
|
|
} {
|
|
got, err := NormalizeScope(scope)
|
|
if err != nil {
|
|
t.Fatalf("%s: unexpected error: %v", name, err)
|
|
}
|
|
if got != nil {
|
|
t.Fatalf("%s: expected nil scope for full sync, got %+v", name, got)
|
|
}
|
|
if got.ChannelCount() != 0 || !got.Allows("anything") {
|
|
t.Fatalf("%s: nil scope must allow every channel", name)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestNormalizeScopeDeduplicatesAndSorts(t *testing.T) {
|
|
got, err := NormalizeScope(&SyncScope{Channels: []string{"217", "173", "217", "189"}})
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
want := []string{"173", "189", "217"}
|
|
if len(got.Channels) != len(want) {
|
|
t.Fatalf("channels = %v, want %v", got.Channels, want)
|
|
}
|
|
for i := range want {
|
|
if got.Channels[i] != want[i] {
|
|
t.Fatalf("channels = %v, want %v (sorted)", got.Channels, want)
|
|
}
|
|
}
|
|
// Sorting keeps ScopeDigest stable for requests listing the same channels
|
|
// in a different order.
|
|
reordered, err := NormalizeScope(&SyncScope{Channels: []string{"189", "217", "173"}})
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if strings.Join(reordered.Channels, ",") != strings.Join(got.Channels, ",") {
|
|
t.Fatalf("order-dependent normalization: %v vs %v", reordered.Channels, got.Channels)
|
|
}
|
|
}
|
|
|
|
func TestNormalizeScopeTrimsWhitespace(t *testing.T) {
|
|
got, err := NormalizeScope(&SyncScope{Channels: []string{" 217 ", "173"}})
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if got.Allows("217") != true {
|
|
t.Fatalf("whitespace-padded chanKey was not trimmed: %+v", got)
|
|
}
|
|
}
|
|
|
|
func TestNormalizeScopeRejectsInvalidInput(t *testing.T) {
|
|
cases := map[string]*SyncScope{
|
|
"too many channels": {Channels: make([]string, MaxScopeChannels+1)},
|
|
"chanKey too long": {Channels: []string{strings.Repeat("a", MaxChanKeyLength+1)}},
|
|
"chanKey with slash": {Channels: []string{"a/b"}},
|
|
"chanKey with space": {Channels: []string{"a b"}},
|
|
"chanKey with unicode": {Channels: []string{"通道"}},
|
|
"chanKey with brace": {Channels: []string{"a{b}"}},
|
|
"empty chanKey": {Channels: []string{""}},
|
|
"blank chanKey": {Channels: []string{" "}},
|
|
"unknown triggerSource": {Channels: []string{"217"}, TriggerSource: "cron"},
|
|
}
|
|
for name, scope := range cases {
|
|
if _, err := NormalizeScope(scope); err == nil {
|
|
t.Fatalf("%s: expected an error", name)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestNormalizeScopeAcceptsBoundaries(t *testing.T) {
|
|
// Exactly the maximum count must pass.
|
|
channels := make([]string, MaxScopeChannels)
|
|
for i := range channels {
|
|
channels[i] = "chan-" + strings.Repeat("0", i%10) + string(rune('a'+i%26))
|
|
}
|
|
if _, err := NormalizeScope(&SyncScope{Channels: channels}); err != nil {
|
|
t.Fatalf("exactly %d channels must be accepted: %v", MaxScopeChannels, err)
|
|
}
|
|
// A chanKey of exactly the maximum length must pass.
|
|
if err := ValidateChanKey(strings.Repeat("a", MaxChanKeyLength)); err != nil {
|
|
t.Fatalf("chanKey of exactly %d characters must be accepted: %v", MaxChanKeyLength, err)
|
|
}
|
|
}
|
|
|
|
func TestNormalizeScopeDefaultsTriggerSource(t *testing.T) {
|
|
got, err := NormalizeScope(&SyncScope{Channels: []string{"217"}})
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if got.TriggerSource != TriggerSourceManual {
|
|
t.Fatalf("triggerSource = %q, want %q", got.TriggerSource, TriggerSourceManual)
|
|
}
|
|
}
|
|
|
|
func TestNormalizeScopeKeepsExplicitTriggerSource(t *testing.T) {
|
|
got, err := NormalizeScope(&SyncScope{Channels: []string{"217"}, TriggerSource: TriggerSourceAPI})
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if got.TriggerSource != TriggerSourceAPI {
|
|
t.Fatalf("triggerSource = %q, want %q", got.TriggerSource, TriggerSourceAPI)
|
|
}
|
|
}
|
|
|
|
func TestScopeChannelSetAndSample(t *testing.T) {
|
|
scope, err := NormalizeScope(&SyncScope{Channels: []string{"217", "173"}})
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
set := scope.ChannelSet()
|
|
if _, ok := set["173"]; !ok {
|
|
t.Fatalf("channel set missing 173: %v", set)
|
|
}
|
|
if len(set) != 2 {
|
|
t.Fatalf("channel set = %v, want 2 entries", set)
|
|
}
|
|
if sample := scope.ChannelSample(1); len(sample) != 1 || sample[0] != "173" {
|
|
t.Fatalf("sample = %v, want [173]", sample)
|
|
}
|
|
if sample := scope.ChannelSample(10); len(sample) != 2 {
|
|
t.Fatalf("sample = %v, want both channels", sample)
|
|
}
|
|
var nilScope *SyncScope
|
|
if nilScope.ChannelSet() != nil {
|
|
t.Fatalf("nil scope must return a nil channel set")
|
|
}
|
|
if nilScope.ChannelSample(10) != nil {
|
|
t.Fatalf("nil scope must return a nil sample")
|
|
}
|
|
}
|