summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/__init__.py3
-rw-r--r--tests/common/__init__.py16
-rw-r--r--tests/common/dhcp/__init__.py16
-rw-r--r--tests/common/dhcp/test_dhcp.py107
-rw-r--r--tests/common/osutil/__init__.py16
-rw-r--r--tests/common/osutil/test_default.py146
-rw-r--r--tests/common/test_version.py65
-rw-r--r--tests/daemon/__init__.py16
-rw-r--r--tests/daemon/test_daemon.py (renamed from tests/distro/test_daemon.py)34
-rw-r--r--tests/data/dhcp.leases56
-rw-r--r--tests/data/dhcp.leases.multi57
-rwxr-xr-xtests/data/ext/sample_ext/sample.py18
-rw-r--r--tests/data/ga/WALinuxAgent-2.1.5.zipbin0 -> 244184 bytes
-rw-r--r--tests/data/wire/ext_conf.xml34
-rw-r--r--tests/data/wire/ext_conf_autoupgrade.xml28
-rw-r--r--tests/data/wire/ext_conf_autoupgrade_internalversion.xml28
-rw-r--r--tests/data/wire/ext_conf_internalversion.xml28
-rw-r--r--tests/data/wire/ga_manifest.xml48
-rw-r--r--tests/data/wire/manifest.xml50
-rw-r--r--tests/distro/__init__.py3
-rw-r--r--tests/distro/test_resourceDisk.py (renamed from tests/distro/test_loader.py)26
-rw-r--r--tests/distro/test_scvmm.py84
-rw-r--r--tests/ga/__init__.py16
-rw-r--r--tests/ga/test_extension.py (renamed from tests/distro/test_extension.py)178
-rw-r--r--tests/ga/test_monitor.py (renamed from tests/distro/test_monitor.py)7
-rw-r--r--tests/ga/test_update.py1135
-rw-r--r--tests/pa/__init__.py16
-rw-r--r--tests/pa/test_provision.py (renamed from tests/distro/test_provision.py)32
-rw-r--r--tests/protocol/__init__.py3
-rw-r--r--tests/protocol/mockmetadata.py7
-rw-r--r--tests/protocol/mockwiredata.py20
-rw-r--r--tests/protocol/test_hostplugin.py85
-rw-r--r--tests/protocol/test_metadata.py11
-rw-r--r--tests/protocol/test_protocol_util.py (renamed from tests/distro/test_protocol_util.py)54
-rw-r--r--tests/protocol/test_restapi.py5
-rw-r--r--tests/protocol/test_wire.py15
-rw-r--r--tests/test_import.py26
-rw-r--r--tests/tools.py31
-rw-r--r--tests/utils/__init__.py3
-rw-r--r--tests/utils/test_file_util.py7
-rw-r--r--tests/utils/test_flexible_version.py477
-rw-r--r--tests/utils/test_rest_util.py15
-rw-r--r--tests/utils/test_shell_util.py10
-rw-r--r--tests/utils/test_text_util.py9
44 files changed, 2793 insertions, 248 deletions
diff --git a/tests/__init__.py b/tests/__init__.py
index 9bdb27e..2ef4c16 100644
--- a/tests/__init__.py
+++ b/tests/__init__.py
@@ -14,6 +14,3 @@
#
# Requires Python 2.4+ and Openssl 1.0+
#
-# Implements parts of RFC 2131, 1541, 1497 and
-# http://msdn.microsoft.com/en-us/library/cc227282%28PROT.10%29.aspx
-# http://msdn.microsoft.com/en-us/library/cc227259%28PROT.13%29.aspx
diff --git a/tests/common/__init__.py b/tests/common/__init__.py
new file mode 100644
index 0000000..2ef4c16
--- /dev/null
+++ b/tests/common/__init__.py
@@ -0,0 +1,16 @@
+# Copyright 2014 Microsoft Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Requires Python 2.4+ and Openssl 1.0+
+#
diff --git a/tests/common/dhcp/__init__.py b/tests/common/dhcp/__init__.py
new file mode 100644
index 0000000..2ef4c16
--- /dev/null
+++ b/tests/common/dhcp/__init__.py
@@ -0,0 +1,16 @@
+# Copyright 2014 Microsoft Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Requires Python 2.4+ and Openssl 1.0+
+#
diff --git a/tests/common/dhcp/test_dhcp.py b/tests/common/dhcp/test_dhcp.py
new file mode 100644
index 0000000..c27ffe8
--- /dev/null
+++ b/tests/common/dhcp/test_dhcp.py
@@ -0,0 +1,107 @@
+# Copyright 2014 Microsoft Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Requires Python 2.4+ and Openssl 1.0+
+#
+
+import mock
+import azurelinuxagent.common.dhcp as dhcp
+import azurelinuxagent.common.osutil.default as osutil
+from tests.tools import *
+
+
+class TestDHCP(AgentTestCase):
+ def test_wireserver_route_exists(self):
+ # setup
+ dhcp_handler = dhcp.get_dhcp_handler()
+ self.assertTrue(dhcp_handler.endpoint is None)
+ self.assertTrue(dhcp_handler.routes is None)
+ self.assertTrue(dhcp_handler.gateway is None)
+
+ # execute
+ routing_table = "\
+ Iface Destination Gateway Flags RefCnt Use Metric " \
+ "Mask MTU Window IRTT \n\
+ eth0 00000000 10813FA8 0003 0 0 5 " \
+ "00000000 0 0 0 \n\
+ eth0 00345B0A 00000000 0001 0 0 5 " \
+ "00000000 0 0 0 \n\
+ lo 00000000 01345B0A 0003 0 0 1 " \
+ "00FCFFFF 0 0 0 \n"
+
+ with patch("os.path.exists", return_value=True):
+ mo = mock.mock_open(read_data=routing_table)
+ with patch(open_patch(), mo):
+ self.assertTrue(dhcp_handler.wireserver_route_exists)
+
+ # test
+ self.assertTrue(dhcp_handler.endpoint is not None)
+ self.assertTrue(dhcp_handler.routes is None)
+ self.assertTrue(dhcp_handler.gateway is None)
+
+ def test_wireserver_route_not_exists(self):
+ # setup
+ dhcp_handler = dhcp.get_dhcp_handler()
+ self.assertTrue(dhcp_handler.endpoint is None)
+ self.assertTrue(dhcp_handler.routes is None)
+ self.assertTrue(dhcp_handler.gateway is None)
+
+ # execute
+ self.assertFalse(dhcp_handler.wireserver_route_exists)
+
+ # test
+ self.assertTrue(dhcp_handler.endpoint is None)
+ self.assertTrue(dhcp_handler.routes is None)
+ self.assertTrue(dhcp_handler.gateway is None)
+
+ def test_dhcp_cache_exists(self):
+ dhcp_handler = dhcp.get_dhcp_handler()
+ dhcp_handler.osutil = osutil.DefaultOSUtil()
+ with patch.object(osutil.DefaultOSUtil, 'get_dhcp_lease_endpoint',
+ return_value=None):
+ self.assertFalse(dhcp_handler.dhcp_cache_exists)
+ self.assertEqual(dhcp_handler.endpoint, None)
+ with patch.object(osutil.DefaultOSUtil, 'get_dhcp_lease_endpoint',
+ return_value="foo"):
+ self.assertTrue(dhcp_handler.dhcp_cache_exists)
+ self.assertEqual(dhcp_handler.endpoint, "foo")
+
+ def test_dhcp_skip_cache(self):
+ handler = dhcp.get_dhcp_handler()
+ handler.osutil = osutil.DefaultOSUtil()
+ with patch('os.path.exists', return_value=False):
+ with patch.object(osutil.DefaultOSUtil, 'get_dhcp_lease_endpoint')\
+ as patch_dhcp_cache:
+ with patch.object(dhcp.DhcpHandler, 'send_dhcp_req') \
+ as patch_dhcp_send:
+
+ endpoint = 'foo'
+ patch_dhcp_cache.return_value = endpoint
+
+ # endpoint comes from cache
+ self.assertFalse(handler.skip_cache)
+ handler.run()
+ self.assertTrue(patch_dhcp_cache.call_count == 1)
+ self.assertTrue(patch_dhcp_send.call_count == 0)
+ self.assertTrue(handler.endpoint == endpoint)
+
+ # reset
+ handler.skip_cache = True
+ handler.endpoint = None
+
+ # endpoint comes from dhcp request
+ self.assertTrue(handler.skip_cache)
+ handler.run()
+ self.assertTrue(patch_dhcp_cache.call_count == 1)
+ self.assertTrue(patch_dhcp_send.call_count == 1)
diff --git a/tests/common/osutil/__init__.py b/tests/common/osutil/__init__.py
new file mode 100644
index 0000000..2ef4c16
--- /dev/null
+++ b/tests/common/osutil/__init__.py
@@ -0,0 +1,16 @@
+# Copyright 2014 Microsoft Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Requires Python 2.4+ and Openssl 1.0+
+#
diff --git a/tests/common/osutil/test_default.py b/tests/common/osutil/test_default.py
new file mode 100644
index 0000000..d9d00f6
--- /dev/null
+++ b/tests/common/osutil/test_default.py
@@ -0,0 +1,146 @@
+# Copyright 2014 Microsoft Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Requires Python 2.4+ and Openssl 1.0+
+#
+
+import socket
+import glob
+import mock
+import azurelinuxagent.common.osutil.default as osutil
+import azurelinuxagent.common.utils.shellutil as shellutil
+from azurelinuxagent.common.osutil import get_osutil
+from tests.tools import *
+
+
+class TestOSUtil(AgentTestCase):
+ def test_restart(self):
+ # setup
+ retries = 3
+ ifname = 'dummy'
+ with patch.object(shellutil, "run") as run_patch:
+ run_patch.return_value = 1
+
+ # execute
+ osutil.DefaultOSUtil.restart_if(osutil.DefaultOSUtil(), ifname=ifname, retries=retries, wait=0)
+
+ # assert
+ self.assertEqual(run_patch.call_count, retries)
+ self.assertEqual(run_patch.call_args_list[0][0][0], 'ifdown {0} && ifup {0}'.format(ifname))
+
+ def test_get_first_if(self):
+ ifname, ipaddr = osutil.DefaultOSUtil().get_first_if()
+ self.assertTrue(ifname.startswith('eth'))
+ self.assertTrue(ipaddr is not None)
+ try:
+ socket.inet_aton(ipaddr)
+ except socket.error:
+ self.fail("not a valid ip address")
+
+ def test_isloopback(self):
+ self.assertTrue(osutil.DefaultOSUtil().is_loopback(b'lo'))
+ self.assertFalse(osutil.DefaultOSUtil().is_loopback(b'eth0'))
+
+ def test_isprimary(self):
+ routing_table = "\
+ Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT \n\
+ eth0 00000000 01345B0A 0003 0 0 5 00000000 0 0 0 \n\
+ eth0 00345B0A 00000000 0001 0 0 5 00000000 0 0 0 \n\
+ lo 00000000 01345B0A 0003 0 0 1 00FCFFFF 0 0 0 \n"
+
+ mo = mock.mock_open(read_data=routing_table)
+ with patch(open_patch(), mo):
+ self.assertFalse(osutil.DefaultOSUtil().is_primary_interface('lo'))
+ self.assertTrue(osutil.DefaultOSUtil().is_primary_interface('eth0'))
+
+ def test_multiple_default_routes(self):
+ routing_table = "\
+ Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT \n\
+ high 00000000 01345B0A 0003 0 0 5 00000000 0 0 0 \n\
+ low1 00000000 01345B0A 0003 0 0 1 00FCFFFF 0 0 0 \n"
+
+ mo = mock.mock_open(read_data=routing_table)
+ with patch(open_patch(), mo):
+ self.assertTrue(osutil.DefaultOSUtil().is_primary_interface('low1'))
+
+ def test_multiple_interfaces(self):
+ routing_table = "\
+ Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT \n\
+ first 00000000 01345B0A 0003 0 0 1 00000000 0 0 0 \n\
+ secnd 00000000 01345B0A 0003 0 0 1 00FCFFFF 0 0 0 \n"
+
+ mo = mock.mock_open(read_data=routing_table)
+ with patch(open_patch(), mo):
+ self.assertTrue(osutil.DefaultOSUtil().is_primary_interface('first'))
+
+ def test_interface_flags(self):
+ routing_table = "\
+ Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT \n\
+ nflg 00000000 01345B0A 0001 0 0 1 00000000 0 0 0 \n\
+ flgs 00000000 01345B0A 0003 0 0 1 00FCFFFF 0 0 0 \n"
+
+ mo = mock.mock_open(read_data=routing_table)
+ with patch(open_patch(), mo):
+ self.assertTrue(osutil.DefaultOSUtil().is_primary_interface('flgs'))
+
+ def test_no_interface(self):
+ routing_table = "\
+ Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT \n\
+ ndst 00000001 01345B0A 0003 0 0 1 00000000 0 0 0 \n\
+ nflg 00000000 01345B0A 0001 0 0 1 00FCFFFF 0 0 0 \n"
+
+ mo = mock.mock_open(read_data=routing_table)
+ with patch(open_patch(), mo):
+ self.assertFalse(osutil.DefaultOSUtil().is_primary_interface('ndst'))
+ self.assertFalse(osutil.DefaultOSUtil().is_primary_interface('nflg'))
+ self.assertFalse(osutil.DefaultOSUtil().is_primary_interface('invalid'))
+
+ def test_no_primary_does_not_throw(self):
+ with patch.object(osutil.DefaultOSUtil, 'get_primary_interface') \
+ as patch_primary:
+ exception = False
+ patch_primary.return_value = ''
+ try:
+ osutil.DefaultOSUtil().get_first_if()[0]
+ except Exception as e:
+ exception = True
+ self.assertFalse(exception)
+
+ def test_dhcp_lease_default(self):
+ self.assertTrue(osutil.DefaultOSUtil().get_dhcp_lease_endpoint() is None)
+
+ def test_dhcp_lease_ubuntu(self):
+ with patch.object(glob, "glob", return_value=['/var/lib/dhcp/dhclient.eth0.leases']):
+ with patch(open_patch(), mock.mock_open(read_data=load_data("dhcp.leases"))):
+ endpoint = get_osutil(distro_name='ubuntu', distro_version='12.04').get_dhcp_lease_endpoint()
+ self.assertTrue(endpoint is not None)
+ self.assertEqual(endpoint, "168.63.129.16")
+
+ endpoint = get_osutil(distro_name='ubuntu', distro_version='12.04').get_dhcp_lease_endpoint()
+ self.assertTrue(endpoint is not None)
+ self.assertEqual(endpoint, "168.63.129.16")
+
+ endpoint = get_osutil(distro_name='ubuntu', distro_version='14.04').get_dhcp_lease_endpoint()
+ self.assertTrue(endpoint is not None)
+ self.assertEqual(endpoint, "168.63.129.16")
+
+ def test_dhcp_lease_multi(self):
+ with patch.object(glob, "glob", return_value=['/var/lib/dhcp/dhclient.eth0.leases']):
+ with patch(open_patch(), mock.mock_open(read_data=load_data("dhcp.leases.multi"))):
+ endpoint = get_osutil(distro_name='ubuntu', distro_version='12.04').get_dhcp_lease_endpoint()
+ self.assertTrue(endpoint is not None)
+ self.assertEqual(endpoint, "second")
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/common/test_version.py b/tests/common/test_version.py
new file mode 100644
index 0000000..6a4dc38
--- /dev/null
+++ b/tests/common/test_version.py
@@ -0,0 +1,65 @@
+# Copyright 2014 Microsoft Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Requires Python 2.4+ and Openssl 1.0+
+#
+
+from __future__ import print_function
+
+import copy
+import glob
+import json
+import os
+import platform
+import random
+import subprocess
+import sys
+import tempfile
+import zipfile
+
+from tests.protocol.mockwiredata import *
+from tests.tools import *
+
+import azurelinuxagent.common.conf as conf
+import azurelinuxagent.common.logger as logger
+import azurelinuxagent.common.utils.fileutil as fileutil
+
+from azurelinuxagent.common.utils.flexible_version import FlexibleVersion
+from azurelinuxagent.common.version import *
+
+
+class TestCurrentAgentName(AgentTestCase):
+ def setUp(self):
+ AgentTestCase.setUp(self)
+ return
+
+ @patch("os.getcwd", return_value="/default/install/directory")
+ def test_extract_name_finds_installed(self, mock_cwd):
+ current_agent, current_version = set_current_agent()
+ self.assertEqual(AGENT_LONG_VERSION, current_agent)
+ self.assertEqual(AGENT_VERSION, str(current_version))
+ return
+
+ @patch("os.getcwd")
+ def test_extract_name_finds_latest_agent(self, mock_cwd):
+ path = os.path.join(conf.get_lib_dir(), "{0}-{1}".format(
+ AGENT_NAME,
+ "1.2.3"))
+ mock_cwd.return_value = path
+ agent = os.path.basename(path)
+ version = AGENT_NAME_PATTERN.match(agent).group(1)
+ current_agent, current_version = set_current_agent()
+ self.assertEqual(agent, current_agent)
+ self.assertEqual(version, str(current_version))
+ return
diff --git a/tests/daemon/__init__.py b/tests/daemon/__init__.py
new file mode 100644
index 0000000..2ef4c16
--- /dev/null
+++ b/tests/daemon/__init__.py
@@ -0,0 +1,16 @@
+# Copyright 2014 Microsoft Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Requires Python 2.4+ and Openssl 1.0+
+#
diff --git a/tests/distro/test_daemon.py b/tests/daemon/test_daemon.py
index 9d3c45b..263af49 100644
--- a/tests/distro/test_daemon.py
+++ b/tests/daemon/test_daemon.py
@@ -14,14 +14,10 @@
#
# Requires Python 2.4+ and Openssl 1.0+
#
-# Implements parts of RFC 2131, 1541, 1497 and
-# http://msdn.microsoft.com/en-us/library/cc227282%28PROT.10%29.aspx
-# http://msdn.microsoft.com/en-us/library/cc227259%28PROT.13%29.aspx
from tests.tools import *
-from azurelinuxagent.distro.loader import get_distro
-from azurelinuxagent.exception import *
-from azurelinuxagent.distro.default.daemon import *
+from azurelinuxagent.common.exception import *
+from azurelinuxagent.daemon import *
class MockDaemonCall(object):
def __init__(self, daemon_handler, count):
@@ -38,26 +34,30 @@ class MockDaemonCall(object):
@patch("time.sleep")
class TestDaemon(AgentTestCase):
def test_daemon_restart(self, mock_sleep):
- distro = get_distro()
- mock_daemon = Mock(side_effect=MockDaemonCall(distro.daemon_handler, 2))
- distro.daemon_handler.daemon = mock_daemon
- distro.daemon_handler.check_pid = Mock()
- distro.daemon_handler.run()
+ #Mock daemon function
+ daemon_handler = get_daemon_handler()
+ mock_daemon = Mock(side_effect=MockDaemonCall(daemon_handler, 2))
+ daemon_handler.daemon = mock_daemon
+
+ daemon_handler.check_pid = Mock()
+
+ daemon_handler.run()
mock_sleep.assert_any_call(15)
- self.assertEquals(2, distro.daemon_handler.daemon.call_count)
+ self.assertEquals(2, daemon_handler.daemon.call_count)
- @patch("azurelinuxagent.distro.default.daemon.conf")
- @patch("azurelinuxagent.distro.default.daemon.sys.exit")
+ @patch("azurelinuxagent.daemon.main.conf")
+ @patch("azurelinuxagent.daemon.main.sys.exit")
def test_check_pid(self, mock_exit, mock_conf, mock_sleep):
- distro = get_distro()
+ daemon_handler = get_daemon_handler()
+
mock_pid_file = os.path.join(self.tmp_dir, "pid")
mock_conf.get_agent_pid_file_path = Mock(return_value=mock_pid_file)
- distro.daemon_handler.check_pid()
+ daemon_handler.check_pid()
self.assertTrue(os.path.isfile(mock_pid_file))
- distro.daemon_handler.check_pid()
+ daemon_handler.check_pid()
mock_exit.assert_any_call(0)
if __name__ == '__main__':
diff --git a/tests/data/dhcp.leases b/tests/data/dhcp.leases
new file mode 100644
index 0000000..cb4f396
--- /dev/null
+++ b/tests/data/dhcp.leases
@@ -0,0 +1,56 @@
+lease {
+ interface "eth0";
+ fixed-address 10.0.1.4;
+ server-name "RDE41D2D9BB18C";
+ option subnet-mask 255.255.255.0;
+ option dhcp-lease-time 4294967295;
+ option routers 10.0.1.1;
+ option dhcp-message-type 5;
+ option dhcp-server-identifier 168.63.129.16;
+ option domain-name-servers invalid;
+ option dhcp-renewal-time 4294967295;
+ option rfc3442-classless-static-routes 0,10,0,1,1,32,168,63,129,16,10,0,1,1;
+ option unknown-245 a8:3f:81:10;
+ option dhcp-rebinding-time 4294967295;
+ option domain-name "qylsde3bnlhu5dstzf3bav5inc.fx.internal.cloudapp.net";
+ renew 0 2152/07/23 23:27:10;
+ rebind 0 2152/07/23 23:27:10;
+ expire 0 never;
+}
+lease {
+ interface "eth0";
+ fixed-address 10.0.1.4;
+ server-name "RDE41D2D9BB18C";
+ option subnet-mask 255.255.255.0;
+ option dhcp-lease-time 4294967295;
+ option routers 10.0.1.1;
+ option dhcp-message-type 5;
+ option dhcp-server-identifier 168.63.129.16;
+ option domain-name-servers expired;
+ option dhcp-renewal-time 4294967295;
+ option unknown-245 a8:3f:81:10;
+ option dhcp-rebinding-time 4294967295;
+ option domain-name "qylsde3bnlhu5dstzf3bav5inc.fx.internal.cloudapp.net";
+ renew 4 2015/06/16 16:58:54;
+ rebind 4 2015/06/16 16:58:54;
+ expire 4 2015/06/16 16:58:54;
+}
+lease {
+ interface "eth0";
+ fixed-address 10.0.1.4;
+ server-name "RDE41D2D9BB18C";
+ option subnet-mask 255.255.255.0;
+ option dhcp-lease-time 4294967295;
+ option routers 10.0.1.1;
+ option dhcp-message-type 5;
+ option dhcp-server-identifier 168.63.129.16;
+ option domain-name-servers 168.63.129.16;
+ option dhcp-renewal-time 4294967295;
+ option rfc3442-classless-static-routes 0,10,0,1,1,32,168,63,129,16,10,0,1,1;
+ option unknown-245 a8:3f:81:10;
+ option dhcp-rebinding-time 4294967295;
+ option domain-name "qylsde3bnlhu5dstzf3bav5inc.fx.internal.cloudapp.net";
+ renew 0 2152/07/23 23:27:10;
+ rebind 0 2152/07/23 23:27:10;
+ expire 0 2152/07/23 23:27:10;
+}
diff --git a/tests/data/dhcp.leases.multi b/tests/data/dhcp.leases.multi
new file mode 100644
index 0000000..cfe9c67
--- /dev/null
+++ b/tests/data/dhcp.leases.multi
@@ -0,0 +1,57 @@
+lease {
+ interface "eth0";
+ fixed-address 10.0.1.4;
+ server-name "RDE41D2D9BB18C";
+ option subnet-mask 255.255.255.0;
+ option dhcp-lease-time 4294967295;
+ option routers 10.0.1.1;
+ option dhcp-message-type 5;
+ option dhcp-server-identifier 168.63.129.16;
+ option domain-name-servers first;
+ option dhcp-renewal-time 4294967295;
+ option rfc3442-classless-static-routes 0,10,0,1,1,32,168,63,129,16,10,0,1,1;
+ option unknown-245 a8:3f:81:10;
+ option dhcp-rebinding-time 4294967295;
+ option domain-name "qylsde3bnlhu5dstzf3bav5inc.fx.internal.cloudapp.net";
+ renew 0 2152/07/23 23:27:10;
+ rebind 0 2152/07/23 23:27:10;
+ expire 0 2152/07/23 23:27:10;
+}
+lease {
+ interface "eth0";
+ fixed-address 10.0.1.4;
+ server-name "RDE41D2D9BB18C";
+ option subnet-mask 255.255.255.0;
+ option dhcp-lease-time 4294967295;
+ option routers 10.0.1.1;
+ option dhcp-message-type 5;
+ option dhcp-server-identifier 168.63.129.16;
+ option domain-name-servers second;
+ option dhcp-renewal-time 4294967295;
+ option rfc3442-classless-static-routes 0,10,0,1,1,32,168,63,129,16,10,0,1,1;
+ option unknown-245 a8:3f:81:10;
+ option dhcp-rebinding-time 4294967295;
+ option domain-name "qylsde3bnlhu5dstzf3bav5inc.fx.internal.cloudapp.net";
+ renew 0 2152/07/23 23:27:10;
+ rebind 0 2152/07/23 23:27:10;
+ expire 0 2152/07/23 23:27:10;
+}
+lease {
+ interface "eth0";
+ fixed-address 10.0.1.4;
+ server-name "RDE41D2D9BB18C";
+ option subnet-mask 255.255.255.0;
+ option dhcp-lease-time 4294967295;
+ option routers 10.0.1.1;
+ option dhcp-message-type 5;
+ option dhcp-server-identifier 168.63.129.16;
+ option domain-name-servers expired;
+ option dhcp-renewal-time 4294967295;
+ option rfc3442-classless-static-routes 0,10,0,1,1,32,168,63,129,16,10,0,1,1;
+ option unknown-245 a8:3f:81:10;
+ option dhcp-rebinding-time 4294967295;
+ option domain-name "qylsde3bnlhu5dstzf3bav5inc.fx.internal.cloudapp.net";
+ renew 0 2152/07/23 23:27:10;
+ rebind 0 2152/07/23 23:27:10;
+ expire 0 2012/07/23 23:27:10;
+}
diff --git a/tests/data/ext/sample_ext/sample.py b/tests/data/ext/sample_ext/sample.py
index 7107ac2..74bd839 100755
--- a/tests/data/ext/sample_ext/sample.py
+++ b/tests/data/ext/sample_ext/sample.py
@@ -2,18 +2,19 @@
import os
+
def get_seq():
- latest_seq = -1;
+ latest_seq = -1
config_dir = os.path.join(os.getcwd(), "config")
if os.path.isdir(config_dir):
for item in os.listdir(config_dir):
item_path = os.path.join(config_dir, item)
if os.path.isfile(item_path):
- seperator = item.rfind(".")
- if seperator > 0 and item[seperator + 1:] == "settings":
- seq = int(item[0: seperator])
- if seq > latest_seq:
- latest_seq = seq
+ separator = item.rfind(".")
+ if separator > 0 and item[separator + 1:] == "settings":
+ sequence = int(item[0: separator])
+ if sequence > latest_seq:
+ latest_seq = sequence
return latest_seq
@@ -28,6 +29,9 @@ succeed_status = """
if __name__ == "__main__":
seq = get_seq()
if seq >= 0:
- status_file = os.path.join(os.getcwd(), "status", "{0}.status".format(seq))
+ status_path = os.path.join(os.getcwd(), "status")
+ if not os.path.exists(status_path):
+ os.makedirs(status_path)
+ status_file = os.path.join(status_path, "{0}.status".format(seq))
with open(status_file, "w+") as status:
status.write(succeed_status)
diff --git a/tests/data/ga/WALinuxAgent-2.1.5.zip b/tests/data/ga/WALinuxAgent-2.1.5.zip
new file mode 100644
index 0000000..b1f2684
--- /dev/null
+++ b/tests/data/ga/WALinuxAgent-2.1.5.zip
Binary files differ
diff --git a/tests/data/wire/ext_conf.xml b/tests/data/wire/ext_conf.xml
index 725271d..0b7c528 100644
--- a/tests/data/wire/ext_conf.xml
+++ b/tests/data/wire/ext_conf.xml
@@ -1,44 +1,24 @@
<Extensions version="1.0.0.0" goalStateIncarnation="9"><GuestAgentExtension xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<GAFamilies>
<GAFamily>
- <Name>Win8</Name>
+ <Name>Prod</Name>
<Uris>
- <Uri>http://rdfepirv2hknprdstr03.blob.core.windows.net/bfd5c281a7dc4e4b84381eb0b47e3aaf/Microsoft.WindowsAzure.GuestAgent_Win8_asiaeast_manifest.xml</Uri>
- <Uri>http://rdfepirv2hknprdstr04.blob.core.windows.net/bfd5c281a7dc4e4b84381eb0b47e3aaf/Microsoft.WindowsAzure.GuestAgent_Win8_asiaeast_manifest.xml</Uri>
- <Uri>http://rdfepirv2hknprdstr05.blob.core.windows.net/bfd5c281a7dc4e4b84381eb0b47e3aaf/Microsoft.WindowsAzure.GuestAgent_Win8_asiaeast_manifest.xml</Uri>
- <Uri>http://rdfepirv2hknprdstr06.blob.core.windows.net/bfd5c281a7dc4e4b84381eb0b47e3aaf/Microsoft.WindowsAzure.GuestAgent_Win8_asiaeast_manifest.xml</Uri>
- <Uri>http://rdfepirv2hknprdstr07.blob.core.windows.net/bfd5c281a7dc4e4b84381eb0b47e3aaf/Microsoft.WindowsAzure.GuestAgent_Win8_asiaeast_manifest.xml</Uri>
- <Uri>http://rdfepirv2hknprdstr08.blob.core.windows.net/bfd5c281a7dc4e4b84381eb0b47e3aaf/Microsoft.WindowsAzure.GuestAgent_Win8_asiaeast_manifest.xml</Uri>
- <Uri>http://rdfepirv2hknprdstr09.blob.core.windows.net/bfd5c281a7dc4e4b84381eb0b47e3aaf/Microsoft.WindowsAzure.GuestAgent_Win8_asiaeast_manifest.xml</Uri>
- <Uri>http://rdfepirv2hknprdstr10.blob.core.windows.net/bfd5c281a7dc4e4b84381eb0b47e3aaf/Microsoft.WindowsAzure.GuestAgent_Win8_asiaeast_manifest.xml</Uri>
- <Uri>http://rdfepirv2hknprdstr11.blob.core.windows.net/bfd5c281a7dc4e4b84381eb0b47e3aaf/Microsoft.WindowsAzure.GuestAgent_Win8_asiaeast_manifest.xml</Uri>
- <Uri>http://rdfepirv2hknprdstr12.blob.core.windows.net/bfd5c281a7dc4e4b84381eb0b47e3aaf/Microsoft.WindowsAzure.GuestAgent_Win8_asiaeast_manifest.xml</Uri>
- <Uri>http://zrdfepirv2hk2prdstr01.blob.core.windows.net/bfd5c281a7dc4e4b84381eb0b47e3aaf/Microsoft.WindowsAzure.GuestAgent_Win8_asiaeast_manifest.xml</Uri>
+ <Uri>http://manifest_of_ga.xml</Uri>
</Uris>
</GAFamily>
<GAFamily>
- <Name>Win7</Name>
+ <Name>Test</Name>
<Uris>
- <Uri>http://rdfepirv2hknprdstr03.blob.core.windows.net/bfd5c281a7dc4e4b84381eb0b47e3aaf/Microsoft.WindowsAzure.GuestAgent_Win7_asiaeast_manifest.xml</Uri>
- <Uri>http://rdfepirv2hknprdstr04.blob.core.windows.net/bfd5c281a7dc4e4b84381eb0b47e3aaf/Microsoft.WindowsAzure.GuestAgent_Win7_asiaeast_manifest.xml</Uri>
- <Uri>http://rdfepirv2hknprdstr05.blob.core.windows.net/bfd5c281a7dc4e4b84381eb0b47e3aaf/Microsoft.WindowsAzure.GuestAgent_Win7_asiaeast_manifest.xml</Uri>
- <Uri>http://rdfepirv2hknprdstr06.blob.core.windows.net/bfd5c281a7dc4e4b84381eb0b47e3aaf/Microsoft.WindowsAzure.GuestAgent_Win7_asiaeast_manifest.xml</Uri>
- <Uri>http://rdfepirv2hknprdstr07.blob.core.windows.net/bfd5c281a7dc4e4b84381eb0b47e3aaf/Microsoft.WindowsAzure.GuestAgent_Win7_asiaeast_manifest.xml</Uri>
- <Uri>http://rdfepirv2hknprdstr08.blob.core.windows.net/bfd5c281a7dc4e4b84381eb0b47e3aaf/Microsoft.WindowsAzure.GuestAgent_Win7_asiaeast_manifest.xml</Uri>
- <Uri>http://rdfepirv2hknprdstr09.blob.core.windows.net/bfd5c281a7dc4e4b84381eb0b47e3aaf/Microsoft.WindowsAzure.GuestAgent_Win7_asiaeast_manifest.xml</Uri>
- <Uri>http://rdfepirv2hknprdstr10.blob.core.windows.net/bfd5c281a7dc4e4b84381eb0b47e3aaf/Microsoft.WindowsAzure.GuestAgent_Win7_asiaeast_manifest.xml</Uri>
- <Uri>http://rdfepirv2hknprdstr11.blob.core.windows.net/bfd5c281a7dc4e4b84381eb0b47e3aaf/Microsoft.WindowsAzure.GuestAgent_Win7_asiaeast_manifest.xml</Uri>
- <Uri>http://rdfepirv2hknprdstr12.blob.core.windows.net/bfd5c281a7dc4e4b84381eb0b47e3aaf/Microsoft.WindowsAzure.GuestAgent_Win7_asiaeast_manifest.xml</Uri>
- <Uri>http://zrdfepirv2hk2prdstr01.blob.core.windows.net/bfd5c281a7dc4e4b84381eb0b47e3aaf/Microsoft.WindowsAzure.GuestAgent_Win7_asiaeast_manifest.xml</Uri>
- </Uris>
+ <Uri>http://manifest_of_ga.xml</Uri>
+ </Uris>
</GAFamily>
</GAFamilies>
</GuestAgentExtension>
<Plugins>
- <Plugin name="OSTCExtensions.ExampleHandlerLinux" version="1.0" location="http://rdfepirv2hknprdstr03.blob.core.windows.net/b01058962be54ceca550a390fa5ff064/Microsoft.OSTCExtensions_ExampleHandlerLinux_asiaeast_manifest.xml" config="" state="enabled" autoUpgrade="false" failoverlocation="http://rdfepirv2hknprdstr04.blob.core.windows.net/b01058962be54ceca550a390fa5ff064/Microsoft.OSTCExtensions_ExampleHandlerLinux_asiaeast_manifest.xml" runAsStartupTask="false" isJson="true" />
+ <Plugin name="OSTCExtensions.ExampleHandlerLinux" version="1.0.0" location="http://rdfepirv2hknprdstr03.blob.core.windows.net/b01058962be54ceca550a390fa5ff064/Microsoft.OSTCExtensions_ExampleHandlerLinux_asiaeast_manifest.xml" config="" state="enabled" autoUpgrade="false" failoverlocation="http://rdfepirv2hknprdstr04.blob.core.windows.net/b01058962be54ceca550a390fa5ff064/Microsoft.OSTCExtensions_ExampleHandlerLinux_asiaeast_manifest.xml" runAsStartupTask="false" isJson="true" />
</Plugins>
<PluginSettings>
- <Plugin name="OSTCExtensions.ExampleHandlerLinux" version="1.0">
+ <Plugin name="OSTCExtensions.ExampleHandlerLinux" version="1.0.0">
<RuntimeSettings seqNo="0">{"runtimeSettings":[{"handlerSettings":{"protectedSettingsCertThumbprint":"4037FBF5F1F3014F99B5D6C7799E9B20E6871CB3","protectedSettings":"MIICWgYJK","publicSettings":{"foo":"bar"}}}]}</RuntimeSettings>
</Plugin>
</PluginSettings>
diff --git a/tests/data/wire/ext_conf_autoupgrade.xml b/tests/data/wire/ext_conf_autoupgrade.xml
new file mode 100644
index 0000000..1d6919e
--- /dev/null
+++ b/tests/data/wire/ext_conf_autoupgrade.xml
@@ -0,0 +1,28 @@
+<Extensions version="1.0.0.0" goalStateIncarnation="9"><GuestAgentExtension xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
+ <GAFamilies>
+ <GAFamily>
+ <Name>Win8</Name>
+ <Uris>
+ <Uri>http://rdfepirv2hknprdstr03.blob.core.windows.net/bfd5c281a7dc4e4b84381eb0b47e3aaf/Microsoft.WindowsAzure.GuestAgent_Win8_asiaeast_manifest.xml</Uri>
+ <Uri>http://rdfepirv2hknprdstr04.blob.core.windows.net/bfd5c281a7dc4e4b84381eb0b47e3aaf/Microsoft.WindowsAzure.GuestAgent_Win8_asiaeast_manifest.xml</Uri>
+ </Uris>
+ </GAFamily>
+ <GAFamily>
+ <Name>Win7</Name>
+ <Uris>
+ <Uri>http://rdfepirv2hknprdstr03.blob.core.windows.net/bfd5c281a7dc4e4b84381eb0b47e3aaf/Microsoft.WindowsAzure.GuestAgent_Win7_asiaeast_manifest.xml</Uri>
+ <Uri>http://rdfepirv2hknprdstr04.blob.core.windows.net/bfd5c281a7dc4e4b84381eb0b47e3aaf/Microsoft.WindowsAzure.GuestAgent_Win7_asiaeast_manifest.xml</Uri>
+ </Uris>
+ </GAFamily>
+ </GAFamilies>
+</GuestAgentExtension>
+<Plugins>
+ <Plugin name="OSTCExtensions.ExampleHandlerLinux" version="1.0.0" location="http://rdfepirv2hknprdstr03.blob.core.windows.net/b01058962be54ceca550a390fa5ff064/Microsoft.OSTCExtensions_ExampleHandlerLinux_asiaeast_manifest.xml" config="" state="enabled" autoUpgrade="true" failoverlocation="http://rdfepirv2hknprdstr04.blob.core.windows.net/b01058962be54ceca550a390fa5ff064/Microsoft.OSTCExtensions_ExampleHandlerLinux_asiaeast_manifest.xml" runAsStartupTask="false" isJson="true" />
+</Plugins>
+<PluginSettings>
+ <Plugin name="OSTCExtensions.ExampleHandlerLinux" version="1.0.0">
+ <RuntimeSettings seqNo="0">{"runtimeSettings":[{"handlerSettings":{"protectedSettingsCertThumbprint":"4037FBF5F1F3014F99B5D6C7799E9B20E6871CB3","protectedSettings":"MIICWgYJK","publicSettings":{"foo":"bar"}}}]}</RuntimeSettings>
+ </Plugin>
+</PluginSettings>
+<StatusUploadBlob>https://yuezhatest.blob.core.windows.net/vhds/test-cs12.test-cs12.test-cs12.status?sr=b&amp;sp=rw&amp;se=9999-01-01&amp;sk=key1&amp;sv=2014-02-14&amp;sig=hfRh7gzUE7sUtYwke78IOlZOrTRCYvkec4hGZ9zZzXo%3D</StatusUploadBlob></Extensions>
+
diff --git a/tests/data/wire/ext_conf_autoupgrade_internalversion.xml b/tests/data/wire/ext_conf_autoupgrade_internalversion.xml
new file mode 100644
index 0000000..1e613ea
--- /dev/null
+++ b/tests/data/wire/ext_conf_autoupgrade_internalversion.xml
@@ -0,0 +1,28 @@
+<Extensions version="1.0.0.0" goalStateIncarnation="9"><GuestAgentExtension xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
+ <GAFamilies>
+ <GAFamily>
+ <Name>Win8</Name>
+ <Uris>
+ <Uri>http://rdfepirv2hknprdstr03.blob.core.windows.net/bfd5c281a7dc4e4b84381eb0b47e3aaf/Microsoft.WindowsAzure.GuestAgent_Win8_asiaeast_manifest.xml</Uri>
+ <Uri>http://rdfepirv2hknprdstr04.blob.core.windows.net/bfd5c281a7dc4e4b84381eb0b47e3aaf/Microsoft.WindowsAzure.GuestAgent_Win8_asiaeast_manifest.xml</Uri>
+ </Uris>
+ </GAFamily>
+ <GAFamily>
+ <Name>Win7</Name>
+ <Uris>
+ <Uri>http://rdfepirv2hknprdstr03.blob.core.windows.net/bfd5c281a7dc4e4b84381eb0b47e3aaf/Microsoft.WindowsAzure.GuestAgent_Win7_asiaeast_manifest.xml</Uri>
+ <Uri>http://rdfepirv2hknprdstr04.blob.core.windows.net/bfd5c281a7dc4e4b84381eb0b47e3aaf/Microsoft.WindowsAzure.GuestAgent_Win7_asiaeast_manifest.xml</Uri>
+ </Uris>
+ </GAFamily>
+ </GAFamilies>
+</GuestAgentExtension>
+<Plugins>
+ <Plugin name="OSTCExtensions.ExampleHandlerLinux" version="1.2.0" location="http://rdfepirv2hknprdstr03.blob.core.windows.net/b01058962be54ceca550a390fa5ff064/Microsoft.OSTCExtensions_ExampleHandlerLinux_asiaeast_manifest.xml" config="" state="enabled" autoUpgrade="true" failoverlocation="http://rdfepirv2hknprdstr04.blob.core.windows.net/b01058962be54ceca550a390fa5ff064/Microsoft.OSTCExtensions_ExampleHandlerLinux_asiaeast_manifest.xml" runAsStartupTask="false" isJson="true" />
+</Plugins>
+<PluginSettings>
+ <Plugin name="OSTCExtensions.ExampleHandlerLinux" version="1.2.0">
+ <RuntimeSettings seqNo="0">{"runtimeSettings":[{"handlerSettings":{"protectedSettingsCertThumbprint":"4037FBF5F1F3014F99B5D6C7799E9B20E6871CB3","protectedSettings":"MIICWgYJK","publicSettings":{"foo":"bar"}}}]}</RuntimeSettings>
+ </Plugin>
+</PluginSettings>
+<StatusUploadBlob>https://yuezhatest.blob.core.windows.net/vhds/test-cs12.test-cs12.test-cs12.status?sr=b&amp;sp=rw&amp;se=9999-01-01&amp;sk=key1&amp;sv=2014-02-14&amp;sig=hfRh7gzUE7sUtYwke78IOlZOrTRCYvkec4hGZ9zZzXo%3D</StatusUploadBlob></Extensions>
+
diff --git a/tests/data/wire/ext_conf_internalversion.xml b/tests/data/wire/ext_conf_internalversion.xml
new file mode 100644
index 0000000..1e613ea
--- /dev/null
+++ b/tests/data/wire/ext_conf_internalversion.xml
@@ -0,0 +1,28 @@
+<Extensions version="1.0.0.0" goalStateIncarnation="9"><GuestAgentExtension xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
+ <GAFamilies>
+ <GAFamily>
+ <Name>Win8</Name>
+ <Uris>
+ <Uri>http://rdfepirv2hknprdstr03.blob.core.windows.net/bfd5c281a7dc4e4b84381eb0b47e3aaf/Microsoft.WindowsAzure.GuestAgent_Win8_asiaeast_manifest.xml</Uri>
+ <Uri>http://rdfepirv2hknprdstr04.blob.core.windows.net/bfd5c281a7dc4e4b84381eb0b47e3aaf/Microsoft.WindowsAzure.GuestAgent_Win8_asiaeast_manifest.xml</Uri>
+ </Uris>
+ </GAFamily>
+ <GAFamily>
+ <Name>Win7</Name>
+ <Uris>
+ <Uri>http://rdfepirv2hknprdstr03.blob.core.windows.net/bfd5c281a7dc4e4b84381eb0b47e3aaf/Microsoft.WindowsAzure.GuestAgent_Win7_asiaeast_manifest.xml</Uri>
+ <Uri>http://rdfepirv2hknprdstr04.blob.core.windows.net/bfd5c281a7dc4e4b84381eb0b47e3aaf/Microsoft.WindowsAzure.GuestAgent_Win7_asiaeast_manifest.xml</Uri>
+ </Uris>
+ </GAFamily>
+ </GAFamilies>
+</GuestAgentExtension>
+<Plugins>
+ <Plugin name="OSTCExtensions.ExampleHandlerLinux" version="1.2.0" location="http://rdfepirv2hknprdstr03.blob.core.windows.net/b01058962be54ceca550a390fa5ff064/Microsoft.OSTCExtensions_ExampleHandlerLinux_asiaeast_manifest.xml" config="" state="enabled" autoUpgrade="true" failoverlocation="http://rdfepirv2hknprdstr04.blob.core.windows.net/b01058962be54ceca550a390fa5ff064/Microsoft.OSTCExtensions_ExampleHandlerLinux_asiaeast_manifest.xml" runAsStartupTask="false" isJson="true" />
+</Plugins>
+<PluginSettings>
+ <Plugin name="OSTCExtensions.ExampleHandlerLinux" version="1.2.0">
+ <RuntimeSettings seqNo="0">{"runtimeSettings":[{"handlerSettings":{"protectedSettingsCertThumbprint":"4037FBF5F1F3014F99B5D6C7799E9B20E6871CB3","protectedSettings":"MIICWgYJK","publicSettings":{"foo":"bar"}}}]}</RuntimeSettings>
+ </Plugin>
+</PluginSettings>
+<StatusUploadBlob>https://yuezhatest.blob.core.windows.net/vhds/test-cs12.test-cs12.test-cs12.status?sr=b&amp;sp=rw&amp;se=9999-01-01&amp;sk=key1&amp;sv=2014-02-14&amp;sig=hfRh7gzUE7sUtYwke78IOlZOrTRCYvkec4hGZ9zZzXo%3D</StatusUploadBlob></Extensions>
+
diff --git a/tests/data/wire/ga_manifest.xml b/tests/data/wire/ga_manifest.xml
new file mode 100644
index 0000000..f43daf5
--- /dev/null
+++ b/tests/data/wire/ga_manifest.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<PluginVersionManifest xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
+ <Plugins>
+ <Plugin>
+ <Version>1.0.0</Version>
+ <Uris>
+ <Uri>http://foo.bar/zar/OSTCExtensions.WALinuxAgent__1.0.0</Uri>
+ </Uris>
+ </Plugin>
+ <Plugin>
+ <Version>1.1.0</Version>
+ <Uris>
+ <Uri>http://foo.bar/zar/OSTCExtensions.WALinuxAgent__1.1.0</Uri>
+ </Uris>
+ </Plugin>
+ <Plugin>
+ <Version>2.0.0</Version><Uris><Uri>http://host/OSTCExtensions.WALinuxAgent__2.0.0</Uri></Uris>
+ </Plugin>
+ <Plugin>
+ <Version>2.1.0</Version><Uris><Uri>http://host/OSTCExtensions.WALinuxAgent__2.1.0</Uri></Uris>
+ </Plugin>
+ <Plugin>
+ <Version>2.1.1</Version><Uris><Uri>http://host/OSTCExtensions.WALinuxAgent__2.1.1</Uri></Uris>
+ </Plugin>
+ <Plugin>
+ <Version>2.2.0</Version><Uris><Uri>http://host/OSTCExtensions.WALinuxAgent__2.2.0</Uri></Uris>
+ </Plugin>
+ <Plugin>
+ <Version>3.0</Version><Uris><Uri>http://host/OSTCExtensions.WALinuxAgent__3.0</Uri></Uris>
+ </Plugin>
+ <Plugin>
+ <Version>3.1</Version><Uris><Uri>http://host/OSTCExtensions.WALinuxAgent__3.1</Uri></Uris>
+ </Plugin>
+ <Plugin>
+ <Version>4.0.0.0</Version><Uris><Uri>http://host/OSTCExtensions.WALinuxAgent__3.0</Uri></Uris>
+ </Plugin>
+ <Plugin>
+ <Version>4.0.0.1</Version><Uris><Uri>http://host/OSTCExtensions.WALinuxAgent__3.1</Uri></Uris>
+ </Plugin>
+ <Plugin>
+ <Version>4.1.0.0</Version><Uris><Uri>http://host/OSTCExtensions.WALinuxAgent__3.1</Uri></Uris>
+ </Plugin>
+ <Plugin>
+ <Version>99999.0.0.0</Version><Uris><Uri>http://host/OSTCExtensions.WALinuxAgent__99999.0.0.0</Uri></Uris>
+ </Plugin>
+ </Plugins>
+</PluginVersionManifest>
+
diff --git a/tests/data/wire/manifest.xml b/tests/data/wire/manifest.xml
index 943755a..ff42b9d 100644
--- a/tests/data/wire/manifest.xml
+++ b/tests/data/wire/manifest.xml
@@ -2,17 +2,59 @@
<PluginVersionManifest xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Plugins>
<Plugin>
- <Version>1.0</Version>
+ <Version>1.0.0</Version>
<Uris>
- <Uri>http://foo.bar/zar/OSTCExtensions.ExampleHandlerLinux</Uri>
+ <Uri>http://foo.bar/zar/OSTCExtensions.ExampleHandlerLinux__1.0.0</Uri>
</Uris>
</Plugin>
<Plugin>
- <Version>1.1</Version>
+ <Version>1.1.0</Version>
<Uris>
- <Uri>http://foo.bar/zar/OSTCExtensions.ExampleHandlerLinux</Uri>
+ <Uri>http://foo.bar/zar/OSTCExtensions.ExampleHandlerLinux__1.1.0</Uri>
</Uris>
</Plugin>
+ <Plugin>
+ <Version>2.0.0</Version><Uris><Uri>http://host/OSTCExtensions.ExampleHandlerLinux__2.0.0</Uri></Uris>
+ </Plugin>
+ <Plugin>
+ <Version>2.1.0</Version><Uris><Uri>http://host/OSTCExtensions.ExampleHandlerLinux__2.1.0</Uri></Uris>
+ <DisallowMajorVersionUpgrade>True</DisallowMajorVersionUpgrade>
+ </Plugin>
+ <Plugin>
+ <Version>2.1.1</Version><Uris><Uri>http://host/OSTCExtensions.ExampleHandlerLinux__2.1.1</Uri></Uris>
+ </Plugin>
+ <Plugin>
+ <Version>2.2.0</Version><Uris><Uri>http://host/OSTCExtensions.ExampleHandlerLinux__2.2.0</Uri></Uris>
+ </Plugin>
+ <Plugin>
+ <Version>3.0</Version><Uris><Uri>http://host/OSTCExtensions.ExampleHandlerLinux__3.0</Uri></Uris>
+ </Plugin>
+ <Plugin>
+ <Version>3.1</Version><Uris><Uri>http://host/OSTCExtensions.ExampleHandlerLinux__3.1</Uri></Uris>
+ </Plugin>
+ <Plugin>
+ <Version>4.0.0.0</Version><Uris><Uri>http://host/OSTCExtensions.ExampleHandlerLinux__3.0</Uri></Uris>
+ </Plugin>
+ <Plugin>
+ <Version>4.0.0.1</Version><Uris><Uri>http://host/OSTCExtensions.ExampleHandlerLinux__3.1</Uri></Uris>
+ </Plugin>
+ <Plugin>
+ <Version>4.1.0.0</Version><Uris><Uri>http://host/OSTCExtensions.ExampleHandlerLinux__3.1</Uri></Uris>
+ </Plugin>
</Plugins>
+ <InternalPlugins>
+ <Plugin>
+ <Version>1.2.0</Version>
+ <Uris>
+ <Uri>http://foo.bar/zar/OSTCExtensions.ExampleHandlerLinux__1.2.0</Uri>
+ </Uris>
+ </Plugin>
+ <Plugin>
+ <Version>2.3.0</Version><Uris><Uri>http://host/OSTCExtensions.ExampleHandlerLinux__2.3.0</Uri></Uris>
+ </Plugin>
+ <Plugin>
+ <Version>2.4.0</Version><Uris><Uri>http://host/OSTCExtensions.ExampleHandlerLinux__2.3.0</Uri></Uris>
+ </Plugin>
+ </InternalPlugins>
</PluginVersionManifest>
diff --git a/tests/distro/__init__.py b/tests/distro/__init__.py
index 9bdb27e..2ef4c16 100644
--- a/tests/distro/__init__.py
+++ b/tests/distro/__init__.py
@@ -14,6 +14,3 @@
#
# Requires Python 2.4+ and Openssl 1.0+
#
-# Implements parts of RFC 2131, 1541, 1497 and
-# http://msdn.microsoft.com/en-us/library/cc227282%28PROT.10%29.aspx
-# http://msdn.microsoft.com/en-us/library/cc227259%28PROT.13%29.aspx
diff --git a/tests/distro/test_loader.py b/tests/distro/test_resourceDisk.py
index 94ca913..198fd49 100644
--- a/tests/distro/test_loader.py
+++ b/tests/distro/test_resourceDisk.py
@@ -19,18 +19,24 @@
# http://msdn.microsoft.com/en-us/library/cc227259%28PROT.13%29.aspx
from tests.tools import *
-from azurelinuxagent.distro.loader import get_distro
-from azurelinuxagent.distro.default.distro import DefaultDistro
+from azurelinuxagent.daemon.resourcedisk import get_resourcedisk_handler
-class TestDistroLoader(AgentTestCase):
+class TestResourceDisk(AgentTestCase):
+ def test_mkfile(self):
+ # setup
+ test_file = os.path.join(self.tmp_dir, 'test_file')
+ file_size = 1024 * 128
+ if os.path.exists(test_file):
+ os.remove(test_file)
- @distros()
- def test_distro_loader(self, *distro_args):
- distro = get_distro(*distro_args)
- self.assertNotEquals(None, distro)
- self.assertNotEquals(DefaultDistro, type(distro))
-
+ # execute
+ get_resourcedisk_handler().mkfile(test_file, file_size)
+
+ # assert
+ assert os.path.exists(test_file)
+
+ # cleanup
+ os.remove(test_file)
if __name__ == '__main__':
unittest.main()
-
diff --git a/tests/distro/test_scvmm.py b/tests/distro/test_scvmm.py
new file mode 100644
index 0000000..2437170
--- /dev/null
+++ b/tests/distro/test_scvmm.py
@@ -0,0 +1,84 @@
+# Copyright 2014 Microsoft Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Requires Python 2.4+ and Openssl 1.0+
+#
+# Implements parts of RFC 2131, 1541, 1497 and
+# http://msdn.microsoft.com/en-us/library/cc227282%28PROT.10%29.aspx
+# http://msdn.microsoft.com/en-us/library/cc227259%28PROT.13%29.aspx
+
+import mock
+from tests.tools import *
+
+import azurelinuxagent.daemon.scvmm as scvmm
+from azurelinuxagent.daemon.main import *
+from azurelinuxagent.common.osutil.default import DefaultOSUtil
+
+class TestSCVMM(AgentTestCase):
+ def test_scvmm_detection_with_file(self):
+ # setup
+ conf.get_dvd_mount_point = Mock(return_value=self.tmp_dir)
+ conf.get_detect_scvmm_env = Mock(return_value=True)
+ scvmm_file = os.path.join(self.tmp_dir, scvmm.VMM_CONF_FILE_NAME)
+ fileutil.write_file(scvmm_file, "")
+
+ with patch.object(scvmm.ScvmmHandler, 'start_scvmm_agent') as po:
+ with patch('os.listdir', return_value=["sr0", "sr1", "sr2"]):
+ with patch('time.sleep', return_value=0):
+ # execute
+ failed = False
+ try:
+ scvmm.get_scvmm_handler().run()
+ except:
+ failed = True
+ # assert
+ self.assertTrue(failed)
+ self.assertTrue(po.call_count == 1)
+ # cleanup
+ os.remove(scvmm_file)
+
+
+ def test_scvmm_detection_with_multiple_cdroms(self):
+ # setup
+ conf.get_dvd_mount_point = Mock(return_value=self.tmp_dir)
+ conf.get_detect_scvmm_env = Mock(return_value=True)
+
+ # execute
+ with mock.patch.object(DefaultOSUtil, 'mount_dvd') as patch_mount:
+ with patch('os.listdir', return_value=["sr0", "sr1", "sr2"]):
+ scvmm.ScvmmHandler().detect_scvmm_env()
+ # assert
+ assert patch_mount.call_count == 3
+ assert patch_mount.call_args_list[0][1]['dvd_device'] == '/dev/sr0'
+ assert patch_mount.call_args_list[1][1]['dvd_device'] == '/dev/sr1'
+ assert patch_mount.call_args_list[2][1]['dvd_device'] == '/dev/sr2'
+
+
+ def test_scvmm_detection_without_file(self):
+ # setup
+ conf.get_dvd_mount_point = Mock(return_value=self.tmp_dir)
+ conf.get_detect_scvmm_env = Mock(return_value=True)
+ scvmm_file = os.path.join(self.tmp_dir, scvmm.VMM_CONF_FILE_NAME)
+ if os.path.exists(scvmm_file):
+ os.remove(scvmm_file)
+
+ with mock.patch.object(scvmm.ScvmmHandler, 'start_scvmm_agent') as patch_start:
+ # execute
+ scvmm.ScvmmHandler().detect_scvmm_env()
+ # assert
+ patch_start.assert_not_called()
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/ga/__init__.py b/tests/ga/__init__.py
new file mode 100644
index 0000000..2ef4c16
--- /dev/null
+++ b/tests/ga/__init__.py
@@ -0,0 +1,16 @@
+# Copyright 2014 Microsoft Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Requires Python 2.4+ and Openssl 1.0+
+#
diff --git a/tests/distro/test_extension.py b/tests/ga/test_extension.py
index d0b631f..71c219c 100644
--- a/tests/distro/test_extension.py
+++ b/tests/ga/test_extension.py
@@ -14,20 +14,15 @@
#
# Requires Python 2.4+ and Openssl 1.0+
#
-# Implements parts of RFC 2131, 1541, 1497 and
-# http://msdn.microsoft.com/en-us/library/cc227282%28PROT.10%29.aspx
-# http://msdn.microsoft.com/en-us/library/cc227259%28PROT.13%29.aspx
-from tests.tools import *
from tests.protocol.mockwiredata import *
-from azurelinuxagent.exception import *
-from azurelinuxagent.distro.loader import get_distro
-from azurelinuxagent.protocol.restapi import get_properties
-from azurelinuxagent.protocol.wire import WireProtocol
-
-@patch("time.sleep")
-@patch("azurelinuxagent.protocol.wire.CryptUtil")
-@patch("azurelinuxagent.utils.restutil.http_get")
+from azurelinuxagent.common.exception import *
+from azurelinuxagent.common.protocol import get_protocol_util
+from azurelinuxagent.ga.exthandlers import *
+from azurelinuxagent.common.protocol.wire import WireProtocol
+
+@patch("azurelinuxagent.common.protocol.wire.CryptUtil")
+@patch("azurelinuxagent.common.utils.restutil.http_get")
class TestExtension(AgentTestCase):
def _assert_handler_status(self, report_vm_status, expected_status,
@@ -42,17 +37,19 @@ class TestExtension(AgentTestCase):
handler_status.name)
self.assertEquals(version, handler_status.version)
self.assertEquals(expected_ext_count, len(handler_status.extensions))
+ return
def _assert_no_handler_status(self, report_vm_status):
self.assertTrue(report_vm_status.called)
args, kw = report_vm_status.call_args
vm_status = args[0]
self.assertEquals(0, len(vm_status.vmAgent.extensionHandlers))
+ return
+
+ def _create_mock(self, test_data, mock_http_get, MockCryptUtil):
+ """Test enable/disable/uninstall of an extension"""
+ handler = get_exthandlers_handler()
- def _create_mock(self, test_data, mock_http_get, MockCryptUtil, _):
- """Test enable/disable/unistall of an extension"""
- distro = get_distro()
-
#Mock protocol to return test data
mock_http_get.side_effect = test_data.mock_http_get
MockCryptUtil.side_effect = test_data.mock_crypt_util
@@ -61,104 +58,104 @@ class TestExtension(AgentTestCase):
protocol.detect()
protocol.report_ext_status = MagicMock()
protocol.report_vm_status = MagicMock()
- distro.protocol_util.get_protocol = Mock(return_value=protocol)
-
- return distro, protocol
+
+ handler.protocol_util.get_protocol = Mock(return_value=protocol)
+ return handler, protocol
def test_ext_handler(self, *args):
test_data = WireProtocolData(DATA_FILE)
- distro, protocol = self._create_mock(test_data, *args)
+ exthandlers_handler, protocol = self._create_mock(test_data, *args)
#Test enable scenario.
- distro.ext_handlers_handler.run()
- self._assert_handler_status(protocol.report_vm_status, "Ready", 1, "1.0")
+ exthandlers_handler.run()
+ self._assert_handler_status(protocol.report_vm_status, "Ready", 1, "1.0.0")
self._assert_ext_status(protocol.report_ext_status, "success", 0)
#Test goal state not changed
- distro.ext_handlers_handler.run()
- self._assert_handler_status(protocol.report_vm_status, "Ready", 1, "1.0")
+ exthandlers_handler.run()
+ self._assert_handler_status(protocol.report_vm_status, "Ready", 1, "1.0.0")
#Test goal state changed
test_data.goal_state = test_data.goal_state.replace("<Incarnation>1<",
"<Incarnation>2<")
test_data.ext_conf = test_data.ext_conf.replace("seqNo=\"0\"",
"seqNo=\"1\"")
- distro.ext_handlers_handler.run()
- self._assert_handler_status(protocol.report_vm_status, "Ready", 1, "1.0")
+ exthandlers_handler.run()
+ self._assert_handler_status(protocol.report_vm_status, "Ready", 1, "1.0.0")
self._assert_ext_status(protocol.report_ext_status, "success", 1)
#Test upgrade
test_data.goal_state = test_data.goal_state.replace("<Incarnation>2<",
"<Incarnation>3<")
- test_data.ext_conf = test_data.ext_conf.replace("1.0", "1.1")
+ test_data.ext_conf = test_data.ext_conf.replace("1.0.0", "1.1.0")
test_data.ext_conf = test_data.ext_conf.replace("seqNo=\"1\"",
"seqNo=\"2\"")
- distro.ext_handlers_handler.run()
- self._assert_handler_status(protocol.report_vm_status, "Ready", 1, "1.1")
+ exthandlers_handler.run()
+ self._assert_handler_status(protocol.report_vm_status, "Ready", 1, "1.1.0")
self._assert_ext_status(protocol.report_ext_status, "success", 2)
#Test disable
test_data.goal_state = test_data.goal_state.replace("<Incarnation>3<",
"<Incarnation>4<")
test_data.ext_conf = test_data.ext_conf.replace("enabled", "disabled")
- distro.ext_handlers_handler.run()
+ exthandlers_handler.run()
self._assert_handler_status(protocol.report_vm_status, "NotReady",
- 1, "1.1")
+ 1, "1.1.0")
#Test uninstall
test_data.goal_state = test_data.goal_state.replace("<Incarnation>4<",
"<Incarnation>5<")
test_data.ext_conf = test_data.ext_conf.replace("disabled", "uninstall")
- distro.ext_handlers_handler.run()
+ exthandlers_handler.run()
self._assert_no_handler_status(protocol.report_vm_status)
#Test uninstall again!
test_data.goal_state = test_data.goal_state.replace("<Incarnation>5<",
"<Incarnation>6<")
- distro.ext_handlers_handler.run()
+ exthandlers_handler.run()
self._assert_no_handler_status(protocol.report_vm_status)
def test_ext_handler_no_settings(self, *args):
test_data = WireProtocolData(DATA_FILE_EXT_NO_SETTINGS)
- distro, protocol = self._create_mock(test_data, *args)
+ exthandlers_handler, protocol = self._create_mock(test_data, *args)
- distro.ext_handlers_handler.run()
- self._assert_handler_status(protocol.report_vm_status, "Ready", 0, "1.0")
+ exthandlers_handler.run()
+ self._assert_handler_status(protocol.report_vm_status, "Ready", 0, "1.0.0")
def test_ext_handler_no_public_settings(self, *args):
test_data = WireProtocolData(DATA_FILE_EXT_NO_PUBLIC)
- distro, protocol = self._create_mock(test_data, *args)
+ exthandlers_handler, protocol = self._create_mock(test_data, *args)
- distro.ext_handlers_handler.run()
- self._assert_handler_status(protocol.report_vm_status, "Ready", 1, "1.0")
+ exthandlers_handler.run()
+ self._assert_handler_status(protocol.report_vm_status, "Ready", 1, "1.0.0")
def test_ext_handler_no_ext(self, *args):
test_data = WireProtocolData(DATA_FILE_NO_EXT)
- distro, protocol = self._create_mock(test_data, *args)
+ exthandlers_handler, protocol = self._create_mock(test_data, *args)
#Assert no extension handler status
- distro.ext_handlers_handler.run()
+ exthandlers_handler.run()
self._assert_no_handler_status(protocol.report_vm_status)
- @patch('azurelinuxagent.distro.default.extension.add_event')
+ @patch('azurelinuxagent.ga.exthandlers.add_event')
def test_ext_handler_download_failure(self, mock_add_event, *args):
test_data = WireProtocolData(DATA_FILE)
- distro, protocol = self._create_mock(test_data, *args)
+ exthandlers_handler, protocol = self._create_mock(test_data, *args)
protocol.download_ext_handler_pkg = Mock(side_effect=ProtocolError)
- distro.ext_handlers_handler.run()
+ exthandlers_handler.run()
args, kw = mock_add_event.call_args
self.assertEquals(False, kw['is_success'])
self.assertEquals("OSTCExtensions.ExampleHandlerLinux", kw['name'])
self.assertEquals("Download", kw['op'])
- @patch('azurelinuxagent.distro.default.extension.fileutil')
+ @patch('azurelinuxagent.ga.exthandlers.fileutil')
def test_ext_handler_io_error(self, mock_fileutil, *args):
test_data = WireProtocolData(DATA_FILE)
- distro, protocol = self._create_mock(test_data, *args)
+ exthandlers_handler, protocol = self._create_mock(test_data, *args)
mock_fileutil.write_file.return_value = IOError("Mock IO Error")
- distro.ext_handlers_handler.run()
+ exthandlers_handler.run()
def _assert_ext_status(self, report_ext_status, expected_status,
expected_seq_no):
@@ -170,21 +167,96 @@ class TestExtension(AgentTestCase):
def test_ext_handler_no_reporting_status(self, *args):
test_data = WireProtocolData(DATA_FILE)
- distro, protocol = self._create_mock(test_data, *args)
- distro.ext_handlers_handler.run()
- self._assert_handler_status(protocol.report_vm_status, "Ready", 1, "1.0")
+ exthandlers_handler, protocol = self._create_mock(test_data, *args)
+ exthandlers_handler.run()
+ self._assert_handler_status(protocol.report_vm_status, "Ready", 1, "1.0.0")
#Remove status file and re-run collecting extension status
status_file = os.path.join(self.tmp_dir,
- "OSTCExtensions.ExampleHandlerLinux-1.0",
+ "OSTCExtensions.ExampleHandlerLinux-1.0.0",
"status", "0.status")
self.assertTrue(os.path.isfile(status_file))
os.remove(status_file)
- distro.ext_handlers_handler.run()
- self._assert_handler_status(protocol.report_vm_status, "Ready", 1, "1.0")
+ exthandlers_handler.run()
+ self._assert_handler_status(protocol.report_vm_status, "Ready", 1, "1.0.0")
self._assert_ext_status(protocol.report_ext_status, "error", 0)
+ def test_ext_handler_version_decide_autoupgrade_internalversion(self, *args):
+ for internal in [False, True]:
+ for autoupgrade in [False, True]:
+ if internal:
+ config_version = '1.2.0'
+ decision_version = '1.2.0'
+ if autoupgrade:
+ datafile = DATA_FILE_EXT_AUTOUPGRADE_INTERNALVERSION
+ else:
+ datafile = DATA_FILE_EXT_INTERNALVERSION
+ else:
+ config_version = '1.0.0'
+ if autoupgrade:
+ datafile = DATA_FILE_EXT_AUTOUPGRADE
+ decision_version = '1.1.0'
+ else:
+ datafile = DATA_FILE
+ decision_version = '1.0.0'
+
+ _, protocol = self._create_mock(WireProtocolData(datafile), *args)
+ ext_handlers, _ = protocol.get_ext_handlers()
+ self.assertEqual(1, len(ext_handlers.extHandlers))
+ ext_handler = ext_handlers.extHandlers[0]
+ self.assertEqual('OSTCExtensions.ExampleHandlerLinux', ext_handler.name)
+ self.assertEqual(config_version, ext_handler.properties.version, "config version.")
+ ExtHandlerInstance(ext_handler, protocol).decide_version()
+ self.assertEqual(decision_version, ext_handler.properties.version, "decision version.")
+
+ def test_ext_handler_version_decide_between_minor_versions(self, *args):
+ """
+ Using v2.x~v4.x for unit testing
+ Available versions via manifest XML (I stands for internal):
+ 2.0.0, 2.1.0, 2.1.1, 2.2.0, 2.3.0(I), 2.4.0(I), 3.0, 3.1, 4.0.0.0, 4.0.0.1, 4.1.0.0
+ See tests/data/wire/manifest.xml for possible versions
+ """
+
+ # (installed_version, config_version, exptected_version, autoupgrade_expected_version)
+ cases = [
+ (None, '2.0', '2.0.0', '2.2.0'),
+ (None, '2.0.0', '2.0.0', '2.2.0'),
+ ('1.0', '1.0.0', '1.0.0', '1.1.0'),
+ (None, '2.1.0', '2.1.1', '2.2.0'),
+ (None, '2.2.0', '2.2.0', '2.2.0'),
+ (None, '2.3.0', '2.3.0', '2.3.0'),
+ (None, '2.4.0', '2.4.0', '2.4.0'),
+ (None, '3.0', '3.0', '3.1'),
+ (None, '4.0', '4.0.0.1', '4.1.0.0'),
+ ]
+
+ _, protocol = self._create_mock(WireProtocolData(DATA_FILE), *args)
+ version_uri = Mock()
+ version_uri.uri = 'http://some/Microsoft.OSTCExtensions_ExampleHandlerLinux_asiaeast_manifest.xml'
+
+ for (installed_version, config_version, expected_version, autoupgrade_expected_version) in cases:
+ ext_handler = Mock()
+ ext_handler.properties = Mock()
+ ext_handler.name = 'OSTCExtensions.ExampleHandlerLinux'
+ ext_handler.versionUris = [version_uri]
+ ext_handler.properties.version = config_version
+
+ ext_handler_instance = ExtHandlerInstance(ext_handler, protocol)
+ ext_handler_instance.get_installed_version = Mock(return_value=installed_version)
+
+ ext_handler_instance.decide_version()
+ self.assertEqual(expected_version, ext_handler.properties.version)
+
+ ext_handler.properties.version = config_version
+ ext_handler.properties.upgradePolicy = 'auto'
+
+ ext_handler_instance = ExtHandlerInstance(ext_handler, protocol)
+ ext_handler_instance.get_installed_version = Mock(return_value=installed_version)
+
+ ext_handler_instance.decide_version()
+ self.assertEqual(autoupgrade_expected_version, ext_handler.properties.version)
+
if __name__ == '__main__':
unittest.main()
diff --git a/tests/distro/test_monitor.py b/tests/ga/test_monitor.py
index 1dd7740..838d037 100644
--- a/tests/distro/test_monitor.py
+++ b/tests/ga/test_monitor.py
@@ -14,13 +14,10 @@
#
# Requires Python 2.4+ and Openssl 1.0+
#
-# Implements parts of RFC 2131, 1541, 1497 and
-# http://msdn.microsoft.com/en-us/library/cc227282%28PROT.10%29.aspx
-# http://msdn.microsoft.com/en-us/library/cc227259%28PROT.13%29.aspx
from tests.tools import *
-from azurelinuxagent.exception import *
-from azurelinuxagent.distro.default.monitor import *
+from azurelinuxagent.common.exception import *
+from azurelinuxagent.ga.monitor import *
class TestMonitor(AgentTestCase):
def test_parse_xml_event(self):
diff --git a/tests/ga/test_update.py b/tests/ga/test_update.py
new file mode 100644
index 0000000..74804fb
--- /dev/null
+++ b/tests/ga/test_update.py
@@ -0,0 +1,1135 @@
+# Copyright 2014 Microsoft Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Requires Python 2.4+ and Openssl 1.0+
+#
+
+from __future__ import print_function
+
+import copy
+import glob
+import json
+import os
+import platform
+import random
+import subprocess
+import sys
+import tempfile
+import zipfile
+
+from tests.protocol.mockwiredata import *
+from tests.tools import *
+
+import azurelinuxagent.common.logger as logger
+import azurelinuxagent.common.utils.fileutil as fileutil
+
+from azurelinuxagent.common.exception import UpdateError
+from azurelinuxagent.common.protocol.restapi import *
+from azurelinuxagent.common.protocol.wire import *
+from azurelinuxagent.common.utils.flexible_version import FlexibleVersion
+from azurelinuxagent.common.version import AGENT_NAME, AGENT_VERSION
+from azurelinuxagent.ga.update import *
+
+NO_ERROR = {
+ "last_failure" : 0.0,
+ "failure_count" : 0,
+ "was_fatal" : False
+}
+
+WITH_ERROR = {
+ "last_failure" : 42.42,
+ "failure_count" : 2,
+ "was_fatal" : False
+}
+
+EMPTY_MANIFEST = {
+ "name": "WALinuxAgent",
+ "version": 1.0,
+ "handlerManifest": {
+ "installCommand": "",
+ "uninstallCommand": "",
+ "updateCommand": "",
+ "enableCommand": "",
+ "disableCommand": "",
+ "rebootAfterInstall": False,
+ "reportHeartbeat": False
+ }
+}
+
+
+def get_agent_pkgs(in_dir=os.path.join(data_dir, "ga")):
+ path = os.path.join(in_dir, AGENT_PKG_GLOB)
+ return glob.glob(path)
+
+
+def get_agents(in_dir=os.path.join(data_dir, "ga")):
+ path = os.path.join(in_dir, AGENT_DIR_GLOB)
+ return [a for a in glob.glob(path) if os.path.isdir(a)]
+
+
+def get_agent_file_path():
+ return get_agent_pkgs()[0]
+
+
+def get_agent_file_name():
+ return os.path.basename(get_agent_file_path())
+
+
+def get_agent_path():
+ return fileutil.trim_ext(get_agent_file_path(), "zip")
+
+
+def get_agent_name():
+ return os.path.basename(get_agent_path())
+
+
+def get_agent_version():
+ return FlexibleVersion(get_agent_name().split("-")[1])
+
+
+def faux_logger():
+ print("STDOUT message")
+ print("STDERR message", file=sys.stderr)
+ return DEFAULT
+
+
+class UpdateTestCase(AgentTestCase):
+ def setUp(self):
+ AgentTestCase.setUp(self)
+ return
+
+ def agent_bin(self, version):
+ return "bin/{0}-{1}.egg".format(AGENT_NAME, version)
+
+ def agent_count(self):
+ return len(self.agent_dirs())
+
+ def agent_dirs(self):
+ return get_agents(in_dir=self.tmp_dir)
+
+ def agent_dir(self, version):
+ return os.path.join(self.tmp_dir, "{0}-{1}".format(AGENT_NAME, version))
+
+ def agent_paths(self):
+ paths = glob.glob(os.path.join(self.tmp_dir, "*"))
+ paths.sort()
+ return paths
+
+ def agent_pkgs(self):
+ return get_agent_pkgs(in_dir=self.tmp_dir)
+
+ def agent_versions(self):
+ v = [FlexibleVersion(AGENT_DIR_PATTERN.match(a).group(1)) for a in self.agent_dirs()]
+ v.sort(reverse=True)
+ return v
+
+ def get_error_file(self, error_data=NO_ERROR):
+ fp = tempfile.NamedTemporaryFile(mode="w")
+ json.dump(error_data if error_data is not None else NO_ERROR, fp)
+ fp.seek(0)
+ return fp
+
+ def create_error(self, error_data=NO_ERROR):
+ with self.get_error_file(error_data) as path:
+ return GuestAgentError(path.name)
+
+ def copy_agents(self, *agents):
+ if len(agents) <= 0:
+ agents = get_agent_pkgs()
+ for agent in agents:
+ fileutil.copy_file(agent, to_dir=self.tmp_dir)
+ return
+
+ def expand_agents(self):
+ for agent in self.agent_pkgs():
+ zipfile.ZipFile(agent).extractall(os.path.join(
+ self.tmp_dir,
+ fileutil.trim_ext(agent, "zip")))
+ return
+
+ def prepare_agents(self, base_version=AGENT_VERSION, count=5, is_available=True):
+ base_v = FlexibleVersion(base_version)
+
+ # Ensure the test data is copied over
+ agent_count = self.agent_count()
+ if agent_count <= 0:
+ self.copy_agents(get_agent_pkgs()[0])
+ self.expand_agents()
+ count -= 1
+
+ # Determine the most recent agent version
+ versions = self.agent_versions()
+ src_v = FlexibleVersion(str(versions[0]))
+
+ # If the most recent agent is newer the minimum requested, use the agent version
+ if base_v < src_v:
+ base_v = src_v
+
+ # Create agent packages and directories
+ return self.replicate_agents(
+ src_v=src_v,
+ count=count-agent_count,
+ is_available=is_available)
+
+ def remove_agents(self):
+ for agent in self.agent_paths():
+ try:
+ if os.path.isfile(agent):
+ os.remove(agent)
+ else:
+ shutil.rmtree(agent)
+ except:
+ pass
+ return
+
+ def replicate_agents(
+ self,
+ count=5,
+ src_v=AGENT_VERSION,
+ is_available=True,
+ increment=1):
+ from_path = self.agent_dir(src_v)
+ dst_v = FlexibleVersion(str(src_v))
+ for i in range(0,count):
+ dst_v += increment
+ to_path = self.agent_dir(dst_v)
+ shutil.copyfile(from_path + ".zip", to_path + ".zip")
+ shutil.copytree(from_path, to_path)
+ shutil.move(
+ os.path.join(to_path, self.agent_bin(src_v)),
+ os.path.join(to_path, self.agent_bin(dst_v)))
+ if not is_available:
+ GuestAgent(to_path).mark_failure(is_fatal=True)
+
+ return dst_v
+
+
+class TestGuestAgentError(UpdateTestCase):
+ def test_creation(self):
+ self.assertRaises(TypeError, GuestAgentError)
+ self.assertRaises(UpdateError, GuestAgentError, None)
+
+ with self.get_error_file(error_data=WITH_ERROR) as path:
+ err = GuestAgentError(path.name)
+ self.assertEqual(path.name, err.path)
+ self.assertNotEqual(None, err)
+
+ self.assertEqual(WITH_ERROR["last_failure"], err.last_failure)
+ self.assertEqual(WITH_ERROR["failure_count"], err.failure_count)
+ self.assertEqual(WITH_ERROR["was_fatal"], err.was_fatal)
+ return
+
+ def test_clear(self):
+ with self.get_error_file(error_data=WITH_ERROR) as path:
+ err = GuestAgentError(path.name)
+ self.assertEqual(path.name, err.path)
+ self.assertNotEqual(None, err)
+
+ err.clear()
+ self.assertEqual(NO_ERROR["last_failure"], err.last_failure)
+ self.assertEqual(NO_ERROR["failure_count"], err.failure_count)
+ self.assertEqual(NO_ERROR["was_fatal"], err.was_fatal)
+ return
+
+ def test_load_preserves_error_state(self):
+ with self.get_error_file(error_data=WITH_ERROR) as path:
+ err = GuestAgentError(path.name)
+ self.assertEqual(path.name, err.path)
+ self.assertNotEqual(None, err)
+
+ with self.get_error_file(error_data=NO_ERROR):
+ err.load()
+ self.assertEqual(WITH_ERROR["last_failure"], err.last_failure)
+ self.assertEqual(WITH_ERROR["failure_count"], err.failure_count)
+ self.assertEqual(WITH_ERROR["was_fatal"], err.was_fatal)
+ return
+
+ def test_save(self):
+ err1 = self.create_error()
+ err1.mark_failure()
+ err1.mark_failure(is_fatal=True)
+
+ err2 = self.create_error(err1.to_json())
+ self.assertEqual(err1.last_failure, err2.last_failure)
+ self.assertEqual(err1.failure_count, err2.failure_count)
+ self.assertEqual(err1.was_fatal, err2.was_fatal)
+
+ def test_mark_failure(self):
+ err = self.create_error()
+ self.assertFalse(err.is_blacklisted)
+
+ for i in range(0, MAX_FAILURE):
+ err.mark_failure()
+
+ # 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):
+ err = self.create_error()
+
+ self.assertFalse(err.is_blacklisted)
+
+ # Fatal errors immediately blacklist
+ err.mark_failure(is_fatal=True)
+ self.assertTrue(err.is_blacklisted)
+ self.assertTrue(err.failure_count < MAX_FAILURE)
+ return
+
+ def test_str(self):
+ err = self.create_error(error_data=NO_ERROR)
+ s = "Last Failure: {0}, Total Failures: {1}, Fatal: {2}".format(
+ NO_ERROR["last_failure"],
+ NO_ERROR["failure_count"],
+ NO_ERROR["was_fatal"])
+ self.assertEqual(s, str(err))
+
+ err = self.create_error(error_data=WITH_ERROR)
+ s = "Last Failure: {0}, Total Failures: {1}, Fatal: {2}".format(
+ WITH_ERROR["last_failure"],
+ WITH_ERROR["failure_count"],
+ WITH_ERROR["was_fatal"])
+ self.assertEqual(s, str(err))
+ return
+
+
+class TestGuestAgent(UpdateTestCase):
+ def setUp(self):
+ UpdateTestCase.setUp(self)
+ self.copy_agents(get_agent_file_path())
+ self.agent_path = os.path.join(self.tmp_dir, get_agent_name())
+ return
+
+ def tearDown(self):
+ self.remove_agents()
+ return
+
+ def test_creation(self):
+ self.assertRaises(UpdateError, GuestAgent, "A very bad file name")
+ n = "{0}-a.bad.version".format(AGENT_NAME)
+ self.assertRaises(UpdateError, GuestAgent, n)
+
+ agent = GuestAgent(path=self.agent_path)
+ self.assertNotEqual(None, agent)
+ self.assertEqual(get_agent_name(), agent.name)
+ self.assertEqual(get_agent_version(), agent.version)
+
+ self.assertEqual(self.agent_path, agent.get_agent_dir())
+
+ path = os.path.join(self.agent_path, AGENT_MANIFEST_FILE)
+ self.assertEqual(path, agent.get_agent_manifest_path())
+
+ self.assertEqual(
+ os.path.join(self.agent_path, AGENT_ERROR_FILE),
+ agent.get_agent_error_file())
+
+ path = ".".join((os.path.join(conf.get_lib_dir(), get_agent_name()), "zip"))
+ self.assertEqual(path, agent.get_agent_pkg_path())
+
+ self.assertTrue(agent.is_downloaded)
+ # Note: Agent will get blacklisted since the package for this test is invalid
+ self.assertTrue(agent.is_blacklisted)
+ self.assertFalse(agent.is_available)
+ return
+
+ @patch("azurelinuxagent.ga.update.GuestAgent._ensure_downloaded")
+ def test_clear_error(self, mock_ensure):
+ agent = GuestAgent(path=self.agent_path)
+ agent.mark_failure(is_fatal=True)
+
+ self.assertTrue(agent.error.last_failure > 0.0)
+ self.assertEqual(1, agent.error.failure_count)
+ self.assertTrue(agent.is_blacklisted)
+ self.assertEqual(agent.is_blacklisted, agent.error.is_blacklisted)
+
+ agent.clear_error()
+ self.assertEqual(0.0, agent.error.last_failure)
+ self.assertEqual(0, agent.error.failure_count)
+ self.assertFalse(agent.is_blacklisted)
+ self.assertEqual(agent.is_blacklisted, agent.error.is_blacklisted)
+ return
+
+ @patch("azurelinuxagent.ga.update.GuestAgent._ensure_downloaded")
+ def test_is_available(self, mock_ensure):
+ agent = GuestAgent(path=self.agent_path)
+
+ self.assertFalse(agent.is_available)
+ agent._unpack()
+ self.assertTrue(agent.is_available)
+
+ agent.mark_failure(is_fatal=True)
+ self.assertFalse(agent.is_available)
+ return
+
+ @patch("azurelinuxagent.ga.update.GuestAgent._ensure_downloaded")
+ def test_is_blacklisted(self, mock_ensure):
+ agent = GuestAgent(path=self.agent_path)
+ self.assertFalse(agent.is_blacklisted)
+
+ agent._unpack()
+ self.assertFalse(agent.is_blacklisted)
+ self.assertEqual(agent.is_blacklisted, agent.error.is_blacklisted)
+
+ agent.mark_failure(is_fatal=True)
+ self.assertTrue(agent.is_blacklisted)
+ self.assertEqual(agent.is_blacklisted, agent.error.is_blacklisted)
+ return
+
+ @patch("azurelinuxagent.ga.update.GuestAgent._ensure_downloaded")
+ def test_is_downloaded(self, mock_ensure):
+ agent = GuestAgent(path=self.agent_path)
+ self.assertFalse(agent.is_downloaded)
+ agent._unpack()
+ self.assertTrue(agent.is_downloaded)
+ return
+
+ @patch("azurelinuxagent.ga.update.GuestAgent._ensure_downloaded")
+ def test_mark_failure(self, mock_ensure):
+ agent = GuestAgent(path=self.agent_path)
+ agent.mark_failure()
+ self.assertEqual(1, agent.error.failure_count)
+
+ agent.mark_failure(is_fatal=True)
+ self.assertEqual(2, agent.error.failure_count)
+ self.assertTrue(agent.is_blacklisted)
+ return
+
+ @patch("azurelinuxagent.ga.update.GuestAgent._ensure_downloaded")
+ def test_unpack(self, mock_ensure):
+ agent = GuestAgent(path=self.agent_path)
+ self.assertFalse(os.path.isdir(agent.get_agent_dir()))
+ agent._unpack()
+ self.assertTrue(os.path.isdir(agent.get_agent_dir()))
+ self.assertTrue(os.path.isfile(agent.get_agent_manifest_path()))
+ return
+
+ @patch("azurelinuxagent.ga.update.GuestAgent._ensure_downloaded")
+ def test_unpack_fail(self, mock_ensure):
+ agent = GuestAgent(path=self.agent_path)
+ self.assertFalse(os.path.isdir(agent.get_agent_dir()))
+ os.remove(agent.get_agent_pkg_path())
+ self.assertRaises(UpdateError, agent._unpack)
+ return
+
+ @patch("azurelinuxagent.ga.update.GuestAgent._ensure_downloaded")
+ def test_load_manifest(self, mock_ensure):
+ agent = GuestAgent(path=self.agent_path)
+ agent._unpack()
+ agent._load_manifest()
+ self.assertEqual(agent.manifest.get_enable_command(), agent.get_agent_cmd())
+ return
+
+ @patch("azurelinuxagent.ga.update.GuestAgent._ensure_downloaded")
+ def test_load_manifest_missing(self, mock_ensure):
+ agent = GuestAgent(path=self.agent_path)
+ self.assertFalse(os.path.isdir(agent.get_agent_dir()))
+ agent._unpack()
+ os.remove(agent.get_agent_manifest_path())
+ self.assertRaises(UpdateError, agent._load_manifest)
+ return
+
+ @patch("azurelinuxagent.ga.update.GuestAgent._ensure_downloaded")
+ def test_load_manifest_is_empty(self, mock_ensure):
+ agent = GuestAgent(path=self.agent_path)
+ self.assertFalse(os.path.isdir(agent.get_agent_dir()))
+ agent._unpack()
+ self.assertTrue(os.path.isfile(agent.get_agent_manifest_path()))
+
+ with open(agent.get_agent_manifest_path(), "w") as file:
+ json.dump(EMPTY_MANIFEST, file)
+ self.assertRaises(UpdateError, agent._load_manifest)
+ return
+
+ @patch("azurelinuxagent.ga.update.GuestAgent._ensure_downloaded")
+ def test_load_manifest_is_malformed(self, mock_ensure):
+ agent = GuestAgent(path=self.agent_path)
+ self.assertFalse(os.path.isdir(agent.get_agent_dir()))
+ agent._unpack()
+ self.assertTrue(os.path.isfile(agent.get_agent_manifest_path()))
+
+ with open(agent.get_agent_manifest_path(), "w") as file:
+ file.write("This is not JSON data")
+ self.assertRaises(UpdateError, agent._load_manifest)
+ return
+
+ def test_load_error(self):
+ agent = GuestAgent(path=self.agent_path)
+ agent.error = None
+
+ agent._load_error()
+ self.assertTrue(agent.error is not None)
+ return
+
+ @patch("azurelinuxagent.ga.update.GuestAgent._ensure_downloaded")
+ @patch("azurelinuxagent.ga.update.restutil.http_get")
+ def test_download(self, mock_http_get, mock_ensure):
+ self.remove_agents()
+ self.assertFalse(os.path.isdir(self.agent_path))
+
+ agent_pkg = load_bin_data(os.path.join("ga", get_agent_file_name()))
+ mock_http_get.return_value= ResponseMock(response=agent_pkg)
+
+ pkg = ExtHandlerPackage(version=str(get_agent_version()))
+ pkg.uris.append(ExtHandlerPackageUri())
+ agent = GuestAgent(pkg=pkg)
+ agent._download()
+
+ self.assertTrue(os.path.isfile(agent.get_agent_pkg_path()))
+ return
+
+ @patch("azurelinuxagent.ga.update.GuestAgent._ensure_downloaded")
+ @patch("azurelinuxagent.ga.update.restutil.http_get")
+ def test_download_fail(self, mock_http_get, mock_ensure):
+ self.remove_agents()
+ self.assertFalse(os.path.isdir(self.agent_path))
+
+ mock_http_get.return_value= ResponseMock(status=restutil.httpclient.SERVICE_UNAVAILABLE)
+
+ pkg = ExtHandlerPackage(version=str(get_agent_version()))
+ pkg.uris.append(ExtHandlerPackageUri())
+ agent = GuestAgent(pkg=pkg)
+
+ self.assertRaises(UpdateError, agent._download)
+ self.assertFalse(os.path.isfile(agent.get_agent_pkg_path()))
+ self.assertFalse(agent.is_downloaded)
+ return
+
+ @patch("azurelinuxagent.ga.update.restutil.http_get")
+ def test_ensure_downloaded(self, mock_http_get):
+ self.remove_agents()
+ self.assertFalse(os.path.isdir(self.agent_path))
+
+ agent_pkg = load_bin_data(os.path.join("ga", get_agent_file_name()))
+ mock_http_get.return_value= ResponseMock(response=agent_pkg)
+
+ pkg = ExtHandlerPackage(version=str(get_agent_version()))
+ pkg.uris.append(ExtHandlerPackageUri())
+ agent = GuestAgent(pkg=pkg)
+
+ self.assertTrue(os.path.isfile(agent.get_agent_manifest_path()))
+ self.assertTrue(agent.is_downloaded)
+ return
+
+ @patch("azurelinuxagent.ga.update.GuestAgent._download", side_effect=UpdateError)
+ def test_ensure_downloaded_download_fails(self, mock_download):
+ self.remove_agents()
+ self.assertFalse(os.path.isdir(self.agent_path))
+
+ pkg = ExtHandlerPackage(version=str(get_agent_version()))
+ pkg.uris.append(ExtHandlerPackageUri())
+ agent = GuestAgent(pkg=pkg)
+
+ self.assertEqual(1, agent.error.failure_count)
+ self.assertFalse(agent.error.was_fatal)
+ self.assertFalse(agent.is_blacklisted)
+ return
+
+ @patch("azurelinuxagent.ga.update.GuestAgent._download")
+ @patch("azurelinuxagent.ga.update.GuestAgent._unpack", side_effect=UpdateError)
+ def test_ensure_downloaded_unpack_fails(self, mock_download, mock_unpack):
+ self.assertFalse(os.path.isdir(self.agent_path))
+
+ pkg = ExtHandlerPackage(version=str(get_agent_version()))
+ pkg.uris.append(ExtHandlerPackageUri())
+ agent = GuestAgent(pkg=pkg)
+
+ self.assertEqual(1, agent.error.failure_count)
+ self.assertTrue(agent.error.was_fatal)
+ self.assertTrue(agent.is_blacklisted)
+ return
+
+ @patch("azurelinuxagent.ga.update.GuestAgent._download")
+ @patch("azurelinuxagent.ga.update.GuestAgent._unpack")
+ @patch("azurelinuxagent.ga.update.GuestAgent._load_manifest", side_effect=UpdateError)
+ def test_ensure_downloaded_load_manifest_fails(self, mock_download, mock_unpack, mock_manifest):
+ self.assertFalse(os.path.isdir(self.agent_path))
+
+ pkg = ExtHandlerPackage(version=str(get_agent_version()))
+ pkg.uris.append(ExtHandlerPackageUri())
+ agent = GuestAgent(pkg=pkg)
+
+ self.assertEqual(1, agent.error.failure_count)
+ self.assertTrue(agent.error.was_fatal)
+ self.assertTrue(agent.is_blacklisted)
+ return
+
+ @patch("azurelinuxagent.ga.update.GuestAgent._download")
+ @patch("azurelinuxagent.ga.update.GuestAgent._unpack")
+ @patch("azurelinuxagent.ga.update.GuestAgent._load_manifest")
+ def test_ensure_download_skips_blacklisted(self, mock_download, mock_unpack, mock_manifest):
+ agent = GuestAgent(path=self.agent_path)
+ agent.clear_error()
+ agent.mark_failure(is_fatal=True)
+
+ pkg = ExtHandlerPackage(version=str(get_agent_version()))
+ pkg.uris.append(ExtHandlerPackageUri())
+ agent = GuestAgent(pkg=pkg)
+
+ self.assertEqual(1, agent.error.failure_count)
+ self.assertTrue(agent.error.was_fatal)
+ self.assertTrue(agent.is_blacklisted)
+ self.assertEqual(0, mock_download.call_count)
+ self.assertEqual(0, mock_unpack.call_count)
+ self.assertEqual(0, mock_manifest.call_count)
+ return
+
+
+class TestUpdate(UpdateTestCase):
+ def setUp(self):
+ UpdateTestCase.setUp(self)
+ self.update_handler = get_update_handler()
+ return
+
+ def test_creation(self):
+ self.assertTrue(self.update_handler.running)
+
+ self.assertEqual(None, self.update_handler.last_etag)
+ self.assertEqual(None, self.update_handler.last_attempt_time)
+
+ self.assertEqual(0, len(self.update_handler.agents))
+
+ self.assertEqual(None, self.update_handler.child_agent)
+ self.assertEqual(None, self.update_handler.child_launch_time)
+ self.assertEqual(0, self.update_handler.child_launch_attempts)
+ self.assertEqual(None, self.update_handler.child_process)
+
+ self.assertEqual(None, self.update_handler.signal_handler)
+ return
+
+ def _test_ensure_latest_agent(
+ self,
+ base_version=FlexibleVersion(AGENT_VERSION),
+ protocol=None,
+ versions=None):
+
+ latest_version = self.prepare_agents()
+ if versions is None or len(versions) <= 0:
+ versions = [latest_version]
+
+ etag = self.update_handler.last_etag if self.update_handler.last_etag is not None else 42
+ if protocol is None:
+ protocol = ProtocolMock(etag=etag, versions=versions)
+ self.update_handler.protocol_util = protocol
+ conf.get_autoupdate_gafamily = Mock(return_value=protocol.family)
+
+ return self.update_handler._ensure_latest_agent(base_version=base_version)
+
+ def test_ensure_latest_agent_returns_true_on_first_use(self):
+ self.assertEqual(None, self.update_handler.last_etag)
+ self.assertTrue(self._test_ensure_latest_agent())
+ return
+
+ def test_ensure_latest_agent_includes_old_agents(self):
+ self.prepare_agents()
+
+ old_count = FlexibleVersion(AGENT_VERSION).version[-1]
+ old_version = self.agent_versions()[-1]
+
+ self.replicate_agents(src_v=old_version, count=old_count, increment=-1)
+ all_count = len(self.agent_versions())
+
+ self.assertTrue(self._test_ensure_latest_agent(versions=self.agent_versions()))
+ self.assertEqual(all_count, len(self.update_handler.agents))
+ return
+
+ def test_ensure_lastest_agent_purges_old_agents(self):
+ self.prepare_agents()
+ agent_count = self.agent_count()
+ self.assertEqual(5, agent_count)
+
+ agent_versions = self.agent_versions()[:3]
+ self.assertTrue(self._test_ensure_latest_agent(versions=agent_versions))
+ self.assertEqual(len(agent_versions), len(self.update_handler.agents))
+ self.assertEqual(agent_versions, self.agent_versions())
+ return
+
+ def test_ensure_latest_agent_skips_if_too_frequent(self):
+ conf.get_autoupdate_frequency = Mock(return_value=10000)
+ self.update_handler.last_attempt_time = time.time()
+ self.assertFalse(self._test_ensure_latest_agent())
+ return
+
+ def test_ensure_latest_agent_skips_when_etag_matches(self):
+ self.update_handler.last_etag = 42
+ self.assertFalse(self._test_ensure_latest_agent())
+ return
+
+ def test_ensure_latest_agent_skips_if_when_no_new_versions(self):
+ self.prepare_agents()
+ base_version = self.agent_versions()[0] + 1
+ self.assertFalse(self._test_ensure_latest_agent(base_version=base_version))
+ return
+
+ def test_ensure_latest_agent_skips_when_no_versions(self):
+ self.assertFalse(self._test_ensure_latest_agent(protocol=ProtocolMock()))
+ return
+
+ def test_ensure_latest_agent_skips_when_updates_are_disabled(self):
+ conf.get_autoupdate_enabled = Mock(return_value=False)
+ self.assertFalse(self._test_ensure_latest_agent())
+ return
+
+ def test_ensure_latest_agent_sorts(self):
+ self.prepare_agents()
+ self._test_ensure_latest_agent()
+
+ v = FlexibleVersion("100000")
+ for a in self.update_handler.agents:
+ self.assertTrue(v > a.version)
+ v = a.version
+ return
+
+ def _test_evaluate_agent_health(self, child_agent_index=0):
+ self.prepare_agents()
+
+ latest_agent = self.update_handler.get_latest_agent()
+ self.assertTrue(latest_agent.is_available)
+ self.assertFalse(latest_agent.is_blacklisted)
+ self.assertTrue(len(self.update_handler.agents) > 1)
+
+ child_agent = self.update_handler.agents[child_agent_index]
+ self.assertTrue(child_agent.is_available)
+ self.assertFalse(child_agent.is_blacklisted)
+ self.update_handler.child_agent = child_agent
+
+ self.update_handler._evaluate_agent_health(latest_agent)
+ return
+
+ def test_evaluate_agent_health_ignores_installed_agent(self):
+ self.update_handler._evaluate_agent_health(None)
+ return
+
+ def test_evaluate_agent_health_raises_exception_for_restarting_agent(self):
+ self.update_handler.child_launch_time = time.time() - (4 * 60)
+ self.update_handler.child_launch_attempts = CHILD_LAUNCH_RESTART_MAX - 1
+ self.assertRaises(Exception, self._test_evaluate_agent_health)
+ return
+
+ def test_evaluate_agent_health_will_not_raise_exception_for_long_restarts(self):
+ self.update_handler.child_launch_time = time.time() - 24 * 60
+ self.update_handler.child_launch_attempts = CHILD_LAUNCH_RESTART_MAX
+ self._test_evaluate_agent_health()
+ return
+
+ def test_evaluate_agent_health_will_not_raise_exception_too_few_restarts(self):
+ self.update_handler.child_launch_time = time.time()
+ self.update_handler.child_launch_attempts = CHILD_LAUNCH_RESTART_MAX - 2
+ self._test_evaluate_agent_health()
+ return
+
+ def test_evaluate_agent_health_resets_with_new_agent(self):
+ self.update_handler.child_launch_time = time.time() - (4 * 60)
+ self.update_handler.child_launch_attempts = CHILD_LAUNCH_RESTART_MAX - 1
+ self._test_evaluate_agent_health(child_agent_index=1)
+ self.assertEqual(1, self.update_handler.child_launch_attempts)
+ return
+
+ def test_filter_blacklisted_agents(self):
+ self.prepare_agents()
+
+ self.update_handler._set_agents([GuestAgent(path=path) for path in self.agent_dirs()])
+ self.assertEqual(len(self.agent_dirs()), len(self.update_handler.agents))
+
+ kept_agents = self.update_handler.agents[1::2]
+ blacklisted_agents = self.update_handler.agents[::2]
+ for agent in blacklisted_agents:
+ agent.mark_failure(is_fatal=True)
+ self.update_handler._filter_blacklisted_agents()
+ self.assertEqual(kept_agents, self.update_handler.agents)
+ return
+
+ def test_get_latest_agent(self):
+ latest_version = self.prepare_agents()
+
+ latest_agent = self.update_handler.get_latest_agent()
+ self.assertEqual(len(get_agents(self.tmp_dir)), len(self.update_handler.agents))
+ self.assertEqual(latest_version, latest_agent.version)
+ return
+
+ def test_get_latest_agent_no_updates(self):
+ self.assertEqual(None, self.update_handler.get_latest_agent())
+ return
+
+ def test_get_latest_agent_skip_updates(self):
+ conf.get_autoupdate_enabled = Mock(return_value=False)
+ self.assertEqual(None, self.update_handler.get_latest_agent())
+ return
+
+ def test_get_latest_agent_skips_unavailable(self):
+ self.prepare_agents()
+ prior_agent = self.update_handler.get_latest_agent()
+
+ latest_version = self.prepare_agents(count=self.agent_count()+1, is_available=False)
+ latest_path = os.path.join(self.tmp_dir, "{0}-{1}".format(AGENT_NAME, latest_version))
+ self.assertFalse(GuestAgent(latest_path).is_available)
+
+ latest_agent = self.update_handler.get_latest_agent()
+ self.assertTrue(latest_agent.version < latest_version)
+ self.assertEqual(latest_agent.version, prior_agent.version)
+ return
+
+ def test_load_agents(self):
+ self.prepare_agents()
+
+ self.assertTrue(0 <= len(self.update_handler.agents))
+ self.update_handler._load_agents()
+ self.assertEqual(len(get_agents(self.tmp_dir)), len(self.update_handler.agents))
+ return
+
+ def test_load_agents_does_not_reload(self):
+ self.prepare_agents()
+
+ self.update_handler._load_agents()
+ agents = self.update_handler.agents
+
+ self.update_handler._load_agents()
+ self.assertEqual(agents, self.update_handler.agents)
+ return
+
+ def test_load_agents_sorts(self):
+ self.prepare_agents()
+ self.update_handler._load_agents()
+
+ v = FlexibleVersion("100000")
+ for a in self.update_handler.agents:
+ self.assertTrue(v > a.version)
+ v = a.version
+ return
+
+ def test_purge_agents(self):
+ self.prepare_agents()
+ self.update_handler._load_agents()
+
+ # Ensure at least three agents initially exist
+ self.assertTrue(2 < len(self.update_handler.agents))
+
+ # Purge every other agent
+ kept_agents = self.update_handler.agents[1::2]
+ purged_agents = self.update_handler.agents[::2]
+
+ # 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.assertEqual(
+ [agent.version for agent in kept_agents],
+ [agent.version for agent in self.update_handler.agents])
+
+ # Ensure both directories and packages are removed
+ for agent in purged_agents:
+ agent_path = os.path.join(self.tmp_dir, "{0}-{1}".format(AGENT_NAME, agent.version))
+ self.assertFalse(os.path.exists(agent_path))
+ self.assertFalse(os.path.exists(agent_path + ".zip"))
+
+ # Ensure kept agent directories and packages remain
+ for agent in kept_agents:
+ agent_path = os.path.join(self.tmp_dir, "{0}-{1}".format(AGENT_NAME, agent.version))
+ self.assertTrue(os.path.exists(agent_path))
+ self.assertTrue(os.path.exists(agent_path + ".zip"))
+ return
+
+ def _test_run_latest(self, mock_child=None, mock_time=None):
+ if mock_child is None:
+ mock_child = ChildMock()
+ if mock_time is None:
+ mock_time = TimeMock()
+
+ with patch('subprocess.Popen', return_value=mock_child) as mock_popen:
+ with patch('time.time', side_effect=mock_time.time):
+ with patch('time.sleep', return_value=mock_time.sleep):
+ self.update_handler.run_latest()
+ self.assertEqual(1, mock_popen.call_count)
+
+ return mock_popen.call_args
+
+ def test_run_latest(self):
+ self.prepare_agents()
+
+ agent = self.update_handler.get_latest_agent()
+ args, kwargs = self._test_run_latest()
+ cmds = shlex.split(agent.get_agent_cmd())
+ if cmds[0].lower() == "python":
+ cmds[0] = get_python_cmd()
+
+ self.assertEqual(args[0], cmds)
+ self.assertEqual(True, 'cwd' in kwargs)
+ self.assertEqual(agent.get_agent_dir(), kwargs['cwd'])
+ 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)
+ self._test_run_latest(mock_child=mock_child, mock_time=mock_time)
+ self.assertEqual(2, mock_child.poll.call_count)
+ self.assertEqual(1, mock_child.wait.call_count)
+ return
+
+ def test_run_latest_polling_stops_at_success(self):
+ mock_child = ChildMock(return_value=0)
+ mock_time = TimeMock(time_increment=CHILD_HEALTH_INTERVAL/3)
+ self._test_run_latest(mock_child=mock_child, mock_time=mock_time)
+ self.assertEqual(1, mock_child.poll.call_count)
+ self.assertEqual(0, mock_child.wait.call_count)
+ return
+
+ def test_run_latest_polling_stops_at_failure(self):
+ mock_child = ChildMock(return_value=42)
+ mock_time = TimeMock()
+ self._test_run_latest(mock_child=mock_child, mock_time=mock_time)
+ self.assertEqual(1, mock_child.poll.call_count)
+ self.assertEqual(0, mock_child.wait.call_count)
+ self.assertEqual(2, mock_time.time_call_count)
+ return
+
+ def test_run_latest_defaults_to_current(self):
+ self.assertEqual(None, self.update_handler.get_latest_agent())
+
+ args, kwargs = self._test_run_latest()
+
+ self.assertEqual(args[0], [get_python_cmd(), "-u", sys.argv[0], "-run-exthandlers"])
+ self.assertEqual(True, 'cwd' in kwargs)
+ self.assertEqual(os.getcwd(), kwargs['cwd'])
+ return
+
+ def test_run_latest_forwards_output(self):
+ try:
+ tempdir = tempfile.mkdtemp()
+ stdout_path = os.path.join(tempdir, "stdout")
+ stderr_path = os.path.join(tempdir, "stderr")
+
+ with open(stdout_path, "w") as stdout:
+ with open(stderr_path, "w") as stderr:
+ saved_stdout, sys.stdout = sys.stdout, stdout
+ saved_stderr, sys.stderr = sys.stderr, stderr
+ try:
+ self._test_run_latest(mock_child=ChildMock(side_effect=faux_logger))
+ finally:
+ sys.stdout = saved_stdout
+ sys.stderr = saved_stderr
+
+ with open(stdout_path, "r") as stdout:
+ self.assertEqual(1, len(stdout.readlines()))
+ with open(stderr_path, "r") as stderr:
+ self.assertEqual(1, len(stderr.readlines()))
+ finally:
+ shutil.rmtree(tempdir, True)
+ return
+
+ def test_run_latest_nonzero_code_marks_failures(self):
+ # logger.add_logger_appender(logger.AppenderType.STDOUT)
+ self.prepare_agents()
+
+ latest_agent = self.update_handler.get_latest_agent()
+ self.assertTrue(latest_agent.is_available)
+ self.assertEqual(0.0, latest_agent.error.last_failure)
+ self.assertEqual(0, latest_agent.error.failure_count)
+
+ self._test_run_latest(mock_child=ChildMock(return_value=1))
+
+ self.assertTrue(latest_agent.is_available)
+ self.assertNotEqual(0.0, latest_agent.error.last_failure)
+ self.assertEqual(1, latest_agent.error.failure_count)
+ return
+
+ def test_run_latest_exception_blacklists(self):
+ # logger.add_logger_appender(logger.AppenderType.STDOUT)
+ self.prepare_agents()
+
+ latest_agent = self.update_handler.get_latest_agent()
+ self.assertTrue(latest_agent.is_available)
+ self.assertEqual(0.0, latest_agent.error.last_failure)
+ self.assertEqual(0, latest_agent.error.failure_count)
+
+ self._test_run_latest(mock_child=ChildMock(side_effect=Exception("Force blacklisting")))
+
+ self.assertFalse(latest_agent.is_available)
+ self.assertTrue(latest_agent.error.is_blacklisted)
+ self.assertNotEqual(0.0, latest_agent.error.last_failure)
+ self.assertEqual(1, latest_agent.error.failure_count)
+ return
+
+ @patch('signal.signal')
+ def test_run_latest_captures_signals(self, mock_signal):
+ self._test_run_latest()
+ self.assertEqual(1, mock_signal.call_count)
+ return
+
+ @patch('signal.signal')
+ def test_run_latest_creates_only_one_signal_handler(self, mock_signal):
+ self.update_handler.signal_handler = "Not None"
+ self._test_run_latest()
+ self.assertEqual(0, mock_signal.call_count)
+ return
+
+ def _test_run(self, invocations=1, calls=[call.run()], enable_updates=False):
+ conf.get_autoupdate_enabled = Mock(return_value=enable_updates)
+
+ # Note:
+ # - Python only allows mutations of objects to which a function has
+ # a reference. Incrementing an integer directly changes the
+ # reference. Incrementing an item of a list changes an item to
+ # which the code has a reference.
+ # See http://stackoverflow.com/questions/26408941/python-nested-functions-and-variable-scope
+ iterations = [0]
+ def iterator(*args, **kwargs):
+ iterations[0] += 1
+ if iterations[0] >= invocations:
+ self.update_handler.running = False
+ return
+
+ calls = calls * invocations
+
+ with patch('azurelinuxagent.ga.exthandlers.get_exthandlers_handler') as mock_handler:
+ with patch('azurelinuxagent.ga.monitor.get_monitor_handler') as mock_monitor:
+ with patch('azurelinuxagent.ga.env.get_env_handler') as mock_env:
+ with patch('time.sleep', side_effect=iterator) as mock_sleep:
+ with patch('sys.exit') as mock_exit:
+
+ self.update_handler.run()
+
+ self.assertEqual(1, mock_handler.call_count)
+ self.assertEqual(mock_handler.return_value.method_calls, calls)
+ self.assertEqual(invocations, mock_sleep.call_count)
+ self.assertEqual(1, mock_monitor.call_count)
+ self.assertEqual(1, mock_env.call_count)
+ self.assertEqual(1, mock_exit.call_count)
+ return
+
+ def test_run(self):
+ self._test_run()
+ return
+
+ def test_run_keeps_running(self):
+ self._test_run(invocations=15)
+ return
+
+ def test_run_stops_if_update_available(self):
+ self.update_handler._ensure_latest_agent = Mock(return_value=True)
+ self._test_run(invocations=0, calls=[], enable_updates=True)
+ return
+
+ def test_set_agents_sets_agents(self):
+ self.prepare_agents()
+
+ self.update_handler._set_agents([GuestAgent(path=path) for path in self.agent_dirs()])
+ self.assertTrue(len(self.update_handler.agents) > 0)
+ self.assertEqual(len(self.agent_dirs()), len(self.update_handler.agents))
+ return
+
+ def test_set_agents_sorts_agents(self):
+ self.prepare_agents()
+
+ self.update_handler._set_agents([GuestAgent(path=path) for path in self.agent_dirs()])
+
+ v = FlexibleVersion("100000")
+ for a in self.update_handler.agents:
+ self.assertTrue(v > a.version)
+ v = a.version
+ return
+
+
+class ChildMock(Mock):
+ def __init__(self, return_value=0, side_effect=None):
+ Mock.__init__(self, return_value=return_value, side_effect=side_effect)
+
+ self.poll = Mock(return_value=return_value, side_effect=side_effect)
+ self.wait = Mock(return_value=return_value, side_effect=side_effect)
+ return
+
+
+class ProtocolMock(object):
+ def __init__(self, family="TestAgent", etag=42, versions=None):
+ self.family = family
+ self.etag = etag
+ self.versions = versions if versions is not None else []
+ self.create_manifests()
+ self.create_packages()
+ return
+
+ def create_manifests(self):
+ self.agent_manifests = VMAgentManifestList()
+ if len(self.versions) <= 0:
+ return
+
+ if self.family is not None:
+ manifest = VMAgentManifest(family=self.family)
+ for i in range(0,10):
+ manifest_uri = "https://nowhere.msft/agent/{0}".format(i)
+ manifest.versionsManifestUris.append(VMAgentManifestUri(uri=manifest_uri))
+ self.agent_manifests.vmAgentManifests.append(manifest)
+ return
+
+ def create_packages(self):
+ self.agent_packages = ExtHandlerPackageList()
+ if len(self.versions) <= 0:
+ return
+
+ for version in self.versions:
+ package = ExtHandlerPackage(str(version))
+ for i in range(0,5):
+ package_uri = "https://nowhere.msft/agent_pkg/{0}".format(i)
+ package.uris.append(ExtHandlerPackageUri(uri=package_uri))
+ self.agent_packages.versions.append(package)
+ return
+
+ def get_protocol(self):
+ return self
+
+ def get_vmagent_manifests(self):
+ return self.agent_manifests, self.etag
+
+ def get_vmagent_pkgs(self, manifest):
+ return self.agent_packages
+
+
+class ResponseMock(Mock):
+ def __init__(self, status=restutil.httpclient.OK, response=None):
+ Mock.__init__(self)
+ self.status = status
+ self.response = response
+ return
+
+ def read(self):
+ return self.response
+
+
+class TimeMock(Mock):
+ def __init__(self, time_increment=1):
+ Mock.__init__(self)
+ self.next_time = time.time()
+ self.time_call_count = 0
+ self.time_increment = time_increment
+
+ self.sleep = Mock(return_value=0)
+ return
+
+ def time(self):
+ self.time_call_count += 1
+ current_time = self.next_time
+ self.next_time += self.time_increment
+ return current_time
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/pa/__init__.py b/tests/pa/__init__.py
new file mode 100644
index 0000000..2ef4c16
--- /dev/null
+++ b/tests/pa/__init__.py
@@ -0,0 +1,16 @@
+# Copyright 2014 Microsoft Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Requires Python 2.4+ and Openssl 1.0+
+#
diff --git a/tests/distro/test_provision.py b/tests/pa/test_provision.py
index 60249ce..6508017 100644
--- a/tests/distro/test_provision.py
+++ b/tests/pa/test_provision.py
@@ -14,33 +14,33 @@
#
# Requires Python 2.4+ and Openssl 1.0+
#
-# Implements parts of RFC 2131, 1541, 1497 and
-# http://msdn.microsoft.com/en-us/library/cc227282%28PROT.10%29.aspx
-# http://msdn.microsoft.com/en-us/library/cc227259%28PROT.13%29.aspx
from tests.tools import *
-from azurelinuxagent.distro.loader import get_distro
-from azurelinuxagent.distro.default.protocolUtil import *
-import azurelinuxagent.utils.fileutil as fileutil
+import azurelinuxagent.common.conf as conf
+from azurelinuxagent.common.protocol import OVF_FILE_NAME
+import azurelinuxagent.common.utils.fileutil as fileutil
+from azurelinuxagent.pa.provision import get_provision_handler
class TestProvision(AgentTestCase):
-
+
@distros("redhat")
def test_provision(self, distro_name, distro_version, distro_full_name):
- distro = get_distro(distro_name, distro_version, distro_full_name)
- distro.osutil = MagicMock()
- distro.osutil.decode_customdata = Mock(return_value="")
-
- distro.protocol_util.detect_protocol_by_file = MagicMock()
- distro.protocol_util.get_protocol = MagicMock()
+ provision_handler = get_provision_handler(distro_name, distro_version,
+ distro_full_name)
+ mock_osutil = MagicMock()
+ mock_osutil.decode_customdata = Mock(return_value="")
+
+ provision_handler.osutil = mock_osutil
+ provision_handler.protocol_util.osutil = mock_osutil
+ provision_handler.protocol_util.get_protocol_by_file = MagicMock()
+ provision_handler.protocol_util.get_protocol = MagicMock()
+
conf.get_dvd_mount_point = Mock(return_value=self.tmp_dir)
-
ovfenv_file = os.path.join(self.tmp_dir, OVF_FILE_NAME)
ovfenv_data = load_data("ovf-env.xml")
fileutil.write_file(ovfenv_file, ovfenv_data)
- handler = distro.provision_handler
- handler.run()
+ provision_handler.run()
if __name__ == '__main__':
unittest.main()
diff --git a/tests/protocol/__init__.py b/tests/protocol/__init__.py
index 9bdb27e..2ef4c16 100644
--- a/tests/protocol/__init__.py
+++ b/tests/protocol/__init__.py
@@ -14,6 +14,3 @@
#
# Requires Python 2.4+ and Openssl 1.0+
#
-# Implements parts of RFC 2131, 1541, 1497 and
-# http://msdn.microsoft.com/en-us/library/cc227282%28PROT.10%29.aspx
-# http://msdn.microsoft.com/en-us/library/cc227259%28PROT.13%29.aspx
diff --git a/tests/protocol/mockmetadata.py b/tests/protocol/mockmetadata.py
index 0f7b568..dce3367 100644
--- a/tests/protocol/mockmetadata.py
+++ b/tests/protocol/mockmetadata.py
@@ -14,13 +14,10 @@
#
# Requires Python 2.4+ and Openssl 1.0+
#
-# Implements parts of RFC 2131, 1541, 1497 and
-# http://msdn.microsoft.com/en-us/library/cc227282%28PROT.10%29.aspx
-# http://msdn.microsoft.com/en-us/library/cc227259%28PROT.13%29.aspx
from tests.tools import *
-from azurelinuxagent.future import httpclient
-from azurelinuxagent.utils.cryptutil import CryptUtil
+from azurelinuxagent.common.future import httpclient
+from azurelinuxagent.common.utils.cryptutil import CryptUtil
DATA_FILE = {
"identity": "metadata/identity.json",
diff --git a/tests/protocol/mockwiredata.py b/tests/protocol/mockwiredata.py
index 6ffd19c..c789de5 100644
--- a/tests/protocol/mockwiredata.py
+++ b/tests/protocol/mockwiredata.py
@@ -14,13 +14,10 @@
#
# Requires Python 2.4+ and Openssl 1.0+
#
-# Implements parts of RFC 2131, 1541, 1497 and
-# http://msdn.microsoft.com/en-us/library/cc227282%28PROT.10%29.aspx
-# http://msdn.microsoft.com/en-us/library/cc227259%28PROT.13%29.aspx
from tests.tools import *
-from azurelinuxagent.future import httpclient
-from azurelinuxagent.utils.cryptutil import CryptUtil
+from azurelinuxagent.common.future import httpclient
+from azurelinuxagent.common.utils.cryptutil import CryptUtil
DATA_FILE = {
"version_info": "wire/version_info.xml",
@@ -30,6 +27,7 @@ DATA_FILE = {
"certs": "wire/certs.xml",
"ext_conf": "wire/ext_conf.xml",
"manifest": "wire/manifest.xml",
+ "ga_manifest" : "wire/ga_manifest.xml",
"trans_prv": "wire/trans_prv",
"trans_cert": "wire/trans_cert",
"test_ext": "ext/sample_ext.zip"
@@ -44,6 +42,15 @@ DATA_FILE_EXT_NO_SETTINGS["ext_conf"] = "wire/ext_conf_no_settings.xml"
DATA_FILE_EXT_NO_PUBLIC = DATA_FILE.copy()
DATA_FILE_EXT_NO_PUBLIC["ext_conf"] = "wire/ext_conf_no_public.xml"
+DATA_FILE_EXT_AUTOUPGRADE = DATA_FILE.copy()
+DATA_FILE_EXT_AUTOUPGRADE["ext_conf"] = "wire/ext_conf_autoupgrade.xml"
+
+DATA_FILE_EXT_INTERNALVERSION = DATA_FILE.copy()
+DATA_FILE_EXT_INTERNALVERSION["ext_conf"] = "wire/ext_conf_internalversion.xml"
+
+DATA_FILE_EXT_AUTOUPGRADE_INTERNALVERSION = DATA_FILE.copy()
+DATA_FILE_EXT_AUTOUPGRADE_INTERNALVERSION["ext_conf"] = "wire/ext_conf_autoupgrade_internalversion.xml"
+
class WireProtocolData(object):
def __init__(self, data_files=DATA_FILE):
self.version_info = load_data(data_files.get("version_info"))
@@ -53,6 +60,7 @@ class WireProtocolData(object):
self.certs = load_data(data_files.get("certs"))
self.ext_conf = load_data(data_files.get("ext_conf"))
self.manifest = load_data(data_files.get("manifest"))
+ self.ga_manifest = load_data(data_files.get("ga_manifest"))
self.trans_prv = load_data(data_files.get("trans_prv"))
self.trans_cert = load_data(data_files.get("trans_cert"))
self.ext = load_bin_data(data_files.get("test_ext"))
@@ -73,6 +81,8 @@ class WireProtocolData(object):
content = self.ext_conf
elif "manifest.xml" in url:
content = self.manifest
+ elif "manifest_of_ga.xml" in url:
+ content = self.ga_manifest
elif "ExampleHandlerLinux" in url:
content = self.ext
resp = MagicMock()
diff --git a/tests/protocol/test_hostplugin.py b/tests/protocol/test_hostplugin.py
new file mode 100644
index 0000000..65c8465
--- /dev/null
+++ b/tests/protocol/test_hostplugin.py
@@ -0,0 +1,85 @@
+# Copyright 2014 Microsoft Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Requires Python 2.4+ and Openssl 1.0+
+#
+
+from tests.tools import *
+import unittest
+import azurelinuxagent.common.protocol.wire as wire
+import azurelinuxagent.common.protocol.restapi as restapi
+
+wireserver_url = "168.63.129.16"
+sas_url = "http://sas_url"
+api_versions = '["2015-09-01"]'
+
+
+class TestHostPlugin(AgentTestCase):
+ def test_fallback(self):
+ with patch.object(wire.HostPluginProtocol,
+ "put_vm_status") as patch_put:
+ with patch.object(wire.StatusBlob, "upload") as patch_upload:
+ patch_upload.return_value = False
+ wire_protocol_client = wire.WireProtocol(wireserver_url).client
+ wire_protocol_client.ext_conf = wire.ExtensionsConfig(None)
+ wire_protocol_client.ext_conf.status_upload_blob = sas_url
+ wire_protocol_client.upload_status_blob()
+ self.assertTrue(patch_put.call_count == 1,
+ "Fallback was not engaged")
+ self.assertTrue(patch_put.call_args[0][1] == sas_url)
+
+ def test_no_fallback(self):
+ with patch.object(wire.HostPluginProtocol,
+ "put_vm_status") as patch_put:
+ with patch.object(wire.StatusBlob, "upload") as patch_upload:
+ patch_upload.return_value = True
+ wire_protocol_client = wire.WireProtocol(wireserver_url).client
+ wire_protocol_client.ext_conf = wire.ExtensionsConfig(None)
+ wire_protocol_client.ext_conf.status_upload_blob = sas_url
+ wire_protocol_client.upload_status_blob()
+ self.assertTrue(patch_put.call_count == 0,
+ "Fallback was engaged")
+
+ def test_init_put(self):
+ expected_url = "http://168.63.129.16:32526/status"
+ expected_headers = {'x-ms-version': '2015-09-01'}
+ expected_content = '{"content": "b2s=", ' \
+ '"headers": [{"headerName": "x-ms-version", ' \
+ '"headerValue": "2014-02-14"}, ' \
+ '{"headerName": "x-ms-blob-type", "headerValue": ' \
+ '"BlockBlob"}], ' \
+ '"requestUri": "http://sas_url"}'
+
+ host_client = wire.HostPluginProtocol(wireserver_url)
+ self.assertFalse(host_client.is_initialized)
+ self.assertTrue(host_client.api_versions is None)
+ status_blob = wire.StatusBlob(None)
+ status_blob.vm_status = "ok"
+ status_blob.type = "BlockBlob"
+ with patch.object(wire.HostPluginProtocol,
+ "get_api_versions") as patch_get:
+ patch_get.return_value = api_versions
+ with patch.object(restapi.restutil, "http_put") as patch_put:
+ patch_put.return_value = MagicMock()
+ host_client.put_vm_status(status_blob, sas_url)
+ self.assertTrue(host_client.is_initialized)
+ self.assertFalse(host_client.api_versions is None)
+ self.assertTrue(patch_put.call_count == 1)
+ self.assertTrue(patch_put.call_args[0][0] == expected_url)
+ self.assertTrue(patch_put.call_args[0][1] == expected_content)
+ self.assertTrue(patch_put.call_args[0][2] == expected_headers)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/protocol/test_metadata.py b/tests/protocol/test_metadata.py
index fca1a82..e2ef57a 100644
--- a/tests/protocol/test_metadata.py
+++ b/tests/protocol/test_metadata.py
@@ -14,17 +14,14 @@
#
# Requires Python 2.4+ and Openssl 1.0+
#
-# Implements parts of RFC 2131, 1541, 1497 and
-# http://msdn.microsoft.com/en-us/library/cc227282%28PROT.10%29.aspx
-# http://msdn.microsoft.com/en-us/library/cc227259%28PROT.13%29.aspx
from tests.tools import *
from tests.protocol.mockmetadata import *
-from azurelinuxagent.utils.restutil import httpclient
-from azurelinuxagent.protocol.metadata import MetadataProtocol
+from azurelinuxagent.common.utils.restutil import httpclient
+from azurelinuxagent.common.protocol.metadata import MetadataProtocol
@patch("time.sleep")
-@patch("azurelinuxagent.protocol.metadata.restutil")
+@patch("azurelinuxagent.common.protocol.metadata.restutil")
class TestWireProtocolGetters(AgentTestCase):
def _test_getters(self, test_data, mock_restutil ,_):
mock_restutil.http_get.side_effect = test_data.mock_http_get
@@ -33,7 +30,7 @@ class TestWireProtocolGetters(AgentTestCase):
protocol.detect()
protocol.get_vminfo()
protocol.get_certs()
- ext_handlers, etag= protocol.get_ext_handlers()
+ ext_handlers, etag = protocol.get_ext_handlers()
for ext_handler in ext_handlers.extHandlers:
protocol.get_ext_handler_pkgs(ext_handler)
diff --git a/tests/distro/test_protocol_util.py b/tests/protocol/test_protocol_util.py
index 61339f3..cb9a06f 100644
--- a/tests/distro/test_protocol_util.py
+++ b/tests/protocol/test_protocol_util.py
@@ -14,72 +14,64 @@
#
# Requires Python 2.4+ and Openssl 1.0+
#
-# Implements parts of RFC 2131, 1541, 1497 and
-# http://msdn.microsoft.com/en-us/library/cc227282%28PROT.10%29.aspx
-# http://msdn.microsoft.com/en-us/library/cc227259%28PROT.13%29.aspx
from tests.tools import *
-from azurelinuxagent.distro.loader import get_distro
-from azurelinuxagent.exception import *
-from azurelinuxagent.distro.default.protocolUtil import *
+from azurelinuxagent.common.exception import *
+from azurelinuxagent.common.protocol import get_protocol_util, \
+ TAG_FILE_NAME
@patch("time.sleep")
class TestProtocolUtil(AgentTestCase):
- @distros()
- @patch("azurelinuxagent.distro.default.protocolUtil.MetadataProtocol")
- @patch("azurelinuxagent.distro.default.protocolUtil.WireProtocol")
- def test_detect_protocol(self, distro_name, distro_version, distro_full_name,
- WireProtocol, MetadataProtocol, _, *distro_args):
-
+ @patch("azurelinuxagent.common.protocol.util.MetadataProtocol")
+ @patch("azurelinuxagent.common.protocol.util.WireProtocol")
+ def test_detect_protocol(self, WireProtocol, MetadataProtocol, _):
WireProtocol.return_value = MagicMock()
MetadataProtocol.return_value = MagicMock()
+
+ protocol_util = get_protocol_util()
- distro = get_distro(distro_name, distro_version, distro_full_name)
- distro.dhcp_handler = MagicMock()
- distro.dhcp_handler.endpoint = "foo.bar"
+ protocol_util.dhcp_handler = MagicMock()
+ protocol_util.dhcp_handler.endpoint = "foo.bar"
#Test wire protocol is available
- protocol = distro.protocol_util.detect_protocol()
+ protocol = protocol_util.get_protocol()
self.assertEquals(WireProtocol.return_value, protocol)
#Test wire protocol is not available
- distro.protocol_util.protocol = None
- WireProtocol.side_effect = ProtocolError()
+ protocol_util.clear_protocol()
+ WireProtocol.return_value.detect.side_effect = ProtocolError()
- protocol = distro.protocol_util.detect_protocol()
+ protocol = protocol_util.get_protocol()
self.assertEquals(MetadataProtocol.return_value, protocol)
#Test no protocol is available
- distro.protocol_util.protocol = None
- WireProtocol.side_effect = ProtocolError()
- MetadataProtocol.side_effect = ProtocolError()
- self.assertRaises(ProtocolError, distro.protocol_util.detect_protocol)
+ protocol_util.clear_protocol()
+ WireProtocol.return_value.detect.side_effect = ProtocolError()
- @distros()
- def test_detect_protocol_by_file(self, distro_name, distro_version,
- distro_full_name, _):
- distro = get_distro(distro_name, distro_version, distro_full_name)
- protocol_util = distro.protocol_util
+ MetadataProtocol.return_value.detect.side_effect = ProtocolError()
+ self.assertRaises(ProtocolError, protocol_util.get_protocol)
+ def test_detect_protocol_by_file(self, _):
+ protocol_util = get_protocol_util()
protocol_util._detect_wire_protocol = Mock()
protocol_util._detect_metadata_protocol = Mock()
tag_file = os.path.join(self.tmp_dir, TAG_FILE_NAME)
#Test tag file doesn't exist
- protocol_util.detect_protocol_by_file()
+ protocol_util.get_protocol_by_file()
protocol_util._detect_wire_protocol.assert_any_call()
protocol_util._detect_metadata_protocol.assert_not_called()
#Test tag file exists
- protocol_util.protocol = None
+ protocol_util.clear_protocol()
protocol_util._detect_wire_protocol.reset_mock()
protocol_util._detect_metadata_protocol.reset_mock()
with open(tag_file, "w+") as tag_fd:
tag_fd.write("")
- protocol_util.detect_protocol_by_file()
+ protocol_util.get_protocol_by_file()
protocol_util._detect_metadata_protocol.assert_any_call()
protocol_util._detect_wire_protocol.assert_not_called()
diff --git a/tests/protocol/test_restapi.py b/tests/protocol/test_restapi.py
index 656ecc6..e4b65c9 100644
--- a/tests/protocol/test_restapi.py
+++ b/tests/protocol/test_restapi.py
@@ -14,9 +14,6 @@
#
# Requires Python 2.4+ and Openssl 1.0+
#
-# Implements parts of RFC 2131, 1541, 1497 and
-# http://msdn.microsoft.com/en-us/library/cc227282%28PROT.10%29.aspx
-# http://msdn.microsoft.com/en-us/library/cc227259%28PROT.13%29.aspx
from tests.tools import *
import uuid
@@ -24,7 +21,7 @@ import unittest
import os
import shutil
import time
-from azurelinuxagent.protocol.restapi import *
+from azurelinuxagent.common.protocol.restapi import *
class SampleDataContract(DataContract):
def __init__(self):
diff --git a/tests/protocol/test_wire.py b/tests/protocol/test_wire.py
index 4c38c13..bd3acaf 100644
--- a/tests/protocol/test_wire.py
+++ b/tests/protocol/test_wire.py
@@ -14,9 +14,6 @@
#
# Requires Python 2.4+ and Openssl 1.0+
#
-# Implements parts of RFC 2131, 1541, 1497 and
-# http://msdn.microsoft.com/en-us/library/cc227282%28PROT.10%29.aspx
-# http://msdn.microsoft.com/en-us/library/cc227259%28PROT.13%29.aspx
from tests.tools import *
from tests.protocol.mockwiredata import *
@@ -24,18 +21,18 @@ import uuid
import unittest
import os
import time
-from azurelinuxagent.utils.restutil import httpclient
-from azurelinuxagent.utils.cryptutil import CryptUtil
-from azurelinuxagent.protocol.restapi import *
-from azurelinuxagent.protocol.wire import WireClient, WireProtocol, \
+from azurelinuxagent.common.utils.restutil import httpclient
+from azurelinuxagent.common.utils.cryptutil import CryptUtil
+from azurelinuxagent.common.protocol.restapi import *
+from azurelinuxagent.common.protocol.wire import WireClient, WireProtocol, \
TRANSPORT_PRV_FILE_NAME, \
TRANSPORT_CERT_FILE_NAME
data_with_bom = b'\xef\xbb\xbfhehe'
@patch("time.sleep")
-@patch("azurelinuxagent.protocol.wire.CryptUtil")
-@patch("azurelinuxagent.protocol.wire.restutil")
+@patch("azurelinuxagent.common.protocol.wire.CryptUtil")
+@patch("azurelinuxagent.common.protocol.wire.restutil")
class TestWireProtocolGetters(AgentTestCase):
def _test_getters(self, test_data, mock_restutil, MockCryptUtil, _):
diff --git a/tests/test_import.py b/tests/test_import.py
new file mode 100644
index 0000000..39a48ab
--- /dev/null
+++ b/tests/test_import.py
@@ -0,0 +1,26 @@
+from tests.tools import *
+import azurelinuxagent.common.osutil as osutil
+import azurelinuxagent.common.dhcp as dhcp
+import azurelinuxagent.common.protocol as protocol
+import azurelinuxagent.pa.provision as provision
+import azurelinuxagent.pa.deprovision as deprovision
+import azurelinuxagent.daemon as daemon
+import azurelinuxagent.daemon.resourcedisk as resourcedisk
+import azurelinuxagent.daemon.scvmm as scvmm
+import azurelinuxagent.ga.exthandlers as exthandlers
+import azurelinuxagent.ga.monitor as monitor
+import azurelinuxagent.ga.update as update
+
+class TestImportHandler(AgentTestCase):
+ def test_get_handler(self):
+ osutil.get_osutil()
+ protocol.get_protocol_util()
+ dhcp.get_dhcp_handler()
+ provision.get_provision_handler()
+ deprovision.get_deprovision_handler()
+ daemon.get_daemon_handler()
+ resourcedisk.get_resourcedisk_handler()
+ scvmm.get_scvmm_handler()
+ monitor.get_monitor_handler()
+ update.get_update_handler()
+ exthandlers.get_exthandlers_handler()
diff --git a/tests/tools.py b/tests/tools.py
index 672c60b..8bf23ed 100644
--- a/tests/tools.py
+++ b/tests/tools.py
@@ -14,31 +14,31 @@
#
# Requires Python 2.4+ and Openssl 1.0+
#
-# Implements parts of RFC 2131, 1541, 1497 and
-# http://msdn.microsoft.com/en-us/library/cc227282%28PROT.10%29.aspx
-# http://msdn.microsoft.com/en-us/library/cc227259%28PROT.13%29.aspx
"""
Define util functions for unit test
"""
-import re
+import json
import os
-import sys
-import unittest
+import re
import shutil
-import json
+import sys
import tempfile
+import unittest
+
from functools import wraps
-import azurelinuxagent.conf as conf
-import azurelinuxagent.logger as logger
-import azurelinuxagent.event as event
+
+import azurelinuxagent.common.conf as conf
+import azurelinuxagent.common.event as event
+import azurelinuxagent.common.logger as logger
+from azurelinuxagent.common.version import PY_VERSION_MAJOR
#Import mock module for Python2 and Python3
try:
- from unittest.mock import Mock, patch, MagicMock
+ from unittest.mock import Mock, patch, MagicMock, DEFAULT, call
except ImportError:
- from mock import Mock, patch, MagicMock
+ from mock import Mock, patch, MagicMock, DEFAULT, call
test_dir = os.path.dirname(os.path.abspath(__file__))
data_dir = os.path.join(test_dir, "data")
@@ -56,6 +56,7 @@ class AgentTestCase(unittest.TestCase):
def setUp(self):
prefix = "{0}_".format(self.__class__.__name__)
self.tmp_dir = tempfile.mkdtemp(prefix=prefix)
+ conf.get_autoupdate_enabled = Mock(return_value=True)
conf.get_lib_dir = Mock(return_value=self.tmp_dir)
ext_log_dir = os.path.join(self.tmp_dir, "azure")
conf.get_ext_log_dir = Mock(return_value=ext_log_dir)
@@ -98,6 +99,12 @@ supported_distro = [
]
+def open_patch():
+ open_name = '__builtin__.open'
+ if PY_VERSION_MAJOR == 3:
+ open_name = 'builtins.open'
+ return open_name
+
def distros(distro_name=".*", distro_version=".*", distro_full_name=".*"):
"""Run test on multiple distros"""
def decorator(test_method):
diff --git a/tests/utils/__init__.py b/tests/utils/__init__.py
index 9bdb27e..2ef4c16 100644
--- a/tests/utils/__init__.py
+++ b/tests/utils/__init__.py
@@ -14,6 +14,3 @@
#
# Requires Python 2.4+ and Openssl 1.0+
#
-# Implements parts of RFC 2131, 1541, 1497 and
-# http://msdn.microsoft.com/en-us/library/cc227282%28PROT.10%29.aspx
-# http://msdn.microsoft.com/en-us/library/cc227259%28PROT.13%29.aspx
diff --git a/tests/utils/test_file_util.py b/tests/utils/test_file_util.py
index bf7c638..9a5479e 100644
--- a/tests/utils/test_file_util.py
+++ b/tests/utils/test_file_util.py
@@ -14,17 +14,14 @@
#
# Requires Python 2.4+ and Openssl 1.0+
#
-# Implements parts of RFC 2131, 1541, 1497 and
-# http://msdn.microsoft.com/en-us/library/cc227282%28PROT.10%29.aspx
-# http://msdn.microsoft.com/en-us/library/cc227259%28PROT.13%29.aspx
from tests.tools import *
import uuid
import unittest
import os
import sys
-from azurelinuxagent.future import ustr
-import azurelinuxagent.utils.fileutil as fileutil
+from azurelinuxagent.common.future import ustr
+import azurelinuxagent.common.utils.fileutil as fileutil
class TestFileOperations(AgentTestCase):
def test_read_write_file(self):
diff --git a/tests/utils/test_flexible_version.py b/tests/utils/test_flexible_version.py
new file mode 100644
index 0000000..1162022
--- /dev/null
+++ b/tests/utils/test_flexible_version.py
@@ -0,0 +1,477 @@
+import random
+import re
+import unittest
+
+from azurelinuxagent.common.utils.flexible_version import FlexibleVersion
+
+class TestFlexibleVersion(unittest.TestCase):
+
+ def setUp(self):
+ self.v = FlexibleVersion()
+
+ def test_compile_separator(self):
+ tests = [
+ '.',
+ '',
+ '-'
+ ]
+ for t in tests:
+ t_escaped = re.escape(t)
+ t_re = re.compile(t_escaped)
+ self.assertEqual((t_escaped, t_re), self.v._compile_separator(t))
+ self.assertEqual(('', re.compile('')), self.v._compile_separator(None))
+ return
+
+ def test_compile_pattern(self):
+ self.v._compile_pattern()
+ tests = {
+ '1': True,
+ '1.2': True,
+ '1.2.3': True,
+ '1.2.3.4': True,
+ '1.2.3.4.5': True,
+
+ '1alpha': True,
+ '1.alpha': True,
+ '1-alpha': True,
+ '1alpha0': True,
+ '1.alpha0': True,
+ '1-alpha0': True,
+ '1.2alpha': True,
+ '1.2.alpha': True,
+ '1.2-alpha': True,
+ '1.2alpha0': True,
+ '1.2.alpha0': True,
+ '1.2-alpha0': True,
+
+ '1beta': True,
+ '1.beta': True,
+ '1-beta': True,
+ '1beta0': True,
+ '1.beta0': True,
+ '1-beta0': True,
+ '1.2beta': True,
+ '1.2.beta': True,
+ '1.2-beta': True,
+ '1.2beta0': True,
+ '1.2.beta0': True,
+ '1.2-beta0': True,
+
+ '1rc': True,
+ '1.rc': True,
+ '1-rc': True,
+ '1rc0': True,
+ '1.rc0': True,
+ '1-rc0': True,
+ '1.2rc': True,
+ '1.2.rc': True,
+ '1.2-rc': True,
+ '1.2rc0': True,
+ '1.2.rc0': True,
+ '1.2-rc0': True,
+
+ '1.2.3.4alpha5': True,
+
+ ' 1': False,
+ 'beta': False,
+ '1delta0': False,
+ '': False
+ }
+ for test in iter(tests):
+ expectation = tests[test]
+ self.assertEqual(
+ expectation,
+ self.v.version_re.match(test) is not None,
+ "test: {0} expected: {1} ".format(test, expectation))
+ return
+
+ def test_compile_pattern_sep(self):
+ self.v.sep = '-'
+ self.v._compile_pattern()
+ tests = {
+ '1': True,
+ '1-2': True,
+ '1-2-3': True,
+ '1-2-3-4': True,
+ '1-2-3-4-5': True,
+
+ '1alpha': True,
+ '1-alpha': True,
+ '1-alpha': True,
+ '1alpha0': True,
+ '1-alpha0': True,
+ '1-alpha0': True,
+ '1-2alpha': True,
+ '1-2.alpha': True,
+ '1-2-alpha': True,
+ '1-2alpha0': True,
+ '1-2.alpha0': True,
+ '1-2-alpha0': True,
+
+ '1beta': True,
+ '1-beta': True,
+ '1-beta': True,
+ '1beta0': True,
+ '1-beta0': True,
+ '1-beta0': True,
+ '1-2beta': True,
+ '1-2.beta': True,
+ '1-2-beta': True,
+ '1-2beta0': True,
+ '1-2.beta0': True,
+ '1-2-beta0': True,
+
+ '1rc': True,
+ '1-rc': True,
+ '1-rc': True,
+ '1rc0': True,
+ '1-rc0': True,
+ '1-rc0': True,
+ '1-2rc': True,
+ '1-2.rc': True,
+ '1-2-rc': True,
+ '1-2rc0': True,
+ '1-2.rc0': True,
+ '1-2-rc0': True,
+
+ '1-2-3-4alpha5': True,
+
+ ' 1': False,
+ 'beta': False,
+ '1delta0': False,
+ '': False
+ }
+ for test in iter(tests):
+ expectation = tests[test]
+ self.assertEqual(
+ expectation,
+ self.v.version_re.match(test) is not None,
+ "test: {0} expected: {1} ".format(test, expectation))
+ return
+
+ def test_compile_pattern_prerel(self):
+ self.v.prerel_tags = ('a', 'b', 'c')
+ self.v._compile_pattern()
+ tests = {
+ '1': True,
+ '1.2': True,
+ '1.2.3': True,
+ '1.2.3.4': True,
+ '1.2.3.4.5': True,
+
+ '1a': True,
+ '1.a': True,
+ '1-a': True,
+ '1a0': True,
+ '1.a0': True,
+ '1-a0': True,
+ '1.2a': True,
+ '1.2.a': True,
+ '1.2-a': True,
+ '1.2a0': True,
+ '1.2.a0': True,
+ '1.2-a0': True,
+
+ '1b': True,
+ '1.b': True,
+ '1-b': True,
+ '1b0': True,
+ '1.b0': True,
+ '1-b0': True,
+ '1.2b': True,
+ '1.2.b': True,
+ '1.2-b': True,
+ '1.2b0': True,
+ '1.2.b0': True,
+ '1.2-b0': True,
+
+ '1c': True,
+ '1.c': True,
+ '1-c': True,
+ '1c0': True,
+ '1.c0': True,
+ '1-c0': True,
+ '1.2c': True,
+ '1.2.c': True,
+ '1.2-c': True,
+ '1.2c0': True,
+ '1.2.c0': True,
+ '1.2-c0': True,
+
+ '1.2.3.4a5': True,
+
+ ' 1': False,
+ '1.2.3.4alpha5': False,
+ 'beta': False,
+ '1delta0': False,
+ '': False
+ }
+ for test in iter(tests):
+ expectation = tests[test]
+ self.assertEqual(
+ expectation,
+ self.v.version_re.match(test) is not None,
+ "test: {0} expected: {1} ".format(test, expectation))
+ return
+
+ def test_ensure_compatible_separators(self):
+ v1 = FlexibleVersion('1.2.3')
+ v2 = FlexibleVersion('1-2-3', sep='-')
+ try:
+ v1 == v2
+ self.assertTrue(False, "Incompatible separators failed to raise an exception")
+ except ValueError:
+ pass
+ except Exception as e:
+ t = e.__class__.__name__
+ self.assertTrue(False, "Incompatible separators raised an unexpected exception: {0}" \
+ .format(t))
+ return
+
+ def test_ensure_compatible_prerel(self):
+ v1 = FlexibleVersion('1.2.3', prerel_tags=('alpha', 'beta', 'rc'))
+ v2 = FlexibleVersion('1.2.3', prerel_tags=('a', 'b', 'c'))
+ try:
+ v1 == v2
+ self.assertTrue(False, "Incompatible prerel_tags failed to raise an exception")
+ except ValueError:
+ pass
+ except Exception as e:
+ t = e.__class__.__name__
+ self.assertTrue(False, "Incompatible prerel_tags raised an unexpected exception: {0}" \
+ .format(t))
+ return
+
+ def test_ensure_compatible_prerel_length(self):
+ v1 = FlexibleVersion('1.2.3', prerel_tags=('a', 'b', 'c'))
+ v2 = FlexibleVersion('1.2.3', prerel_tags=('a', 'b'))
+ try:
+ v1 == v2
+ self.assertTrue(False, "Incompatible prerel_tags failed to raise an exception")
+ except ValueError:
+ pass
+ except Exception as e:
+ t = e.__class__.__name__
+ self.assertTrue(False, "Incompatible prerel_tags raised an unexpected exception: {0}" \
+ .format(t))
+ return
+
+ def test_ensure_compatible_prerel_order(self):
+ v1 = FlexibleVersion('1.2.3', prerel_tags=('a', 'b'))
+ v2 = FlexibleVersion('1.2.3', prerel_tags=('b', 'a'))
+ try:
+ v1 == v2
+ self.assertTrue(False, "Incompatible prerel_tags failed to raise an exception")
+ except ValueError:
+ pass
+ except Exception as e:
+ t = e.__class__.__name__
+ self.assertTrue(False, "Incompatible prerel_tags raised an unexpected exception: {0}" \
+ .format(t))
+ return
+
+ def test_major(self):
+ tests = {
+ '1' : 1,
+ '1.2' : 1,
+ '1.2.3' : 1,
+ '1.2.3.4' : 1
+ }
+ for test in iter(tests):
+ expectation = tests[test]
+ self.assertEqual(
+ expectation,
+ FlexibleVersion(test).major)
+ return
+
+ def test_minor(self):
+ tests = {
+ '1' : 0,
+ '1.2' : 2,
+ '1.2.3' : 2,
+ '1.2.3.4' : 2
+ }
+ for test in iter(tests):
+ expectation = tests[test]
+ self.assertEqual(
+ expectation,
+ FlexibleVersion(test).minor)
+ return
+
+ def test_patch(self):
+ tests = {
+ '1' : 0,
+ '1.2' : 0,
+ '1.2.3' : 3,
+ '1.2.3.4' : 3
+ }
+ for test in iter(tests):
+ expectation = tests[test]
+ self.assertEqual(
+ expectation,
+ FlexibleVersion(test).patch)
+ return
+
+ def test_parse(self):
+ tests = {
+ "1.2.3.4": ((1, 2, 3, 4), None),
+ "1.2.3.4alpha5": ((1, 2, 3, 4), ('alpha', 5)),
+ "1.2.3.4-alpha5": ((1, 2, 3, 4), ('alpha', 5)),
+ "1.2.3.4.alpha5": ((1, 2, 3, 4), ('alpha', 5))
+ }
+ for test in iter(tests):
+ expectation = tests[test]
+ self.v._parse(test)
+ self.assertEqual(expectation, (self.v.version, self.v.prerelease))
+ return
+
+ def test_decrement(self):
+ src_v = FlexibleVersion('1.0.0.0.10')
+ dst_v = FlexibleVersion(str(src_v))
+ for i in range(1,10):
+ dst_v -= 1
+ self.assertEqual(i, src_v.version[-1] - dst_v.version[-1])
+ return
+
+ def test_decrement_disallows_below_zero(self):
+ try:
+ FlexibleVersion('1.0') - 1
+ self.assertTrue(False, "Decrement failed to raise an exception")
+ except ArithmeticError:
+ pass
+ except Exception as e:
+ t = e.__class__.__name__
+ self.assertTrue(False, "Decrement raised an unexpected exception: {0}".format(t))
+ return
+
+ def test_increment(self):
+ src_v = FlexibleVersion('1.0.0.0.0')
+ dst_v = FlexibleVersion(str(src_v))
+ for i in range(1,10):
+ dst_v += 1
+ self.assertEqual(i, dst_v.version[-1] - src_v.version[-1])
+ return
+
+ def test_str(self):
+ tests = [
+ '1',
+ '1.2',
+ '1.2.3',
+ '1.2.3.4',
+ '1.2.3.4.5',
+
+ '1alpha',
+ '1.alpha',
+ '1-alpha',
+ '1alpha0',
+ '1.alpha0',
+ '1-alpha0',
+ '1.2alpha',
+ '1.2.alpha',
+ '1.2-alpha',
+ '1.2alpha0',
+ '1.2.alpha0',
+ '1.2-alpha0',
+
+ '1beta',
+ '1.beta',
+ '1-beta',
+ '1beta0',
+ '1.beta0',
+ '1-beta0',
+ '1.2beta',
+ '1.2.beta',
+ '1.2-beta',
+ '1.2beta0',
+ '1.2.beta0',
+ '1.2-beta0',
+
+ '1rc',
+ '1.rc',
+ '1-rc',
+ '1rc0',
+ '1.rc0',
+ '1-rc0',
+ '1.2rc',
+ '1.2.rc',
+ '1.2-rc',
+ '1.2rc0',
+ '1.2.rc0',
+ '1.2-rc0',
+
+ '1.2.3.4alpha5',
+ ]
+ for test in tests:
+ self.assertEqual(test, str(FlexibleVersion(test)))
+ return
+
+ def test_repr(self):
+ v = FlexibleVersion('1,2,3rc4', ',', ['lol', 'rc'])
+ expected = "FlexibleVersion ('1,2,3rc4', ',', ('lol', 'rc'))"
+ self.assertEqual(expected, repr(v))
+
+ def test_order(self):
+ test0 = ["1.7.0", "1.7.0rc0", "1.11.0"]
+ expected0 = ['1.7.0rc0', '1.7.0', '1.11.0']
+ self.assertEqual(expected0, list(map(str, sorted([FlexibleVersion(v) for v in test0]))))
+
+ test1 = [
+ '2.0.2rc2',
+ '2.2.0beta3',
+ '2.0.10',
+ '2.1.0alpha42',
+ '2.0.2beta4',
+ '2.1.1',
+ '2.0.1',
+ '2.0.2rc3',
+ '2.2.0',
+ '2.0.0',
+ '3.0.1',
+ '2.1.0rc1'
+ ]
+ expected1 = [
+ '2.0.0',
+ '2.0.1',
+ '2.0.2beta4',
+ '2.0.2rc2',
+ '2.0.2rc3',
+ '2.0.10',
+ '2.1.0alpha42',
+ '2.1.0rc1',
+ '2.1.1',
+ '2.2.0beta3',
+ '2.2.0',
+ '3.0.1'
+ ]
+ self.assertEqual(expected1, list(map(str, sorted([FlexibleVersion(v) for v in test1]))))
+
+ self.assertEqual(FlexibleVersion("1.0.0.0.0.0.0.0"), FlexibleVersion("1"))
+
+ self.assertFalse(FlexibleVersion("1.0") > FlexibleVersion("1.0"))
+ self.assertFalse(FlexibleVersion("1.0") < FlexibleVersion("1.0"))
+
+ self.assertTrue(FlexibleVersion("1.0") < FlexibleVersion("1.1"))
+ self.assertTrue(FlexibleVersion("1.9") < FlexibleVersion("1.10"))
+ self.assertTrue(FlexibleVersion("1.9.9") < FlexibleVersion("1.10.0"))
+ self.assertTrue(FlexibleVersion("1.0.0.0") < FlexibleVersion("1.2.0.0"))
+
+ self.assertTrue(FlexibleVersion("1.1") > FlexibleVersion("1.0"))
+ self.assertTrue(FlexibleVersion("1.10") > FlexibleVersion("1.9"))
+ self.assertTrue(FlexibleVersion("1.10.0") > FlexibleVersion("1.9.9"))
+ self.assertTrue(FlexibleVersion("1.2.0.0") > FlexibleVersion("1.0.0.0"))
+
+ self.assertTrue(FlexibleVersion("1.0") <= FlexibleVersion("1.1"))
+ self.assertTrue(FlexibleVersion("1.1") > FlexibleVersion("1.0"))
+ self.assertTrue(FlexibleVersion("1.1") >= FlexibleVersion("1.0"))
+
+ self.assertTrue(FlexibleVersion("1.0") == FlexibleVersion("1.0"))
+ self.assertTrue(FlexibleVersion("1.0") >= FlexibleVersion("1.0"))
+ self.assertTrue(FlexibleVersion("1.0") <= FlexibleVersion("1.0"))
+
+ self.assertFalse(FlexibleVersion("1.0") != FlexibleVersion("1.0"))
+ self.assertTrue(FlexibleVersion("1.1") != FlexibleVersion("1.0"))
+ return
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/utils/test_rest_util.py b/tests/utils/test_rest_util.py
index bd22c55..874e527 100644
--- a/tests/utils/test_rest_util.py
+++ b/tests/utils/test_rest_util.py
@@ -14,17 +14,14 @@
#
# Requires Python 2.4+ and Openssl 1.0+
#
-# Implements parts of RFC 2131, 1541, 1497 and
-# http://msdn.microsoft.com/en-us/library/cc227282%28PROT.10%29.aspx
-# http://msdn.microsoft.com/en-us/library/cc227259%28PROT.13%29.aspx
from tests.tools import AgentTestCase, patch, Mock, MagicMock
import uuid
import unittest
import os
-import azurelinuxagent.utils.restutil as restutil
-from azurelinuxagent.future import ustr, httpclient
-import azurelinuxagent.logger as logger
+import azurelinuxagent.common.utils.restutil as restutil
+from azurelinuxagent.common.future import ustr, httpclient
+import azurelinuxagent.common.logger as logger
class TestHttpOperations(AgentTestCase):
@@ -57,8 +54,8 @@ class TestHttpOperations(AgentTestCase):
self.assertEquals(rel_uri, "None")
- @patch("azurelinuxagent.future.httpclient.HTTPSConnection")
- @patch("azurelinuxagent.future.httpclient.HTTPConnection")
+ @patch("azurelinuxagent.common.future.httpclient.HTTPSConnection")
+ @patch("azurelinuxagent.common.future.httpclient.HTTPConnection")
def test_http_request(self, HTTPConnection, HTTPSConnection):
mock_httpconn = MagicMock()
mock_httpresp = MagicMock()
@@ -98,7 +95,7 @@ class TestHttpOperations(AgentTestCase):
self.assertEquals("_(:3| <)_", resp.read())
@patch("time.sleep")
- @patch("azurelinuxagent.utils.restutil._http_request")
+ @patch("azurelinuxagent.common.utils.restutil._http_request")
def test_http_request_with_retry(self, _http_request, sleep):
mock_httpresp = MagicMock()
mock_httpresp.read = Mock(return_value="hehe")
diff --git a/tests/utils/test_shell_util.py b/tests/utils/test_shell_util.py
index aa89121..57e6c33 100644
--- a/tests/utils/test_shell_util.py
+++ b/tests/utils/test_shell_util.py
@@ -15,15 +15,12 @@
#
# Requires Python 2.4+ and Openssl 1.0+
#
-# Implements parts of RFC 2131, 1541, 1497 and
-# http://msdn.microsoft.com/en-us/library/cc227282%28PROT.10%29.aspx
-# http://msdn.microsoft.com/en-us/library/cc227259%28PROT.13%29.aspx
from tests.tools import *
import uuid
import unittest
import os
-import azurelinuxagent.utils.shellutil as shellutil
+import azurelinuxagent.common.utils.shellutil as shellutil
import test
class TestrunCmd(AgentTestCase):
@@ -38,5 +35,10 @@ class TestrunCmd(AgentTestCase):
err = shellutil.run_get_output(u"ls 我")
self.assertNotEquals(0, err[0])
+ def test_shellquote(self):
+ self.assertEqual("\'foo\'", shellutil.quote("foo"))
+ self.assertEqual("\'foo bar\'", shellutil.quote("foo bar"))
+ self.assertEqual("'foo'\\''bar'", shellutil.quote("foo\'bar"))
+
if __name__ == '__main__':
unittest.main()
diff --git a/tests/utils/test_text_util.py b/tests/utils/test_text_util.py
index 0e8cc7d..9ac0707 100644
--- a/tests/utils/test_text_util.py
+++ b/tests/utils/test_text_util.py
@@ -14,17 +14,14 @@
#
# Requires Python 2.4+ and Openssl 1.0+
#
-# Implements parts of RFC 2131, 1541, 1497 and
-# http://msdn.microsoft.com/en-us/library/cc227282%28PROT.10%29.aspx
-# http://msdn.microsoft.com/en-us/library/cc227259%28PROT.13%29.aspx
from tests.tools import *
import uuid
import unittest
import os
-from azurelinuxagent.future import ustr
-import azurelinuxagent.utils.textutil as textutil
-from azurelinuxagent.utils.textutil import Version
+from azurelinuxagent.common.future import ustr
+import azurelinuxagent.common.utils.textutil as textutil
+from azurelinuxagent.common.utils.textutil import Version
class TestTextUtil(AgentTestCase):
def test_get_password_hash(self):