class TestCase(unittest.TestCase): """ Test distributed simulation. """ def run(self, result=None): """ Record the :class:`TestResult` used so we can conditionally cleanup directories in :meth:`tearDown`. """ self.test_result = result or unittest.TestResult() return super(TestCase, self).run(self.test_result) def setUp(self): """ Called before each test. """ self.n_errors = len(self.test_result.errors) self.n_failures = len(self.test_result.failures) self.factories = [] self.servers = [] self.server_dirs = [] # Ensure we control directory cleanup. self.keepdirs = os.environ.get('OPENMDAO_KEEPDIRS', '0') os.environ['OPENMDAO_KEEPDIRS'] = '1' def start_factory(self, port=None, allowed_users=None): """ Start each factory process in a unique directory. """ global _SERVER_ID _SERVER_ID += 1 server_dir = 'Factory_%d' % _SERVER_ID if os.path.exists(server_dir): shutil.rmtree(server_dir) os.mkdir(server_dir) os.chdir(server_dir) self.server_dirs.append(server_dir) try: logging.debug('') logging.debug('tester pid: %s', os.getpid()) logging.debug('starting server...') if port is None: # Exercise both AF_INET and AF_UNIX/AF_PIPE. port = -1 if _SERVER_ID & 1 else 0 if allowed_users is None: credentials = get_credentials() allowed_users = {credentials.user: credentials.public_key} allowed_types = [ 'openmdao.main.test.test_distsim.HollowSphere', 'openmdao.main.test.test_distsim.Box', 'openmdao.main.test.test_distsim.ProtectedBox' ] server, server_cfg = start_server(port=port, allowed_users=allowed_users, allowed_types=allowed_types) self.servers.append(server) cfg = read_server_config(server_cfg) self.address = cfg['address'] self.port = cfg['port'] self.tunnel = cfg['tunnel'] self.key = cfg['key'] logging.debug('server pid: %s', server.pid) logging.debug('server address: %s', self.address) logging.debug('server port: %s', self.port) logging.debug('server key: %s', self.key) finally: os.chdir('..') factory = connect(self.address, self.port, self.tunnel, pubkey=self.key) self.factories.append(factory) logging.debug('factory: %r', factory) return factory def tearDown(self): """ Shut down server process. """ try: for factory in self.factories: factory.cleanup() for server in self.servers: logging.debug('terminating server pid %s', server.pid) server.terminate(timeout=10) # Cleanup only if there weren't any new errors or failures. if len(self.test_result.errors) == self.n_errors and \ len(self.test_result.failures) == self.n_failures and \ not int(self.keepdirs): for server_dir in self.server_dirs: shutil.rmtree(server_dir) finally: os.environ['OPENMDAO_KEEPDIRS'] = self.keepdirs def test_1_client(self): logging.debug('') logging.debug('test_client') factory = self.start_factory() # List available types. types = factory.get_available_types() logging.debug('Available types:') for typname, version in types: logging.debug(' %s %s', typname, version) # First a HollowSphere, accessed via get()/set(). obj = factory.create(_MODULE + '.HollowSphere') sphere_pid = obj.get('pid') self.assertNotEqual(sphere_pid, os.getpid()) radius = obj.get('radius') self.assertEqual(radius, 1.) radius += 1 obj.set('radius', radius) new_radius = obj.get('radius') self.assertEqual(new_radius, 2.) self.assertEqual(obj.get('inner_volume'), 0.) self.assertEqual(obj.get('volume'), 0.) self.assertEqual(obj.get('solid_volume'), 0.) self.assertEqual(obj.get('surface_area'), 0.) obj.run() assert_rel_error(self, obj.get('inner_volume'), 33.510321638, 0.000001) assert_rel_error(self, obj.get('volume'), 36.086951213, 0.000001) assert_rel_error(self, obj.get('solid_volume'), 2.5766295747, 0.000001) assert_rel_error(self, obj.get('surface_area'), 50.265482457, 0.000001) msg = ": Variable 'radius' must be a float in the range (0.0, " assert_raises(self, "obj.set('radius', -1)", globals(), locals(), ValueError, msg) # Now a Box, accessed via attribute methods. obj = factory.create(_MODULE + '.Box') box_pid = obj.get('pid') self.assertNotEqual(box_pid, os.getpid()) self.assertNotEqual(box_pid, sphere_pid) obj.width += 2 obj.height += 2 obj.depth += 2 self.assertEqual(obj.width, 2.) self.assertEqual(obj.height, 2.) self.assertEqual(obj.depth, 2.) self.assertEqual(obj.volume, 0.) self.assertEqual(obj.surface_area, 0.) obj.run() self.assertEqual(obj.volume, 8.0) self.assertEqual(obj.surface_area, 24.0) try: obj.no_rbac() except RemoteError as exc: msg = "AttributeError: method 'no_rbac' of" logging.debug('msg: %s', msg) logging.debug('exc: %s', exc) self.assertTrue(msg in str(exc)) else: self.fail('Expected RemoteError') def test_2_model(self): logging.debug('') logging.debug('test_model') factory = self.start_factory() # Create model and run it. box = factory.create(_MODULE + '.Box') model = set_as_top(Model(box)) model.run() # Check results. for width in range(1, 2): for height in range(1, 3): for depth in range(1, 4): case = model.driver.recorders[0].cases.pop(0) self.assertEqual(case.outputs[0][2], width * height * depth) self.assertTrue(is_instance(model.box.parent, Assembly)) self.assertTrue(has_interface(model.box.parent, IComponent)) # Upcall to use parent to resolve sibling. # At one time this caused proxy problems. source = model.box.parent.source self.assertEqual(source.width_in, 1.) # Proxy resolution. obj, path = get_closest_proxy(model, 'box.subcontainer.subvar') self.assertEqual(obj, model.box) self.assertEqual(path, 'subcontainer.subvar') obj, path = get_closest_proxy(model, 'source.subcontainer.subvar') self.assertEqual(obj, model.source.subcontainer) self.assertEqual(path, 'subvar') obj, path = get_closest_proxy(model.source.subcontainer, 'subvar') self.assertEqual(obj, model.source.subcontainer) self.assertEqual(path, 'subvar') # Observable proxied type. tmp = model.box.open_in_parent('tmp', 'w') tmp.close() os.remove('tmp') # Cause server-side errors we can see. try: box.cause_parent_error1() except RemoteError as exc: msg = "AttributeError: attribute 'no_such_variable' of" logging.debug('msg: %s', msg) logging.debug('exc: %s', exc) self.assertTrue(msg in str(exc)) else: self.fail('Expected RemoteError') try: box.cause_parent_error2() except RemoteError as exc: msg = "AttributeError: method 'get_trait' of" logging.debug('msg: %s', msg) logging.debug('exc: %s', exc) self.assertTrue(msg in str(exc)) else: self.fail('Expected RemoteError') try: box.cause_parent_error3() except RemoteError as exc: msg = "RoleError: xyzzy(): No access for role 'owner'" logging.debug('msg: %s', msg) logging.debug('exc: %s', exc) self.assertTrue(msg in str(exc)) else: self.fail('Expected RemoteError')
def test_2_model(self): logging.debug('') logging.debug('test_model') factory = self.start_factory() # Create model and run it. box = factory.create(_MODULE+'.Box') model = set_as_top(Model(box)) model.run() # Check results. for width in range(1, 2): for height in range(1, 3): for depth in range(1, 4): case = model.driver.recorder.cases.pop(0) self.assertEqual(case.outputs[0][2], width*height*depth) self.assertTrue(is_instance(model.box.parent, Assembly)) self.assertTrue(has_interface(model.box.parent, IComponent)) # Upcall to use parent to resolve sibling. # At one time this caused proxy problems. source = model.box.parent.source self.assertEqual(source.width_in, 1.) # Proxy resolution. obj, path = get_closest_proxy(model, 'box.subcontainer.subvar') self.assertEqual(obj, model.box) self.assertEqual(path, 'subcontainer.subvar') obj, path = get_closest_proxy(model, 'source.subcontainer.subvar') self.assertEqual(obj, model.source.subcontainer) self.assertEqual(path, 'subvar') obj, path = get_closest_proxy(model.source.subcontainer, 'subvar') self.assertEqual(obj, model.source.subcontainer) self.assertEqual(path, 'subvar') # Observable proxied type. tmp = model.box.open_in_parent('tmp', 'w') tmp.close() os.remove('tmp') # Cause server-side errors we can see. try: box.cause_parent_error1() except RemoteError as exc: msg = "AttributeError: attribute 'no_such_variable' of" logging.debug('msg: %s', msg) logging.debug('exc: %s', exc) self.assertTrue(msg in str(exc)) else: self.fail('Expected RemoteError') try: box.cause_parent_error2() except RemoteError as exc: msg = "AttributeError: method 'get_trait' of" logging.debug('msg: %s', msg) logging.debug('exc: %s', exc) self.assertTrue(msg in str(exc)) else: self.fail('Expected RemoteError') try: box.cause_parent_error3() except RemoteError as exc: msg = "RoleError: xyzzy(): No access for role 'owner'" logging.debug('msg: %s', msg) logging.debug('exc: %s', exc) self.assertTrue(msg in str(exc)) else: self.fail('Expected RemoteError')