Table of Contents

Class ClientSession

Namespace
Valheim.Testing.Game
Assembly
Valheim.Testing.Game.dll

A game client for a system test: one this session launched and owns, or one an operator runs that it only attaches to. Either way Actor is strictly pinned to the plan's menu expectations when the session is returned, and every command it sends is recorded to client-commands.jsonl in the output directory (client-commands-2.jsonl and so on for later sessions: evidence is never overwritten). Disposing closes the connection and, for an owned client, stops only the process this session started (never one found by name): it asks the client to quit and kills it only if it does not (Stopped), then keeps its logs beside the evidence. An attached client's process is never touched. The client is pinned at its menu. A session given a leased Steam account (a multi-machine session's client) starts or attaches only while that lease is held (and signed-in checked when the profile asks); the hold's owner releases it after disposing the session.

public sealed class ClientSession
Inheritance
object
ClientSession

Properties

Actor

public GameActor Actor { get; }

Property Value

GameActor

Architecture

The slice the owned client was launched as (Architecture; x64 unless the plan asked for arm64), or null for an attached client, whose operator chose it.

public ClientArchitecture? Architecture { get; }

Property Value

ClientArchitecture?

Closed

Whether Dispose() has run.

public bool Closed { get; }

Property Value

bool

Logs

The owned client's logs as kept beside the evidence once it is disposed (its BepInEx log and Unity's Player.log), for a teardown ScanLogs(IEnumerable<RunLog>, IReadOnlyDictionary<string, LogClassification>?); empty for an attached client, whose logs are its operator's.

public IReadOnlyList<RunLog> Logs { get; }

Property Value

IReadOnlyList<RunLog>

Owned

public bool Owned { get; }

Property Value

bool

ProcessId

The owned client's process ID, or null for an attached client.

public int? ProcessId { get; }

Property Value

int?

QuitTimeout

How long disposing waits for the owned client to quit (its profile save) after asking it, before it kills it. Default one minute.

public TimeSpan QuitTimeout { get; set; }

Property Value

TimeSpan

Stopped

How the owned client ended once disposed; null before that, and for an attached client.

public ProcessStop? Stopped { get; }

Property Value

ProcessStop

Methods

Attach(ClientRunPlan, string, IGameTransport?)

Connects to an operator's client and verifies its menu pins. The operator launched it and still owns it.

public static ClientSession Attach(ClientRunPlan plan, string output, IGameTransport? transport = null)

Parameters

plan ClientRunPlan
output string
transport IGameTransport

Returns

ClientSession

Dispose()

Closes the connection and, for an owned client, stops the process this session started: asks it to quit (it saves its profile, as a player's quit does), waits up to QuitTimeout, and kills it only then. Stopped says which.

public void Dispose()

Launch(ClientRunPlan, string, Func<IOwnedProcess>, Func<IGameTransport>, Func<TimeSpan, CancellationToken, Task>, CancellationToken)

The owned launch with its process, connection and readiness supplied, so a test can drive startup failures and cleanup without a game. ready gets the time left and a token that is cancelled when the process exits first.

public static ClientSession Launch(ClientRunPlan plan, string output, Func<IOwnedProcess> start, Func<IGameTransport> connect, Func<TimeSpan, CancellationToken, Task> ready, CancellationToken cancellation = default)

Parameters

plan ClientRunPlan
output string
start Func<IOwnedProcess>
connect Func<IGameTransport>
ready Func<TimeSpan, CancellationToken, Task>
cancellation CancellationToken

Returns

ClientSession

Launch(ClientRunPlan, string, CancellationToken)

Launches the plan's client install with ForClient(string, IEnumerable<string>, IReadOnlyDictionary<string, string>?, ClientPlatform?, ClientArchitecture?, bool, IEnumerable<string>?) and waits, on events, until it reaches its main menu: ValheimCLI's listening line in this launch's BepInEx log, then the main-menu state push. Every wait races the process exit, which ends startup at once with its exit code. Refuses before launching when something already listens on the client's CLI port (a command could reach a client this session does not own), when no Steam client is running here, when the plan's password variable is not set in this process (the client inherits it), when the install's game build, loader or patchers are not the plan's InstallPins, when ForClient(string, IEnumerable<string>, IReadOnlyDictionary<string, string>?, ClientPlatform?, ClientArchitecture?, bool, IEnumerable<string>?) refuses the install for the plan's Architecture (an arm64 request without an arm64 Doorstop library or a native BepInEx core is refused, never run under Rosetta) or its Doorstop proxy and configuration are from different versions, or when the rest of Preflight()'s install checks fail (a pinned plugin build that is not installed, a script ScriptEngine will not load at start, a standing expectations file that would refuse the run). Once started, BepInEx must write this launch's first log line within BepInExSeconds, or startup fails then, naming the loader, instead of at the start deadline. A failed startup stops the process it started. The process's output goes to client-boot.stdout.log/.stderr.log, and its BepInEx log and Unity's log (the launch's -logFile, toolkit-unity.log in output) are copied beside them (client-boot.game-0.log, client-boot.game-1.log) when it stops; Logs lists them. When BepInEx never logged, a BepInEx preloader crash log this launch wrote beside the game is kept as client-boot.game-2.preloader-N.log and its first error quoted in the failure; an older one is only named.

public static ClientSession Launch(ClientRunPlan plan, string output, CancellationToken cancellation = default)

Parameters

plan ClientRunPlan
output string
cancellation CancellationToken

Returns

ClientSession

Open(ClientRunPlan, string, ICollection<RunLog>, CancellationToken)

Open(ClientRunPlan, string, CancellationToken), adding the logs the owned client keeps beside the evidence (Logs) to logs for the teardown scan: when the session opens, and also when its startup fails after the process started, so a client that never reached its menu is still scanned and listed in the result.

public static ClientSession Open(ClientRunPlan plan, string output, ICollection<RunLog> logs, CancellationToken cancellation = default)

Parameters

plan ClientRunPlan
output string
logs ICollection<RunLog>
cancellation CancellationToken

Returns

ClientSession

Open(ClientRunPlan, string, CancellationToken)

public static ClientSession Open(ClientRunPlan plan, string output, CancellationToken cancellation = default)

Parameters

plan ClientRunPlan
output string
cancellation CancellationToken

Returns

ClientSession