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:

  • testBirthControl builds an AppContext over a QTemporaryDir and passes headless=true — correct, and the shape adopted here.
  • testDiscovery and testConnectionUI call AppLauncher<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.
  • testDeliveryWizard passes (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 QTemporaryDir in 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, because PathResolver answers 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::systemEnvironment outside 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.

In this section