Merge lp:~lool/linaro-image-tools/testsuite-when-installed-v2 into lp:linaro-image-tools/11.11

Proposed by Loïc Minier
Status: Merged
Merged at revision: 304
Proposed branch: lp:~lool/linaro-image-tools/testsuite-when-installed-v2
Merge into: lp:linaro-image-tools/11.11
Diff against target: 1000 lines (+483/-228) (has conflicts)
20 files modified
linaro-media-create (+4/-8)
linaro_image_tools/cmd_runner.py (+6/-1)
linaro_image_tools/hwpack/testing.py (+0/-34)
linaro_image_tools/hwpack/tests/test_builder.py (+1/-1)
linaro_image_tools/hwpack/tests/test_packages.py (+1/-1)
linaro_image_tools/hwpack/tests/test_script.py (+3/-20)
linaro_image_tools/media_create/boards.py (+2/-1)
linaro_image_tools/media_create/hwpack.py (+2/-2)
linaro_image_tools/media_create/partitions.py (+1/-1)
linaro_image_tools/media_create/populate_boot.py.OTHER (+58/-0)
linaro_image_tools/media_create/rootfs.py (+1/-1)
linaro_image_tools/media_create/tests/fixtures.py (+2/-92)
linaro_image_tools/media_create/tests/test_media_create.py (+15/-62)
linaro_image_tools/media_create/unpack_binary_tarball.py (+1/-1)
linaro_image_tools/testing.py (+59/-0)
linaro_image_tools/tests/__init__.py (+10/-2)
linaro_image_tools/tests/fixtures.py (+113/-0)
linaro_image_tools/tests/test_cmd_runner.py (+84/-0)
linaro_image_tools/tests/test_utils.py (+111/-0)
linaro_image_tools/utils.py (+9/-1)
Contents conflict in linaro_image_tools/media_create/populate_boot.py
Text conflict in linaro_image_tools/media_create/tests/test_media_create.py
To merge this branch: bzr merge lp:~lool/linaro-image-tools/testsuite-when-installed-v2
Reviewer Review Type Date Requested Status
Guilherme Salgado (community) Approve
Review via email: mp+54679@code.launchpad.net

Description of the change

This series fixes bug #711312, but it also shuffles code around so that modules at the top of the hierarchy don't depend on modules down below (e.g. so that linaro_image_tools.utils doesn't depend on linaro_image_tools.hwpack or .media_create).

I'm aware of some minor issues with this patchset:
- there is one class of change I didn't finish: converting the "%s foo bar" % sudo_args calls to SUDO_ARGS + ["foo", "bar"]; I only did half of the changes -- I'm happy to finish it if reviewers think that's the right way to pursue the change
- it's a bit confusing to have linaro_image_tools.(hwpack.testing, media_create.tests.fixtures, testing, tests.fixtures) modules which all contain helpers for testing; maybe hwpack.tests.utils, media_create.tests.utils, and tests.utils would be a clearer set? I'm a bit worried about having too many utils though
- I didn't add a test for preferred_tools_dir when I promoted it to linaro_image_tools.utils; this is because it uses __file__; I guess I could make that an optional argument, but it would make callers slightly more complex; I think it's ok to keep this untested while it's that short

I did run the testsuite both from the source tree and from an installed version; I did the later with:
sudo ./setup.py install
python -m subunit.run linaro_image_tools.tests.test_suite|grep -v ^successful:|grep -v ^test:

To post a comment you must log in.
Revision history for this message
Loïc Minier (lool) wrote :

Incidentally, the find_command() changes also fix bug #710104. I managed to complete a run of:
linaro-media-create --image_file efikamx.img --image_size 1536M --dev efikamx --rootfs btrfs --hwpack ~/downloads/linaro/11.05/hwpack_linaro-efikamx_20110217-1_armel.tar.gz --binary ~/downloads/linaro/11.05/linaro-n-developer-tar-20110308-0.tar.gz --hwpack-force-yes

with this branch with the locally installed (not packaged -- sudo ./setup.py install) linaro-image-tools.

Revision history for this message
Guilherme Salgado (salgado) wrote :

On Thu, 2011-03-24 at 11:31 +0000, Loïc Minier wrote:
> This series fixes bug #711312, but it also shuffles code around so
> that modules at the top of the hierarchy don't depend on modules down
> below (e.g. so that linaro_image_tools.utils doesn't depend on
> linaro_image_tools.hwpack or .media_create).

The code shuffling is most welcome, but given the size of the diff, it's
very tricky to find out what are the exact bits that fix bug 711312.
Care to point them out for me?

>
> I'm aware of some minor issues with this patchset:
> - there is one class of change I didn't finish: converting the "%s foo
> bar" % sudo_args calls to SUDO_ARGS + ["foo", "bar"]; I only did half
> of the changes -- I'm happy to finish it if reviewers think that's the
> right way to pursue the change

Well, for that you reverted my recent changes to use the
mock's .commands_executed instead of .calls. The former makes for more
readable tests and makes it easier to spot differences when tests fail,
so I'm against your changes here. If all you want is to use the
SUDO_ARGS constant from cmd_runner.py you could just define sudo_args at
the top of test_media_create.py as

  sudo_args = " ".join(SUDO_ARGS)

instead of the current definition. That would allow the tests to
continue using .commands_executed instead of .calls

> - it's a bit confusing to have linaro_image_tools.(hwpack.testing,
> media_create.tests.fixtures, testing, tests.fixtures) modules which
> all contain helpers for testing; maybe hwpack.tests.utils,
> media_create.tests.utils, and tests.utils would be a clearer set? I'm
> a bit worried about having too many utils though

I think the best way forward here would be to have a testing directory
under linaro_image_tools, l_i_t.hwpack and l_i_t.media_create, with all
test helpers/fixtures in there. We could then have separate files for
utils and fixtures there if we think it's useful, but by making all
those names available in testing/__init__.py the tests themselves
wouldn't have to worry about the exact location of the code as they'd be
able to import helpers/fixtures directly from <whatever>.testing.

Oh, and the reason why I suggest a 'testing' dir is to separate actual
test code from test helpers/fixtures.

