44 lines
4.6 KiB
Markdown
44 lines
4.6 KiB
Markdown
# QA: PostgreSQL database driver
|
|
|
|
Backend only. Go tests in test/, black-box, no live server by default.
|
|
|
|
Decisions: DB_DRIVER=postgres (alias postgresql), gorm.io/driver/postgres (pgx, pure Go), shared DB_* vars plus DB_SSLMODE, pure-Go logical dump backup, `task test:postgres` against postgres:16 and postgres:17, SQLite or MySQL to PostgreSQL migration is a documented manual export/import only.
|
|
|
|
## Automated, no server (task test)
|
|
1. Registry: contains sqlite, mysql and postgres. Alias "postgresql" resolves to postgres. "oracle" returns `unsupported database driver "oracle"`.
|
|
2. Env validation: table-driven over Driver selection and Missing PostgreSQL variable. Invalid DB_SSLMODE or a non-numeric pool var returns an error naming the variable. DB_SSLMODE is ignored under sqlite and mysql. MySQL validation unchanged.
|
|
3. DSN builder: table-driven over the DSN scenario. Parse the output with the pgx config parser and assert host, port, database, sslmode and the UTC time zone. Round-trip a password such as `s3cr3t/Value@42:x 'q'`. The form used in errors never contains the password.
|
|
4. Settings.DataDir under postgres: DATA_DIR wins, DB_FILE ignored.
|
|
5. Fail fast without a server: closed 127.0.0.1 port, 1s connect timeout. Error has the "Unable to open the database" prefix, mentions host and port, not the password.
|
|
6. Pool settings via a stub opener or the real test below.
|
|
7. Regression: the existing SQLite and MySQL tests pass unchanged. A pre-change SQLite fixture is unchanged after Migrate.
|
|
8. Dump writer: reuse the existing formatter tests. Add PostgreSQL value formatting with a fake row source: bool as true/false, bytea hex escapes, timestamptz in UTC, NULL, identifier and string quoting.
|
|
9. Migrate dialect handling: no MySQL table options are applied under postgres (tableOptionsFor).
|
|
|
|
## Automated, real server (task test:postgres)
|
|
Setup: the task runs `docker run` for postgres:16 then postgres:17, waits with pg_isready, exports RENEWCMS_TEST_POSTGRES_DSN, runs `go test -tags nofrontend ./test/... -run Postgres -count=1`, then removes the container. Tests t.Skip when the variable is unset. Repository contract tests are parameterised over sqlite, mysql and postgres with a fresh database each.
|
|
10. Migrate on an empty database: tables and indexes via information_schema and pg_indexes, role backfill, idempotent second run.
|
|
11. User create/read, case-sensitive username and email, duplicate email, ErrUserNotFound. After the unique violation the next query on the same pool succeeds.
|
|
12. Invite accept twice, accept with a taken username (invite stays unaccepted), renew with unchanged values.
|
|
13. Image duplicates grouping and counts (GROUP BY strictness), search with % and _ and its case rule, filename backfill listing.
|
|
14. Article body 1 MB, unicode title, title lookup, online filter, listing order and pagination parity with sqlite.
|
|
15. API key unique hashed_key, revoke, last_used.
|
|
16. Zero-time round trip, UTC times.
|
|
17. Purge settings upsert.
|
|
18. Backup on a populated database: .sql file, 3-file retention, replay into a second empty database gives identical rows, no password in the file, next insert after replay gets a fresh id.
|
|
19. Wrong password, missing database and TLS-required-but-disabled fail with the "Unable to open the database" prefix and no password.
|
|
|
|
## Build and lint
|
|
20. `task lint:go` and `task test` pass. `task test:postgres` passes on 16 and 17 (record both; NOT RUN if Docker is unavailable).
|
|
21. `CGO_ENABLED=0 go build -tags nofrontend ./...` passes. Cross-compile the 6 `task release` targets.
|
|
22. `task mutate` impact: none (useCases only).
|
|
23. No comment lines in the added Go files.
|
|
24. Layering: `go list -deps` on useCases and domain shows no pgx or gorm. Only api/dependecyInjection.go builds the postgres config.
|
|
|
|
## Manual (needs Compose and real SMTP)
|
|
25. docker-compose.postgres.yml: renewcms plus a postgres service with a named volume and a pg_isready healthcheck, depends_on service_healthy, DB_DRIVER=postgres, DB_HOST=postgres, DATA_DIR=/data. `docker compose up`: /healthz 200, register, log in, create an article, restart the stack, data persists.
|
|
26. Stop the postgres container and start renewcms: clear error, no password in the logs.
|
|
27. In the Docker image (uid 10001), trigger the backup path and confirm the .sql file lands under /data/backups.
|
|
28. Docs: .env.example, docker.env.example, docs/configuration.md, docs/docker.md, docs/deployment.md, docs/development.md and the docs/architecture.md "Storage and database seams" section list DB_DRIVER=postgres, DB_SSLMODE and the manual migration note. DB_SSLMODE goes into cmd/server/main.go envDefaults.
|
|
29. SQLite default end to end with no new vars set behaves as before.
|