-
Notifications
You must be signed in to change notification settings - Fork 50
Expand file tree
/
Copy pathrun_coverage.bash
More file actions
executable file
·178 lines (133 loc) · 6.81 KB
/
run_coverage.bash
File metadata and controls
executable file
·178 lines (133 loc) · 6.81 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
#!/bin/bash
###############################################################################
# mpi-sppy: MPI-based Stochastic Programming in PYthon
#
# Copyright (c) 2024, Lawrence Livermore National Security, LLC, Alliance for
# Sustainable Energy, LLC, The Regents of the University of California, et al.
# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md for
# full copyright and license information.
###############################################################################
# Run mpi-sppy tests with code coverage collection.
#
# This mirrors all the test jobs from .github/workflows/test_pr_and_main.yml.
#
# Usage: bash run_coverage.bash [SOLVER]
#
# SOLVER defaults to "cplex" (matches CI). Use e.g. "xpress" or "gurobi".
#
# Tests that require unavailable optional dependencies (amplpy, parapint, mip)
# are either skipped automatically via has_module checks or fail gracefully
# through run_phase (which continues to the next phase on error).
#
# Results are written to htmlcov/index.html
set -e
SOLVER="${1:-cplex}"
SOLVER_PERSISTENT="${SOLVER}_persistent"
SOLVER_DIRECT="${SOLVER}_direct"
PROJ_DIR="$(cd "$(dirname "$0")" && pwd)"
cd "$PROJ_DIR"
# Clean previous coverage data
rm -f .coverage .coverage.*
# --- Environment for automatic subprocess coverage ---
export COVERAGE_PROCESS_START="$PROJ_DIR/.coveragerc"
# Put our sitecustomize on the path so every python process auto-starts coverage
export PYTHONPATH="$PROJ_DIR:${PYTHONPATH:-}"
# Helper: run a phase, continue on failure
phase=0
run_phase() {
phase=$((phase + 1))
echo ""
echo "=== Phase $phase: $1 ==="
shift
"$@" 2>&1 || echo " (phase $phase finished with non-zero exit)"
}
# Helper: check if a python module is importable
has_module() {
python -c "import $1" 2>/dev/null
}
# ---------- Serial pytest / unittest tests ----------
run_phase "test_ef_ph (serial)" \
coverage run --rcfile=.coveragerc -m pytest mpisppy/tests/test_ef_ph.py -v
run_phase "test_component_map_usage (serial)" \
coverage run --rcfile=.coveragerc -m pytest mpisppy/tests/test_component_map_usage.py -v
run_phase "test_nonant_validation (serial)" \
coverage run --rcfile=.coveragerc -m pytest mpisppy/tests/test_nonant_validation.py -v
run_phase "test_ph_main (serial)" \
coverage run --rcfile=.coveragerc mpisppy/tests/test_ph_main.py
run_phase "test_ph_extensions (serial)" \
coverage run --rcfile=.coveragerc mpisppy/tests/test_ph_extensions.py
run_phase "test_admmWrapper (serial, spawns mpiexec)" \
coverage run --rcfile=.coveragerc mpisppy/tests/test_admmWrapper.py
run_phase "test_stoch_admmWrapper (serial, spawns mpiexec)" \
coverage run --rcfile=.coveragerc mpisppy/tests/test_stoch_admmWrapper.py
run_phase "test_admm_bundler (serial)" \
coverage run --rcfile=.coveragerc -m pytest mpisppy/tests/test_admm_bundler.py -v
run_phase "test_aph (spawns mpiexec)" \
coverage run --rcfile=.coveragerc mpisppy/tests/test_aph.py
run_phase "test_pickle_bundle (spawns mpiexec)" \
coverage run --rcfile=.coveragerc mpisppy/tests/test_pickle_bundle.py
run_phase "test_mps (serial)" \
coverage run --rcfile=.coveragerc mpisppy/tests/test_mps.py
run_phase "test_smps (serial)" \
coverage run --rcfile=.coveragerc -m pytest mpisppy/tests/test_smps.py -v
run_phase "test_generic_cylinders (serial)" \
coverage run --rcfile=.coveragerc -m pytest mpisppy/tests/test_generic_cylinders.py -v
run_phase "test_conf_int_farmer (spawns mpiexec)" \
coverage run --rcfile=.coveragerc mpisppy/tests/test_conf_int_farmer.py
run_phase "test_conf_int_aircond (spawns mpiexec)" \
coverage run --rcfile=.coveragerc mpisppy/tests/test_conf_int_aircond.py
run_phase "test_gradient_rho (spawns mpiexec)" \
coverage run --rcfile=.coveragerc mpisppy/tests/test_gradient_rho.py
run_phase "test_xbar_w_reader_writer (spawns mpiexec)" \
coverage run --rcfile=.coveragerc mpisppy/tests/test_xbar_w_reader_writer.py
run_phase "test_pysp_model (serial)" \
coverage run --rcfile=.coveragerc mpisppy/tests/test_pysp_model.py
run_phase "pysp_model pytest (serial)" \
coverage run --rcfile=.coveragerc -m pytest mpisppy/utils/pysp_model/ -v
# ---------- MPI tests (direct launch) ----------
run_phase "test_with_cylinders (mpiexec -np 2)" \
mpiexec -np 2 coverage run --rcfile="$PROJ_DIR/.coveragerc" -m mpi4py mpisppy/tests/test_with_cylinders.py
# ---------- Tests that spawn mpiexec internally ----------
PYARGS="-m coverage run --parallel-mode --rcfile=$PROJ_DIR/.coveragerc --data-file=$PROJ_DIR/.coverage"
run_phase "straight_tests.py (spawns mpiexec)" \
coverage run --rcfile=.coveragerc mpisppy/tests/straight_tests.py --python-args="$PYARGS"
# ---------- Example-based tests ----------
# Use --source with absolute paths so both mpisppy and the example test
# harnesses (generic_tester.py, run_all.py, afew.py) are tracked.
EX_SRC="--source=$PROJ_DIR/mpisppy,$PROJ_DIR/examples"
EX_COV="coverage run $EX_SRC --data-file=$PROJ_DIR/.coverage --rcfile=$PROJ_DIR/.coveragerc"
run_phase "examples/afew.py $SOLVER_PERSISTENT" \
bash -c "cd '$PROJ_DIR/examples' && $EX_COV afew.py '$SOLVER_PERSISTENT' '' --python-args='$PYARGS'"
run_phase "examples/run_all.py $SOLVER_PERSISTENT nouc" \
bash -c "cd '$PROJ_DIR/examples' && $EX_COV run_all.py '$SOLVER_PERSISTENT' '' nouc --python-args='$PYARGS'"
run_phase "examples/run_all.py $SOLVER_DIRECT nouc" \
bash -c "cd '$PROJ_DIR/examples' && $EX_COV run_all.py '$SOLVER_DIRECT' '' nouc --python-args='$PYARGS'"
run_phase "examples/generic_tester.py ${SOLVER}_direct nouc" \
bash -c "cd '$PROJ_DIR/examples' && $EX_COV generic_tester.py '${SOLVER}_direct' '' nouc --python-args='$PYARGS'"
# ---------- Optional tests (skip if deps missing) ----------
if has_module amplpy; then
run_phase "test_agnostic (serial)" \
coverage run --rcfile=.coveragerc mpisppy/tests/test_agnostic.py
run_phase "afew_agnostic.py" \
bash -c "cd '$PROJ_DIR/mpisppy/agnostic/examples' && coverage run --rcfile='$PROJ_DIR/.coveragerc' afew_agnostic.py --python-args='$PYARGS'"
else
echo ""
echo "=== SKIPPED: agnostic tests (amplpy not installed) ==="
fi
if has_module parapint; then
run_phase "test_sc (serial)" \
coverage run --rcfile=.coveragerc -m pytest mpisppy/tests/test_sc.py -v
run_phase "test_sc (mpiexec -np 3)" \
mpiexec -np 3 coverage run --rcfile="$PROJ_DIR/.coveragerc" -m pytest mpisppy/tests/test_sc.py -v
else
echo ""
echo "=== SKIPPED: schur-complement tests (parapint not installed) ==="
fi
# ---------- Combine and report ----------
echo ""
echo "=== Combining and reporting ==="
coverage combine --rcfile=.coveragerc
coverage report --rcfile=.coveragerc --include='mpisppy/*,examples/*.py' --show-missing | head -150
coverage html --rcfile=.coveragerc --include='mpisppy/*,examples/*.py'
echo ""
echo "HTML report: file://$PROJ_DIR/htmlcov/index.html"