Loading files
# Copyright (c) 2026 TiaC Systems
# SPDX-License-Identifier: Apache-2.0
"""Unit: emitter/context -- context.cmake, the build-glue handoff kept
OUT of `emit()`. Pinned here: the "no
declaration, no artifact" rule for RIG_REVISION/RIG_VARIANT/
RIG_SHIELD_REVISIONS, RIG_SHIELDS distinct-in-rig-order, RIG_DEPENDS
sorted, and `_cmake_list_escape` over the one input shape no real path
produces but a caller could (`;`, `"`, `\\`) -- hand-differential
territory made a unit test.
"""
from __future__ import annotations
from rigc.emitter.context import _cmake_list_escape, render
from rigc.model import AxisDecl, Instance, Rig, Shield
def _shield(name: str, revisions: AxisDecl | None = None, revision: str | None = None) -> Shield:
return Shield(
name=name, label=name, plugs={"plug": "t"}, revisions=revisions, revision=revision
)
def test_cmake_list_escape_backslash_quote_and_semicolon() -> None:
assert _cmake_list_escape("a;b") == "a\\;b"
assert _cmake_list_escape('a"b') == 'a\\"b'
assert _cmake_list_escape("a\\b") == "a\\\\b"
def test_cmake_list_escape_backslash_runs_first_so_its_own_escapes_survive() -> None:
"""Escaping order matters: a literal backslash must double BEFORE the
quote/semicolon substitutions add their own backslashes, or those
added backslashes would get doubled too and cmake would read back one
mis-split element instead of the path.
Asserted against a hand-computed literal over an input carrying ALL
THREE metacharacters at once, because that is what actually
distinguishes the orders: with the backslash step moved last this
input yields 'a\\\\;b\\\\"c\\\\d' instead. Composing the expectation
out of the function's own single-character results instead would hold
under EITHER order -- the two errors cancel on single-character
inputs."""
assert _cmake_list_escape('a;b"c\\d') == 'a\\;b\\"c\\\\d'
def test_axis_less_rig_omits_revision_variant_and_shield_revisions() -> None:
inst = Instance(name="i1", shield=_shield("sh"), sockets={"plug": "sock"})
rig = Rig(name="r", board="b", instances=[inst])
out = render(rig, frozenset()).decode("utf-8")
assert "RIG_REVISION" not in out
assert "RIG_VARIANT" not in out
assert "RIG_SHIELD_REVISIONS" not in out
assert 'set(RIG_NAME "r")' in out
assert 'set(RIG_BOARD "b")' in out
assert 'set(RIG_SHIELDS "sh")' in out
def test_declared_axes_and_shield_revision_all_appear_resolved() -> None:
shield = _shield("sh", revisions=AxisDecl(values=["1", "2"], default="1"), revision="2")
inst = Instance(name="i1", shield=shield, sockets={"plug": "sock"})
rig = Rig(
name="r",
board="b",
instances=[inst],
revisions=AxisDecl(values=["1", "2"], default="1"),
revision="2",
variants=AxisDecl(values=["x"], default="x"),
variant="x",
)
out = render(rig, frozenset()).decode("utf-8")
assert 'set(RIG_REVISION "2")' in out
assert 'set(RIG_VARIANT "x")' in out
assert 'set(RIG_SHIELD_REVISIONS "sh@2")' in out
def test_rig_shields_is_distinct_in_rig_declaration_order() -> None:
sh_a, sh_b = _shield("a"), _shield("b")
insts = [
Instance(name="i1", shield=sh_b, sockets={"plug": "s"}),
Instance(name="i2", shield=sh_a, sockets={"plug": "s"}),
Instance(name="i3", shield=sh_b, sockets={"plug": "s"}),
] # repeats "b"
rig = Rig(name="r", board="board", instances=insts)
out = render(rig, frozenset()).decode("utf-8")
assert 'set(RIG_SHIELDS "b;a")' in out
def test_rig_depends_is_sorted() -> None:
rig = Rig(name="r", board="b", instances=[])
deps = frozenset({"/z/path", "/a/path", "/m/path"})
out = render(rig, deps).decode("utf-8")
assert 'set(RIG_DEPENDS "/a/path;/m/path;/z/path")' in out
def test_render_returns_utf8_encoded_bytes() -> None:
rig = Rig(name="r", board="b", instances=[])
result = render(rig, frozenset())
assert isinstance(result, bytes)
assert b"generated by rigc" in result
55022eb50This file is pinned to the selected release. Download the original to open it in your design tool.