package controller import ( "context" "sync" "testing" "time" ) // TestMintSuccessChannel_BufferAndOverflow 验证 mintSuccessCh 的 256 cap + 非阻塞投递行为。 // 真实消费路径涉及 DB,这里只验证 channel 行为: // 1) 256 buffer 容量满足 // 2) 256 cap 满后再投递走 default 分支(不阻塞) // 3) 投递出的事件能被 consumer 协程读取 func TestMintSuccessChannel_BufferAndOverflow(t *testing.T) { ctrl := &AssetController{ mintSuccessCh: make(chan *MintSuccessEvent, 256), } // 1. 投递 256 个事件,全部应入队(channel 容量刚好) for i := 0; i < 256; i++ { ev := &MintSuccessEvent{ UserID: int64(i), AssetID: int64(1000 + i), OrderID: "order", InstanceNo: "inst", } select { case ctrl.mintSuccessCh <- ev: // 期望入队 default: t.Fatalf("event %d should be enqueued, channel not full yet", i) } } // 2. 现在 channel 满,再投递应走 default(非阻塞丢弃) dropped := false extra := &MintSuccessEvent{UserID: 999, AssetID: 9999, OrderID: "x", InstanceNo: "y"} select { case ctrl.mintSuccessCh <- extra: // 不应到这里 default: dropped = true } if !dropped { t.Fatal("expected extra event to be dropped when channel full") } // 3. 启 consumer 协程消费 ctx, cancel := context.WithCancel(context.Background()) defer cancel() var wg sync.WaitGroup wg.Add(1) go func() { defer wg.Done() // 简单 consume:读到 256 个就停 consumed := 0 for consumed < 256 { select { case <-ctx.Done(): return case ev := <-ctrl.mintSuccessCh: _ = ev consumed++ } } }() // 4. 等待 consumer 读完 done := make(chan struct{}) go func() { wg.Wait() close(done) }() select { case <-done: // OK case <-time.After(2 * time.Second): t.Fatal("consumer did not drain 256 events within 2s") } // 5. 再次投递,通道已空,应能入队 for i := 0; i < 256; i++ { ev := &MintSuccessEvent{UserID: int64(i), AssetID: int64(i)} select { case ctrl.mintSuccessCh <- ev: default: t.Fatalf("post-drain event %d should be enqueued", i) } } } // TestMintSuccessChannel_NonBlockingSend 验证正常路径上 Send 不阻塞(空 channel 立即入队)。 func TestMintSuccessChannel_NonBlockingSend(t *testing.T) { ctrl := &AssetController{ mintSuccessCh: make(chan *MintSuccessEvent, 256), } ev := &MintSuccessEvent{ UserID: 42, AssetID: 100, OrderID: "order-abc", InstanceNo: "inst-xyz", } // 空 channel:Send 立即返回 done := make(chan struct{}) go func() { ctrl.mintSuccessCh <- ev close(done) }() select { case <-done: // OK case <-time.After(100 * time.Millisecond): t.Fatal("send to empty channel should not block") } // 验证可读出 got := <-ctrl.mintSuccessCh if got.UserID != 42 || got.AssetID != 100 || got.OrderID != "order-abc" { t.Fatalf("got event payload mismatch: %+v", got) } } // TestMintSuccessEvent_StructFields 验证 MintSuccessEvent payload 字段能够在测试中正确传递, // 替代直接构造 resp.GetAsset() 的复杂 setup。 func TestMintSuccessEvent_StructFields(t *testing.T) { ev := &MintSuccessEvent{ UserID: 1, AssetID: 2, OrderID: "order-3", InstanceNo: "inst-4", } if ev.UserID != 1 || ev.AssetID != 2 || ev.OrderID != "order-3" || ev.InstanceNo != "inst-4" { t.Fatal("MintSuccessEvent field round-trip failed") } }