Example #1
0
def start_agent():
    conf = load_config(cfg.CONF)
    log.set_defaults()
    log.setup(conf, "watcher_metering")

    agent = Agent(conf, **conf.agent)

    agent.register_drivers()
    agent.start()
    agent.join()
    def test_register_metering_drivers(self):
        # Try to register/load each one of the driver using the Agent
        agent = Agent(
            conf=self.conf,
            driver_names=[self.driver_cls.get_name()],
            use_nanoconfig_service=False,
            publisher_endpoint="fake",
            nanoconfig_service_endpoint="",
            nanoconfig_update_endpoint="",
            nanoconfig_profile="nanoconfig://test_profile"
        )
        # Because it seems it does not clear from previous scenarios
        agent.drivers.clear()
        agent.register_drivers()

        self.assertEqual(
            sorted(agent.drivers.keys()),
            ["%s_%s" % (self.driver_cls.get_entry_name(),
                        self.driver_cls.get_default_probe_id())]
        )
Example #3
0
    def setUp(self):
        super(TestAgent, self).setUp()
        self.conf = cfg.ConfigOpts()
        # To load the drivers without using the config file
        self.useFixture(ConfFixture(self.conf))

        def _fake_parse(self, args=[]):
            return cfg.ConfigOpts._parse_cli_opts(self, [])

        _fake_parse_method = types.MethodType(_fake_parse, self.conf)
        self.conf._parse_cli_opts = _fake_parse_method

        # First dependency to be returned
        self.dummy_driver_manager = DriverManager.make_test_instance(
            extension=Extension(
                name=DummyMetricPuller.get_name(),
                entry_point='fake.entry.point',
                plugin=DummyMetricPuller,
                obj=None,
            ),
            namespace='TESTING',
        )
        # 2nd dependency to be returned
        self.fake_driver_manager = DriverManager.make_test_instance(
            extension=Extension(
                name=FakeMetricPuller.get_name(),
                entry_point='fake.entry.point',
                plugin=FakeMetricPuller,
                obj=None,
            ),
            namespace='TESTING',
        )
        self.defaults_drivers = {
            DummyMetricPuller.get_name(): self.dummy_driver_manager,
            FakeMetricPuller.get_name(): self.fake_driver_manager,
        }

        def _fake_loader(name, **kw):
            return self.defaults_drivers[name]

        # Patches the agent socket
        self.m_agent_socket = MagicMock(autospec=True)

        self.patches.extend([
            # Deactivates the nanomsg socket
            patch(
                "watcher_metering.agent.agent.nanomsg.Socket",
                new=self.m_agent_socket,
            ),
            # Sets the test namespace to 'TESTING'
            patch.object(
                Agent,
                "namespace",
                PropertyMock(return_value='TESTING'),
            ),
            # Patches the driver manager to retourn our test drivers
            # instead of the real ones
            patch(
                "watcher_metering.load.loader.DriverManager",
                MagicMock(side_effect=_fake_loader),
            ),
        ])

        # Applies all of our patches before each test
        for _patch in self.patches:
            _patch.start()

        self.agent = Agent(
            conf=self.conf,
            driver_names=self.conf.agent.driver_names,
            use_nanoconfig_service=False,
            publisher_endpoint="fake",
            nanoconfig_service_endpoint="",
            nanoconfig_update_endpoint="",
            nanoconfig_profile="nanoconfig://test_profile"
        )
        # Default ticking is set to 0 to reduce test execution time
        self.agent.TICK_INTERVAL = 0
