Files
sanderling/cmd/internal-tools/campaign/manifest_test.go
T
pj ebed84afc3 feat(campaign): record the label source in the manifest
A finished sweep should say which cell it ran without anyone having to
remember the invocation.

Claude-Session: https://claude.ai/code/session_01A5KmftdEJ49A9z5mF5ESrX
2026-08-15 13:32:05 +05:30

95 lines
2.9 KiB
Go

package main
import (
"encoding/json"
"io"
"os"
"path/filepath"
"slices"
"testing"
"time"
)
func TestBuildManifest_RecordsIntendedRunsAndTemplate(t *testing.T) {
configuration, err := parseArguments(append(baseArguments(), "--devices", "a,b", "--duration", "90s"), io.Discard)
if err != nil {
t.Fatal(err)
}
startedAt := time.Date(2026, 8, 12, 9, 0, 0, 0, time.UTC)
value := buildManifest(configuration, "worker-7", "/usr/local/bin/sanderling", "1.4.2", startedAt)
if !slices.Equal(value.Seeds, []int64{1, 2, 3}) {
t.Errorf("seeds: got %v", value.Seeds)
}
if value.Host != "worker-7" || value.SanderlingVersion != "1.4.2" || value.SanderlingPath != "/usr/local/bin/sanderling" {
t.Errorf("provenance: %+v", value)
}
if value.DurationMillis != 90_000 || value.MaxSteps != 300 {
t.Errorf("budget: duration=%d max_steps=%d", value.DurationMillis, value.MaxSteps)
}
if !value.StartedAt.Equal(startedAt) {
t.Errorf("started_at: got %s", value.StartedAt)
}
if got := argumentValue(value.ArgumentTemplate, "--seed"); got != seedPlaceholder {
t.Errorf("template seed: got %q, want %q", got, seedPlaceholder)
}
if got := argumentValue(value.ArgumentTemplate, "--device"); got != devicePlaceholder {
t.Errorf("template device: got %q, want %q", got, devicePlaceholder)
}
if got := argumentValue(value.ArgumentTemplate, "--output"); got != "/campaigns/a/seed-"+seedPlaceholder {
t.Errorf("template output: got %q", got)
}
}
func TestWriteManifest_RecordsTheLabelSourceCell(t *testing.T) {
configuration, err := parseArguments(append(baseArguments(), "--label-source", "resource-id"), io.Discard)
if err != nil {
t.Fatal(err)
}
directory := t.TempDir()
if err := writeManifest(directory, buildManifest(configuration, "host", "sanderling", "dev", time.Now())); err != nil {
t.Fatal(err)
}
body, err := os.ReadFile(filepath.Join(directory, manifestFileName))
if err != nil {
t.Fatal(err)
}
var decoded struct {
LabelSource string `json:"label_source"`
}
if err := json.Unmarshal(body, &decoded); err != nil {
t.Fatal(err)
}
if decoded.LabelSource != "resource-id" {
t.Errorf("label_source: got %q, want resource-id", decoded.LabelSource)
}
}
func TestBuildManifest_EmptyDeviceListSerializesAsArray(t *testing.T) {
configuration, err := parseArguments(baseArguments(), io.Discard)
if err != nil {
t.Fatal(err)
}
directory := t.TempDir()
if err := writeManifest(directory, buildManifest(configuration, "host", "sanderling", "dev", time.Now())); err != nil {
t.Fatal(err)
}
body, err := os.ReadFile(filepath.Join(directory, manifestFileName))
if err != nil {
t.Fatal(err)
}
var decoded struct {
Devices []string `json:"devices"`
Arm string `json:"arm"`
}
if err := json.Unmarshal(body, &decoded); err != nil {
t.Fatal(err)
}
if decoded.Devices == nil || len(decoded.Devices) != 0 {
t.Errorf("devices: got %v, want []", decoded.Devices)
}
if decoded.Arm != "seeded-baseline" {
t.Errorf("arm: got %q", decoded.Arm)
}
}