import io
p='.github/ci/classify-changes-selftest.py'
s=io.open(p,encoding='utf-8',newline='').read(); nl='\r\n' if '\r\n' in s else '\n'
anchor='# [unit->REQ-CI-PUSH-DOCS-ONLY-THIN]\nclass OtherEventsAndErrors(unittest.TestCase):'.replace('\n',nl)
assert s.count(anchor)==1
add='''def lines(git, **env):
    """(CLASSIFY_PROBE line, CLASSIFY line) from one real main() call."""
    out = io.StringIO()
    cc.main(git=git, env=env, out=out)
    text = out.getvalue().splitlines()
    probe = [l for l in text if l.startswith("CLASSIFY_PROBE ")]
    verdict = [l for l in text if l.startswith("CLASSIFY ")]
    assert len(probe) == 1 and len(verdict) == 1, text
    return probe[0], verdict[0]


def push_lines(git, before=BEFORE, forced="false"):
    return lines(git, GITHUB_EVENT_NAME="push", GITHUB_SHA=SHA,
                 CLASSIFY_BEFORE=before, CLASSIFY_FORCED=forced)


# [unit->REQ-CI-CLASSIFY-PROBE-WITNESS]
class ProbeWitnessesTheMechanism(unittest.TestCase):
    """IR-148: the log names WHICH step connected before..sha and whether the
    graph was shallow AT DECISION TIME, so a dead deepen cannot hide behind
    a correct-looking verdict on a warm workspace."""

    def test_graft_arm_names_the_deepen_that_connected(self):
        # The #258 field shape: before PRESENT at step 0 but grafted off; only
        # the first deepen connects it. The probe must say deepen50, not step0.
        g = FakeGit({(BEFORE, SHA): ["docs/a.md"]}, reachable_after=1, ancestor_after_fetches=1)
        probe, verdict = push_lines(g)
        self.assertEqual(probe, "CLASSIFY_PROBE connected_at=deepen50 shallow=true")
        self.assertEqual(verdict, "CLASSIFY code=false reason=docs-only")

    def test_already_connected_names_step0(self):
        g = FakeGit({(BEFORE, SHA): ["docs/a.md"]}, reachable_after=1)
        self.assertEqual(push_lines(g)[0], "CLASSIFY_PROBE connected_at=step0 shallow=true")

    def test_second_deepen_is_named(self):
        g = FakeGit({(BEFORE, SHA): ["docs/a.md"]}, reachable_after=1, ancestor_after_fetches=2)
        self.assertEqual(push_lines(g)[0], "CLASSIFY_PROBE connected_at=deepen500 shallow=true")

    def test_undecidable_and_unreachable_name_none(self):
        g = FakeGit({(BEFORE, SHA): ["docs/a.md"]}, reachable_after=1, ancestor=False, shallow=True)
        self.assertEqual(push_lines(g), ("CLASSIFY_PROBE connected_at=none shallow=true",
                                         "CLASSIFY code=true reason=before-undecidable"))
        g = FakeGit({(BEFORE, SHA): ["docs/a.md"]}, reachable_after=0)
        self.assertEqual(push_lines(g), ("CLASSIFY_PROBE connected_at=none shallow=true",
                                         "CLASSIFY code=true reason=before-unreachable"))

    def test_complete_graph_non_ancestor_reports_shallow_false(self):
        g = FakeGit({(BEFORE, SHA): ["docs/a.md"]}, reachable_after=1, ancestor=False, shallow=False)
        self.assertEqual(push_lines(g), ("CLASSIFY_PROBE connected_at=none shallow=false",
                                         "CLASSIFY code=true reason=before-not-ancestor"))

    def test_shallow_is_read_once_at_decision_time(self):
        # One read feeds both the probe and the undecidable/not-ancestor
        # split; a second, later read would be a different measurement.
        for kw in ({"reachable_after": 1}, {"reachable_after": 1, "ancestor": False},
                   {"reachable_after": 1, "ancestor_after_fetches": 1}):
            g = FakeGit({(BEFORE, SHA): ["docs/a.md"]}, **kw)
            push_lines(g)
            reads = [c for c in g.calls if c[0] == "rev-parse"]
            self.assertEqual(reads, [("rev-parse", "--is-shallow-repository")], kw)

    def test_paths_that_never_probe_say_so(self):
        self.assertEqual(push_lines(FakeGit(), before="0" * 40)[0],
                         "CLASSIFY_PROBE connected_at=not-probed shallow=n/a")
        self.assertEqual(push_lines(FakeGit(), forced="true")[0],
                         "CLASSIFY_PROBE connected_at=not-probed shallow=n/a")
        pr = FakeGit({("HEAD^1", "HEAD"): ["docs/a.md"]})
        self.assertEqual(lines(pr, GITHUB_EVENT_NAME="pull_request")[0],
                         "CLASSIFY_PROBE connected_at=not-probed shallow=n/a")
        self.assertEqual(lines(FakeGit(raise_on="cat-file"), GITHUB_EVENT_NAME="push",
                               GITHUB_SHA=SHA, CLASSIFY_BEFORE=BEFORE, CLASSIFY_FORCED="false"),
                         ("CLASSIFY_PROBE connected_at=not-probed shallow=n/a",
                          "CLASSIFY code=true reason=classifier-error:OSError"))


'''.replace('\n',nl)
s=s.replace(anchor, add+anchor)
io.open(p,'w',encoding='utf-8',newline='').write(s)
print('ok')
