MockNodeHarness
A configured Node in a throwaway directory, for a test (§AC-3.1, §ACM rows 15–17).
Declared in src/libs/libmocknode/mocknode/MockNodeHarness.hpp.
Detailed description
Why this exists
Several Node behaviours can only be observed on a node that has been through appConfigure() — the hive observer of §ACM row 16 is the example that prompted this class, because the session it listens to is created inside that call and nowhere else. Until now every suite that needed one built the bring-up by hand, and they did not agree:
testBirthControlbuilds anAppContextover aQTemporaryDirand passesheadless=true— correct, and the shape adopted here.testDiscoveryandtestConnectionUIcallAppLauncher<T>::configure(name), which resolves the platform's real application-data location. Those runs write into the developer's own profile and see whatever a previous run left behind.testDeliveryWizardpasses(name, 0, nullptr).
Three shapes for one operation is how a fixture becomes the thing under test. This class is the merged best of them, in the library the handoff already names as the sanctioned harness.
⚠ ONE HARNESS PER PROCESS is the only isolated configuration
app::PathResolver owns on-disk location process-wide and **latches its base directory on first use** (§SPP-3, and deliberately: a process with two trees is the defect §WFR-RC-11 describes). A second harness in the same process gets its own AppContext, and AppContext::baseDir() reports its own temporary directory — but everything routed through PathResolver still answers with the FIRST harness's directory, and PathResolver says so in a warning.
So two harnesses in one test binary are isolated in their contexts and NOT isolated on disk. The constructor warns when it is not the first, because the silent version of this is a suite that shares state it believes it does not. **Put each multi-node scenario in its own suite, or accept a shared tree and say so.**
What it guarantees
- The base directory is a
QTemporaryDirin the scratch folder of the process (utility::file::processScratchDir), so a run cannot read state a previous run left, and cannot leave any — subject to the one-per-process limit above. The first harness keeps its folder until the process ends, becausePathResolveranswers with it. - The context is headless. Nothing here constructs a window, and
MockNode::nodeWindow()is never called. - The environment handed to the context is EMPTY, not the process environment. §NEV-A1 forbids
QProcessEnvironment::systemEnvironmentoutside the one child-process channel, and a fixture that inherits the ambient environment is a fixture whose behaviour depends on the machine.
What it deliberately does not do
It configures. It does not activate. Node::appActivate(true) starts the startup state machine, the service levels and their threads, which is a much larger surface than most suites want and a much slower one. A suite that wants it calls node()->appActivate(true) itself and can then read the acknowledgement back from launcher().
See also MockAppLauncher, MockNode.