84 lines
4.4 KiB
Go
84 lines
4.4 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
|
|
"git.cin.su/m/Assistant/adapters/notificationexecutor"
|
|
"git.cin.su/m/Assistant/contracts/capability"
|
|
commitcontract "git.cin.su/m/Assistant/contracts/commit"
|
|
"git.cin.su/m/Assistant/contracts/identity"
|
|
)
|
|
|
|
type fakeNotificationBindings struct {
|
|
exact capability.Binding
|
|
active capability.Binding
|
|
exactErr error
|
|
activeErr error
|
|
}
|
|
|
|
func (f fakeNotificationBindings) CapabilityBinding(context.Context, capability.CapabilityBindingID, int64) (capability.Binding, error) {
|
|
return f.exact, f.exactErr
|
|
}
|
|
func (f fakeNotificationBindings) ActiveCapabilityBinding(context.Context, capability.CapabilityID, identity.PrincipalID) (capability.Binding, error) {
|
|
return f.active, f.activeErr
|
|
}
|
|
|
|
func dispatcherAction(t *testing.T, binding capability.Binding) commitcontract.AuthorizedAction {
|
|
t.Helper()
|
|
payload := notificationexecutor.Payload{ActionIntentID: "intent-1", TemplateCode: commitcontract.ProspectiveDeliveredTemplateV1, ProspectiveItemID: "item-1", ExpectedRevision: 1, Title: "Домовой", Message: "Пора вернуться"}
|
|
digest, err := notificationexecutor.Digest(payload)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return commitcontract.AuthorizedAction{PrincipalID: binding.OwnerPrincipalID, Proposal: commitcontract.ActionProposal{IntentID: payload.ActionIntentID, CapabilityID: commitcontract.CapabilityProspectiveNotification, Operation: commitcontract.OperationDeliverProspectiveNotification, NotificationSubject: commitcontract.ProspectiveNotificationSubject{ProspectiveItemID: "item-1", ExpectedRevision: 1, TemplateCode: payload.TemplateCode, BindingID: binding.ID, BindingRevision: binding.Revision, RenderedTitle: payload.Title, RenderedMessage: payload.Message, RequestDigest: digest}}}
|
|
}
|
|
|
|
func dispatcherBinding(origin string) capability.Binding {
|
|
return capability.Binding{ID: "binding-1", CapabilityID: commitcontract.CapabilityProspectiveNotification, OwnerPrincipalID: "owner-1", Revision: 1, State: capability.BindingActive, HTTPSOrigin: origin, DeliveryPath: "/delivery/v1/deliveries", ReceiptPath: "/delivery/v1/receipts", Protocol: capability.ProtocolIdempotentReceiptV1, SecretRef: "write-v1", VerifiedAtUnixMillis: 1, Health: capability.HealthAvailable}
|
|
}
|
|
|
|
func TestOperationDispatcherRequiresExactCurrentBinding(t *testing.T) {
|
|
var action commitcontract.AuthorizedAction
|
|
server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
_ = json.NewEncoder(w).Encode(notificationexecutor.Receipt{ReceiptID: "receipt-1", ActionIntentID: action.Proposal.IntentID, RequestDigest: action.Proposal.NotificationSubject.RequestDigest, AcceptedAt: 1})
|
|
}))
|
|
defer server.Close()
|
|
binding := dispatcherBinding(server.URL)
|
|
action = dispatcherAction(t, binding)
|
|
fallback := &knownExecutor{}
|
|
dispatcher := operationDispatcher{continuityExecutor: fallback, continuityReconciler: fallback, bindings: fakeNotificationBindings{exact: binding, active: binding}, secretRef: "write-v1", secret: "secret", client: server.Client()}
|
|
if result := dispatcher.Execute(action); !result.Known || !result.Succeeded {
|
|
t.Fatalf("execute=%+v", result)
|
|
}
|
|
stale := binding
|
|
stale.Revision = 2
|
|
dispatcher.bindings = fakeNotificationBindings{exact: binding, active: stale}
|
|
if result := dispatcher.Execute(action); !result.Known || result.Succeeded {
|
|
t.Fatalf("stale binding=%+v", result)
|
|
}
|
|
}
|
|
|
|
func TestOperationDispatcherReconcilesRetiredHistoricalBinding(t *testing.T) {
|
|
var action commitcontract.AuthorizedAction
|
|
server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != http.MethodGet {
|
|
t.Fatal("reconciliation mutated receiver")
|
|
}
|
|
_ = json.NewEncoder(w).Encode(notificationexecutor.Receipt{ReceiptID: "receipt-1", ActionIntentID: action.Proposal.IntentID, RequestDigest: action.Proposal.NotificationSubject.RequestDigest, AcceptedAt: 1})
|
|
}))
|
|
defer server.Close()
|
|
binding := dispatcherBinding(server.URL)
|
|
action = dispatcherAction(t, binding)
|
|
binding.State = capability.BindingRetired
|
|
binding.Revision = 1
|
|
fallback := &knownExecutor{}
|
|
dispatcher := operationDispatcher{continuityExecutor: fallback, continuityReconciler: fallback, bindings: fakeNotificationBindings{exact: binding}, secretRef: "write-v1", secret: "secret", client: server.Client()}
|
|
if result := dispatcher.Reconcile(action); !result.Known || !result.Succeeded {
|
|
t.Fatalf("reconcile=%+v", result)
|
|
}
|
|
}
|