114 lines
3.6 KiB
Go
114 lines
3.6 KiB
Go
//go:build integration
|
|
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"os"
|
|
"testing"
|
|
"time"
|
|
|
|
"git.ipao.vip/rogee/go-sip/internal/mq"
|
|
amqp "github.com/rabbitmq/amqp091-go"
|
|
)
|
|
|
|
func TestSharedVhostDoesNotConsumeFormalFeedback(t *testing.T) {
|
|
address := os.Getenv("SAAS_MOCK_TEST_BROKER_URL")
|
|
if address == "" {
|
|
t.Skip("requires isolated test broker")
|
|
}
|
|
dir, id := fixture(t)
|
|
source, err := loadSnapshots(dir, id)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
data, err := testSnapshots(source)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
b, err := connectBroker(address, data)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer b.conn.Close()
|
|
ch, err := b.conn.Channel()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer ch.Close()
|
|
if err = ch.Confirm(false); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
confirms := ch.NotifyPublish(make(chan amqp.Confirmation, 2))
|
|
returns := ch.NotifyReturn(make(chan amqp.Return, 1))
|
|
publishCtx, stopPublish := context.WithTimeout(context.Background(), 5*time.Second)
|
|
defer stopPublish()
|
|
formalQueue := "agent-call.saas.d." + source.dispatcherID + ".v1"
|
|
if _, err = ch.QueueDeclare(formalQueue, true, false, false, false, nil); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err = ch.QueueBind(formalQueue, "d."+source.dispatcherID+".out", mq.ResultsExchange, false, nil); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
raw, err := os.ReadFile("../../contracts/schema/examples/mq-execute-ack.json")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err = ch.PublishWithContext(context.Background(), mq.ResultsExchange, "d."+source.dispatcherID+".out", true, false, amqp.Publishing{ContentType: "application/json", DeliveryMode: amqp.Persistent, Body: raw}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
// Publishing and a passive declare alone do not prove the message was queued.
|
|
if _, err = awaitConfirm(publishCtx, confirms, returns); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
before, err := ch.QueueDeclarePassive(formalQueue, true, false, false, false, nil)
|
|
if err != nil || before.Messages != 1 {
|
|
t.Fatalf("formal setup: %+v %v", before, err)
|
|
}
|
|
s := newService(data, "test-secret")
|
|
s.feedbackDir = t.TempDir()
|
|
s.publish = b.publish
|
|
if _, err = s.send(context.Background(), "call.execute", commandInput{EventID: "test-call-example", TaskID: "test-1", Callee: "123456"}, time.Now()); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
defer cancel()
|
|
done := make(chan error, 1)
|
|
go func() { done <- b.consume(ctx, s) }()
|
|
var msg envelope
|
|
json.Unmarshal(raw, &msg)
|
|
msg.DispatcherID = data.dispatcherID
|
|
msg.TenantID = data.tenantID
|
|
msg.EventID = "test-call-example"
|
|
raw, _ = json.Marshal(msg)
|
|
if err = ch.PublishWithContext(ctx, mq.ResultsExchange, "d."+data.dispatcherID+".out", true, false, amqp.Publishing{ContentType: "application/json", DeliveryMode: amqp.Persistent, Body: raw}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, err = awaitConfirm(publishCtx, confirms, returns); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
deadline := time.Now().Add(5 * time.Second)
|
|
for len(s.events("test-call-example")) == 0 && time.Now().Before(deadline) {
|
|
time.Sleep(10 * time.Millisecond)
|
|
}
|
|
records := s.events("test-call-example")
|
|
if len(records) != 1 || records[0].Validation != "valid" {
|
|
t.Fatalf("test feedback: %+v", records)
|
|
}
|
|
after, err := ch.QueueDeclarePassive(formalQueue, true, false, false, false, nil)
|
|
if err != nil || after.Messages != 2 || after.Consumers != 0 {
|
|
t.Fatalf("formal original or independent copy was consumed: %+v %v", after, err)
|
|
}
|
|
cancel()
|
|
select {
|
|
case err = <-done:
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
case <-time.After(5 * time.Second):
|
|
t.Fatal("consumer did not stop")
|
|
}
|
|
t.Log("same vhost and Dispatcher ID; test tenant offset/task prefix/private feedback queue; formal messages not consumed")
|
|
}
|