test_buffer.py

Overview

`test_buffer.py` is a test module designed to validate the behavior of the `orjson` JSON parsing library under constrained memory conditions. Specifically, it verifies that `orjson.loads()` correctly raises a `JSONDecodeError` when attempting to parse a very large JSON string that exceeds available memory limits. The test is conditionally executed based on an environment variable that specifies the memory available for the test, ensuring it only runs in appropriate environments.

This file uses the `pytest` testing framework and relies on an environment variable `ORJSON_RUNNER_MEMORY_GIB` to determine the memory setting in GiB (gibibytes). It constructs a large JSON string and checks that parsing fails gracefully with the expected error message when memory is insufficient.


Detailed Explanation

Imports and Constants

import os
import pytest
import orjson

ORJSON_RUNNER_MEMORY_GIB = os.getenv("ORJSON_RUNNER_MEMORY_GIB", "")

Function: test_memory_loads

@pytest.mark.skipif(
    not ORJSON_RUNNER_MEMORY_GIB,
    reason="ORJSON_RUNNER_MEMORY_GIB not defined",
)
def test_memory_loads():
    buffer_factor = 12
    segment = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
    size = (
        (int(ORJSON_RUNNER_MEMORY_GIB) * 1024 * 1024 * 1024)
        // buffer_factor
        // len(segment)
    )
    doc = "".join(segment for _ in range(size))
    with pytest.raises(orjson.JSONDecodeError) as exc_info:
        _ = orjson.loads(doc)
    assert (
        str(exc_info.value)
        == "Not enough memory to allocate buffer for parsing: line 1 column 1 (char 0)"
    )

Purpose

This test verifies that `orjson.loads()` raises a `JSONDecodeError` with a specific error message when attempting to parse a large JSON string that exceeds the available memory buffer.

Parameters

Behavior and Workflow

  1. Conditional Execution:
    The test is skipped if ORJSON_RUNNER_MEMORY_GIB is not defined in the environment.

  2. Setup Large Input:

    • buffer_factor is set to 12, a divisor used to calculate the size of the JSON string relative to available memory.

    • segment is a fixed 64-character string of repeated 'a' characters.

    • size is calculated as the number of repeated segments to create a JSON string that will roughly consume available memory divided by buffer_factor and the length of the segment.

  3. Create Large Document:

    • Joins the segment string size times to create a very large string doc.

  4. Test for Exception:

    • Attempts to parse doc using orjson.loads().

    • Expects a JSONDecodeError to be raised due to insufficient memory to allocate the parsing buffer.

  5. Assertion:

    • Confirms that the exception message matches the expected error message:

      Not enough memory to allocate buffer for parsing: line 1 column 1 (char 0)
      

Return Value

Usage Example

This test is meant to be run in an environment where `ORJSON_RUNNER_MEMORY_GIB` is defined. Example:

export ORJSON_RUNNER_MEMORY_GIB=2
pytest test_buffer.py

This will run the test with 2 GiB memory considered for buffer allocation.


Important Implementation Details


Interaction with Other Parts of the System


Visual Diagram: Class and Function Structure

This file contains a single test function and no classes, so a flowchart representing the test function workflow is most appropriate.

flowchart TD
    Start["Start test_memory_loads()"]
    CheckEnv["Check ORJSON_RUNNER_MEMORY_GIB\n(environment variable)"]
    SkipTest["Skip test if variable not set"]
    CalculateSize["Calculate size of large string:\nsize = (memory in bytes) // buffer_factor // len(segment)"]
    CreateDoc["Create large string 'doc' by repeating segment 'size' times"]
    CallOrjson["Call orjson.loads(doc)"]
    ExpectError["Expect orjson.JSONDecodeError exception"]
    AssertMsg["Assert exception message matches\n\"Not enough memory to allocate buffer...\""]
    End["Test passes if assertion succeeds"]

    Start --> CheckEnv
    CheckEnv -- Not Set --> SkipTest
    CheckEnv -- Set --> CalculateSize
    SkipTest --> End
    CalculateSize --> CreateDoc
    CreateDoc --> CallOrjson
    CallOrjson --> ExpectError
    ExpectError --> AssertMsg
    AssertMsg --> End

Summary

This test helps maintain the reliability and stability of the JSON parsing library in extreme memory usage scenarios, providing confidence that memory allocation failures are handled predictably.