Files
Artificial-Sweetener-Simple…/tests/test_conditioning_batch_snapshot_probe.py
T

133 lines
4.2 KiB
Python

# SimpleSyrup - workflow-focused ComfyUI extensions for image generation
# Copyright (C) 2026 Artificial Sweetener and contributors
# SPDX-License-Identifier: AGPL-3.0-or-later
"""Verify ordered benchmark snapshots for mixed conditioning values."""
from __future__ import annotations
import pytest
import torch
from simple_syrup.domain.conditioning_batch import ConditioningBatch
from tools.attention_coupling_benchmark.comfy_probe.conditioning_batch_snapshot import (
SnapshotConditioningBatchV3,
snapshot_conditioning_value,
)
def test_snapshot_preserves_batch_and_conditioning_entry_order() -> None:
"""Retain exact global/region and scheduled-entry tensor identities."""
global_tensor = torch.tensor([[[1.0]]])
region_first = torch.tensor([[[2.0]]])
region_second = torch.tensor([[[3.0]]])
value = ConditioningBatch(
(
[[global_tensor, {"name": "global"}]],
[
[region_first, {"start_percent": 0.0}],
[region_second, {"start_percent": 0.5}],
],
)
)
snapshot = snapshot_conditioning_value(value)
assert snapshot["kind"] == "conditioning_batch"
batches = snapshot["batch_entries"]
assert isinstance(batches, list)
assert [batch["batch_index"] for batch in batches] == [0, 1]
region_entries = batches[1]["conditioning_entries"]
assert [entry["entry_index"] for entry in region_entries] == [0, 1]
assert (
region_entries[0]["tensor"]["float32_sha256"]
!= region_entries[1]["tensor"]["float32_sha256"]
)
def test_snapshot_accepts_plain_conditioning_and_rejects_malformed_entries() -> None:
"""Distinguish broadcast conditioning and fail on invalid tensor metadata pairs."""
snapshot = snapshot_conditioning_value([[torch.zeros((1, 2, 3)), {}]])
assert snapshot["kind"] == "conditioning"
batch_entries = snapshot["batch_entries"]
assert isinstance(batch_entries, list)
assert len(batch_entries) == 1
with pytest.raises(TypeError, match="tensor or metadata"):
snapshot_conditioning_value([[object(), {}]])
with pytest.raises(TypeError, match="conditioning sequence"):
snapshot_conditioning_value(object())
def test_snapshot_node_is_output_only_and_dev_only() -> None:
"""Keep the observation node outside the product export surface."""
schema = SnapshotConditioningBatchV3.define_schema()
assert schema.node_id == "SimpleSyrupBenchmark.SnapshotConditioningBatch"
assert schema.is_output_node is True
assert schema.is_dev_only is True
def test_snapshot_accepts_the_canonical_host_namespace_surface() -> None:
"""Recognize the immutable domain value when Comfy prefixes its module name."""
module_name = "custom_nodes.SimpleSyrup.simple_syrup.domain.conditioning_batch"
host_type = type(
"ConditioningBatch",
(),
{"__module__": module_name},
)
host_value = host_type()
host_value.entries = ([[torch.ones((1, 1, 1)), {}]],)
snapshot = snapshot_conditioning_value(host_value)
assert snapshot["kind"] == "conditioning_batch"
@pytest.mark.parametrize(
("name", "module", "entries", "message"),
[
(
"OtherBatch",
"simple_syrup.domain.conditioning_batch",
(object(),),
"runtime type",
),
(
"ConditioningBatch",
"example.conditioning_batch",
(object(),),
"runtime type",
),
(
"ConditioningBatch",
"simple_syrup.domain.conditioning_batch",
[object()],
"immutable tuple",
),
(
"ConditioningBatch",
"simple_syrup.domain.conditioning_batch",
(),
"must not be empty",
),
],
)
def test_snapshot_rejects_noncanonical_or_malformed_batch_surfaces(
name: str,
module: str,
entries: object,
message: str,
) -> None:
"""Fail closed on lookalike types and mutable or empty batch state."""
value_type = type(name, (), {"__module__": module})
value = value_type()
value.entries = entries
with pytest.raises((TypeError, ValueError), match=message):
snapshot_conditioning_value(value)