Merge lp:~barry/ubuntu-system-image/lp1558190 into lp:ubuntu-system-image/server

Proposed by Barry Warsaw
Status: Merged
Approved by: Łukasz Zemczak
Approved revision: 287
Merged at revision: 285
Proposed branch: lp:~barry/ubuntu-system-image/lp1558190
Merge into: lp:ubuntu-system-image/server
Diff against target: 215 lines (+60/-17)
6 files modified
coverage-py35.ini (+7/-0)
lib/systemimage/tests/test_generators.py (+2/-1)
lib/systemimage/tests/test_static.py (+1/-1)
lib/systemimage/tests/test_tools.py (+32/-10)
lib/systemimage/tools.py (+8/-4)
tox.ini (+10/-1)
To merge this branch: bzr merge lp:~barry/ubuntu-system-image/lp1558190
Reviewer Review Type Date Requested Status
Łukasz Zemczak (community) Approve
Review via email: mp+289275@code.launchpad.net

Commit message

Fixes LP: #1558190 and repairs the test suite.

Description of the change

This fixes LP: #1558190 by adding mtime attributes to the tarball files config.d and the enclosed .ini symlinks.

This branch also repairs the test suite and adds Python 3.5 support so that tox will work on Xenial.

To post a comment you must log in.
Revision history for this message
Łukasz Zemczak (sil2100) wrote :

