@@ -16,12 +16,167 @@ uv run ruff check . --exclude examples/ --line-length 120
1616
1717## Testing
1818
19+ ### Unit Tests
20+
1921Run tests with pytest:
2022
2123``` bash
2224uv run pytest tests/ -v
2325```
2426
27+ ### Test Requirements
28+
29+ When adding new functionality:
30+
31+ 1 . ** Database methods** (` src/libkernelbot/leaderboard_db.py ` ):
32+ - Add tests to ` tests/test_leaderboard_db.py `
33+ - Test empty results, basic functionality, edge cases, and pagination
34+
35+ 2 . ** API endpoints** (` src/kernelbot/api/main.py ` ):
36+ - Add tests to ` tests/test_admin_api.py ` or create endpoint-specific test files
37+ - Test authentication, authorization (403), not found (404), and validation (400)
38+
39+ 3 . ** Regression tests** : Use the popcorn-cli against a local instance to verify end-to-end functionality
40+
41+ ### E2E Regression Testing with popcorn-cli
42+
43+ Full end-to-end testing requires running the API server locally and testing with popcorn-cli. This tests the complete flow from CLI through API to database.
44+
45+ #### Step 1: Start PostgreSQL
46+
47+ ``` bash
48+ # macOS with Homebrew
49+ brew services start postgresql@14
50+
51+ # Verify it's running
52+ pg_isready
53+ ```
54+
55+ #### Step 2: Create Database and Run Migrations
56+
57+ ``` bash
58+ # Create database (first time only)
59+ createdb kernelbot
60+
61+ # Run migrations
62+ export DATABASE_URL=" postgresql://$( whoami) @localhost:5432/kernelbot"
63+ uv run yoyo apply --database " $DATABASE_URL " src/migrations/
64+ ```
65+
66+ #### Step 3: Create a Test User
67+
68+ The CLI requires a registered user. Create one in the database:
69+
70+ ``` bash
71+ export DATABASE_URL=" postgresql://$( whoami) @localhost:5432/kernelbot"
72+ psql " $DATABASE_URL " -c " INSERT INTO leaderboard.user_info (id, user_name, cli_id, cli_valid)
73+ VALUES ('999999', 'testuser', 'test-cli-id-123', true)
74+ ON CONFLICT (id) DO UPDATE SET cli_id = 'test-cli-id-123', cli_valid = true;"
75+ ```
76+
77+ #### Step 4: Start the API Server
78+
79+ ``` bash
80+ cd src/kernelbot
81+
82+ # Set required environment variables
83+ export DATABASE_URL=" postgresql://$( whoami) @localhost:5432/kernelbot"
84+ export ADMIN_TOKEN=" your-admin-token-here" # Check .env for LOCAL_ADMIN_TOKEN
85+
86+ # Start API server (without Discord bot)
87+ uv run python main.py --api-only
88+
89+ # Server runs on http://localhost:8000
90+ ```
91+
92+ #### Step 5: Sync Leaderboards
93+
94+ Leaderboards must be synced from reference-kernels before testing submissions:
95+
96+ ``` bash
97+ curl -X POST " http://localhost:8000/admin/update-problems" \
98+ -H " Authorization: Bearer $ADMIN_TOKEN " \
99+ -H " Content-Type: application/json" \
100+ -d ' {"problem_set": "pmpp_v2"}'
101+ ```
102+
103+ #### Step 6: Configure popcorn-cli for Local Testing
104+
105+ Temporarily update ` ~/.popcorn.yaml ` to use test credentials:
106+
107+ ``` bash
108+ # Backup existing config
109+ cp ~ /.popcorn.yaml ~ /.popcorn.yaml.bak
110+
111+ # Set test CLI ID
112+ echo " cli_id: test-cli-id-123" > ~ /.popcorn.yaml
113+ ```
114+
115+ #### Step 7: Run CLI Commands
116+
117+ ``` bash
118+ cd /path/to/popcorn-cli
119+
120+ # Set API URL to local server
121+ export POPCORN_API_URL=http://localhost:8000
122+
123+ # Test various commands
124+ cargo run --release -- submissions list --leaderboard vectoradd_v2
125+ cargo run --release -- submissions show < ID>
126+ cargo run --release -- submissions delete < ID>
127+
128+ # Test submission (runs on Modal H100, requires Modal account)
129+ cargo run --release -- submit solution.py --gpu H100 --leaderboard vectoradd_v2 --mode test
130+ ```
131+
132+ #### Step 8: Restore Original Config
133+
134+ ``` bash
135+ cp ~ /.popcorn.yaml.bak ~ /.popcorn.yaml
136+ rm ~ /.popcorn.yaml.bak
137+ ```
138+
139+ #### Quick Reference: Testing API Endpoints Directly
140+
141+ ``` bash
142+ # List user submissions
143+ curl -s " http://localhost:8000/user/submissions?leaderboard=vectoradd_v2" \
144+ -H " X-Popcorn-Cli-Id: test-cli-id-123"
145+
146+ # Get submission details
147+ curl -s " http://localhost:8000/user/submissions/1" \
148+ -H " X-Popcorn-Cli-Id: test-cli-id-123"
149+
150+ # Delete submission
151+ curl -s -X DELETE " http://localhost:8000/user/submissions/1" \
152+ -H " X-Popcorn-Cli-Id: test-cli-id-123"
153+
154+ # Submit a file (multipart form)
155+ curl -s -X POST " http://localhost:8000/vectoradd_v2/H100/test" \
156+ -H " X-Popcorn-Cli-Id: test-cli-id-123" \
157+ -F " file=@solution.py"
158+ ```
159+
160+ #### Troubleshooting
161+
162+ - ** 401 Unauthorized** : CLI ID not in database or ` cli_valid ` is false
163+ - ** 404 Not Found** : Leaderboards not synced - run update-problems first
164+ - ** 500 Internal Error** : Check server logs in terminal, often a TypedDict vs object access issue
165+ - ** "Device not configured" from CLI** : Usually a TTY issue, try running with explicit env vars
166+
167+ ## Before Adding New Features
168+
169+ ** Important:** Check for existing code before implementing:
170+
171+ 1 . ** Database methods** : ` src/libkernelbot/leaderboard_db.py `
172+ 2 . ** Discord commands** : ` src/kernelbot/cogs/ `
173+ 3 . ** API endpoints** : ` src/kernelbot/api/main.py `
174+
175+ Reuse existing patterns:
176+ - ` validate_user_header ` / ` validate_cli_header ` for authentication
177+ - ` get_submission_by_id() ` , ` delete_submission() ` for submission operations
178+ - ` simple_rate_limit() ` for rate limiting
179+
25180## Local Development
26181
27182See ` SKILLS/test_bot.md ` for local testing setup instructions.
0 commit comments