Merge lp:~chad.smith/curtin/common-ci-test-case into lp:~curtin-dev/curtin/trunk
- common-ci-test-case
- Merge into trunk
Status: | Merged |
---|---|
Merged at revision: | 519 |
Proposed branch: | lp:~chad.smith/curtin/common-ci-test-case |
Merge into: | lp:~curtin-dev/curtin/trunk |
Diff against target: |
1483 lines (+247/-347) 24 files modified
tests/unittests/helpers.py (+36/-0) tests/unittests/test_apt_custom_sources_list.py (+3/-6) tests/unittests/test_apt_source.py (+4/-7) tests/unittests/test_basic.py (+4/-4) tests/unittests/test_block.py (+20/-36) tests/unittests/test_block_iscsi.py (+6/-18) tests/unittests/test_block_lvm.py (+2/-2) tests/unittests/test_block_mdadm.py (+10/-22) tests/unittests/test_block_mkfs.py (+2/-2) tests/unittests/test_clear_holders.py (+5/-5) tests/unittests/test_commands_apply_net.py (+8/-20) tests/unittests/test_commands_block_meta.py (+6/-19) tests/unittests/test_commands_install.py (+4/-4) tests/unittests/test_config.py (+6/-6) tests/unittests/test_curthooks.py (+21/-46) tests/unittests/test_feature.py (+2/-2) tests/unittests/test_gpg.py (+4/-4) tests/unittests/test_make_dname.py (+4/-4) tests/unittests/test_net.py (+8/-14) tests/unittests/test_partitioning.py (+4/-3) tests/unittests/test_public.py (+4/-4) tests/unittests/test_reporter.py (+29/-38) tests/unittests/test_util.py (+48/-62) tests/unittests/test_version.py (+7/-19) |
To merge this branch: | bzr merge lp:~chad.smith/curtin/common-ci-test-case |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Server Team CI bot | continuous-integration | Approve | |
curtin developers | Pending | ||
Review via email: mp+328477@code.launchpad.net |
Commit message
tests: Add CiTestCase common parent for all curtin tests
This branch makes sure all unittests subclass from CiTestCase which provides all unit tests with an add_patch method for mocking as well as tmp_dir and tmp_path creation.
Drop any unittest-specific tempfile setup in favor of self.tmp_dir and self.tmp_path.
Also drop any duplicate add_patch method definitions and convert any mock start/stop logic to add_patch where possible.
Description of the change
tests: Add CiTestCase common parent for all curtin tests
This branch makes sure all unittests subclass from CiTestCase which provides all unit tests with an add_patch method for mocking as well as tmp_dir and tmp_path creation.
Drop any unittest-specific tempfile setup in favor of self.tmp_dir and self.tmp_path.
Also drop any duplicate add_patch method definitions and convert any mock start/stop logic to add_patch where possible.
Server Team CI bot (server-team-bot) wrote : | # |
Ryan Harper (raharper) wrote : | # |
Thanks for starting this.
I'd suggest also adding in the add_patch() which is repeated in many of the base classes in the unittests. It's fine if we punt that to a second MP after this lands as well.
Overall looks fine, couple of questions in line.
Scott Moser (smoser) wrote : | # |
responded to ryan's comment in line. lets drop the functools.
- 518. By Chad Smith
-
drop functools partial as it is unneeded
Chad Smith (chad.smith) : | # |
Server Team CI bot (server-team-bot) wrote : | # |
PASSED: Continuous integration, rev:518
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
Click here to trigger a rebuild:
https:/
- 519. By Chad Smith
-
move add_patch up into CiTestCase, drop all add_patch definitions in subclasses. Convert any locally defined mock start/stop definitions to use add_patch
- 520. By Chad Smith
-
add missing super...setUp calls to classes which have overridden the unittest.setUp method
Server Team CI bot (server-team-bot) wrote : | # |
FAILED: Continuous integration, rev:520
https:/
Executed test runs:
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
Ryan Harper (raharper) wrote : | # |
Looks good once you make tox happy
- 521. By Chad Smith
-
allow kwargs passed into CiTestCase.
add_patch per review comments
Server Team CI bot (server-team-bot) wrote : | # |
PASSED: Continuous integration, rev:521
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
Click here to trigger a rebuild:
https:/
Preview Diff
1 | === modified file 'tests/unittests/helpers.py' |
2 | --- tests/unittests/helpers.py 2016-11-30 22:57:10 +0000 |
3 | +++ tests/unittests/helpers.py 2017-08-03 19:32:06 +0000 |
4 | @@ -19,6 +19,10 @@ |
5 | import imp |
6 | import importlib |
7 | import mock |
8 | +import os |
9 | +import shutil |
10 | +import tempfile |
11 | +from unittest import TestCase |
12 | |
13 | |
14 | def builtin_module_name(): |
15 | @@ -43,3 +47,35 @@ |
16 | m_patch = '{}.open'.format(mod_name) |
17 | with mock.patch(m_patch, m_open, create=True): |
18 | yield m_open |
19 | + |
20 | + |
21 | +class CiTestCase(TestCase): |
22 | + """Common testing class which all curtin unit tests subclass.""" |
23 | + |
24 | + def add_patch(self, target, attr, **kwargs): |
25 | + """Patches specified target object and sets it as attr on test |
26 | + instance also schedules cleanup""" |
27 | + if 'autospec' not in kwargs: |
28 | + kwargs['autospec'] = True |
29 | + m = mock.patch(target, **kwargs) |
30 | + p = m.start() |
31 | + self.addCleanup(m.stop) |
32 | + setattr(self, attr, p) |
33 | + |
34 | + def tmp_dir(self, dir=None, cleanup=True): |
35 | + """Return a full path to a temporary directory for the test run.""" |
36 | + if dir is None: |
37 | + tmpd = tempfile.mkdtemp( |
38 | + prefix="curtin-ci-%s." % self.__class__.__name__) |
39 | + else: |
40 | + tmpd = tempfile.mkdtemp(dir=dir) |
41 | + self.addCleanup(shutil.rmtree, tmpd) |
42 | + return tmpd |
43 | + |
44 | + def tmp_path(self, path, _dir=None): |
45 | + # return an absolute path to 'path' under dir. |
46 | + # if dir is None, one will be created with tmp_dir() |
47 | + # the file is not created or modified. |
48 | + if _dir is None: |
49 | + _dir = self.tmp_dir() |
50 | + return os.path.normpath(os.path.abspath(os.path.join(_dir, path))) |
51 | |
52 | === modified file 'tests/unittests/test_apt_custom_sources_list.py' |
53 | --- tests/unittests/test_apt_custom_sources_list.py 2016-07-29 10:27:20 +0000 |
54 | +++ tests/unittests/test_apt_custom_sources_list.py 2017-08-03 19:32:06 +0000 |
55 | @@ -3,10 +3,7 @@ |
56 | """ |
57 | import logging |
58 | import os |
59 | -import shutil |
60 | -import tempfile |
61 | |
62 | -from unittest import TestCase |
63 | |
64 | import yaml |
65 | import mock |
66 | @@ -14,6 +11,7 @@ |
67 | |
68 | from curtin import util |
69 | from curtin.commands import apt_config |
70 | +from .helpers import CiTestCase |
71 | |
72 | LOG = logging.getLogger(__name__) |
73 | |
74 | @@ -85,12 +83,11 @@ |
75 | """) |
76 | |
77 | |
78 | -class TestAptSourceConfigSourceList(TestCase): |
79 | +class TestAptSourceConfigSourceList(CiTestCase): |
80 | """TestAptSourceConfigSourceList - Class to test sources list rendering""" |
81 | def setUp(self): |
82 | super(TestAptSourceConfigSourceList, self).setUp() |
83 | - self.new_root = tempfile.mkdtemp() |
84 | - self.addCleanup(shutil.rmtree, self.new_root) |
85 | + self.new_root = self.tmp_dir() |
86 | # self.patchUtils(self.new_root) |
87 | |
88 | @staticmethod |
89 | |
90 | === modified file 'tests/unittests/test_apt_source.py' |
91 | --- tests/unittests/test_apt_source.py 2017-02-09 19:59:11 +0000 |
92 | +++ tests/unittests/test_apt_source.py 2017-08-03 19:32:06 +0000 |
93 | @@ -4,11 +4,8 @@ |
94 | import glob |
95 | import os |
96 | import re |
97 | -import shutil |
98 | import socket |
99 | -import tempfile |
100 | |
101 | -from unittest import TestCase |
102 | |
103 | import mock |
104 | from mock import call |
105 | @@ -16,6 +13,7 @@ |
106 | from curtin import util |
107 | from curtin import gpg |
108 | from curtin.commands import apt_config |
109 | +from .helpers import CiTestCase |
110 | |
111 | |
112 | EXPECTEDKEY = u"""-----BEGIN PGP PUBLIC KEY BLOCK----- |
113 | @@ -62,14 +60,13 @@ |
114 | ChrootableTargetStr = "curtin.commands.apt_config.util.ChrootableTarget" |
115 | |
116 | |
117 | -class TestAptSourceConfig(TestCase): |
118 | +class TestAptSourceConfig(CiTestCase): |
119 | """ TestAptSourceConfig |
120 | Main Class to test apt configs |
121 | """ |
122 | def setUp(self): |
123 | super(TestAptSourceConfig, self).setUp() |
124 | - self.tmp = tempfile.mkdtemp() |
125 | - self.addCleanup(shutil.rmtree, self.tmp) |
126 | + self.tmp = self.tmp_dir() |
127 | self.aptlistfile = os.path.join(self.tmp, "single-deb.list") |
128 | self.aptlistfile2 = os.path.join(self.tmp, "single-deb2.list") |
129 | self.aptlistfile3 = os.path.join(self.tmp, "single-deb3.list") |
130 | @@ -930,7 +927,7 @@ |
131 | orig, apt_config.disable_suites(["proposed"], orig, rel)) |
132 | |
133 | |
134 | -class TestDebconfSelections(TestCase): |
135 | +class TestDebconfSelections(CiTestCase): |
136 | |
137 | @mock.patch("curtin.commands.apt_config.debconf_set_selections") |
138 | def test_no_set_sel_if_none_to_set(self, m_set_sel): |
139 | |
140 | === modified file 'tests/unittests/test_basic.py' |
141 | --- tests/unittests/test_basic.py 2013-07-29 19:59:51 +0000 |
142 | +++ tests/unittests/test_basic.py 2017-08-03 19:32:06 +0000 |
143 | @@ -1,7 +1,7 @@ |
144 | -from unittest import TestCase |
145 | - |
146 | - |
147 | -class TestImport(TestCase): |
148 | +from .helpers import CiTestCase |
149 | + |
150 | + |
151 | +class TestImport(CiTestCase): |
152 | def test_import(self): |
153 | import curtin |
154 | self.assertFalse(getattr(curtin, 'BOGUS_ENTRY', None)) |
155 | |
156 | === modified file 'tests/unittests/test_block.py' |
157 | --- tests/unittests/test_block.py 2017-05-22 20:10:23 +0000 |
158 | +++ tests/unittests/test_block.py 2017-08-03 19:32:06 +0000 |
159 | @@ -1,19 +1,16 @@ |
160 | -from unittest import TestCase |
161 | import functools |
162 | import os |
163 | import mock |
164 | -import tempfile |
165 | -import shutil |
166 | import sys |
167 | |
168 | from collections import OrderedDict |
169 | |
170 | -from .helpers import simple_mocked_open |
171 | +from .helpers import CiTestCase, simple_mocked_open |
172 | from curtin import util |
173 | from curtin import block |
174 | |
175 | |
176 | -class TestBlock(TestCase): |
177 | +class TestBlock(CiTestCase): |
178 | |
179 | @mock.patch("curtin.block.util") |
180 | def test_get_volume_uuid(self, mock_util): |
181 | @@ -103,7 +100,7 @@ |
182 | block.lookup_disk(serial) |
183 | |
184 | |
185 | -class TestSysBlockPath(TestCase): |
186 | +class TestSysBlockPath(CiTestCase): |
187 | @mock.patch("curtin.block.get_blockdev_for_partition") |
188 | @mock.patch("os.path.exists") |
189 | def test_existing_valid_devname(self, m_os_path_exists, m_get_blk): |
190 | @@ -177,19 +174,13 @@ |
191 | block.sys_block_path('/dev/cciss/c0d0p1')) |
192 | |
193 | |
194 | -class TestWipeFile(TestCase): |
195 | +class TestWipeFile(CiTestCase): |
196 | def __init__(self, *args, **kwargs): |
197 | super(TestWipeFile, self).__init__(*args, **kwargs) |
198 | |
199 | - def tfile(self, *args): |
200 | - # return a temp file in a dir that will be cleaned up |
201 | - tmpdir = tempfile.mkdtemp() |
202 | - self.addCleanup(shutil.rmtree, tmpdir) |
203 | - return os.path.sep.join([tmpdir] + list(args)) |
204 | - |
205 | def test_non_exist_raises_file_not_found(self): |
206 | try: |
207 | - p = self.tfile("enofile") |
208 | + p = self.tmp_path("enofile") |
209 | block.wipe_file(p) |
210 | raise Exception("%s did not raise exception" % p) |
211 | except Exception as e: |
212 | @@ -198,7 +189,7 @@ |
213 | |
214 | def test_non_exist_dir_raises_file_not_found(self): |
215 | try: |
216 | - p = self.tfile("enodir", "file") |
217 | + p = self.tmp_path(os.path.sep.join(["enodir", "file"])) |
218 | block.wipe_file(p) |
219 | raise Exception("%s did not raise exception" % p) |
220 | except Exception as e: |
221 | @@ -207,7 +198,7 @@ |
222 | |
223 | def test_default_is_zero(self): |
224 | flen = 1024 |
225 | - myfile = self.tfile("def_zero") |
226 | + myfile = self.tmp_path("def_zero") |
227 | util.write_file(myfile, flen * b'\1', omode="wb") |
228 | block.wipe_file(myfile) |
229 | found = util.load_file(myfile, decode=False) |
230 | @@ -219,7 +210,7 @@ |
231 | def reader(size): |
232 | return size * b'\1' |
233 | |
234 | - myfile = self.tfile("reader_used") |
235 | + myfile = self.tmp_path("reader_used") |
236 | # populate with nulls |
237 | util.write_file(myfile, flen * b'\0', omode="wb") |
238 | block.wipe_file(myfile, reader=reader, buflen=flen) |
239 | @@ -236,15 +227,15 @@ |
240 | data['x'] = data['x'][size:] |
241 | return buf |
242 | |
243 | - myfile = self.tfile("reader_twice") |
244 | + myfile = self.tmp_path("reader_twice") |
245 | util.write_file(myfile, flen * b'\xff', omode="wb") |
246 | block.wipe_file(myfile, reader=reader, buflen=20) |
247 | found = util.load_file(myfile, decode=False) |
248 | self.assertEqual(found, expected) |
249 | |
250 | def test_reader_fhandle(self): |
251 | - srcfile = self.tfile("fhandle_src") |
252 | - trgfile = self.tfile("fhandle_trg") |
253 | + srcfile = self.tmp_path("fhandle_src") |
254 | + trgfile = self.tmp_path("fhandle_trg") |
255 | data = '\n'.join(["this is source file." for f in range(0, 10)] + []) |
256 | util.write_file(srcfile, data) |
257 | util.write_file(trgfile, 'a' * len(data)) |
258 | @@ -254,7 +245,7 @@ |
259 | self.assertEqual(data, found) |
260 | |
261 | def test_exclusive_open_raise_missing(self): |
262 | - myfile = self.tfile("no-such-file") |
263 | + myfile = self.tmp_path("no-such-file") |
264 | |
265 | with self.assertRaises(ValueError): |
266 | with block.exclusive_open(myfile) as fp: |
267 | @@ -265,7 +256,7 @@ |
268 | @mock.patch('os.open') |
269 | def test_exclusive_open(self, mock_os_open, mock_os_fdopen, mock_os_close): |
270 | flen = 1024 |
271 | - myfile = self.tfile("my_exclusive_file") |
272 | + myfile = self.tmp_path("my_exclusive_file") |
273 | util.write_file(myfile, flen * b'\1', omode="wb") |
274 | mock_fd = 3 |
275 | mock_os_open.return_value = mock_fd |
276 | @@ -288,7 +279,7 @@ |
277 | mock_os_close, |
278 | mock_util_fuser): |
279 | flen = 1024 |
280 | - myfile = self.tfile("my_exclusive_file") |
281 | + myfile = self.tmp_path("my_exclusive_file") |
282 | util.write_file(myfile, flen * b'\1', omode="wb") |
283 | mock_os_open.side_effect = OSError("NO_O_EXCL") |
284 | mock_holders.return_value = ['md1'] |
285 | @@ -310,7 +301,7 @@ |
286 | def test_exclusive_open_fdopen_failure(self, mock_os_open, |
287 | mock_os_fdopen, mock_os_close): |
288 | flen = 1024 |
289 | - myfile = self.tfile("my_exclusive_file") |
290 | + myfile = self.tmp_path("my_exclusive_file") |
291 | util.write_file(myfile, flen * b'\1', omode="wb") |
292 | mock_fd = 3 |
293 | mock_os_open.return_value = mock_fd |
294 | @@ -328,7 +319,7 @@ |
295 | self.assertEqual([], mock_os_close.call_args_list) |
296 | |
297 | |
298 | -class TestWipeVolume(TestCase): |
299 | +class TestWipeVolume(CiTestCase): |
300 | dev = '/dev/null' |
301 | |
302 | @mock.patch('curtin.block.lvm') |
303 | @@ -366,7 +357,7 @@ |
304 | block.wipe_volume(self.dev, mode='invalidmode') |
305 | |
306 | |
307 | -class TestBlockKnames(TestCase): |
308 | +class TestBlockKnames(CiTestCase): |
309 | """Tests for some of the kname functions in block""" |
310 | def test_determine_partition_kname(self): |
311 | part_knames = [(('sda', 1), 'sda1'), |
312 | @@ -430,7 +421,7 @@ |
313 | block.kname_to_path(kname) |
314 | |
315 | |
316 | -class TestPartTableSignature(TestCase): |
317 | +class TestPartTableSignature(CiTestCase): |
318 | blockdev = '/dev/null' |
319 | dos_content = b'\x00' * 0x1fe + b'\x55\xAA' + b'\x00' * 0xf00 |
320 | gpt_content = b'\x00' * 0x200 + b'EFI PART' + b'\x00' * (0x200 - 8) |
321 | @@ -493,7 +484,7 @@ |
322 | block.check_efi_signature(self.blockdev)) |
323 | |
324 | |
325 | -class TestNonAscii(TestCase): |
326 | +class TestNonAscii(CiTestCase): |
327 | @mock.patch('curtin.block.util.subp') |
328 | def test_lsblk(self, mock_subp): |
329 | # lsblk can write non-ascii data, causing shlex to blow up |
330 | @@ -519,14 +510,7 @@ |
331 | block.blkid() |
332 | |
333 | |
334 | -class TestSlaveKnames(TestCase): |
335 | - def add_patch(self, target, attr, autospec=True): |
336 | - """Patches specified target object and sets it as attr on test |
337 | - instance also schedules cleanup""" |
338 | - m = mock.patch(target, autospec=autospec) |
339 | - p = m.start() |
340 | - self.addCleanup(m.stop) |
341 | - setattr(self, attr, p) |
342 | +class TestSlaveKnames(CiTestCase): |
343 | |
344 | def setUp(self): |
345 | super(TestSlaveKnames, self).setUp() |
346 | |
347 | === modified file 'tests/unittests/test_block_iscsi.py' |
348 | --- tests/unittests/test_block_iscsi.py 2017-05-12 20:20:02 +0000 |
349 | +++ tests/unittests/test_block_iscsi.py 2017-08-03 19:32:06 +0000 |
350 | @@ -1,23 +1,11 @@ |
351 | import mock |
352 | |
353 | -from unittest import TestCase |
354 | from curtin.block import iscsi |
355 | - |
356 | - |
357 | -class IscsiTestBase(TestCase): |
358 | - def setUp(self): |
359 | - super(IscsiTestBase, self).setUp() |
360 | - |
361 | - def add_patch(self, target, attr): |
362 | - """Patches specified target object and sets it as attr on test |
363 | - instance also schedules cleanup""" |
364 | - m = mock.patch(target, autospec=True) |
365 | - p = m.start() |
366 | - self.addCleanup(m.stop) |
367 | - setattr(self, attr, p) |
368 | - |
369 | - |
370 | -class TestBlockIscsiPortalParsing(IscsiTestBase): |
371 | +from .helpers import CiTestCase |
372 | + |
373 | + |
374 | +class TestBlockIscsiPortalParsing(CiTestCase): |
375 | + |
376 | def test_iscsi_portal_parsing_string(self): |
377 | with self.assertRaisesRegexp(ValueError, 'not a string'): |
378 | iscsi.assert_valid_iscsi_portal(1234) |
379 | @@ -490,7 +478,7 @@ |
380 | self.assertEquals(i.target, 'iqn.2017-04.com.example.test:target-name') |
381 | |
382 | |
383 | -class TestBlockIscsiVolPath(IscsiTestBase): |
384 | +class TestBlockIscsiVolPath(CiTestCase): |
385 | # non-iscsi backed disk returns false |
386 | # regular iscsi-backed disk returns true |
387 | # layered setup without an iscsi member returns false |
388 | |
389 | === modified file 'tests/unittests/test_block_lvm.py' |
390 | --- tests/unittests/test_block_lvm.py 2016-08-15 14:52:56 +0000 |
391 | +++ tests/unittests/test_block_lvm.py 2017-08-03 19:32:06 +0000 |
392 | @@ -1,10 +1,10 @@ |
393 | from curtin.block import lvm |
394 | |
395 | -from unittest import TestCase |
396 | +from .helpers import CiTestCase |
397 | import mock |
398 | |
399 | |
400 | -class TestBlockLvm(TestCase): |
401 | +class TestBlockLvm(CiTestCase): |
402 | vg_name = 'ubuntu-volgroup' |
403 | |
404 | @mock.patch('curtin.block.lvm.util') |
405 | |
406 | === modified file 'tests/unittests/test_block_mdadm.py' |
407 | --- tests/unittests/test_block_mdadm.py 2017-05-08 20:38:48 +0000 |
408 | +++ tests/unittests/test_block_mdadm.py 2017-08-03 19:32:06 +0000 |
409 | @@ -1,27 +1,15 @@ |
410 | -from unittest import TestCase |
411 | from mock import call, patch |
412 | from curtin.block import dev_short |
413 | from curtin.block import mdadm |
414 | from curtin import util |
415 | +from .helpers import CiTestCase |
416 | import os |
417 | import subprocess |
418 | import textwrap |
419 | |
420 | |
421 | -class MdadmTestBase(TestCase): |
422 | - def setUp(self): |
423 | - super(MdadmTestBase, self).setUp() |
424 | - |
425 | - def add_patch(self, target, attr): |
426 | - """Patches specified target object and sets it as attr on test |
427 | - instance also schedules cleanup""" |
428 | - m = patch(target, autospec=True) |
429 | - p = m.start() |
430 | - self.addCleanup(m.stop) |
431 | - setattr(self, attr, p) |
432 | - |
433 | - |
434 | -class TestBlockMdadmAssemble(MdadmTestBase): |
435 | +class TestBlockMdadmAssemble(CiTestCase): |
436 | + |
437 | def setUp(self): |
438 | super(TestBlockMdadmAssemble, self).setUp() |
439 | self.add_patch('curtin.block.mdadm.util', 'mock_util') |
440 | @@ -94,7 +82,7 @@ |
441 | rcs=[0, 1, 2]) |
442 | |
443 | |
444 | -class TestBlockMdadmCreate(MdadmTestBase): |
445 | +class TestBlockMdadmCreate(CiTestCase): |
446 | def setUp(self): |
447 | super(TestBlockMdadmCreate, self).setUp() |
448 | self.add_patch('curtin.block.mdadm.util', 'mock_util') |
449 | @@ -243,7 +231,7 @@ |
450 | self.mock_util.subp.assert_has_calls(expected_calls) |
451 | |
452 | |
453 | -class TestBlockMdadmExamine(MdadmTestBase): |
454 | +class TestBlockMdadmExamine(CiTestCase): |
455 | def setUp(self): |
456 | super(TestBlockMdadmExamine, self).setUp() |
457 | self.add_patch('curtin.block.mdadm.util', 'mock_util') |
458 | @@ -328,7 +316,7 @@ |
459 | self.assertEqual(data, {}) |
460 | |
461 | |
462 | -class TestBlockMdadmStop(MdadmTestBase): |
463 | +class TestBlockMdadmStop(CiTestCase): |
464 | def setUp(self): |
465 | super(TestBlockMdadmStop, self).setUp() |
466 | self.add_patch('curtin.block.mdadm.util.lsb_release', 'mock_util_lsb') |
467 | @@ -495,7 +483,7 @@ |
468 | self.mock_util_write_file.assert_has_calls(expected_writes) |
469 | |
470 | |
471 | -class TestBlockMdadmRemove(MdadmTestBase): |
472 | +class TestBlockMdadmRemove(CiTestCase): |
473 | def setUp(self): |
474 | super(TestBlockMdadmRemove, self).setUp() |
475 | self.add_patch('curtin.block.mdadm.util', 'mock_util') |
476 | @@ -521,7 +509,7 @@ |
477 | self.mock_util.subp.assert_has_calls(expected_calls) |
478 | |
479 | |
480 | -class TestBlockMdadmQueryDetail(MdadmTestBase): |
481 | +class TestBlockMdadmQueryDetail(CiTestCase): |
482 | def setUp(self): |
483 | super(TestBlockMdadmQueryDetail, self).setUp() |
484 | self.add_patch('curtin.block.mdadm.util', 'mock_util') |
485 | @@ -599,7 +587,7 @@ |
486 | '93a73e10:427f280b:b7076c02:204b8f7a') |
487 | |
488 | |
489 | -class TestBlockMdadmDetailScan(MdadmTestBase): |
490 | +class TestBlockMdadmDetailScan(CiTestCase): |
491 | def setUp(self): |
492 | super(TestBlockMdadmDetailScan, self).setUp() |
493 | self.add_patch('curtin.block.mdadm.util', 'mock_util') |
494 | @@ -634,7 +622,7 @@ |
495 | self.assertEqual(None, data) |
496 | |
497 | |
498 | -class TestBlockMdadmMdHelpers(MdadmTestBase): |
499 | +class TestBlockMdadmMdHelpers(CiTestCase): |
500 | def setUp(self): |
501 | super(TestBlockMdadmMdHelpers, self).setUp() |
502 | self.add_patch('curtin.block.mdadm.util', 'mock_util') |
503 | |
504 | === modified file 'tests/unittests/test_block_mkfs.py' |
505 | --- tests/unittests/test_block_mkfs.py 2016-06-30 21:40:28 +0000 |
506 | +++ tests/unittests/test_block_mkfs.py 2017-08-03 19:32:06 +0000 |
507 | @@ -1,10 +1,10 @@ |
508 | from curtin.block import mkfs |
509 | |
510 | -from unittest import TestCase |
511 | +from .helpers import CiTestCase |
512 | import mock |
513 | |
514 | |
515 | -class TestBlockMkfs(TestCase): |
516 | +class TestBlockMkfs(CiTestCase): |
517 | test_uuid = "fb26cc6c-ae73-11e5-9e38-2fb63f0c3155" |
518 | |
519 | def _get_config(self, fstype): |
520 | |
521 | === modified file 'tests/unittests/test_clear_holders.py' |
522 | --- tests/unittests/test_clear_holders.py 2017-05-30 15:27:14 +0000 |
523 | +++ tests/unittests/test_clear_holders.py 2017-08-03 19:32:06 +0000 |
524 | @@ -1,12 +1,12 @@ |
525 | -from unittest import TestCase |
526 | import mock |
527 | - |
528 | -from curtin.block import clear_holders |
529 | import os |
530 | import textwrap |
531 | |
532 | - |
533 | -class TestClearHolders(TestCase): |
534 | +from curtin.block import clear_holders |
535 | +from .helpers import CiTestCase |
536 | + |
537 | + |
538 | +class TestClearHolders(CiTestCase): |
539 | test_blockdev = '/dev/null' |
540 | test_syspath = '/sys/class/block/null' |
541 | remove_retries = [0.2] * 150 # clear_holders defaults to 30 seconds |
542 | |
543 | === modified file 'tests/unittests/test_commands_apply_net.py' |
544 | --- tests/unittests/test_commands_apply_net.py 2017-07-19 14:32:15 +0000 |
545 | +++ tests/unittests/test_commands_apply_net.py 2017-08-03 19:32:06 +0000 |
546 | @@ -1,26 +1,14 @@ |
547 | -from unittest import TestCase |
548 | from mock import patch, call |
549 | import copy |
550 | import os |
551 | |
552 | from curtin.commands import apply_net |
553 | from curtin import util |
554 | - |
555 | - |
556 | -class ApplyNetTestBase(TestCase): |
557 | - def setUp(self): |
558 | - super(ApplyNetTestBase, self).setUp() |
559 | - |
560 | - def add_patch(self, target, attr): |
561 | - """Patches specified target object and sets it as attr on test |
562 | - instance also schedules cleanup""" |
563 | - m = patch(target, autospec=True) |
564 | - p = m.start() |
565 | - self.addCleanup(m.stop) |
566 | - setattr(self, attr, p) |
567 | - |
568 | - |
569 | -class TestApplyNet(ApplyNetTestBase): |
570 | +from .helpers import CiTestCase |
571 | + |
572 | + |
573 | +class TestApplyNet(CiTestCase): |
574 | + |
575 | def setUp(self): |
576 | super(TestApplyNet, self).setUp() |
577 | |
578 | @@ -150,7 +138,7 @@ |
579 | self.m_ipv6_mtu.assert_called_with(self.target) |
580 | |
581 | |
582 | -class TestApplyNetPatchIfupdown(ApplyNetTestBase): |
583 | +class TestApplyNetPatchIfupdown(CiTestCase): |
584 | |
585 | @patch('curtin.util.write_file') |
586 | def test_apply_ipv6_mtu_hook(self, mock_write): |
587 | @@ -218,7 +206,7 @@ |
588 | self.assertEqual(0, mock_write.call_count) |
589 | |
590 | |
591 | -class TestApplyNetPatchIpv6Priv(ApplyNetTestBase): |
592 | +class TestApplyNetPatchIpv6Priv(CiTestCase): |
593 | |
594 | @patch('curtin.util.del_file') |
595 | @patch('curtin.util.load_file') |
596 | @@ -274,7 +262,7 @@ |
597 | self.assertEqual(0, mock_load.call_count) |
598 | |
599 | |
600 | -class TestApplyNetRemoveLegacyEth0(ApplyNetTestBase): |
601 | +class TestApplyNetRemoveLegacyEth0(CiTestCase): |
602 | |
603 | @patch('curtin.util.del_file') |
604 | @patch('curtin.util.load_file') |
605 | |
606 | === modified file 'tests/unittests/test_commands_block_meta.py' |
607 | --- tests/unittests/test_commands_block_meta.py 2017-03-22 15:34:21 +0000 |
608 | +++ tests/unittests/test_commands_block_meta.py 2017-08-03 19:32:06 +0000 |
609 | @@ -1,24 +1,11 @@ |
610 | -from unittest import TestCase |
611 | from mock import patch, call |
612 | from argparse import Namespace |
613 | |
614 | from curtin.commands import block_meta |
615 | - |
616 | - |
617 | -class BlockMetaTestBase(TestCase): |
618 | - def setUp(self): |
619 | - super(BlockMetaTestBase, self).setUp() |
620 | - |
621 | - def add_patch(self, target, attr): |
622 | - """Patches specified target object and sets it as attr on test |
623 | - instance also schedules cleanup""" |
624 | - m = patch(target, autospec=True) |
625 | - p = m.start() |
626 | - self.addCleanup(m.stop) |
627 | - setattr(self, attr, p) |
628 | - |
629 | - |
630 | -class TestBlockMetaSimple(BlockMetaTestBase): |
631 | +from .helpers import CiTestCase |
632 | + |
633 | + |
634 | +class TestBlockMetaSimple(CiTestCase): |
635 | def setUp(self): |
636 | super(TestBlockMetaSimple, self).setUp() |
637 | self.target = "my_target" |
638 | @@ -120,10 +107,10 @@ |
639 | [call(['mount', devname, self.target])]) |
640 | |
641 | |
642 | -class TestBlockMeta(BlockMetaTestBase): |
643 | +class TestBlockMeta(CiTestCase): |
644 | + |
645 | def setUp(self): |
646 | super(TestBlockMeta, self).setUp() |
647 | - # self.target = tempfile.mkdtemp() |
648 | |
649 | basepath = 'curtin.commands.block_meta.' |
650 | self.add_patch(basepath + 'get_path_to_storage_volume', 'mock_getpath') |
651 | |
652 | === modified file 'tests/unittests/test_commands_install.py' |
653 | --- tests/unittests/test_commands_install.py 2017-07-21 20:57:06 +0000 |
654 | +++ tests/unittests/test_commands_install.py 2017-08-03 19:32:06 +0000 |
655 | @@ -1,10 +1,10 @@ |
656 | -from unittest import TestCase |
657 | import copy |
658 | |
659 | from curtin.commands import install |
660 | - |
661 | - |
662 | -class TestMigrateProxy(TestCase): |
663 | +from .helpers import CiTestCase |
664 | + |
665 | + |
666 | +class TestMigrateProxy(CiTestCase): |
667 | def test_legacy_moved_over(self): |
668 | """Legacy setting should get moved over.""" |
669 | proxy = "http://my.proxy:3128" |
670 | |
671 | === modified file 'tests/unittests/test_config.py' |
672 | --- tests/unittests/test_config.py 2015-09-02 17:17:45 +0000 |
673 | +++ tests/unittests/test_config.py 2017-08-03 19:32:06 +0000 |
674 | @@ -1,12 +1,12 @@ |
675 | -from unittest import TestCase |
676 | import copy |
677 | import json |
678 | import textwrap |
679 | |
680 | from curtin import config |
681 | - |
682 | - |
683 | -class TestMerge(TestCase): |
684 | +from .helpers import CiTestCase |
685 | + |
686 | + |
687 | +class TestMerge(CiTestCase): |
688 | def test_merge_cfg_string(self): |
689 | d1 = {'str1': 'str_one'} |
690 | d2 = {'dict1': {'d1.e1': 'd1-e1'}} |
691 | @@ -16,7 +16,7 @@ |
692 | self.assertEqual(d1, expected) |
693 | |
694 | |
695 | -class TestCmdArg2Cfg(TestCase): |
696 | +class TestCmdArg2Cfg(CiTestCase): |
697 | def test_cmdarg_flat(self): |
698 | self.assertEqual(config.cmdarg2cfg("foo=bar"), {'foo': 'bar'}) |
699 | |
700 | @@ -50,7 +50,7 @@ |
701 | self.assertEqual(via_merge, via_merge_cmdarg) |
702 | |
703 | |
704 | -class TestConfigArchive(TestCase): |
705 | +class TestConfigArchive(CiTestCase): |
706 | def test_archive_dict(self): |
707 | myarchive = _replace_consts(textwrap.dedent(""" |
708 | _ARCH_HEAD_ |
709 | |
710 | === modified file 'tests/unittests/test_curthooks.py' |
711 | --- tests/unittests/test_curthooks.py 2017-07-28 19:01:38 +0000 |
712 | +++ tests/unittests/test_curthooks.py 2017-08-03 19:32:06 +0000 |
713 | @@ -1,29 +1,14 @@ |
714 | import os |
715 | -from unittest import TestCase |
716 | from mock import call, patch, MagicMock |
717 | -import shutil |
718 | -import tempfile |
719 | |
720 | from curtin.commands import curthooks |
721 | from curtin import util |
722 | from curtin import config |
723 | from curtin.reporter import events |
724 | - |
725 | - |
726 | -class CurthooksBase(TestCase): |
727 | - def setUp(self): |
728 | - super(CurthooksBase, self).setUp() |
729 | - |
730 | - def add_patch(self, target, attr, autospec=True): |
731 | - """Patches specified target object and sets it as attr on test |
732 | - instance also schedules cleanup""" |
733 | - m = patch(target, autospec=autospec) |
734 | - p = m.start() |
735 | - self.addCleanup(m.stop) |
736 | - setattr(self, attr, p) |
737 | - |
738 | - |
739 | -class TestGetFlashKernelPkgs(CurthooksBase): |
740 | +from .helpers import CiTestCase |
741 | + |
742 | + |
743 | +class TestGetFlashKernelPkgs(CiTestCase): |
744 | def setUp(self): |
745 | super(TestGetFlashKernelPkgs, self).setUp() |
746 | self.add_patch('curtin.util.subp', 'mock_subp') |
747 | @@ -57,7 +42,7 @@ |
748 | self.mock_is_uefi_bootable.assert_called_once_with() |
749 | |
750 | |
751 | -class TestCurthooksInstallKernel(CurthooksBase): |
752 | +class TestCurthooksInstallKernel(CiTestCase): |
753 | def setUp(self): |
754 | super(TestCurthooksInstallKernel, self).setUp() |
755 | self.add_patch('curtin.util.has_pkg_available', 'mock_haspkg') |
756 | @@ -70,7 +55,7 @@ |
757 | 'fallback-package': 'mock-fallback', |
758 | 'mapping': {}}} |
759 | # Tests don't actually install anything so we just need a name |
760 | - self.target = tempfile.mktemp() |
761 | + self.target = self.tmp_dir() |
762 | |
763 | def test__installs_flash_kernel_packages_when_needed(self): |
764 | kernel_package = self.kernel_cfg.get('kernel', {}).get('package', {}) |
765 | @@ -94,14 +79,11 @@ |
766 | [kernel_package], target=self.target) |
767 | |
768 | |
769 | -class TestUpdateInitramfs(CurthooksBase): |
770 | +class TestUpdateInitramfs(CiTestCase): |
771 | def setUp(self): |
772 | super(TestUpdateInitramfs, self).setUp() |
773 | self.add_patch('curtin.util.subp', 'mock_subp') |
774 | - self.target = tempfile.mkdtemp() |
775 | - |
776 | - def tearDown(self): |
777 | - shutil.rmtree(self.target) |
778 | + self.target = self.tmp_dir() |
779 | |
780 | def _mnt_call(self, point): |
781 | target = os.path.join(self.target, point) |
782 | @@ -134,7 +116,7 @@ |
783 | self.mock_subp.assert_has_calls(subp_calls) |
784 | |
785 | |
786 | -class TestInstallMissingPkgs(CurthooksBase): |
787 | +class TestInstallMissingPkgs(CiTestCase): |
788 | def setUp(self): |
789 | super(TestInstallMissingPkgs, self).setUp() |
790 | self.add_patch('platform.machine', 'mock_machine') |
791 | @@ -176,11 +158,11 @@ |
792 | self.assertEqual([], self.mock_install_packages.call_args_list) |
793 | |
794 | |
795 | -class TestSetupZipl(CurthooksBase): |
796 | +class TestSetupZipl(CiTestCase): |
797 | |
798 | def setUp(self): |
799 | super(TestSetupZipl, self).setUp() |
800 | - self.target = tempfile.mkdtemp() |
801 | + self.target = self.tmp_dir() |
802 | |
803 | @patch('curtin.block.get_devices_for_mp') |
804 | @patch('platform.machine') |
805 | @@ -203,11 +185,11 @@ |
806 | content) |
807 | |
808 | |
809 | -class TestSetupGrub(CurthooksBase): |
810 | +class TestSetupGrub(CiTestCase): |
811 | |
812 | def setUp(self): |
813 | super(TestSetupGrub, self).setUp() |
814 | - self.target = tempfile.mkdtemp() |
815 | + self.target = self.tmp_dir() |
816 | self.add_patch('curtin.util.lsb_release', 'mock_lsb_release') |
817 | self.mock_lsb_release.return_value = { |
818 | 'codename': 'xenial', |
819 | @@ -230,9 +212,6 @@ |
820 | self.mock_in_chroot_subp.side_effect = iter(self.in_chroot_subp_output) |
821 | self.mock_chroot.return_value = self.mock_in_chroot |
822 | |
823 | - def tearDown(self): |
824 | - shutil.rmtree(self.target) |
825 | - |
826 | def test_uses_old_grub_install_devices_in_cfg(self): |
827 | cfg = { |
828 | 'grub_install_devices': ['/dev/vdb'] |
829 | @@ -461,17 +440,13 @@ |
830 | self.mock_in_chroot_subp.call_args_list[0][0]) |
831 | |
832 | |
833 | -class TestUbuntuCoreHooks(CurthooksBase): |
834 | +class TestUbuntuCoreHooks(CiTestCase): |
835 | def setUp(self): |
836 | super(TestUbuntuCoreHooks, self).setUp() |
837 | self.target = None |
838 | |
839 | - def tearDown(self): |
840 | - if self.target: |
841 | - shutil.rmtree(self.target) |
842 | - |
843 | def test_target_is_ubuntu_core(self): |
844 | - self.target = tempfile.mkdtemp() |
845 | + self.target = self.tmp_dir() |
846 | ubuntu_core_path = os.path.join(self.target, 'system-data', |
847 | 'var/lib/snapd') |
848 | util.ensure_dir(ubuntu_core_path) |
849 | @@ -484,7 +459,7 @@ |
850 | self.assertFalse(is_core) |
851 | |
852 | def test_target_is_ubuntu_core_noncore_target(self): |
853 | - self.target = tempfile.mkdtemp() |
854 | + self.target = self.tmp_dir() |
855 | non_core_path = os.path.join(self.target, 'curtin') |
856 | util.ensure_dir(non_core_path) |
857 | self.assertTrue(os.path.isdir(non_core_path)) |
858 | @@ -496,7 +471,7 @@ |
859 | @patch('curtin.commands.curthooks.handle_cloudconfig') |
860 | def test_curthooks_no_config(self, mock_handle_cc, mock_del_file, |
861 | mock_write_file): |
862 | - self.target = tempfile.mkdtemp() |
863 | + self.target = self.tmp_dir() |
864 | cfg = {} |
865 | curthooks.ubuntu_core_curthooks(cfg, target=self.target) |
866 | self.assertEqual(len(mock_handle_cc.call_args_list), 0) |
867 | @@ -505,7 +480,7 @@ |
868 | |
869 | @patch('curtin.commands.curthooks.handle_cloudconfig') |
870 | def test_curthooks_cloud_config_remove_disabled(self, mock_handle_cc): |
871 | - self.target = tempfile.mkdtemp() |
872 | + self.target = self.tmp_dir() |
873 | uc_cloud = os.path.join(self.target, 'system-data', 'etc/cloud') |
874 | cc_disabled = os.path.join(uc_cloud, 'cloud-init.disabled') |
875 | cc_path = os.path.join(uc_cloud, 'cloud.cfg.d') |
876 | @@ -531,7 +506,7 @@ |
877 | @patch('curtin.commands.curthooks.handle_cloudconfig') |
878 | def test_curthooks_cloud_config(self, mock_handle_cc, mock_del_file, |
879 | mock_write_file): |
880 | - self.target = tempfile.mkdtemp() |
881 | + self.target = self.tmp_dir() |
882 | cfg = { |
883 | 'cloudconfig': { |
884 | 'file1': { |
885 | @@ -553,7 +528,7 @@ |
886 | @patch('curtin.commands.curthooks.handle_cloudconfig') |
887 | def test_curthooks_net_config(self, mock_handle_cc, mock_del_file, |
888 | mock_write_file): |
889 | - self.target = tempfile.mkdtemp() |
890 | + self.target = self.tmp_dir() |
891 | cfg = { |
892 | 'network': { |
893 | 'version': '1', |
894 | @@ -603,7 +578,7 @@ |
895 | curthooks.handle_cloudconfig([], base_dir="foobar") |
896 | |
897 | |
898 | -class TestDetectRequiredPackages(TestCase): |
899 | +class TestDetectRequiredPackages(CiTestCase): |
900 | test_config = { |
901 | 'storage': { |
902 | 1: { |
903 | |
904 | === modified file 'tests/unittests/test_feature.py' |
905 | --- tests/unittests/test_feature.py 2017-07-28 19:22:14 +0000 |
906 | +++ tests/unittests/test_feature.py 2017-08-03 19:32:06 +0000 |
907 | @@ -1,9 +1,9 @@ |
908 | -from unittest import TestCase |
909 | +from .helpers import CiTestCase |
910 | |
911 | import curtin |
912 | |
913 | |
914 | -class TestExportsFeatures(TestCase): |
915 | +class TestExportsFeatures(CiTestCase): |
916 | def test_has_storage_v1(self): |
917 | self.assertIn('STORAGE_CONFIG_V1', curtin.FEATURES) |
918 | |
919 | |
920 | === modified file 'tests/unittests/test_gpg.py' |
921 | --- tests/unittests/test_gpg.py 2017-02-03 16:02:29 +0000 |
922 | +++ tests/unittests/test_gpg.py 2017-08-03 19:32:06 +0000 |
923 | @@ -1,12 +1,12 @@ |
924 | -from unittest import TestCase |
925 | from mock import call, patch |
926 | import textwrap |
927 | |
928 | from curtin import gpg |
929 | from curtin import util |
930 | - |
931 | - |
932 | -class TestCurtinGpg(TestCase): |
933 | +from .helpers import CiTestCase |
934 | + |
935 | + |
936 | +class TestCurtinGpg(CiTestCase): |
937 | |
938 | @patch('curtin.util.subp') |
939 | def test_export_armour(self, mock_subp): |
940 | |
941 | === modified file 'tests/unittests/test_make_dname.py' |
942 | --- tests/unittests/test_make_dname.py 2016-07-13 17:07:11 +0000 |
943 | +++ tests/unittests/test_make_dname.py 2017-08-03 19:32:06 +0000 |
944 | @@ -1,13 +1,13 @@ |
945 | -from unittest import TestCase |
946 | import mock |
947 | |
948 | import textwrap |
949 | import uuid |
950 | |
951 | from curtin.commands import block_meta |
952 | - |
953 | - |
954 | -class TestMakeDname(TestCase): |
955 | +from .helpers import CiTestCase |
956 | + |
957 | + |
958 | +class TestMakeDname(CiTestCase): |
959 | state = {'scratch': '/tmp/null'} |
960 | rules_d = '/tmp/null/rules.d' |
961 | rule_file = '/tmp/null/rules.d/{}.rules' |
962 | |
963 | === modified file 'tests/unittests/test_net.py' |
964 | --- tests/unittests/test_net.py 2017-07-19 21:54:01 +0000 |
965 | +++ tests/unittests/test_net.py 2017-08-03 19:32:06 +0000 |
966 | @@ -1,16 +1,14 @@ |
967 | -from unittest import TestCase |
968 | import mock |
969 | import os |
970 | -import shutil |
971 | -import tempfile |
972 | import yaml |
973 | |
974 | from curtin import config, net, util |
975 | import curtin.net.network_state as network_state |
976 | +from .helpers import CiTestCase |
977 | from textwrap import dedent |
978 | |
979 | |
980 | -class TestNetParserData(TestCase): |
981 | +class TestNetParserData(CiTestCase): |
982 | |
983 | def test_parse_deb_config_data_ignores_comments(self): |
984 | contents = dedent("""\ |
985 | @@ -235,13 +233,11 @@ |
986 | }, ifaces) |
987 | |
988 | |
989 | -class TestNetParser(TestCase): |
990 | +class TestNetParser(CiTestCase): |
991 | |
992 | def setUp(self): |
993 | - self.target = tempfile.mkdtemp() |
994 | - |
995 | - def tearDown(self): |
996 | - shutil.rmtree(self.target) |
997 | + super(TestNetParser, self).setUp() |
998 | + self.target = self.tmp_dir() |
999 | |
1000 | def make_config(self, path=None, name=None, contents=None, |
1001 | parse=True): |
1002 | @@ -387,9 +383,10 @@ |
1003 | self.assertEqual({}, observed) |
1004 | |
1005 | |
1006 | -class TestNetConfig(TestCase): |
1007 | +class TestNetConfig(CiTestCase): |
1008 | def setUp(self): |
1009 | - self.target = tempfile.mkdtemp() |
1010 | + super(TestNetConfig, self).setUp() |
1011 | + self.target = self.tmp_dir() |
1012 | self.config_f = os.path.join(self.target, 'config') |
1013 | self.config = ''' |
1014 | # YAML example of a simple network config |
1015 | @@ -436,9 +433,6 @@ |
1016 | ns.parse_config() |
1017 | return ns |
1018 | |
1019 | - def tearDown(self): |
1020 | - shutil.rmtree(self.target) |
1021 | - |
1022 | def test_parse_net_config_data(self): |
1023 | ns = self.get_net_state() |
1024 | net_state_from_cls = ns.network_state |
1025 | |
1026 | === modified file 'tests/unittests/test_partitioning.py' |
1027 | --- tests/unittests/test_partitioning.py 2015-08-10 16:34:02 +0000 |
1028 | +++ tests/unittests/test_partitioning.py 2017-08-03 19:32:06 +0000 |
1029 | @@ -1,6 +1,7 @@ |
1030 | -import unittest |
1031 | +from unittest import skip |
1032 | import mock |
1033 | import curtin.commands.block_meta |
1034 | +from .helpers import CiTestCase |
1035 | |
1036 | from sys import version_info |
1037 | if version_info.major == 2: |
1038 | @@ -11,8 +12,8 @@ |
1039 | parted = None # FIXME: remove these tests entirely. This is here for flake8 |
1040 | |
1041 | |
1042 | -@unittest.skip |
1043 | -class TestBlock(unittest.TestCase): |
1044 | +@skip |
1045 | +class TestBlock(CiTestCase): |
1046 | storage_config = { |
1047 | "sda": {"id": "sda", "type": "disk", "ptable": "msdos", |
1048 | "serial": "DISK_1", "grub_device": "True"}, |
1049 | |
1050 | === modified file 'tests/unittests/test_public.py' |
1051 | --- tests/unittests/test_public.py 2017-07-28 20:54:10 +0000 |
1052 | +++ tests/unittests/test_public.py 2017-08-03 19:32:06 +0000 |
1053 | @@ -1,4 +1,3 @@ |
1054 | -from unittest import TestCase |
1055 | |
1056 | from curtin import block |
1057 | from curtin import config |
1058 | @@ -6,9 +5,10 @@ |
1059 | from curtin import util |
1060 | |
1061 | from curtin.commands import curthooks |
1062 | - |
1063 | - |
1064 | -class TestPublicAPI(TestCase): |
1065 | +from .helpers import CiTestCase |
1066 | + |
1067 | + |
1068 | +class TestPublicAPI(CiTestCase): |
1069 | """Test entry points known to be used externally. |
1070 | |
1071 | Curtin's only known external library user is the curthooks |
1072 | |
1073 | === modified file 'tests/unittests/test_reporter.py' |
1074 | --- tests/unittests/test_reporter.py 2016-06-22 15:27:45 +0000 |
1075 | +++ tests/unittests/test_reporter.py 2017-08-03 19:32:06 +0000 |
1076 | @@ -21,7 +21,6 @@ |
1077 | unicode_literals, |
1078 | ) |
1079 | |
1080 | -from unittest import TestCase |
1081 | from mock import patch |
1082 | |
1083 | from curtin.reporter.legacy import ( |
1084 | @@ -39,13 +38,12 @@ |
1085 | from curtin.reporter import handlers |
1086 | from curtin import url_helper |
1087 | from curtin.reporter import events |
1088 | +from .helpers import CiTestCase |
1089 | |
1090 | -import os |
1091 | -import tempfile |
1092 | import base64 |
1093 | |
1094 | |
1095 | -class TestLegacyReporter(TestCase): |
1096 | +class TestLegacyReporter(CiTestCase): |
1097 | |
1098 | @patch('curtin.reporter.legacy.LOG') |
1099 | def test_load_reporter_logs_empty_cfg(self, mock_LOG): |
1100 | @@ -72,7 +70,7 @@ |
1101 | self.assertTrue(mock_LOG.error.called) |
1102 | |
1103 | |
1104 | -class TestMAASReporter(TestCase): |
1105 | +class TestMAASReporter(CiTestCase): |
1106 | def test_load_factory_raises_exception_wrong_options(self): |
1107 | options = {'wrong': 'wrong'} |
1108 | self.assertRaises( |
1109 | @@ -86,7 +84,7 @@ |
1110 | self.assertIsInstance(reporter, MAASReporter) |
1111 | |
1112 | |
1113 | -class TestReporter(TestCase): |
1114 | +class TestReporter(CiTestCase): |
1115 | config = {'element1': {'type': 'webhook', 'level': 'INFO', |
1116 | 'consumer_key': "ck_foo", |
1117 | 'consumer_secret': 'cs_foo', |
1118 | @@ -175,39 +173,32 @@ |
1119 | @patch('curtin.reporter.events.report_event') |
1120 | def test_report_finished_post_files(self, mock_report_event): |
1121 | test_data = b'abcdefg' |
1122 | - tmp = tempfile.mkstemp() |
1123 | - try: |
1124 | - with open(tmp[1], 'wb') as fp: |
1125 | - fp.write(test_data) |
1126 | - events.report_finish_event(self.ev_name, self.ev_desc, |
1127 | - post_files=[tmp[1]]) |
1128 | - event = self._get_reported_event(mock_report_event) |
1129 | - files = event.as_dict().get('files') |
1130 | - self.assertTrue(len(files) == 1) |
1131 | - self.assertEqual(files[0].get('path'), tmp[1]) |
1132 | - self.assertEqual(files[0].get('encoding'), 'base64') |
1133 | - self.assertEqual(files[0].get('content'), |
1134 | - base64.b64encode(test_data).decode()) |
1135 | - finally: |
1136 | - os.remove(tmp[1]) |
1137 | + tmpfname = self.tmp_path('testfile') |
1138 | + with open(tmpfname, 'wb') as fp: |
1139 | + fp.write(test_data) |
1140 | + events.report_finish_event(self.ev_name, self.ev_desc, |
1141 | + post_files=[tmpfname]) |
1142 | + event = self._get_reported_event(mock_report_event) |
1143 | + files = event.as_dict().get('files') |
1144 | + self.assertTrue(len(files) == 1) |
1145 | + self.assertEqual(files[0].get('path'), tmpfname) |
1146 | + self.assertEqual(files[0].get('encoding'), 'base64') |
1147 | + self.assertEqual(files[0].get('content'), |
1148 | + base64.b64encode(test_data).decode()) |
1149 | |
1150 | @patch('curtin.url_helper.OauthUrlHelper') |
1151 | def test_webhook_handler_post_files(self, mock_url_helper): |
1152 | test_data = b'abcdefg' |
1153 | - tmp = tempfile.mkstemp() |
1154 | - tmpfname = tmp[1] |
1155 | - try: |
1156 | - with open(tmpfname, 'wb') as fp: |
1157 | - fp.write(test_data) |
1158 | - event = events.FinishReportingEvent('test_event_name', |
1159 | - 'test event description', |
1160 | - post_files=[tmpfname], |
1161 | - level='INFO') |
1162 | - webhook_handler = handlers.WebHookHandler('127.0.0.1:8000', |
1163 | - level='INFO') |
1164 | - webhook_handler.publish_event(event) |
1165 | - webhook_handler.oauth_helper.geturl.assert_called_with( |
1166 | - url='127.0.0.1:8000', data=event.as_dict(), |
1167 | - headers=webhook_handler.headers, retries=None) |
1168 | - finally: |
1169 | - os.remove(tmpfname) |
1170 | + tmpfname = self.tmp_path('testfile') |
1171 | + with open(tmpfname, 'wb') as fp: |
1172 | + fp.write(test_data) |
1173 | + event = events.FinishReportingEvent('test_event_name', |
1174 | + 'test event description', |
1175 | + post_files=[tmpfname], |
1176 | + level='INFO') |
1177 | + webhook_handler = handlers.WebHookHandler('127.0.0.1:8000', |
1178 | + level='INFO') |
1179 | + webhook_handler.publish_event(event) |
1180 | + webhook_handler.oauth_helper.geturl.assert_called_with( |
1181 | + url='127.0.0.1:8000', data=event.as_dict(), |
1182 | + headers=webhook_handler.headers, retries=None) |
1183 | |
1184 | === modified file 'tests/unittests/test_util.py' |
1185 | --- tests/unittests/test_util.py 2017-06-09 20:54:25 +0000 |
1186 | +++ tests/unittests/test_util.py 2017-08-03 19:32:06 +0000 |
1187 | @@ -1,16 +1,14 @@ |
1188 | -from unittest import TestCase, skipIf |
1189 | +from unittest import skipIf |
1190 | import mock |
1191 | import os |
1192 | import stat |
1193 | -import shutil |
1194 | -import tempfile |
1195 | from textwrap import dedent |
1196 | |
1197 | from curtin import util |
1198 | -from .helpers import simple_mocked_open |
1199 | - |
1200 | - |
1201 | -class TestLogTimer(TestCase): |
1202 | +from .helpers import CiTestCase, simple_mocked_open |
1203 | + |
1204 | + |
1205 | +class TestLogTimer(CiTestCase): |
1206 | def test_logger_called(self): |
1207 | data = {} |
1208 | |
1209 | @@ -24,16 +22,14 @@ |
1210 | self.assertIn("mymessage", data['msg']) |
1211 | |
1212 | |
1213 | -class TestDisableDaemons(TestCase): |
1214 | +class TestDisableDaemons(CiTestCase): |
1215 | prcpath = "usr/sbin/policy-rc.d" |
1216 | |
1217 | def setUp(self): |
1218 | - self.target = tempfile.mkdtemp() |
1219 | + super(TestDisableDaemons, self).setUp() |
1220 | + self.target = self.tmp_dir() |
1221 | self.temp_prc = os.path.join(self.target, self.prcpath) |
1222 | |
1223 | - def tearDown(self): |
1224 | - shutil.rmtree(self.target) |
1225 | - |
1226 | def test_disable_daemons_in_root_works(self): |
1227 | ret = util.disable_daemons_in_root(self.target) |
1228 | self.assertTrue(ret) |
1229 | @@ -55,8 +51,10 @@ |
1230 | self.assertTrue(os.path.exists(self.temp_prc)) |
1231 | |
1232 | |
1233 | -class TestWhich(TestCase): |
1234 | +class TestWhich(CiTestCase): |
1235 | + |
1236 | def setUp(self): |
1237 | + super(TestWhich, self).setUp() |
1238 | self.orig_is_exe = util.is_exe |
1239 | util.is_exe = self.my_is_exe |
1240 | self.orig_path = os.environ.get("PATH") |
1241 | @@ -103,8 +101,10 @@ |
1242 | self.assertEqual(found, "/usr/bin2/fuzz") |
1243 | |
1244 | |
1245 | -class TestLsbRelease(TestCase): |
1246 | +class TestLsbRelease(CiTestCase): |
1247 | + |
1248 | def setUp(self): |
1249 | + super(TestLsbRelease, self).setUp() |
1250 | self._reset_cache() |
1251 | |
1252 | def _reset_cache(self): |
1253 | @@ -143,7 +143,7 @@ |
1254 | self.assertEqual(util.lsb_release(), expected) |
1255 | |
1256 | |
1257 | -class TestSubp(TestCase): |
1258 | +class TestSubp(CiTestCase): |
1259 | |
1260 | stdin2err = ['bash', '-c', 'cat >&2'] |
1261 | stdin2out = ['cat'] |
1262 | @@ -162,10 +162,9 @@ |
1263 | |
1264 | def setUp(self): |
1265 | super(TestSubp, self).setUp() |
1266 | - mock_getunsh = mock.patch( |
1267 | - "curtin.util._get_unshare_pid_args", return_value=[]) |
1268 | - self.mock_get_unshare_pid_args = mock_getunsh.start() |
1269 | - self.addCleanup(mock_getunsh.stop) |
1270 | + self.add_patch( |
1271 | + 'curtin.util._get_unshare_pid_args', 'mock_get_unshare_pid_args', |
1272 | + return_value=[]) |
1273 | |
1274 | def printf_cmd(self, *args): |
1275 | # bash's printf supports \xaa. So does /usr/bin/printf |
1276 | @@ -382,19 +381,17 @@ |
1277 | self.assertEqual(expected, args[0]) |
1278 | |
1279 | |
1280 | -class TestGetUnsharePidArgs(TestCase): |
1281 | +class TestGetUnsharePidArgs(CiTestCase): |
1282 | """Test the internal implementation for when to unshare.""" |
1283 | |
1284 | def setUp(self): |
1285 | super(TestGetUnsharePidArgs, self).setUp() |
1286 | - mock_hasunsh = mock.patch( |
1287 | - "curtin.util._has_unshare_pid", return_value=True) |
1288 | - self.mock_has_unshare_pid = mock_hasunsh.start() |
1289 | - self.addCleanup(mock_hasunsh.stop) |
1290 | - mock_geteuid = mock.patch( |
1291 | - "curtin.util.os.geteuid", return_value=0) |
1292 | - self.mock_geteuid = mock_geteuid.start() |
1293 | - self.addCleanup(mock_geteuid.stop) |
1294 | + self.add_patch('curtin.util._has_unshare_pid', 'mock_has_unshare_pid', |
1295 | + return_value=True) |
1296 | + # our trusty tox environment with mock 1.0.1 will stack trace |
1297 | + # if autospec is not disabled here. |
1298 | + self.add_patch('curtin.util.os.geteuid', 'mock_geteuid', |
1299 | + autospec=False, return_value=0) |
1300 | |
1301 | def assertOff(self, result): |
1302 | self.assertEqual([], result) |
1303 | @@ -455,7 +452,7 @@ |
1304 | self.assertOff(util._get_unshare_pid_args("", "/target", 0)) |
1305 | |
1306 | |
1307 | -class TestHuman2Bytes(TestCase): |
1308 | +class TestHuman2Bytes(CiTestCase): |
1309 | GB = 1024 * 1024 * 1024 |
1310 | MB = 1024 * 1024 |
1311 | |
1312 | @@ -509,52 +506,42 @@ |
1313 | util.bytes2human(util.human2bytes(size_str)), size_str) |
1314 | |
1315 | |
1316 | -class TestSetUnExecutable(TestCase): |
1317 | +class TestSetUnExecutable(CiTestCase): |
1318 | tmpf = None |
1319 | tmpd = None |
1320 | |
1321 | - def tearDown(self): |
1322 | - if self.tmpf: |
1323 | - if os.path.exists(self.tmpf): |
1324 | - os.unlink(self.tmpf) |
1325 | - self.tmpf = None |
1326 | - if self.tmpd: |
1327 | - shutil.rmtree(self.tmpd) |
1328 | - self.tmpd = None |
1329 | - |
1330 | - def tempfile(self, data=None): |
1331 | - fp, self.tmpf = tempfile.mkstemp() |
1332 | - if data: |
1333 | - fp.write(data) |
1334 | - os.close(fp) |
1335 | - return self.tmpf |
1336 | + def setUp(self): |
1337 | + super(CiTestCase, self).setUp() |
1338 | + self.tmpd = self.tmp_dir() |
1339 | |
1340 | def test_change_needed_returns_original_mode(self): |
1341 | - tmpf = self.tempfile() |
1342 | + tmpf = self.tmp_path('testfile') |
1343 | + util.write_file(tmpf, '') |
1344 | os.chmod(tmpf, 0o755) |
1345 | ret = util.set_unexecutable(tmpf) |
1346 | self.assertEqual(ret, 0o0755) |
1347 | |
1348 | def test_no_change_needed_returns_none(self): |
1349 | - tmpf = self.tempfile() |
1350 | + tmpf = self.tmp_path('testfile') |
1351 | + util.write_file(tmpf, '') |
1352 | os.chmod(tmpf, 0o600) |
1353 | ret = util.set_unexecutable(tmpf) |
1354 | self.assertEqual(ret, None) |
1355 | |
1356 | def test_change_does_as_expected(self): |
1357 | - tmpf = self.tempfile() |
1358 | + tmpf = self.tmp_path('testfile') |
1359 | + util.write_file(tmpf, '') |
1360 | os.chmod(tmpf, 0o755) |
1361 | ret = util.set_unexecutable(tmpf) |
1362 | self.assertEqual(ret, 0o0755) |
1363 | self.assertEqual(stat.S_IMODE(os.stat(tmpf).st_mode), 0o0644) |
1364 | |
1365 | def test_strict_no_exists_raises_exception(self): |
1366 | - self.tmpd = tempfile.mkdtemp() |
1367 | bogus = os.path.join(self.tmpd, 'bogus') |
1368 | self.assertRaises(ValueError, util.set_unexecutable, bogus, True) |
1369 | |
1370 | |
1371 | -class TestTargetPath(TestCase): |
1372 | +class TestTargetPath(CiTestCase): |
1373 | def test_target_empty_string(self): |
1374 | self.assertEqual("/etc/passwd", util.target_path("", "/etc/passwd")) |
1375 | |
1376 | @@ -596,7 +583,7 @@ |
1377 | util.target_path("/target/", "///my/path/")) |
1378 | |
1379 | |
1380 | -class TestRunInChroot(TestCase): |
1381 | +class TestRunInChroot(CiTestCase): |
1382 | """Test the legacy 'RunInChroot'. |
1383 | |
1384 | The test works by mocking ChrootableTarget's __enter__ to do nothing. |
1385 | @@ -626,7 +613,7 @@ |
1386 | m_subp.assert_called_with(cmd, target=target) |
1387 | |
1388 | |
1389 | -class TestLoadFile(TestCase): |
1390 | +class TestLoadFile(CiTestCase): |
1391 | """Test utility 'load_file'""" |
1392 | |
1393 | def test_load_file_simple(self): |
1394 | @@ -657,7 +644,7 @@ |
1395 | self.assertEqual(loaded_contents, contents) |
1396 | |
1397 | |
1398 | -class TestIpAddress(TestCase): |
1399 | +class TestIpAddress(CiTestCase): |
1400 | """Test utility 'is_valid_ip{,v4,v6}_address'""" |
1401 | |
1402 | def test_is_valid_ipv6_address(self): |
1403 | @@ -682,10 +669,11 @@ |
1404 | '2002:4559:1FE2:0000:0000:0000:4559:1FE2')) |
1405 | |
1406 | |
1407 | -class TestLoadCommandEnvironment(TestCase): |
1408 | +class TestLoadCommandEnvironment(CiTestCase): |
1409 | + |
1410 | def setUp(self): |
1411 | - self.tmpd = tempfile.mkdtemp() |
1412 | - self.addCleanup(shutil.rmtree, self.tmpd) |
1413 | + super(TestLoadCommandEnvironment, self).setUp() |
1414 | + self.tmpd = self.tmp_dir() |
1415 | all_names = { |
1416 | 'CONFIG', |
1417 | 'OUTPUT_FSTAB', |
1418 | @@ -728,7 +716,7 @@ |
1419 | self.fail("unexpected key error raised: %s" % e) |
1420 | |
1421 | |
1422 | -class TestWaitForRemoval(TestCase): |
1423 | +class TestWaitForRemoval(CiTestCase): |
1424 | def test_wait_for_removal_missing_path(self): |
1425 | with self.assertRaises(ValueError): |
1426 | util.wait_for_removal(None) |
1427 | @@ -796,14 +784,12 @@ |
1428 | ]) |
1429 | |
1430 | |
1431 | -class TestGetEFIBootMGR(TestCase): |
1432 | +class TestGetEFIBootMGR(CiTestCase): |
1433 | |
1434 | def setUp(self): |
1435 | super(TestGetEFIBootMGR, self).setUp() |
1436 | - mock_chroot = mock.patch( |
1437 | - 'curtin.util.ChrootableTarget', autospec=False) |
1438 | - self.mock_chroot = mock_chroot.start() |
1439 | - self.addCleanup(mock_chroot.stop) |
1440 | + self.add_patch( |
1441 | + 'curtin.util.ChrootableTarget', 'mock_chroot', autospec=False) |
1442 | self.mock_in_chroot = mock.MagicMock() |
1443 | self.mock_in_chroot.__enter__.return_value = self.mock_in_chroot |
1444 | self.in_chroot_subp_output = [] |
1445 | |
1446 | === modified file 'tests/unittests/test_version.py' |
1447 | --- tests/unittests/test_version.py 2017-02-06 22:49:33 +0000 |
1448 | +++ tests/unittests/test_version.py 2017-08-03 19:32:06 +0000 |
1449 | @@ -1,28 +1,16 @@ |
1450 | -from unittest import TestCase |
1451 | import mock |
1452 | import subprocess |
1453 | import os |
1454 | |
1455 | from curtin import version |
1456 | from curtin import __version__ as old_version |
1457 | - |
1458 | - |
1459 | -class CurtinVersionBase(TestCase): |
1460 | - def setUp(self): |
1461 | - super(CurtinVersionBase, self).setUp() |
1462 | - |
1463 | - def add_patch(self, target, attr): |
1464 | - """Patches specified target object and sets it as attr on test |
1465 | - instance also schedules cleanup""" |
1466 | - m = mock.patch(target, autospec=True) |
1467 | - p = m.start() |
1468 | - self.addCleanup(m.stop) |
1469 | - setattr(self, attr, p) |
1470 | - |
1471 | - |
1472 | -class TestCurtinVersion(CurtinVersionBase): |
1473 | - |
1474 | - def setUp(self): |
1475 | +from .helpers import CiTestCase |
1476 | + |
1477 | + |
1478 | +class TestCurtinVersion(CiTestCase): |
1479 | + |
1480 | + def setUp(self): |
1481 | + super(TestCurtinVersion, self).setUp() |
1482 | self.add_patch('subprocess.check_output', 'mock_subp') |
1483 | self.add_patch('os.path', 'mock_path') |
1484 |
PASSED: Continuous integration, rev:517 /jenkins. ubuntu. com/server/ job/curtin- ci/580/ /jenkins. ubuntu. com/server/ job/curtin- ci/nodes= metal-amd64/ 580 /jenkins. ubuntu. com/server/ job/curtin- ci/nodes= metal-arm64/ 580 /jenkins. ubuntu. com/server/ job/curtin- ci/nodes= metal-ppc64el/ 580 /jenkins. ubuntu. com/server/ job/curtin- ci/nodes= metal-s390x/ 580 /jenkins. ubuntu. com/server/ job/curtin- ci/nodes= vm-i386/ 580
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
Click here to trigger a rebuild: /jenkins. ubuntu. com/server/ job/curtin- ci/580/ rebuild
https:/