Skip to content

Commit ba2bcd4

Browse files
committed
add multithreading test
1 parent 091a872 commit ba2bcd4

File tree

2 files changed

+46
-4
lines changed

2 files changed

+46
-4
lines changed

README.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ Compatibility
285285
-------------
286286

287287
This library should be compatible with py-bcrypt and it will run on Python
288-
3.6+, and PyPy 3.
288+
3.8+ (including free-threaded builds), and PyPy 3.
289289

290290
Security
291291
--------

tests/test_bcrypt.py

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
1-
import pytest
1+
import random
2+
import uuid
3+
4+
from concurrent.futures import ThreadPoolExecutor
5+
from dataclasses import dataclass
26

37
import bcrypt
8+
import pytest
49

510
_test_vectors = [
611
(
@@ -171,7 +176,7 @@
171176
]
172177

173178

174-
def test_gensalt_basic(monkeypatch):
179+
def test_gensalt_basic():
175180
salt = bcrypt.gensalt()
176181
assert salt.startswith(b"$2b$12$")
177182

@@ -219,7 +224,7 @@ def test_gensalt_bad_prefix():
219224
bcrypt.gensalt(prefix=b"bad")
220225

221226

222-
def test_gensalt_2a_prefix(monkeypatch):
227+
def test_gensalt_2a_prefix():
223228
salt = bcrypt.gensalt(prefix=b"2a")
224229
assert salt.startswith(b"$2a$12$")
225230

@@ -495,3 +500,40 @@ def test_2a_wraparound_bug():
495500
)
496501
== b"$2a$04$R1lJ2gkNaoPGdafE.H.16.1MKHPvmKwryeulRe225LKProWYwt9Oi"
497502
)
503+
504+
505+
@pytest.mark.thread_unsafe()
506+
def test_multithreading():
507+
def get_id():
508+
return uuid.uuid4().bytes
509+
510+
class User:
511+
def __init__(self, id_, pw):
512+
self.id_ = id_
513+
self.salt = bcrypt.gensalt(4)
514+
self.hash_ = bcrypt.hashpw(pw, self.salt)
515+
self.key = bcrypt.kdf(pw, self.salt, 32, 50)
516+
assert self.check(pw)
517+
518+
def check(self, pw):
519+
return bcrypt.checkpw(pw, self.hash_)
520+
521+
# use UUIDs as both ID and passwords
522+
NUM_USERS = 50
523+
ids = [get_id() for _ in range(NUM_USERS)]
524+
pws = {id_: get_id() for id_, _ in zip(ids, range(NUM_USERS))}
525+
526+
user_creator = ThreadPoolExecutor(max_workers=4)
527+
528+
def create_user(id_, pw):
529+
return id_, User(id_, pw)
530+
531+
creator_futures = [
532+
user_creator.submit(create_user, id_, pw) for id_, pw in pws.items()]
533+
534+
users = [future.result() for future in creator_futures]
535+
536+
for id_, user in users:
537+
assert bcrypt.hashpw(pws[id_], user.salt) == user.hash_
538+
assert user.check(pws[id_])
539+
assert bcrypt.kdf(pws[id_], user.salt, 32, 50) == user.key

0 commit comments

Comments
 (0)