Merge lp:~salgado/linaro-image-tools/misc into lp:linaro-image-tools/11.11

Proposed by Guilherme Salgado
Status: Merged
Merged at revision: 265
Proposed branch: lp:~salgado/linaro-image-tools/misc
Merge into: lp:linaro-image-tools/11.11
Diff against target: 99 lines (+25/-10)
4 files modified
README (+2/-0)
linaro_media_create/tests/fixtures.py (+16/-4)
linaro_media_create/tests/test_media_create.py (+6/-5)
linaro_media_create/utils.py (+1/-1)
To merge this branch: bzr merge lp:~salgado/linaro-image-tools/misc
Reviewer Review Type Date Requested Status
James Westby (community) Approve
Review via email: mp+47700@code.launchpad.net

Description of the change

When testing lmc in a chroot I noticed install_package_providing() would not wait for its child so we could end up running multiple 'apt-get install' in parallel, which will fail.

In the process of fixing that it occurred to me that it'd be worthwhile to assert in MockCmdRunnerPopenFixture (which is used by most of our tests that run subprocesses) that any code that invokes __call__() on a Popen object must also call wait() (either directly or via communicate()) on it. So I did that, and although there were no callsites (other than install_package_providing) that were not waiting for their child, I'm sure this new assertion will help prevent regressions.

To post a comment you must log in.
Revision history for this message
James Westby (james-w) wrote :

Nice. I like the extra check. We can add a way to avoid the check if
we ever need to when we encounter it.

Thanks,

James

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'README'
2--- README 2010-12-10 21:39:04 +0000
3+++ README 2011-01-27 18:01:50 +0000
4@@ -13,6 +13,8 @@
5 - dpkg-dev
6 - python-parted
7 - python-dbus
8+ - python-apt
9+ - qemu-kvm
10
11 And run the following command:
12
13
14=== modified file 'linaro_media_create/tests/fixtures.py'
15--- linaro_media_create/tests/fixtures.py 2011-01-17 17:51:13 +0000
16+++ linaro_media_create/tests/fixtures.py 2011-01-27 18:01:50 +0000
17@@ -66,7 +66,13 @@
18 class MockCmdRunnerPopen(object):
19 """A mock for cmd_runner.Popen() which stores the args given to it."""
20 calls = None
21+ # A variable that is set to False in __call__() and only set back to True
22+ # when wait() is called, to indicate that tht subprocess has finished. Is
23+ # used in tests to make sure all callsites wait for their child.
24+ child_finished = True
25+
26 def __call__(self, cmd, *args, **kwargs):
27+ self.child_finished = False
28 if self.calls is None:
29 self.calls = []
30 if isinstance(cmd, basestring):
31@@ -83,6 +89,7 @@
32 return '', ''
33
34 def wait(self):
35+ self.child_finished = True
36 return self.returncode
37
38 @property
39@@ -96,11 +103,16 @@
40 If no mock is given, a MockCmdRunnerPopen instance is used.
41 """
42
43- def __init__(self, mock=None):
44- if mock is None:
45- mock = MockCmdRunnerPopen()
46+ def __init__(self):
47 super(MockCmdRunnerPopenFixture, self).__init__(
48- cmd_runner, 'Popen', mock)
49+ cmd_runner, 'Popen', MockCmdRunnerPopen())
50+
51+ def tearDown(self):
52+ super(MockCmdRunnerPopenFixture, self).tearDown()
53+ if not self.mock.child_finished:
54+ raise AssertionError(
55+ "You should call wait() or communicate() to ensure "
56+ "the subprocess is finished before proceeding.")
57
58
59 class MockCallableWithPositionalArgs(object):
60
61=== modified file 'linaro_media_create/tests/test_media_create.py'
62--- linaro_media_create/tests/test_media_create.py 2011-01-26 18:03:50 +0000
63+++ linaro_media_create/tests/test_media_create.py 2011-01-27 18:01:50 +0000
64@@ -354,16 +354,17 @@
65 class TestCmdRunner(TestCaseWithFixtures):
66
67 def test_run(self):
68- fixture = MockCmdRunnerPopenFixture()
69- self.useFixture(fixture)
70+ fixture = self.useFixture(MockCmdRunnerPopenFixture())
71 proc = cmd_runner.run(['foo', 'bar', 'baz'])
72+ # Call wait or else MockCmdRunnerPopenFixture() raises an
73+ # AssertionError().
74+ proc.wait()
75 self.assertEqual(0, proc.returncode)
76 self.assertEqual([['foo', 'bar', 'baz']], fixture.mock.calls)
77
78 def test_run_as_root(self):
79- fixture = MockCmdRunnerPopenFixture()
80- self.useFixture(fixture)
81- cmd_runner.run(['foo', 'bar'], as_root=True)
82+ fixture = self.useFixture(MockCmdRunnerPopenFixture())
83+ cmd_runner.run(['foo', 'bar'], as_root=True).wait()
84 self.assertEqual([['sudo', 'foo', 'bar']], fixture.mock.calls)
85
86 def test_run_succeeds_on_zero_return_code(self):
87
88=== modified file 'linaro_media_create/utils.py'
89--- linaro_media_create/utils.py 2011-01-18 12:43:13 +0000
90+++ linaro_media_create/utils.py 2011-01-27 18:01:50 +0000
91@@ -28,7 +28,7 @@
92 package, _ = packages[0]
93 print ("Installing required command %s from package %s"
94 % (command, package))
95- cmd_runner.run(['apt-get', 'install', package], as_root=True)
96+ cmd_runner.run(['apt-get', 'install', package], as_root=True).wait()
97
98
99 def ensure_command(command):

Subscribers

People subscribed via source and target branches