clone

a self-hosted multitenant nostr relay with sites, file storage, git hosting, and inbox and outbox delivery

feat/tinyagent
tinyrelay / docs / testing.md
testing.md 8.8K rendered
1# Testing and the Linux host23The normal development loop is local:45```sh6make verify7make test-race8```910`make verify` runs the Go tests, Go vet, JavaScript tests and a check that the bundled browser dependencies match their locked sources. Install JavaScript dependencies with `npm ci` first. `make web-test` runs the browser checks alone.1112The repository also contains a multistage Docker build. `make docker-test` runs `TEST_PACKAGES` (default `./...`) under Go 1.27.1 on Debian Bookworm with the race detector. `make docker-build` builds the self-hosted runtime image.1314## Component checks1516Build all executables with `make build`. Run the focused component suites with:1718```sh19go test -race ./protocol/... ./internal/auth ./internal/event ./tinygit ./cmd/tinygit ./tinyclient ./cmd/tinyclient20go test -race ./tinyrelay ./internal/relaycmd ./cmd/tinyrelay21go test ./internal/daemon -run TestStandaloneTinyclient22npm run test:tinyclient23```2425The tinygit command test exercises a real binary through signed metadata publication, Git push, clone, unauthorized-ref rejection and restart. The tinyclient integration test compares the standalone frontend with the integrated renderer using a real backend, including session authentication, signed writes, logout and private metadata masking. Public-consumer and dependency checks guard the package boundaries.2627The tinyrelay tests cover the standalone relay's WebSocket protocol, NIP-11 metadata, durable restart, authentication mode, connection limits and shutdown. The command tests cover flag defaults, public URL normalization, listener startup and cancellation. The standalone profile has generic event visibility; tenant and feature access tests belong to the combined daemon.2829Run `make verify` for the full integrated regression suite before shipping. Standalone tests verify the documented component profiles, not every integrated capability. During an extraction, also compare the baseline and refactored binaries using the same fixture data and check that moved browser assets and existing tests were retained. See the [module contracts](module-contracts.md#verification).3031## Remote Linux host3233`scripts/test-linux.sh` runs the same internal race test in an isolated Docker build on the configured Linux host. It synchronizes the exact worktree, including untracked files, over SSH into a unique directory under `~/tinyrelay-tests/` in the remote home directory; it never runs global Docker cleanup and never edits host configuration.3435```sh36LINUX_HOST=<host> LINUX_NAME=tinyrelay-review-1 ./scripts/test-linux.sh37```3839Useful overrides are `LINUX_PACKAGES` (the default internal package list) and `LINUX_ARTIFACTS` (local artifact destination). The script records UTC time, host, kernel, CPU count, Docker server version, Go version, target platform, and SQLite module version beside the Docker build log, including a status file when the build fails. A unique `LINUX_NAME` is required when multiple runs share a host.4041To run the complete tree on Linux, set `LINUX_PACKAGES='./...'`.4243The runtime image is a small Debian image containing the static Go binary, `ca-certificates`, and `git`. It runs as UID 10001 (`relay`) with `/data` as the writable volume. Bind the relay and diagnostics listeners explicitly; diagnostics should stay on loopback or a protected Tailscale address and must not be published publicly.4445Performance runs should use a separate artifact name and record workload seed, client version, host CPU, Go version, SQLite version, storage medium, configuration, raw logs, and profiles. Capacity claims are meaningful only when those inputs are kept with the result.4647The checked-in benchmarks provide a repeatable first baseline without claiming an optimized capacity:4849```sh50make benchmark51LINUX_HOST=<host> ./scripts/bench-linux.sh52```5354`BenchmarkSave`, `BenchmarkQuery`, and `BenchmarkTextSearch` use a local SQLite WAL store with representative seeded events. `BenchmarkFanout` measures only the in-memory broadcast and enqueue path to 10, 100, and 1,000 subscribed clients; it excludes websocket network writes and client-reader scheduling. The benchmark script records the Linux host, CPU count, Docker/Go/SQLite versions, benchmark output, and exit status under `artifacts/bench/`; use `BENCH_PACKAGES` and `BENCHTIME` for controlled comparisons. Treat these as baselines until a workload and hardware matrix supports a capacity claim.5556For Git workloads that include child processes inside Docker, `scripts/observe-git-benchmark.py` captures the benchmark output, host load/memory, and Docker cgroup v2 CPU, memory, I/O, and PID samples every 500ms. It also snapshots authenticated `/metrics`, heap, and goroutine profiles before and after the run. The optional `--cpu-profile` captures one bounded 60-second Go CPU profile; cgroup samples remain the source for child CPU accounting.5758```sh59python3 scripts/observe-git-benchmark.py --out artifacts/git/baseline \60 --container tiny-git-perf-baseline \61 --diagnostics http://127.0.0.1:17448 --token "$TINY_DIAGNOSTICS_TOKEN" \62 -- ./scripts/git-performance.mjs63```6465The [conformance suite](../scripts/conformance/README.md) runs black-box NIP and GRASP cases against a running local daemon and preserves stdout, stderr, status, and environment artifacts. Start the daemon, then run `node scripts/conformance/run.mjs`. To try the Bunker URL sign-in without a phone, run `node scripts/qa/nip46-bunker.mjs` and paste the printed URL into the sign-in page.6667The [UI checks](../scripts/qa/README.md) cover hosted viewers, malformed URLs, signer controls, browser history, failed requests and mobile navigation with and without JavaScript.6869## Real Git repositories7071The Git performance harness below records raw profiles and results under `artifacts/git-performance/`.7273Prepare a new corpus from committed local branches and tags. This leaves the source repositories unchanged and refuses an existing output directory:7475```sh76python3 scripts/prepare-git-performance.py \77 --source-directory "$HOME/Developer" --out /tmp/tiny-git-corpus78```7980Create a dedicated test tenant using the public benchmark fixture identity, then start a separate test daemon. Never use this identity for a real relay:8182```sh83tiny tenant create --data-dir /tmp/tiny-git-test --name main \84 --owner 5ac640e5df8f7945381c31f435288ba3f587fbd68efb27abaf941792f9c3636985tiny serve --data-dir /tmp/tiny-git-test --default-tenant main \86 --listen 127.0.0.1:17447 --allow-private-relays87```8889In another terminal, enable Git hosting and run the workload:9091```sh92node scripts/configure-git-performance.mjs http://127.0.0.1:1744793node scripts/git-performance.mjs --relay ws://127.0.0.1:17447 \94 --repos-dir /tmp/tiny-git-corpus --out artifacts/git-performance/local-run \95 --repeats 396```9798Use `--only strudel,atlas` to select fixtures. Each run creates distinct signed repository identities, checks all transferred refs and HEAD, runs `git fsck`, and measures relay EVENT/REQ traffic throughout the Git phases. The incremental push adds a commit with an unchanged tree; it is a small metadata update, not a new binary upload.99100Add `--private` to both commands to test a GRASP-08 private tenant. The private fixture uses the documented benchmark owner key, so it is already a tenant member. The harness authenticates its control WebSocket with the repository signer and starts a loopback signing proxy for native Git. The proxy adds a repository-root proof with the literal `GET` method to each Git request, and its temporary file handling is included in private timings. Signed repository state authorizes each pushed ref. Use a fresh data directory for each comparison. Do not interpret private timings as a like-for-like unauthenticated native Git comparison.101102For native Git comparisons, `go run ./scripts/git-http-baseline --root /path/to/fresh-bare-repos --listen 127.0.0.1:17449` exposes a benchmark-only HTTP server. Initialize one empty bare `<name>.git` per fixture, set its symbolic HEAD to the corpus manifest's `head_branch`, and enable `http.receivepack`. Add `--baseline http://127.0.0.1:17449` to the workload. Use fresh baseline repositories for each run so initial pushes transfer the complete corpus.103104The raw JSON records failures as failures; interrupted or absent phases are not successful samples. The observer separates Go process memory from container memory, which also includes native Git and file cache. Run performance measurements separately from compilation and test suites on the same host.105106## Git collaboration checks107108Run `npm run test:collaboration` to check signed issue, reply, status and pull request events. Run `go test ./internal/daemon ./tinygit ./internal/replication ./tinyclient` for collaboration queries, access controls, synchronization, Git repair and page rendering.109110The UX fixture includes an issue, a threaded comment, a status change and a pull request with a real Git diff. Use a disposable daemon when testing signed browser publishing.