package adapter import ( "context" "sync" "testing" "time" "github.com/ThreeDotsLabs/watermill/message" ) // 简单的测试日志适配器 type testLogger struct{} func (t *testLogger) InfoContext(ctx context.Context, msg string, args ...interface{}) {} func (t *testLogger) DebugContext(ctx context.Context, msg string, args ...interface{}) {} func (t *testLogger) WarnContext(ctx context.Context, msg string, args ...interface{}) {} func (t *testLogger) ErrorContext(ctx context.Context, msg string, args ...interface{}) {} func (t *testLogger) Info(msg string, args ...interface{}) {} func (t *testLogger) Debug(msg string, args ...interface{}) {} func (t *testLogger) Warn(msg string, args ...interface{}) {} func (t *testLogger) Error(msg string, args ...interface{}) {} func TestTCPPublisherSubscriber_Integration(t *testing.T) { testLogger := &testLogger{} // 创建 Subscriber subscriberConfig := TCPSubscriberConfig{ ListenAddr: "127.0.0.1:18080", } subscriber, err := NewTCPSubscriber(subscriberConfig, testLogger) if err != nil { t.Fatalf("Failed to create subscriber: %v", err) } defer subscriber.Close() // 等待服务器启动 time.Sleep(100 * time.Millisecond) // 订阅 topic ctx := context.Background() topic := "test-topic" msgChan, err := subscriber.Subscribe(ctx, topic) if err != nil { t.Fatalf("Failed to subscribe: %v", err) } // 创建 Publisher publisherConfig := TCPPublisherConfig{ ServerAddr: "127.0.0.1:18080", ConnectTimeout: 5 * time.Second, } publisher, err := NewTCPPublisher(publisherConfig, testLogger) if err != nil { t.Fatalf("Failed to create publisher: %v", err) } defer publisher.Close() // 测试发送和接收消息 testPayload := []byte("Hello, TCP Watermill!") testMsg := message.NewMessage("test-msg-1", testPayload) // 启动接收协程 var wg sync.WaitGroup wg.Add(1) go func() { defer wg.Done() select { case receivedMsg := <-msgChan: if string(receivedMsg.Payload) != string(testPayload) { t.Errorf("Payload mismatch: got %s, want %s", receivedMsg.Payload, testPayload) } if receivedMsg.UUID != testMsg.UUID { t.Errorf("UUID mismatch: got %s, want %s", receivedMsg.UUID, testMsg.UUID) } // ACK 消息 receivedMsg.Ack() case <-time.After(5 * time.Second): t.Error("Timeout waiting for message") } }() // 发送消息 err = publisher.Publish(topic, testMsg) if err != nil { t.Fatalf("Failed to publish message: %v", err) } // 等待接收完成 wg.Wait() } func TestTCPPublisherSubscriber_MultipleMessages(t *testing.T) { testLogger := &testLogger{} // 创建 Subscriber subscriberConfig := TCPSubscriberConfig{ ListenAddr: "127.0.0.1:18081", } subscriber, err := NewTCPSubscriber(subscriberConfig, testLogger) if err != nil { t.Fatalf("Failed to create subscriber: %v", err) } defer subscriber.Close() time.Sleep(100 * time.Millisecond) // 订阅 ctx := context.Background() topic := "test-topic-multi" msgChan, err := subscriber.Subscribe(ctx, topic) if err != nil { t.Fatalf("Failed to subscribe: %v", err) } // 创建 Publisher publisherConfig := TCPPublisherConfig{ ServerAddr: "127.0.0.1:18081", ConnectTimeout: 5 * time.Second, } publisher, err := NewTCPPublisher(publisherConfig, testLogger) if err != nil { t.Fatalf("Failed to create publisher: %v", err) } defer publisher.Close() // 准备多条消息 messageCount := 10 messages := make([]*message.Message, messageCount) for i := 0; i < messageCount; i++ { payload := []byte("Message " + string(rune('0'+i))) messages[i] = message.NewMessage("msg-"+string(rune('0'+i)), payload) } // 启动接收协程 receivedCount := 0 var mu sync.Mutex var wg sync.WaitGroup for i := 0; i < messageCount; i++ { wg.Add(1) go func() { defer wg.Done() select { case receivedMsg := <-msgChan: mu.Lock() receivedCount++ mu.Unlock() receivedMsg.Ack() case <-time.After(10 * time.Second): t.Error("Timeout waiting for message") } }() } // 发送消息(并发发送) err = publisher.Publish(topic, messages...) if err != nil { t.Fatalf("Failed to publish messages: %v", err) } // 等待接收完成 wg.Wait() if receivedCount != messageCount { t.Errorf("Received count mismatch: got %d, want %d", receivedCount, messageCount) } } func TestTCPPublisherSubscriber_Nack(t *testing.T) { testLogger := &testLogger{} // 创建 Subscriber subscriberConfig := TCPSubscriberConfig{ ListenAddr: "127.0.0.1:18082", } subscriber, err := NewTCPSubscriber(subscriberConfig, testLogger) if err != nil { t.Fatalf("Failed to create subscriber: %v", err) } defer subscriber.Close() time.Sleep(100 * time.Millisecond) // 订阅 ctx := context.Background() topic := "test-topic-nack" msgChan, err := subscriber.Subscribe(ctx, topic) if err != nil { t.Fatalf("Failed to subscribe: %v", err) } // 创建 Publisher publisherConfig := TCPPublisherConfig{ ServerAddr: "127.0.0.1:18082", ConnectTimeout: 5 * time.Second, } publisher, err := NewTCPPublisher(publisherConfig, testLogger) if err != nil { t.Fatalf("Failed to create publisher: %v", err) } defer publisher.Close() // 准备消息 testMsg := message.NewMessage("nack-test", []byte("This will be nacked")) // 启动接收协程,这次 NACK var wg sync.WaitGroup wg.Add(1) go func() { defer wg.Done() select { case receivedMsg := <-msgChan: // NACK 消息 receivedMsg.Nack() case <-time.After(5 * time.Second): t.Error("Timeout waiting for message") } }() // 发送消息,由于不等待ACK,应该立即返回成功 // 注意:即使消费者NACK,发布者也会返回成功 err = publisher.Publish(topic, testMsg) if err != nil { t.Errorf("Expected no error (fire-and-forget), got: %v", err) } wg.Wait() }