Source code
Revision control
Copy as Markdown
Other Tools
Test Info:
- Manifest: tools/rb/test/python.toml
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
import os
import sys
import threading
import time
import unittest
from subprocess import PIPE, Popen
import mozunit
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
import fix_stacks
ECHO = "import sys\nfor line in sys.stdin:\n sys.stdout.write(line)\n sys.stdout.flush()\n"
class TestFixStacksThreads(unittest.TestCase):
"""Checks that concurrent fixSymbols callers each get the answer to their own line.
An echo process stands in for `fix-stacks`, so a correct answer is the line itself.
"""
def setUp(self):
self.proc = Popen(
[sys.executable, "-u", "-c", ECHO],
stdin=PIPE,
stdout=PIPE,
universal_newlines=True,
)
fix_stacks.fix_stacks = self.proc
def tearDown(self):
self.proc.kill()
self.proc.wait()
for t in getattr(self, "threads", []):
t.join()
fix_stacks.fix_stacks = None
def test_concurrent_callers_get_their_own_answers(self):
threads_count = 8
lines = 500
barrier = threading.Barrier(threads_count)
wrong = []
def worker(tid):
barrier.wait()
for i in range(lines):
line = f"#01: ???[libxul.so +0x{tid:x}{i:06x}]"
out = fix_stacks.fixSymbols(line)
if not out:
return
if out != line:
wrong.append((line, out))
self.threads = [
threading.Thread(target=worker, args=(t,), daemon=True)
for t in range(threads_count)
]
for t in self.threads:
t.start()
deadline = time.monotonic() + 30
for t in self.threads:
t.join(timeout=max(0, deadline - time.monotonic()))
stuck = sum(t.is_alive() for t in self.threads)
self.assertEqual(stuck, 0, "threads never got an answer")
self.assertEqual(wrong, [], "threads got answers for other lines")
if __name__ == "__main__":
mozunit.main()