Example #4
0
class TestAgent(BaseTestCase):

    # patches to be applied for each test in this test suite
    patches = []

    def setUp(self):
        super(TestAgent, self).setUp()
        self.conf = cfg.ConfigOpts()
        # To load the drivers without using the config file
        self.useFixture(ConfFixture(self.conf))

        def _fake_parse(self, args=[]):
            return cfg.ConfigOpts._parse_cli_opts(self, [])

        _fake_parse_method = types.MethodType(_fake_parse, self.conf)
        self.conf._parse_cli_opts = _fake_parse_method

        # First dependency to be returned
        self.dummy_driver_manager = DriverManager.make_test_instance(
            extension=Extension(
                name=DummyMetricPuller.get_name(),
                entry_point='fake.entry.point',
                plugin=DummyMetricPuller,
                obj=None,
            ),
            namespace='TESTING',
        )
        # 2nd dependency to be returned
        self.fake_driver_manager = DriverManager.make_test_instance(
            extension=Extension(
                name=FakeMetricPuller.get_name(),
                entry_point='fake.entry.point',
                plugin=FakeMetricPuller,
                obj=None,
            ),
            namespace='TESTING',
        )
        self.defaults_drivers = {
            DummyMetricPuller.get_name(): self.dummy_driver_manager,
            FakeMetricPuller.get_name(): self.fake_driver_manager,
        }

        def _fake_loader(name, **kw):
            return self.defaults_drivers[name]

        # Patches the agent socket
        self.m_agent_socket = MagicMock(autospec=True)

        self.patches.extend([
            # Deactivates the nanomsg socket
            patch(
                "watcher_metering.agent.agent.nanomsg.Socket",
                new=self.m_agent_socket,
            ),
            # Sets the test namespace to 'TESTING'
            patch.object(
                Agent,
                "namespace",
                PropertyMock(return_value='TESTING'),
            ),
            # Patches the driver manager to retourn our test drivers
            # instead of the real ones
            patch(
                "watcher_metering.load.loader.DriverManager",
                MagicMock(side_effect=_fake_loader),
            ),
        ])

        # Applies all of our patches before each test
        for _patch in self.patches:
            _patch.start()

        self.agent = Agent(
            conf=self.conf,
            driver_names=self.conf.agent.driver_names,
            use_nanoconfig_service=False,
            publisher_endpoint="fake",
            nanoconfig_service_endpoint="",
            nanoconfig_update_endpoint="",
            nanoconfig_profile="nanoconfig://test_profile"
        )
        # Default ticking is set to 0 to reduce test execution time
        self.agent.TICK_INTERVAL = 0

    def tearDown(self):
        super(TestAgent, self).tearDown()
        # The drivers are stored at the class level so we need to clear
        # it after each test
        self.agent.drivers.clear()
        for _patch in self.patches:
            _patch.stop()

    def test_register_driver(self):
        expected_driver1_key = "metrics_driver.dummy_data.puller.dummy"
        expected_driver2_key = "metrics_driver.fake_data.puller.fake"

        self.agent.register_drivers()

        self.assertEqual(
            sorted(self.agent.drivers.keys()),
            [expected_driver1_key, expected_driver2_key]
        )
        sorted_drivers = OrderedDict(
            sorted(self.agent.drivers.items(), key=operator.itemgetter(0))
        )
        self.assertEqual(len(sorted_drivers), 2)
        driver1 = self.agent.drivers[expected_driver1_key]
        driver2 = self.agent.drivers[expected_driver2_key]

        self.assertEqual(driver1.title, "metrics_driver.dummy")
        self.assertEqual(driver1.probe_id, "data.puller.dummy")
        self.assertEqual(driver1.interval, 0.01)

        self.assertEqual(driver2.title, "metrics_driver.fake")
        self.assertEqual(driver2.probe_id, "data.puller.fake")
        self.assertEqual(driver2.interval, 0.01)

        self.assertIn(self.agent, driver1._observers)
        self.assertIn(self.agent, driver2._observers)

    def test_unregister_driver(self):
        driver_key = "metrics_driver.dummy_data.puller.dummy"
        self.agent.register_drivers()
        self.agent.unregister_driver(driver_key)

        # Initial is 2 drivers => 2 - 1 == 1
        self.assertEqual(len(self.agent.drivers), 1)

    @patch.object(Measurement, "as_dict")
    def test_send_measurements(self, m_as_dict):
        self.agent.register_drivers()

        measurement_dict = OrderedDict(
            name="dummy.data.puller",
            unit="",
            type_="",
            value=13.37,
            resource_id="test_hostname",
            host="test_hostname",
            timestamp="2015-08-04T15:15:45.703542",
        )
        m_as_dict.return_value = measurement_dict

        measurement = Measurement(**measurement_dict)

        for driver in self.agent.drivers.values():
            driver.send_measurements([measurement])
            break  # only the first one
        expected_encoded_msg = msgpack.dumps(measurement_dict)
        self.m_agent_socket.return_value.send.assert_called_once_with(
            expected_encoded_msg
        )

    @patch.object(DummyMetricPuller, "is_alive")
    @patch.object(DummyMetricPuller, "start")
    @patch("watcher_metering.agent.manager.MetricManager.lock")
    def test_check_drivers_alive(self, m_lock, m_start, m_is_alive):
        m_lock.acquire = Mock(return_value=True)  # Emulates a thread behavior
        m_lock.release = Mock(return_value=True)  # Emulates a thread behavior
        m_is_alive.return_value = True  # Emulates a thread that is running
        m_start.return_value = None

        self.agent.register_drivers()
        self.agent.check_drivers_alive()

        self.assertTrue(m_is_alive.called)
        self.assertFalse(m_start.called)

    @patch.object(DummyMetricPuller, "is_alive")
    @patch.object(DummyMetricPuller, "start")
    @patch("watcher_metering.agent.manager.MetricManager.lock")
    def test_check_drivers_alive_with_driver_stopped(self, m_lock, m_start,
                                                     m_is_alive):
        m_lock.acquire = Mock(return_value=True)  # Emulates a thread behavior
        m_lock.release = Mock(return_value=True)  # Emulates a thread behavior
        m_is_alive.side_effect = [False, True]
        m_start.side_effect = [RuntimeError, True, True]  # Fails once

        self.agent.register_drivers()
        # should re-run the driver
        self.agent.check_drivers_alive()

        self.assertEqual(m_is_alive.call_count, 1)
        self.assertEqual(m_start.call_count, 2)

    @patch.object(os._Environ, "__setitem__")
    @patch("watcher_metering.agent.agent.os.environ.get")
    def test_setup_nanoconfig_valid_using_default(self, m_env_getter,
                                                  m_env_setter):
        # Override default where it is set to False
        m_env_getter.side_effect = ["FAKE_NN_CONFIG_SERVICE",
                                    "FAKE_NN_CONFIG_UPDATES"]
        self.agent.use_nanoconfig_service = True
        self.agent.nanoconfig_service_endpoint = ""
        self.agent.nanoconfig_update_endpoint = ""
        self.agent.set_nanoconfig_endpoints()

        self.assertEqual(m_env_getter.call_count, 2)
        m_env_getter.assert_any_call("NN_CONFIG_SERVICE")  # First call
        m_env_getter.assert_called_with("NN_CONFIG_UPDATES")  # Last call
        self.assertEqual(m_env_setter.call_count, 0)
        self.assertEqual(self.agent.nanoconfig_service_endpoint,
                         "FAKE_NN_CONFIG_SERVICE")
        self.assertEqual(self.agent.nanoconfig_update_endpoint,
                         "FAKE_NN_CONFIG_UPDATES")

    @patch.object(os._Environ, "__setitem__")
    @patch("watcher_metering.agent.agent.os.environ.get")
    def test_setup_nanoconfig_valid_custom_values(self, m_env_getter,
                                                  m_env_setter):
        # Override default where it is set to False
        m_env_getter.side_effect = ["FAKE_NN_CONFIG_SERVICE",
                                    "FAKE_NN_CONFIG_UPDATES"]
        self.agent.use_nanoconfig_service = True
        self.agent.nanoconfig_service_endpoint = "CUSTOM_NN_CONFIG_SERVICE"
        self.agent.nanoconfig_update_endpoint = "CUSTOM_NN_CONFIG_UPDATES"
        self.agent.set_nanoconfig_endpoints()

        self.assertEqual(m_env_getter.call_count, 2)
        m_env_getter.assert_any_call("NN_CONFIG_SERVICE")
        m_env_getter.assert_called_with("NN_CONFIG_UPDATES")
        m_env_setter.assert_any_call("NN_CONFIG_SERVICE",
                                     "CUSTOM_NN_CONFIG_SERVICE")
        m_env_setter.assert_called_with("NN_CONFIG_UPDATES",
                                        "CUSTOM_NN_CONFIG_UPDATES")
        self.assertEqual(self.agent.nanoconfig_service_endpoint,
                         "CUSTOM_NN_CONFIG_SERVICE")
        self.assertEqual(self.agent.nanoconfig_update_endpoint,
                         "CUSTOM_NN_CONFIG_UPDATES")

    @patch.object(os._Environ, "__setitem__")
    @patch("watcher_metering.agent.agent.os.environ.get")
    def test_setup_nanoconfig_invalid_service(self, m_env_getter,
                                              m_env_setter):
        # Override default where it is set to False
        m_env_getter.return_value = ""  # Emulates empty ENV vars
        self.agent.use_nanoconfig_service = True
        self.agent.nanoconfig_service_endpoint = ""
        self.agent.nanoconfig_update_endpoint = "CUSTOM_NN_CONFIG_UPDATES"

        self.assertRaises(ValueError, self.agent.set_nanoconfig_endpoints)

        m_env_getter.assert_called_once_with("NN_CONFIG_SERVICE")
        self.assertEqual(m_env_setter.call_count, 0)

    @patch.object(os._Environ, "__setitem__")
    @patch("watcher_metering.agent.agent.os.environ.get")
    def test_setup_nanoconfig_invalid_update(self, m_env_getter, m_env_setter):
        # Override default where it is set to False
        m_env_getter.return_value = ""  # Emulates empty ENV vars
        self.agent.use_nanoconfig_service = True
        self.agent.nanoconfig_service_endpoint = "CUSTOM_NN_CONFIG_SERVICE"
        self.agent.nanoconfig_update_endpoint = ""

        self.assertRaises(ValueError, self.agent.set_nanoconfig_endpoints)

        m_env_getter.assert_any_call("NN_CONFIG_SERVICE")
        m_env_getter.assert_called_with("NN_CONFIG_UPDATES")
        m_env_setter.assert_called_once_with("NN_CONFIG_SERVICE",
                                             "CUSTOM_NN_CONFIG_SERVICE")

    @patch.object(Agent, 'check_drivers_alive', MagicMock())
    @patch("watcher_metering.agent.manager."
           "MetricManager.terminated",
           new_callable=PropertyMock)
    def test_run_agent(self, m_terminated):
        # Patches the guard/exit condition of the thread periodic event loop
        # -> 1st time = False (carry on) and 2nd = True (Should terminate)
        m_terminated.side_effect = [False, True]

        self.agent.run()

        self.assertEqual(m_terminated.call_count, 2)

    @patch.object(DummyMetricPuller, 'send_measurements', MagicMock())
    def test_stop_agent(self):
        self.agent.register_drivers()

        self.agent.start()
        self.agent.join(timeout=.01)
        self.agent.stop()

        self.assertEqual(len(self.agent.drivers.values()), 2)
        self.assertTrue(
            all([driver.terminated for driver in self.agent.drivers.values()])
        )
        self.assertTrue(self.agent.terminated)
        self.assertFalse(self.agent.is_alive())
