Implement Phase 4 test coverage

This commit is contained in:
2026-06-08 15:03:41 -05:00
parent fd81f443d6
commit bba767c821
27 changed files with 2780 additions and 2 deletions
+447
View File
@@ -0,0 +1,447 @@
# Phase 4 Plan: Full-Codebase Test Coverage
## Goal
Build comprehensive automated tests across the full Gitocean codebase so that core behavior is protected by repeatable checks. The test suite should give high confidence that Gitocean works when the external environment is correct: MySQL is available, Git is installed, network ports are free, credentials are valid, and filesystem permissions are sane.
Phase 4 is focused on correctness and regression protection. Product behavior should remain unchanged unless a test exposes a real bug that must be fixed.
## Non-goals
- Do not add a Web UI.
- Do not add SSH Git transport.
- Do not replace MySQL.
- Do not redesign APIs or CLI commands for test convenience.
- Do not mock away all meaningful behavior; tests should exercise real logic where practical.
- Do not require MySQL or network services for the default fast unit test suite.
## Testing principles
1. **Fast tests by default**
- `go test ./...` should remain quick and should not require MySQL, long-running servers, or external network access.
2. **Integration tests are explicit**
- Tests requiring MySQL, Git subprocesses, or real HTTP listeners should be opt-in via build tags or environment variables.
3. **Cover logic, not incidental implementation**
- Prefer behavior-focused tests over brittle line-by-line implementation tests.
- Preserve public API routes, CLI UX, auth rules, permissions, and storage behavior.
4. **Table-driven tests**
- Use table-driven tests for validators, parsers, permission checks, route handling, config parsing, output formatting, and error mapping.
5. **Hermetic filesystem use**
- Use `t.TempDir()` for storage, config, bare repositories, worktrees, and backup fixtures.
6. **No production data**
- Integration tests must create isolated databases, repos, users, and tokens.
- Tests must clean up after themselves.
7. **Regression tests for bugs**
- Every bug fixed during Phase 4 should get a regression test before or with the fix.
8. **Coverage with intent**
- Track coverage using `go test -cover ./...`.
- Aim for effectively full coverage of pure/domain logic and high meaningful coverage of handlers and CLI parsing.
- External process wrappers and unavoidable OS-specific failure paths may be documented as excluded from practical full coverage.
## Test tiers
### Tier 1: Unit tests
Run with:
```bash
go test ./...
```
Must not require MySQL, a running Gitocean server, or external network access.
Covers:
- Validators
- CLI argument parsing
- Config load/save
- JSON helpers
- MySQL DSN and identifier helpers
- Git route parsing
- Permission helpers where dependencies can be isolated
- Output formatting
- Token/password helper behavior where possible
- Pure backup helper behavior such as path/argument construction
### Tier 2: Integration tests
Run explicitly, for example:
```bash
go test -tags=integration ./...
```
or with environment gates such as:
```bash
GITOOCEAN_TEST_MYSQL_DSN='user:pass@tcp(127.0.0.1:3306)/gitocean_test?parseTime=true' go test -tags=integration ./...
```
Covers:
- MySQL migrations
- Register/login/logout/whoami against a real DB
- Token expiry/revoke/prune flows
- Repository create/get/update/delete/search/fork flows
- Collaborator read/write rules
- Pull request create/list/view/close/comment/diff/merge flows
- HTTP Smart Git clone/fetch/push authorization paths
- Backup/restore with real metadata and repository files when tools are present
### Tier 3: End-to-end CLI tests
Run explicitly because they spawn commands and may be slower:
```bash
go test -tags=e2e ./...
```
Covers user workflows through the actual CLI binary or `app.Run`:
- `init -> server config`
- `register -> login -> whoami -> logout`
- `repo create -> clone -> push/fetch`
- `repo publish`
- `repo collaborator add/remove`
- `pr create -> comment -> diff -> merge`
- `token list/revoke/prune`
- `backup create/restore`
## Coverage targets
### Required before Phase 4 is considered complete
- `go test ./...` passes.
- `go vet ./...` passes.
- Unit coverage exists for every internal package.
- Every HTTP API handler has at least one success-path test and meaningful failure-path tests.
- Every CLI command parser has success and failure tests.
- Permission-sensitive behavior has positive and negative tests:
- public read
- private read denied
- owner write
- collaborator read
- collaborator write
- archived repo write denied
- admin-only route allowed/denied
- Auth-sensitive behavior has positive and negative tests:
- valid token
- revoked token
- expired token
- malformed bearer token
- basic auth for Git
- Git HTTP behavior has read/write route coverage.
- Migrations can run against a clean database and are idempotent.
- Coverage reports are generated and reviewed.
### Practical coverage expectation
Use coverage as a signal, not a vanity number. The target is full meaningful coverage of project logic:
- Pure functions and parsers: near 100%.
- Domain rules and permission checks: near 100%.
- HTTP handlers: high coverage across success and expected errors.
- CLI dispatch/parsing/output: high coverage.
- External command execution wrappers: covered through integration/e2e where possible; hard-to-trigger OS failure branches may be documented.
## Proposed package-by-package work
### `internal/validate`
Add/expand tests for:
- Valid usernames
- Invalid usernames
- Valid repo names
- Invalid repo names
- Valid branches
- Invalid branches
- Reserved names
### `internal/config`
Add/expand tests for:
- Default server URL
- Environment overrides
- Client config path override
- Server config path override
- Client config load/save
- Server config load/save
- Invalid JSON
- Missing token/server cases
### `internal/dbutil`
Add/expand unit tests for:
- MySQL identifier quoting
- Duplicate column error detection
- DSN parsing edge cases where possible
Add integration tests for:
- Auto-create missing database behavior
- Migration idempotency
- Schema contains expected tables/columns/indexes
### `internal/gitutil`
Add unit/integration tests for:
- Bare repository initialization
- Default HEAD points to `refs/heads/main`
- Branch existence true/false
- Ref listing for branches and tags
- Git command error messages
These tests require Git but should use `t.TempDir()` only.
### `internal/httputil`
Add tests for:
- Strict JSON decoding rejects unknown fields
- Invalid JSON returns HTTP 400
- `WriteJSON` content type/status/body
- `WriteError` body format
### `internal/backup`
Add unit tests for:
- MySQL CLI arg generation for tcp DSNs
- MySQL CLI arg generation for unix socket DSNs
- Copy directory behavior
- File mode preservation where practical
Add integration tests for:
- Backup archive creation
- Restore into a clean temp storage directory
- Failure when required external tools are unavailable, if practical
### `internal/app`
Split tests by behavior area:
#### CLI dispatch and parsing
- Unknown root command
- Help output
- `server` flag parsing defaults/overrides
- Repo create/publish parser combinations
- Repo refs/view/search JSON flag behavior
- PR create/list/view parser combinations
- Token/admin command validation
- Human-readable output by default
- `--json` output where supported
#### HTTP API routing
Use `httptest` where possible.
- Unknown route returns 404
- Wrong method returns 404 or expected error
- Register/login/logout/me routes
- Token routes
- Admin routes
- Repo routes
- PR routes
- Git HTTP route dispatch
#### Auth behavior
- First registered user becomes admin
- Later users are not admin
- Login with username
- Login with email
- Invalid password rejected
- Token generated with 7-day expiry
- Logout revokes token
- Expired/revoked token rejected
- Basic auth maps username/token correctly for Git
#### Repo behavior
- Create public repo
- Create private repo
- Reject invalid repo name
- Reject reserved repo/owner names
- Duplicate repo rejected
- Get public repo anonymously
- Private repo denied anonymously
- Private repo allowed to owner
- Private repo allowed to collaborator according to role
- Update description/visibility/default branch
- Archive/unarchive
- Delete requires force when non-empty if current behavior requires it
- Search public/all/mine scopes
- Fork public repo
- Fork private repo access rules
#### Pull request behavior
- Create same-repo PR as owner
- Create cross-repo PR from fork
- Reject invalid branches
- Reject unauthorized PR source/target combinations
- List PRs
- View PR
- Close PR
- Comment on PR
- List comments
- Diff PR
- Merge PR
- Reject merge when not authorized
- Reject merge for closed PR
#### Git HTTP behavior
Use temp bare repos and `httptest` where possible.
- Parse git paths
- Upload-pack public access
- Upload-pack private denied without auth
- Upload-pack private allowed for owner/collaborator read
- Receive-pack denied without auth
- Receive-pack allowed for owner/write collaborator
- Receive-pack denied for read-only collaborator
- Receive-pack denied when repo is archived
- Required CGI environment variables are set for `git http-backend`
## Test harness improvements
Phase 4 will likely need small internal test helpers:
```text
internal/app/test_helpers_test.go
internal/testutil/
```
Potential helpers:
- Create temp server storage
- Create test DB handle or skip integration tests if env var absent
- Run migrations
- Create users/tokens/repos directly for tests
- Create temp Git repos and commits
- Start `httptest.Server`
- Capture stdout/stderr for CLI output tests
- Build authenticated API requests
Helpers should live in `_test.go` files unless they are useful production abstractions.
## Test data and isolation
- Use unique usernames/repo names per test when a real DB is used.
- Use `t.Cleanup` for filesystem and DB cleanup.
- Prefer transactions for DB tests when possible.
- For migration tests, use a uniquely named temporary database.
- Never use real `storage/` or real user config files in tests.
- Override config paths with environment variables:
- `GITOOCEAN_CONFIG`
- `GITOOCEAN_SERVER_CONFIG`
## Commands to run during Phase 4
Fast loop:
```bash
gofmt -w .
go test ./...
go vet ./...
```
Coverage:
```bash
go test -cover ./...
go test -coverprofile=coverage.out ./...
go tool cover -func=coverage.out
```
Integration loop:
```bash
go test -tags=integration ./...
```
Optional race checks:
```bash
go test -race ./...
```
## Milestones
### Milestone 1: Establish coverage baseline
- Run `go test -cover ./...`.
- Record low-coverage packages.
- Add missing tests for current pure helpers.
- Add `internal/httputil`, `internal/gitutil`, `internal/backup`, and parser tests where missing.
### Milestone 2: Add HTTP/API unit tests
- Build `httptest` helpers.
- Add route and handler tests for auth, tokens, repos, PRs, collaborators, and admin.
- Mock or isolate DB state where possible; otherwise mark tests integration.
### Milestone 3: Add DB/migration integration tests
- Add opt-in integration test setup for MySQL.
- Test clean migrations and idempotency.
- Test DB-backed auth/repo/PR flows.
### Milestone 4: Add Git behavior tests
- Test Git utility functions with temp repos.
- Test HTTP Smart Git permissions.
- Test push/fetch behavior through temp repositories where practical.
### Milestone 5: Add CLI workflow tests
- Capture CLI output for human-readable defaults.
- Test `--json` opt-ins.
- Add end-to-end workflows behind explicit `e2e` tag.
### Milestone 6: Coverage review and hardening
- Generate coverage profile.
- Add targeted tests for missed branches.
- Document any intentionally uncovered external/environmental branches.
- Run final checks:
```bash
gofmt -w .
go test ./...
go vet ./...
go test -cover ./...
```
## Completion checklist
- [x] Coverage baseline captured.
- [x] Unit tests added for all packages.
- [x] HTTP route and handler tests added.
- [x] CLI parser and output tests added.
- [x] Auth/token behavior tests added.
- [x] Repo permission tests added.
- [x] Collaborator permission tests added.
- [x] PR behavior tests added.
- [x] Git utility and Git HTTP tests added.
- [x] Backup helper tests added.
- [x] MySQL migration integration tests added.
- [ ] Optional e2e CLI workflow tests added.
- [x] `go test ./...` passes.
- [x] `go vet ./...` passes.
- [x] Coverage report reviewed.
- [x] Any intentionally uncovered environment-dependent paths documented.