-
Notifications
You must be signed in to change notification settings - Fork 253
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #249 from cs50/develop
v3.2.1
- Loading branch information
Showing
5 changed files
with
130 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
check50: true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import check50 | ||
import sys | ||
|
||
# Set the excepthook to an unpicklable value, the run_check process will try to copy this | ||
sys.excepthook = lambda type, value, traceback: "bar" | ||
|
||
@check50.check() | ||
def foo(): | ||
"""foo""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
import check50 | ||
import check50.runner | ||
|
||
import importlib | ||
import multiprocessing | ||
import os | ||
import pathlib | ||
import pexpect | ||
import sys | ||
import tempfile | ||
import unittest | ||
|
||
|
||
CHECKS_DIRECTORY = pathlib.Path(__file__).absolute().parent / "checks" | ||
CHECK50_SUPPORTED_START_METHODS = ("fork", "spawn") | ||
|
||
|
||
# Just test spawn under OS X due to a bug with "fork": https://bugs.python.org/issue33725 | ||
if sys.platform == "darwin": | ||
SUPPORTED_START_METHODS = ("spawn",) | ||
|
||
# Don't test forkserver under linux, serves no usecase for check50 | ||
else: | ||
SUPPORTED_START_METHODS = tuple(set(CHECK50_SUPPORTED_START_METHODS) & set(multiprocessing.get_all_start_methods())) | ||
|
||
|
||
class TestMultiprocessingStartMethods(unittest.TestCase): | ||
def setUp(self): | ||
self.working_directory = tempfile.TemporaryDirectory() | ||
os.chdir(self.working_directory.name) | ||
|
||
# Keep track of get_start_method | ||
# This function gets monkey patched to ensure run_check is aware of the multiprocessing context, | ||
# without needing to explicitely pass the context to run_check. | ||
# The same behavior can't be achieved by multiprocessing.set_start_method as that can only run once per program | ||
# https://docs.python.org/3/library/multiprocessing.html#contexts-and-start-methods | ||
self._get_start_method = multiprocessing.get_start_method() | ||
|
||
def tearDown(self): | ||
self.working_directory.cleanup() | ||
multiprocessing.get_start_method = self._get_start_method | ||
|
||
def test_unpicklable_attribute(self): | ||
# Create the checks_spec and check_name needed for run_check | ||
checks_path = CHECKS_DIRECTORY / "unpicklable_attribute/__init__.py" | ||
check_name = "foo" | ||
spec = importlib.util.spec_from_file_location("checks", checks_path) | ||
|
||
# Execute the module once in the main process, as the Runner does too | ||
# This will set sys.excepthook to an unpicklable lambda | ||
check_module = importlib.util.module_from_spec(spec) | ||
spec.loader.exec_module(check_module) | ||
|
||
# For each available method | ||
for start_method in SUPPORTED_START_METHODS: | ||
|
||
# Create a multiprocessing context for that method | ||
ctx = multiprocessing.get_context(start_method) | ||
|
||
# Monkey patch get_start_method() used by run_check to check for its method | ||
multiprocessing.get_start_method = lambda: start_method | ||
|
||
# Start and join each check process | ||
p = ctx.Process(target=check50.runner.run_check(check_name, spec)) | ||
p.start() | ||
p.join() | ||
|
||
|
||
if __name__ == "__main__": | ||
unittest.main() |