This document describes what would be required to add real integration tests that
exercise NextGenSoftware.Holochain.HoloNET.Client against a live Holochain 0.6.1
conductor process, as a follow-up to the unit tests in
NextGenSoftware.Holochain.HoloNET.Client.Tests (which only cover serialization
round-trips and do not require a conductor).
This is a plan only. No conductor install or live-process work has been attempted as part of producing this document — see "Feasibility" at the end.
Three realistic options, roughly in order of CI-friendliness:
-
Prebuilt binary from the GitHub release. The
holochain/holochainrepo publishes release artifacts taggedholochain-0.6.1. Download the binary for the target OS/arch from the GitHub Releases page for that tag and put it onPATH(or reference its full path from the test fixture). This is the most CI-friendly option since it avoids a Rust toolchain entirely, but the artifact name/availability per-platform should be confirmed at https://github.com/holochain/holochain/releases when this is actually attempted. -
cargo install holochain --version 0.6.1. Requires a working Rust toolchain (rustup) and takes several minutes to compile from source. Most portable across platforms (anywhere Rust can run) but slow and adds a Rust toolchain as a CI dependency. -
Nix / Holonix dev shell. The Holochain project publishes a
flake.nix/ Holonix shell that pins all ofholochain,hc(the dev CLI), andlair-keystoreto compatible versions for a given release. This is the approach the Holochain project itself uses for its own CI and is the most reliable way to get a known-good, version-matched set of binaries (avoids subtle incompatibilities between a manually acquiredholochainbinary andlair-keystore/hcversions). Requires Nix installed on the CI runner.
Whichever method is used, two binaries are actually required at runtime:
holochain(the conductor itself)lair-keystore(the keystore processholochainshells out to / connects to — seeKeystoreConfig.csin this repo for theLairServerInProc/LairServermodes HoloNET's config models already (not yet wired to a real conductor launch)).
A real .happ bundle is needed to install via the Admin API. Options:
- Use Holochain's own
hello_worldordummyexample hApp from theholochain/holochainrepo'scrates/test_utils/wasmfixtures, if pre-built.happ/.wasmartifacts are published — these are intentionally trivial (e.g. a single zome with a no-op or echo function) and are what Holochain's own integration tests use. - Alternatively, build a minimal custom DNA with
hc(the Holochain dev CLI, included in the Holonix shell) from a one-zome scaffold (hc scaffoldcan generate a trivial zome). This requires the Rust + WASM toolchain (cargo build --release --target wasm32-unknown-unknown) to compile the zome, thenhc dna pack/hc app packto bundle it. - Either way, the resulting
.happfile path needs to be checked into the test repo (as a small binary fixture) or built as a pre-test step, not downloaded at test-run time from an untrusted source.
A minimal sandbox conductor config (conductor-config.yaml or generated via hc sandbox)
needs:
admin_interfaceswith awebsocket.portset to a known or dynamically-allocated port (port 0 lets the OS pick a free port, but then the actual bound port must be read back from the conductor's stdout/log —hc sandboxprints this).- A
data_root_pathpointed at a temp directory per test run (so test runs don't collide or leave state behind). - A
networkblock — for a fully offline/local-only integration test, thebootstrap_url/signal_urlcan point at a local mock or simply rely on single-node operation if the test doesn't need real peer-to-peer gossip.
The easiest path is actually hc sandbox generate + hc sandbox run, which handles
conductor-config generation, lair-keystore setup, and admin port assignment
automatically — wrapping this CLI rather than hand-rolling a YAML config is the
pragmatic choice for a first integration-test pass.
A [CollectionDefinition]/IAsyncLifetime-based xUnit fixture, conceptually:
public class HolochainConductorFixture : IAsyncLifetime
{
private Process _conductorProcess;
public int AdminPort { get; private set; }
public string InstalledAppId { get; } = "integration-test-app";
public async Task InitializeAsync()
{
// 1. Locate the holochain/lair-keystore/hc binaries (env var or PATH).
// 2. Run `hc sandbox generate --directory <tempdir> <path-to-happ>` to create
// a sandboxed conductor + install the test hApp in one step, OR run
// `hc sandbox create` then issue InstallAppAsync via HoloNETClientAdmin
// after the conductor is up (closer to what real HoloNET consumers do).
// 3. Launch `holochain` (or `hc sandbox run`) as a child Process, redirecting
// stdout/stderr to a buffer.
// 4. Parse stdout for the actual bound admin websocket port (sandbox tooling
// prints "Listening on port: N" or similar - exact string must be confirmed
// against the real 0.6.1 CLI output when this is implemented).
// 5. Poll/retry connecting a HoloNETClientAdmin instance to
// ws://127.0.0.1:{port} until it succeeds or a timeout elapses (the
// conductor takes a moment to bind the socket after process start).
}
public async Task DisposeAsync()
{
// Gracefully send SIGTERM/CloseMainWindow, then kill if it doesn't exit within
// a few seconds. Clean up the temp data_root_path directory.
_conductorProcess?.Kill(entireProcessTree: true);
}
}
[CollectionDefinition("HolochainConductor")]
public class HolochainConductorCollection : ICollectionFixture<HolochainConductorFixture> { }
[Collection("HolochainConductor")]
public class AdminApiIntegrationTests
{
private readonly HolochainConductorFixture _fixture;
public AdminApiIntegrationTests(HolochainConductorFixture fixture) => _fixture = fixture;
[Fact]
public async Task GenerateAgentPubKeyAsync_ReturnsValidKey() { /* connect, call, assert */ }
[Fact]
public async Task InstallApp_Enable_AttachAppInterface_FullFlow_Succeeds() { /* ... */ }
[Fact]
public async Task DumpNetworkStatsAsync_ReturnsParsedResponse() { /* exercises the new
typed DumpNetworkStatsResponse added in the 0.6.1 upgrade against a real conductor */ }
}Key properties this harness needs that the unit tests deliberately don't exercise:
- Process lifecycle management — starting/stopping a real OS process per test
collection (not per test, to keep runtime reasonable), with robust cleanup even on
test failure/cancellation (xUnit's
IAsyncLifetime.DisposeAsyncplus atry/finallyKill(entireProcessTree: true)). - Readiness polling — the admin websocket isn't immediately available the instant the process starts; tests need a retry-with-backoff connect loop rather than a fixed sleep.
- Test isolation — a fresh
data_root_path(temp directory) per test run so state from one run doesn't leak into the next; delete it in teardown. - CI environment gating — these tests should be skippable (e.g. an xUnit
[Trait("Category", "Integration")]+ a CI flag, or checking for theholochainbinary onPATHin a static[Fact(Skip = ...)]condition) so thatdotnet testin normal dev/CI runs (which only have the binary-free unit test project) doesn't fail trying to launch a conductor that isn't installed.
- That the real conductor accepts HoloNET's exact wire bytes for
ZomeCallParamsSigned, the new Admin/App request types, etc. — the unit tests verify internal consistency (HoloNET serializes and deserializes its own types correctly) but cannot prove the real Holochain 0.6.1 conductor accepts those exact bytes without a live round trip. - Real signature verification (a real conductor-generated
AgentPubKey+ a real Ed25519 signature over the realZomeCallParamsbytes) versus the unit tests' use of arbitrary placeholder byte arrays. - Real error responses from the conductor for the new 0.6.1-only Admin/App calls (e.g.
whether
GetCompatibleCellsis actually enabled by default or gated behind a feature flag in a given build — this was flagged as uncertain during the original upgrade).
I have not attempted to install or run a Holochain conductor as part of producing this plan, per instruction. Realistically:
- Downloading a prebuilt 0.6.1 binary or running
cargo install holochain --version 0.6.1requires outbound internet access and (for the cargo path) a multi-minute build; both are plausible to attempt with the tools available in this environment, but neither has been attempted here since it wasn't requested as an action — only the plan was. - The Nix/Holonix path additionally requires Nix to be installed, which is a heavier, more deliberate environment change.
- This is something the user should explicitly approve before it's attempted —
installing a multi-hundred-MB Rust toolchain or Holochain binary, or running a long
cargo install, is a meaningful environment change with real time/disk cost, not a small step to take silently as part of a "write tests" task. If the user wants this done, the recommended next step is the prebuilt-binary route (option 1 above) as the fastest, lowest-footprint way to get a working conductor binary for a first integration-test attempt, falling back to Nix/Holonix only if version-compatibility issues withlair-keystoreshow up.