Merge ~smoser/cloud-init:bug/run_test_net into cloud-init:master

Proposed by Scott Moser
Status: Merged
Merged at revision: 65e01b463cee0bdb8c8b415e78abfcc3262aad89
Proposed branch: ~smoser/cloud-init:bug/run_test_net
Merge into: cloud-init:master
Diff against target: 338 lines (+55/-61)
5 files modified
tests/unittests/helpers.py (+27/-20)
tests/unittests/test__init__.py (+6/-6)
tests/unittests/test_atomic_helper.py (+2/-2)
tests/unittests/test_distros/test_user_data_normalize.py (+0/-0)
tests/unittests/test_net.py (+20/-33)
Reviewer Review Type Date Requested Status
cloud-init Commiters Pending
Review via email: mp+315402@code.launchpad.net

Commit message

tests: remove executable bit on test_net, so it runs, and fix it.

The test_user_data_normalize and test_net files had gotten
the executable bit set, and thus are skipped by nose by default.
We could set run with the --exe flag, but they should not have
gotten this way.

Other changes here:
 * replace TempDirTestCase with CiTestCase, which has some nice
   tmp_dir() and tmp_path() functions. Going forward the intent
   is to have CiTestCase be the base test case for tests.
 * test_net: switch to CiTestCase and fix usage that was
   silently broken, because of exe bit.
 * populate_dir: return the list of files that it writes rather
   than having no return value.
 * CiTestCase:
    * support tmp_path("foo") that returns a full path to 'foo'
      under a tmpdir.
    * add tmp_dir() to get a temp dir and clean up.