Example #5
0
    def setUp(self):
        super(TestAgent, self).setUp()
        self.conf = cfg.ConfigOpts()
        # To load the drivers without using the config file
        self.useFixture(ConfFixture(self.conf))

        def _fake_parse(self, args=[]):
            return cfg.ConfigOpts._parse_cli_opts(self, [])

        _fake_parse_method = types.MethodType(_fake_parse, self.conf)
        self.conf._parse_cli_opts = _fake_parse_method

        # First dependency to be returned
        self.dummy_driver_manager = DriverManager.make_test_instance(
            extension=Extension(
                name=DummyMetricPuller.get_name(),
                entry_point='fake.entry.point',
                plugin=DummyMetricPuller,
                obj=None,
            ),
            namespace='TESTING',
        )
        # 2nd dependency to be returned
        self.fake_driver_manager = DriverManager.make_test_instance(
            extension=Extension(
                name=FakeMetricPuller.get_name(),
                entry_point='fake.entry.point',
                plugin=FakeMetricPuller,
                obj=None,
            ),
            namespace='TESTING',
        )
        self.defaults_drivers = {
            DummyMetricPuller.get_name(): self.dummy_driver_manager,
            FakeMetricPuller.get_name(): self.fake_driver_manager,
        }

        def _fake_loader(name, **kw):
            return self.defaults_drivers[name]

        # Patches the agent socket
        self.m_agent_socket = MagicMock(autospec=True)

        self.patches.extend([
            # Deactivates the nanomsg socket
            patch(
                "watcher_metering.agent.agent.nanomsg.Socket",
                new=self.m_agent_socket,
            ),
            # Sets the test namespace to 'TESTING'
            patch.object(
                Agent,
                "namespace",
                PropertyMock(return_value='TESTING'),
            ),
            # Patches the driver manager to retourn our test drivers
            # instead of the real ones
            patch(
                "watcher_metering.load.loader.DriverManager",
                MagicMock(side_effect=_fake_loader),
            ),
        ])

        # Applies all of our patches before each test
        for _patch in self.patches:
            _patch.start()

        self.agent = Agent(conf=self.conf,
                           driver_names=self.conf.agent.driver_names,
                           use_nanoconfig_service=False,
                           publisher_endpoint="fake",
                           nanoconfig_service_endpoint="",
                           nanoconfig_update_endpoint="",
                           nanoconfig_profile="nanoconfig://test_profile")
        # Default ticking is set to 0 to reduce test execution time
        self.agent.TICK_INTERVAL = 0
