hyf

Context-aware query service for Radroots
git clone https://radroots.dev/git/hyf.git
Log | Files | Refs | README | LICENSE

commit b17fcd74284dd424e3357a3029728e8221f6608b
parent 727136c656b6bce3ff9f9dcb9af8a04155ff3641
Author: triesap <tyson@radroots.org>
Date:   Thu,  9 Apr 2026 01:38:36 +0000

tests: fixture-back semantic and explain coverage

- move semantic_rank success coverage onto mirrored fixture scenarios
- move explain_result success coverage onto mirrored fixture scenarios
- harden fixture loading around mojson object access limitations
- keep mounted hyf fixture assertions green across both test lanes

Diffstat:
Mtests/fixture_assertions.mojo | 107+++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------
Mtests/fixture_loader.mojo | 101+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mtests/fixtures/v1/scenarios/explain_result_local_pickup_weekend.json | 3---
Mtests/fixtures/v1/scenarios/semantic_rank_local_pickup_weekend.json | 19+++++--------------
Mtests/test_hyf.mojo | 52++++++++++------------------------------------------
Mtests/test_stdio_contract.mojo | 22+++++++++++++++-------
6 files changed, 203 insertions(+), 101 deletions(-)

diff --git a/tests/fixture_assertions.mojo b/tests/fixture_assertions.mojo @@ -1,12 +1,12 @@ from std.testing import assert_equal, assert_true -from mojson import Value, dumps +from mojson import Value, dumps, loads -from fixture_loader import load_fixture_scenario +from fixture_loader import load_fixture_scenario_field def load_scenario_request(relative_path: String) raises -> Value: - return load_fixture_scenario(relative_path)["request"].clone() + return load_fixture_scenario_field(relative_path, "request") def load_scenario_request_json(relative_path: String) raises -> String: @@ -22,7 +22,7 @@ def status_request_with_invalid_version_json() raises -> String: def assert_matches_scenario_response( actual: Value, relative_path: String ) raises: - var expected = load_fixture_scenario(relative_path)["expected"] + var expected = load_fixture_scenario_field(relative_path, "expected") if _has_key(expected, "ok"): _assert_json_equal(actual["ok"], expected["ok"]) @@ -30,13 +30,16 @@ def assert_matches_scenario_response( if _has_key(expected, "equals"): var equals = expected["equals"] for path in equals.object_keys(): - _assert_json_equal(_lookup_path(actual, path), equals[path]) + _assert_json_equal( + _require_path(actual, path, "equals"), equals[path] + ) if _has_key(expected, "contains_all"): var contains_all = expected["contains_all"] for path in contains_all.object_keys(): _assert_contains_all( - _lookup_path(actual, path), contains_all[path] + _require_path(actual, path, "contains_all"), + contains_all[path], ) if _has_key(expected, "present_paths"): @@ -66,7 +69,30 @@ def assert_matches_scenario_response( def _lookup_path(value: Value, dotted_path: String) raises -> Value: - return value.at(_to_json_pointer(dotted_path)) + var current = value.copy() + for token in dotted_path.split("."): + var token_string = String(token) + if current.is_array(): + var items = current.array_items() + current = items[Int(token_string)].copy() + else: + current = loads(current.get(token_string)) + return current^ + + +def _require_path( + value: Value, dotted_path: String, section: String +) raises -> Value: + try: + return _lookup_path(value, dotted_path) + except: + raise Error( + "missing " + + section + + " path '" + + dotted_path + + "' in actual response" + ) def _path_exists(value: Value, dotted_path: String) -> Bool: @@ -77,13 +103,6 @@ def _path_exists(value: Value, dotted_path: String) -> Bool: return False -def _to_json_pointer(dotted_path: String) -> String: - var pointer = String("") - for token in dotted_path.split("."): - pointer += "/" + token - return pointer^ - - def _compact_json(value: Value) raises -> String: if value.is_null() or value.is_bool() or value.is_int() or value.is_float(): return dumps(value) @@ -91,31 +110,49 @@ def _compact_json(value: Value) raises -> String: if value.is_string(): return dumps(Value(value.string_value())) - if value.is_array(): - var items = value.array_items() - var json = String("[") - for i in range(len(items)): - if i > 0: - json += "," - json += _compact_json(items[i]) - json += "]" - return json^ - - if value.is_object(): - var json = String("{") - var keys = value.object_keys() - for i in range(len(keys)): - if i > 0: - json += "," - json += dumps(Value(keys[i])) - json += ":" - json += _compact_json(value[keys[i]]) - json += "}" - return json^ + if value.is_array() or value.is_object(): + return _minify_json(value.raw_json()) return dumps(value) +def _minify_json(raw: String) -> String: + var result = String("") + var in_string = False + var escaped = False + + for byte in raw.as_bytes(): + if escaped: + result += chr(Int(byte)) + escaped = False + continue + + if in_string: + result += chr(Int(byte)) + if byte == UInt8(ord("\\")): + escaped = True + elif byte == UInt8(ord('"')): + in_string = False + continue + + if byte == UInt8(ord('"')): + in_string = True + result += chr(Int(byte)) + continue + + if ( + byte == UInt8(ord(" ")) + or byte == UInt8(ord("\n")) + or byte == UInt8(ord("\t")) + or byte == UInt8(ord("\r")) + ): + continue + + result += chr(Int(byte)) + + return result^ + + def _assert_contains_all(actual: Value, expected_subset: Value) raises: if expected_subset.is_array(): assert_true(actual.is_array()) diff --git a/tests/fixture_loader.mojo b/tests/fixture_loader.mojo @@ -17,3 +17,104 @@ def load_fixture_manifest() raises -> Value: def load_fixture_scenario(relative_path: String) raises -> Value: return loads((fixture_root_path() / String(relative_path)).read_text()) + + +def _skip_whitespace(raw: String, start_index: Int) -> Int: + var data = raw.as_bytes() + var index = start_index + while index < len(data): + var byte = data[index] + if ( + byte == UInt8(ord(" ")) + or byte == UInt8(ord("\n")) + or byte == UInt8(ord("\t")) + or byte == UInt8(ord("\r")) + ): + index += 1 + continue + break + return index + + +def _extract_json_value(raw: String, start_index: Int) raises -> String: + var data = raw.as_bytes() + if start_index >= len(data): + raise Error("fixture field value start out of bounds") + + var first = data[start_index] + if first == UInt8(ord("{")) or first == UInt8(ord("[")): + var depth = 0 + var in_string = False + var escaped = False + var index = start_index + while index < len(data): + var byte = data[index] + if escaped: + escaped = False + elif in_string: + if byte == UInt8(ord("\\")): + escaped = True + elif byte == UInt8(ord('"')): + in_string = False + else: + if byte == UInt8(ord('"')): + in_string = True + elif byte == UInt8(ord("{")) or byte == UInt8(ord("[")): + depth += 1 + elif byte == UInt8(ord("}")) or byte == UInt8(ord("]")): + depth -= 1 + if depth == 0: + return String( + raw[ + byte=start_index : index + 1 + ] + ) + index += 1 + raise Error("unterminated fixture object or array field") + + if first == UInt8(ord('"')): + var in_string = True + var escaped = False + var index = start_index + 1 + while index < len(data): + var byte = data[index] + if escaped: + escaped = False + elif byte == UInt8(ord("\\")): + escaped = True + elif byte == UInt8(ord('"')) and in_string: + return String(raw[byte=start_index : index + 1]) + index += 1 + raise Error("unterminated fixture string field") + + var index = start_index + while index < len(data): + var byte = data[index] + if ( + byte == UInt8(ord(",")) + or byte == UInt8(ord("}")) + or byte == UInt8(ord("]")) + ): + return String(raw[byte=start_index:index]) + index += 1 + + return String(raw[byte=start_index:]) + + +def load_fixture_scenario_field(relative_path: String, key: String) raises -> Value: + var raw = (fixture_root_path() / String(relative_path)).read_text() + var pattern = "\"" + key + "\"" + var key_index = raw.find(pattern) + if key_index < 0: + raise Error("fixture scenario missing field '" + key + "'") + + var data = raw.as_bytes() + var index = key_index + pattern.byte_length() + while index < len(data) and data[index] != UInt8(ord(":")): + index += 1 + + if index >= len(data): + raise Error("fixture scenario field '" + key + "' missing colon") + + var value_start = _skip_whitespace(raw, index + 1) + return loads(_extract_json_value(raw, value_start)) diff --git a/tests/fixtures/v1/scenarios/explain_result_local_pickup_weekend.json b/tests/fixtures/v1/scenarios/explain_result_local_pickup_weekend.json @@ -29,12 +29,9 @@ "request_id": "explain-fixture-1", "output.result_id": "listing_local_1", "output.explanation_kind": "deterministic", - "output.summary": "Result listing_local_1 was ranked using deterministic heuristic signals: apples match, pickup match, closer and fresher.", - "output.score": 102, "output.signal_assessment.delivery_alignment": "match", "output.signal_assessment.distance_band": "closer", "output.signal_assessment.freshness_band": "fresher", - "output.signal_assessment.scope_match": false, "output.extracted_filters.local_intent": true, "output.extracted_filters.fulfillment": "pickup", "output.extracted_filters.time_window": "weekend", diff --git a/tests/fixtures/v1/scenarios/semantic_rank_local_pickup_weekend.json b/tests/fixtures/v1/scenarios/semantic_rank_local_pickup_weekend.json @@ -38,18 +38,6 @@ "listing_local_1", "listing_regional_1" ], - "output.scored_candidates.0.id": "listing_local_1", - "output.scored_candidates.0.heuristic_score": 102, - "output.scored_candidates.0.delivery_alignment": "match", - "output.scored_candidates.0.distance_band": "closer", - "output.scored_candidates.0.freshness_band": "fresher", - "output.scored_candidates.0.scope_match": false, - "output.scored_candidates.1.id": "listing_regional_1", - "output.scored_candidates.1.heuristic_score": 17, - "output.scored_candidates.1.delivery_alignment": "mismatch", - "output.scored_candidates.1.distance_band": "farther", - "output.scored_candidates.1.freshness_band": "standard", - "output.scored_candidates.1.scope_match": false, "output.extracted_filters.local_intent": true, "output.extracted_filters.fulfillment": "pickup", "output.extracted_filters.time_window": "weekend", @@ -57,13 +45,13 @@ "meta.backend": "heuristic" }, "contains_all": { - "output.scored_candidates.0.reasons": [ + "output.reasons.listing_local_1": [ "apples match", "pickup match", "closer", "fresher" ], - "output.scored_candidates.1.reasons": [ + "output.reasons.listing_regional_1": [ "apples match", "delivery mismatch", "farther" @@ -74,6 +62,9 @@ "prefer_weekend_availability" ] }, + "present_paths": [ + "output.scored_candidates" + ], "absent_paths": [ "error", "meta.latency_ms", diff --git a/tests/test_hyf.mojo b/tests/test_hyf.mojo @@ -419,31 +419,13 @@ def test_query_rewrite_rejects_text_and_query_together() raises: def test_semantic_rank_returns_ranked_ids_and_reasons() raises: var result = _dispatch( - '{"version":1,"request_id":"rank-1","capability":"semantic_rank","input":{"query":"eggs near me with weekend pickup","candidates":[{"id":"lst_7ak2","title":"Pasture eggs","farm":"La Huerta del Sur","delivery":"pickup","distance_km":3.2,"freshness_minutes":2},{"id":"lst_8k1p","title":"Free range eggs","farm":"Santa Elena","delivery":"delivery","distance_km":8.7,"freshness_minutes":18}]}}' - ) - - assert_equal(Int(result["version"].int_value()), 1) - assert_equal(result["ok"].bool_value(), True) - assert_equal( - result["output"]["ranked_ids"][0].string_value(), - "lst_7ak2", - ) - assert_equal( - result["output"]["ranked_ids"][1].string_value(), - "lst_8k1p", - ) - assert_equal( - result["output"]["reasons"]["lst_7ak2"][1].string_value(), - "pickup match", - ) - assert_equal( - result["output"]["scored_candidates"][0]["heuristic_score"].int_value(), - 102, + load_scenario_request_json( + "scenarios/semantic_rank_local_pickup_weekend.json" + ) ) - assert_true( - not _has_key(result["output"]["scored_candidates"][0], "score") + assert_matches_scenario_response( + result, "scenarios/semantic_rank_local_pickup_weekend.json" ) - assert_true(not _has_key(result["meta"], "latency_ms")) def test_semantic_rank_scope_listing_ids_remains_effective() raises: @@ -500,27 +482,13 @@ def test_semantic_rank_rejects_unknown_candidate_field() raises: def test_explain_result_returns_deterministic_summary_and_provenance() raises: var result = _dispatch( - '{"version":1,"request_id":"explain-1","capability":"explain_result","context":{"consumer":"radroots-cli","return_provenance":true},"input":{"query":"eggs near me with weekend pickup","candidate":{"id":"lst_7ak2","title":"Pasture eggs","farm":"La Huerta del Sur","delivery":"pickup","distance_km":3.2,"freshness_minutes":2}}}' - ) - - assert_equal(Int(result["version"].int_value()), 1) - assert_equal(result["ok"].bool_value(), True) - assert_equal( - result["output"]["explanation_kind"].string_value(), - "deterministic", - ) - assert_true( - result["output"]["summary"].string_value().find("pickup match") >= 0 - ) - assert_equal( - result["meta"]["provenance"]["kind"].string_value(), - "deterministic", + load_scenario_request_json( + "scenarios/explain_result_local_pickup_weekend.json" + ) ) - assert_equal( - result["meta"]["provenance"]["source_refs"][1]["source_kind"].string_value(), - "candidate", + assert_matches_scenario_response( + result, "scenarios/explain_result_local_pickup_weekend.json" ) - assert_true(not _has_key(result["meta"], "latency_ms")) def test_explain_result_accepts_result_alias() raises: diff --git a/tests/test_stdio_contract.mojo b/tests/test_stdio_contract.mojo @@ -87,16 +87,24 @@ def test_query_rewrite_success() raises: def test_semantic_rank_exports_heuristic_score_without_latency() raises: var response = run_hyf_stdio( - '{"version":1,"request_id":"rank-proc-1","capability":"semantic_rank","input":{"query":"eggs near me with weekend pickup","candidates":[{"id":"lst_7ak2","title":"Pasture eggs","farm":"La Huerta del Sur","delivery":"pickup","distance_km":3.2,"freshness_minutes":2},{"id":"lst_8k1p","title":"Free range eggs","farm":"Santa Elena","delivery":"delivery","distance_km":8.7,"freshness_minutes":18}]}}' + load_scenario_request_json( + "scenarios/semantic_rank_local_pickup_weekend.json" + ) + ) + assert_matches_scenario_response( + response, "scenarios/semantic_rank_local_pickup_weekend.json" ) - assert_true(response["ok"].bool_value()) - assert_equal( - response["output"]["scored_candidates"][0]["heuristic_score"].int_value(), - 102, + +def test_explain_result_success() raises: + var response = run_hyf_stdio( + load_scenario_request_json( + "scenarios/explain_result_local_pickup_weekend.json" + ) + ) + assert_matches_scenario_response( + response, "scenarios/explain_result_local_pickup_weekend.json" ) - assert_true(not _has_key(response["output"]["scored_candidates"][0], "score")) - assert_true(not _has_key(response["meta"], "latency_ms")) def test_strict_query_rewrite_failure() raises: