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

88 lines
3.2 KiB
Go

package dispatcher
import (
"context"
"encoding/json"
"errors"
"io"
"log/slog"
"net/http"
"net/http/httptest"
"testing"
"git.ipao.vip/rogee/go-sip/internal/configread"
"git.ipao.vip/rogee/go-sip/internal/store"
)
func TestStartupAndSIPNotificationNeverLoadOverOccupiedOrUnknownCalls(t *testing.T) {
for _, outcome := range []string{"active", "unknown"} {
for _, phase := range []string{"startup", "notification"} {
t.Run(outcome+"/"+phase, func(t *testing.T) {
execute, originator, _, database := newExecuteFixture(t)
if outcome == "unknown" {
originator.err = context.DeadlineExceeded
}
err := execute.ProcessExecute(context.Background(), executeBody(t, "sip-load-occupied", "15003164745"))
if (outcome == "unknown") != (err != nil) {
t.Fatalf("unexpected isolated execution state: %v", err)
}
occupied, err := database.OccupiedCalls(execute.DispatcherID)
if err != nil || occupied != 1 {
t.Fatalf("occupied before update = %d, error = %v", occupied, err)
}
var snapshot configread.SIP
if err := json.Unmarshal(configExample(t, "config-read-sip"), &snapshot); err != nil {
t.Fatal(err)
}
snapshot.Revision = 9
body, err := json.Marshal(snapshot)
if err != nil {
t.Fatal(err)
}
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/internal/v1/dispatcher/sip" {
t.Errorf("occupied startup requested unrelated configuration: %s", r.URL.Path)
w.WriteHeader(http.StatusNotFound)
return
}
w.Header().Set("Content-Type", "application/json")
_, _ = w.Write(body)
}))
defer server.Close()
client, err := configread.NewClient(server.URL, execute.DispatcherID, "test-secret", server.Client())
if err != nil {
t.Fatal(err)
}
applied, verified := 0, 0
bootstrap := Bootstrap{
Client: client, Store: database, DispatcherID: execute.DispatcherID,
ApplySIP: func(context.Context, configread.SIP) error { applied++; return nil },
VerifySIP: func(context.Context, configread.SIP) error { verified++; return nil },
DrainControls: func(context.Context) error { return nil },
}
if phase == "startup" {
err = bootstrap.Run(context.Background())
} else {
if err := database.NoteSIPChange(execute.DispatcherID, 9); err != nil {
t.Fatal(err)
}
runtime := &Runtime{Bootstrap: bootstrap, Logger: slog.New(slog.NewTextHandler(io.Discard, nil))}
current := policySnapshot(t).SIP
err = runtime.refreshSIP(context.Background(), &current)
}
fenced := phase == "startup" && errors.Is(err, store.ErrSIPPending) || phase == "notification" && err == nil
if !fenced || applied != 0 || verified != 0 {
t.Fatalf("occupied SIP load was not fenced: error=%v applied=%d verified=%d", err, applied, verified)
}
occupied, err = database.OccupiedCalls(execute.DispatcherID)
if err != nil || occupied != 1 {
t.Fatalf("SIP update released occupied execution: %d %v", occupied, err)
}
if admitted, err := database.CanAdmit(execute.DispatcherID, 1001, "task-asr"); err != nil || admitted {
t.Fatalf("occupied SIP update reopened admission: %v %v", admitted, err)
}
})
}
}
}