class TestConnector(SignalMixin, unittest.TestCase): def setUpClass(self): """Start an Aggregator in a child process to test against""" # aggregator startup script directory bindir = os.path.join(agdevicecontrol.path, 'server') # keep track of temporary files for deletion in tearDown self.tempfiles = [] # create a temporary aggregator config file filename = 'test_aggregator.conf' fqfilename = bindir + os.sep + filename f = open(fqfilename,'w') f.write(aggregator_config_contents) f.close() self.tempfiles.append(fqfilename) # start aggregator as a child process self.process = SubProcessProtocol() self.process.waitOnStartUp(['aggregator.py', filename, '-n', '--test'], path = bindir) if self.process.running is False: raise unittest.SkipTest, "Aggregator didn't start correctly, skipping tests" import time time.sleep(1) def tearDownClass(self): """Stop the Aggregator running in a child process""" print "*** tearDownClass: ", self.process.done self.process.waitOnShutDown() # clean-up temporary config files for f in self.tempfiles: os.remove(f) def setUp(self): """Per test initalization""" self.done = False self.failure = None def tearDown(self): """Per test cleanup code""" if self.connector: self.connector.close() def succeeded(self, *args): """Allow reactor iteration loop in test proper to exit and pass test""" self.done = True self.timeout.cancel() # safety timeout no longer necessary self.lastargs = args # make persistent for later checks def failed(self, reason, unknown): """Allow reactor iteration loop in test proper to exit and fail test""" self.done = True self.failure = reason self.lastargs = None def test_simple_connect(self): """Obtain perspective on Aggregator""" # safety timeout self.timeout = reactor.callLater(10, self.failed, "attempt to connect to Aggregator timed out ... failing") self.connector = Connector('localhost', port=8789) self.connector.connect(callback=self.succeeded, errback=self.failed, password='******') # idle until code above triggers succeeded or timeout causes failure while not self.done: reactor.iterate(0.1) # will arrive here eventually when either succeeded or failed method has fired if self.failure: self.fail(self.failure) connector = self.lastargs[0] assert connector == self.connector # paranoia check assert self.connector.connected is True if False: test_simple_connect.skip = True
class TestContainer(SignalMixin, unittest.TestCase): def setUpClass(self): self.csProcess = SubProcessProtocol() self.csProcess.waitOnStartUp(['container_server.py'], \ path = os.path.join(agdevicecontrol.path,'tests')) print "csProcess started" time.sleep(1) def tearDownClass(self): print "tearDownClass" self.csProcess.waitOnShutDown() def setUp(self): print print "setUP" self.done = False self.failure = None def succeeded(self, *args): """Allow reactor iteration loop in test proper to exit and pass test""" self.done = True self.timeout.cancel() # safety timeout no longer necessary self.lastargs = args # make persistent for later checks def failed(self, reason): """Allow reactor iteration loop in test proper to exit and fail test""" print print "DEBUG: failed" self.done = True self.failure = reason self.lastargs = None #---------------------------------------------------------------------- def test_hashable(self): """Containers need to be hashable""" b = Container() assert hash(b) def test_hashable(self): """Comparison for equality""" b1 = Container() b1.name = 'Device1' b2 = copy(b1) self.assertEqual(b1,b2) def test_attributes(self): """Can iterate over previously set attributes of container""" b = Container() b.int = 1234 b.float = 3.14 b.string = "sample string" def test_serializable(self): """Confirm containers can travel the wire""" b = Container() b.name = 'Device' b.type = 'PseudoDevice' b.description = "A string describing this device" # Jelly is the low-level serializer of the twisted framework assert jelly(b) def test_unique_ids(self): """Confirm that reasonably large number of discrete containers all get unique ids""" ids = [] instances = [] for i in range(1000): instance = Container() assert instance.id not in ids ids.append(instance.id) instances.append(instance) def test_zzz_echo_tcp(self): """Test container can travel over a TCP connection""" # safety timeout self.timeout = reactor.callLater(5, self.failed, "Something Bad happened... Bailing") factory = pb.PBClientFactory() reactor.connectTCP("localhost",8800, factory) deferred = factory.getRootObject() deferred.addCallback(self._got_reference) deferred.addErrback(self.failed) while self.done is False: reactor.iterate(0.1) if self.failure: self.fail(self.failure) def _got_reference(self, remote): self.remote = remote d = self.remote.callRemote("get_bucket") d.addCallback(self.succeeded) d.addErrback(self.failed)
class TestAggregator(SignalMixin, unittest.TestCase): def setUpClass(self): """Start a DeviceServer in a child process to test against""" self.deviceserverprocess = SubProcessProtocol() self.deviceserverprocess.waitOnStartUp( ['server.py', 'deviceserver.conf', '-n'], \ path=os.path.join(agdevicecontrol.path,'bin') ) if self.deviceserverprocess.running is False: raise unittest.SkipTest, "DeviceServer didn't start correctly, skipping tests" #wait for slow single CPU buildbots to catch up import time time.sleep(1) # use the config above conf = Configurator() conf.fromString(configdata) # can be set by timeout self.failure = False # safety timeout self.timeout = reactor.callLater(10, self.failed, "Aggregator failed to connect to all deviceservers ... failing") self.aggregator = Aggregator(conf) self.done = False while not self.done: print "Waiting for aggregator to connect to deviceservers" reactor.iterate(0.1) if self.aggregator.connected: self.succeeded() if self.failure: raise unittest.SkipTest, "Aggregator didn't connect to all deviceservers ... skipping tests" # FIXME: we really should handle missing and newly appearing deviceservers. # safety timeout self.timeout = reactor.callLater(10, self.failed, "Aggregator failed to map all deviceservers ... failing") self.aggregator.notifyOnMapped(self.succeeded) self.done = False while not self.done: print "Waiting for aggregator to map deviceservers" reactor.iterate(0.1) if self.failure: raise unittest.SkipTest, "Aggregator didn't start correctly, skipping tests" def tearDownClass(self): """Stop the DeviceServer running in a child process""" print "*** tearDownClass: ", self.deviceserverprocess.done self.deviceserverprocess.waitOnShutDown() def succeeded(self, *args): """Allow reactor iteration loop in test proper to exit and pass test""" self.done = True if self.timeout is not None: self.timeout.cancel() # safety timeout no longer necessary self.timeout = None self.lastargs = args # make persistent for later checks def failed(self, reason): """Allow reactor iteration loop in test proper to exit and fail test""" self.done = True self.failure = reason self.timeout.cancel() # safety timeout no longer necessary self.timeout = None def setUp(self): """I'm called at the very beginning of each test""" self.done = False self.failure = None self.timeout = None def tearDown(self): """I'm called at the end of each test""" if self.timeout: self.timeout.cancel() def timedOut(self): """I'm called when the safety timer expires indicating test probably won't complete""" print "timedOut callback, test did not complete" self.failed("Safety timeout callback ... test did not complete") reactor.crash() #---------- tests proper ------------------------------------ def test_handled_configurator(self): """Aggregator instantiated with a configurator rather than .conf filename""" assert 'DeviceServer1' in self.aggregator.config def test_password(self): """Aggregator should have random password""" assert type(self.aggregator.getPassword()) == type("") # ensure a second instance has differing password ... conf = Configurator() conf.fromString('') other = Aggregator(conf) assert other.getPassword() != self.aggregator.getPassword() def test_devicelist_as_deferred(self): """Return aggregated device list""" # safety timeout self.timeout = reactor.callLater(10, self.failed, "retrieving devicelist timed out ... failing") d = self.aggregator.getDeviceList() assert isinstance(d, defer.Deferred) d.addCallback(self.succeeded) # idle until code above triggers succeeded or timeout causes failure while not self.done: reactor.iterate(0.1) # will arrive here eventually when either succeeded or failed method has fired if self.failure: self.failed(self.failure) devicelist = self.lastargs[0] assert len(devicelist) == 2 assert 'Device1' in devicelist assert 'Device2' in devicelist def test_devicemap_as_deferred(self): """Return aggregated device map""" # safety timeout self.timeout = reactor.callLater(10, self.failed, "retrieving devicemap timed out ... failing") d = self.aggregator.getDeviceMap() assert isinstance(d, defer.Deferred) # caution: as this deferred is ready-to-go, the callback is called *immediately* d.addCallback(self.succeeded) # i.e., self.succeeded has now been called # idle until code above triggers succeeded or timeout causes failure while not self.done: reactor.iterate(0.1) # will arrive here eventually when either succeeded or failed method has fired if self.failure: self.failed(self.failure) devicemap = self.lastargs[0] print devicemap assert type(devicemap) == types.DictType assert len(devicemap) == 1 assert 'PseudoDevice' in devicemap assert len(devicemap['PseudoDevice']) == 2 assert 'Device1' in devicemap['PseudoDevice'] assert 'Device2' in devicemap['PseudoDevice'] def test_device_execute(self): """Proxy forward command to correct DeviceServer""" # safety timeout self.timeout = reactor.callLater(10, self.failed, "executing remote setParameter timed out ... failing") # 3-digit random integer value = int(random.random()*1000) # get a device key for use in next step self.done = False d = self.aggregator.getDeviceList() d.addCallback(self.succeeded) d.addErrback(self.failed) while not self.done: reactor.iterate(0.1) if self.failure: self.fail(self.failure) print print "DEBUG:" device = self.lastargs[0][0] print device.name # store number in 'remote' PseudoDevice d = self.aggregator.deviceExecute(device, 'setParameter', value) assert isinstance(d, defer.Deferred) d.addCallback(self.succeeded) # idle until code above triggers succeeded or timeout causes failure self.done = False while not self.done: reactor.iterate(0.1) # will arrive here eventually when either succeeded or failed method has fired if self.failure: self.failed(self.failure) # safety timeout self.timeout = reactor.callLater(10, self.failed, "executing remote getParameter timed out ... failing") # store number in 'remote' PseudoDevice d = self.aggregator.deviceExecute(device, 'getParameter') assert isinstance(d, defer.Deferred) d.addCallback(self.succeeded) # idle until code above triggers succeeded or timeout causes failure self.done = False while not self.done: reactor.iterate(0.1) # will arrive here eventually when either succeeded or failed method has fired if self.failure: self.failed(self.failure) returnvalue = self.lastargs[0] assert returnvalue == value if False: test_handled_configurator = True test_devicelist_as_deferred = True test_devicemap_as_deferred = True test_device_execute = True test_password = True
class TestConnector(SignalMixin, unittest.TestCase): def setUpClass(self): """Start a DeviceServer in a child process to test against""" # deviceserver startup script directory bindir = os.path.join(agdevicecontrol.path, 'bin') # keep track of temporary files for deletion in tearDown self.tempfiles = [] # create a temporary deviceserver config file filename = 'test_deviceserver.conf' fqfilename = bindir + os.sep + filename f = open(fqfilename,'w') f.write(deviceserver_config_contents) f.close() self.tempfiles.append(fqfilename) # start deviceserver as a child process self.process = SubProcessProtocol() self.process.waitOnStartUp(['server.py', filename, '-n'], path = bindir) if self.process.running is False: raise unittest.SkipTest, "DeviceServer didn't start correctly, skipping tests" def tearDownClass(self): """Stop the DeviceServer running in a child process""" print "*** tearDownClass: ", self.process.done self.process.waitOnShutDown() # clean-up temporary config files for f in self.tempfiles: os.remove(f) def setUp(self): """Per test initalization""" self.done = False self.failure = None def tearDown(self): """Per test cleanup code""" if self.connector: self.connector.close() def succeeded(self, *args): """Allow reactor iteration loop in test proper to exit and pass test""" self.done = True self.timeout.cancel() # safety timeout no longer necessary self.lastargs = args # make persistent for later checks def failed(self, reason): """Allow reactor iteration loop in test proper to exit and fail test""" self.done = True self.failure = reason self.lastargs = None def test_unauthorized_connect(self): """Should fail to connect (unauthorized)""" # safety timeout self.timeout = reactor.callLater(10, self.failed, "attempt to connect to DeviceServer timed out ... failing") self.connector = Connector('localhost') self.connector.connect(callback=self.failed, errback=self.succeeded) # idle until code above triggers succeeded or timeout causes failure while not self.done: reactor.iterate(0.1) # will arrive here eventually when either succeeded or failed method has fired if self.failure: self.fail(self.failure) # paranoia check assert self.connector.connected is False def test_simple_connect(self): """Obtain perspective on DeviceServer""" # safety timeout self.timeout = reactor.callLater(10, self.failed, "attempt to connect to DeviceServer timed out ... failing") self.connector = Connector('localhost') self.connector.connect(callback=self.succeeded, errback=self.failed, password='******') # idle until code above triggers succeeded or timeout causes failure while not self.done: reactor.iterate(0.1) # will arrive here eventually when either succeeded or failed method has fired if self.failure: self.fail(self.failure) connector = self.lastargs[0] assert connector == self.connector # paranoia check assert self.connector.connected is True def test_connect_to_nonexistent_server(self): """Attempt to connect to known non-existent deviceserver""" # safety timeout self.timeout = reactor.callLater(15, self.failed, "attempt to connect to DeviceServer timed out ... failing") self.connector = Connector('localhost', port=9999) # assumption self.connector.connect(callback=self.failed, errback=self.succeeded, password='******') # idle until code above triggers succeeded or timeout causes failure while not self.done: reactor.iterate(0.1) print "self.connector.connected: ", self.connector.connected # paranoia check assert self.connector.connected is False # will arrive here eventually when either succeeded or failed method has fired if self.failure: self.fail(self.failure) def test_connect_and_execute(self): """Connect and issue simple command""" # wait for slow, single CPU machine to get twisted going in another thread. import time time.sleep(1) # safety timeout self.timeout = reactor.callLater(5, self.failed, "attempt to connect to DeviceServer timed out ... failing") self.connector = Connector('localhost') self.connector.connect(callback=self.succeeded, errback=self.failed, password='******') # idle until code above triggers succeeded or timeout causes failure while not self.done: reactor.iterate(0.1) # will arrive here eventually when either succeeded or failed method has fired if self.failure: self.fail(self.failure) self.timeout = reactor.callLater(5, self.failed, "Attempt to get devicelist timed out ... failing") # get a device key for use in next step self.done = False self.connector.getDeviceList(self.succeeded, errback=self.failed) while not self.done: reactor.iterate(0.1) if self.failure: self.fail(self.failure) print print "DEBUG:" print self.lastargs[0][0] device = self.lastargs[0][0] # safety timeout self.timeout = reactor.callLater(5, self.failed, "attempt to getParameter timed out ... failing") self.connector.deviceExecute(device, 'getParameter', callback=self.succeeded, errback=self.failed) # idle until code above triggers succeeded or timeout causes failure self.done = False while not self.done: reactor.iterate(0.1) # will arrive here eventually when either succeeded or failed method has fired if self.failure: self.fail(self.failure) # expected return values value, connector, device, command, params = self.lastargs assert type(value) == types.IntType assert connector == self.connector assert device == 'Device1' assert command == 'getParameter' assert params == None def test_connect_and_get_devicemap(self): """Connect and retrieve devicemap""" # safety timeout self.timeout = reactor.callLater(5, self.failed, "attempt to connect to DeviceServer timed out ... failing") self.connector = Connector('localhost') self.connector.connect(callback=self.succeeded, errback=self.failed, password='******') # idle until code above triggers succeeded or timeout causes failure while not self.done: reactor.iterate(0.1) # will arrive here eventually when either succeeded or failed method has fired if self.failure: self.fail(self.failure) # safety timeout self.timeout = reactor.callLater(5, self.failed, "attempt to getDeviceMap timed out ... failing") self.connector.getDeviceMap(callback=self.succeeded, errback=self.failed) # idle until code above triggers succeeded or timeout causes failure self.done = False while not self.done: reactor.iterate(0.1) # will arrive here eventually when either succeeded or failed method has fired if self.failure: self.fail(self.failure) # expected return values devmap = self.lastargs[0] assert len(devmap) == 1 assert 'PseudoDevice' in devmap assert len(devmap['PseudoDevice']) == 2 assert 'Device1' in devmap['PseudoDevice'] assert 'Device2' in devmap['PseudoDevice'] def test_connect_and_raise_exception(self): """Connect and raise pseudodevice error""" # safety timeout self.timeout = reactor.callLater(5, self.failed, "attempt to connect to DeviceServer timed out ... failing") self.connector = Connector('localhost') self.connector.connect(callback=self.succeeded, errback=self.failed, password='******') # idle until code above triggers succeeded or timeout causes failure while not self.done: reactor.iterate(0.1) # will arrive here eventually when either succeeded or failed method has fired if self.failure: self.fail(self.failure) # safety timeout self.timeout = reactor.callLater(5, self.failed, "attempt to raise remote exception timed out ... failing") self.done = False self.connector.deviceExecute('Device1', 'raiseException', callback=self.failed, errback=self.succeeded) # idle until code above triggers succeeded or timeout causes failure while not self.done: reactor.iterate(0.1) # will arrive here eventually when either succeeded or failed method has fired if self.failure: self.fail(self.failure) # expecting returnvalue of exception # should still be connected ... # safety timeout self.timeout = reactor.callLater(5, self.failed, "attempt to getDeviceMap timed out ... failing") self.connector.getDeviceMap(callback=self.succeeded, errback=self.failed) # idle until code above triggers succeeded or timeout causes failure self.done = False while not self.done: reactor.iterate(0.1) # will arrive here eventually when either succeeded or failed method has fired if self.failure: assert connector.connected is False self.fail(self.failure) # expected return values devmap = self.lastargs[0] self.assertEqual(self.connector.connected, True) if False: test_unauthorized_connect.skip = True test_simple_connect.skip = True test_connect_to_nonexistent_server.skip = True test_connect_and_execute.skip = True test_connect_and_get_devicemap.skip = True test_connect_and_raise_exception.skip = True