9. Worked Example: Pigweed System Stress Test

This example models a realistic “Pigweed System” configuration, stressing the hierarchy with:

  1. Global Constraints: Hardware targets limiting OS choices.
  2. Cross-Module Constraints: pw_async2 logic depending on Host vs Embedded.
  3. Recursive Scope: pw_rpc having internal backends.
  4. Hybrid Coverage: Jointly optimizing “RPC internals” with “Global Platforms”.

9.1 The Hierarchy Definition

# --- Root Component (The System) ---
pigweed = Component(
    name="Pigweed",
    parameters=[
        # Global Build Args
        Parameter("Target", [Option("Host"), Option("STM32"), Option("RP2040")]),
        Parameter("HostOS", [Option("Linux"), Option("Mac"), Option("Win")]),
        Parameter("Toolchain", [Option("Clang"), Option("GCC"), Option("ARM-EABI")]),
        Parameter("RTOS", [Option("None"), Option("FreeRTOS"), Option("Zephyr")]),
    ],
    constraints=[
        # Constraint: Hardware dictates valid RTOS
        Constraint(If(Eq(Val("Target"), Lit("STM32")),  In(Val("RTOS"), {"None", "FreeRTOS"}))),
        Constraint(If(Eq(Val("Target"), Lit("RP2040")), In(Val("RTOS"), {"None", "FreeRTOS"}))),
        # Constraint: Host only runs "None" (simulated) or special host-RTOS? Let's say None.
        Constraint(If(Eq(Val("Target"), Lit("Host")),   Eq(Val("RTOS"), Lit("None")))),

        # Constraint: ARM-EABI only for embedded
        Constraint(If(Eq(Val("Toolchain"), Lit("ARM-EABI")), Neq(Val("Target"), Lit("Host")))),
    ],
    coverage=[
        # System-Level Matrix: Ensure we test all valid Target/RTOS/Toolchain combos
        Coverage(axes=["Target", "RTOS", "Toolchain"])
    ],
    sub_components=[
        # --- Sub-Component: pw_async2 ---
        Component(
            name="pw_async2",
            parameters=[
                Parameter("Dispatcher", [
                    Option("Basic"),      # Works everywhere
                    Option("LibEvent"),   # Host only
                    Option("FreeRTOS"),   # FreeRTOS only
                    Option("WorkQueue"),  # Generic
                ]),
            ],
            constraints=[
                # Logic: LibEvent backend requires Host target (and maybe not Windows?)
                Constraint(If(
                    Eq(Val("Dispatcher"), Lit("LibEvent")),
                    And(
                        Eq(Val("//Target"), Lit("Host")),
                        Neq(Val("//HostOS"), Lit("Win"))
                    )
                )),
                # Logic: FreeRTOS backend requires FreeRTOS OS
                Constraint(If(
                    Eq(Val("Dispatcher"), Lit("FreeRTOS")),
                    Eq(Val("//RTOS"), Lit("FreeRTOS"))
                )),
            ],
            coverage=[
                # Module Goal: Test all Dispatchers *where valid*
                Coverage(axes=["Dispatcher"])
            ]
        ),

        # --- Sub-Component: pw_rpc ---
        Component(
            name="pw_rpc",
            parameters=[
                # Implicit "Enabled" param logic:
                # If we select any internal option, this must be "On".
                # If we select "Off", all internal options are IsDisabled().
                Parameter("Enabled", [Option(True), Option(False)]),

                Parameter("ChannelID", [Option(1), Option(42)]),
                Parameter("DynamicAlloc", [Option(True), Option(False)]),
            ],
            constraints=[
                 # Logic: Hierarchical Enabling
                 # 1. If 'Enabled' is FALSE, all child params MUST be Disabled. (Enforcement)
                 Constraint(If(
                     Eq(Val("Enabled"), Lit(False)),
                     And(IsDisabled("ChannelID"), IsDisabled("DynamicAlloc"))
                 )),

                 # 2. If 'Enabled' is TRUE, child params MUST be Enabled (have values).
                 Constraint(If(
                     Eq(Val("Enabled"), Lit(True)),
                     And(IsEnabled("ChannelID"), IsEnabled("DynamicAlloc"))
                 )),
            ],
            coverage=[
                 # Verify we test both channel IDs and alloc modes
                 Coverage(axes=["ChannelID", "DynamicAlloc"])
            ]
        ),

        # --- Sub-Component: pw_sync ---
        Component(
            name="pw_sync",
            parameters=[
                Parameter("Backend", [
                    Option("BinarySemaphore"),
                    Option("RecursiveMutex"),
                    Option("InterruptSpinLock")
                ])
            ],
            constraints=[
                # Backend availability depends on RTOS
                Constraint(If(
                   Eq(Val("Backend"), Lit("BinarySemaphore")),
                   Neq(Val("//RTOS"), Lit("None"))
                ))
            ],
            coverage=[
                Coverage(axes=["Backend"])
            ]
        )
    ]
)

9.2 The “Hybrid” Solving Process

When we solve this via Strategy C (System Matrix):

  1. System Matrix: The solver identifies the “Platform Matrix” from the root coverage:

    • {Target=Host, RTOS=None, Toolchain=Clang}
    • {Target=STM32, RTOS=FreeRTOS, Toolchain=ARM-EABI}
    • ... etc ...
  2. Aggregation: It sees pw_async2 wants to cover Dispatcher=*.

  3. Joint Optimization:

    • Requirement: Cover Dispatcher=LibEvent.

    • Constraint Check: Requires Target=Host.

    • Selection: Solver piggybacks this onto a Time=Host global test.

    • Requirement: Cover Dispatcher=FreeRTOS.

    • Constraint Check: Requires RTOS=FreeRTOS.

    • Selection: Solver piggybacks this onto the STM32 + FreeRTOS global test.

9.3 The Resulting efficiency

Instead of N*M isolated tests, we get a minimal set of System Configurations that:

  1. Satisfy Constraints (No invalid builds).
  2. Exercise Internals: pw_async2 gets fully exercised across relevant platforms.
  3. Minimize Redundancy: If pw_rpc doesn't care about OS, it just gets standard coverage via valid configurations chosen for other modules.