package domain import ( "testing" "git.cin.su/m/Assistant/contracts/capability" "git.cin.su/m/Assistant/contracts/identity" ) func validCandidateBinding() capability.CandidateBinding { context := capability.CandidateReleaseContext{ReleaseSetID: "assistant-slot-b", Slot: "b", TaskID: "GEN2-CAPABILITY-001", TaskRevision: 7, PrincipalID: identity.PrincipalID("owner-1"), CapabilityID: "prospective-notification-delivery", ResourceScope: "synthetic-shadow-notification-v1", Mode: capability.CandidateBindingModeShadow, TargetKind: "NOTIFICATION_SHADOW_RECEIVER", TargetRef: "notification-receiver-candidate", AuthorityGrantID: "grant-1"} binding := capability.CandidateBinding{ID: "candidate-binding-1", Revision: 1, BaseActiveBindingID: "stable-binding-1", BaseActiveBindingRevision: 1, Context: context, TargetOrigin: "http://notification-receiver-candidate:8085", DeliveryPath: "/delivery/v1/deliveries", ReceiptPath: "/delivery/v1/receipts", Protocol: capability.ProtocolIdempotentReceiptV1, CreatedAtUnixMillis: 10, ExpiresAtUnixMillis: 100, Status: capability.CandidateBindingActive} digest, err := CandidateTargetDigest(binding) if err != nil { panic(err) } binding.Context.TargetDigest = digest return binding } func TestCandidateBindingIsExactAndFailsClosed(t *testing.T) { binding := validCandidateBinding() if err := CandidateBindingInvocable(binding, binding.Context, 20); err != nil { t.Fatalf("valid candidate binding denied: %v", err) } for _, mutate := range []func(*capability.CandidateReleaseContext){ func(v *capability.CandidateReleaseContext) { v.ReleaseSetID = "assistant-slot-other" }, func(v *capability.CandidateReleaseContext) { v.TaskID = "GEN2-OTHER" }, func(v *capability.CandidateReleaseContext) { v.AuthorityGrantID = "other-grant" }, } { request := binding.Context mutate(&request) if err := CandidateBindingInvocable(binding, request, 20); err == nil { t.Fatal("mismatched candidate context was allowed") } } if err := CandidateBindingInvocable(binding, binding.Context, 100); err == nil { t.Fatal("expired candidate binding was allowed") } binding.Status = capability.CandidateBindingRevoked if err := CandidateBindingInvocable(binding, binding.Context, 20); err == nil { t.Fatal("revoked candidate binding was allowed") } } func TestCandidateTargetDigestBindsSemanticDescriptor(t *testing.T) { binding := validCandidateBinding() digest, err := CandidateTargetDigest(binding) if err != nil || digest != binding.Context.TargetDigest { t.Fatalf("digest=%q err=%v", digest, err) } if digest != "f9f9fa49a0727444c280c092d5bb340f3a8f33cf325c5396f5ae177a6666da35" { t.Fatalf("canonical descriptor digest changed: %q", digest) } changed := binding changed.Context.ResourceScope = "different-resource" other, err := CandidateTargetDigest(changed) if err != nil || other == digest { t.Fatalf("scope did not affect digest: %q %q err=%v", digest, other, err) } changed = binding changed.Revision++ other, err = CandidateTargetDigest(changed) if err != nil || other == digest { t.Fatalf("binding revision did not affect digest: %q %q err=%v", digest, other, err) } }