Skip to content

Commit c69b057

Browse files
committed
small updates
1 parent b44cbcb commit c69b057

1 file changed

Lines changed: 32 additions & 21 deletions

File tree

holoviews/tests/core/test_storeoptions.py

Lines changed: 32 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import sys
1010
import threading
1111
from concurrent.futures import ThreadPoolExecutor
12+
from contextlib import contextmanager
1213

1314
import numpy as np
1415

@@ -21,12 +22,30 @@
2122
import holoviews.plotting.mpl
2223

2324

25+
@contextmanager
26+
def fast_switch():
27+
"""
28+
Sets sys.getswitchinterval to 1 microsecond to force thread interleaving in
29+
tests that check for id collisions with multiple threads
30+
"""
31+
old = sys.getswitchinterval()
32+
sys.setswitchinterval(1e-6)
33+
try:
34+
yield
35+
finally:
36+
sys.setswitchinterval(old)
37+
38+
2439
@mpl_skip
2540
class TestStoreOptionsMerge:
2641
def setup_method(self):
42+
self._backend = hv.Store.current_backend
2743
hv.Store.current_backend = "matplotlib"
2844
self.expected = {"Image": {"plot": {"fig_size": 150}, "style": {"cmap": "Blues"}}}
2945

46+
def teardown_method(self):
47+
hv.Store.current_backend = self._backend
48+
3049
def test_full_spec_format(self):
3150
out = hv.StoreOptions.merge_options(
3251
["plot", "style"],
@@ -58,7 +77,11 @@ class TestStoreOptsMethod:
5877
"""
5978

6079
def setup_method(self):
61-
hv.Store.current_backend = "matplotlib"
80+
self._backend = hv.Store.current_backend
81+
hv.Store.set_current_backend("matplotlib")
82+
83+
def teardown_method(self):
84+
hv.Store.current_backend = self._backend
6285

6386
def test_overlay_options_partitioned(self):
6487
"""
@@ -171,48 +194,36 @@ def test_overlay_subset_update_keeps_ids_bounded(self):
171194
assert max_ids[-1] < 500, f"id growth is not polynomial: {max_ids}"
172195

173196
def test_concurrent_recustomization_keeps_styles_distinct(self):
174-
n_workers = 8
197+
n_workers = 4
175198
barrier = threading.Barrier(n_workers)
176199

177200
def worker(w):
178201
barrier.wait()
179202
mismatches = 0
180-
for _ in range(120):
203+
for _ in range(60):
181204
el = hv.Curve([1, 2, 3], label=f"w{w}").opts(linewidth=w + 1)
182205
got = hv.Store.lookup_options("matplotlib", el, "style").kwargs.get("linewidth")
183206
mismatches += got != w + 1
184207
return mismatches
185208

186-
# A normal opts() runs within one thread-scheduling quantum, so the id
187-
# race stays hidden; a tiny switch interval forces interleaving.
188-
old = sys.getswitchinterval()
189-
sys.setswitchinterval(1e-6)
190-
try:
191-
with ThreadPoolExecutor(max_workers=n_workers) as executor:
192-
mismatches = sum(executor.map(worker, range(n_workers)))
193-
finally:
194-
sys.setswitchinterval(old)
209+
with fast_switch(), ThreadPoolExecutor(max_workers=n_workers) as executor:
210+
mismatches = sum(executor.map(worker, range(n_workers)))
195211

196212
assert mismatches == 0, f"concurrent customizations collided on ids: {mismatches}"
197213

198214
def test_concurrent_id_reservation_yields_disjoint_blocks(self):
199-
n_workers = 8
215+
n_workers = 4
200216
barrier = threading.Barrier(n_workers)
201217

202218
def worker(_):
203219
barrier.wait()
204220
ids = []
205-
for n in range(1, 120):
221+
for n in range(10, 30):
206222
start = hv.StoreOptions.reserve_ids(n)
207223
ids.extend(range(start, start + n))
208224
return ids
209225

210-
old = sys.getswitchinterval()
211-
sys.setswitchinterval(1e-6) # force interleaving of the read-modify-write
212-
try:
213-
with ThreadPoolExecutor(max_workers=n_workers) as executor:
214-
reserved = [i for block in executor.map(worker, range(n_workers)) for i in block]
215-
finally:
216-
sys.setswitchinterval(old)
226+
with fast_switch(), ThreadPoolExecutor(max_workers=n_workers) as executor:
227+
reserved = [i for block in executor.map(worker, range(n_workers)) for i in block]
217228

218229
assert len(reserved) == len(set(reserved)), "reserved id blocks overlap"

0 commit comments

Comments
 (0)