Files
openobserve/tests/test-data/query-agent/queries/error_paths.json
T
Neha PandClaude Opus 4.7 9af9a47fea test: add error path, explain analyze, and concurrency stress tests for query agent (#12809)
## Summary
- **Phase 4 — Error Paths** (`test_4_error_paths.py`): 28 cases across 8
categories that send intentionally invalid SQL and assert 4xx not 5xx.
Self-contained, runs in ~24s without data dependency.
- **Phase 5 — Concurrency Stress** (`test_5_concurrency.py`): 26 queries
(2 per category) run simultaneously at 5/10/15 worker levels via
ThreadPoolExecutor. Each thread gets its own client. Catches deadlocks
and thread-safety bugs.
- **EXPLAIN ANALYZE** (`test_explain_analyze.py`): Verifies
EXPLAIN/EXPLAIN ANALYZE return 200 with plan output and no
`partial_error`. Also validates EXPLAIN ANALYZE on cross-schema
dot-notation queries returns 4xx (not 500 crash).
- **Fix**: `load_all_queries()` now skips JSON files without a
`"queries"` key.

## Test plan
- [x] Error path tests pass on pentest (28/28, all return 400)
- [ ] CI run: `rye run pytest tests/query_agent/test_4_error_paths.py
-v`
- [ ] CI run: `rye run pytest tests/query_agent/test_5_concurrency.py
-v`
- [ ] CI run: `rye run pytest tests/query_agent/test_explain_analyze.py
-v`

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-07-14 05:08:33 +00:00

269 lines
8.9 KiB
JSON

{
"description": "Error path validation — verifies the server returns proper 4xx client-error codes (not 5xx) for invalid inputs. Each case sends an intentionally bad query or payload and asserts the response stays in the 400-499 range.",
"cases": [
{
"id": "ERR_SYNTAX_01",
"category": "malformed_sql",
"description": "Typo in SELECT keyword",
"sql": "SELEC * FROM \"{stream}\"",
"payload_overrides": {},
"expect_status_min": 400,
"expect_status_max": 499
},
{
"id": "ERR_SYNTAX_02",
"category": "malformed_sql",
"description": "Incomplete WHERE clause (no condition)",
"sql": "SELECT * FROM \"{stream}\" WHERE",
"payload_overrides": {},
"expect_status_min": 400,
"expect_status_max": 499
},
{
"id": "ERR_SYNTAX_03",
"category": "malformed_sql",
"description": "Garbage / non-SQL input",
"sql": "FOOBAR BAZ QUX 12345 !@#$%",
"payload_overrides": {},
"expect_status_min": 400,
"expect_status_max": 499
},
{
"id": "ERR_SYNTAX_04",
"category": "malformed_sql",
"description": "Unclosed single-quoted string literal",
"sql": "SELECT * FROM \"{stream}\" WHERE facility_zone = 'unclosed",
"payload_overrides": {},
"expect_status_min": 400,
"expect_status_max": 499
},
{
"id": "ERR_SYNTAX_05",
"category": "malformed_sql",
"description": "Call to non-existent function",
"sql": "SELECT NONEXISTENT_FUNC_XYZ999(*) FROM \"{stream}\"",
"payload_overrides": {},
"expect_status_min": 400,
"expect_status_max": 499
},
{
"id": "ERR_SYNTAX_06",
"category": "malformed_sql",
"description": "Unterminated GROUP BY clause",
"sql": "SELECT facility_zone, COUNT(*) FROM \"{stream}\" GROUP BY",
"payload_overrides": {},
"expect_status_min": 400,
"expect_status_max": 499
},
{
"id": "ERR_TYPE_01",
"category": "type_mismatch",
"description": "Arithmetic on string literal",
"sql": "SELECT 'hello' + 5 FROM \"{stream}\"",
"payload_overrides": {},
"expect_status_min": 400,
"expect_status_max": 499
},
{
"id": "ERR_TYPE_02",
"category": "type_mismatch",
"description": "Comparing numeric column to non-numeric string literal",
"sql": "SELECT * FROM \"{stream}\" WHERE throughput_rate > 'not_a_number'",
"payload_overrides": {},
"expect_status_min": 400,
"expect_status_max": 499
},
{
"id": "ERR_TYPE_03",
"category": "type_mismatch",
"description": "String argument to numeric ROUND function",
"sql": "SELECT ROUND(facility_zone) FROM \"{stream}\"",
"payload_overrides": {},
"expect_status_min": 400,
"expect_status_max": 499
},
{
"id": "ERR_STREAM_01",
"category": "missing_stream",
"description": "Query references a stream that does not exist",
"sql": "SELECT * FROM \"nonexistent_stream_zyxwv_99999\"",
"payload_overrides": {},
"expect_status_min": 400,
"expect_status_max": 499
},
{
"id": "ERR_STREAM_02",
"category": "missing_stream",
"description": "Empty stream name (zero-length identifier)",
"sql": "SELECT * FROM \"\"",
"payload_overrides": {},
"expect_status_min": 400,
"expect_status_max": 499
},
{
"id": "ERR_STREAM_03",
"category": "missing_stream",
"description": "Cross-stream JOIN where one side does not exist",
"sql": "SELECT * FROM \"{stream}\" JOIN \"nonexistent_stream_zyxwv_99999\" ON true",
"payload_overrides": {},
"expect_status_min": 400,
"expect_status_max": 499
},
{
"id": "ERR_STREAM_04",
"category": "missing_stream",
"description": "Unclosed double-quoted stream identifier",
"sql": "SELECT * FROM \"unclosed_identifier",
"payload_overrides": {},
"expect_status_min": 400,
"expect_status_max": 499
},
{
"id": "ERR_TIME_01",
"category": "invalid_time_range",
"description": "start_time > end_time (reversed time window)",
"sql": "SELECT COUNT(*) FROM \"{stream}\"",
"payload_overrides": {
"start_time": 2000000000,
"end_time": 1000000000
},
"expect_status_min": 400,
"expect_status_max": 499
},
{
"id": "ERR_TIME_02",
"category": "invalid_time_range",
"description": "Missing start_time in query payload",
"sql": "SELECT COUNT(*) FROM \"{stream}\"",
"payload_overrides": {},
"payload_remove": [
"start_time"
],
"expect_status_min": 400,
"expect_status_max": 499
},
{
"id": "ERR_TIME_03",
"category": "invalid_time_range",
"description": "Missing end_time in query payload",
"sql": "SELECT COUNT(*) FROM \"{stream}\"",
"payload_overrides": {},
"payload_remove": [
"end_time"
],
"expect_status_min": 400,
"expect_status_max": 499
},
{
"id": "ERR_BODY_01",
"category": "invalid_request_body",
"description": "SQL field set to empty string",
"sql": "",
"payload_overrides": {},
"expect_status_min": 400,
"expect_status_max": 499
},
{
"id": "ERR_BODY_02",
"category": "invalid_request_body",
"description": "Missing 'sql' key in query payload",
"sql": "SELECT COUNT(*) FROM \"{stream}\"",
"payload_overrides": {},
"payload_remove": [
"sql"
],
"expect_status_min": 400,
"expect_status_max": 499
},
{
"id": "ERR_DDL_01",
"category": "disallowed_sql",
"description": "DROP TABLE in search SQL",
"sql": "DROP TABLE \"{stream}\"",
"payload_overrides": {},
"expect_status_min": 400,
"expect_status_max": 499
},
{
"id": "ERR_DDL_02",
"category": "disallowed_sql",
"description": "INSERT INTO in search SQL",
"sql": "INSERT INTO \"{stream}\" (facility_zone) VALUES ('test')",
"payload_overrides": {},
"expect_status_min": 400,
"expect_status_max": 499
},
{
"id": "ERR_DDL_03",
"category": "disallowed_sql",
"description": "ALTER TABLE in search SQL",
"sql": "ALTER TABLE \"{stream}\" ADD COLUMN foo STRING",
"payload_overrides": {},
"expect_status_min": 400,
"expect_status_max": 499
},
{
"id": "ERR_NESTING_01",
"category": "edge_case",
"description": "SELECT * without FROM clause",
"sql": "SELECT *",
"payload_overrides": {},
"expect_status_min": 400,
"expect_status_max": 499
},
{
"id": "ERR_NESTING_02",
"category": "edge_case",
"description": "Reference to non-existent column on an existing stream",
"sql": "SELECT nonexistent_column_xyz999 FROM \"{stream}\"",
"payload_overrides": {},
"expect_status_min": 400,
"expect_status_max": 499
},
{
"id": "ERR_EDGE_01",
"category": "edge_case",
"description": "Excessively large LIMIT value",
"sql": "SELECT * FROM \"{stream}\" LIMIT 99999999999",
"payload_overrides": {},
"expect_status_min": 400,
"expect_status_max": 499
},
{
"id": "ERR_EDGE_03",
"category": "edge_case",
"description": "Invalid histogram interval (negative value)",
"sql": "SELECT histogram(_timestamp, -60) FROM \"{stream}\"",
"payload_overrides": {},
"expect_status_min": 400,
"expect_status_max": 499
},
{
"id": "ERR_EDGE_04",
"category": "edge_case",
"description": "Deeply nested SELECT (30 levels)",
"sql": "SELECT * FROM (SELECT * FROM (SELECT * FROM (SELECT * FROM (SELECT * FROM (SELECT * FROM (SELECT * FROM (SELECT * FROM (SELECT * FROM (SELECT * FROM (SELECT * FROM (SELECT * FROM (SELECT * FROM (SELECT * FROM (SELECT * FROM (SELECT * FROM (SELECT * FROM (SELECT * FROM (SELECT * FROM (SELECT * FROM (SELECT * FROM (SELECT * FROM (SELECT * FROM (SELECT * FROM (SELECT * FROM (SELECT * FROM (SELECT * FROM (SELECT * FROM (SELECT * FROM (SELECT * FROM (SELECT * FROM \"{stream}\"))))))))))))))))))))))))))))))",
"payload_overrides": {},
"expect_status_min": 400,
"expect_status_max": 499
},
{
"id": "ERR_SCHEMA_01",
"category": "cross_schema",
"description": "Cross-schema JOIN with dot-notation table references",
"sql": "SELECT b.id, b.name FROM default AS a INNER JOIN enrich.rich AS b ON a.id = b.id LIMIT 1",
"payload_overrides": {},
"expect_status_min": 400,
"expect_status_max": 499
},
{
"id": "ERR_SCHEMA_02",
"category": "cross_schema",
"description": "Fully-qualified dot-notation reference on an existing stream",
"sql": "SELECT * FROM default.\"{stream}\" LIMIT 1",
"payload_overrides": {},
"expect_status_min": 400,
"expect_status_max": 499
}
]
}