Files
Assistant/adapters/continuityexecutor/executor_test.go
2026-08-16 16:19:23 +03:00

90 lines
3.2 KiB
Go

package continuityexecutor
import (
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
commitcontract "git.cin.su/m/Assistant/contracts/commit"
"git.cin.su/m/Assistant/contracts/continuity"
)
func TestExecuteAndReconcileUseTypedReceipt(t *testing.T) {
action := testAction()
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Header.Get("Authorization") != "Bearer secret" {
http.Error(w, "denied", http.StatusUnauthorized)
return
}
receipt := continuity.ActionReceipt{
ActionIntentID: continuity.CommittedActionIntentID(action.Proposal.IntentID), AuthorizedActionID: continuity.CommittedAuthorizedActionID(action.ID),
OwnerPrincipalID: action.PrincipalID, Subject: action.Proposal.ContinuitySubject,
ResultState: continuity.ProspectiveSatisfied, ResultRevision: 5,
}
_ = json.NewEncoder(w).Encode(receipt)
}))
defer server.Close()
adapter, err := New(server.URL, "secret", server.Client())
if err != nil {
t.Fatal(err)
}
if result := adapter.Execute(action); !result.Known || !result.Succeeded {
t.Fatalf("execute result = %#v", result)
}
if result := adapter.Reconcile(action); !result.Known || !result.Succeeded {
t.Fatalf("reconcile result = %#v", result)
}
}
func TestAcknowledgementLossReconcilesWithoutDuplicatePost(t *testing.T) {
action := testAction()
posts := 0
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method == http.MethodPost {
posts++
hijacker, ok := w.(http.Hijacker)
if !ok {
t.Fatal("test server cannot simulate acknowledgement loss")
}
connection, _, err := hijacker.Hijack()
if err != nil {
t.Fatal(err)
}
_ = connection.Close()
return
}
receipt := continuity.ActionReceipt{
ActionIntentID: continuity.CommittedActionIntentID(action.Proposal.IntentID), AuthorizedActionID: continuity.CommittedAuthorizedActionID(action.ID),
OwnerPrincipalID: action.PrincipalID, Subject: action.Proposal.ContinuitySubject,
ResultState: continuity.ProspectiveSatisfied, ResultRevision: 5,
}
_ = json.NewEncoder(w).Encode(receipt)
}))
defer server.Close()
adapter, err := New(server.URL, "secret", server.Client())
if err != nil {
t.Fatal(err)
}
if result := adapter.Execute(action); result.Known {
t.Fatalf("lost acknowledgement was treated as known: %#v", result)
}
if result := adapter.Reconcile(action); !result.Known || !result.Succeeded {
t.Fatalf("reconciliation result = %#v", result)
}
if posts != 1 {
t.Fatalf("effect was posted %d times", posts)
}
}
func testAction() commitcontract.AuthorizedAction {
return commitcontract.AuthorizedAction{
ID: "authorized-1", PrincipalID: "principal-1", State: commitcontract.ActionAuthorized,
Proposal: commitcontract.ActionProposal{
IntentID: "intent-1", CapabilityID: commitcontract.CapabilityContinuityTransition,
Operation: commitcontract.OperationSatisfyDelivered,
ContinuitySubject: continuity.SatisfyDeliveredSubject{ProspectiveItemID: "prospective-1", ExpectedRevision: 4, FromState: continuity.ProspectiveDelivered, ToState: continuity.ProspectiveSatisfied, EvidenceRef: "artifact://evidence/1"},
},
}
}