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),属既有缺陷,本仓未引入亦未修复。
152 lines
3.2 KiB
Go
152 lines
3.2 KiB
Go
package rabbitmq
|
|
|
|
import (
|
|
"context"
|
|
"reflect"
|
|
"sync"
|
|
"testing"
|
|
)
|
|
|
|
type fakeChannel struct {
|
|
mu sync.Mutex
|
|
cancelCalls int
|
|
closeCalls int
|
|
closed bool
|
|
}
|
|
|
|
func (f *fakeChannel) Cancel(string, bool) error {
|
|
f.mu.Lock()
|
|
defer f.mu.Unlock()
|
|
f.cancelCalls++
|
|
return nil
|
|
}
|
|
|
|
func (f *fakeChannel) Close() error {
|
|
f.mu.Lock()
|
|
defer f.mu.Unlock()
|
|
f.closeCalls++
|
|
f.closed = true
|
|
return nil
|
|
}
|
|
|
|
func (f *fakeChannel) IsClosed() bool {
|
|
f.mu.Lock()
|
|
defer f.mu.Unlock()
|
|
return f.closed
|
|
}
|
|
|
|
func TestCloseIsIdempotent(t *testing.T) {
|
|
resetRabbitMQState(t)
|
|
|
|
channel := &fakeChannel{}
|
|
done := make(chan struct{})
|
|
close(done)
|
|
registerConsumer(&managedConsumer{
|
|
channel: channel,
|
|
tag: "test-consumer",
|
|
done: done,
|
|
})
|
|
|
|
if err := Close(context.Background()); err != nil {
|
|
t.Fatalf("first Close() error = %v", err)
|
|
}
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
cancel()
|
|
if err := Close(ctx); err != nil {
|
|
t.Fatalf("second Close() error = %v", err)
|
|
}
|
|
|
|
channel.mu.Lock()
|
|
defer channel.mu.Unlock()
|
|
if channel.cancelCalls != 1 {
|
|
t.Fatalf("Cancel() calls = %d, want 1", channel.cancelCalls)
|
|
}
|
|
if channel.closeCalls != 1 {
|
|
t.Fatalf("Close() calls = %d, want 1", channel.closeCalls)
|
|
}
|
|
}
|
|
|
|
func TestCloseSkipsAlreadyClosedChannel(t *testing.T) {
|
|
resetRabbitMQState(t)
|
|
|
|
channel := &fakeChannel{closed: true}
|
|
done := make(chan struct{})
|
|
close(done)
|
|
registerConsumer(&managedConsumer{
|
|
channel: channel,
|
|
tag: "closed-consumer",
|
|
done: done,
|
|
})
|
|
|
|
if err := Close(context.Background()); err != nil {
|
|
t.Fatalf("Close() error = %v", err)
|
|
}
|
|
|
|
channel.mu.Lock()
|
|
defer channel.mu.Unlock()
|
|
if channel.cancelCalls != 0 || channel.closeCalls != 0 {
|
|
t.Fatalf("closed channel calls: Cancel=%d Close=%d, want 0", channel.cancelCalls, channel.closeCalls)
|
|
}
|
|
}
|
|
|
|
func TestCloseHonorsContextWhileWaiting(t *testing.T) {
|
|
resetRabbitMQState(t)
|
|
|
|
channel := &fakeChannel{}
|
|
registerConsumer(&managedConsumer{
|
|
channel: channel,
|
|
tag: "blocked-consumer",
|
|
done: make(chan struct{}),
|
|
})
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
cancel()
|
|
if err := Close(ctx); err == nil {
|
|
t.Fatal("Close() error = nil, want context cancellation error")
|
|
}
|
|
|
|
channel.mu.Lock()
|
|
defer channel.mu.Unlock()
|
|
if channel.closeCalls != 1 {
|
|
t.Fatalf("Close() calls = %d, want forced cleanup", channel.closeCalls)
|
|
}
|
|
}
|
|
|
|
func TestDeliveryMetadataContext(t *testing.T) {
|
|
expected := DeliveryMetadata{
|
|
DeliveryTag: 42,
|
|
Redelivered: true,
|
|
Consumer: "batch-consumer",
|
|
Queue: "iotlcm.batch.execute",
|
|
}
|
|
ctx := WithDeliveryMetadata(context.Background(), expected)
|
|
actual, ok := DeliveryMetadataFromContext(ctx)
|
|
if !ok {
|
|
t.Fatal("delivery metadata not found in context")
|
|
}
|
|
if !reflect.DeepEqual(actual, expected) {
|
|
t.Fatalf("delivery metadata = %+v, want %+v", actual, expected)
|
|
}
|
|
if _, ok = DeliveryMetadataFromContext(context.Background()); ok {
|
|
t.Fatal("unexpected delivery metadata in empty context")
|
|
}
|
|
}
|
|
|
|
func resetRabbitMQState(t *testing.T) {
|
|
t.Helper()
|
|
consumerMu.Lock()
|
|
consumers = nil
|
|
consumerMu.Unlock()
|
|
connMu.Lock()
|
|
conn = nil
|
|
connMu.Unlock()
|
|
t.Cleanup(func() {
|
|
consumerMu.Lock()
|
|
consumers = nil
|
|
consumerMu.Unlock()
|
|
connMu.Lock()
|
|
conn = nil
|
|
connMu.Unlock()
|
|
})
|
|
}
|