Files
go-sip/cmd/saas-server/shared_vhost_integration_test.go
T

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")
}