Run artifact

build/jq/tests/test_data_003_entries_containment.py

"""Behavioral coverage for object entries, membership, and containment."""

import json
import subprocess
from pathlib import Path


ROOT = Path(__file__).parents[1]


def run(program: str, value: object) -> list[object]:
    result = subprocess.run(
        [str(ROOT / "jq"), "-c", program],
        input=json.dumps(value) + "\n",
        text=True,
        capture_output=True,
        check=False,
    )
    assert result.returncode == 0, result.stderr
    return [json.loads(line) for line in result.stdout.splitlines()]


def test_keys_sort_objects_but_keys_unsorted_preserves_insertion_order() -> None:
    assert run("[keys, keys_unsorted]", {"b": 2, "a": 1, "c": 3}) == [
        [["a", "b", "c"], ["b", "a", "c"]]
    ]


def test_has_and_in_distinguish_object_keys_from_array_indices() -> None:
    assert run("[has(1), has(1.5)]", ["zero", "one"]) == [[True, False]]
    assert run("1 | in({\"1\":0})", None) == [False]
    assert run("1 | in([0,1])", None) == [True]


def test_contains_and_inside_recurse_through_objects_and_arrays() -> None:
    value = {"foo": 12, "bar": [1, 2, {"nested": 3}]}
    return_values = run(
        "[contains({foo:12, bar:[{nested:3}]}), "
        "inside({foo:12, bar:[1,2,{nested:3, extra:4}]})]",
        value,
    )
    assert return_values == [[True, True]]


def test_entry_conversion_accepts_supported_aliases_and_transforms_keys() -> None:
    assert run(
        "to_entries | map(.key |= \"KEY_\" + .) | from_entries",
        {"a": 1, "b": 2},
    ) == [{"KEY_a": 1, "KEY_b": 2}]


def test_with_entries_drops_empty_results_and_keeps_first_value() -> None:
    assert run(
        "with_entries(if .key == \"drop\" then empty else .value |= . + 1 end)",
        {"keep": 1, "drop": 2},
    ) == [{"keep": 2}]


def test_index_utilities_cover_overlaps_empty_search_and_insertion_points() -> None:
    assert run('[indices("aba"), index("aba"), rindex("aba"), index("")]', "xababababa") == [
        [[1, 3, 5, 7], 1, 7, None]
    ]
    assert run('[bsearch(0,1,2,3,4)]', [1, 2, 3]) == [[-1, 0, 1, 2, -4]]


def test_quantifiers_and_membership_use_all_generated_values() -> None:
    assert run('[any((false,true); .), all((true,false); .)]', None) == [[True, False]]
    assert run('[IN(range(10;20); range(10)), IN(range(5;20); range(10))]', None) == [
        [False, True]
    ]