blob: 573fbc26878017aa426529f0a2806a398e388585 [file] [view] [edit]
# 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
```python
# --- 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.