Commit dea2a17
Tests: end-to-end verify solver_options_layers reach gurobi at solve time (#700)
* tests: end-to-end verify solver_options_layers reach gurobi at solve time
A new gurobi-only test module
``mpisppy/tests/test_options_reach_solver.py`` exercises every
layer-source path documented in
``doc/designs/solver_options_redesign.md``: each test sets one
option through a specific surface (CLI flag, --solver-options-file
sub-block, per-spoke file, --max-solver-threads cap, deprecated
--mipgaps-json) via the Config / cfg_vanilla flow, runs farmer PH
for a couple of iterations against gurobi_persistent with
``solver_log_dir`` set to a tmpdir, then greps the per-solve
Gurobi log files for the ``Set parameter X to value Y`` line that
proves the parameter actually reached the solver at the expected
iteration.
12 tests covering:
- ``--solver-options`` inline: mipgap, threads (canonical→native
rename), and a non-translated key (presolve).
- ``--iter0-mipgap`` and ``--iterk-mipgap`` apply at the right
iteration.
- ``--mipgaps-json`` (deprecated path): per-iteration schedule
fires at the right N; the N=0 entry is routed through the
``default`` predicate per the validator.
- ``--solver-options-file`` per sub-block: ``default`` applies
everywhere; ``iter0`` and ``iterk`` fire at their predicates
separately; ``starting_at_iter`` fires from N onward; CLI sugar
flags override file entries at the same predicate per axis 2.
- Per-spoke layers: global file's ``spokes.<name>`` sub-block AND
dedicated ``--{name}-solver-options-file`` both reach the
spoke's solver (exercised through apply_solver_specs so the
test stays single-process).
- ``--max-solver-threads`` cap wins over any user-supplied
``threads`` value.
The test class is decorated with ``skipUnless(gurobi_persistent
available)`` so it cleanly skips when gurobi isn't installed. The
CI gurobi-via-pip job runs it; run_coverage.bash also runs it
locally when available.
## Companion code fix in spopt.solve_one
Setting ``s._solver_plugin.options["LogFile"]`` must happen
BEFORE the solver-options loop. With GurobiPersistent, the model
instance is reused across iterations, and setParam writes
``Set parameter X to value Y`` to the *currently active* LogFile.
With the previous order (options first, then LogFile), each
iteration's parameter-set lines landed in the previous
iteration's still-open log, mis-attributing per-iteration options
to the wrong log file. Reordering puts the LogFile change first
so parameter-set lines land in the right per-solve log. No
behavior change for the actual solves; only the log-file
attribution.
## CI wiring
Added under the existing ``straight-tests-gurobi`` job (which is
already gated on the gurobi-via-pip install + the
``Probe gurobi_persistent availability`` step). The new test file
runs as its own pytest step after straight_tests.py and uploads
into the same ``coverage-straight-tests-gurobi`` artifact, so
codecov picks it up.
Local: 12/12 pass in this file; 237/238 pass in the wider sweep
(unrelated pre-existing test_proper_bundler failure on main).
ruff clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* ci: install pytest in straight-tests-gurobi job
The new `Options-reach-solver end-to-end tests` step invokes
pytest, which the gurobi-via-pip job didn't pip-install. Adding
pytest to the install line fixes the `No module named 'pytest'`
error.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>1 parent eef175e commit dea2a17
4 files changed
Lines changed: 373 additions & 15 deletions
File tree
- .github/workflows
- mpisppy
- tests
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
436 | 436 | | |
437 | 437 | | |
438 | 438 | | |
439 | | - | |
| 439 | + | |
440 | 440 | | |
441 | 441 | | |
442 | 442 | | |
| |||
452 | 452 | | |
453 | 453 | | |
454 | 454 | | |
| 455 | + | |
| 456 | + | |
| 457 | + | |
| 458 | + | |
455 | 459 | | |
456 | 460 | | |
457 | 461 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
180 | 180 | | |
181 | 181 | | |
182 | 182 | | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
183 | 207 | | |
184 | 208 | | |
185 | 209 | | |
| |||
191 | 215 | | |
192 | 216 | | |
193 | 217 | | |
194 | | - | |
195 | 218 | | |
196 | 219 | | |
197 | 220 | | |
| |||
210 | 233 | | |
211 | 234 | | |
212 | 235 | | |
213 | | - | |
214 | | - | |
215 | | - | |
216 | | - | |
217 | | - | |
218 | | - | |
219 | | - | |
220 | | - | |
221 | | - | |
222 | | - | |
223 | | - | |
224 | | - | |
225 | | - | |
226 | 236 | | |
227 | 237 | | |
228 | 238 | | |
| |||
0 commit comments