|
1 | | -import pytest, ultraplot as uplt, numpy as np |
| 1 | +import multiprocessing as mp |
| 2 | +import os |
| 3 | + |
| 4 | +import numpy as np |
| 5 | +import pytest |
| 6 | +import ultraplot as uplt |
2 | 7 |
|
3 | 8 |
|
4 | 9 | def test_unsharing_after_creation(rng): |
@@ -146,6 +151,48 @@ def test_toggle_input_axis_sharing(): |
146 | 151 | fig._toggle_axis_sharing(which="does not exist") |
147 | 152 |
|
148 | 153 |
|
| 154 | +def _layout_signature() -> tuple: |
| 155 | + fig, ax = uplt.subplots(ncols=2, nrows=2) |
| 156 | + for axi in ax: |
| 157 | + axi.plot([0, 1], [0, 1], label="line") |
| 158 | + axi.set_xlabel("X label") |
| 159 | + axi.set_ylabel("Y label") |
| 160 | + fig.suptitle("Title") |
| 161 | + fig.legend() |
| 162 | + fig.canvas.draw() |
| 163 | + signature = tuple( |
| 164 | + tuple(np.round(axi.get_position().bounds, 6)) |
| 165 | + for axi in fig.axes |
| 166 | + if axi.get_visible() |
| 167 | + ) |
| 168 | + uplt.close(fig) |
| 169 | + return signature |
| 170 | + |
| 171 | + |
| 172 | +def _layout_worker(queue): |
| 173 | + queue.put(_layout_signature()) |
| 174 | + |
| 175 | + |
| 176 | +def test_layout_deterministic_across_runs(): |
| 177 | + """ |
| 178 | + Layout should be deterministic for identical inputs. |
| 179 | + """ |
| 180 | + positions = [_layout_signature() for _ in range(3)] |
| 181 | + assert all(p == positions[0] for p in positions) |
| 182 | + |
| 183 | + # Probe mode: exercise multiple processes to catch nondeterminism. |
| 184 | + if os.environ.get("ULTRAPLOT_LAYOUT_PROBE") == "1": |
| 185 | + ctx = mp.get_context("spawn") |
| 186 | + queue = ctx.Queue() |
| 187 | + workers = [ctx.Process(target=_layout_worker, args=(queue,)) for _ in range(4)] |
| 188 | + for proc in workers: |
| 189 | + proc.start() |
| 190 | + proc_positions = [queue.get() for _ in workers] |
| 191 | + for proc in workers: |
| 192 | + proc.join() |
| 193 | + assert all(p == proc_positions[0] for p in proc_positions) |
| 194 | + |
| 195 | + |
149 | 196 | def test_suptitle_alignment(): |
150 | 197 | """ |
151 | 198 | Test that suptitle uses the original centering behavior with includepanels parameter. |
|
0 commit comments