Environment Matrix Mechanism
The env_matrix configuration allows a single scenario definition to be executed multiple times concurrently using a Cartesian product of defined environment variables. This is useful for running the same workflow with different user data without duplicating .sinq files or directory structures.
Definition and Cartesian Product
The env_matrix property in a .scenario file takes an array of objects. Each object represents an axis in the matrix. The keys in these objects serve as labels, and their values are the environment variable overrides/additions applied to that specific branch of the execution. The objects must have all their top-level keys correspond to objects. Empty objects ({}) are safely ignored and dropped by the parser.
config.scenario:
{
"env_matrix": [
{
"admin": { "role": "admin", "auth_token": "sys-jwt-999" },
"guest": { "role": "guest", "auth_token": "guest-jwt-111" }
},
{
"card": { "method": "card", "expected_status": 200 },
"crypto": { "method": "crypto", "expected_status": 202 }
}
]
}
During the Treewalker aggregation phase, sinq gathers all of these arrays into a single flat array of objects. Then the runner dispatches the resulting scenario combined with every possible combination of environments from these objects (creating a Cartesian product by picking exactly one key-value pair from each axis object). These combinations are then deep merged with the static env for this particular run. The example above yields 4 distinct data sets that are sent to the worker pool:
admin_card:role="admin",auth_token="sys-jwt-999",method="card",expected_status=200admin_crypto:role="admin",auth_token="sys-jwt-999",method="crypto",expected_status=202guest_card:role="guest",auth_token="guest-jwt-111",method="card",expected_status=200guest_crypto:role="guest",auth_token="guest-jwt-111",method="crypto",expected_status=202
The generated scenarios will automatically append these labels to the base scenario name (e.g., checkout_admin_card).
Note: Because the combination parsing relies on Go map iteration, the generation and execution sequence of the matrix combinations is inherently non-deterministic.
Usage in Requests
The generated matrix values are injected directly into the scenario's environment. They can be accessed via standard interpolation (${env.variable}) in the raw HTTP text or inside Lua scripts via the env global table.
01_checkout.sinq:
POST ${env.BASE_URL}/checkout
Authorization: Bearer ${env.auth_token}
Content-Type: application/json
{
"role": "${env.role}",
"payment_method": "${env.method}"
}
$ASSERT{
sinq.assert.code(env.expected_status, "Matrix status code mismatch for " .. env.role .. " using " .. env.method)
}
Inheritance and Deep Merging
Matrix environments adhere to the standard Treewalker inheritance rules, with specific behaviors for resolution and merging:
- Base Environment Overrides: Values generated by a matrix combination take precedence over the base
envaggregated for the scenario. The matrix values are deep-merged on top of the base environment. - Parent-Child Matrix Multiplication: If a parent directory defines an
env_matrix, and a child directory also defines its ownenv_matrix, the child inherits the parent's axes. This results in the matrix expanding exponentially as the dimensions are multiplied together.
Note: Be cautious when nesting matrices deeply within the directory tree, as it can unintentionally generate a massive number of concurrent workers and exhaust network or system resources.