test_api.py
Overview
`test_api.py` is a comprehensive test suite designed to verify the correctness, robustness, and expected behavior of the `orjson` library's core JSON serialization and deserialization functions: `orjson.dumps` and `orjson.loads`. This file uses the `pytest` framework to define multiple test cases that cover a wide range of scenarios including:
Handling of simple data types.
Trailing whitespace and invalid characters in JSON input.
Recursion limits in JSON parsing.
Correctness of option flags and default handlers during serialization.
Validation of exceptions and error handling.
Signature and module metadata correctness.
Edge cases involving buffer sizes and null-termination of serialized bytes.
The tests ensure that `orjson` maintains compatibility with Python's built-in `json` module (for simple types), enforces recursion limits to prevent stack overflows, and validates option parameters rigorously.
Detailed Explanation of Classes and Methods
Class: TestApi
This class encapsulates all the test cases for the `orjson` library API.
Test Methods
Each method name starts with `test_` and uses `pytest` assertions or exception checks to validate behavior.
1. test_loads_trailing(self)
Purpose: Verify that
orjson.loads()correctly parses JSON strings with trailing whitespace.Behavior: Confirms that trailing whitespace characters do not affect parsing.
Example Usage:
assert orjson.loads("{}\n\t ") == {}
2. test_loads_trailing_invalid(self)
Purpose: Ensure
orjson.loads()raisesJSONDecodeErrorwhen invalid trailing characters are present.Example Usage:
pytest.raises(orjson.JSONDecodeError, orjson.loads, "{}\n\t a")
3. test_simple_json(self)
Purpose: Confirm that
orjson.dumps()produces byte strings identical tojson.dumps()encoded in UTF-8 for simple types.Simple Types Tested: Integer, float, negative integers,
None, string, booleans.Example Usage:
for obj in SIMPLE_TYPES: assert orjson.dumps(obj) == json.dumps(obj).encode("utf-8")
4. test_simple_round_trip(self)
Purpose: Validate that serializing and then deserializing simple types returns the original object.
Example Usage:
for obj in SIMPLE_TYPES: assert orjson.loads(orjson.dumps(obj)) == obj
5. test_loads_type(self)
Purpose: Confirm that passing invalid types (non-bytes or str JSON input) to
orjson.loads()raisesJSONDecodeError.Invalid Inputs Tested: Integer, float, list, dict, None.
Example Usage:
for val in (1, 3.14, [], {}, None): pytest.raises(orjson.JSONDecodeError, orjson.loads, val)
6. Recursion Limit Tests:
`orjson` enforces a recursion limit (`LOADS_RECURSION_LIMIT = 1024`) to prevent stack overflow when parsing deeply nested JSON. Several tests validate this behavior.
test_loads_recursion_partial(self)test_loads_recursion_valid_limit_array(self)test_loads_recursion_valid_limit_object(self)test_loads_recursion_valid_limit_mixed(self)test_loads_recursion_valid_excessive_array(self)
All these test cases construct JSON strings or bytes that exceed or reach the recursion limit with arrays or objects or combinations and verify that a `JSONDecodeError` is raised.
7. Pretty-Printed Recursion Limit Tests
These tests are similar to the recursion limit tests but include newlines and spaces (pretty formatting) in the JSON input to ensure whitespace does not affect recursion limit detection.
test_loads_recursion_valid_limit_array_pretty(self)test_loads_recursion_valid_limit_object_pretty(self)test_loads_recursion_valid_limit_mixed_pretty(self)test_loads_recursion_valid_excessive_array_pretty(self)
8. test_version(self)
Purpose: Check that
orjson.__version__matches a semantic versioning pattern.Example Usage:
assert re.match(r"^\d+\.\d+(\.\d+)?$", orjson.__version__)
9. test_valueerror(self)
Purpose: Confirm that
orjson.JSONDecodeErroris a subclass ofValueError.Example Usage:
pytest.raises(orjson.JSONDecodeError, orjson.loads, "{") pytest.raises(ValueError, orjson.loads, "{")
10. Option and Default Argument Tests
These tests validate that the `option` and `default` parameters of `orjson.dumps()` behave correctly, including error handling for invalid inputs:
test_optional_none(self): PassingNoneas option and default.test_option_not_int(self): Passing non-integer option raisesJSONEncodeError.test_option_invalid_int(self): Passing out-of-range large integer option.test_option_range_low(self): Option below valid range.test_option_range_high(self): Option above valid range.test_opts_multiple(self): Combining multiple options via bitwise OR produces correct output.test_default_positional(self): Invalid positional passing ofdefault.test_default_unknown_kwarg(self): Unknown keyword arguments raiseTypeError.test_default_empty_kwarg(self): Passing no extra kwargs works.test_default_twice(self): Passingdefaulttwice raisesTypeError.test_option_twice(self): Passingoptiontwice raisesTypeError.test_option_mixed(self): Mixing positional and keyword arguments for option and default.
**Example of combining options and default:**
class Custom:
def __str__(self):
return "zxc"
orjson.dumps(
[Custom(), datetime.datetime(2000, 1, 1, 2, 3, 4)],
default,
option=orjson.OPT_NAIVE_UTC,
)
# Output: b'["zxc","2000-01-01T02:03:04+00:00"]'
11. Signature and Module Metadata Tests
test_dumps_signature(self): Validates the signature oforjson.dumps.test_loads_signature(self): Validates the signature oforjson.loads.test_dumps_module_str(self): Checksorjson.dumps.__module__is"orjson".test_loads_module_str(self): Checksorjson.loads.__module__is"orjson".
12. Buffer and Null-Termination Tests
test_bytes_buffer(self): Serializes very large strings to ensure internal buffer grows correctly.test_bytes_null_terminated(self): Ensures the serialized output is null-terminated at the C level, avoiding ValueError during conversion.
Important Implementation Details
Recursion Limit Enforcement: The tests demonstrate that
orjson.loads()enforces a recursion limit of 1024 levels to prevent stack overflow from deeply nested JSON. This is critical for parser robustness and security.Strict Option Validation: The
optionparameter inorjson.dumps()must be an integer within a valid range; otherwise, aJSONEncodeErroris raised.Default Argument Handling: Only one
defaultfunction can be specified, and it must be passed correctly as a positional or keyword argument.Compatibility Checks: Simple data types serialize identically to Python's
jsonmodule, maintaining expected behavior for common cases.Error Hierarchy:
orjson.JSONDecodeErrorinherits fromValueError, maintaining compatibility with standard Python exceptions.Buffer Management: The test suite confirms that
orjson.dumps()manages internal buffers efficiently, even for very large strings.
Interaction with Other Parts of the System
This test file exercises the
orjsonlibrary, which is a high-performance JSON parsing and serialization module implemented in Rust with Python bindings.It interacts directly with:
orjson.dumps(obj, default=None, option=None)- serialization function.orjson.loads(obj)- deserialization function.orjson.JSONDecodeErrorandorjson.JSONEncodeError- exception classes.
It also verifies conformance with Python's standard
jsonmodule for simple types.The tests rely on
pytestfor running test assertions and exception handling.Tests involving datetime objects utilize Python's built-in
datetimemodule to check ISO8601 serialization with specific options.The test suite helps maintain
orjson's API stability and correctness across versions.
Usage Example
Running this test suite requires `pytest` and the `orjson` package installed in the environment. The tests can be executed with:
pytest test_api.py
Visual Diagram
The following Mermaid class diagram illustrates the structure of `test_api.py`. Since the file contains a single test class with multiple test methods (no properties), the diagram focuses on this class and its methods.
classDiagram
class TestApi {
+test_loads_trailing()
+test_loads_trailing_invalid()
+test_simple_json()
+test_simple_round_trip()
+test_loads_type()
+test_loads_recursion_partial()
+test_loads_recursion_valid_limit_array()
+test_loads_recursion_valid_limit_object()
+test_loads_recursion_valid_limit_mixed()
+test_loads_recursion_valid_excessive_array()
+test_loads_recursion_valid_limit_array_pretty()
+test_loads_recursion_valid_limit_object_pretty()
+test_loads_recursion_valid_limit_mixed_pretty()
+test_loads_recursion_valid_excessive_array_pretty()
+test_version()
+test_valueerror()
+test_optional_none()
+test_option_not_int()
+test_option_invalid_int()
+test_option_range_low()
+test_option_range_high()
+test_opts_multiple()
+test_default_positional()
+test_default_unknown_kwarg()
+test_default_empty_kwarg()
+test_default_twice()
+test_option_twice()
+test_option_mixed()
+test_dumps_signature()
+test_loads_signature()
+test_dumps_module_str()
+test_loads_module_str()
+test_bytes_buffer()
+test_bytes_null_terminated()
}
Summary
`test_api.py` is a critical quality assurance component for the `orjson` library, containing an extensive set of tests that cover serialization, deserialization, error handling, recursion limits, option validation, and metadata checks. This ensures that `orjson` behaves consistently, safely, and as expected across a broad spectrum of use cases, contributing to the reliability of applications that depend on it for JSON processing.