These changes can be saved for later, though, if you'd prefer.

> - I didn't add a test for preferred_tools_dir when I promoted it to
> linaro_image_tools.utils; this is because it uses __file__; I guess I
> could make that an optional argument, but it would make callers
> slightly more complex; I think it's ok to keep this untested while
> it's that short

That's not ideal, but I don't think it's a big deal either.

>
> I did run the testsuite both from the source tree and from an
> installed version; I did the later with:
> sudo ./setup.py install
> python -m subunit.run linaro_image_tools.tests.test_suite|grep -v
> ^successful:|grep -v ^test:

Does that actually use the system installed version or would it prefer
the one in the current directory if you had one? IOW, is '.' prepended
or appended to sys.path?

Revision history for this message
Loïc Minier (lool) wrote :

On Thu, Mar 24, 2011, Guilherme Salgado wrote:
> The code shuffling is most welcome, but given the size of the diff, it's
> very tricky to find out what are the exact bits that fix bug 711312.
> Care to point them out for me?

 It's the very first revision of the series which has the lp:xyz tag,
 r302 in this branch; it moves from hwpack's find_script to
 media_create's find_command().

> > I'm aware of some minor issues with this patchset:
> > - there is one class of change I didn't finish: converting the "%s foo
> > bar" % sudo_args calls to SUDO_ARGS + ["foo", "bar"]; I only did half
> > of the changes -- I'm happy to finish it if reviewers think that's the
> > right way to pursue the change
>
> Well, for that you reverted my recent changes to use the
> mock's .commands_executed instead of .calls. The former makes for more
> readable tests and makes it easier to spot differences when tests fail,
> so I'm against your changes here. If all you want is to use the
> SUDO_ARGS constant from cmd_runner.py you could just define sudo_args at
> the top of test_media_create.py as
>
> sudo_args = " ".join(SUDO_ARGS)
>
> instead of the current definition. That would allow the tests to
> continue using .commands_executed instead of .calls

 Ok; this is exactly what I guessed might be the case, and the reason I
 stopped mass-converting commands; I actually added a sudo_args
 definition as you suggest. I'll revert the changs from string to list
 in the tests.

> These changes can be saved for later, though, if you'd prefer.

 I don't mind deferring this to a later submission; I'll open a bug to
 not forget about it.

> > I did run the testsuite both from the source tree and from an
> > installed version; I did the later with:
> > sudo ./setup.py install
> > python -m subunit.run linaro_image_tools.tests.test_suite|grep -v
> > ^successful:|grep -v ^test:
>
> Does that actually use the system installed version or would it prefer
> the one in the current directory if you had one? IOW, is '.' prepended
> or appended to sys.path?

 It would probably pick the local version instead of the system one by
 default, but I had taken care to change to another directory before
 running the system-wide tests.

--
Loïc Minier

315. By Loïc Minier

Revert parts of r309; use MockCmdRunnerPopenFixture.mock.commands_executed
instead of .calls for clarity in the test cases, and simply define sudo_args
from SUDO_ARGS.

Revision history for this message
Guilherme Salgado (salgado) wrote :

This looks very good; I only have a few comments.

438 +from linaro_image_tools import cmd_runner
439 +
440 +from linaro_image_tools.cmd_runner import SUDO_ARGS

There's no need to import the latter as it's easily accessible from the cmd_runner you already have defined. That's on linaro_image_tools/media_create/tests/test_media_create.py but it's duplicated in linaro_image_tools/tests/test_cmd_runner.py as well.

And you don't need blank lines between those imports -- we only use blank lines to separate between stdlib/external/local imports.

review: Approve
316. By Loïc Minier

Use cmd_runner.SUDO_ARGS instead of importing it; tidy up imports.

Revision history for this message
Loïc Minier (lool) wrote :

On Thu, Mar 24, 2011, Guilherme Salgado wrote:
> There's no need to import the latter as it's easily accessible from
> the cmd_runner you already have defined. That's on
> linaro_image_tools/media_create/tests/test_media_create.py but it's
> duplicated in linaro_image_tools/tests/test_cmd_runner.py as well.

 (There was a third case in linaro_image_tools/tests/test_utils.py as
 well.)

> And you don't need blank lines between those imports -- we only use
> blank lines to separate between stdlib/external/local imports.

 Thanks for the advice; all fixed and pushed, will merge.

