From 4fb0b5a09b26135ade285844da5d7dfe582a8d4c Mon Sep 17 00:00:00 2001 From: Ɓukasz 'sil2100' Zemczak Date: Thu, 18 May 2017 19:58:02 +0200 Subject: Import patches-unapplied version 2.2.12-0ubuntu1 to ubuntu/artful-proposed Imported using git-ubuntu import. Changelog parent: 473ad6fbfe0b9c3b362b530492928303f2b4c7f3 New changelog entries: * New upstream release (LP: #1690854). - Refreshed debian/patches/disable_import_test.patch. --- tests/ga/test_extension.py | 105 ++++++++++++++++++++ tests/ga/test_update.py | 233 ++++++++++++++++++++++++++++++++++++++------- 2 files changed, 306 insertions(+), 32 deletions(-) (limited to 'tests/ga') diff --git a/tests/ga/test_extension.py b/tests/ga/test_extension.py index 1df0a04..2a60ea3 100644 --- a/tests/ga/test_extension.py +++ b/tests/ga/test_extension.py @@ -15,6 +15,14 @@ # Requires Python 2.4+ and Openssl 1.0+ # +import glob +import os +import os.path +import shutil +import tempfile +import zipfile + +import azurelinuxagent.common.conf as conf import azurelinuxagent.common.utils.fileutil as fileutil from tests.protocol.mockwiredata import * @@ -30,6 +38,103 @@ from azurelinuxagent.common.protocol.restapi import ExtHandlerStatus, \ from azurelinuxagent.ga.exthandlers import * from azurelinuxagent.common.protocol.wire import WireProtocol +class TestExtensionCleanup(AgentTestCase): + def setUp(self): + AgentTestCase.setUp(self) + self.ext_handlers = ExtHandlersHandler() + self.lib_dir = tempfile.mkdtemp() + + def _install_handlers(self, start=0, count=1, + handler_state=ExtHandlerState.Installed): + src = os.path.join(data_dir, "ext", "sample_ext-1.2.0.zip") + version = FlexibleVersion("1.2.0") + version += start - version.patch + + for i in range(start, start+count): + eh = ExtHandler() + eh.name = "sample_ext" + eh.properties.version = str(version) + handler = ExtHandlerInstance(eh, "unused") + + dst = os.path.join(self.lib_dir, + handler.get_full_name()+HANDLER_PKG_EXT) + shutil.copy(src, dst) + + if not handler_state is None: + zipfile.ZipFile(dst).extractall(handler.get_base_dir()) + handler.set_handler_state(handler_state) + + version += 1 + + def _count_packages(self): + return len(glob.glob(os.path.join(self.lib_dir, "*.zip"))) + + def _count_installed(self): + paths = os.listdir(self.lib_dir) + paths = [os.path.join(self.lib_dir, p) for p in paths] + return len([p for p in paths + if os.path.isdir(p) and self._is_installed(p)]) + + def _count_uninstalled(self): + paths = os.listdir(self.lib_dir) + paths = [os.path.join(self.lib_dir, p) for p in paths] + return len([p for p in paths + if os.path.isdir(p) and not self._is_installed(p)]) + + def _is_installed(self, path): + path = os.path.join(path, 'config', 'HandlerState') + return fileutil.read_file(path) != "NotInstalled" + + @patch("azurelinuxagent.common.conf.get_lib_dir") + def test_cleanup_leaves_installed_extensions(self, mock_conf): + mock_conf.return_value = self.lib_dir + + self._install_handlers(start=0, count=5, handler_state=ExtHandlerState.Installed) + self._install_handlers(start=5, count=5, handler_state=ExtHandlerState.Enabled) + + self.assertEqual(self._count_packages(), 10) + self.assertEqual(self._count_installed(), 10) + + self.ext_handlers.cleanup_outdated_handlers() + + self.assertEqual(self._count_packages(), 10) + self.assertEqual(self._count_installed(), 10) + self.assertEqual(self._count_uninstalled(), 0) + + @patch("azurelinuxagent.common.conf.get_lib_dir") + def test_cleanup_removes_uninstalled_extensions(self, mock_conf): + mock_conf.return_value = self.lib_dir + + self._install_handlers(start=0, count=5, handler_state=ExtHandlerState.Installed) + self._install_handlers(start=5, count=5, handler_state=ExtHandlerState.NotInstalled) + + self.assertEqual(self._count_packages(), 10) + self.assertEqual(self._count_installed(), 5) + self.assertEqual(self._count_uninstalled(), 5) + + self.ext_handlers.cleanup_outdated_handlers() + + self.assertEqual(self._count_packages(), 5) + self.assertEqual(self._count_installed(), 5) + self.assertEqual(self._count_uninstalled(), 0) + + @patch("azurelinuxagent.common.conf.get_lib_dir") + def test_cleanup_removes_orphaned_packages(self, mock_conf): + mock_conf.return_value = self.lib_dir + + self._install_handlers(start=0, count=5, handler_state=ExtHandlerState.Installed) + self._install_handlers(start=5, count=5, handler_state=None) + + self.assertEqual(self._count_packages(), 10) + self.assertEqual(self._count_installed(), 5) + self.assertEqual(self._count_uninstalled(), 0) + + self.ext_handlers.cleanup_outdated_handlers() + + self.assertEqual(self._count_packages(), 5) + self.assertEqual(self._count_installed(), 5) + self.assertEqual(self._count_uninstalled(), 0) + class TestHandlerStateMigration(AgentTestCase): def setUp(self): AgentTestCase.setUp(self) diff --git a/tests/ga/test_update.py b/tests/ga/test_update.py index e7a7af4..a83db95 100644 --- a/tests/ga/test_update.py +++ b/tests/ga/test_update.py @@ -17,9 +17,16 @@ from __future__ import print_function +from datetime import datetime + +import json +import shutil + from azurelinuxagent.common.protocol.hostplugin import * from azurelinuxagent.common.protocol.wire import * +from azurelinuxagent.common.utils.fileutil import * from azurelinuxagent.ga.update import * + from tests.tools import * NO_ERROR = { @@ -28,6 +35,18 @@ NO_ERROR = { "was_fatal" : False } +FATAL_ERROR = { + "last_failure" : 42.42, + "failure_count" : 2, + "was_fatal" : True +} + +SENTINEL_ERROR = { + "last_failure" : 0.0, + "failure_count" : 0, + "was_fatal" : True +} + WITH_ERROR = { "last_failure" : 42.42, "failure_count" : 2, @@ -137,19 +156,25 @@ class UpdateTestCase(AgentTestCase): fileutil.copy_file(agent, to_dir=self.tmp_dir) return - def expand_agents(self): + def expand_agents(self, mark_test=False): for agent in self.agent_pkgs(): - zipfile.ZipFile(agent).extractall(os.path.join( - self.tmp_dir, - fileutil.trim_ext(agent, "zip"))) + path = os.path.join(self.tmp_dir, fileutil.trim_ext(agent, "zip")) + zipfile.ZipFile(agent).extractall(path) + if mark_test: + src = os.path.join(data_dir, 'ga', 'supported.json') + dst = os.path.join(path, 'supported.json') + shutil.copy(src, dst) + + dst = os.path.join(path, 'error.json') + fileutil.write_file(dst, json.dumps(SENTINEL_ERROR)) return - def prepare_agent(self, version): + def prepare_agent(self, version, mark_test=False): """ Create a download for the current agent version, copied from test data """ self.copy_agents(get_agent_pkgs()[0]) - self.expand_agents() + self.expand_agents(mark_test=mark_test) versions = self.agent_versions() src_v = FlexibleVersion(str(versions[0])) @@ -214,6 +239,64 @@ class UpdateTestCase(AgentTestCase): return dst_v +class TestSupportedDistribution(UpdateTestCase): + def setUp(self): + UpdateTestCase.setUp(self) + self.sd = SupportedDistribution({ + 'slice':10, + 'versions': ['^Ubuntu,16.10,yakkety$']}) + + + def test_creation(self): + self.assertRaises(TypeError, SupportedDistribution) + self.assertRaises(UpdateError, SupportedDistribution, None) + + self.assertEqual(self.sd.slice, 10) + self.assertEqual(self.sd.versions, ['^Ubuntu,16.10,yakkety$']) + + @patch('platform.linux_distribution') + def test_is_supported(self, mock_dist): + mock_dist.return_value = ['Ubuntu', '16.10', 'yakkety'] + self.assertTrue(self.sd.is_supported) + + mock_dist.return_value = ['something', 'else', 'entirely'] + self.assertFalse(self.sd.is_supported) + + @patch('azurelinuxagent.ga.update.datetime') + def test_in_slice(self, mock_dt): + mock_dt.utcnow = Mock(return_value=datetime(2017, 1, 1, 0, 0, 5)) + self.assertTrue(self.sd.in_slice) + + mock_dt.utcnow = Mock(return_value=datetime(2017, 1, 1, 0, 0, 42)) + self.assertFalse(self.sd.in_slice) + + +class TestSupported(UpdateTestCase): + def setUp(self): + UpdateTestCase.setUp(self) + self.sp = Supported(os.path.join(data_dir, 'ga', 'supported.json')) + + def test_creation(self): + self.assertRaises(TypeError, Supported) + self.assertRaises(UpdateError, Supported, None) + + @patch('platform.linux_distribution') + def test_is_supported(self, mock_dist): + mock_dist.return_value = ['Ubuntu', '16.10', 'yakkety'] + self.assertTrue(self.sp.is_supported) + + mock_dist.return_value = ['something', 'else', 'entirely'] + self.assertFalse(self.sp.is_supported) + + @patch('platform.linux_distribution', return_value=['Ubuntu', '16.10', 'yakkety']) + @patch('azurelinuxagent.ga.update.datetime') + def test_in_slice(self, mock_dt, mock_dist): + mock_dt.utcnow = Mock(return_value=datetime(2017, 1, 1, 0, 0, 5)) + self.assertTrue(self.sp.in_slice) + + mock_dt.utcnow = Mock(return_value=datetime(2017, 1, 1, 0, 0, 42)) + self.assertFalse(self.sp.in_slice) + class TestGuestAgentError(UpdateTestCase): def test_creation(self): self.assertRaises(TypeError, GuestAgentError) @@ -241,6 +324,17 @@ class TestGuestAgentError(UpdateTestCase): self.assertEqual(NO_ERROR["was_fatal"], err.was_fatal) return + def test_is_sentinel(self): + with self.get_error_file(error_data=SENTINEL_ERROR) as path: + err = GuestAgentError(path.name) + self.assertTrue(err.is_blacklisted) + self.assertTrue(err.is_sentinel) + + with self.get_error_file(error_data=FATAL_ERROR) as path: + err = GuestAgentError(path.name) + self.assertTrue(err.is_blacklisted) + self.assertFalse(err.is_sentinel) + def test_load_preserves_error_state(self): with self.get_error_file(error_data=WITH_ERROR) as path: err = GuestAgentError(path.name) @@ -274,15 +368,6 @@ class TestGuestAgentError(UpdateTestCase): # Agent failed >= MAX_FAILURE, it should be blacklisted self.assertTrue(err.is_blacklisted) self.assertEqual(MAX_FAILURE, err.failure_count) - - # Clear old failure does not clear recent failure - err.clear_old_failure() - self.assertTrue(err.is_blacklisted) - - # Clear does remove old, outdated failures - err.last_failure -= RETAIN_INTERVAL * 2 - err.clear_old_failure() - self.assertFalse(err.is_blacklisted) return def test_mark_failure_permanent(self): @@ -334,6 +419,9 @@ class TestGuestAgent(UpdateTestCase): self.assertEqual(get_agent_name(), agent.name) self.assertEqual(get_agent_version(), agent.version) + self.assertFalse(agent.is_test) + self.assertFalse(agent.in_slice) + self.assertEqual(self.agent_path, agent.get_agent_dir()) path = os.path.join(self.agent_path, AGENT_MANIFEST_FILE) @@ -403,6 +491,48 @@ class TestGuestAgent(UpdateTestCase): self.assertTrue(agent.is_downloaded) return + @patch('platform.linux_distribution', return_value=['Ubuntu', '16.10', 'yakkety']) + def test_is_test(self, mock_dist): + self.expand_agents(mark_test=True) + agent = GuestAgent(path=self.agent_path) + + self.assertTrue(agent.is_blacklisted) + self.assertTrue(agent.is_test) + + @patch('platform.linux_distribution', return_value=['Ubuntu', '16.10', 'yakkety']) + @patch('azurelinuxagent.ga.update.datetime') + def test_in_slice(self, mock_dt, mock_dist): + self.expand_agents(mark_test=True) + agent = GuestAgent(path=self.agent_path) + + mock_dt.utcnow = Mock(return_value=datetime(2017, 1, 1, 0, 0, 5)) + self.assertTrue(agent.in_slice) + + mock_dt.utcnow = Mock(return_value=datetime(2017, 1, 1, 0, 0, 42)) + self.assertFalse(agent.in_slice) + + @patch('platform.linux_distribution', return_value=['Ubuntu', '16.10', 'yakkety']) + @patch('azurelinuxagent.ga.update.datetime') + def test_enable(self, mock_dt, mock_dist): + mock_dt.utcnow = Mock(return_value=datetime(2017, 1, 1, 0, 0, 5)) + + self.expand_agents(mark_test=True) + agent = GuestAgent(path=self.agent_path) + + self.assertTrue(agent.is_blacklisted) + self.assertTrue(agent.is_test) + self.assertTrue(agent.in_slice) + + agent.enable() + + self.assertFalse(agent.is_blacklisted) + self.assertFalse(agent.is_test) + + # Ensure the new state is preserved to disk + agent = GuestAgent(path=self.agent_path) + self.assertFalse(agent.is_blacklisted) + self.assertFalse(agent.is_test) + @patch("azurelinuxagent.ga.update.GuestAgent._ensure_downloaded") def test_mark_failure(self, mock_ensure): agent = GuestAgent(path=self.agent_path) @@ -933,6 +1063,14 @@ class TestUpdate(UpdateTestCase): self.assertEqual("1250_waagent.pid", os.path.basename(pid_file)) return + @patch('platform.linux_distribution', return_value=['Ubuntu', '16.10', 'yakkety']) + @patch('azurelinuxagent.ga.update.datetime') + def test_get_test_agent(self, mock_dt, mock_dist): + mock_dt.utcnow = Mock(return_value=datetime(2017, 1, 1, 0, 0, 5)) + self.prepare_agent(AGENT_VERSION, mark_test=True) + + self.assertNotEqual(None, self.update_handler.get_test_agent()) + def test_is_clean_start_returns_true_when_no_sentinal(self): self.assertFalse(os.path.isfile(self.update_handler._sentinal_file_path())) self.assertTrue(self.update_handler._is_clean_start) @@ -972,27 +1110,27 @@ class TestUpdate(UpdateTestCase): self.assertTrue(self.update_handler._is_orphaned) return - def test_load_agents(self): + def test_find_agents(self): self.prepare_agents() self.assertTrue(0 <= len(self.update_handler.agents)) - self.update_handler._load_agents() + self.update_handler._find_agents() self.assertEqual(len(get_agents(self.tmp_dir)), len(self.update_handler.agents)) return - def test_load_agents_does_reload(self): + def test_find_agents_does_reload(self): self.prepare_agents() - self.update_handler._load_agents() + self.update_handler._find_agents() agents = self.update_handler.agents - self.update_handler._load_agents() + self.update_handler._find_agents() self.assertNotEqual(agents, self.update_handler.agents) return - def test_load_agents_sorts(self): + def test_find_agents_sorts(self): self.prepare_agents() - self.update_handler._load_agents() + self.update_handler._find_agents() v = FlexibleVersion("100000") for a in self.update_handler.agents: @@ -1002,7 +1140,7 @@ class TestUpdate(UpdateTestCase): def test_purge_agents(self): self.prepare_agents() - self.update_handler._load_agents() + self.update_handler._find_agents() # Ensure at least three agents initially exist self.assertTrue(2 < len(self.update_handler.agents)) @@ -1014,7 +1152,7 @@ class TestUpdate(UpdateTestCase): # Reload and assert only the kept agents remain on disk self.update_handler.agents = kept_agents self.update_handler._purge_agents() - self.update_handler._load_agents() + self.update_handler._find_agents() self.assertEqual( [agent.version for agent in kept_agents], [agent.version for agent in self.update_handler.agents]) @@ -1032,7 +1170,7 @@ class TestUpdate(UpdateTestCase): self.assertTrue(os.path.exists(agent_path + ".zip")) return - def _test_run_latest(self, mock_child=None, mock_time=None): + def _test_run_latest(self, mock_child=None, mock_time=None, child_args=None): if mock_child is None: mock_child = ChildMock() if mock_time is None: @@ -1041,7 +1179,7 @@ class TestUpdate(UpdateTestCase): with patch('subprocess.Popen', return_value=mock_child) as mock_popen: with patch('time.time', side_effect=mock_time.time): with patch('time.sleep', side_effect=mock_time.sleep): - self.update_handler.run_latest() + self.update_handler.run_latest(child_args=child_args) self.assertEqual(1, mock_popen.call_count) return mock_popen.call_args @@ -1051,16 +1189,32 @@ class TestUpdate(UpdateTestCase): agent = self.update_handler.get_latest_agent() args, kwargs = self._test_run_latest() + args = args[0] cmds = textutil.safe_shlex_split(agent.get_agent_cmd()) if cmds[0].lower() == "python": cmds[0] = get_python_cmd() - self.assertEqual(args[0], cmds) + self.assertEqual(args, cmds) + self.assertTrue(len(args) > 1) + self.assertTrue(args[0].startswith("python")) + self.assertEqual("-run-exthandlers", args[len(args)-1]) self.assertEqual(True, 'cwd' in kwargs) self.assertEqual(agent.get_agent_dir(), kwargs['cwd']) self.assertEqual(False, '\x00' in cmds[0]) return + def test_run_latest_passes_child_args(self): + self.prepare_agents() + + agent = self.update_handler.get_latest_agent() + args, kwargs = self._test_run_latest(child_args="AnArgument") + args = args[0] + + self.assertTrue(len(args) > 1) + self.assertTrue(args[0].startswith("python")) + self.assertEqual("AnArgument", args[len(args)-1]) + return + def test_run_latest_polls_and_waits_for_success(self): mock_child = ChildMock(return_value=None) mock_time = TimeMock(time_increment=CHILD_HEALTH_INTERVAL/3) @@ -1147,7 +1301,8 @@ class TestUpdate(UpdateTestCase): with patch('azurelinuxagent.ga.update.UpdateHandler.get_latest_agent', return_value=latest_agent): self._test_run_latest(mock_child=ChildMock(return_value=1)) - self.assertTrue(latest_agent.is_available) + self.assertTrue(latest_agent.is_blacklisted) + self.assertFalse(latest_agent.is_available) self.assertNotEqual(0.0, latest_agent.error.last_failure) self.assertEqual(1, latest_agent.error.failure_count) return @@ -1198,8 +1353,6 @@ class TestUpdate(UpdateTestCase): self.update_handler.running = False return - calls = calls * invocations - fileutil.write_file(conf.get_agent_pid_file_path(), ustr(42)) with patch('azurelinuxagent.ga.exthandlers.get_exthandlers_handler') as mock_handler: @@ -1227,13 +1380,30 @@ class TestUpdate(UpdateTestCase): return def test_run_keeps_running(self): - self._test_run(invocations=15) + self._test_run(invocations=15, calls=[call.run()]*15) return def test_run_stops_if_update_available(self): self.update_handler._upgrade_available = Mock(return_value=True) self._test_run(invocations=0, calls=[], enable_updates=True) return + + @patch('platform.linux_distribution', return_value=['Ubuntu', '16.10', 'yakkety']) + @patch('azurelinuxagent.ga.update.datetime') + def test_run_stops_if_test_agent_available(self, mock_dt, mock_dist): + mock_dt.utcnow = Mock(return_value=datetime(2017, 1, 1, 0, 0, 5)) + self.prepare_agent(AGENT_VERSION, mark_test=True) + + agent = GuestAgent(path=self.agent_dir(AGENT_VERSION)) + agent.enable = Mock() + self.assertTrue(agent.is_test) + self.assertTrue(agent.in_slice) + + with patch('azurelinuxagent.ga.update.UpdateHandler.get_test_agent', + return_value=agent) as mock_test: + self._test_run(invocations=0) + self.assertEqual(mock_test.call_count, 1) + self.assertEqual(agent.enable.call_count, 1) def test_run_stops_if_orphaned(self): with patch('os.getppid', return_value=1): @@ -1417,6 +1587,5 @@ class TimeMock(Mock): self.next_time += self.time_increment return current_time - if __name__ == '__main__': unittest.main() -- cgit v1.2.3