Skip to content

Commit c1c4fbb

Browse files
committed
Fix test infrastructure: Docker detection, expander tests, update CLAUDE.md
- docker.Installed(): Also verify Docker daemon is running (not just binary in PATH). Without this, tests try Docker first, fail on docker pull, and t.Fatal instead of falling back to native databases. - expander_test.go: Use the same Docker/native detection chain as other tests instead of hardcoding connection URIs. The PostgreSQL test was hardcoded to password 'mysecretpassword' which doesn't match native setup (password 'postgres'). - CLAUDE.md: Replace manual apt/dpkg database setup instructions with sqlc-test-setup commands. Remove Step 1-4 manual instructions. All 29 test packages pass with zero skips. https://claude.ai/code/session_01CsyRwSkRxBcQoaQFVkMQsJ
1 parent a57b647 commit c1c4fbb

File tree

3 files changed

+92
-215
lines changed

3 files changed

+92
-215
lines changed

CLAUDE.md

Lines changed: 48 additions & 187 deletions
Original file line numberDiff line numberDiff line change
@@ -10,136 +10,74 @@ This document provides essential information for working with the sqlc codebase,
1010
- **Docker & Docker Compose** - Required for integration tests with databases (local development)
1111
- **Git** - For version control
1212

13-
## Claude Code Remote Environment Setup
13+
## Database Setup with sqlc-test-setup
1414

15-
When running in the Claude Code remote environment (or any environment without Docker), you can install PostgreSQL and MySQL natively. The test framework automatically detects and uses native database installations.
15+
The `sqlc-test-setup` tool (`cmd/sqlc-test-setup/`) automates installing and starting PostgreSQL and MySQL for tests. Both commands are idempotent and safe to re-run.
1616

17-
### Step 1: Configure apt Proxy (Required in Remote Environment)
18-
19-
The Claude Code remote environment requires an HTTP proxy for apt. Configure it:
20-
21-
```bash
22-
bash -c 'echo "Acquire::http::Proxy \"$http_proxy\";"' | sudo tee /etc/apt/apt.conf.d/99proxy
23-
```
24-
25-
### Step 2: Install PostgreSQL
17+
### Install databases
2618

2719
```bash
28-
sudo apt-get update
29-
sudo apt-get install -y postgresql
30-
sudo service postgresql start
20+
go run ./cmd/sqlc-test-setup install
3121
```
3222

33-
Configure PostgreSQL for password authentication:
34-
35-
```bash
36-
# Set password for postgres user
37-
sudo -u postgres psql -c "ALTER USER postgres PASSWORD 'postgres';"
38-
39-
# Enable password authentication for localhost
40-
echo 'host all all 127.0.0.1/32 md5' | sudo tee -a /etc/postgresql/16/main/pg_hba.conf
41-
sudo service postgresql reload
42-
```
23+
This will:
24+
- Configure the apt proxy (if `http_proxy` is set, e.g. in Claude Code remote environments)
25+
- Install PostgreSQL via apt
26+
- Download and install MySQL 9 from Oracle's deb bundle
27+
- Resolve all dependencies automatically
28+
- Skip anything already installed
4329

44-
Test the connection:
30+
### Start databases
4531

4632
```bash
47-
PGPASSWORD=postgres psql -h 127.0.0.1 -U postgres -c "SELECT 1;"
33+
go run ./cmd/sqlc-test-setup start
4834
```
4935

50-
### Step 3: Install MySQL 9
51-
52-
MySQL 9 is required for full test compatibility (includes VECTOR type support). Download and install from Oracle:
36+
This will:
37+
- Start PostgreSQL and configure password auth (`postgres`/`postgres`)
38+
- Start MySQL via `mysqld_safe` and set root password (`mysecretpassword`)
39+
- Verify both connections
40+
- Skip steps that are already done (running services, existing config)
5341

