This document describes all the tests available in PizzaSQL and how to run them.
PizzaSQL includes comprehensive unit tests for each major component written in Go.
pkg/lexer/lexer_test.go)Tests the SQL tokenizer/lexer that breaks SQL strings into tokens.
What it tests:
<=, >=, <>, !=, ||)SELECT, FROM, WHERE, JOIN, etc.-- and multi-line /* */)Run lexer tests:
make test-lexer
# or
go test -v ./pkg/lexer/...
pkg/parser/parser_test.go)Tests the SQL parser that converts tokens into Abstract Syntax Trees (AST).
What it tests:
*, column lists, aliases, DISTINCTRun parser tests:
make test-parser
# or
go test -v ./pkg/parser/...
pkg/analyzer/analyzer_test.go)Tests semantic analysis and type checking of SQL statements.
What it tests:
Run analyzer tests:
go test -v ./pkg/analyzer/...
pkg/executor/executor_test.go)Tests SQL execution and query evaluation.
What it tests:
Run executor tests:
go test -v ./pkg/executor/...
pkg/httpserver/server_test.go)Tests the HTTP API endpoints and request handling.
What it tests:
pretty, explain, readonly, timeoutRun HTTP server tests:
go test -v ./pkg/httpserver/...
The stress test suite (stress_test.js) is a comprehensive end-to-end test that validates the entire database system with realistic workloads.
Test Data Scale:
Test Duration: ~30 seconds
Total Queries: ~8,600
Success Rate: 100% (32/32 tests)
Verbose Output Example:
Testing Insert 1000 users...
→ Preparing 1000 user records... done
→ Executing batch insert... done
→ Verified 1000 users in database
✓ PASSED (121ms)
The most complex test validates a real-world analytics query:
SELECT
u.username,
COUNT(DISTINCT o.id) as order_count,
SUM(oi.quantity * oi.price) as total_spent,
AVG(oi.price) as avg_item_price
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
LEFT JOIN order_items oi ON o.id = oi.order_id
WHERE u.id <= 100
GROUP BY u.id, u.username
HAVING COUNT(o.id) > 0
ORDER BY total_spent DESC
LIMIT 10
This tests:
Dedicated test for DISTINCT functionality:
-- Insert test data with duplicates
INSERT INTO test_distinct VALUES (1, 'pending'), (2, 'completed'),
(3, 'pending'), (4, 'shipped'), (5, 'pending');
-- Without DISTINCT: Returns all 5 rows
SELECT status FROM test_distinct;
-- Result: pending, completed, pending, shipped, pending
-- With DISTINCT: Returns only 3 unique values
SELECT DISTINCT status FROM test_distinct ORDER BY status;
-- Result: completed, pending, shipped
What it validates:
Test output:
✅ DISTINCT is working correctly!
Expected 3 unique values, got 3
Values: completed, pending, shipped
PizzaKV must be running (for storage-backed tests):
# In a separate terminal
pizzakv -port 8085
Node.js (for stress test):
node --version # Should be v14+
# Run all Go tests
make test
# Run with verbose output
make test-v
# Run with coverage report
make test-cover
# Open coverage.html in browser
# Lexer only
make test-lexer
# Parser only
make test-parser
# All tests with race detection
make test-race
# Run benchmarks
make bench
Step 1: Build and start PizzaSQL server
make build
./pizzasql -http
Step 2: Run stress test (in another terminal)
./stress_test.js
Clean run with fresh database:
# Kill server, delete database, restart, and run test
pkill -9 pizzasql; rm -f .db && ./pizzasql -http > /dev/null 2>&1 & sleep 2 && ./stress_test.js
Edit stress_test.js to change test parameters:
const CONFIG = {
numUsers: 1000, // Number of test users
numProducts: 500, // Number of products
numOrders: 2000, // Number of orders
numOrderItems: 5000, // Number of order items
concurrentRequests: 10 // Concurrent query limit
};
Environment variables:
# Custom server URL
PIZZASQL_URL=http://localhost:9000 ./stress_test.js
# With API key
PIZZASQL_API_KEY=your-secret-key ./stress_test.js
Run make test-cover to generate coverage report. Expected coverage:
After running make test-cover, open coverage.html:
make test-cover
open coverage.html # macOS
# or
xdg-open coverage.html # Linux
$ make test-v
=== RUN TestLexerSingleTokens
--- PASS: TestLexerSingleTokens (0.00s)
=== RUN TestParseSelectStar
--- PASS: TestParseSelectStar (0.00s)
...
PASS
ok github.com/danfragoso/pizzasql-next/pkg/lexer 0.012s
ok github.com/danfragoso/pizzasql-next/pkg/parser 0.089s
╔════════════════════════════════════════════════════════════╗
║ TEST SUMMARY ║
╚════════════════════════════════════════════════════════════╝
Total tests: 32
Passed: 32 ✓
Failed: 0 ✗
Success rate: 100.0%
Total queries: 8,591
Total time: 29,805ms
Avg query time: 3.47ms
Queries/sec: 288
Metrics explained:
1. "PizzaKV not available"
# Start PizzaKV first
pizzakv -port 8085
2. Stress test timeout errors
# Increase server timeout (default: 5 minutes)
# Edit pkg/httpserver/handler.go, line 56:
timeout := 10 * time.Minute
3. "Connection refused" during stress test
# Make sure server is running
./pizzasql -http
# Check port 8080 is available
lsof -i :8080
4. Tests failing after code changes
# Rebuild and restart
make build
pkill -9 pizzasql
rm -f .db
./pizzasql -http &
sleep 2
./stress_test.js
To run all tests in CI:
#!/bin/bash
set -e
# Start PizzaKV
pizzakv -port 8085 &
PIZZAKV_PID=$!
# Run unit tests
make test-v
# Build server
make build
# Start server
./pizzasql -http > /dev/null 2>&1 &
PIZZASQL_PID=$!
sleep 3
# Run stress test
./stress_test.js
# Cleanup
kill $PIZZASQL_PID $PIZZAKV_PID
Create test file in same package:
// pkg/mypackage/myfile_test.go
package mypackage
import "testing"
func TestMyFunction(t *testing.T) {
result := MyFunction("input")
if result != "expected" {
t.Errorf("got %v, want %v", result, "expected")
}
}
Edit stress_test.js:
async function testMyFeature() {
const result = await query('SELECT ...');
assertEqual(result.rows.length, 10, 'Should return 10 rows');
}
// Add to test suite
await runTest('My feature', testMyFeature);
Run benchmarks to measure performance:
make bench
Example benchmark output:
BenchmarkExecuteSelect-8 1000 1123456 ns/op 24576 B/op 245 allocs/op
BenchmarkExecuteJoin-8 100 10234567 ns/op 245760 B/op 2456 allocs/op
Metrics:
Run make test && ./stress_test.js for complete validation! 🍕