Skip to content

Commit 7fb4b99

Browse files
committed
add a shared compressor test
1 parent 110418d commit 7fb4b99

File tree

1 file changed

+106
-0
lines changed

1 file changed

+106
-0
lines changed

test/test_multithreaded_sharing.py

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
""" Test multithreaded sharing of Compressor and Decompressor instances
2+
3+
Originally written by Eugene Kliuchnikov at Google for the brotli
4+
Python bindings under an MIT license.
5+
6+
"""
7+
import queue
8+
import random
9+
import threading
10+
import time
11+
12+
import brotlicffi
13+
14+
15+
def make_input(size):
16+
abc = [bytes([b]) for b in b"abcdefghijklmnopqrstuvwxyz"]
17+
abc_cap = [bytes([b]) for b in b"ABCDEFGHIJKLMNOPQRSTUVWXYZ"]
18+
num_words_by_len = [0, 25, 100, 175, 1700, 1000, 1000, 1000]
19+
word_set = set()
20+
rng = random.Random()
21+
rng.seed(2025)
22+
words_by_len = [[]]
23+
for word_len in range(1, len(num_words_by_len)):
24+
num_words = num_words_by_len[word_len]
25+
words = []
26+
for _ in range(num_words):
27+
while True:
28+
word = b"".join(
29+
[rng.choice(abc_cap)]
30+
+ [rng.choice(abc) for _ in range(word_len - 1)]
31+
)
32+
if word not in word_set:
33+
word_set.add(word)
34+
words.append(word)
35+
break
36+
words_by_len.append(words)
37+
total_size = 0
38+
out = []
39+
while total_size < size:
40+
word_len = rng.choice(range(1, len(num_words_by_len)))
41+
word = rng.choice(words_by_len[word_len])
42+
total_size += len(word)
43+
out.append(word)
44+
return b"".join(out)
45+
46+
47+
def _thread_compress(original, compressor, results):
48+
compressed = compressor.process(original)
49+
compressed += compressor.finish()
50+
results.put(1)
51+
52+
53+
def _thread_concurrent_process(compressor, results):
54+
time.sleep(0.01)
55+
try:
56+
_ = compressor.process(b"whatever")
57+
except brotlicffi.error:
58+
results.put(2)
59+
60+
61+
def _thread_concurrent_flush(compressor, results):
62+
time.sleep(0.02)
63+
try:
64+
_ = compressor.flush()
65+
except brotlicffi.error:
66+
results.put(3)
67+
68+
69+
def _thread_concurrent_finish(compressor, results):
70+
time.sleep(0.03)
71+
try:
72+
_ = compressor.finish()
73+
except brotlicffi.error:
74+
results.put(4)
75+
76+
77+
def test_concurrency():
78+
original = make_input(2 * 1024 * 1024)
79+
compressor = brotlicffi.Compressor(quality=9)
80+
results = queue.Queue()
81+
threads = []
82+
threads.append(
83+
threading.Thread(
84+
target=_thread_compress, args=(original, compressor, results)
85+
)
86+
)
87+
threads.append(
88+
threading.Thread(
89+
target=_thread_concurrent_process, args=(compressor, results)
90+
)
91+
)
92+
threads.append(
93+
threading.Thread(
94+
target=_thread_concurrent_flush, args=(compressor, results)
95+
)
96+
)
97+
threads.append(
98+
threading.Thread(
99+
target=_thread_concurrent_finish, args=(compressor, results)
100+
)
101+
)
102+
for thread in threads:
103+
thread.start()
104+
for thread in threads:
105+
thread.join()
106+
assert sorted(list(results.queue)) == [1, 2, 3, 4]

0 commit comments

Comments
 (0)