To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/tests/unittests/helpers.py b/tests/unittests/helpers.py
2index a093346..90e2431 100644
3--- a/tests/unittests/helpers.py
4+++ b/tests/unittests/helpers.py
5@@ -2,6 +2,7 @@
6
7 from __future__ import print_function
8
9+import functools
10 import os
11 import shutil
12 import sys
13@@ -82,6 +83,28 @@ class TestCase(unittest2.TestCase):
14 pass
15
16
17+class CiTestCase(TestCase):
18+ """This is the preferred test case base class unless user
19+ needs other test case classes below."""
20+ def tmp_dir(self, dir=None, cleanup=True):
21+ # return a full path to a temporary directory that will be cleaned up.
22+ if dir is None:
23+ tmpd = tempfile.mkdtemp(
24+ prefix="ci-%s." % self.__class__.__name__)
25+ else:
26+ tmpd = tempfile.mkdtemp(dir=dir)
27+ self.addCleanup(functools.partial(shutil.rmtree, tmpd))
28+ return tmpd
29+
30+ def tmp_path(self, path, dir=None):
31+ # return an absolute path to 'path' under dir.
32+ # if dir is None, one will be created with tmp_dir()
33+ # the file is not created or modified.
34+ if dir is None:
35+ dir = self.tmp_dir()
36+ return os.path.normpath(os.path.abspath(os.path.join(dir, path)))
37+
38+
39 class ResourceUsingTestCase(TestCase):
40 def setUp(self):
41 super(ResourceUsingTestCase, self).setUp()
42@@ -227,29 +250,10 @@ class HttprettyTestCase(TestCase):
43 super(HttprettyTestCase, self).tearDown()
44
45
46-class TempDirTestCase(TestCase):
47- # provide a tempdir per class, not per test.
48- @classmethod
49- def setUpClass(cls):
50- cls.tmpd = tempfile.mkdtemp(prefix="ci-%s." % cls.__name__)
51- return TestCase.setUpClass()
52-
53- @classmethod
54- def tearDownClass(cls):
55- shutil.rmtree(cls.tmpd)
56- return TestCase.tearDownClass()
57-
58- def tmp_path(self, path):
59- # if absolute path (starts with /), then make ./path
60- if path.startswith(os.path.sep):
61- path = "." + path
62-
63- return os.path.normpath(os.path.join(self.tmpd, path))
64-
65-
66 def populate_dir(path, files):
67 if not os.path.exists(path):
68 os.makedirs(path)
69+ ret = []
70 for (name, content) in files.items():
71 p = os.path.join(path, name)
72 util.ensure_dir(os.path.dirname(p))
73@@ -259,6 +263,9 @@ def populate_dir(path, files):
74 else:
75 fp.write(content.encode('utf-8'))
76 fp.close()
77+ ret.append(p)
78+
79+ return ret
80
81
82 def dir2dict(startdir, prefix=None):
83diff --git a/tests/unittests/test__init__.py b/tests/unittests/test__init__.py
84index e6f4c31..781f6d5 100644
85--- a/tests/unittests/test__init__.py
86+++ b/tests/unittests/test__init__.py
87@@ -12,7 +12,7 @@ from cloudinit import settings
88 from cloudinit import url_helper
89 from cloudinit import util
90
91-from .helpers import TestCase, TempDirTestCase, ExitStack, mock
92+from .helpers import TestCase, CiTestCase, ExitStack, mock
93
94
95 class FakeModule(handlers.Handler):
96@@ -172,7 +172,7 @@ class TestHandlerHandlePart(TestCase):
97 self.data, self.ctype, self.filename, self.payload)
98
99
100-class TestCmdlineUrl(TempDirTestCase):
101+class TestCmdlineUrl(CiTestCase):
102 def test_parse_cmdline_url_nokey_raises_keyerror(self):
103 self.assertRaises(
104 KeyError, main.parse_cmdline_url, 'root=foo bar single')
105@@ -189,7 +189,7 @@ class TestCmdlineUrl(TempDirTestCase):
106 cmdline = "ro %s=%s bar=1" % (key, url)
107 m_read.return_value = url_helper.StringResponse(b"unexpected blob")
108
109- fpath = self.tmp_path("test_valid")
110+ fpath = self.tmp_path("ccfile")
111 lvl, msg = main.attempt_cmdline_url(
112 fpath, network=True, cmdline=cmdline)
113 self.assertEqual(logging.WARN, lvl)
114@@ -203,7 +203,7 @@ class TestCmdlineUrl(TempDirTestCase):
115 cmdline = "ro %s=%s bar=1" % ('cloud-config-url', url)
116
117 m_read.return_value = url_helper.StringResponse(payload)
118- fpath = self.tmp_path("test_valid")
119+ fpath = self.tmp_path("ccfile")
120 lvl, msg = main.attempt_cmdline_url(
121 fpath, network=True, cmdline=cmdline)
122 self.assertEqual(util.load_file(fpath, decode=False), payload)
123@@ -213,7 +213,7 @@ class TestCmdlineUrl(TempDirTestCase):
124 @mock.patch('cloudinit.cmd.main.util.read_file_or_url')
125 def test_no_key_found(self, m_read):
126 cmdline = "ro mykey=http://example.com/foo root=foo"
127- fpath = self.tmp_path("test_no_key_found")
128+ fpath = self.tmp_path("ccpath")
129 lvl, msg = main.attempt_cmdline_url(
130 fpath, network=True, cmdline=cmdline)
131
132@@ -225,7 +225,7 @@ class TestCmdlineUrl(TempDirTestCase):
133 def test_exception_warns(self, m_read):
134 url = "http://example.com/foo"
135 cmdline = "ro cloud-config-url=%s root=LABEL=bar" % url
136- fpath = self.tmp_path("test_no_key_found")
137+ fpath = self.tmp_path("ccfile")
138 m_read.side_effect = url_helper.UrlError(
139 cause="Unexpected Error", url="http://example.com/foo")
140
141diff --git a/tests/unittests/test_atomic_helper.py b/tests/unittests/test_atomic_helper.py
142index e170c7c..515919d 100644
143--- a/tests/unittests/test_atomic_helper.py
144+++ b/tests/unittests/test_atomic_helper.py
145@@ -6,10 +6,10 @@ import stat
146
147 from cloudinit import atomic_helper
148
149-from . import helpers
150+from .helpers import CiTestCase
151
152
153-class TestAtomicHelper(helpers.TempDirTestCase):
154+class TestAtomicHelper(CiTestCase):
155 def test_basic_usage(self):
156 """write_file takes bytes if no omode."""
157 path = self.tmp_path("test_basic_usage")
158diff --git a/tests/unittests/test_distros/test_user_data_normalize.py b/tests/unittests/test_distros/test_user_data_normalize.py
159old mode 100755
160new mode 100644
161index 88746e0..88746e0
162--- a/tests/unittests/test_distros/test_user_data_normalize.py
163+++ b/tests/unittests/test_distros/test_user_data_normalize.py
164diff --git a/tests/unittests/test_net.py b/tests/unittests/test_net.py
165old mode 100755
166new mode 100644
167index 1090282..2c2bde9
168--- a/tests/unittests/test_net.py
169+++ b/tests/unittests/test_net.py
170@@ -8,11 +8,10 @@ from cloudinit.net import sysconfig
171 from cloudinit.sources.helpers import openstack
172 from cloudinit import util
173
174+from .helpers import CiTestCase
175 from .helpers import dir2dict
176 from .helpers import mock
177 from .helpers import populate_dir
178-from .helpers import TempDirTestCase
179-from .helpers import TestCase
180
181 import base64
182 import copy
183@@ -20,8 +19,6 @@ import gzip
184 import io
185 import json
186 import os
187-import shutil
188-import tempfile
189 import textwrap
190 import yaml
191
192@@ -478,7 +475,7 @@ def _setup_test(tmp_dir, mock_get_devicelist, mock_read_sys_net,
193 mock_sys_dev_path.side_effect = sys_dev_path
194
195
196-class TestSysConfigRendering(TestCase):
197+class TestSysConfigRendering(CiTestCase):
198
199 @mock.patch("cloudinit.net.sys_dev_path")
200 @mock.patch("cloudinit.net.read_sys_net")
201@@ -486,8 +483,7 @@ class TestSysConfigRendering(TestCase):
202 def test_default_generation(self, mock_get_devicelist,
203 mock_read_sys_net,
204 mock_sys_dev_path):
205- tmp_dir = tempfile.mkdtemp()
206- self.addCleanup(shutil.rmtree, tmp_dir)
207+ tmp_dir = self.tmp_dir()
208 _setup_test(tmp_dir, mock_get_devicelist,
209 mock_read_sys_net, mock_sys_dev_path)
210
211@@ -518,9 +514,7 @@ USERCTL=no
212 self.assertEqual(expected_content, content)
213
214 def test_openstack_rendering_samples(self):
215- tmp_dir = tempfile.mkdtemp()
216- self.addCleanup(shutil.rmtree, tmp_dir)
217- render_dir = os.path.join(tmp_dir, "render")
218+ render_dir = self.tmp_dir()
219 for os_sample in OS_SAMPLES:
220 ex_input = os_sample['in_data']
221 ex_mac_addrs = os_sample['in_macs']
222@@ -535,7 +529,7 @@ USERCTL=no
223 self.assertEqual(expected_content, fh.read())
224
225
226-class TestEniNetRendering(TestCase):
227+class TestEniNetRendering(CiTestCase):
228
229 @mock.patch("cloudinit.net.sys_dev_path")
230 @mock.patch("cloudinit.net.read_sys_net")
231@@ -543,8 +537,7 @@ class TestEniNetRendering(TestCase):
232 def test_default_generation(self, mock_get_devicelist,
233 mock_read_sys_net,
234 mock_sys_dev_path):
235- tmp_dir = tempfile.mkdtemp()
236- self.addCleanup(shutil.rmtree, tmp_dir)
237+ tmp_dir = self.tmp_dir()
238 _setup_test(tmp_dir, mock_get_devicelist,
239 mock_read_sys_net, mock_sys_dev_path)
240
241@@ -576,7 +569,7 @@ iface eth1000 inet dhcp
242 self.assertEqual(expected.lstrip(), contents.lstrip())
243
244
245-class TestEniNetworkStateToEni(TestCase):
246+class TestEniNetworkStateToEni(CiTestCase):
247 mycfg = {
248 'config': [{"type": "physical", "name": "eth0",
249 "mac_address": "c0:d6:9f:2c:e8:80",
250@@ -607,7 +600,7 @@ class TestEniNetworkStateToEni(TestCase):
251 self.assertNotIn("hwaddress", rendered)
252
253
254-class TestCmdlineConfigParsing(TestCase):
255+class TestCmdlineConfigParsing(CiTestCase):
256 simple_cfg = {
257 'config': [{"type": "physical", "name": "eth0",
258 "mac_address": "c0:d6:9f:2c:e8:80",
259@@ -665,7 +658,7 @@ class TestCmdlineConfigParsing(TestCase):
260 self.assertEqual(found, self.simple_cfg)
261
262
263-class TestCmdlineReadKernelConfig(TempDirTestCase):
264+class TestCmdlineReadKernelConfig(CiTestCase):
265 macs = {
266 'eth0': '14:02:ec:42:48:00',
267 'eno1': '14:02:ec:42:48:01',
268@@ -673,8 +666,7 @@ class TestCmdlineReadKernelConfig(TempDirTestCase):
269
270 def test_ip_cmdline_read_kernel_cmdline_ip(self):
271 content = {'net-eth0.conf': DHCP_CONTENT_1}
272- populate_dir(self.tmp, content)
273- files = [os.path.join(self.tmp, k) for k in content.keys()]
274+ files = sorted(populate_dir(self.tmp_dir(), content))
275 found = cmdline.read_kernel_cmdline_config(
276 files=files, cmdline='foo ip=dhcp', mac_addrs=self.macs)
277 exp1 = copy.deepcopy(DHCP_EXPECTED_1)
278@@ -684,8 +676,7 @@ class TestCmdlineReadKernelConfig(TempDirTestCase):
279
280 def test_ip_cmdline_read_kernel_cmdline_ip6(self):
281 content = {'net6-eno1.conf': DHCP6_CONTENT_1}
282- populate_dir(self.tmp, content)
283- files = [os.path.join(self.tmp, k) for k in content.keys()]
284+ files = sorted(populate_dir(self.tmp_dir(), content))
285 found = cmdline.read_kernel_cmdline_config(
286 files=files, cmdline='foo ip6=dhcp root=/dev/sda',
287 mac_addrs=self.macs)
288@@ -701,8 +692,7 @@ class TestCmdlineReadKernelConfig(TempDirTestCase):
289 def test_ip_cmdline_read_kernel_cmdline_none(self):
290 # if there is no ip= or ip6= on cmdline, return value should be None
291 content = {'net6-eno1.conf': DHCP6_CONTENT_1}
292- populate_dir(self.tmp, content)
293- files = [os.path.join(self.tmp, k) for k in content.keys()]
294+ files = sorted(populate_dir(self.tmp_dir(), content))
295 found = cmdline.read_kernel_cmdline_config(
296 files=files, cmdline='foo root=/dev/sda', mac_addrs=self.macs)
297 self.assertEqual(found, None)
298@@ -710,8 +700,7 @@ class TestCmdlineReadKernelConfig(TempDirTestCase):
299 def test_ip_cmdline_both_ip_ip6(self):
300 content = {'net-eth0.conf': DHCP_CONTENT_1,
301 'net6-eth0.conf': DHCP6_CONTENT_1.replace('eno1', 'eth0')}
302- populate_dir(self.tmp, content)
303- files = [os.path.join(self.tmp, k) for k in sorted(content.keys())]
304+ files = sorted(populate_dir(self.tmp_dir(), content))
305 found = cmdline.read_kernel_cmdline_config(
306 files=files, cmdline='foo ip=dhcp ip6=dhcp', mac_addrs=self.macs)
307
308@@ -725,14 +714,12 @@ class TestCmdlineReadKernelConfig(TempDirTestCase):
309 self.assertEqual(found['config'], expected)
310
311
312-class TestEniRoundTrip(TestCase):
313- def setUp(self):
314- super(TestCase, self).setUp()
315- self.tmp_dir = tempfile.mkdtemp()
316- self.addCleanup(shutil.rmtree, self.tmp_dir)
317-
318+class TestEniRoundTrip(CiTestCase):
319 def _render_and_read(self, network_config=None, state=None, eni_path=None,
320- links_prefix=None, netrules_path=None):
321+ links_prefix=None, netrules_path=None, dir=None):
322+ if dir is None:
323+ dir = self.tmp_dir()
324+
325 if network_config:
326 ns = network_state.parse_net_config_data(network_config)
327 elif state:
328@@ -747,8 +734,8 @@ class TestEniRoundTrip(TestCase):
329 config={'eni_path': eni_path, 'links_path_prefix': links_prefix,
330 'netrules_path': netrules_path})
331
332- renderer.render_network_state(self.tmp_dir, ns)
333- return dir2dict(self.tmp_dir)
334+ renderer.render_network_state(dir, ns)
335+ return dir2dict(dir)
336
337 def testsimple_convert_and_render(self):
338 network_config = eni.convert_eni_data(EXAMPLE_ENI)

Subscribers

People subscribed via source and target branches