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
9 changes: 5 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -227,12 +227,13 @@ jobs:
group: yield
timeout_minutes: 20
cargo_test_args: ""
# Both files share this one crate (issue #923, Phase 3 of the
# All three files share this one crate (issue #923, Phase 3 of the
# statistical/yield epic #710, added `klt yield-sensitivity` to
# the same `klt_yield_native` extension `klt yield` uses).
test_paths: tests/test_yield.py tests/test_yield_sensitivity.py
# the same `klt_yield_native` extension `klt yield` uses; issue
# #2675 added the `klt yield-campaign` native end-to-end tests).
test_paths: tests/test_yield.py tests/test_yield_campaign.py tests/test_yield_sensitivity.py
extension_module: klt_yield_native
no_skip_message: "klt_yield_native did not install -- tests/test_yield.py's and tests/test_yield_sensitivity.py's statistics tiers would have skipped"
no_skip_message: "klt_yield_native did not install -- tests/test_yield.py's, tests/test_yield_campaign.py's and tests/test_yield_sensitivity.py's statistics tiers would have skipped"
defaults:
run:
working-directory: ${{ matrix.dir }}
Expand Down
29 changes: 26 additions & 3 deletions tests/test_yield_campaign.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,13 @@
import importlib.util
import json
import os
import shutil
from pathlib import Path

import pytest

from helpers.subprocess_fakes import fake_completed
from klayout_tools import _paths as paths_module
from klayout_tools import sim, yield_campaign
from klayout_tools.yield_analysis import _read_samples
from klayout_tools.yield_campaign import CampaignError, run_campaign
Expand Down Expand Up @@ -77,7 +79,28 @@ def _base_spec(**overrides) -> dict:
return spec


def _stub_ngspice_discovery(monkeypatch) -> None:
"""Issue #2675: `sim.py` resolves the `ngspice` binary (issue #2423)
*before* dispatching any corner, i.e. before the `subprocess.run` stubs
below take effect. Stub resolution to the bare name (mirrors
`test_sim.py`'s `_bare_name_ngspice_resolution`) and drop any host
`$KLT_NGSPICE_BINARY`, so these tests do not need a real install.
Production discovery is untouched; only called by tests that also stub
`subprocess.run`."""
real_which = shutil.which

def fake_which(cmd, *args, **kwargs):
if cmd == "ngspice":
return cmd
return real_which(cmd, *args, **kwargs)

monkeypatch.delenv("KLT_NGSPICE_BINARY", raising=False)
monkeypatch.setattr(paths_module.shutil, "which", fake_which)


def _stub_subprocess_run(monkeypatch, *, log_text: str) -> None:
_stub_ngspice_discovery(monkeypatch)

def fake_run(cmd, capture_output, text, timeout, cwd=None):
log_path = cmd[cmd.index("-o") + 1]
with open(log_path, "w", encoding="utf-8") as handle:
Expand Down Expand Up @@ -636,6 +659,7 @@ def _stub_subprocess_run_per_sample(monkeypatch, *, values: list[str]) -> None:
"""Like `_stub_subprocess_run`, but emits a different measured value per
ngspice invocation, so a single campaign can mix trustworthy and
implausible draws."""
_stub_ngspice_discovery(monkeypatch)
calls = {"n": 0}

def fake_run(cmd, capture_output, text, timeout, cwd=None):
Expand Down Expand Up @@ -722,9 +746,8 @@ def test_run_campaign_hands_yield_a_netlist_that_unwraps_to_a_string(
):
"""The regression, over the **real** `run_sim` -> `_read_samples` seam
rather than a hand-built fixture -- only the native statistics core is
stubbed, so this runs everywhere (`test_yield_campaign.py` is not in
CI's `klt_yield_native` matrix leg, which is why the `requires_native`
end-to-end below cannot be the only cover for this).
stubbed, so this runs everywhere (the `requires_native`
end-to-end below also runs in CI's `klt_yield_native` matrix leg).

`run_campaign` dumps `run_sim`'s live report verbatim to
`sample-set.json` and hands the path straight to `run_yield`, so
Expand Down
Loading