54-
```bash
55-
# Download MySQL 9 bundle
56-
curl -LO https://dev.mysql.com/get/Downloads/MySQL-9.1/mysql-server_9.1.0-1ubuntu24.04_amd64.deb-bundle.tar
57-
58-
# Extract packages
59-
mkdir -p /tmp/mysql9
60-
tar -xf mysql-server_9.1.0-1ubuntu24.04_amd64.deb-bundle.tar -C /tmp/mysql9
61-
62-
# Install packages (in order)
63-
cd /tmp/mysql9
64-
sudo dpkg -i mysql-common_*.deb \
65-
mysql-community-client-plugins_*.deb \
66-
mysql-community-client-core_*.deb \
67-
mysql-community-client_*.deb \
68-
mysql-client_*.deb \
69-
mysql-community-server-core_*.deb \
70-
mysql-community-server_*.deb \
71-
mysql-server_*.deb
72-
73-
# Make init script executable
74-
sudo chmod +x /etc/init.d/mysql
75-
76-
# Initialize data directory and start MySQL
77-
sudo mysqld --initialize-insecure --user=mysql
78-
sudo /etc/init.d/mysql start
79-
80-
# Set root password
81-
mysql -u root -e "ALTER USER 'root'@'localhost' IDENTIFIED BY 'mysecretpassword'; FLUSH PRIVILEGES;"
82-
```
42+
Connection URIs after start:
43+
- PostgreSQL: `postgres://postgres:postgres@127.0.0.1:5432/postgres?sslmode=disable`
44+
- MySQL: `root:mysecretpassword@tcp(127.0.0.1:3306)/mysql`
8345

84-
Test the connection:
46+
### Run tests
8547

8648
```bash
87-
mysql -h 127.0.0.1 -u root -pmysecretpassword -e "SELECT VERSION();"
88-
```
89-
90-
### Step 4: Run End-to-End Tests
91-
92-
With both databases running, the test framework automatically detects them:
93-
94-
```bash
95-
# Run all end-to-end tests
96-
go test --tags=examples -timeout 20m ./internal/endtoend/...
97-
98-
# Run example tests
99-
go test --tags=examples -timeout 20m ./examples/...
100-
101-
# Run the full test suite
49+
# Full test suite (requires databases running)
10250
go test --tags=examples -timeout 20m ./...
10351
```
10452

105-
The native database support (in `internal/sqltest/native/`) automatically:
106-
- Detects running PostgreSQL and MySQL instances
107-
- Starts services if installed but not running
108-
- Uses standard connection URIs:
109-
- PostgreSQL: `postgres://postgres:postgres@127.0.0.1:5432/postgres?sslmode=disable`
110-
- MySQL: `root:mysecretpassword@tcp(127.0.0.1:3306)/mysql`
111-
112-
### Running Tests
53+
## Running Tests
11354

114-
#### Basic Unit Tests (No Database Required)
55+
### Basic Unit Tests (No Database Required)
11556

11657
```bash
117-
# Simplest approach - runs all unit tests
11858
go test ./...
119-
120-
# Using make
121-
make test
12259
```
12360

124-
#### Full Test Suite with Integration Tests
61+
### Full Test Suite with Docker (Local Development)
12562

12663
```bash
127-
# Step 1: Start database containers
12864
docker compose up -d
129-
130-
# Step 2: Run all tests including examples
13165
go test --tags=examples -timeout 20m ./...
66+
```
67+
68+
### Full Test Suite without Docker (Remote / CI)
13269

133-
# Or use make for the full CI suite
134-
make test-ci
70+
```bash
71+
go run ./cmd/sqlc-test-setup install
72+
go run ./cmd/sqlc-test-setup start
73+
go test --tags=examples -timeout 20m ./...
13574
```
13675

137-
#### Running Specific Tests
76+
### Running Specific Tests
13877

