148 lines
4.5 KiB
Go
148 lines
4.5 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
|
|
"git.ipao.vip/rogee/go-sip/internal/configread"
|
|
)
|
|
|
|
const testDispatcher = "c046b893-8628-4589-ae50-619d049248a6"
|
|
|
|
func testDataDir(t *testing.T) string {
|
|
t.Helper()
|
|
root := t.TempDir()
|
|
if err := os.Mkdir(filepath.Join(root, "tasks"), 0700); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for target, source := range map[string]string{
|
|
"sip.json": "config-read-sip.json",
|
|
"providers.json": "config-read-providers.json",
|
|
"quota.json": "config-read-quota.json",
|
|
"tasks/task-full.json": "config-read-task-full.json",
|
|
} {
|
|
original, err := os.ReadFile(filepath.Join("..", "..", "..", "contracts", "local", "examples", source))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.WriteFile(filepath.Join(root, target), original, 0600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
return root
|
|
}
|
|
|
|
func TestSaaSMockServesFormalReadContract(t *testing.T) {
|
|
data, err := loadDataset(testDataDir(t), testDispatcher)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
server := httptest.NewServer(data.handler("test-only-secret"))
|
|
defer server.Close()
|
|
client, err := configread.NewClient(server.URL, testDispatcher, "test-only-secret", server.Client())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
ctx := context.Background()
|
|
sip, err := client.ReadSIP(ctx)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
providers, err := client.ReadProviders(ctx)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
tasks, cursor, err := client.ReadAllTasks(ctx)
|
|
if err != nil || len(tasks) != 1 || tasks[0].TaskID != "task-full" || cursor == "" {
|
|
t.Fatalf("formal task discovery: count=%d cursor=%q err=%v", len(tasks), cursor, err)
|
|
}
|
|
snapshot, err := client.ReadTask(ctx, "task-full", 1001, sip, providers)
|
|
if err != nil || snapshot.Task.TaskID != "task-full" || snapshot.Quota.TenantID != snapshot.Task.TenantID {
|
|
t.Fatalf("formal task/quota read: task=%q quota=%d err=%v", snapshot.Task.TaskID, snapshot.Quota.TenantID, err)
|
|
}
|
|
if _, err := client.ReadTask(ctx, "absent", 1001, sip, providers); err == nil {
|
|
t.Fatal("unknown task must fail closed")
|
|
}
|
|
wrong, err := configread.NewClient(server.URL, testDispatcher, "wrong-secret", server.Client())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, err := wrong.ReadSIP(ctx); err == nil || !strings.Contains(err.Error(), "HTTP 403") {
|
|
t.Fatalf("wrong dispatcher identity should be rejected: %v", err)
|
|
}
|
|
request, err := http.NewRequest(http.MethodPost, server.URL+"/internal/v1/dispatcher/sip", nil)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
request.Header.Set("X-DISPATCHER-id", testDispatcher)
|
|
request.Header.Set("X-DISPATCHER-SECRET-KEY", "test-only-secret")
|
|
response, err := server.Client().Do(request)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer response.Body.Close()
|
|
if response.StatusCode != http.StatusMethodNotAllowed {
|
|
t.Fatalf("configuration must stay read-only: HTTP %d", response.StatusCode)
|
|
}
|
|
}
|
|
|
|
func TestSaaSMockDiscoversSixDistinctTasks(t *testing.T) {
|
|
root := testDataDir(t)
|
|
original, err := os.ReadFile(filepath.Join(root, "tasks", "task-full.json"))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for n := 2; n <= 6; n++ {
|
|
var task map[string]any
|
|
if err := json.Unmarshal(original, &task); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
id := fmt.Sprintf("task-%d", n)
|
|
task["task_id"] = id
|
|
body, err := json.Marshal(task)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.WriteFile(filepath.Join(root, "tasks", id+".json"), body, 0600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
data, err := loadDataset(root, testDispatcher)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
server := httptest.NewServer(data.handler("test-only-secret"))
|
|
defer server.Close()
|
|
client, err := configread.NewClient(server.URL, testDispatcher, "test-only-secret", server.Client())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
tasks, cursor, err := client.ReadAllTasks(context.Background())
|
|
if err != nil || len(tasks) != 6 || cursor != "mock-complete" {
|
|
t.Fatalf("six independent formal tasks were not discovered: count=%d cursor=%q err=%v", len(tasks), cursor, err)
|
|
}
|
|
}
|
|
|
|
func TestSaaSMockRejectsInvalidOwnerAtStartup(t *testing.T) {
|
|
root := testDataDir(t)
|
|
path := filepath.Join(root, "tasks", "task-full.json")
|
|
original, err := os.ReadFile(path)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
bad := strings.Replace(string(original), testDispatcher, "00000000-0000-4000-8000-000000000000", 1)
|
|
if err := os.WriteFile(path, []byte(bad), 0600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, err := loadDataset(root, testDispatcher); err == nil {
|
|
t.Fatal("a task assigned to another dispatcher cannot be served")
|
|
}
|
|
}
|