Merge lp:~chad.smith/curtin/common-ci-test-case into lp:~curtin-dev/curtin/trunk

Proposed by Chad Smith on 2017-08-02
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
Reviewer Review Type Date Requested Status
Server Team CI bot continuous-integration Approve on 2017-08-03
curtin developers 2017-08-02 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.

To post a comment you must log in.
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 on 2017-08-03

drop functools partial as it is unneeded

Chad Smith (chad.smith) :
519. By Chad Smith on 2017-08-03

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 on 2017-08-03

add missing super...setUp calls to classes which have overridden the unittest.setUp method

Ryan Harper (raharper) wrote :

Looks good once you make tox happy

521. By Chad Smith on 2017-08-03

allow kwargs passed into CiTestCase.add_patch per review comments

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
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

Subscribers

People subscribed via source and target branches