package configread import ( "os" "strings" "testing" ) func TestExecutionBindingSHA256CoversTaskProvidersAndSIPRevision(t *testing.T) { task, err := os.ReadFile("../../contracts/local/examples/config-read-task-full.json") if err != nil { t.Fatal(err) } providers, err := os.ReadFile("../../contracts/local/examples/config-read-providers.json") if err != nil { t.Fatal(err) } original, err := ExecutionBindingSHA256(task, providers, 8) if err != nil || len(original) != 64 { t.Fatalf("binding hash: %q %v", original, err) } changedTask := append(append([]byte(nil), task...), ' ') changedProviders := append(append([]byte(nil), providers...), ' ') for _, tc := range []struct { name string task []byte providers []byte revision int64 }{ {"task", changedTask, providers, 8}, {"providers", task, changedProviders, 8}, {"sip-revision", task, providers, 9}, } { t.Run(tc.name, func(t *testing.T) { got, err := ExecutionBindingSHA256(tc.task, tc.providers, tc.revision) if err != nil || got == original { t.Fatalf("snapshot field not bound: %q %v", got, err) } }) } for _, tc := range []struct { task, providers []byte revision int64 }{ {nil, providers, 8}, {task, nil, 8}, {[]byte(`not-json`), providers, 8}, {task, providers, 0}, } { if _, err := ExecutionBindingSHA256(tc.task, tc.providers, tc.revision); err == nil || strings.Contains(err.Error(), "example-only-not-a-real-secret") { t.Fatalf("invalid binding must be rejected without printing provider credentials: %v", err) } } }