--
Loïc Minier

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'linaro-media-create'
2--- linaro-media-create 2011-03-23 22:55:29 +0000
3+++ linaro-media-create 2011-03-24 18:00:58 +0000
4@@ -23,6 +23,8 @@
5 import sys
6 import tempfile
7
8+from linaro_image_tools import cmd_runner
9+
10 from linaro_image_tools.media_create.boards import board_configs
11 from linaro_image_tools.media_create.check_device import (
12 confirm_device_selection_and_ensure_it_is_ready)
13@@ -36,14 +38,8 @@
14 from linaro_image_tools.media_create.unpack_binary_tarball import (
15 unpack_binary_tarball,
16 )
17-from linaro_image_tools.media_create.utils import (
18- ensure_command,
19- is_arm_host,
20- )
21-from linaro_image_tools.media_create import (
22- cmd_runner,
23- get_args_parser
24- )
25+from linaro_image_tools.media_create import get_args_parser
26+from linaro_image_tools.utils import ensure_command, is_arm_host
27
28 # Just define the global variables
29 TMP_DIR = None
30
31=== renamed file 'linaro_image_tools/media_create/cmd_runner.py' => 'linaro_image_tools/cmd_runner.py'
32--- linaro_image_tools/media_create/cmd_runner.py 2011-03-09 15:11:28 +0000
33+++ linaro_image_tools/cmd_runner.py 2011-03-24 18:00:58 +0000
34@@ -21,6 +21,9 @@
35 import subprocess
36
37
38+SUDO_ARGS = ['sudo', '-E']
39+
40+
41 def run(args, as_root=False, stdin=None, stdout=None, stderr=None):
42 """Run the given command as a sub process.
43
44@@ -37,8 +40,10 @@
45 """
46 assert isinstance(args, (list, tuple)), (
47 "The command to run must be a list or tuple, found: %s" % type(args))
48+ if isinstance(args, tuple):
49+ args = list(args)
50 if as_root and os.getuid() != 0:
51- args = ['sudo', '-E'] + args
52+ args = SUDO_ARGS + args
53 return Popen(args, stdin=stdin, stdout=stdout, stderr=stderr)
54
55
56
57=== modified file 'linaro_image_tools/hwpack/testing.py'
58--- linaro_image_tools/hwpack/testing.py 2011-03-23 22:25:10 +0000
59+++ linaro_image_tools/hwpack/testing.py 2011-03-24 18:00:58 +0000
60@@ -32,7 +32,6 @@
61
62 from debian.deb822 import Packages
63
64-from testtools import TestCase
65 from testtools.matchers import Annotate, Equals, Matcher, Mismatch
66
67 from linaro_image_tools.hwpack.better_tarfile import writeable_tarfile
68@@ -173,39 +172,6 @@
69 return "file:" + os.path.abspath(self.rootdir) +" ./"
70
71
72-class TestCaseWithFixtures(TestCase):
73- """A TestCase with the ability to easily add 'fixtures'.
74-
75- A fixture is an object which can be created and cleaned up, and
76- this test case knows how to manage them to ensure that they will
77- always be cleaned up at the end of the test.
78- """
79-
80- def useFixture(self, fixture):
81- """Make use of a fixture, ensuring that it will be cleaned up.
82-
83- Given a fixture, this method will run the `setUp` method of
84- the fixture, and ensure that its `tearDown` method will be
85- called at the end of the test, regardless of success or failure.
86-
87- :param fixture: the fixture to use.
88- :type fixture: an object with setUp and tearDown methods.
89- :return: the fixture that was passed in.
90- """
91- self.addCleanup(fixture.tearDown)
92- fixture.setUp()
93- return fixture
94-
95- def createTempFileAsFixture(self, prefix='tmp', dir=None):
96- """Create a temp file and make sure it is removed on tearDown.
97-
98- :return: The filename of the file created.
99- """
100- _, filename = tempfile.mkstemp(prefix=prefix, dir=dir)
101- self.addCleanup(os.unlink, filename)
102- return filename
103-
104-
105 class ConfigFileFixture(object):
106
107 def __init__(self, contents):
108
109=== modified file 'linaro_image_tools/hwpack/tests/test_builder.py'
110--- linaro_image_tools/hwpack/tests/test_builder.py 2011-03-23 22:25:10 +0000
111+++ linaro_image_tools/hwpack/tests/test_builder.py 2011-03-24 18:00:58 +0000
112@@ -48,8 +48,8 @@
113 IsHardwarePack,
114 MatchesStructure,
115 Not,
116- TestCaseWithFixtures,
117 )
118+from linaro_image_tools.testing import TestCaseWithFixtures
119
120
121 class ConfigFileMissingTests(TestCase):
122
123=== modified file 'linaro_image_tools/hwpack/tests/test_packages.py'
124--- linaro_image_tools/hwpack/tests/test_packages.py 2011-03-23 22:25:10 +0000
125+++ linaro_image_tools/hwpack/tests/test_packages.py 2011-03-24 18:00:58 +0000
126@@ -50,8 +50,8 @@
127 ContextManagerFixture,
128 DummyFetchedPackage,
129 MatchesPackage,
130- TestCaseWithFixtures,
131 )
132+from linaro_image_tools.testing import TestCaseWithFixtures
133
134
135 class GetPackagesFileTests(TestCase):
136
137=== modified file 'linaro_image_tools/hwpack/tests/test_script.py'
138--- linaro_image_tools/hwpack/tests/test_script.py 2011-03-23 22:25:10 +0000
139+++ linaro_image_tools/hwpack/tests/test_script.py 2011-03-24 18:00:58 +0000
140@@ -19,7 +19,6 @@
141 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
142 # USA.
143
144-import os
145 import subprocess
146
147 from linaro_image_tools.hwpack.hardwarepack import Metadata
148@@ -29,8 +28,9 @@
149 ConfigFileFixture,
150 DummyFetchedPackage,
151 IsHardwarePack,
152- TestCaseWithFixtures,
153 )
154+from linaro_image_tools.testing import TestCaseWithFixtures
155+from linaro_image_tools.utils import find_command
156
157
158 class ScriptTests(TestCaseWithFixtures):
159@@ -38,26 +38,9 @@
160
161 def setUp(self):
162 super(ScriptTests, self).setUp()
163- self.script_path = self.find_script()
164+ self.script_path = find_command("linaro-hwpack-create")
165 self.useFixture(ChdirToTempdirFixture())
166
167- def find_script(self):
168- script_name = "linaro-hwpack-create"
169- this_path = os.path.abspath(__file__)
170- parent_path = this_path
171- for i in range(4):
172- parent_path = os.path.dirname(parent_path)
173- possible_paths = [
174- os.path.join(parent_path, script_name),
175- os.path.join("usr", "local", "bin", script_name),
176- os.path.join("usr", "bin", script_name),
177- ]
178- for script_path in possible_paths:
179- if os.path.exists(script_path):
180- return script_path
181- raise AssertionError(
182- "Could not find linaro-hwpack-create script to test.")
183-
184 def run_script(self, args, expected_returncode=0):
185 cmdline = [self.script_path] + args
186 proc = subprocess.Popen(
187
188=== modified file 'linaro_image_tools/media_create/boards.py'
189--- linaro_image_tools/media_create/boards.py 2011-03-23 23:14:51 +0000
190+++ linaro_image_tools/media_create/boards.py 2011-03-24 18:00:58 +0000
191@@ -32,7 +32,8 @@
192 import struct
193 from binascii import crc32
194
195-from linaro_image_tools.media_create import cmd_runner
196+from linaro_image_tools import cmd_runner
197+
198 from linaro_image_tools.media_create.partitions import SECTOR_SIZE
199
200 # Notes:
201
202=== modified file 'linaro_image_tools/media_create/hwpack.py'
203--- linaro_image_tools/media_create/hwpack.py 2011-03-23 22:25:10 +0000
204+++ linaro_image_tools/media_create/hwpack.py 2011-03-24 18:00:58 +0000
205@@ -20,8 +20,8 @@
206 import os
207 import sys
208
209-from linaro_image_tools.media_create import cmd_runner
210-from linaro_image_tools.media_create.utils import (
211+from linaro_image_tools import cmd_runner
212+from linaro_image_tools.utils import (
213 is_arm_host,
214 find_command,
215 )
216
217=== modified file 'linaro_image_tools/media_create/partitions.py'
218--- linaro_image_tools/media_create/partitions.py 2011-03-23 22:25:10 +0000
219+++ linaro_image_tools/media_create/partitions.py 2011-03-24 18:00:58 +0000
220@@ -30,7 +30,7 @@
221 PARTITION_NORMAL,
222 )
223
224-from linaro_image_tools.media_create import cmd_runner
225+from linaro_image_tools import cmd_runner
226
227
228 HEADS = 128
229
230=== added file 'linaro_image_tools/media_create/populate_boot.py.OTHER'
231--- linaro_image_tools/media_create/populate_boot.py.OTHER 1970-01-01 00:00:00 +0000
232+++ linaro_image_tools/media_create/populate_boot.py.OTHER 2011-03-24 18:00:58 +0000
233@@ -0,0 +1,58 @@
234+# Copyright (C) 2010, 2011 Linaro
235+#
236+# Author: Guilherme Salgado <guilherme.salgado@linaro.org>
237+#
238+# This file is part of Linaro Image Tools.
239+#
240+# Linaro Image Tools is free software: you can redistribute it and/or modify
241+# it under the terms of the GNU General Public License as published by
242+# the Free Software Foundation, either version 3 of the License, or
243+# (at your option) any later version.
244+#
245+# Linaro Image Tools is distributed in the hope that it will be useful,
246+# but WITHOUT ANY WARRANTY; without even the implied warranty of
247+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
248+# GNU General Public License for more details.
249+#
250+# You should have received a copy of the GNU General Public License
251+# along with Linaro Image Tools. If not, see <http://www.gnu.org/licenses/>.
252+
253+import os
254+
255+from linaro_image_tools import cmd_runner
256+
257+
258+def populate_boot(board_config, chroot_dir, rootfs_uuid, boot_partition,
259+ boot_disk, boot_device_or_file, is_live, is_lowmem,
260+ consoles):
261+
262+ parts_dir = 'boot'
263+ if is_live:
264+ parts_dir = 'casper'
265+ uboot_parts_dir = os.path.join(chroot_dir, parts_dir)
266+
267+ cmd_runner.run(['mkdir', '-p', boot_disk]).wait()
268+ cmd_runner.run(['mount', boot_partition, boot_disk], as_root=True).wait()
269+
270+ if board_config.uboot_in_boot_part:
271+ uboot_flavor = board_config.uboot_flavor
272+ assert uboot_flavor is not None, (
273+ "uboot_in_boot_part is set but not uboot_flavor")
274+ uboot_bin = os.path.join(
275+ chroot_dir, 'usr', 'lib', 'u-boot', uboot_flavor, 'u-boot.bin')
276+ cmd_runner.run(
277+ ['cp', '-v', uboot_bin, boot_disk], as_root=True).wait()
278+
279+ boot_script = "%(boot_disk)s/%(boot_script_name)s" % (
280+ dict(boot_disk=boot_disk,
281+ boot_script_name=board_config.boot_script))
282+
283+ board_config.make_boot_files(
284+ uboot_parts_dir, is_live, is_lowmem, consoles, chroot_dir, rootfs_uuid,
285+ boot_disk, boot_script, boot_device_or_file)
286+
287+ cmd_runner.run(['sync']).wait()
288+ try:
289+ cmd_runner.run(['umount', boot_disk], as_root=True).wait()
290+ except cmd_runner.SubcommandNonZeroReturnValue:
291+ pass
292
293=== modified file 'linaro_image_tools/media_create/rootfs.py'
294--- linaro_image_tools/media_create/rootfs.py 2011-03-23 22:25:10 +0000
295+++ linaro_image_tools/media_create/rootfs.py 2011-03-24 18:00:58 +0000
296@@ -21,7 +21,7 @@
297 import os
298 import tempfile
299
300-from linaro_image_tools.media_create import cmd_runner
301+from linaro_image_tools import cmd_runner
302
303
304 def populate_rootfs(content_dir, root_disk, partition, rootfs_type,
305
306=== modified file 'linaro_image_tools/media_create/tests/fixtures.py'
307--- linaro_image_tools/media_create/tests/fixtures.py 2011-03-23 22:25:10 +0000
308+++ linaro_image_tools/media_create/tests/fixtures.py 2011-03-24 18:00:58 +0000
309@@ -18,28 +18,11 @@
310 # along with this program. If not, see <http://www.gnu.org/licenses/>.
311
312 import os
313-import shutil
314 import subprocess
315-import tempfile
316
317 from linaro_image_tools.media_create import partitions
318-from linaro_image_tools.media_create import cmd_runner
319-
320-
321-class CreateTempDirFixture(object):
322-
323- def __init__(self):
324- self.tempdir = None
325-
326- def setUp(self):
327- self.tempdir = tempfile.mkdtemp()
328-
329- def tearDown(self):
330- if os.path.exists(self.tempdir):
331- shutil.rmtree(self.tempdir)
332-
333- def get_temp_dir(self):
334- return self.tempdir
335+
336+from linaro_image_tools.tests.fixtures import MockSomethingFixture
337
338
339 class CreateTarballFixture(object):
340@@ -66,79 +49,6 @@
341 def get_tarball(self):
342 return self.tarball
343
344-
345-class MockSomethingFixture(object):
346- """A fixture which mocks something on the given object.
347-
348- Replaces attr_name on obj with the given mock, undoing that upon
349- tearDown().
350- """
351-
352- def __init__(self, obj, attr_name, mock):
353- self.obj = obj
354- self.attr_name = attr_name
355- self.mock = mock
356- self.orig_attr = getattr(obj, attr_name)
357-
358- def setUp(self):
359- setattr(self.obj, self.attr_name, self.mock)
360-
361- def tearDown(self):
362- setattr(self.obj, self.attr_name, self.orig_attr)
363-
364-
365-class MockCmdRunnerPopen(object):
366- """A mock for cmd_runner.Popen() which stores the args given to it."""
367- calls = None
368- # A variable that is set to False in __call__() and only set back to True
369- # when wait() is called, to indicate that tht subprocess has finished. Is
370- # used in tests to make sure all callsites wait for their child.
371- child_finished = True
372-
373- def __call__(self, cmd, *args, **kwargs):
374- self.child_finished = False
375- if self.calls is None:
376- self.calls = []
377- if isinstance(cmd, basestring):
378- all_args = [cmd]
379- else:
380- all_args = cmd
381- all_args.extend(args)
382- self.calls.append(all_args)
383- self.returncode = 0
384- return self
385-
386- def communicate(self, input=None):
387- self.wait()
388- return '', ''
389-
390- def wait(self):
391- self.child_finished = True
392- return self.returncode
393-
394- @property
395- def commands_executed(self):
396- return [' '.join(args) for args in self.calls]
397-
398-
399-class MockCmdRunnerPopenFixture(MockSomethingFixture):
400- """A test fixture which mocks cmd_runner.do_run with the given mock.
401-
402- If no mock is given, a MockCmdRunnerPopen instance is used.
403- """
404-
405- def __init__(self):
406- super(MockCmdRunnerPopenFixture, self).__init__(
407- cmd_runner, 'Popen', MockCmdRunnerPopen())
408-
409- def tearDown(self):
410- super(MockCmdRunnerPopenFixture, self).tearDown()
411- if not self.mock.child_finished:
412- raise AssertionError(
413- "You should call wait() or communicate() to ensure "
414- "the subprocess is finished before proceeding.")
415-
416-
417 class MockCallableWithPositionalArgs(object):
418 """A callable mock which just stores the positional args given to it.
419
420
421=== modified file 'linaro_image_tools/media_create/tests/test_media_create.py'
422--- linaro_image_tools/media_create/tests/test_media_create.py 2011-03-24 14:49:25 +0000
423+++ linaro_image_tools/media_create/tests/test_media_create.py 2011-03-24 18:00:58 +0000
424@@ -21,7 +21,6 @@
425 import glob
426 import os
427 import random
428-import stat
429 import string
430 import subprocess
431 import sys
432@@ -31,17 +30,14 @@
433
434 from testtools import TestCase
435
436-from linaro_image_tools.hwpack.testing import TestCaseWithFixtures
437-
438+from linaro_image_tools import cmd_runner
439+import linaro_image_tools.media_create
440 from linaro_image_tools.media_create import (
441 check_device,
442- cmd_runner,
443 boards,
444 partitions,
445 rootfs,
446- utils,
447 )
448-import linaro_image_tools.media_create
449 from linaro_image_tools.media_create.boards import (
450 LOADER_MIN_SIZE_S,
451 SECTOR_SIZE,
452@@ -88,23 +84,20 @@
453 populate_rootfs,
454 write_data_to_protected_file,
455 )
456+from linaro_image_tools.media_create.tests.fixtures import (
457+ CreateTarballFixture,
458+ MockRunSfdiskCommandsFixture,
459+ )
460 from linaro_image_tools.media_create.unpack_binary_tarball import (
461 unpack_binary_tarball,
462 )
463-from linaro_image_tools.media_create.utils import (
464- ensure_command,
465- find_command,
466- install_package_providing,
467- UnableToFindPackageProvidingCommand,
468- )
469-
470-from linaro_image_tools.media_create.tests.fixtures import (
471+from linaro_image_tools.testing import TestCaseWithFixtures
472+from linaro_image_tools.tests.fixtures import (
473 CreateTempDirFixture,
474- CreateTarballFixture,
475 MockCmdRunnerPopenFixture,
476 MockSomethingFixture,
477- MockRunSfdiskCommandsFixture,
478 )
479+<<<<<<< TREE
480
481
482 sudo_args = 'sudo -E'
483@@ -185,6 +178,12 @@
484 self.assertRaises(
485 UnableToFindPackageProvidingCommand,
486 install_package_providing, 'mkfs.lean')
487+=======
488+from linaro_image_tools.utils import find_command, preferred_tools_dir
489+
490+
491+sudo_args = " ".join(cmd_runner.SUDO_ARGS)
492+>>>>>>> MERGE-SOURCE
493
494
495 class TestGetMLOFile(TestCaseWithFixtures):
496@@ -582,52 +581,6 @@
497 self.assertEquals("67d641db-ea7d-4acf-9f46-5f1f8275dce2", uuid)
498
499
500-class TestCmdRunner(TestCaseWithFixtures):
501-
502- def test_run(self):
503- fixture = self.useFixture(MockCmdRunnerPopenFixture())
504- proc = cmd_runner.run(['foo', 'bar', 'baz'])
505- # Call wait or else MockCmdRunnerPopenFixture() raises an
506- # AssertionError().
507- proc.wait()
508- self.assertEqual(0, proc.returncode)
509- self.assertEqual([['foo', 'bar', 'baz']], fixture.mock.calls)
510-
511- def test_run_as_root_with_sudo(self):
512- fixture = self.useFixture(MockCmdRunnerPopenFixture())
513- self.useFixture(MockSomethingFixture(os, 'getuid', lambda: 1000))
514- cmd_runner.run(['foo', 'bar'], as_root=True).wait()
515- self.assertEqual(
516- ['%s foo bar' % sudo_args], fixture.mock.commands_executed)
517-
518- def test_run_as_root_as_root(self):
519- fixture = self.useFixture(MockCmdRunnerPopenFixture())
520- self.useFixture(MockSomethingFixture(os, 'getuid', lambda: 0))
521- cmd_runner.run(['foo', 'bar'], as_root=True).wait()
522- self.assertEqual([['foo', 'bar']], fixture.mock.calls)
523-
524- def test_run_succeeds_on_zero_return_code(self):
525- proc = cmd_runner.run(['true'])
526- # Need to wait() here as we're using the real Popen.
527- proc.wait()
528- self.assertEqual(0, proc.returncode)
529-
530- def test_run_raises_exception_on_non_zero_return_code(self):
531- def run_and_wait():
532- proc = cmd_runner.run(['false'])
533- proc.wait()
534- self.assertRaises(
535- cmd_runner.SubcommandNonZeroReturnValue, run_and_wait)
536-
537- def test_run_must_be_given_list_as_args(self):
538- self.assertRaises(AssertionError, cmd_runner.run, 'true')
539-
540- def test_Popen(self):
541- proc = cmd_runner.Popen('true')
542- returncode = proc.wait()
543- self.assertEqual(0, returncode)
544-
545-
546 class TestBoards(TestCaseWithFixtures):
547
548 def _mock_get_file_matching(self):
549
550=== modified file 'linaro_image_tools/media_create/unpack_binary_tarball.py'
551--- linaro_image_tools/media_create/unpack_binary_tarball.py 2011-03-23 22:25:10 +0000
552+++ linaro_image_tools/media_create/unpack_binary_tarball.py 2011-03-24 18:00:58 +0000
553@@ -17,7 +17,7 @@
554 # You should have received a copy of the GNU General Public License
555 # along with Linaro Image Tools. If not, see <http://www.gnu.org/licenses/>.
556
557-from linaro_image_tools.media_create import cmd_runner
558+from linaro_image_tools import cmd_runner
559
560
561 def unpack_binary_tarball(tarball, unpack_dir, as_root=True):
562
563=== added file 'linaro_image_tools/testing.py'
564--- linaro_image_tools/testing.py 1970-01-01 00:00:00 +0000
565+++ linaro_image_tools/testing.py 2011-03-24 18:00:58 +0000
566@@ -0,0 +1,59 @@
567+# Copyright (C) 2010, 2011 Linaro
568+#
569+# Author: James Westby <james.westby@linaro.org>
570+#
571+# This file is part of Linaro Image Tools.
572+#
573+# Linaro Image Tools is free software; you can redistribute it and/or
574+# modify it under the terms of the GNU General Public License
575+# as published by the Free Software Foundation; either version 2
576+# of the License, or (at your option) any later version.
577+#
578+# Linaro Image Tools is distributed in the hope that it will be useful,
579+# but WITHOUT ANY WARRANTY; without even the implied warranty of
580+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
581+# GNU General Public License for more details.
582+#
583+# You should have received a copy of the GNU General Public License
584+# along with Linaro Image Tools; if not, write to the Free Software
585+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
586+# USA.
587+
588+import os
589+import tempfile
590+
591+from testtools import TestCase
592+
593+
594+class TestCaseWithFixtures(TestCase):
595+ """A TestCase with the ability to easily add 'fixtures'.
596+
597+ A fixture is an object which can be created and cleaned up, and
598+ this test case knows how to manage them to ensure that they will
599+ always be cleaned up at the end of the test.
600+ """
601+
602+ def useFixture(self, fixture):
603+ """Make use of a fixture, ensuring that it will be cleaned up.
604+
605+ Given a fixture, this method will run the `setUp` method of
606+ the fixture, and ensure that its `tearDown` method will be
607+ called at the end of the test, regardless of success or failure.
608+
609+ :param fixture: the fixture to use.
610+ :type fixture: an object with setUp and tearDown methods.
611+ :return: the fixture that was passed in.
612+ """
613+ self.addCleanup(fixture.tearDown)
614+ fixture.setUp()
615+ return fixture
616+
617+ def createTempFileAsFixture(self, prefix='tmp', dir=None):
618+ """Create a temp file and make sure it is removed on tearDown.
619+
620+ :return: The filename of the file created.
621+ """
622+ _, filename = tempfile.mkstemp(prefix=prefix, dir=dir)
623+ self.addCleanup(os.unlink, filename)
624+ return filename
625+
626
627=== modified file 'linaro_image_tools/tests/__init__.py'
628--- linaro_image_tools/tests/__init__.py 2011-03-23 22:25:10 +0000
629+++ linaro_image_tools/tests/__init__.py 2011-03-24 18:00:58 +0000
630@@ -1,10 +1,18 @@
631+import unittest
632+
633 from linaro_image_tools.hwpack.tests import test_suite as hwpack_suite
634 from linaro_image_tools.media_create.tests import (
635 test_suite as media_create_suite,
636 )
637
638-
639 def test_suite():
640- suite = hwpack_suite()
641+ module_names = [
642+ 'linaro_image_tools.tests.test_cmd_runner',
643+ 'linaro_image_tools.tests.test_utils',
644+ ]
645+ loader = unittest.TestLoader()
646+ suite = loader.loadTestsFromNames(module_names)
647+ suite.addTests(hwpack_suite())
648 suite.addTests(media_create_suite())
649 return suite
650+
651
652=== added file 'linaro_image_tools/tests/fixtures.py'
653--- linaro_image_tools/tests/fixtures.py 1970-01-01 00:00:00 +0000
654+++ linaro_image_tools/tests/fixtures.py 2011-03-24 18:00:58 +0000
655@@ -0,0 +1,113 @@
656+# Copyright (C) 2010, 2011 Linaro
657+#
658+# Author: Guilherme Salgado <guilherme.salgado@linaro.org>
659+#
660+# This file is part of Linaro Image Tools.
661+#
662+# Linaro Image Tools is free software: you can redistribute it and/or modify
663+# it under the terms of the GNU General Public License as published by
664+# the Free Software Foundation, either version 3 of the License, or
665+# (at your option) any later version.
666+#
667+# Linaro Image Tools is distributed in the hope that it will be useful,
668+# but WITHOUT ANY WARRANTY; without even the implied warranty of
669+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
670+# GNU General Public License for more details.
671+#
672+# You should have received a copy of the GNU General Public License
673+# along with this program. If not, see <http://www.gnu.org/licenses/>.
674+
675+import os
676+import shutil
677+import tempfile
678+
679+from linaro_image_tools import cmd_runner
680+
681+
682+class CreateTempDirFixture(object):
683+
684+ def __init__(self):
685+ self.tempdir = None
686+
687+ def setUp(self):
688+ self.tempdir = tempfile.mkdtemp()
689+
690+ def tearDown(self):
691+ if os.path.exists(self.tempdir):
692+ shutil.rmtree(self.tempdir)
693+
694+ def get_temp_dir(self):
695+ return self.tempdir
696+
697+
698+class MockSomethingFixture(object):
699+ """A fixture which mocks something on the given object.
700+
701+ Replaces attr_name on obj with the given mock, undoing that upon
702+ tearDown().
703+ """
704+
705+ def __init__(self, obj, attr_name, mock):
706+ self.obj = obj
707+ self.attr_name = attr_name
708+ self.mock = mock
709+ self.orig_attr = getattr(obj, attr_name)
710+
711+ def setUp(self):
712+ setattr(self.obj, self.attr_name, self.mock)
713+
714+ def tearDown(self):
715+ setattr(self.obj, self.attr_name, self.orig_attr)
716+
717+
718+class MockCmdRunnerPopen(object):
719+ """A mock for cmd_runner.Popen() which stores the args given to it."""
720+ calls = None
721+ # A variable that is set to False in __call__() and only set back to True
722+ # when wait() is called, to indicate that the subprocess has finished. Is
723+ # used in tests to make sure all callsites wait for their child.
724+ child_finished = True
725+
726+ def __call__(self, cmd, *args, **kwargs):
727+ self.child_finished = False
728+ if self.calls is None:
729+ self.calls = []
730+ if isinstance(cmd, basestring):
731+ all_args = [cmd]
732+ else:
733+ all_args = cmd
734+ all_args.extend(args)
735+ self.calls.append(all_args)
736+ self.returncode = 0
737+ return self
738+
739+ def communicate(self, input=None):
740+ self.wait()
741+ return '', ''
742+
743+ def wait(self):
744+ self.child_finished = True
745+ return self.returncode
746+
747+ @property
748+ def commands_executed(self):
749+ return [' '.join(args) for args in self.calls]
750+
751+
752+class MockCmdRunnerPopenFixture(MockSomethingFixture):
753+ """A test fixture which mocks cmd_runner.do_run with the given mock.
754+
755+ If no mock is given, a MockCmdRunnerPopen instance is used.
756+ """
757+
758+ def __init__(self):
759+ super(MockCmdRunnerPopenFixture, self).__init__(
760+ cmd_runner, 'Popen', MockCmdRunnerPopen())
761+
762+ def tearDown(self):
763+ super(MockCmdRunnerPopenFixture, self).tearDown()
764+ if not self.mock.child_finished:
765+ raise AssertionError(
766+ "You should call wait() or communicate() to ensure "
767+ "the subprocess is finished before proceeding.")
768+
769
770=== added file 'linaro_image_tools/tests/test_cmd_runner.py'
771--- linaro_image_tools/tests/test_cmd_runner.py 1970-01-01 00:00:00 +0000
772+++ linaro_image_tools/tests/test_cmd_runner.py 2011-03-24 18:00:58 +0000
773@@ -0,0 +1,84 @@
774+# Copyright (C) 2010, 2011 Linaro
775+#
776+# Author: Guilherme Salgado <guilherme.salgado@linaro.org>
777+#
778+# This file is part of Linaro Image Tools.
779+#
780+# Linaro Image Tools is free software: you can redistribute it and/or modify
781+# it under the terms of the GNU General Public License as published by
782+# the Free Software Foundation, either version 3 of the License, or
783+# (at your option) any later version.
784+#
785+# Linaro Image Tools is distributed in the hope that it will be useful,
786+# but WITHOUT ANY WARRANTY; without even the implied warranty of
787+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
788+# GNU General Public License for more details.
789+#
790+# You should have received a copy of the GNU General Public License
791+# along with this program. If not, see <http://www.gnu.org/licenses/>.
792+
793+import os
794+
795+from linaro_image_tools import cmd_runner
796+from linaro_image_tools.testing import TestCaseWithFixtures
797+from linaro_image_tools.tests.fixtures import (
798+ MockCmdRunnerPopenFixture,
799+ MockSomethingFixture,
800+ )
801+
802+
803+sudo_args = " ".join(cmd_runner.SUDO_ARGS)
804+
805+
806+class TestCmdRunner(TestCaseWithFixtures):
807+
808+ def test_run(self):
809+ fixture = self.useFixture(MockCmdRunnerPopenFixture())
810+ proc = cmd_runner.run(['foo', 'bar', 'baz'])
811+ # Call wait or else MockCmdRunnerPopenFixture() raises an
812+ # AssertionError().
813+ proc.wait()
814+ self.assertEqual(0, proc.returncode)
815+ self.assertEqual(['foo bar baz'], fixture.mock.commands_executed)
816+
817+ def test_run_as_root_with_sudo(self):
818+ fixture = self.useFixture(MockCmdRunnerPopenFixture())
819+ self.useFixture(MockSomethingFixture(os, 'getuid', lambda: 1000))
820+ cmd_runner.run(['foo', 'bar'], as_root=True).wait()
821+ self.assertEqual(
822+ ['%s foo bar' % sudo_args], fixture.mock.commands_executed)
823+
824+ def test_run_as_root_as_root(self):
825+ fixture = self.useFixture(MockCmdRunnerPopenFixture())
826+ self.useFixture(MockSomethingFixture(os, 'getuid', lambda: 0))
827+ cmd_runner.run(['foo', 'bar'], as_root=True).wait()
828+ self.assertEqual(['foo bar'], fixture.mock.commands_executed)
829+
830+ def test_tuple_with_sudo(self):
831+ fixture = self.useFixture(MockCmdRunnerPopenFixture())
832+ self.useFixture(MockSomethingFixture(os, 'getuid', lambda: 1000))
833+ cmd_runner.run(('foo', 'bar',), as_root=True).wait()
834+ self.assertEqual(
835+ ['%s foo bar' % sudo_args], fixture.mock.commands_executed)
836+
837+ def test_run_succeeds_on_zero_return_code(self):
838+ proc = cmd_runner.run(['true'])
839+ # Need to wait() here as we're using the real Popen.
840+ proc.wait()
841+ self.assertEqual(0, proc.returncode)
842+
843+ def test_run_raises_exception_on_non_zero_return_code(self):
844+ def run_and_wait():
845+ proc = cmd_runner.run(['false'])
846+ proc.wait()
847+ self.assertRaises(
848+ cmd_runner.SubcommandNonZeroReturnValue, run_and_wait)
849+
850+ def test_run_must_be_given_list_as_args(self):
851+ self.assertRaises(AssertionError, cmd_runner.run, 'true')
852+
853+ def test_Popen(self):
854+ proc = cmd_runner.Popen('true')
855+ returncode = proc.wait()
856+ self.assertEqual(0, returncode)
857+
858
859=== added file 'linaro_image_tools/tests/test_utils.py'
860--- linaro_image_tools/tests/test_utils.py 1970-01-01 00:00:00 +0000
861+++ linaro_image_tools/tests/test_utils.py 2011-03-24 18:00:58 +0000
862@@ -0,0 +1,111 @@
863+# Copyright (C) 2010, 2011 Linaro
864+#
865+# Author: Guilherme Salgado <guilherme.salgado@linaro.org>
866+#
867+# This file is part of Linaro Image Tools.
868+#
869+# Linaro Image Tools is free software: you can redistribute it and/or modify
870+# it under the terms of the GNU General Public License as published by
871+# the Free Software Foundation, either version 3 of the License, or
872+# (at your option) any later version.
873+#
874+# Linaro Image Tools is distributed in the hope that it will be useful,
875+# but WITHOUT ANY WARRANTY; without even the implied warranty of
876+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
877+# GNU General Public License for more details.
878+#
879+# You should have received a copy of the GNU General Public License
880+# along with this program. If not, see <http://www.gnu.org/licenses/>.
881+
882+import os
883+import stat
884+import subprocess
885+import sys
886+
887+from linaro_image_tools import cmd_runner, utils
888+from linaro_image_tools.testing import TestCaseWithFixtures
889+from linaro_image_tools.tests.fixtures import (
890+ CreateTempDirFixture,
891+ MockCmdRunnerPopenFixture,
892+ MockSomethingFixture,
893+ )
894+from linaro_image_tools.utils import (
895+ ensure_command,
896+ find_command,
897+ install_package_providing,
898+ preferred_tools_dir,
899+ UnableToFindPackageProvidingCommand,
900+ )
901+
902+
903+sudo_args = " ".join(cmd_runner.SUDO_ARGS)
904+
905+
906+class TestEnsureCommand(TestCaseWithFixtures):
907+
908+ install_pkg_providing_called = False
909+
910+ def setUp(self):
911+ super(TestEnsureCommand, self).setUp()
912+ self.useFixture(MockSomethingFixture(
913+ sys, 'stdout', open('/dev/null', 'w')))
914+
915+ def test_command_already_present(self):
916+ self.mock_install_package_providing()
917+ ensure_command('apt-get')
918+ self.assertFalse(self.install_pkg_providing_called)
919+
920+ def test_command_not_present(self):
921+ self.mock_install_package_providing()
922+ ensure_command('apt-get-two-o')
923+ self.assertTrue(self.install_pkg_providing_called)
924+
925+ def mock_install_package_providing(self):
926+ def mock_func(command):
927+ self.install_pkg_providing_called = True
928+ self.useFixture(MockSomethingFixture(
929+ utils, 'install_package_providing', mock_func))
930+
931+
932+class TestFindCommand(TestCaseWithFixtures):
933+
934+ def test_preferred_dir(self):
935+ tempdir = self.useFixture(CreateTempDirFixture()).get_temp_dir()
936+ lmc = 'linaro-media-create'
937+ path = os.path.join(tempdir, lmc)
938+ open(path, 'w').close()
939+ os.chmod(path, stat.S_IXUSR)
940+ self.assertEquals(path, find_command(lmc, tempdir))
941+
942+ def test_existing_command(self):
943+ lmc = 'linaro-media-create'
944+ prefer_dir = preferred_tools_dir()
945+ if prefer_dir is None:
946+ expected, _ = cmd_runner.run(
947+ ['which', lmc, ],
948+ stdout=subprocess.PIPE).communicate()
949+ expected = expected.strip()
950+ else:
951+ expected = os.path.join(prefer_dir, lmc)
952+ self.assertEquals(expected, find_command(lmc))
953+
954+ def test_nonexisting_command(self):
955+ self.assertEquals(find_command('linaro-moo'), None)
956+
957+
958+class TestInstallPackageProviding(TestCaseWithFixtures):
959+
960+ def test_found_package(self):
961+ self.useFixture(MockSomethingFixture(
962+ sys, 'stdout', open('/dev/null', 'w')))
963+ fixture = self.useFixture(MockCmdRunnerPopenFixture())
964+ install_package_providing('mkfs.vfat')
965+ self.assertEqual(
966+ ['%s apt-get install dosfstools' % sudo_args],
967+ fixture.mock.commands_executed)
968+
969+ def test_not_found_package(self):
970+ self.assertRaises(
971+ UnableToFindPackageProvidingCommand,
972+ install_package_providing, 'mkfs.lean')
973+
974
975=== renamed file 'linaro_image_tools/media_create/utils.py' => 'linaro_image_tools/utils.py'
976--- linaro_image_tools/media_create/utils.py 2011-03-24 11:49:40 +0000
977+++ linaro_image_tools/utils.py 2011-03-24 18:00:58 +0000
978@@ -25,7 +25,7 @@
979 except ImportError:
980 CommandNotFound = None
981
982-from linaro_image_tools.media_create import cmd_runner
983+from linaro_image_tools import cmd_runner
984
985
986 def install_package_providing(command):
987@@ -99,5 +99,13 @@
988 return platform.machine().startswith('arm')
989
990
991+def preferred_tools_dir():
992+ prefer_dir = None
993+ # running from bzr checkout?
994+ if not os.path.isabs(__file__):
995+ prefer_dir = os.getcwd()
996+ return prefer_dir
997+
998+
999 class UnableToFindPackageProvidingCommand(Exception):
1000 """We can't find a package which provides the given command."""

Subscribers

People subscribed via source and target branches