class TestICAClass(tornado.testing.AsyncTestCase): def setUp(self): super(TestICAClass, self).setUp() self.client = InspectingClientAsync('', 0, initial_inspection=False, ioloop=self.io_loop) self.client.set_state_callback(self._cb_state) def test_initial_state(self): self.assertEqual(self.client.state, inspecting_client.InspectingClientStateType( connected=False, synced=False, model_changed=False, data_synced=False)) def _cb_state(self, state, model_changes): """A callback used in the test.""" self.stop((state, model_changes)) def test_util_method_difference_add(self): """Test the _difference utility method on add.""" name = None original_keys = ['B', 'C'] updated_keys = ['B', 'C', 'D'] self.client._sensors_index = {} for sen in original_keys: data = {'description': "This is {0}.".format(sen)} self.client._update_index(self.client._sensors_index, sen, data) added, removed = self.client._difference( original_keys, updated_keys, name, self.client._sensors_index) self.assertIn('D', added) self.assertIn('B', self.client.sensors) self.assertIn('C', self.client.sensors) def test_util_method_difference_rem(self): """Test the _difference utility method on remove.""" name = None original_keys = ['A', 'B', 'C'] updated_keys = ['B', 'C'] self.client._sensors_index = {} for sen in original_keys: data = {'description': "This is {0}.".format(sen)} self.client._update_index(self.client._sensors_index, sen, data) added, removed = self.client._difference( original_keys, updated_keys, name, self.client._sensors_index) self.assertIn('A', removed) self.assertNotIn('A', self.client.sensors) self.assertIn('B', self.client.sensors) self.assertIn('C', self.client.sensors) def test_util_method_difference_rem_named(self): """Test the _difference utility method on remove with name set.""" name = 'A' original_keys = ['B', 'C'] updated_keys = [] self.client._sensors_index = {} for sen in original_keys: data = {'description': "This is {0}.".format(sen)} self.client._update_index(self.client._sensors_index, sen, data) added, removed = self.client._difference( original_keys, updated_keys, name, self.client._sensors_index) self.assertNotIn('A', removed) self.assertNotIn('A', self.client.sensors) self.assertIn('B', self.client.sensors) self.assertIn('C', self.client.sensors) def test_util_method_difference_changed(self): """Test the _difference utility method on changed.""" name = None original_keys = ['B'] updated_keys = ['B'] self.client._sensors_index = {} for sen in original_keys: data = {'description': "This is {0}.".format(sen), '_changed': True} self.client._update_index(self.client._sensors_index, sen, data) added, removed = self.client._difference(original_keys, updated_keys, name, self.client._sensors_index) self.assertIn('B', self.client.sensors) def test_update_index(self): """Test the update_index method.""" index = self.client._sensors_index = {} data = {'description': "This is {0}.".format('A')} self.client._update_index(index, 'A', data) data = {'description': "This is {0}.".format('B')} self.client._update_index(index, 'B', data) data = {'description': "This is {0}.".format('A')} self.client._update_index(index, 'A', data) data = {'description': "This is new {0}.".format('B')} self.client._update_index(index, 'B', data) self.assertIn('new', index['B'].get('description')) self.assertFalse(index['A'].get('_changed', False)) self.assertTrue(index['B'].get('_changed'))
class TestInspectingClientAsyncStateCallback(tornado.testing.AsyncTestCase): longMessage = True maxDiff = None def setUp(self): super(TestInspectingClientAsyncStateCallback, self).setUp() self.server = DeviceTestServer('', 0) start_thread_with_cleanup(self, self.server, start_timeout=1) self.host, self.port = self.server.bind_address self.state_cb_future = tornado.concurrent.Future() self.client = InspectingClientAsync(self.host, self.port, ioloop=self.io_loop) # Set a short initial_resync timeout to make resync tests quick self.client.initial_resync_timeout = 0.001 self.client.set_state_callback(self._test_state_cb) self.done_state_cb_futures = [] self.cnt_state_cb_futures = collections.defaultdict(tornado.concurrent.Future) def _test_state_cb(self, state, model_changes): f = self.state_cb_future self.state_cb_future = tornado.concurrent.Future() self.done_state_cb_futures.append(f) num_calls = len(self.done_state_cb_futures) f.set_result((state, model_changes)) self.cnt_state_cb_futures[num_calls].set_result(None) @tornado.gen.coroutine def _check_cb_count(self, expected_count): """Let the ioloop run and assert that the callback has been called the expected number of times""" yield tornado.gen.moment self.assertEqual(len(self.done_state_cb_futures), expected_count) @tornado.testing.gen_test(timeout=1) def test_from_connect(self): # Hold back #version-connect informs num_calls_before = len(self.done_state_cb_futures) logger.debug('before starting client, num_calls_before:{}'.format(num_calls_before)) self.server.proceed_on_client_connect.clear() self.client.connect() state, model_changes = yield self.state_cb_future self.assertEqual(state, inspecting_client.InspectingClientStateType( connected=False, synced=False, model_changed=False, data_synced=False)) state, model_changes = yield self.state_cb_future self.assertEqual(state, inspecting_client.InspectingClientStateType( connected=True, synced=False, model_changed=False, data_synced=False)) self.assertIs(model_changes, None) # Due to the structure of the state loop the initial state may be sent # twice before we get here, and was the case for the initial # implementation. Changes made on 2015-01-26 caused it to happen only # once, hence + 1. If the implementation changes having + 2 would also # be OK. As, indeed, changes made on 2016-11-03 caused again :) yield self._check_cb_count(num_calls_before + 2) # Now let the server send #version-connect informs num_calls_before = len(self.done_state_cb_futures) self.server.ioloop.add_callback(self.server.proceed_on_client_connect.set) # We're expecting two calls hard on each other's heels, so lets wait for them yield self.cnt_state_cb_futures[num_calls_before + 2] # We expected two status callbacks, and no more after yield self._check_cb_count(num_calls_before + 2) state, model_changes = yield self.done_state_cb_futures[-2] state2, model_changes2 = yield self.done_state_cb_futures[-1] self.assertEqual(state, inspecting_client.InspectingClientStateType( connected=True, synced=False, model_changed=True, data_synced=True)) # Check that the expected model changes came from the callback self._test_expected_model_changes(model_changes) self.assertEqual(state2, inspecting_client.InspectingClientStateType( connected=True, synced=True, model_changed=False, data_synced=True)) self.assertEqual(model_changes2, None) def _test_expected_model_changes(self, model_changes): # Check that the model_changes reflect the sensors and requests of the # test sever (self.server) server_sensors = self.server._sensors.keys() server_requests = self.server._request_handlers.keys() self.assertEqual(model_changes, dict( sensors=dict(added=set(server_sensors), removed=set()), requests=dict(added=set(server_requests), removed=set()))) @tornado.testing.gen_test(timeout=1) def test_reconnect(self): self.client.connect() yield self.client.until_synced() yield tornado.gen.moment # Make sure the ioloop is 'caught up' # cause a disconnection and check that the callback is called num_calls_before = len(self.done_state_cb_futures) self.server.stop() self.server.join() state, model_changes = yield self.state_cb_future self.assertEqual(state, inspecting_client.InspectingClientStateType( connected=False, synced=False, model_changed=False, data_synced=False)) self.assertIs(model_changes, None) yield self._check_cb_count(num_calls_before + 1) @tornado.gen.coroutine def _test_inspection_error(self, break_var, break_message): # Test that the client retries if there is an error in the inspection # process setattr(self.server, break_var, break_message) self.client.connect() # Wait for the client to be connected yield self.client.until_connected() # Wait for the state loop to send another update or 2 yield self.state_cb_future state, _ = yield self.state_cb_future # Check that data is still not synced self.assertFalse(state.synced) self.assertFalse(state.data_synced) # Now fix the inspection request, client should sync up. setattr(self.server, break_var, False) # Check that the server's sensors and request are reflected in the model # changes. # changes_state = inspecting_client.InspectingClientStateType( connected=True, synced=False, model_changed=True, data_synced=True) yield self.client.until_state(changes_state) state, model_changes = self.done_state_cb_futures[-1].result() assert state == changes_state self._test_expected_model_changes(model_changes) yield self.client.until_synced() self.assertTrue(self.client.synced) @tornado.testing.gen_test(timeout=1) def test_help_inspection_error(self): yield self._test_inspection_error('break_help', 'Help is broken') @tornado.testing.gen_test(timeout=1) def test_sensor_list_inspection_error(self): yield self._test_inspection_error( 'break_sensor_list', 'Sensor-list is broken')
class TestICAClass(tornado.testing.AsyncTestCase): def setUp(self): super(TestICAClass, self).setUp() self.client = InspectingClientAsync('', 0, initial_inspection=False, ioloop=self.io_loop) self.client.set_state_callback(self._cb_state) def test_initial_state(self): self.assertEqual(self.client.state, inspecting_client.InspectingClientStateType( connected=False, synced=False, model_changed=False, data_synced=False)) def _cb_state(self, state, model_changes): """A callback used in the test.""" self.stop((state, model_changes)) def test_util_method_difference_add(self): """Test the _difference utility method on add.""" name = None original_keys = ['B', 'C'] updated_keys = ['B', 'C', 'D'] self.client._sensors_index = {} for sen in original_keys: data = {'description': "This is {0}.".format(sen)} self.client._update_index(self.client._sensors_index, sen, data) added, removed = self.client._difference( original_keys, updated_keys, name, self.client._sensors_index) self.assertIn('D', added) self.assertIn('B', self.client.sensors) self.assertIn('C', self.client.sensors) def test_util_method_difference_rem(self): """Test the _difference utility method on remove.""" name = None original_keys = ['A', 'B', 'C'] updated_keys = ['B', 'C'] self.client._sensors_index = {} for sen in original_keys: data = {'description': "This is {0}.".format(sen)} self.client._update_index(self.client._sensors_index, sen, data) added, removed = self.client._difference( original_keys, updated_keys, name, self.client._sensors_index) self.assertIn('A', removed) self.assertNotIn('A', self.client.sensors) self.assertIn('B', self.client.sensors) self.assertIn('C', self.client.sensors) def test_util_method_difference_rem_named(self): """Test the _difference utility method on remove with name set.""" name = 'A' original_keys = ['B', 'C'] updated_keys = [] self.client._sensors_index = {} for sen in original_keys: data = {'description': "This is {0}.".format(sen)} self.client._update_index(self.client._sensors_index, sen, data) added, removed = self.client._difference( original_keys, updated_keys, name, self.client._sensors_index) self.assertNotIn('A', removed) self.assertNotIn('A', self.client.sensors) self.assertIn('B', self.client.sensors) self.assertIn('C', self.client.sensors) def test_util_method_difference_changed(self): """Test the _difference utility method on changed.""" name = None original_keys = ['B'] updated_keys = ['B'] self.client._sensors_index = {} for sen in original_keys: data = {'description': "This is {0}.".format(sen), '_changed': True} self.client._update_index(self.client._sensors_index, sen, data) added, removed = self.client._difference(original_keys, updated_keys, name, self.client._sensors_index) self.assertIn('B', self.client.sensors) def test_update_index(self): """Test the update_index method.""" index = self.client._sensors_index = {} data = {'description': "This is {0}.".format('A')} self.client._update_index(index, 'A', data) data = {'description': "This is {0}.".format('B')} self.client._update_index(index, 'B', data) data = {'description': "This is {0}.".format('A')} self.client._update_index(index, 'A', data) data = {'description': "This is new {0}.".format('B')} self.client._update_index(index, 'B', data) self.assertIn('new', index['B'].get('description')) self.assertFalse(index['A'].get('_changed', False)) self.assertTrue(index['B'].get('_changed'))
class TestInspectingClientAsyncStateCallback(tornado.testing.AsyncTestCase): def setUp(self): super(TestInspectingClientAsyncStateCallback, self).setUp() self.server = DeviceTestServer('', 0) start_thread_with_cleanup(self, self.server, start_timeout=1) self.host, self.port = self.server.bind_address self.state_cb_future = tornado.concurrent.Future() self.client = InspectingClientAsync(self.host, self.port, ioloop=self.io_loop) self.client.set_state_callback(self._test_state_cb) self.done_state_cb_futures = [] self.cnt_state_cb_futures = collections.defaultdict(tornado.concurrent.Future) def _test_state_cb(self, state, model_changes): f = self.state_cb_future self.state_cb_future = tornado.concurrent.Future() self.done_state_cb_futures.append(f) num_calls = len(self.done_state_cb_futures) f.set_result((state, model_changes)) self.cnt_state_cb_futures[num_calls].set_result(None) @tornado.gen.coroutine def _check_no_cb(self, no_expected): """Let the ioloop run and assert that the callback was not called""" yield tornado.gen.moment self.assertEqual(len(self.done_state_cb_futures), no_expected) @tornado.testing.gen_test(timeout=1) def test_from_connect(self): # Hold back #version-connect informs num_calls_before = len(self.done_state_cb_futures) logger.debug('before starting client, num_calls_before:{}'.format(num_calls_before)) self.server.proceed_on_client_connect.clear() self.client.connect() state, model_changes = yield self.state_cb_future self.assertEqual(state, inspecting_client.InspectingClientStateType( connected=True, synced=False, model_changed=False, data_synced=False)) self.assertIs(model_changes, None) # Due to the structure of the state loop the initial state may be sent twice # before we get her, and was the case for the initial implementation. Changes made # on 2015-01-26 caused it to happy only once, hence + 1. If the implementation # changes having + 2 would also be OK. yield self._check_no_cb(num_calls_before + 1) # Now let the server send #version-connect informs num_calls_before = len(self.done_state_cb_futures) self.server.ioloop.add_callback(self.server.proceed_on_client_connect.set) # We're expecting two calls hard on each other's heels, so lets wait for them yield self.cnt_state_cb_futures[num_calls_before + 2] # We expected two status callbacks, and no more after yield self._check_no_cb(num_calls_before + 2) state, model_changes = yield self.done_state_cb_futures[-2] state2, model_changes2 = yield self.done_state_cb_futures[-1] self.assertEqual(state, inspecting_client.InspectingClientStateType( connected=True, synced=False, model_changed=True, data_synced=True)) server_sensors = self.server._sensors.keys() server_requests = self.server._request_handlers.keys() self.assertEqual(model_changes, dict( sensors=dict(added=set(server_sensors), removed=set()), requests=dict(added=set(server_requests), removed=set()))) self.assertEqual(state2, inspecting_client.InspectingClientStateType( connected=True, synced=True, model_changed=False, data_synced=True)) self.assertEqual(model_changes2, None) @tornado.testing.gen_test(timeout=1) def test_reconnect(self): self.client.connect() yield self.client.until_synced() yield tornado.gen.moment # Make sure the ioloop is 'caught up' # cause a disconnection and check that the callback is called num_calls_before = len(self.done_state_cb_futures) self.server.stop() self.server.join() state, model_changes = yield self.state_cb_future self.assertEqual(state, inspecting_client.InspectingClientStateType( connected=False, synced=False, model_changed=False, data_synced=False)) self.assertIs(model_changes, None) yield self._check_no_cb(num_calls_before + 1)
class TestInspectingClientAsyncStateCallback(tornado.testing.AsyncTestCase): longMessage = True maxDiff = None def setUp(self): super(TestInspectingClientAsyncStateCallback, self).setUp() self.server = DeviceTestServer('', 0) start_thread_with_cleanup(self, self.server, start_timeout=1) self.host, self.port = self.server.bind_address self.state_cb_future = tornado.concurrent.Future() self.client = InspectingClientAsync(self.host, self.port, ioloop=self.io_loop) # Set a short initial_resync timeout to make resync tests quick self.client.initial_resync_timeout = 0.001 self.client.set_state_callback(self._test_state_cb) self.done_state_cb_futures = [] self.cnt_state_cb_futures = collections.defaultdict(tornado.concurrent.Future) def _test_state_cb(self, state, model_changes): f = self.state_cb_future self.state_cb_future = tornado.concurrent.Future() self.done_state_cb_futures.append(f) num_calls = len(self.done_state_cb_futures) f.set_result((state, model_changes)) self.cnt_state_cb_futures[num_calls].set_result(None) @tornado.gen.coroutine def _check_cb_count(self, expected_count): """Let the ioloop run and assert that the callback has been called the expected number of times""" yield tornado.gen.moment self.assertEqual(len(self.done_state_cb_futures), expected_count) @tornado.testing.gen_test(timeout=1) def test_from_connect(self): # Hold back #version-connect informs num_calls_before = len(self.done_state_cb_futures) logger.debug('before starting client, num_calls_before:{}'.format(num_calls_before)) self.server.proceed_on_client_connect.clear() self.client.connect() state, model_changes = yield self.state_cb_future self.assertEqual(state, inspecting_client.InspectingClientStateType( connected=False, synced=False, model_changed=False, data_synced=False)) state, model_changes = yield self.state_cb_future self.assertEqual(state, inspecting_client.InspectingClientStateType( connected=True, synced=False, model_changed=False, data_synced=False)) self.assertIs(model_changes, None) # Due to the structure of the state loop the initial state may be sent # twice before we get here, and was the case for the initial # implementation. Changes made on 2015-01-26 caused it to happen only # once, hence + 1. If the implementation changes having + 2 would also # be OK. As, indeed, changes made on 2016-11-03 caused again :) yield self._check_cb_count(num_calls_before + 2) # Now let the server send #version-connect informs num_calls_before = len(self.done_state_cb_futures) self.server.ioloop.add_callback(self.server.proceed_on_client_connect.set) # We're expecting two calls hard on each other's heels, so lets wait for them yield self.cnt_state_cb_futures[num_calls_before + 2] # We expected two status callbacks, and no more after yield self._check_cb_count(num_calls_before + 2) state, model_changes = yield self.done_state_cb_futures[-2] state2, model_changes2 = yield self.done_state_cb_futures[-1] self.assertEqual(state, inspecting_client.InspectingClientStateType( connected=True, synced=False, model_changed=True, data_synced=True)) # Check that the expected model changes came from the callback self._test_expected_model_changes(model_changes) self.assertEqual(state2, inspecting_client.InspectingClientStateType( connected=True, synced=True, model_changed=False, data_synced=True)) self.assertEqual(model_changes2, None) def _test_expected_model_changes(self, model_changes): # Check that the model_changes reflect the sensors and requests of the # test sever (self.server) server_sensors = self.server._sensors.keys() server_requests = self.server._request_handlers.keys() self.assertEqual(model_changes, dict( sensors=dict(added=set(server_sensors), removed=set()), requests=dict(added=set(server_requests), removed=set()))) @tornado.testing.gen_test(timeout=1) def test_reconnect(self): self.client.connect() yield self.client.until_synced() yield tornado.gen.moment # Make sure the ioloop is 'caught up' # cause a disconnection and check that the callback is called num_calls_before = len(self.done_state_cb_futures) self.server.stop() self.server.join() state, model_changes = yield self.state_cb_future self.assertEqual(state, inspecting_client.InspectingClientStateType( connected=False, synced=False, model_changed=False, data_synced=False)) self.assertIs(model_changes, None) yield self._check_cb_count(num_calls_before + 1) @tornado.gen.coroutine def _test_inspection_error(self, break_var, break_message): # Test that the client retries if there is an error in the inspection # process setattr(self.server, break_var, break_message) self.client.connect() # Wait for the client to be connected yield self.client.until_connected() # Wait for the state loop to send another update or 2 yield self.state_cb_future state, _ = yield self.state_cb_future # Check that data is still not synced self.assertFalse(state.synced) self.assertFalse(state.data_synced) # Now fix the inspection request, client should sync up. setattr(self.server, break_var, False) # Check that the server's sensors and request are reflected in the model # changes. # changes_state = inspecting_client.InspectingClientStateType( connected=True, synced=False, model_changed=True, data_synced=True) yield self.client.until_state(changes_state) state, model_changes = self.done_state_cb_futures[-1].result() assert state == changes_state self._test_expected_model_changes(model_changes) yield self.client.until_synced() self.assertTrue(self.client.synced) @tornado.testing.gen_test(timeout=1) def test_help_inspection_error(self): yield self._test_inspection_error('break_help', 'Help is broken') @tornado.testing.gen_test(timeout=1) def test_sensor_list_inspection_error(self): yield self._test_inspection_error( 'break_sensor_list', 'Sensor-list is broken')