Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import json
import math
import os
import re
from collections import Counter
from dataclasses import replace
from pathlib import Path
Expand Down Expand Up @@ -1347,6 +1348,20 @@ def test_each_coarse_band_lists_exactly_its_native_rows_labels(artifact):
}


# The native income rows whose label repeats the previous row's upper endpoint
# ($50,000, $80,000 and $300,000). Each opens a coarse band, and right closure
# leaves the shared endpoint in the band below.
_INCOME_SHARED_ENDPOINT_ROWS = {"row_60", "row_90", "row_230"}


def _label_cents(label):
"""The cents at each end of a "$a - $b" label."""
lower, upper = re.fullmatch(
r"\$([\d,]+) - \$([\d,]+)", " ".join(label.split())
).groups()
return 100 * int(lower.replace(",", "")), 100 * int(upper.replace(",", ""))


def test_each_coarse_row_selects_its_native_rows_committed_labels():
"""R2C-16 without the feed: membership checked against committed rows.

Expand All @@ -1355,6 +1370,11 @@ def test_each_coarse_row_selects_its_native_rows_committed_labels():
equals theirs. For each measure the 12 bands' native rows tile rows 50 to
244 once, in order. The feed audit above checks the same labels against the
feed, which CI doesn't load.

Each finite band's first label starts $1 above the band's lower cut (at the
cut, for the three pinned rows) and its last label ends at its
``upper_cent``, so no native row can move to a neighbouring band in both
lists unnoticed. The open tail's one label is "Over $1,000,000".
"""
native = {
row["name"]: row
Expand Down Expand Up @@ -1385,3 +1405,29 @@ def test_each_coarse_row_selects_its_native_rows_committed_labels():
assert labels == expected, row["name"]
for kind, members in tiled.items():
assert members == [f"row_{n}" for n in range(50, 245)], kind
(table,) = (
table
for table in _document("reference_intervals.json")["tables"]
if table["id"] == "ird_taxable_income_standin_ty2024"
)
coarse = {row["name"]: row for row in _rows()}
cut, shared = table["first_lower_cut_cents"], set()
for band in table["bands"]:
for name in (band["count_reference"], band["amount_reference"]):
row = coarse[name]
(labels,) = row["ledger_selector"]["dimension_values"].values()
if band["upper_cent"] is None:
assert [" ".join(label.split()) for label in labels] == [
"Over $1,000,000"
], name
assert cut == 100_000_000, name
continue
lower, _ = _label_cents(labels[0])
_, upper = _label_cents(labels[-1])
if lower == cut:
shared.add(row["metadata"]["native_rows"].split(",")[0])
else:
assert lower == cut + 100, name
assert upper == band["upper_cent"], name
cut = band["upper_cent"]
assert shared == _INCOME_SHARED_ENDPOINT_ROWS
Original file line number Diff line number Diff line change
Expand Up @@ -834,6 +834,18 @@ def test_target_profile_coverage_passes_on_the_toy_with_income_required(toy):
assert "income" in entry["parameters"]["required_families"]
row = _gate_row(run, "toy_target_profile_coverage")
assert row["status"] == "passed", row["failures"]
# The gate needs one income match; this pins all six stand-in rows, so a
# row that leaves the income family turns the test red while the gate
# still passes. The binding hands the gate the problem's row names, which
# read name@period (target_kernels.py), so the comparison drops the period.
from test_support.microcosm_build.transport_nz_toy import toy_standin_table

matched = row["details"]["matches_by_requirement"]["income"]
assert sorted(name.partition("@")[0] for name in matched) == sorted(
band[role]
for band in toy_standin_table()["bands"]
for role in ("count_reference", "amount_reference")
)


def test_measurement_prefit_fails_the_toy_only_on_its_unwired_evidence(toy):
Expand All @@ -847,6 +859,7 @@ def test_measurement_prefit_fails_the_toy_only_on_its_unwired_evidence(toy):

from test_support.microcosm_build.transport_nz_toy import (
TOY_PREFIT_EVIDENCE,
TOY_PREFIT_SUPPORT,
TOY_STANDIN_TABLE,
)

Expand All @@ -856,6 +869,18 @@ def test_measurement_prefit_fails_the_toy_only_on_its_unwired_evidence(toy):
gate for gate in gates["gates"] if gate["gate"] == "measurement_prefit"
]
assert list(TOY_PREFIT_EVIDENCE) == packaged["parameters"]["required_evidence"]
(entry,) = [
gate
for gate in fixture.spec["resources"]["gates"]["gates"]
if gate["id"] == "toy_measurement_prefit"
]
# R2C-3's ratio bounds stand on the toy; only the two support floors scale
# down to forty households.
assert set(entry["parameters"]) == set(packaged["parameters"])
for key in ("roster_total_bounds", "band_bounds", "maximum_discrepant_bands"):
assert entry["parameters"][key] == packaged["parameters"][key], key
for key, value in TOY_PREFIT_SUPPORT.items():
assert entry["parameters"][key] == value, key
row = _gate_row(run, "toy_measurement_prefit")
assert row["gate"] == "measurement_prefit"
assert row["status"] == "failed"
Expand Down Expand Up @@ -954,7 +979,7 @@ def test_property_a_positive_standin_above_the_first_cut_lands_in_one_band(
in none, and x <= 0 is ``excluded`` and in none. The table, as NZ's, has
no nil band and a first cut above zero.
"""
from hypothesis import given, settings
from hypothesis import example, given, settings
from hypothesis import strategies as st

from microcosm.build.reference_intervals import interval_indicators
Expand All @@ -971,6 +996,13 @@ def test_property_a_positive_standin_above_the_first_cut_lands_in_one_band(
factor = Fraction(11, 10)
cuts = [factor * cut for cut in (TOY_STANDIN_FIRST_CUT, *TOY_STANDIN_CUTS)]
signed = st.integers(-150_000, 150_000)
# Wages at zero and on each aged cut, one either side, with every other
# component zero: random draws almost never land on an edge.
edges = [
(value + step, *(0 for _ in TOY_STANDIN_COMPONENTS[1:]))
for value in (0, *(int(cut) for cut in cuts))
for step in (-1, 0, 1)
]

@settings(max_examples=150, deadline=None)
@given(
Expand All @@ -980,6 +1012,7 @@ def test_property_a_positive_standin_above_the_first_cut_lands_in_one_band(
max_size=12,
)
)
@example(edges)
def check(records):
columns = {
column: pd.Series([row[i] for row in records], dtype="int64")
Expand Down Expand Up @@ -1007,6 +1040,29 @@ def check(records):
check()


def test_the_toy_standin_measure_keeps_the_packaged_central_rules():
"""The toy declaration differs from ``measures.central`` only in its columns.

Its entity, add-backs, floor and scale equal the packaged declaration's, it
names the same three outputs, and both give every component sign +1, so
the toy's gates run on the packaged measure's arithmetic. The toy sums
seven toy columns where the packaged measure sums ten.
"""
from importlib.resources import files

from test_support.microcosm_build.transport_nz_toy import toy_standin_declaration

packaged = json.loads(
(files("microcosm.build") / "nz" / "income_measurements.json").read_text()
)["measures"]["central"]["declaration"]
toy = toy_standin_declaration()
for key in ("entity", "add_backs", "floor", "scale"):
assert toy[key] == packaged[key], key
assert set(toy["outputs"]) == set(packaged["outputs"])
assert {row["sign"] for row in toy["components"]} == {1}
assert {row["sign"] for row in packaged["components"]} == {1}


def test_without_the_toy_standin_its_six_rows_refuse_activation_by_name(toy):
"""The drop-the-node mutant, built in the test: A's proof fails closed."""
from test_support.microcosm_build.transport_nz_toy import (
Expand Down
Loading