81 lines
2.9 KiB
Go
81 lines
2.9 KiB
Go
package manifest
|
|
|
|
import (
|
|
"context"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
const testSemanticDigest = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
|
|
|
|
func TestSemanticConfigFingerprintRoundTripsAndLegacyRecordsRemainReadable(t *testing.T) {
|
|
ctx := context.Background()
|
|
store := &LocalStore{}
|
|
dir := t.TempDir()
|
|
fingerprint := &SemanticConfigFingerprint{Version: 3, Digest: testSemanticDigest}
|
|
|
|
session := New("session", time.Now().UTC())
|
|
session.MarkStageSucceeded("prepare", time.Now().UTC(), nil)
|
|
session.Stages["prepare"].SemanticConfig = fingerprint
|
|
sessionPath := filepath.Join(dir, "session.json")
|
|
if err := store.Save(ctx, sessionPath, session); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
loadedSession, err := store.Load(ctx, sessionPath)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if loadedSession.Stages["prepare"].SemanticConfig == nil || !loadedSession.Stages["prepare"].SemanticConfig.Equal(*fingerprint) {
|
|
t.Fatalf("session fingerprint = %#v", loadedSession.Stages["prepare"].SemanticConfig)
|
|
}
|
|
|
|
run := NewRun("session", "campaign", "run", false, []string{"prepare"}, time.Now().UTC())
|
|
run.MarkStageSucceeded("prepare", time.Now().UTC(), nil)
|
|
run.Stages["prepare"].SemanticConfig = fingerprint
|
|
runPath := filepath.Join(dir, "run.json")
|
|
if err := store.SaveRun(ctx, runPath, run); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
loadedRun, err := store.LoadRun(ctx, runPath)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if loadedRun.Stages["prepare"].SemanticConfig == nil || !loadedRun.Stages["prepare"].SemanticConfig.Equal(*fingerprint) {
|
|
t.Fatalf("run fingerprint = %#v", loadedRun.Stages["prepare"].SemanticConfig)
|
|
}
|
|
|
|
legacyPath := filepath.Join(dir, "legacy.json")
|
|
legacy := `{"session_id":"session","created_at":"2026-01-01T00:00:00Z","updated_at":"2026-01-01T00:00:00Z","stages":{"prepare":{"name":"prepare","status":"succeeded","created_at":"2026-01-01T00:00:00Z","updated_at":"2026-01-01T00:00:00Z"}}}`
|
|
if err := os.WriteFile(legacyPath, []byte(legacy), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
legacyManifest, err := store.Load(ctx, legacyPath)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if legacyManifest.Stages["prepare"].SemanticConfig != nil {
|
|
t.Fatalf("legacy fingerprint = %#v, want nil", legacyManifest.Stages["prepare"].SemanticConfig)
|
|
}
|
|
}
|
|
|
|
func TestSemanticConfigFingerprintValidation(t *testing.T) {
|
|
for _, test := range []struct {
|
|
name string
|
|
value SemanticConfigFingerprint
|
|
want string
|
|
}{
|
|
{name: "zero version", value: SemanticConfigFingerprint{Digest: testSemanticDigest}, want: "positive"},
|
|
{name: "uppercase digest", value: SemanticConfigFingerprint{Version: 1, Digest: strings.ToUpper(testSemanticDigest)}, want: "lowercase"},
|
|
{name: "short digest", value: SemanticConfigFingerprint{Version: 1, Digest: "abcd"}, want: "lowercase"},
|
|
} {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
if err := test.value.Validate(); err == nil || !strings.Contains(err.Error(), test.want) {
|
|
t.Fatalf("Validate() error = %v, want %q", err, test.want)
|
|
}
|
|
})
|
|
}
|
|
}
|