Keep registry key validation local to workflowdef with composition-root injection, adapt FlatCatalog for projectworkflow, and drive the orchestrator through LiveInstancePort views instead of projectinstance.
105 lines
3.1 KiB
Go
105 lines
3.1 KiB
Go
package workflowdef
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestOfficialWorkflowKeys(t *testing.T) {
|
|
keys := OfficialWorkflowKeys()
|
|
if len(keys) != 6 {
|
|
t.Fatalf("expected 6 official keys, got %d", len(keys))
|
|
}
|
|
for _, k := range keys {
|
|
if !IsOfficialWorkflowKey(k) {
|
|
t.Fatalf("key %q not official", k)
|
|
}
|
|
}
|
|
if len(MedicalWorkflowKeys()) != 4 {
|
|
t.Fatalf("expected 4 medical keys")
|
|
}
|
|
if len(SoftwareWorkflowKeys()) != 2 {
|
|
t.Fatalf("expected 2 software keys")
|
|
}
|
|
if OfficialCatalogOrder(OfficialKeyRDev) != 40 {
|
|
t.Fatalf("rdev catalog_order want 40")
|
|
}
|
|
if OfficialCatalogOrder(OfficialKeySoftwareBootstrap) != 50 {
|
|
t.Fatalf("software_bootstrap catalog_order want 50")
|
|
}
|
|
if !CompatibleWithProductDomain(OfficialKeyRDev, "medical_device") {
|
|
t.Fatal("rdev should accept medical_device")
|
|
}
|
|
if CompatibleWithProductDomain(OfficialKeyRDev, "non_medical_software") {
|
|
t.Fatal("rdev must reject non_medical_software")
|
|
}
|
|
}
|
|
|
|
func TestCompatibleWithProductDomain(t *testing.T) {
|
|
if !CompatibleWithProductDomain(OfficialKeyMain, "medical_device") {
|
|
t.Fatal("main should accept medical_device")
|
|
}
|
|
if !CompatibleWithProductDomain(OfficialKeySoftwareBootstrap, "non_medical_software") {
|
|
t.Fatal("software_bootstrap should accept non_medical_software")
|
|
}
|
|
if CompatibleWithProductDomain(OfficialKeySoftwareBootstrap, "medical_device") {
|
|
t.Fatal("software_bootstrap must reject medical_device")
|
|
}
|
|
if !CompatibleWithProductDomain(OfficialKeySoftwareDelivery, "") {
|
|
t.Fatal("empty domain should not filter")
|
|
}
|
|
}
|
|
|
|
func TestValidateDefinitionV2_OfficialDocCounts(t *testing.T) {
|
|
def, err := LoadManifestDefinition("main.v2.json")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
normalizeManifestDefinition(&def)
|
|
res := ValidateDefinitionV2(def, nil, nil)
|
|
if !res.Valid {
|
|
t.Fatalf("main v2 invalid: %+v", res.Issues)
|
|
}
|
|
}
|
|
|
|
func TestValidateDefinitionV2_SoftwareManifests(t *testing.T) {
|
|
medicalTerms := []string{"临床", "nmpa", "注册检验", "gb 9706", "cdmo", "疗效"}
|
|
for _, file := range []string{"software_bootstrap.v2.json", "software_delivery.v2.json"} {
|
|
def, err := LoadManifestDefinition(file)
|
|
if err != nil {
|
|
t.Fatalf("%s: %v", file, err)
|
|
}
|
|
normalizeManifestDefinition(&def)
|
|
res := ValidateDefinitionV2(def, nil, nil)
|
|
if !res.Valid {
|
|
t.Fatalf("%s invalid: %+v", file, res.Issues)
|
|
}
|
|
for _, st := range def.Stages {
|
|
for _, dt := range st.DocTasks {
|
|
blob := strings.ToLower(dt.Title + " " + dt.OutputDocTitle + " " + dt.Key)
|
|
for _, bad := range medicalTerms {
|
|
if strings.Contains(blob, strings.ToLower(bad)) {
|
|
t.Fatalf("%s task %s contains medical term %q", file, dt.Key, bad)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestValidateDefinitionV2_RejectsUpstream(t *testing.T) {
|
|
def := VersionDefinition{
|
|
SchemaVersion: 2,
|
|
WorkflowKey: OfficialKeyTestManager,
|
|
RequiredUpstreamWorkflow: "product_manager",
|
|
Stages: []StageDef{{
|
|
Key: "s", Position: 10,
|
|
DocTasks: []DocTaskDef{{Key: "test_manager", OutputDocType: "test_manager", ExecutorKey: "squad.test_manager.v1"}},
|
|
}},
|
|
}
|
|
res := ValidateDefinitionV2(def, nil, nil)
|
|
if res.Valid {
|
|
t.Fatal("expected upstream rejection")
|
|
}
|
|
}
|