Published manifests now use bd_/pm_/tm_/sw_ prefixes so workflows cannot share a doc id. Frozen instances keep the old keys; lookup, templates, and duty checks treat the two names as the same task. Co-authored-by: Cursor <cursoragent@cursor.com>
94 lines
2.7 KiB
Go
94 lines
2.7 KiB
Go
package workflowdef
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestSameTaskKey_LegacyAndCanonical(t *testing.T) {
|
|
pairs := [][2]string{
|
|
{"intake", "bd_intake"},
|
|
{"system_reqs", "pm_system_reqs"},
|
|
{"test_manager", "tm_system_verification"},
|
|
{"software_charter", "sw_software_charter"},
|
|
{"change_brief", "sw_change_brief"},
|
|
}
|
|
for _, pair := range pairs {
|
|
if !SameTaskKey(pair[0], pair[1]) {
|
|
t.Fatalf("expected %s == %s", pair[0], pair[1])
|
|
}
|
|
if CanonicalTaskKey(pair[0]) != pair[1] {
|
|
t.Fatalf("canonical %s = %s, want %s", pair[0], CanonicalTaskKey(pair[0]), pair[1])
|
|
}
|
|
if ImplementationTaskKey(pair[1]) != pair[0] {
|
|
t.Fatalf("implementation %s = %s, want %s", pair[1], ImplementationTaskKey(pair[1]), pair[0])
|
|
}
|
|
}
|
|
if SameTaskKey("intake", "research") {
|
|
t.Fatal("intake and research must stay distinct")
|
|
}
|
|
if CanonicalTaskKey("rd_proposal") != "rd_proposal" {
|
|
t.Fatal("rd_ keys are already namespaced")
|
|
}
|
|
}
|
|
|
|
func TestAlternateDocIDs_RoundTrip(t *testing.T) {
|
|
alts := AlternateDocIDs("doc_proj56_intake")
|
|
if len(alts) != 1 || alts[0] != "doc_proj56_bd_intake" {
|
|
t.Fatalf("old id aliases = %v", alts)
|
|
}
|
|
back := AlternateDocIDs("doc_proj56_bd_intake")
|
|
if len(back) != 1 || back[0] != "doc_proj56_intake" {
|
|
t.Fatalf("new id aliases = %v", back)
|
|
}
|
|
if got := AlternateDocIDs("doc_proj56_rd_proposal"); len(got) != 0 {
|
|
t.Fatalf("rd_ doc id should not alias, got %v", got)
|
|
}
|
|
}
|
|
|
|
func TestPublishedTaskKeysAreNamespacedAndDisjoint(t *testing.T) {
|
|
files := map[string]string{
|
|
"main.v2.json": "bd_",
|
|
"product_manager.v2.json": "pm_",
|
|
"test_manager.v2.json": "tm_",
|
|
"rdev.v2.json": "rd_",
|
|
"software_bootstrap.v2.json": "sw_",
|
|
"software_delivery.v2.json": "sw_",
|
|
}
|
|
seen := map[string]string{}
|
|
for file, prefix := range files {
|
|
def, err := LoadManifestDefinition(file)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for _, stage := range def.Stages {
|
|
for _, task := range stage.DocTasks {
|
|
key := task.Key
|
|
if !strings.HasPrefix(key, prefix) {
|
|
t.Fatalf("%s task %s missing prefix %s", file, key, prefix)
|
|
}
|
|
if prev, ok := seen[key]; ok {
|
|
t.Fatalf("task key %s intersects %s and %s", key, prev, file)
|
|
}
|
|
seen[key] = file
|
|
if task.OutputDocType != key {
|
|
t.Fatalf("%s output_doc_type %s != key %s", file, task.OutputDocType, key)
|
|
}
|
|
if prefix == "rd_" {
|
|
if ImplementationTaskKey(key) != key {
|
|
t.Fatalf("rd_ key %s must not alias", key)
|
|
}
|
|
continue
|
|
}
|
|
legacy := ImplementationTaskKey(key)
|
|
if legacy == key {
|
|
t.Fatalf("%s has no legacy alias", key)
|
|
}
|
|
if CanonicalTaskKey(legacy) != key {
|
|
t.Fatalf("legacy %s does not round-trip to %s", legacy, key)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|