jj-commit-cloud-poc / Tests

Testing

Every test is an end-to-end test: it starts a real jj-cc-server process, runs the real jj binary against it in a temporary directory, and checks files or command output. There are nine tests, and no unit tests anywhere in the workspace.

On this page
  1. The testutils harness
  2. Building the server for the tests
  3. Starting a server
  4. Creating a workspace
  5. The tests
  6. Two tests that pass for other reasons
  7. The invalid-server test
  8. The SQLite test
  9. Running them

In short: the testutils crate builds the server binary, starts it on a random port and initialises a workspace with jj cc init. The eight cli tests cover init, describe, log and op log. The one server test calls the health service. One test is marked #[should_panic] because the SQLite store doesn't exist, and one passes without ever reaching a server.

The testutils harness

Building the server for the tests

Integration tests in cli and server need the jj-cc-server binary, but Cargo only builds binaries of the package under test. testutils, a dev-dependency of both, solves this in its build script:

  1. It runs cargo build -p jj-commit-cloud-server --bin jj-cc-server with CARGO_TARGET_DIR set to a directory under its own OUT_DIR (L15–26). The separate target directory avoids a deadlock on the outer build's lock.
  2. It copies the binary into the outer profile directory, next to the test executables' deps/ folder (L36–54).
  3. It reruns only when server/src/ or server/Cargo.toml change (L7–8).

Starting a server

spawn_server_with_args finds the binary two levels above the running test executable and starts it with --port=0, so the OS picks a free port and tests can run in parallel. It pipes stdout and discards stderr. It then reads stdout line by line until one contains listening on (extract_listening_address), which the server's startup log line supplies (main.rs L91). It panics if stdout closes first or if two seconds pass. The returned ServerGuard holds the child process and kills it on drop.

Creating a workspace

TestWorkspace::init starts a server, creates a temporary directory, and runs jj cc init --server <url> --create . in it, asserting success. The workspace owns both the server guard and the directory, so each test gets its own server and repository, and both go away when the test ends. jj_cmd returns an assert_cmd command for the jj binary with its working directory set to the workspace. init_sqlite is the same, but starts the server with --store-type=sqlite.

How a test sets up a server and workspace The test calls TestWorkspace::init. That spawns jj-cc-server with --port=0 and reads its stdout until the listening address appears. It then runs jj cc init in a temporary directory against that address. The test then runs jj commands in the directory, which talk to the server over gRPC, and asserts on their output or on files under .jj. #[tokio::test] TestWorkspace::init jj-cc-server --port=0 jj cc init, then jj … in a tempdir spawn, read stdout assert_cmd gRPC

The tests

TestWhat it doesWhat it asserts
test_cc_init_creates_local_workspaceinit.jj/repo/store/type is commit_cloud; config.toml holds the server URL and a repo_id that parses as a UUID.
test_cc_init_registers_repositoryinit, then a raw ReadCommit for a made-up ID (all bytes 1)The error message is "commit should have been present in cloud database". The server checks registration before looking the commit up (backend.rs L43–52), so this message shows it knows the repo_id.
test_cc_init_fails_on_invalid_server_addrjj cc init against an unresolvable host, into /invalid_path_dest_dirThe command fails. See below.
test_log_snapshots_working_copyWrite hello.txt, describe -m "snapshot test"log -r @ -T description prints snapshot test. It doesn't check that the file reached the server.
test_log_root_commit_existslog -r root() -T commit_idThe output is the root commit's graph node and 40 zeros: the root commit ID is 20 zero bytes (common/src/lib.rs).
test_cc_init_op_store_type_returns_commit_cloudinitop_store/type and op_heads/type are both commit_cloud.
test_op_log_succeeds_on_snapshotop log, write a file, describe -m "description 0"op log --no-graph -T description prints add workspace 'default' followed by root(), with no separator: the init operation and the root operation, both read back from the server. After the describe, it checks log, not op log.
test_sqlite_store_init_and_snapshot_succeedsinit_sqlite, then the same steps as the snapshot test#[should_panic]. See below.
test_server_startup_succeedsStart a server, call the gRPC health service for service ""The status is SERVING.

That is nine test functions in six files. Nothing tests the server or the client stores directly: the lib, common and server sources contain no #[test] functions. Nothing exercises concurrent writers, the NotFound paths, jj new, rebases or any operation with more than one parent.

Two tests that pass for other reasons

The invalid-server test

test_cc_init_fails_on_invalid_server_addr passes the destination /invalid_path_dest_dir, a directory that doesn't exist under /. jj-lib's create_jj_dir runs before any backend code and fails because the parent directory is missing, so jj cc init exits with an error before it tries to reach the server (confirmed by hand). The test would pass with a working server URL too. It doesn't test what its name says.

The SQLite test

test_sqlite_store_init_and_snapshot_succeeds is marked #[should_panic] (L4). init_sqlite starts the server with --store-type=sqlite, which prints "SQLite storage backend is not yet implemented" to stderr and exits (main.rs L73–76). The harness sees stdout close and panics (lib.rs L79). That panic is what the test expects. The body after init_sqlite, which describes the intended SQLite behaviour, never runs. See storage.

Running them

cargo test --workspace runs everything. The build needs protoc on the PATH, because common's build script compiles the .proto files with tonic-build (see protobufs).

Run at the pinned commit on 2026-10-06 (Rust 1.97.0, Linux), all nine tests passed, including the should_panic test. Running the invalid-server test's command by hand gives Path(PathError { path: "/invalid_path_dest_dir/.jj", … NotFound }). Pointing the same command at a directory that exists gives a DNS ConnectError from the backend initialiser instead, and leaves no .jj behind.