package mq import ( "bytes" "context" "errors" "log/slog" "strings" "testing" "git.ipao.vip/rogee/go-sip/internal/logging" amqp "github.com/rabbitmq/amqp091-go" ) type logAck struct { acks, rejects, nacks int err error } func (a *logAck) Ack(uint64, bool) error { a.acks++; return a.err } func (a *logAck) Nack(uint64, bool, bool) error { a.nacks++; return a.err } func (a *logAck) Reject(uint64, bool) error { a.rejects++; return a.err } func TestMQReceiveAndDispositionLogsPreserveMessageAndErrors(t *testing.T) { for _, debug := range []bool{false, true} { t.Run(map[bool]string{false: "normal", true: "debug"}[debug], func(t *testing.T) { prior := slog.Default() defer slog.SetDefault(prior) var out bytes.Buffer logging.Configure("dispatcher", debug, &out) body := []byte(`{ "event_id":"event-1", "event_type":"call.execute", "payload":{"task_id":"4","callee":"12345"},"api_key":"private"}`) original := bytes.Clone(body) ack := &logAck{} delivery := amqp.Delivery{Body: body, MessageId: "event-1", DeliveryTag: 1, Acknowledger: ack} observeDelivery(context.Background(), "task-4", &delivery) if !bytes.Equal(delivery.Body, original) { t.Fatal("message changed") } if err := delivery.Ack(false); err != nil || ack.acks != 1 { t.Fatal(err, ack) } expected := errors.New("ack transport failed") ack.err = expected if err := delivery.Reject(false); !errors.Is(err, expected) || ack.rejects != 1 { t.Fatal("disposition error lost", err) } text := out.String() for _, part := range []string{"received", "ack_sent", "reject_sent", "ack transport failed", "event-1", "task-4"} { if !strings.Contains(text, part) { t.Fatalf("missing %s: %s", part, text) } } if strings.Contains(text, "private") { t.Fatal(text) } if strings.Contains(text, `\"callee\":\"12345\"`) != debug { t.Fatal("mode failed", text) } }) } } func TestMQRejectedPublishDoesNotClaimConfirmation(t *testing.T) { previous := slog.Default() defer slog.SetDefault(previous) var out bytes.Buffer logging.Configure("dispatcher", true, &out) b := &Broker{} if err := b.Publish(context.Background(), "invalid", "invalid", []byte(`{"api_key":"private"}`)); err == nil { t.Fatal("invalid publish accepted") } text := out.String() if strings.Contains(text, "private") || strings.Contains(text, "publisher_confirmed") || !strings.Contains(text, "publish_failed") { t.Fatal(text) } }