Looks good! I personally prefer adding test descriptions in """ """ for each test case, but that's just my style preference. I suppose checking if the date is higher than the epoch is good enough, but we could think of doing some closer checks to like fetching the local time now and looking if the generated tarball has a higher-or-equal one, to check for any future bugs that might make s-i writing some strange timestamps buuut... that's not really a probable case (can't think of a way that could happen). So a big +1 from me.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== added file 'coverage-py35.ini'
--- coverage-py35.ini 1970-01-01 00:00:00 +0000
+++ coverage-py35.ini 2016-03-16 19:03:31 +0000
@@ -0,0 +1,7 @@
1[run]
2branch = true
3parallel = true
4omit =
5 lib/systemimage/testing/*
6 lib/systemimage/tests/*
7 /usr/lib/*
08
=== modified file 'lib/systemimage/tests/test_generators.py'
--- lib/systemimage/tests/test_generators.py 2015-11-12 14:46:48 +0000
+++ lib/systemimage/tests/test_generators.py 2016-03-16 19:03:31 +0000
@@ -989,7 +989,8 @@
989 fd.write(url)989 fd.write(url)
990 mock_urlretrieve.side_effect = urlretrieve_side_effect990 mock_urlretrieve.side_effect = urlretrieve_side_effect
991991
992 def repack_recovery_keyring_effect(conf, path, keyring):992 def repack_recovery_keyring_effect(conf, path, keyring,
993 device_name=None):
993 if keyring == "fail":994 if keyring == "fail":
994 return False995 return False
995996
996997
=== modified file 'lib/systemimage/tests/test_static.py'
--- lib/systemimage/tests/test_static.py 2015-09-29 14:16:48 +0000
+++ lib/systemimage/tests/test_static.py 2016-03-16 19:03:31 +0000
@@ -101,7 +101,7 @@
101 output = subp.communicate()[0].splitlines()101 output = subp.communicate()[0].splitlines()
102 for line in output:102 for line in output:
103 print(line)103 print(line)
104 self.assertEqual(0, len(output))104 self.assertEqual(0, len(output), output)
105105
106 @unittest.skipIf(pyflakes is None, "Missing pyflakes, skipping test.")106 @unittest.skipIf(pyflakes is None, "Missing pyflakes, skipping test.")
107 def test_pyflakes_clean(self):107 def test_pyflakes_clean(self):
108108
=== modified file 'lib/systemimage/tests/test_tools.py'
--- lib/systemimage/tests/test_tools.py 2016-02-17 09:23:22 +0000
+++ lib/systemimage/tests/test_tools.py 2016-03-16 19:03:31 +0000
@@ -24,6 +24,8 @@
24import unittest24import unittest
25import six25import six
2626
27from datetime import datetime
28from glob import glob
27from systemimage import config, tools, tree, gpg29from systemimage import config, tools, tree, gpg
28from systemimage.helpers import chdir30from systemimage.helpers import chdir
29from systemimage.testing.helpers import HAS_TEST_KEYS, MISSING_KEYS_WARNING31from systemimage.testing.helpers import HAS_TEST_KEYS, MISSING_KEYS_WARNING
@@ -259,7 +261,7 @@
259 source_path = os.path.join(self.temp_directory, "source")261 source_path = os.path.join(self.temp_directory, "source")
260 stripped_path = os.path.join(self.temp_directory, "stripped")262 stripped_path = os.path.join(self.temp_directory, "stripped")
261 reattached_path = os.path.join(self.temp_directory, "reattached")263 reattached_path = os.path.join(self.temp_directory, "reattached")
262 264
263 header = bytearray(512)265 header = bytearray(512)
264 contents = b"RECOVERY"266 contents = b"RECOVERY"
265 for i in range(0, 64):267 for i in range(0, 64):
@@ -278,7 +280,6 @@
278 with open(reattached_path, "rb") as f, open(source_path, "rb") as fs:280 with open(reattached_path, "rb") as f, open(source_path, "rb") as fs:
279 self.assertEqual(f.read(), fs.read())281 self.assertEqual(f.read(), fs.read())
280282
281
282 @unittest.skipUnless(HAS_TEST_KEYS, MISSING_KEYS_WARNING)283 @unittest.skipUnless(HAS_TEST_KEYS, MISSING_KEYS_WARNING)
283 def test_repack_recovery_keyring(self):284 def test_repack_recovery_keyring(self):
284 # Generate the keyring tarballs285 # Generate the keyring tarballs
@@ -371,7 +372,6 @@
371 self.temp_directory,372 self.temp_directory,
372 "archive-master", "krillin")373 "archive-master", "krillin")
373374
374
375 def test_system_image_30_symlinks(self):375 def test_system_image_30_symlinks(self):
376 # To support system-image 3.0, generate symlinks for config.d376 # To support system-image 3.0, generate symlinks for config.d
377 version_tarball = "%s/version.tar" % self.temp_directory377 version_tarball = "%s/version.tar" % self.temp_directory
@@ -398,16 +398,38 @@
398 # Extract the tarfile to another temp directory, so that we can398 # Extract the tarfile to another temp directory, so that we can
399 # exactly compare extracted directory modes.399 # exactly compare extracted directory modes.
400 extract_dir = tempfile.mkdtemp()400 extract_dir = tempfile.mkdtemp()
401 try:401 self.addCleanup(shutil.rmtree, extract_dir)
402 safe_extract(version_tarball, extract_dir)402 safe_extract(version_tarball, extract_dir)
403 config_d = os.path.join(403 config_d = os.path.join(
404 extract_dir, "system", "etc", "system-image", "config.d")404 extract_dir, "system", "etc", "system-image", "config.d")
405 mode = stat.S_IMODE(os.stat(config_d).st_mode)405 mode = stat.S_IMODE(os.stat(config_d).st_mode)
406 finally:
407 shutil.rmtree(extract_dir)
408 self.assertEqual(mode, 0o775,406 self.assertEqual(mode, 0o775,
409 'got 0o{:o}, expected 0o775'.format(mode))407 'got 0o{:o}, expected 0o775'.format(mode))
410408
409 def test_system_image_30_mtimes(self):
410 # The etc/system-image/config.d directory and the 00_default.ini,
411 # 01_channel.ini symlinks should have proper mtimes. LP: #1558190
412 version_tarball = "%s/version.tar" % self.temp_directory
413 tools.generate_version_tarball(self.config, "testing", "test",
414 "1.2.3.4",
415 version_tarball)
416 # Extract the tarfile to another temp directory, so that we can
417 # exactly check mtimes.
418 extract_dir = tempfile.mkdtemp()
419 self.addCleanup(shutil.rmtree, extract_dir)
420 safe_extract(version_tarball, extract_dir)
421 config_d = os.path.join(
422 extract_dir, "system", "etc", "system-image", "config.d")
423 epoch = datetime(1970, 1, 1)
424 self.assertGreater(datetime.fromtimestamp(os.stat(config_d).st_mtime),
425 epoch)
426 ini_files = glob(os.path.join(config_d, '*.ini'))
427 # Future-proof: at least two ini files.
428 self.assertGreaterEqual(len(ini_files), 2)
429 for ini_file in ini_files:
430 mtime = os.lstat(ini_file).st_mtime
431 self.assertGreater(datetime.fromtimestamp(mtime), epoch)
432
411 def test_set_tag_on_version_detail(self):433 def test_set_tag_on_version_detail(self):
412 """Set a basic tag."""434 """Set a basic tag."""
413 version_detail_list = [435 version_detail_list = [
414436
=== modified file 'lib/systemimage/tools.py'
--- lib/systemimage/tools.py 2016-02-17 09:23:22 +0000
+++ lib/systemimage/tools.py 2016-03-16 19:03:31 +0000
@@ -32,7 +32,7 @@
32from systemimage import gpg32from systemimage import gpg
3333
3434
35READ_SIZE = 1024*102435READ_SIZE = 1024 * 1024
3636
37logger = logging.getLogger(__name__)37logger = logging.getLogger(__name__)
3838
@@ -86,10 +86,11 @@
86 """86 """
8787
88 tarball = tarfile.open(path, 'w:')88 tarball = tarfile.open(path, 'w:')
89 now_mtime = int(time.time())
8990
90 version_file = tarfile.TarInfo()91 version_file = tarfile.TarInfo()
91 version_file.size = len(version) + 192 version_file.size = len(version) + 1
92 version_file.mtime = int(time.strftime("%s", time.localtime()))93 version_file.mtime = now_mtime
93 version_file.name = build_path94 version_file.name = build_path
9495
95 # Append a line break96 # Append a line break
@@ -124,7 +125,7 @@
124125
125 channel_file = tarfile.TarInfo()126 channel_file = tarfile.TarInfo()
126 channel_file.size = len(channel)127 channel_file.size = len(channel)
127 channel_file.mtime = int(time.strftime("%s", time.localtime()))128 channel_file.mtime = now_mtime
128 channel_file.name = channel_path129 channel_file.name = channel_path
129130
130 tarball.addfile(channel_file, BytesIO(channel.encode("utf-8")))131 tarball.addfile(channel_file, BytesIO(channel.encode("utf-8")))
@@ -142,6 +143,7 @@
142 directory = tarfile.TarInfo(config_d)143 directory = tarfile.TarInfo(config_d)
143 directory.type = tarfile.DIRTYPE144 directory.type = tarfile.DIRTYPE
144 directory.mode = 0o775145 directory.mode = 0o775
146 directory.mtime = now_mtime
145 tarball.addfile(directory)147 tarball.addfile(directory)
146148
147 path_00_default = os.path.join(config_d, "00_default.ini")149 path_00_default = os.path.join(config_d, "00_default.ini")
@@ -149,6 +151,7 @@
149 default_file.name = path_00_default151 default_file.name = path_00_default
150 default_file.type = tarfile.SYMTYPE152 default_file.type = tarfile.SYMTYPE
151 default_file.linkname = "../client.ini"153 default_file.linkname = "../client.ini"
154 default_file.mtime = now_mtime
152 tarball.addfile(default_file)155 tarball.addfile(default_file)
153156
154 path_01_channel = os.path.join(config_d, "01_channel.ini")157 path_01_channel = os.path.join(config_d, "01_channel.ini")
@@ -157,6 +160,7 @@
157 channel_file.type = tarfile.SYMTYPE160 channel_file.type = tarfile.SYMTYPE
158 channel_file.linkname = os.path.join(161 channel_file.linkname = os.path.join(
159 "..", os.path.basename(channel_path))162 "..", os.path.basename(channel_path))
163 channel_file.mtime = now_mtime
160 tarball.addfile(channel_file)164 tarball.addfile(channel_file)
161165
162 tarball.close()166 tarball.close()
@@ -194,7 +198,7 @@
194 compressions = {198 compressions = {
195 b"\x1f\x8b\x08": "gzip",199 b"\x1f\x8b\x08": "gzip",
196 b"\xfd\x37\x7a\x58\x5a\x00": "xz"200 b"\xfd\x37\x7a\x58\x5a\x00": "xz"
197 }201 }
198 length = max(len(x) for x in compressions)202 length = max(len(x) for x in compressions)
199203
200 with open(path, 'rb') as f:204 with open(path, 'rb') as f:
201205
=== modified file 'tox.ini'
--- tox.ini 2015-10-20 21:51:48 +0000
+++ tox.ini 2016-03-16 19:03:31 +0000
@@ -1,6 +1,7 @@
1[tox]1[tox]
2envlist = py27,py34,coverage-py27,coverage-py34,fast-{py27,py34}2envlist = py27,py34,py35,coverage-py27,coverage-py34,coverage-py35,fast-{py27,py34,py35}
3recreate = True3recreate = True
4skip_missing_interpreters = True
45
5[coverage]6[coverage]
6rcfile = {toxinidir}/{envname}.ini7rcfile = {toxinidir}/{envname}.ini
@@ -37,3 +38,11 @@
37 python3-coverage html {[coverage]rc} {[coverage]dir}38 python3-coverage html {[coverage]rc} {[coverage]dir}
38sitepackages = True39sitepackages = True
39usedevelop = True40usedevelop = True
41
42[testenv:coverage-py35]
43commands =
44 python /usr/bin/python3-coverage run {[coverage]rc} -m nose2 -v
45 python3-coverage combine {[coverage]rc}
46 python3-coverage html {[coverage]rc} {[coverage]dir}
47sitepackages = True
48usedevelop = True

Subscribers

People subscribed via source and target branches

to all changes: