Testing JSON Parser Edge Cases in AutoGPT
This test suite validates JSON parsing functionality, focusing on handling malformed JSON inputs and edge cases. It tests both fixable and unfixable JSON formatting scenarios using pytest framework.
Test Coverage Overview
Implementation Analysis
Technical Details
Best Practices Demonstrated
significant-gravitas/autogpt
classic/forge/forge/json/test_parsing.py
import json
import pytest
from .parsing import json_loads
_JSON_FIXABLE: list[tuple[str, str]] = [
# Missing comma
('{"name": "John Doe" "age": 30,}', '{"name": "John Doe", "age": 30}'),
("[1, 2 3]", "[1, 2, 3]"),
# Trailing comma
('{"name": "John Doe", "age": 30,}', '{"name": "John Doe", "age": 30}'),
("[1, 2, 3,]", "[1, 2, 3]"),
# Extra comma in object
('{"name": "John Doe",, "age": 30}', '{"name": "John Doe", "age": 30}'),
# Extra newlines
('{"name": "John Doe",
"age": 30}', '{"name": "John Doe", "age": 30}'),
("[1, 2,
3]", "[1, 2, 3]"),
# Missing closing brace or bracket
('{"name": "John Doe", "age": 30', '{"name": "John Doe", "age": 30}'),
("[1, 2, 3", "[1, 2, 3]"),
# Different numerals
("[+1, ---2, .5, +-4.5, 123.]", "[1, -2, 0.5, -4.5, 123]"),
('{"bin": 0b1001, "hex": 0x1A, "oct": 0o17}', '{"bin": 9, "hex": 26, "oct": 15}'),
# Broken array
(
'[1, 2 3, "yes" true, false null, 25, {"obj": "var"}',
'[1, 2, 3, "yes", true, false, null, 25, {"obj": "var"}]',
),
# Codeblock
(
'```json
{"name": "John Doe", "age": 30}
```',
'{"name": "John Doe", "age": 30}',
),
# Multiple problems
(
'{"name":"John Doe" "age": 30
"empty": "","address": '
"// random comment
"
'{"city": "New York", "state": "NY"},'
'"skills": ["Python" "C++", "Java",""],',
'{"name": "John Doe", "age": 30, "empty": "", "address": '
'{"city": "New York", "state": "NY"}, '
'"skills": ["Python", "C++", "Java", ""]}',
),
# All good
(
'{"name": "John Doe", "age": 30, "address": '
'{"city": "New York", "state": "NY"}, '
'"skills": ["Python", "C++", "Java"]}',
'{"name": "John Doe", "age": 30, "address": '
'{"city": "New York", "state": "NY"}, '
'"skills": ["Python", "C++", "Java"]}',
),
("true", "true"),
("false", "false"),
("null", "null"),
("123.5", "123.5"),
('"Hello, World!"', '"Hello, World!"'),
("{}", "{}"),
("[]", "[]"),
]
_JSON_UNFIXABLE: list[tuple[str, str]] = [
# Broken booleans and null
("[TRUE, False, NULL]", "[true, false, null]"),
# Missing values in array
("[1, , 3]", "[1, 3]"),
# Leading zeros (are treated as octal)
("[0023, 015]", "[23, 15]"),
# Missing quotes
('{"name": John Doe}', '{"name": "John Doe"}'),
# Missing opening braces or bracket
('"name": "John Doe"}', '{"name": "John Doe"}'),
("1, 2, 3]", "[1, 2, 3]"),
]
@pytest.fixture(params=_JSON_FIXABLE)
def fixable_json(request: pytest.FixtureRequest) -> tuple[str, str]:
return request.param
@pytest.fixture(params=_JSON_UNFIXABLE)
def unfixable_json(request: pytest.FixtureRequest) -> tuple[str, str]:
return request.param
def test_json_loads_fixable(fixable_json: tuple[str, str]):
assert json_loads(fixable_json[0]) == json.loads(fixable_json[1])
def test_json_loads_unfixable(unfixable_json: tuple[str, str]):
assert json_loads(unfixable_json[0]) != json.loads(unfixable_json[1])