Skip to content

Commit 35641c3

Browse files
authored
Performance Testing (#58)
1 parent 0642d02 commit 35641c3

File tree

2 files changed

+118
-0
lines changed

2 files changed

+118
-0
lines changed

tests/cache_file_generator.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
"""
2+
Usage: cache_file_generator.py cache_file_path sleep_interval
3+
4+
This is a console application which is to be used for cross-platform lock performance testing.
5+
The app will acquire lock for the cache file, log the process id and then release the lock.
6+
7+
It takes in two arguments - cache file path and the sleep interval.
8+
The cache file path is the path of cache file.
9+
The sleep interval is the time in seconds for which the lock is held by a process.
10+
"""
11+
12+
import logging
13+
import os
14+
import sys
15+
import time
16+
17+
from portalocker import exceptions
18+
19+
from msal_extensions import FilePersistence, CrossPlatLock
20+
21+
22+
def _acquire_lock_and_write_to_cache(cache_location, sleep_interval):
23+
cache_accessor = FilePersistence(cache_location)
24+
lock_file_path = cache_accessor.get_location() + ".lockfile"
25+
try:
26+
with CrossPlatLock(lock_file_path):
27+
data = cache_accessor.load()
28+
if data is None:
29+
data = ""
30+
data += "< " + str(os.getpid()) + "\n"
31+
time.sleep(sleep_interval)
32+
data += "> " + str(os.getpid()) + "\n"
33+
cache_accessor.save(data)
34+
except exceptions.LockException as e:
35+
logging.warning("Unable to acquire lock %s", e)
36+
37+
38+
if __name__ == "__main__":
39+
if len(sys.argv) < 3:
40+
print(__doc__)
41+
sys.exit(0)
42+
_acquire_lock_and_write_to_cache(sys.argv[1], float(sys.argv[2]))
43+

tests/test_cache_lock_file_perf.py

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import multiprocessing
2+
import os
3+
import shutil
4+
import tempfile
5+
6+
import pytest
7+
8+
from cache_file_generator import _acquire_lock_and_write_to_cache
9+
10+
11+
@pytest.fixture
12+
def temp_location():
13+
test_folder = tempfile.mkdtemp(prefix="test_persistence_roundtrip")
14+
yield os.path.join(test_folder, 'persistence.bin')
15+
shutil.rmtree(test_folder, ignore_errors=True)
16+
17+
18+
def _validate_result_in_cache(cache_location):
19+
with open(cache_location) as handle:
20+
data = handle.read()
21+
prev_process_id = None
22+
count = 0
23+
for line in data.split("\n"):
24+
if line:
25+
count += 1
26+
tag, process_id = line.split(" ")
27+
if prev_process_id is not None:
28+
assert process_id == prev_process_id, "Process overlap found"
29+
assert tag == '>', "Process overlap_found"
30+
prev_process_id = None
31+
else:
32+
assert tag == '<', "Opening bracket not found"
33+
prev_process_id = process_id
34+
return count
35+
36+
37+
def _run_multiple_processes(no_of_processes, cache_location, sleep_interval):
38+
open(cache_location, "w+")
39+
processes = []
40+
for i in range(no_of_processes):
41+
process = multiprocessing.Process(
42+
target=_acquire_lock_and_write_to_cache,
43+
args=(cache_location, sleep_interval))
44+
processes.append(process)
45+
46+
for process in processes:
47+
process.start()
48+
49+
for process in processes:
50+
process.join()
51+
52+
53+
def test_lock_for_normal_workload(temp_location):
54+
num_of_processes = 4
55+
sleep_interval = 0.1
56+
_run_multiple_processes(num_of_processes, temp_location, sleep_interval)
57+
count = _validate_result_in_cache(temp_location)
58+
assert count == num_of_processes * 2, "Should not observe starvation"
59+
60+
61+
def test_lock_for_high_workload(temp_location):
62+
num_of_processes = 80
63+
sleep_interval = 0
64+
_run_multiple_processes(num_of_processes, temp_location, sleep_interval)
65+
count = _validate_result_in_cache(temp_location)
66+
assert count <= num_of_processes * 2, "Starvation or not, we should not observe garbled payload"
67+
68+
69+
def test_lock_for_timeout(temp_location):
70+
num_of_processes = 10
71+
sleep_interval = 1
72+
_run_multiple_processes(num_of_processes, temp_location, sleep_interval)
73+
count = _validate_result_in_cache(temp_location)
74+
assert count < num_of_processes * 2, "Should observe starvation"
75+

0 commit comments

Comments
 (0)