hyf

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

test_domain.mojo (21865B)


      1 from std.testing import TestSuite, assert_equal, assert_raises, assert_true
      2 
      3 from hyf_core.domain.evidence import EvidenceRef
      4 from hyf_core.domain.source import (
      5     actor_id,
      6     farm_id,
      7     lot_id,
      8     need_id,
      9     revision,
     10     source_id,
     11     trusted_source,
     12 )
     13 
     14 
     15 def test_source_identity_accepts_valid_and_rejects_empty() raises:
     16     assert_equal(source_id("s1").value, "s1")
     17     assert_equal(actor_id("a1").value, "a1")
     18     assert_equal(farm_id("f1").value, "f1")
     19     assert_equal(need_id("n1").value, "n1")
     20     assert_equal(lot_id("l1").value, "l1")
     21     assert_equal(revision("r1").value, "r1")
     22     with assert_raises():
     23         _ = source_id("")
     24     with assert_raises():
     25         _ = revision(" r1")
     26     with assert_raises():
     27         _ = actor_id("a1 ")
     28 
     29 
     30 def test_trusted_source_preserves_revision() raises:
     31     var source = trusted_source("s1", "r1", "a1", "f1")
     32     assert_equal(source.source_id.value, "s1")
     33     assert_equal(source.revision.value, "r1")
     34     assert_equal(source.actor_id.value, "a1")
     35     assert_equal(source.farm_id.value, "f1")
     36 
     37 
     38 def main() raises:
     39     TestSuite.discover_tests[__functions_in_module()]().run()
     40 
     41 
     42 from hyf_core.domain.evidence import (
     43     record_field_evidence,
     44     selected_text,
     45     span_evidence,
     46     span_is_valid,
     47     validate_span_against_revision,
     48 )
     49 
     50 
     51 def test_evidence_span_byte_offsets_and_revision() raises:
     52     var text = "caf\u00e9: 80 lb"
     53     var evidence = span_evidence("s1", "r1", 7, 12, "span")
     54     assert_equal(evidence.kind, "span")
     55     assert_equal(selected_text(text, evidence), "80 lb")
     56     validate_span_against_revision(text, "r1", evidence)
     57     assert_true(span_is_valid(text, evidence))
     58 
     59     with assert_raises():
     60         _ = span_evidence("s1", "r1", 5, 4, "span")
     61 
     62 
     63 def test_evidence_rejects_out_of_range_and_revision_mismatch() raises:
     64     var text = "short"
     65     with assert_raises():
     66         _ = span_evidence("s1", "r1", -1, 2, "span")
     67     var beyond = span_evidence("s1", "r1", 0, 99, "span")
     68     with assert_raises():
     69         validate_span_against_revision(text, "r1", beyond)
     70     var good = span_evidence("s1", "r1", 0, 3, "span")
     71     with assert_raises():
     72         validate_span_against_revision(text, "r2", good)
     73     var field = record_field_evidence(
     74         "s1", "r1", "lot-1", "unreserved_quantity"
     75     )
     76     assert_equal(field.kind, "record_field")
     77     assert_equal(field.record_id.value(), "lot-1")
     78 
     79 
     80 from hyf_core.domain.field import (
     81     DecodedField,
     82     field_is_known,
     83     field_known_or,
     84     known_approximate_field,
     85     known_field,
     86     unresolved_field,
     87     validate_field_consistency,
     88 )
     89 
     90 
     91 def test_field_known_zero_distinct_from_unknown_and_false() raises:
     92     var zero = known_field("0", "span")
     93     assert_true(field_is_known(zero))
     94     assert_equal(field_known_or(zero, "?"), "0")
     95     var false_value = known_field("false", "model")
     96     assert_true(field_is_known(false_value))
     97     var unknown = unresolved_field("span")
     98     assert_true(not field_is_known(unknown))
     99     assert_equal(field_known_or(unknown, "?"), "?")
    100     validate_field_consistency(zero)
    101     validate_field_consistency(unknown)
    102     var approximate = known_approximate_field("80", "span")
    103     assert_equal(approximate.qualifier, "approximate")
    104 
    105 
    106 from hyf_core.domain.quantity import (
    107     new_quantity,
    108     quantity_add,
    109     quantity_compare,
    110     quantity_is_negative,
    111     quantity_rescale,
    112 )
    113 
    114 
    115 def test_quantity_exact_compare_and_scale() raises:
    116     var a = new_quantity(8000, 2, "kg", "mass", "exact")
    117     var b = new_quantity(80, 0, "kg", "mass", "exact")
    118     assert_equal(quantity_compare(a, b), 0)
    119     var c = new_quantity(50, 0, "kg", "mass", "exact")
    120     assert_equal(quantity_compare(c, b), -1)
    121     assert_equal(quantity_rescale(b, 2).value, 8000)
    122 
    123 
    124 def test_quantity_add_overflow_and_approximation() raises:
    125     var approx = new_quantity(80, 0, "lb", "mass", "approximate")
    126     var exact = new_quantity(5, 0, "lb", "mass", "exact")
    127     var total = quantity_add(approx, exact)
    128     assert_equal(total.value, 85)
    129     assert_equal(total.qualifier, "approximate")
    130     var huge = new_quantity(9223372036854775807, 0, "kg", "mass", "exact")
    131     with assert_raises():
    132         _ = quantity_add(huge, exact)
    133     var adjustment = new_quantity(-5, 0, "kg", "mass", "exact")
    134     assert_true(quantity_is_negative(adjustment))
    135 
    136 
    137 from hyf_core.domain.units import (
    138     apply_conversion,
    139     conversion_rule,
    140     unit_dimension,
    141 )
    142 
    143 
    144 def test_unit_dimensions_and_exact_mass_conversion() raises:
    145     assert_equal(unit_dimension("lb"), "mass")
    146     assert_equal(unit_dimension("ml"), "volume")
    147     assert_equal(unit_dimension("widget"), "unknown")
    148 
    149     var pounds = new_quantity(80, 0, "lb", "mass", "exact")
    150     var rule = conversion_rule("lb", "kg", 45359237, 100000000, "test-1")
    151     var kilograms = apply_conversion(pounds, rule)
    152     assert_equal(kilograms.unit, "kg")
    153     assert_equal(kilograms.dimension, "mass")
    154     assert_equal(kilograms.value, 3628738960)
    155     assert_equal(kilograms.scale, 8)
    156 
    157 
    158 def test_unit_conversion_rejects_dimension_mismatch_and_unknown_denominator() raises:
    159     with assert_raises():
    160         _ = conversion_rule("lb", "l", 1, 1, "v1")
    161     with assert_raises():
    162         _ = conversion_rule("lb", "kg", 1, 3, "v1")
    163     var pounds = new_quantity(1, 0, "lb", "mass", "exact")
    164     var kg_rule = conversion_rule("lb", "kg", 45359237, 100000000, "test-1")
    165     with assert_raises():
    166         _ = apply_conversion(new_quantity(1, 0, "kg", "mass", "exact"), kg_rule)
    167     _ = pounds
    168 
    169 
    170 from hyf_core.domain.pack import apply_pack_conversion, pack_rule
    171 
    172 
    173 def test_pack_conversion_known_and_rejections() raises:
    174     var boxes = new_quantity(20, 0, "box", "count", "exact")
    175     var rule = pack_rule("tomato.roma", "box", "kg", 5, 0, "pack-1")
    176     var mass = apply_pack_conversion("tomato.roma", boxes, rule)
    177     assert_equal(mass.value, 100)
    178     assert_equal(mass.unit, "kg")
    179     assert_equal(mass.dimension, "mass")
    180 
    181     with assert_raises():
    182         _ = apply_pack_conversion("carrot", boxes, rule)
    183     with assert_raises():
    184         _ = apply_pack_conversion(
    185             "tomato.roma", new_quantity(1, 0, "kg", "mass", "exact"), rule
    186         )
    187     with assert_raises():
    188         _ = pack_rule("tomato.roma", "box", "mystery", 5, 0, "pack-1")
    189 
    190 
    191 from hyf_core.domain.units import normalize_quantity_with_rule
    192 
    193 
    194 def test_normalization_preserves_approximation() raises:
    195     var approximate = new_quantity(80, 0, "lb", "mass", "approximate")
    196     var rule = conversion_rule("lb", "kg", 45359237, 100000000, "test-1")
    197     var normalized = normalize_quantity_with_rule(approximate, rule)
    198     assert_equal(normalized.qualifier, "approximate")
    199     assert_equal(normalized.unit, "kg")
    200     var exact = new_quantity(80, 0, "lb", "mass", "exact")
    201     assert_equal(normalize_quantity_with_rule(exact, rule).qualifier, "exact")
    202 
    203 
    204 from hyf_core.domain.price import (
    205     known_price,
    206     price_compare,
    207     price_is_known,
    208     unknown_price,
    209 )
    210 
    211 
    212 def test_price_unknown_distinct_from_zero_and_no_fx() raises:
    213     var unknown = unknown_price()
    214     assert_true(not price_is_known(unknown))
    215     assert_equal(unknown.amount, 0)
    216     var zero = known_price(0, 2, "CAD", "per_unit")
    217     assert_true(price_is_known(zero))
    218     var five = known_price(500, 2, "CAD", "per_unit")
    219     assert_equal(price_compare(five, zero), 1)
    220     with assert_raises():
    221         _ = price_compare(five, unknown)
    222     var usd = known_price(500, 2, "USD", "per_unit")
    223     with assert_raises():
    224         _ = price_compare(five, usd)
    225     with assert_raises():
    226         _ = known_price(1, 2, "", "per_unit")
    227     with assert_raises():
    228         _ = known_price(1, 2, "CAD", "per_kg_approx")
    229 
    230 
    231 from hyf_core.domain.time import (
    232     date_only,
    233     time_context,
    234     timestamp,
    235     timestamp_has_zone,
    236     zoneless_timestamp,
    237 )
    238 
    239 
    240 def test_time_types_distinguish_source_and_evaluation() raises:
    241     var source = timestamp(1789000000, "America/Vancouver")
    242     var ingestion = timestamp(1789000100, "America/Vancouver")
    243     var replay_later = timestamp(1789900000, "America/Vancouver")
    244     var context = time_context(source, ingestion, replay_later)
    245     assert_true(timestamp_has_zone(context.source_time))
    246     assert_true(timestamp_has_zone(context.evaluation_time))
    247     assert_true(
    248         context.evaluation_time.epoch_seconds
    249         > context.source_time.epoch_seconds
    250     )
    251     var d = date_only(2026, 9, 25)
    252     assert_equal(d.year, 2026)
    253     assert_equal(d.month, 9)
    254     assert_equal(d.day, 25)
    255     var zoneless = zoneless_timestamp(1789000000)
    256     assert_true(not timestamp_has_zone(zoneless))
    257     with assert_raises():
    258         _ = time_context(zoneless, ingestion, replay_later)
    259     with assert_raises():
    260         _ = date_only(2026, 13, 1)
    261     with assert_raises():
    262         _ = timestamp(1, "")
    263 
    264 
    265 from hyf_core.normalization.dates import (
    266     resolve_relative_expression,
    267     resolve_weekday,
    268     weekday_index,
    269 )
    270 
    271 
    272 def test_source_anchored_relative_date_replay() raises:
    273     var monday = date_only(2026, 9, 21)
    274     assert_equal(weekday_index(monday), 0)
    275     var friday = resolve_relative_expression("Friday", monday)
    276     assert_equal(friday.resolution, "resolved")
    277     assert_equal(friday.date.year, 2026)
    278     assert_equal(friday.date.month, 9)
    279     assert_equal(friday.date.day, 25)
    280     var same = resolve_weekday(monday, "Monday", "on_or_after")
    281     assert_equal(same.date.day, 21)
    282     var next = resolve_weekday(monday, "Monday", "next")
    283     assert_equal(next.date.day, 28)
    284     # Replay at a later evaluation time uses the same source reference.
    285     assert_equal(resolve_relative_expression("Friday", monday).date.day, 25)
    286 
    287 
    288 from hyf_core.normalization.dates import (
    289     LocalTimeResolution,
    290     resolve_local_time,
    291     window_contains,
    292 )
    293 
    294 
    295 def test_local_time_ambiguity_and_window_boundaries() raises:
    296     var offsets = List[Int]()
    297     offsets.append(-420)
    298     offsets.append(-480)
    299     var ambiguous = resolve_local_time(offsets)
    300     assert_equal(ambiguous.resolution, "unresolved")
    301     assert_equal(ambiguous.ambiguity, "ambiguous_local")
    302 
    303     var empty = List[Int]()
    304     assert_equal(resolve_local_time(empty).ambiguity, "missing_zone")
    305 
    306     var single = List[Int]()
    307     single.append(-420)
    308     assert_equal(resolve_local_time(single).resolution, "resolved")
    309 
    310     assert_true(window_contains(20717, 20721, "exclusive", 20721) == False)
    311     assert_true(window_contains(20717, 20721, "inclusive", 20721))
    312     assert_true(window_contains(20717, 20721, "exclusive", 20720))
    313     with assert_raises():
    314         _ = window_contains(1, 2, "half-open", 1)
    315 
    316 
    317 from hyf_core.domain.freshness import (
    318     freshness,
    319     record_recency_implies_harvest_age,
    320 )
    321 
    322 
    323 def test_freshness_separates_record_harvest_and_verification() raises:
    324     var value = freshness(5, 240, 60)
    325     assert_equal(value.record_age_minutes, 5)
    326     assert_equal(value.harvest_age_minutes, 240)
    327     assert_equal(value.verification_age_minutes, 60)
    328     assert_true(not record_recency_implies_harvest_age())
    329     with assert_raises():
    330         _ = freshness(-1, 0, 0)
    331 
    332 
    333 from hyf_core.domain.product import (
    334     product_is_resolved,
    335     product_matches,
    336     resolved_product,
    337     unresolved_product,
    338 )
    339 
    340 
    341 def test_product_reference_resolution_and_unknown() raises:
    342     var tomato = resolved_product("Roma tomatoes", "tomato.roma")
    343     var other = resolved_product("Roma tomato", "tomato.roma")
    344     assert_true(product_is_resolved(tomato))
    345     assert_true(product_matches(tomato, other))
    346     var unknown = unresolved_product("mystery greens")
    347     assert_true(not product_is_resolved(unknown))
    348     assert_true(not product_matches(tomato, unknown))
    349     with assert_raises():
    350         _ = resolved_product("x", "")
    351 
    352 
    353 from hyf_core.domain.supply_claim import (
    354     claim_confirms_inventory,
    355     claim_is_forecast,
    356     supply_claim,
    357 )
    358 
    359 
    360 def test_supply_claims_are_per_product_and_not_inventory() raises:
    361     var tomatoes = resolved_product("Roma tomatoes", "tomato.roma")
    362     var basil = resolved_product("Basil", "basil")
    363     var tomato_claim = supply_claim(
    364         "c1", tomatoes, "offered", "known", 80, 0, "lb", "approximate"
    365     )
    366     var basil_claim = supply_claim(
    367         "c2", basil, "unavailable", "unknown", 0, 0, "", "unknown"
    368     )
    369     assert_equal(tomato_claim.status, "offered")
    370     assert_equal(basil_claim.status, "unavailable")
    371     assert_true(not claim_confirms_inventory(tomato_claim))
    372     var forecast = supply_claim(
    373         "c3", basil, "forecast", "unknown", 0, 0, "", "unknown"
    374     )
    375     assert_true(claim_is_forecast(forecast))
    376     assert_true(not claim_is_forecast(tomato_claim))
    377     with assert_raises():
    378         _ = supply_claim(
    379             "c4", tomatoes, "probably", "known", 1, 0, "kg", "exact"
    380         )
    381 
    382 
    383 from hyf_core.domain.supply_change import (
    384     change_expands_to_farm,
    385     proposed_change,
    386 )
    387 
    388 
    389 def test_supply_change_operations_and_scoped_withdrawal() raises:
    390     var addition = proposed_change(
    391         "listing", Optional[String]("b1"), "addition", None
    392     )
    393     assert_equal(addition.operation, "addition")
    394     var remaining = proposed_change(
    395         "listing", Optional[String]("b1"), "remaining", None
    396     )
    397     assert_equal(remaining.operation, "remaining")
    398     var replacement = proposed_change(
    399         "listing", Optional[String]("b1"), "replacement", None
    400     )
    401     assert_equal(replacement.operation, "replacement")
    402     # Ambiguous withdrawal target must not expand to whole-farm stock.
    403     var ambiguous = proposed_change("listing", None, "withdrawal", None)
    404     assert_equal(ambiguous.operation, "unresolved")
    405     assert_true(ambiguous.unresolved)
    406     assert_true(not change_expands_to_farm(ambiguous))
    407     var correction = proposed_change("product", None, "correction", None)
    408     assert_equal(correction.operation, "unresolved")
    409     with assert_raises():
    410         _ = proposed_change("galaxy", Optional[String]("x"), "addition", None)
    411 
    412 
    413 from hyf_core.domain.review import review_add, review_clear, review_required
    414 
    415 
    416 def test_review_state_optional_price_does_not_block_withdrawal_does() raises:
    417     var clear = review_clear()
    418     assert_true(not clear.required)
    419     var blocked = review_required("withdrawal.target", "ambiguous_target")
    420     assert_true(blocked.required)
    421     assert_equal(len(blocked.clarifications), 1)
    422     var extended = review_add(blocked, "quantity.unreserved", "stock_unknown")
    423     assert_equal(len(extended.clarifications), 2)
    424 
    425 
    426 from hyf_core.domain.clarification import (
    427     apply_clarification,
    428     clarification_evidence,
    429     clarification_is_stale,
    430 )
    431 
    432 
    433 def test_clarification_refines_without_overwriting_original() raises:
    434     var original = known_field("80", "span")
    435     var evidence = clarification_evidence(
    436         "quantity.unreserved", "farm-source-1", "r2", "60 lb unreserved"
    437     )
    438     var refined = apply_clarification(original, evidence, "60")
    439     assert_equal(original.value.value(), "80")
    440     assert_equal(refined.value.value(), "60")
    441     assert_true(not clarification_is_stale(evidence, "r2"))
    442     assert_true(clarification_is_stale(evidence, "r3"))
    443 
    444 
    445 from hyf_core.domain.demand import (
    446     Condition,
    447     DemandLine,
    448     condition,
    449     condition_is_exclusion,
    450     demand_line,
    451     missing_information_is_prohibition,
    452 )
    453 
    454 
    455 def test_demand_lines_and_condition_strength() raises:
    456     var tomatoes = resolved_product("tomatoes", "tomato")
    457     var lines = List[DemandLine]()
    458     var conditions_a = List[Condition]()
    459     conditions_a.append(
    460         condition("fulfillment", "mandatory", Optional[String]("delivery"))
    461     )
    462     conditions_a.append(
    463         condition(
    464             "fulfillment_excluded", "excluded", Optional[String]("pickup")
    465         )
    466     )
    467     lines.append(demand_line("l1", tomatoes, "known", 25, 0, conditions_a))
    468     var conditions_b = List[Condition]()
    469     conditions_b.append(
    470         condition("grade", "permitted", Optional[String]("seconds"))
    471     )
    472     lines.append(demand_line("l2", tomatoes, "unknown", 0, 0, conditions_b))
    473     assert_equal(len(lines), 2)
    474     assert_true(condition_is_exclusion(lines[0].conditions[1]))
    475     assert_true(not condition_is_exclusion(lines[0].conditions[0]))
    476     assert_true(not missing_information_is_prohibition())
    477     with assert_raises():
    478         _ = condition("grade", "maybe", Optional[String]("x"))
    479 
    480 
    481 from hyf_core.domain.snapshot import (
    482     SupplySnapshot,
    483     snapshot_identity,
    484     snapshot_unreserved_known,
    485     supply_snapshot,
    486 )
    487 
    488 
    489 def test_supply_snapshot_revisions_and_unknown_unreserved() raises:
    490     var tomatoes = resolved_product("Roma tomatoes", "tomato.roma")
    491     var known = supply_snapshot(
    492         "lot-1", "l1", "farm-1", tomatoes, "known", 50, 0, "kg"
    493     )
    494     var other_revision = supply_snapshot(
    495         "lot-1", "l2", "farm-1", tomatoes, "known", 30, 0, "kg"
    496     )
    497     assert_true(snapshot_unreserved_known(known))
    498     assert_true(snapshot_identity(known) != snapshot_identity(other_revision))
    499     var unknown = supply_snapshot(
    500         "lot-2", "l1", "farm-1", tomatoes, "unknown", 0, 0, "kg"
    501     )
    502     assert_true(not snapshot_unreserved_known(unknown))
    503 
    504 
    505 from hyf_core.domain.eligibility import (
    506     ConstraintAssessment,
    507     compose_eligibility,
    508     constraint_assessment,
    509 )
    510 
    511 
    512 def test_eligibility_precedence() raises:
    513     var checks = List[ConstraintAssessment]()
    514     checks.append(
    515         constraint_assessment("product", "pass", True, "product_mismatch")
    516     )
    517     checks.append(
    518         constraint_assessment("quantity", "unknown", True, "stock_unknown")
    519     )
    520     checks.append(
    521         constraint_assessment(
    522             "preference", "unknown", False, "evidence_insufficient"
    523         )
    524     )
    525     assert_equal(compose_eligibility(checks), "conditional")
    526 
    527     var failing = List[ConstraintAssessment]()
    528     failing.append(
    529         constraint_assessment("quantity", "fail", True, "quantity_insufficient")
    530     )
    531     failing.append(
    532         constraint_assessment("window", "unknown", True, "window_mismatch")
    533     )
    534     assert_equal(compose_eligibility(failing), "ineligible")
    535 
    536     var optional_only = List[ConstraintAssessment]()
    537     optional_only.append(
    538         constraint_assessment(
    539             "preference", "unknown", False, "evidence_insufficient"
    540         )
    541     )
    542     assert_equal(compose_eligibility(optional_only), "eligible")
    543     with assert_raises():
    544         _ = constraint_assessment("product", "maybe", True, "x")
    545 
    546 
    547 from hyf_core.domain.plan import (
    548     Allocation,
    549     LotCapacity,
    550     MatchPlan,
    551     allocation,
    552     match_plan,
    553     plan_conservation_violations,
    554 )
    555 
    556 
    557 def test_plan_conservation_across_lots() raises:
    558     var lots = List[LotCapacity]()
    559     lots.append(LotCapacity(lot_id="lot-1", revision="l1", value=30, scale=0))
    560     lots.append(LotCapacity(lot_id="lot-2", revision="l1", value=40, scale=0))
    561     var allocations = List[Allocation]()
    562     allocations.append(allocation("lot-1", "l1", "line-1", 30, 0))
    563     allocations.append(allocation("lot-2", "l1", "line-1", 40, 0))
    564     var plan = match_plan("p1", "farm-1", allocations)
    565     assert_equal(len(plan_conservation_violations(plan, lots)), 0)
    566 
    567     var over = List[Allocation]()
    568     over.append(allocation("lot-1", "l1", "line-1", 31, 0))
    569     var bad = match_plan("p2", "farm-1", over)
    570     assert_true(len(plan_conservation_violations(bad, lots)) > 0)
    571 
    572     var shared = List[Allocation]()
    573     shared.append(allocation("lot-1", "l1", "line-1", 20, 0))
    574     shared.append(allocation("lot-1", "l1", "line-2", 20, 0))
    575     var shared_plan = match_plan("p3", "farm-1", shared)
    576     assert_true(len(plan_conservation_violations(shared_plan, lots)) > 0)
    577 
    578 
    579 from hyf_core.domain.coverage import (
    580     Coverage,
    581     coverage,
    582     no_match_is_global_absence,
    583     unsupported_is_no_supply,
    584 )
    585 
    586 
    587 def test_coverage_limitations_do_not_claim_global_absence() raises:
    588     var unsupported = List[String]()
    589     unsupported.append("multi_supplier")
    590     var value = coverage(
    591         True, 10, 2, "single_supplier_compatible_lots", unsupported
    592     )
    593     assert_equal(value.scope, "supplied_only")
    594     assert_true(value.truncated)
    595     assert_equal(len(value.unsupported), 1)
    596     assert_true(not no_match_is_global_absence())
    597     assert_true(not unsupported_is_no_supply())
    598 
    599 
    600 from hyf_core.domain.execution import (
    601     ExecutionMeta,
    602     execution_is_business_outcome,
    603     execution_meta,
    604 )
    605 
    606 
    607 def test_execution_metadata_is_separate_from_business_outcome() raises:
    608     var complete = execution_meta(
    609         "complete", 0, None, Optional[String]("qb1"), None
    610     )
    611     assert_equal(complete.status, "complete")
    612     var degraded = execution_meta(
    613         "degraded", 0, None, None, Optional[String]("provider_degraded")
    614     )
    615     assert_equal(degraded.status, "degraded")
    616     assert_true(not execution_is_business_outcome())
    617     with assert_raises():
    618         _ = execution_meta("degraded", 0, None, None, None)
    619     with assert_raises():
    620         _ = execution_meta("weird", 0, None, None, None)
    621 
    622 
    623 from hyf_core.normalization.candidates import (
    624     Candidate,
    625     candidate_kinds,
    626     discover_candidates,
    627 )
    628 
    629 
    630 def test_candidate_discovery_spans_and_unknown_products() raises:
    631     var products = List[String]()
    632     products.append("roma tomatoes")
    633     var units = List[String]()
    634     units.append("lb")
    635     var dates = List[String]()
    636     dates.append("friday")
    637     var candidates = discover_candidates(
    638         "Got about 80 lb of Roma tomatoes. Can deliver Friday.",
    639         products,
    640         units,
    641         dates,
    642     )
    643     var kinds = candidate_kinds(candidates)
    644     assert_true(len(kinds) == 3)
    645     var saw_quantity = False
    646     for candidate in candidates:
    647         if candidate.kind == "quantity":
    648             assert_equal(candidate.text, "80 lb")
    649             saw_quantity = True
    650     assert_true(saw_quantity)
    651 
    652     var unknown_products = List[String]()
    653     unknown_products.append("kohlrabi")
    654     var empty_units = List[String]()
    655     var empty_dates = List[String]()
    656     assert_equal(
    657         len(
    658             discover_candidates(
    659                 "mystery greens", unknown_products, empty_units, empty_dates
    660             )
    661         ),
    662         0,
    663     )