Example #6
0
class TestAgent(BaseTestCase):

    # patches to be applied for each test in this test suite
    patches = []

    def setUp(self):
        super(TestAgent, self).setUp()
        self.conf = cfg.ConfigOpts()
        # To load the drivers without using the config file
        self.useFixture(ConfFixture(self.conf))

        def _fake_parse(self, args=[]):
            return cfg.ConfigOpts._parse_cli_opts(self, [])

        _fake_parse_method = types.MethodType(_fake_parse, self.conf)
        self.conf._parse_cli_opts = _fake_parse_method

        # First dependency to be returned
        self.dummy_driver_manager = DriverManager.make_test_instance(
            extension=Extension(
                name=DummyMetricPuller.get_name(),
                entry_point='fake.entry.point',
                plugin=DummyMetricPuller,
                obj=None,
            ),
            namespace='TESTING',
        )
        # 2nd dependency to be returned
        self.fake_driver_manager = DriverManager.make_test_instance(
            extension=Extension(
                name=FakeMetricPuller.get_name(),
                entry_point='fake.entry.point',
                plugin=FakeMetricPuller,
                obj=None,
            ),
            namespace='TESTING',
        )
        self.defaults_drivers = {
            DummyMetricPuller.get_name(): self.dummy_driver_manager,
            FakeMetricPuller.get_name(): self.fake_driver_manager,
        }

        def _fake_loader(name, **kw):
            return self.defaults_drivers[name]

        # Patches the agent socket
        self.m_agent_socket = MagicMock(autospec=True)

        self.patches.extend([
            # Deactivates the nanomsg socket
            patch(
                "watcher_metering.agent.agent.nanomsg.Socket",
                new=self.m_agent_socket,
            ),
            # Sets the test namespace to 'TESTING'
            patch.object(
                Agent,
                "namespace",
                PropertyMock(return_value='TESTING'),
            ),
            # Patches the driver manager to retourn our test drivers
            # instead of the real ones
            patch(
                "watcher_metering.load.loader.DriverManager",
                MagicMock(side_effect=_fake_loader),
            ),
        ])

        # Applies all of our patches before each test
        for _patch in self.patches:
            _patch.start()

        self.agent = Agent(conf=self.conf,
                           driver_names=self.conf.agent.driver_names,
                           use_nanoconfig_service=False,
                           publisher_endpoint="fake",
                           nanoconfig_service_endpoint="",
                           nanoconfig_update_endpoint="",
                           nanoconfig_profile="nanoconfig://test_profile")
        # Default ticking is set to 0 to reduce test execution time
        self.agent.TICK_INTERVAL = 0

    def tearDown(self):
        super(TestAgent, self).tearDown()
        # The drivers are stored at the class level so we need to clear
        # it after each test
        self.agent.drivers.clear()
        for _patch in self.patches:
            _patch.stop()

    def test_register_driver(self):
        expected_driver1_key = "metrics_driver.dummy_data.puller.dummy"
        expected_driver2_key = "metrics_driver.fake_data.puller.fake"

        self.agent.register_drivers()

        self.assertEqual(sorted(self.agent.drivers.keys()),
                         [expected_driver1_key, expected_driver2_key])
        sorted_drivers = OrderedDict(
            sorted(self.agent.drivers.items(), key=operator.itemgetter(0)))
        self.assertEqual(len(sorted_drivers), 2)
        driver1 = self.agent.drivers[expected_driver1_key]
        driver2 = self.agent.drivers[expected_driver2_key]

        self.assertEqual(driver1.title, "metrics_driver.dummy")
        self.assertEqual(driver1.probe_id, "data.puller.dummy")
        self.assertEqual(driver1.interval, 0.01)

        self.assertEqual(driver2.title, "metrics_driver.fake")
        self.assertEqual(driver2.probe_id, "data.puller.fake")
        self.assertEqual(driver2.interval, 0.01)

        self.assertIn(self.agent, driver1._observers)
        self.assertIn(self.agent, driver2._observers)

    def test_unregister_driver(self):
        driver_key = "metrics_driver.dummy_data.puller.dummy"
        self.agent.register_drivers()
        self.agent.unregister_driver(driver_key)

        # Initial is 2 drivers => 2 - 1 == 1
        self.assertEqual(len(self.agent.drivers), 1)

    @patch.object(Measurement, "as_dict")
    def test_send_measurements(self, m_as_dict):
        self.agent.register_drivers()

        measurement_dict = OrderedDict(
            name="dummy.data.puller",
            unit="",
            type_="",
            value=13.37,
            resource_id="test_hostname",
            host="test_hostname",
            timestamp="2015-08-04T15:15:45.703542",
        )
        m_as_dict.return_value = measurement_dict

        measurement = Measurement(**measurement_dict)

        for driver in self.agent.drivers.values():
            driver.send_measurements([measurement])
            break  # only the first one
        expected_encoded_msg = msgpack.dumps(measurement_dict)
        self.m_agent_socket.return_value.send.assert_called_once_with(
            expected_encoded_msg)

    @patch.object(DummyMetricPuller, "is_alive")
    @patch.object(DummyMetricPuller, "start")
    @patch("watcher_metering.agent.manager.MetricManager.lock")
    def test_check_drivers_alive(self, m_lock, m_start, m_is_alive):
        m_lock.acquire = Mock(return_value=True)  # Emulates a thread behavior
        m_lock.release = Mock(return_value=True)  # Emulates a thread behavior
        m_is_alive.return_value = True  # Emulates a thread that is running
        m_start.return_value = None

        self.agent.register_drivers()
        self.agent.check_drivers_alive()

        self.assertTrue(m_is_alive.called)
        self.assertFalse(m_start.called)

    @patch.object(DummyMetricPuller, "is_alive")
    @patch.object(DummyMetricPuller, "start")
    @patch("watcher_metering.agent.manager.MetricManager.lock")
    def test_check_drivers_alive_with_driver_stopped(self, m_lock, m_start,
                                                     m_is_alive):
        m_lock.acquire = Mock(return_value=True)  # Emulates a thread behavior
        m_lock.release = Mock(return_value=True)  # Emulates a thread behavior
        m_is_alive.side_effect = [False, True]
        m_start.side_effect = [RuntimeError, True, True]  # Fails once

        self.agent.register_drivers()
        # should re-run the driver
        self.agent.check_drivers_alive()

        self.assertEqual(m_is_alive.call_count, 1)
        self.assertEqual(m_start.call_count, 2)

    @patch.object(os._Environ, "__setitem__")
    @patch("watcher_metering.agent.agent.os.environ.get")
    def test_setup_nanoconfig_valid_using_default(self, m_env_getter,
                                                  m_env_setter):
        # Override default where it is set to False
        m_env_getter.side_effect = [
            "FAKE_NN_CONFIG_SERVICE", "FAKE_NN_CONFIG_UPDATES"
        ]
        self.agent.use_nanoconfig_service = True
        self.agent.nanoconfig_service_endpoint = ""
        self.agent.nanoconfig_update_endpoint = ""
        self.agent.set_nanoconfig_endpoints()

        self.assertEqual(m_env_getter.call_count, 2)
        m_env_getter.assert_any_call("NN_CONFIG_SERVICE")  # First call
        m_env_getter.assert_called_with("NN_CONFIG_UPDATES")  # Last call
        self.assertEqual(m_env_setter.call_count, 0)
        self.assertEqual(self.agent.nanoconfig_service_endpoint,
                         "FAKE_NN_CONFIG_SERVICE")
        self.assertEqual(self.agent.nanoconfig_update_endpoint,
                         "FAKE_NN_CONFIG_UPDATES")

    @patch.object(os._Environ, "__setitem__")
    @patch("watcher_metering.agent.agent.os.environ.get")
    def test_setup_nanoconfig_valid_custom_values(self, m_env_getter,
                                                  m_env_setter):
        # Override default where it is set to False
        m_env_getter.side_effect = [
            "FAKE_NN_CONFIG_SERVICE", "FAKE_NN_CONFIG_UPDATES"
        ]
        self.agent.use_nanoconfig_service = True
        self.agent.nanoconfig_service_endpoint = "CUSTOM_NN_CONFIG_SERVICE"
        self.agent.nanoconfig_update_endpoint = "CUSTOM_NN_CONFIG_UPDATES"
        self.agent.set_nanoconfig_endpoints()

        self.assertEqual(m_env_getter.call_count, 2)
        m_env_getter.assert_any_call("NN_CONFIG_SERVICE")
        m_env_getter.assert_called_with("NN_CONFIG_UPDATES")
        m_env_setter.assert_any_call("NN_CONFIG_SERVICE",
                                     "CUSTOM_NN_CONFIG_SERVICE")
        m_env_setter.assert_called_with("NN_CONFIG_UPDATES",
                                        "CUSTOM_NN_CONFIG_UPDATES")
        self.assertEqual(self.agent.nanoconfig_service_endpoint,
                         "CUSTOM_NN_CONFIG_SERVICE")
        self.assertEqual(self.agent.nanoconfig_update_endpoint,
                         "CUSTOM_NN_CONFIG_UPDATES")

    @patch.object(os._Environ, "__setitem__")
    @patch("watcher_metering.agent.agent.os.environ.get")
    def test_setup_nanoconfig_invalid_service(self, m_env_getter,
                                              m_env_setter):
        # Override default where it is set to False
        m_env_getter.return_value = ""  # Emulates empty ENV vars
        self.agent.use_nanoconfig_service = True
        self.agent.nanoconfig_service_endpoint = ""
        self.agent.nanoconfig_update_endpoint = "CUSTOM_NN_CONFIG_UPDATES"

        self.assertRaises(ValueError, self.agent.set_nanoconfig_endpoints)

        m_env_getter.assert_called_once_with("NN_CONFIG_SERVICE")
        self.assertEqual(m_env_setter.call_count, 0)

    @patch.object(os._Environ, "__setitem__")
    @patch("watcher_metering.agent.agent.os.environ.get")
    def test_setup_nanoconfig_invalid_update(self, m_env_getter, m_env_setter):
        # Override default where it is set to False
        m_env_getter.return_value = ""  # Emulates empty ENV vars
        self.agent.use_nanoconfig_service = True
        self.agent.nanoconfig_service_endpoint = "CUSTOM_NN_CONFIG_SERVICE"
        self.agent.nanoconfig_update_endpoint = ""

        self.assertRaises(ValueError, self.agent.set_nanoconfig_endpoints)

        m_env_getter.assert_any_call("NN_CONFIG_SERVICE")
        m_env_getter.assert_called_with("NN_CONFIG_UPDATES")
        m_env_setter.assert_called_once_with("NN_CONFIG_SERVICE",
                                             "CUSTOM_NN_CONFIG_SERVICE")

    @patch.object(Agent, 'check_drivers_alive', MagicMock())
    @patch("watcher_metering.agent.manager."
           "MetricManager.terminated",
           new_callable=PropertyMock)
    def test_run_agent(self, m_terminated):
        # Patches the guard/exit condition of the thread periodic event loop
        # -> 1st time = False (carry on) and 2nd = True (Should terminate)
        m_terminated.side_effect = [False, True]

        self.agent.run()

        self.assertEqual(m_terminated.call_count, 2)

    @patch.object(DummyMetricPuller, 'send_measurements', MagicMock())
    def test_stop_agent(self):
        self.agent.register_drivers()

        self.agent.start()
        self.agent.join(timeout=.01)
        self.agent.stop()

        self.assertEqual(len(self.agent.drivers.values()), 2)
        self.assertTrue(
            all([driver.terminated for driver in self.agent.drivers.values()]))
        self.assertTrue(self.agent.terminated)
        self.assertFalse(self.agent.is_alive())