def test_send_request(self):
        """Very high level test.

        Calling methods to insure they do not raise exception.

        """
        client = InspectingClientAsync(self.host, self.port,
                                       ioloop=self.io_loop,
                                       initial_inspection=False)

        yield client.connect()
        yield client.until_connected()
        yield client.until_synced()
        self.assertEquals(len(client.sensors), 0)

        self.assertEquals(len(client.requests), 0)
        self.assertTrue(client.synced)
        self.assertTrue(client.is_connected())
        self.assertTrue(client.connected)
        yield client.simple_request('sensor-sampling', 'an.int', 'event')
        # Wait for sync and check if the sensor was automaticaly added.
        # Get the sensor object and see if it has data.
        sensor = yield client.future_get_sensor('an.int')
        self.assertEquals(len(client.sensors), 1)
        self.assertTrue(sensor.read())
        self.assertEquals(len(client.requests), 0)
    def test_send_request(self):
        """Very high level test.

        Calling methods to insure they do not raise exception.

        """
        client = InspectingClientAsync(self.host, self.port,
                                       ioloop=self.io_loop,
                                       initial_inspection=False)

        yield client.connect()
        yield client.until_connected()
        yield client.until_synced()
        self.assertEquals(len(client.sensors), 0)

        self.assertEquals(len(client.requests), 0)
        self.assertTrue(client.synced)
        self.assertTrue(client.is_connected())
        self.assertTrue(client.connected)
        yield client.simple_request('sensor-sampling', 'an.int', 'event')
        # Wait for sync and check if the sensor was automaticaly added.
        # Get the sensor object and see if it has data.
        sensor = yield client.future_get_sensor('an.int')
        self.assertEquals(len(client.sensors), 1)
        self.assertTrue(sensor.read())
        self.assertEquals(len(client.requests), 0)
