"""Invariants for utils.fast_safe_load.

fast_safe_load is a drop-in for yaml.safe_load that prefers the libyaml
CSafeLoader C extension for speed. These tests assert the behavior contract
(it parses identically to safe_load across input shapes), not a snapshot of
any particular document.
"""

import io

import hermes_yaml as yaml

from utils import fast_safe_load


_DOCS = [
    "",  # empty document -> None
    "a: 1\nb: two\nc: 3.5\n",
    "list: [1, 2, 3]\nnested:\n  k: v\n  flag: true\n  empty: null\n",
    "name: skill-x\nmetadata:\n  hermes:\n    tags: [alpha, beta]\n    category: devops\n",
    "- one\n- two\n- three\n",  # top-level sequence
    "scalar string",  # bare scalar
]


def test_equivalent_to_safe_load_for_strings():
    for doc in _DOCS:
        assert fast_safe_load(doc) == yaml.safe_load(doc), repr(doc)


def test_equivalent_to_safe_load_for_file_objects():
    for doc in _DOCS:
        assert fast_safe_load(io.StringIO(doc)) == yaml.safe_load(io.StringIO(doc)), repr(doc)






def test_rejects_arbitrary_python_objects_like_safe_load():
    # Safe loaders must not construct arbitrary Python objects. This tag is
    # accepted by the unsafe Loader but rejected by Safe/CSafe loaders.
    dangerous = "!!python/object/apply:os.system ['echo pwned']\n"
    try:
        fast_safe_load(dangerous)
        raised = False
    except yaml.YAMLError:
        raised = True
    assert raised, "fast_safe_load must reject python/object tags like safe_load"
