Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions pyoaev/apis/signature.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ def send_signatures(
return

sig_data = json.loads(payload["execution_output_structured"])
targets = sig_data["signatures"]["targets"]
targets = sig_data["expectation_signatures"]["targets"]
envelopes = self._split_into_envelopes(
payload,
sig_data,
Expand Down Expand Up @@ -199,8 +199,8 @@ def _build_envelope(
targets_subset: list[dict[str, Any]],
) -> dict[str, Any]:
subset_sig = dict(sig_data)
subset_sig["signatures"] = dict(sig_data["signatures"])
subset_sig["signatures"]["targets"] = targets_subset
subset_sig["expectation_signatures"] = dict(sig_data["expectation_signatures"])
subset_sig["expectation_signatures"]["targets"] = targets_subset

envelope = dict(base_payload)
envelope["execution_output_structured"] = json.dumps(subset_sig)
Expand Down
16 changes: 8 additions & 8 deletions pyoaev/signatures/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,15 +122,15 @@ class SignatureOutputStructure(BaseModel):

model_config = ConfigDict(populate_by_name=True, extra="forbid")

signatures: SignaturePayload
expectation_signatures: SignaturePayload

def normalize_signature_payload(self) -> None:
"""
Regroup signature_values by expectation_type within each target.
"""
normalized_targets: list[TargetSignatures] = []

for target in self.signatures.targets:
for target in self.expectation_signatures.targets:
if not target.signature_values:
normalized_targets.append(target)
continue
Expand All @@ -156,7 +156,7 @@ def normalize_signature_payload(self) -> None:

normalized_targets.append(normalized_target)

self.signatures.targets = normalized_targets
self.expectation_signatures.targets = normalized_targets


class ExecutionDetails(BaseModel):
Expand Down Expand Up @@ -191,19 +191,19 @@ def post_execution_update(self, tool_output: ToolOutput, now: datetime) -> None:
self.end_time = now

if tool_output.error_info and tool_output.error_info.exit_code != 0:
self.execution_status = "failed"
self.execution_status = "ERROR"
if tool_output.error_info.crash_timestamp:
self.end_time = datetime.strptime(
tool_output.error_info.crash_timestamp, "%Y-%m-%dT%H:%M:%SZ"
)
elif tool_output.timeout_info:
self.execution_status = "timeout"
self.execution_status = "TIMEOUT"
elif tool_output.status == "partial":
self.execution_status = "partial"
self.execution_status = "ERROR"
else:
self.execution_status = "success"
self.execution_status = "EXECUTED"

self.execution_action = InjectExecutionActions("complete")
self.execution_action = InjectExecutionActions("command_execution")


class SignatureCallbackPayload(BaseModel):
Expand Down
4 changes: 3 additions & 1 deletion pyoaev/signatures/signature_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,9 @@ def send_signatures(
Raises:
SignatureTransmissionError: Validation failed, 4xx hit, or retries exhausted.
"""
sig_output = SignatureOutputStructure(signatures=SignaturePayload(**signatures))
sig_output = SignatureOutputStructure(
expectation_signatures=SignaturePayload(**signatures)
)

self.client.signature.send_signatures(
inject_id,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,22 @@ Feature: SignatureManager post-execution constraints
Scenario: Tool crash sets execution_status to failed and uses crash timestamp as end_time
Given a tool_output containing error_info with exit_code=1 and crash_timestamp="2024-06-26T06:05:00Z"
When I call post_execution_updates with the execution_details, execution_signatures and tool_output
Then execution_status equals "failed"
Then execution_status equals "ERROR"
And end_time equals "2024-06-26T06:05:00Z"
And the execution signature model contains every previous parameter unchanged
And the execution details model contain every previous parameter pair unchanged

Scenario: Timeout sets execution_status to timeout and includes available partial results
Given a tool_output containing timeout_info with partial_results=["result-A", "result-B"]
When I call post_execution_updates with the execution_details, execution_signatures and tool_output
Then execution_status equals "timeout"
Then execution_status equals "TIMEOUT"
And the returned dict contains the partial results ["result-A", "result-B"] from timeout_info
And the execution signature model contains every previous parameter unchanged
And the execution details model contain every previous parameter pair unchanged

Scenario: Timeout with no partial results still sets execution_status to timeout
Given a tool_output containing timeout_info with no partial results available
When I call post_execution_updates with the execution_details, execution_signatures and tool_output
Then execution_status equals "timeout"
Then execution_status equals "TIMEOUT"
And the execution signature model contains every previous parameter unchanged
And the execution details model contain every previous parameter pair unchanged
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,5 @@ Feature: SignatureManager post-execution execution elements update
And the execution details model contain every previous parameter pair unchanged
And the end_time parameter in the execution details model is a datetime object
And this end_time is chronologically greater than or equal to start_time "2024-06-26T06:00:00Z"
And the execution_status parameter in the execution details model is equal to "success"
And the execution_action parameter in the execution details model is equal to "complete"
And the execution_status parameter in the execution details model is equal to "EXECUTED"
And the execution_action parameter in the execution details model is equal to "command_execution"
2 changes: 1 addition & 1 deletion test/signatures/test_signature_manager_post_execution.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ def execution_details():
target_fixture="tool_output",
)
def successful_tool_output():
return {"status": "success"}
return {"status": "EXECUTED"}


@given(
Expand Down
20 changes: 10 additions & 10 deletions test/signatures/test_signature_manager_transmission.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ def context():
def _extract_targets(body: dict) -> list[dict]:
"""Parse targets from the SignatureCallbackPayload wire format."""
sig_data = json.loads(body["execution_output_structured"])
return sig_data["signatures"]["targets"]
return sig_data["expectation_signatures"]["targets"]


def _build_signature_payload(
Expand Down Expand Up @@ -172,20 +172,20 @@ def _http_post(*args, **kwargs):
context["status_plan"] = [200]
context["error_body"] = ""
context["inject_id"] = "inject-abc-001"
context["signatures"] = _build_signature_payload()
context["expectation_signatures"] = _build_signature_payload()
context["signature_manager"] = SignatureManager(mock_client, logger=logger)


@given(parsers.parse('a compiled post-execution payload for inject_id "{inject_id}"'))
def compiled_post_execution_payload(context, inject_id):
context["inject_id"] = inject_id
context["signatures"] = _build_signature_payload()
context["expectation_signatures"] = _build_signature_payload()


@given(parsers.parse("an updated post-execution execution details object"))
def updated_post_execution_execution_details(context):
execution_details = ExecutionDetails(
execution_status="success",
execution_status="SUCCESS",
execution_action="complete",
)
execution_details.end_time = execution_details.start_time + timedelta(0.1)
Expand All @@ -203,7 +203,7 @@ def compiled_payload_single_target(
signature_type,
signature_value,
):
context["signatures"] = {
context["expectation_signatures"] = {
"targets": [
{
"signature_target": dict(_CANONICAL_SIGNATURE_TARGET),
Expand All @@ -230,9 +230,9 @@ def compiled_large_payload(context):
context["signature_manager"] = SignatureManager(
context["mock_client"],
logger=context["logger"],
max_payload_size=700,
max_payload_size=800,
)
context["signatures"] = {
context["expectation_signatures"] = {
"targets": [
{
"signature_target": {
Expand Down Expand Up @@ -335,7 +335,7 @@ def compiled_payload_grouped_by_expectation(
expectation_a,
expectation_b,
):
context["signatures"] = {
context["expectation_signatures"] = {
"targets": [
{
"signature_target": dict(_CANONICAL_SIGNATURE_TARGET),
Expand Down Expand Up @@ -376,7 +376,7 @@ def call_send_signatures(context, inject_id):
context["signature_manager"].send_signatures(
inject_id,
context["execution_details"],
context["signatures"],
context["expectation_signatures"],
)
except Exception as exc:
context["send_exception"] = exc
Expand Down Expand Up @@ -498,7 +498,7 @@ def assert_no_chunk_metadata(context):

@then("the union of targets across all POST requests equals the original target set")
def assert_targets_union_matches_original(context):
original_targets = context["signatures"]["targets"]
original_targets = context["expectation_signatures"]["targets"]
sent_targets = [
target
for call_item in context["captured_calls"]
Expand Down
Loading