Files
go-sip/internal/dispatcher/sip_runtime_test.go
T

84 lines
2.8 KiB
Go

package dispatcher
import (
"context"
"encoding/json"
"errors"
"log/slog"
"net/http"
"net/http/httptest"
"strings"
"sync/atomic"
"testing"
"git.ipao.vip/rogee/go-sip/internal/configread"
)
func TestSIPNotificationPersistsBarrierAndWaitsForLoadedFullSnapshot(t *testing.T) {
executor, _, _, s := newExecuteFixture(t)
approved := policySnapshot(t).SIP
changed := approved
changed.Revision = 9
newSIP, err := json.Marshal(changed)
if err != nil {
t.Fatal(err)
}
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
var body []byte
switch r.URL.Path {
case "/internal/v1/dispatcher/sip":
body = newSIP
default:
t.Errorf("unexpected HTTP path %s", r.URL.Path)
w.WriteHeader(http.StatusNotFound)
return
}
_, _ = w.Write(body)
}))
defer server.Close()
client, err := configread.NewClient(server.URL, executor.DispatcherID, "test-secret", server.Client())
if err != nil {
t.Fatal(err)
}
var loaded atomic.Bool
verify := func(_ context.Context, sip configread.SIP) error {
if sip.Revision != 9 || !loaded.Load() {
return errors.New("Agent and Asterisk have not applied SIP revision 9")
}
return nil
}
runtime := &Runtime{Bootstrap: Bootstrap{DispatcherID: executor.DispatcherID, Client: client, Store: s, VerifySIP: verify}, Logger: slog.Default()}
body := []byte(strings.Replace(string(configExample(t, "mq-sip-change")), `"revision":8`, `"revision":9`, 1))
if err := runtime.handleControl(context.Background(), "", body); err != nil {
t.Fatal(err)
}
if admitted, err := s.CanAdmit(executor.DispatcherID, 1001, "task-asr"); err != nil || admitted {
t.Fatalf("SIP notification did not close admission: %v %v", admitted, err)
}
if applied, pending, err := s.SIPState(executor.DispatcherID); err != nil || applied != 8 || pending != 9 {
t.Fatalf("notification not durable before ACK: %d %d %v", applied, pending, err)
}
if err := runtime.refreshSIP(context.Background(), &approved); err != nil {
t.Fatal(err)
}
if admitted, err := s.CanAdmit(executor.DispatcherID, 1001, "task-asr"); err != nil || admitted {
t.Fatalf("unloaded SIP reopened admission: %v %v", admitted, err)
}
loaded.Store(true)
if err := runtime.refreshSIP(context.Background(), &approved); err != nil {
t.Fatal(err)
}
if admitted, err := s.CanAdmit(executor.DispatcherID, 1001, "task-asr"); err != nil || !admitted {
t.Fatalf("verified SIP did not reopen: %v %v", admitted, err)
}
if approved.Revision != 9 {
t.Fatalf("reloaded SIP not bound: rev=%d", approved.Revision)
}
bound, err := s.ReadSnapshot(executor.DispatcherID, 1001, "task-asr")
if err != nil || bound.SIP.Revision != 9 {
t.Fatalf("existing task did not inherit the approved SIP revision: %+v %v", bound.SIP, err)
}
}