13978
```bash
14079
# Test a specific package
14180
go test ./internal/config
142-
go test ./internal/compiler
14381

14482
# Run with verbose output
14583
go test -v ./internal/config
@@ -193,21 +131,6 @@ The `docker-compose.yml` provides test databases:
193131
- Password: `mysecretpassword`
194132
- Database: `dinotest`
195133

196-
### Managing Databases
197-
198-
```bash
199-
# Start databases
200-
make start
201-
# or
202-
docker compose up -d
203-
204-
# Stop databases
205-
docker compose down
206-
207-
# View logs
208-
docker compose logs -f
209-
```
210-
211134
## Makefile Targets
212135

213136
```bash
@@ -228,19 +151,6 @@ make start # Start database containers
228151
- **Test Command:** `gotestsum --junitfile junit.xml -- --tags=examples -timeout 20m ./...`
229152
- **Additional Checks:** `govulncheck` for vulnerability scanning
230153

231-
### Running Tests Like CI Locally
232-
233-
```bash
234-
# Install CI tools (optional)
235-
go install gotest.tools/gotestsum@latest
236-
237-
# Run tests with same timeout as CI
238-
go test --tags=examples -timeout 20m ./...
239-
240-
# Or use the CI make target
241-
make test-ci
242-
```
243-
244154
## Development Workflow
245155

246156
### Building Development Versions
@@ -255,37 +165,18 @@ go build -o ~/go/bin/sqlc-gen-json ./cmd/sqlc-gen-json
255165

256166
### Environment Variables for Tests
257167

258-
You can customize database connections:
259-
260-
**PostgreSQL:**
261-
```bash
262-
PG_HOST=127.0.0.1
263-
PG_PORT=5432
264-
PG_USER=postgres
265-
PG_PASSWORD=mysecretpassword
266-
PG_DATABASE=dinotest
267-
```
268-
269-
**MySQL:**
270-
```bash
271-
MYSQL_HOST=127.0.0.1
272-
MYSQL_PORT=3306
273-
MYSQL_USER=root
274-
MYSQL_ROOT_PASSWORD=mysecretpassword
275-
MYSQL_DATABASE=dinotest
276-
```
168+
You can override database connections via environment variables:
277169

278-
**Example:**
279170
```bash
280-
POSTGRESQL_SERVER_URI="postgres://postgres:mysecretpassword@localhost:5432/postgres" \
281-
go test -v ./...
171+
POSTGRESQL_SERVER_URI="postgres://postgres:postgres@localhost:5432/postgres?sslmode=disable"
172+
MYSQL_SERVER_URI="root:mysecretpassword@tcp(127.0.0.1:3306)/mysql?multiStatements=true&parseTime=true"
282173
```
283174

284175
## Code Structure
285176

286177
### Key Directories
287178

288-
- `/cmd/` - Main binaries (sqlc, sqlc-gen-json)
179+
- `/cmd/` - Main binaries (sqlc, sqlc-gen-json, sqlc-test-setup)
289180
- `/internal/cmd/` - Command implementations (vet, generate, etc.)
290181
- `/internal/engine/` - Database engine implementations
291182
- `/postgresql/` - PostgreSQL parser and converter
@@ -295,20 +186,20 @@ POSTGRESQL_SERVER_URI="postgres://postgres:mysecretpassword@localhost:5432/postg
295186
- `/internal/codegen/` - Code generation for different languages
296187
- `/internal/config/` - Configuration file parsing
297188
- `/internal/endtoend/` - End-to-end tests
189+
- `/internal/sqltest/` - Test database setup (Docker, native, local detection)
298190
- `/examples/` - Example projects for testing
299191

300192
### Important Files
301193

302194
- `/Makefile` - Build and test targets
303195
- `/docker-compose.yml` - Database services for testing
304196
- `/.github/workflows/ci.yml` - CI configuration
305-
- `/docs/guides/development.md` - Developer documentation
306197

307198
## Common Issues & Solutions
308199

309200
### Network Connectivity Issues
310201

