Simplify imports and exports and provide driver isolation for remote functions. (#288)

* Remove import counter and export counter.

* Provide isolation between drivers for remote functions.

* Add test for driver function isolation.

* Hash source code into function ID to reduce likelihood of collisions.

* Fix failure test example.

* Replace assertTrue with assertIn to improve failure messages in tests.

* Fix failure test.
This commit is contained in:
Robert Nishihara
2017-02-16 11:30:35 -08:00
committed by Philipp Moritz
parent 883f945db4
commit 88a5b4e77b
6 changed files with 252 additions and 181 deletions
+38 -25
View File
@@ -2,10 +2,12 @@ from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import unittest
import os
import ray
import sys
import tempfile
import time
import unittest
if sys.version_info >= (3, 0):
from importlib import reload
@@ -67,13 +69,13 @@ class TaskStatusTest(unittest.TestCase):
result = ray.error_info()
self.assertEqual(len(relevant_errors(b"task")), 2)
for task in relevant_errors(b"task"):
self.assertTrue(b"Test function 1 intentionally failed." in task.get(b"message"))
self.assertIn(b"Test function 1 intentionally failed.", task.get(b"message"))
x = test_functions.throw_exception_fct2.remote()
try:
ray.get(x)
except Exception as e:
self.assertTrue("Test function 2 intentionally failed." in str(e))
self.assertIn("Test function 2 intentionally failed.", str(e))
else:
self.assertTrue(False) # ray.get should throw an exception
@@ -82,7 +84,7 @@ class TaskStatusTest(unittest.TestCase):
try:
ray.get(ref)
except Exception as e:
self.assertTrue("Test function 3 intentionally failed." in str(e))
self.assertIn("Test function 3 intentionally failed.", str(e))
else:
self.assertTrue(False) # ray.get should throw an exception
@@ -91,29 +93,40 @@ class TaskStatusTest(unittest.TestCase):
def testFailImportingRemoteFunction(self):
ray.init(num_workers=2, driver_mode=ray.SILENT_MODE)
# This example is somewhat contrived. It should be successfully pickled, and
# then it should throw an exception when it is unpickled. This may depend a
# bit on the specifics of our pickler.
def reducer(*args):
raise Exception("There is a problem here.")
class Foo(object):
def __init__(self):
self.__name__ = "Foo_object"
self.func_doc = ""
self.__globals__ = {}
def __reduce__(self):
return reducer, ()
def __call__(self):
return
f = ray.remote(Foo())
# Create the contents of a temporary Python file.
temporary_python_file = """
def temporary_helper_function():
return 1
"""
f = tempfile.NamedTemporaryFile(suffix=".py")
f.write(temporary_python_file.encode("ascii"))
f.flush()
directory = os.path.dirname(f.name)
# Get the module name and strip ".py" from the end.
module_name = os.path.basename(f.name)[:-3]
sys.path.append(directory)
module = __import__(module_name)
# Define a function that closes over this temporary module. This should fail
# when it is unpickled.
@ray.remote
def g():
return module.temporary_python_file()
wait_for_errors(b"register_remote_function", 2)
self.assertTrue(b"There is a problem here." in ray.error_info()[0][b"message"])
self.assertIn(b"No module named", ray.error_info()[0][b"message"])
self.assertIn(b"No module named", ray.error_info()[1][b"message"])
# Check that if we try to call the function it throws an exception and does
# not hang.
for _ in range(10):
self.assertRaises(Exception, lambda : ray.get(f.remote()))
self.assertRaises(Exception, lambda : ray.get(g.remote()))
f.close()
# Clean up the junk we added to sys.path.
sys.path.pop(-1)
ray.worker.cleanup()
def testFailImportingEnvironmentVariable(self):
@@ -128,7 +141,7 @@ class TaskStatusTest(unittest.TestCase):
ray.env.foo = ray.EnvironmentVariable(initializer)
wait_for_errors(b"register_environment_variable", 2)
# Check that the error message is in the task info.
self.assertTrue(b"The initializer failed." in ray.error_info()[0][b"message"])
self.assertIn(b"The initializer failed.", ray.error_info()[0][b"message"])
ray.worker.cleanup()
@@ -146,7 +159,7 @@ class TaskStatusTest(unittest.TestCase):
use_foo.remote()
wait_for_errors(b"reinitialize_environment_variable", 1)
# Check that the error message is in the task info.
self.assertTrue(b"The reinitializer failed." in ray.error_info()[0][b"message"])
self.assertIn(b"The reinitializer failed.", ray.error_info()[0][b"message"])
ray.worker.cleanup()
@@ -160,8 +173,8 @@ class TaskStatusTest(unittest.TestCase):
wait_for_errors(b"function_to_run", 2)
# Check that the error message is in the task info.
self.assertEqual(len(ray.error_info()), 2)
self.assertTrue(b"Function to run failed." in ray.error_info()[0][b"message"])
self.assertTrue(b"Function to run failed." in ray.error_info()[1][b"message"])
self.assertIn(b"Function to run failed.", ray.error_info()[0][b"message"])
self.assertIn(b"Function to run failed.", ray.error_info()[1][b"message"])
ray.worker.cleanup()