class TestInspectingClientAsync(tornado.testing.AsyncTestCase):

    def setUp(self):
        super(TestInspectingClientAsync, 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.client = InspectingClientAsync(self.host, self.port,
                                            ioloop=self.io_loop)
        self.io_loop.add_callback(self.client.connect)

    @tornado.testing.gen_test
    def test_timeout_of_until_synced(self):
        # Test for timing out
        with self.assertRaises(tornado.gen.TimeoutError):
            yield self.client.until_synced(timeout=0.00001)
        # Test for NOT timing out
        yield self.client.until_synced(timeout=0.5)

    @tornado.testing.gen_test
    def test_simple_request(self):
        """Perform a basic request."""
        yield self.client.until_synced()
        reply, informs = yield self.client.simple_request('help', 'watchdog')
        self.assertIn('ok', str(reply))
        self.assertEquals(len(informs), 1)

    @tornado.testing.gen_test
    def test_sensor(self):
        """Access the sensor with the Async client."""
        yield self.client.until_synced()
        sensor_name = 'an.int'
        sensor = yield self.client.future_get_sensor(sensor_name)
        self.assertEquals(sensor.name, sensor_name)
        self.assertEquals(sensor.stype, 'integer')

        # Unknown sensor requests return a None.
        sensor_name = 'thing.unknown_sensor'
        sensor = yield self.client.future_get_sensor(sensor_name)
        self.assertIsNone(sensor)

    @tornado.testing.gen_test
    def test_request_access(self):
        """Test access to requests."""
        yield self.client.until_synced()

        request_name = 'watchdog'
        self.assertIn(request_name, self.client.requests)
        request = yield self.client.future_get_request(request_name)
        self.assertEqual(request.name, request_name)
        self.assertTrue(request.description,
                        'Expected an description: got nothing.')

        # Unknown request return a None.
        request_name = 'watchcat'
        self.assertNotIn(request_name, self.client.requests)
        request = yield self.client.future_get_request(request_name)
        self.assertIsNone(request)

    @tornado.testing.gen_test
    def test_sensor_add_remove(self):
        """Test a sensor being added and then remove it."""
        yield self.client.until_synced()

        sensor = DeviceTestSensor(Sensor.INTEGER, "another.int",
                                  "An Integer.",
                                  "count", [-5, 5], timestamp=time.time(),
                                  status=Sensor.NOMINAL, value=3)
        # Check that the sensor does not exist currently
        self.assertNotIn(sensor.name, self.client.sensors)

        # Add a sensor.
        self.server.add_sensor(sensor)
        self.server.mass_inform(Message.inform('interface-changed'))
        # Do a blocking request to ensure #interface-changed has been received
        yield self.client.simple_request('watchdog')
        yield self.client.until_synced()
        self.assertIn('another.int', self.client.sensors)

        # Remove a sensor.
        self.server.remove_sensor(sensor)
        self.server.mass_inform(Message.inform('interface-changed'))
        # Do a blocking request to ensure #interface-changed has been received
        yield self.client.simple_request('watchdog')

        yield self.client.until_synced()
        self.assertNotIn('another.int', self.client.sensors)


    @tornado.testing.gen_test
    def test_request_add_remove(self):
        """Test a request being added and then remove it."""
        yield self.client.until_synced()

        def request_sparkling_new(self, req, msg):
            """A new command."""
            return Message.reply(msg.name, "ok", "bling1", "bling2")

        # Check that the request did not exist before
        self.assertNotIn('sparkling-new', self.client.requests)

        # Add a request.
        self.server.request_sparkling_new = request_sparkling_new
        self.server._request_handlers['sparkling-new'] = request_sparkling_new
        self.server.mass_inform(Message.inform('interface-changed'))
        # Do a blocking request to ensure #interface-changed has been received
        yield self.client.simple_request('watchdog')

        yield self.client.until_synced()
        self.assertIn('sparkling-new', self.client.requests)
        req = yield self.client.future_get_request('sparkling-new')
        self.assertEqual(req.name, 'sparkling-new')

        # Remove a request.
        self.server.request_sparkling_new = None
        del(self.server._request_handlers['sparkling-new'])
        self.server.mass_inform(Message.inform('interface-changed'))
        # Do a blocking request to ensure #interface-changed has been received
        self.client.simple_request('watchdog')
        yield self.client.until_synced()
        self.assertNotIn('sparkling_new', self.client.requests)

    @tornado.testing.gen_test
    def test_send_request(self):
        """Very high level test.

        Calling methods to insure they do not raise exception.

        """
        client = InspectingClientAsync(self.host, self.port,
                                       ioloop=self.io_loop,
                                       initial_inspection=False)

        yield client.connect()
        yield client.until_connected()
        yield client.until_synced()
        self.assertEquals(len(client.sensors), 0)

        self.assertEquals(len(client.requests), 0)
        self.assertTrue(client.synced)
        self.assertTrue(client.is_connected())
        self.assertTrue(client.connected)
        yield client.simple_request('sensor-sampling', 'an.int', 'event')
        # Wait for sync and check if the sensor was automaticaly added.
        # Get the sensor object and see if it has data.
        sensor = yield client.future_get_sensor('an.int')
        self.assertEquals(len(client.sensors), 1)
        self.assertTrue(sensor.read())
        self.assertEquals(len(client.requests), 0)

    @tornado.testing.gen_test
    def test_handle_sensor_value(self):
        yield self.client.until_connected()
        # Test that #sensor-value informs are handles like #sensor-inform informs if
        # handle_sensor_value() is called.
        sens = yield self.client.future_get_sensor('an.int')
        test_val = 1911
        # Check that the sensor doesn't start out with our test value
        self.assertNotEqual(sens.read().value, test_val)
        # Now set the value of the sensor on the server
        server_sens = self.server.get_sensor('an.int')
        server_sens.set_value(test_val)
        # Do a request to ensure we are synced with the server
        yield self.client.simple_request('watchdog')
        # Test that the value has not yet been set on the client sensor (there are no
        # strategies set)
        self.assertNotEqual(sens.read().value, test_val)
        # Now do a ?sensor-value request, and check that our object is NOT YET updated,
        # since we have not called handle_sensor_value() yet
        yield self.client.simple_request('sensor-value', 'an.int')
        self.assertNotEqual(sens.read().value, test_val)

        # Test call
        self.client.handle_sensor_value()

        # Now do a ?sensor-value request, and check that our object is updated
        yield self.client.simple_request('sensor-value', 'an.int')
        self.assertEqual(sens.read().value, test_val)

    @tornado.testing.gen_test
    def test_factories(self):
        yield self.client.until_connected()
        # Test that the correct factories are used to construct sensor and request
        # objects, and that the factories are called with the correct parameters.
        sf = self.client.sensor_factory = mock.Mock()
        rf = self.client.request_factory = mock.Mock()

        sen = yield self.client.future_get_sensor('an.int')
        req = yield self.client.future_get_request('watchdog')
        self.assertIs(sen, sf.return_value)
        sf.assert_called_once_with(
            units='count', sensor_type=0, params=[-5, 5],
            description='An Integer.', name='an.int')
        self.assertIs(req, rf.return_value)
        rf.assert_called_once_with(
            name='watchdog', description=mock.ANY, timeout_hint=None)
class TestInspectingClientAsync(tornado.testing.AsyncTestCase):

    def setUp(self):
        super(TestInspectingClientAsync, 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.client = InspectingClientAsync(self.host, self.port,
                                            ioloop=self.io_loop)
        self.io_loop.add_callback(self.client.connect)


    @tornado.testing.gen_test
    def test_simple_request(self):
        """Perform a basic request."""
        yield self.client.until_synced()
        reply, informs = yield self.client.simple_request('help', 'watchdog')
        self.assertIn('ok', str(reply))
        self.assertEquals(len(informs), 1)

    @tornado.testing.gen_test
    def test_sensor(self):
        """Access the sensor with the Async client."""
        yield self.client.until_synced()
        sensor_name = 'an.int'
        sensor = yield self.client.future_get_sensor(sensor_name)
        self.assertEquals(sensor.name, sensor_name)
        self.assertEquals(sensor.stype, 'integer')

        # Unknown sensor requests return a None.
        sensor_name = 'thing.unknown_sensor'
        sensor = yield self.client.future_get_sensor(sensor_name)
        self.assertIsNone(sensor)

    @tornado.testing.gen_test
    def test_request_access(self):
        """Test access to requests."""
        yield self.client.until_synced()

        request_name = 'watchdog'
        self.assertIn(request_name, self.client.requests)
        request = yield self.client.future_get_request(request_name)
        self.assertEqual(request.name, request_name)
        self.assertTrue(request.description,
                        'Expected an description: got nothing.')

        # Unknown request return a None.
        request_name = 'watchcat'
        self.assertNotIn(request_name, self.client.requests)
        request = yield self.client.future_get_request(request_name)
        self.assertIsNone(request)

    @tornado.testing.gen_test
    def test_sensor_add_remove(self):
        """Test a sensor being added and then remove it."""
        yield self.client.until_synced()

        sensor = DeviceTestSensor(Sensor.INTEGER, "another.int",
                                  "An Integer.",
                                  "count", [-5, 5], timestamp=time.time(),
                                  status=Sensor.NOMINAL, value=3)
        # Check that the sensor does not exist currently
        self.assertNotIn(sensor.name, self.client.sensors)

        # Add a sensor.
        self.server.add_sensor(sensor)
        self.server.mass_inform(Message.inform('interface-changed'))
        # Do a blocking request to ensure #interface-changed has been received
        yield self.client.simple_request('watchdog')
        yield self.client.until_synced()
        self.assertIn('another.int', self.client.sensors)

        # Remove a sensor.
        self.server.remove_sensor(sensor)
        self.server.mass_inform(Message.inform('interface-changed'))
        # Do a blocking request to ensure #interface-changed has been received
        yield self.client.simple_request('watchdog')

        yield self.client.until_synced()
        self.assertNotIn('another.int', self.client.sensors)


    @tornado.testing.gen_test
    def test_request_add_remove(self):
        """Test a request being added and then remove it."""
        yield self.client.until_synced()

        def request_sparkling_new(self, req, msg):
            """A new command."""
            return Message.reply(msg.name, "ok", "bling1", "bling2")

        # Check that the request did not exist before
        self.assertNotIn('sparkling-new', self.client.requests)

        # Add a request.
        self.server.request_sparkling_new = request_sparkling_new
        self.server._request_handlers['sparkling-new'] = request_sparkling_new
        self.server.mass_inform(Message.inform('interface-changed'))
        # Do a blocking request to ensure #interface-changed has been received
        yield self.client.simple_request('watchdog')

        yield self.client.until_synced()
        self.assertIn('sparkling-new', self.client.requests)
        req = yield self.client.future_get_request('sparkling-new')
        self.assertEqual(req.name, 'sparkling-new')

        # Remove a request.
        self.server.request_sparkling_new = None
        del(self.server._request_handlers['sparkling-new'])
        self.server.mass_inform(Message.inform('interface-changed'))
        # Do a blocking request to ensure #interface-changed has been received
        self.client.simple_request('watchdog')
        yield self.client.until_synced()
        self.assertNotIn('sparkling_new', self.client.requests)

    @tornado.testing.gen_test
    def test_send_request(self):
        """Very high level test.

        Calling methods to insure they do not raise exception.

        """
        client = InspectingClientAsync(self.host, self.port,
                                       ioloop=self.io_loop,
                                       initial_inspection=False)

        yield client.connect()
        yield client.until_connected()
        yield client.until_synced()
        self.assertEquals(len(client.sensors), 0)

        self.assertEquals(len(client.requests), 0)
        self.assertTrue(client.synced)
        self.assertTrue(client.is_connected())
        self.assertTrue(client.connected)
        yield client.simple_request('sensor-sampling', 'an.int', 'event')
        # Wait for sync and check if the sensor was automaticaly added.
        # Get the sensor object and see if it has data.
        sensor = yield client.future_get_sensor('an.int')
        self.assertEquals(len(client.sensors), 1)
        self.assertTrue(sensor.read())
        self.assertEquals(len(client.requests), 0)

    @tornado.testing.gen_test
    def test_handle_sensor_value(self):
        yield self.client.until_connected()
        # Test that #sensor-value informs are handles like #sensor-inform informs if
        # handle_sensor_value() is called.
        sens = yield self.client.future_get_sensor('an.int')
        test_val = 1911
        # Check that the sensor doesn't start out with our test value
        self.assertNotEqual(sens.read().value, test_val)
        # Now set the value of the sensor on the server
        server_sens = self.server.get_sensor('an.int')
        server_sens.set_value(test_val)
        # Do a request to ensure we are synced with the server
        yield self.client.simple_request('watchdog')
        # Test that the value has not yet been set on the client sensor (there are no
        # strategies set)
        self.assertNotEqual(sens.read().value, test_val)
        # Now do a ?sensor-value request, and check that our object is NOT YET updated,
        # since we have not called handle_sensor_value() yet
        yield self.client.simple_request('sensor-value', 'an.int')
        self.assertNotEqual(sens.read().value, test_val)

        # Test call
        self.client.handle_sensor_value()

        # Now do a ?sensor-value request, and check that our object is updated
        yield self.client.simple_request('sensor-value', 'an.int')
        self.assertEqual(sens.read().value, test_val)

    @tornado.testing.gen_test
    def test_factories(self):
        yield self.client.until_connected()
        # Test that the correct factories are used to construct sensor and request
        # objects, and that the factories are called with the correct parameters.
        sf = self.client.sensor_factory = mock.Mock()
        rf = self.client.request_factory = mock.Mock()

        sen = yield self.client.future_get_sensor('an.int')
        req = yield self.client.future_get_request('watchdog')

        self.assertIs(sen, sf.return_value)
        sf.assert_called_once_with(
            units=None, sensor_type=0, params=[-5, 5],
            description='An Integer.', name='an.int')
        self.assertIs(req, rf.return_value)
        rf.assert_called_once_with('watchdog', mock.ANY)