311-
If you see errors about `storage.googleapis.com`, the Go proxy may be unreachable. Tests may still pass for packages that don't require network dependencies.
202+
If you see errors about `storage.googleapis.com`, the Go proxy may be unreachable. Use `GOPROXY=direct go mod download` to fetch modules directly from source.
312203

313204
### Test Timeouts
314205

@@ -326,19 +217,23 @@ go test -race ./...
326217

327218
### Database Connection Failures
328219

329-
Ensure Docker containers are running:
220+
If using Docker:
330221
```bash
331222
docker compose ps
332223
docker compose up -d
333224
```
334225

226+
If using sqlc-test-setup:
227+
```bash
228+
go run ./cmd/sqlc-test-setup start
229+
```
230+
335231
## Tips for Contributors
336232

337-
1. **Run tests before committing:** `make test-ci`
233+
1. **Run tests before committing:** `go test --tags=examples -timeout 20m ./...`
338234
2. **Check for race conditions:** Use `-race` flag when testing concurrent code
339235
3. **Use specific package tests:** Faster iteration during development
340-
4. **Start databases early:** `docker compose up -d` before running integration tests
341-
5. **Read existing tests:** Good examples in `/internal/engine/postgresql/*_test.go`
236+
4. **Read existing tests:** Good examples in `/internal/engine/postgresql/*_test.go`
342237

343238
## Git Workflow
344239

@@ -350,34 +245,18 @@ docker compose up -d
350245
### Committing Changes
351246

352247
```bash
353-
# Stage changes
354248
git add <files>
355-
356-
# Commit with descriptive message
357-
git commit -m "Brief description
358-
359-
Detailed explanation of changes.
360-
361-
🤖 Generated with [Claude Code](https://claude.com/claude-code)
362-
363-
Co-Authored-By: Claude <noreply@anthropic.com>"
364-
365-
# Push to remote
249+
git commit -m "Brief description of changes"
366250
git push -u origin <branch-name>
367251
```
368252

369253
### Rebasing
370254

371255
```bash
372-
# Update main
373256
git checkout main
374257
git pull origin main
375-
376-
# Rebase feature branch
377258
git checkout <feature-branch>
378259
git rebase main
379-
380-
# Force push rebased branch
381260
git push --force-with-lease origin <feature-branch>
382261
```
383262

@@ -387,21 +266,3 @@ git push --force-with-lease origin <feature-branch>
387266
- **Development Guide:** `/docs/guides/development.md`
388267
- **CI Configuration:** `/.github/workflows/ci.yml`
389268
- **Docker Compose:** `/docker-compose.yml`
390-
391-
## Recent Fixes & Improvements
392-
393-
### Fixed Issues
394-
395-
1. **Typo in create_function_stmt.go** - Fixed "Undertand" → "Understand"
396-
2. **Race condition in vet.go** - Fixed Client initialization using `sync.Once`
397-
3. **Nil pointer dereference in parse.go** - Fixed unsafe type assertion in primary key parsing
398-
399-
These fixes demonstrate common patterns:
400-
- Using `sync.Once` for thread-safe lazy initialization
401-
- Using comma-ok idiom for safe type assertions: `if val, ok := x.(Type); ok { ... }`
402-
- Adding proper nil checks and defensive programming
403-
404-
---
405-
406-
**Last Updated:** 2025-10-21
407-
**Maintainer:** Claude Code

internal/sqltest/docker/enabled.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,11 @@ func Installed() error {
1313
if _, err := exec.LookPath("docker"); err != nil {
1414
return fmt.Errorf("docker not found: %w", err)
1515
}
16+
// Verify the Docker daemon is actually running and accessible.
17+
// Without this check, tests will try Docker, fail on docker pull,
18+
// and t.Fatal instead of falling back to native database support.
19+
if out, err := exec.Command("docker", "info").CombinedOutput(); err != nil {
20+
return fmt.Errorf("docker daemon not available: %w\n%s", err, out)
21+
}
1622
return nil
1723
}

0 commit comments

Comments
 (0)