You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
PostgreSQL test runner and coverage tool — pure Go (no CGO, no external CLI tools).
4
+
5
+
## Execution Pipeline
6
+
7
+
1.`internal/discovery` — walk dirs, classify `.sql` files as `Source` or `Test` (`*_test.sql`)
8
+
2.`internal/parser` — token-split SQL into `[]*Statement` using `pashagolub/pglex` (pure Go lexer, not pg_query_go)
9
+
3.`internal/instrument` — per-statement: PL/pgSQL/SQL function bodies get `PERFORM pg_notify('coverage_signal', '<relPath>:<startByteOffset>:<byteLength>')` injected; all other DDL/DML is marked implicitly covered
10
+
4.`internal/database` — create isolated temp DB (`pgcov_test_<yyyymmdd_hhmmss>_<4-byte hex>`), deploy instrumented sources, execute the test `.sql` file, then `DROP DATABASE ... WITH (FORCE)`
11
+
5.`internal/database.Listener` — dedicated `pgx.Conn` running `LISTEN coverage_signal`; forwards signals to a buffered channel (size 1000)
12
+
6.`internal/coverage.Collector` — thread-safe (`sync.Mutex`) aggregation of signals into `Coverage.Positions[file]["startPos:length"]`
**Parallelism**: `runner.WorkerPool` fans out `*testJob` over a buffered channel; each worker owns its own temp DB — no shared state at all.
16
+
17
+
**Config flow**: `pkg/types.Config` is the canonical struct; aliased in `internal/cli`; CLI flags applied via `ApplyFlagsToConfig`; default coverage output path `.pgcov/coverage.json`.
18
+
19
+
## Key Files
20
+
21
+
| Path | Role |
22
+
|---|---|
23
+
|`cmd/pgcov/main.go`|`run` / `report` subcommands via `urfave/cli/v3`; wires flags → `ApplyFlagsToConfig`|
|`internal/testutil/postgres.go`| Docker-based Postgres setup for integration tests (`testcontainers-go`) |
35
+
36
+
## Build & Test
37
+
38
+
```bash
39
+
# Build (no CGO required — pure Go)
40
+
go build ./cmd/pgcov
41
+
42
+
# Unit tests
43
+
go test ./...
44
+
45
+
# Integration tests (require Docker)
46
+
go test ./... -run Integration
47
+
```
48
+
49
+
VS Code tasks: **Build pgcov** (`Ctrl+Shift+B`), **Unit Test**, **Coverage Report**.
50
+
51
+
## Project-Specific Conventions
52
+
53
+
**Signal ID format** — `"<relPath>:<startByteOffset>:<byteLength>"` (byte offsets, not line numbers). Always use `instrument.ParseSignalID` to parse, never split manually.
54
+
55
+
**Source scoping** — each test only sees sources from its own directory. `filterSourcesByDirectory` in `executor.go` enforces this. Never pass sources from sibling directories.
56
+
57
+
**Logging** — no logger package exists. Use `fmt.Printf(...)` guarded by `if verbose`. Do not add a logger dependency.
58
+
59
+
**Error wrapping** — always `fmt.Errorf("context: %w", err)`, never bare `return err`.
60
+
61
+
**Adding a report format** — implement `report.Formatter` (`Format`, `FormatString`, `Name`), add a `case` in `GetFormatter`, add `_test.go` alongside.
62
+
63
+
**Adding a config flag** — add field to `pkg/types.Config`, wire in `ApplyFlagsToConfig` in `internal/cli/config.go`, support `PGCOV_*` env var via `urfave/cli/v3``EnvVars`.
64
+
65
+
## Hard Constraints
66
+
67
+
- Never use `psql` or shell exec — always `pgx` directly
68
+
- Never require PostgreSQL extensions
69
+
- Instrumentation must not change semantic behavior of tested SQL
70
+
- Each test gets its own temp DB — no shared DB state, ever
71
+
- Do not add CGO dependencies — the project is intentionally pure Go
0 commit comments