| #!/usr/bin/python |
| |
| # Copyright (c) 2011 The Chromium OS Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| """Unit tests for cros_portage_upgrade.py.""" |
| |
| import cStringIO |
| import exceptions |
| import optparse |
| import os |
| import re |
| import sys |
| import unittest |
| |
| import mox |
| |
| import cros_portage_upgrade as cpu |
| import parallel_emerge |
| import portage.package.ebuild.config as portcfg |
| import portage.tests.resolver.ResolverPlayground as respgnd |
| |
| # Configuration for generating a temporary valid ebuild hierarchy. |
| # TODO(mtennant): Wrap this mechanism to create multiple overlays. |
| EBUILDS = { |
| "dev-libs/A-1": {"RDEPEND" : "dev-libs/B"}, |
| "dev-libs/A-2": {"RDEPEND" : "dev-libs/B"}, |
| "dev-libs/B-1": {"RDEPEND" : "dev-libs/C"}, |
| "dev-libs/B-2": {"RDEPEND" : "dev-libs/C"}, |
| "dev-libs/C-1": {}, |
| "dev-libs/C-2": {}, |
| "dev-libs/D-1": {}, |
| "dev-libs/D-2": {}, |
| "dev-libs/E-2": {}, |
| "dev-libs/E-3": {}, |
| |
| "chromeos-base/flimflam-0.0.1-r228": { |
| "EAPI" : "2", |
| "SLOT" : "0", |
| "KEYWORDS" : "amd64 x86 arm", |
| "RDEPEND" : ">=dev-libs/D-2", |
| }, |
| "chromeos-base/libchrome-57098-r4": { |
| "EAPI" : "2", |
| "SLOT" : "0", |
| "KEYWORDS" : "amd64 x86 arm", |
| "RDEPEND" : ">=dev-libs/E-2", |
| }, |
| "chromeos-base/libcros-1": { |
| "EAPI" : "2", |
| "SLOT" : "0", |
| "KEYWORDS" : "amd64 x86 arm", |
| "RDEPEND" : "dev-libs/B dev-libs/C chromeos-base/flimflam", |
| "DEPEND" : |
| "dev-libs/B dev-libs/C chromeos-base/flimflam chromeos-base/libchrome", |
| }, |
| |
| "Virtual/libusb-0" : { |
| "EAPI" :"2", "SLOT" : "0", |
| "RDEPEND" : |
| "|| ( >=dev-libs/libusb-0.1.12-r1:0 dev-libs/libusb-compat " + |
| ">=sys-freebsd/freebsd-lib-8.0[usb] )"}, |
| "virtual/libusb-1" : { |
| "EAPI" :"2", "SLOT" : "1", |
| "RDEPEND" : ">=dev-libs/libusb-1.0.4:1"}, |
| "dev-libs/libusb-0.1.13" : {}, |
| "dev-libs/libusb-1.0.5" : {"SLOT":"1"}, |
| "dev-libs/libusb-compat-1" : {}, |
| "sys-freebsd/freebsd-lib-8": {"IUSE" : "+usb"}, |
| |
| "sys-fs/udev-164" : {"EAPI" : "1", "RDEPEND" : "virtual/libusb:0"}, |
| |
| "virtual/jre-1.5.0" : { |
| "SLOT" : "1.5", |
| "RDEPEND" : "|| ( =dev-java/sun-jre-bin-1.5.0* =virtual/jdk-1.5.0* )"}, |
| "virtual/jre-1.5.0-r1" : { |
| "SLOT" : "1.5", |
| "RDEPEND" : "|| ( =dev-java/sun-jre-bin-1.5.0* =virtual/jdk-1.5.0* )"}, |
| "virtual/jre-1.6.0" : { |
| "SLOT" : "1.6", |
| "RDEPEND" : "|| ( =dev-java/sun-jre-bin-1.6.0* =virtual/jdk-1.6.0* )"}, |
| "virtual/jre-1.6.0-r1" : { |
| "SLOT" : "1.6", |
| "RDEPEND" : "|| ( =dev-java/sun-jre-bin-1.6.0* =virtual/jdk-1.6.0* )"}, |
| "virtual/jdk-1.5.0" : { |
| "SLOT" : "1.5", |
| "RDEPEND" : "|| ( =dev-java/sun-jdk-1.5.0* dev-java/gcj-jdk )"}, |
| "virtual/jdk-1.5.0-r1" : { |
| "SLOT" : "1.5", |
| "RDEPEND" : "|| ( =dev-java/sun-jdk-1.5.0* dev-java/gcj-jdk )"}, |
| "virtual/jdk-1.6.0" : { |
| "SLOT" : "1.6", |
| "RDEPEND" : "|| ( =dev-java/icedtea-6* =dev-java/sun-jdk-1.6.0* )"}, |
| "virtual/jdk-1.6.0-r1" : { |
| "SLOT" : "1.6", |
| "RDEPEND" : "|| ( =dev-java/icedtea-6* =dev-java/sun-jdk-1.6.0* )"}, |
| "dev-java/gcj-jdk-4.5" : {}, |
| "dev-java/gcj-jdk-4.5-r1" : {}, |
| "dev-java/icedtea-6.1" : {}, |
| "dev-java/icedtea-6.1-r1" : {}, |
| "dev-java/sun-jdk-1.5" : {"SLOT" : "1.5"}, |
| "dev-java/sun-jdk-1.6" : {"SLOT" : "1.6"}, |
| "dev-java/sun-jre-bin-1.5" : {"SLOT" : "1.5"}, |
| "dev-java/sun-jre-bin-1.6" : {"SLOT" : "1.6"}, |
| |
| "dev-java/ant-core-1.8" : {"DEPEND" : ">=virtual/jdk-1.4"}, |
| "dev-db/hsqldb-1.8" : {"RDEPEND" : ">=virtual/jre-1.6"}, |
| } |
| |
| INSTALLED = { |
| "dev-libs/A-1": {"RDEPEND" : "dev-libs/B"}, |
| "dev-libs/B-1": {"RDEPEND" : "dev-libs/C"}, |
| "dev-libs/C-1": {}, |
| "dev-libs/D-1": {}, |
| |
| "virtual/jre-1.5.0" : { |
| "SLOT" : "1.5", |
| "RDEPEND" : "|| ( =virtual/jdk-1.5.0* =dev-java/sun-jre-bin-1.5.0* )"}, |
| "virtual/jre-1.6.0" : { |
| "SLOT" : "1.6", |
| "RDEPEND" : "|| ( =virtual/jdk-1.6.0* =dev-java/sun-jre-bin-1.6.0* )"}, |
| "virtual/jdk-1.5.0" : { |
| "SLOT" : "1.5", |
| "RDEPEND" : "|| ( =dev-java/sun-jdk-1.5.0* dev-java/gcj-jdk )"}, |
| "virtual/jdk-1.6.0" : { |
| "SLOT" : "1.6", |
| "RDEPEND" : "|| ( =dev-java/icedtea-6* =dev-java/sun-jdk-1.6.0* )"}, |
| "dev-java/gcj-jdk-4.5" : {}, |
| "dev-java/icedtea-6.1" : {}, |
| |
| "virtual/libusb-0" : { |
| "EAPI" :"2", "SLOT" : "0", |
| "RDEPEND" : |
| "|| ( >=dev-libs/libusb-0.1.12-r1:0 dev-libs/libusb-compat " + |
| ">=sys-freebsd/freebsd-lib-8.0[usb] )"}, |
| } |
| |
| # For verifying dependency graph results |
| GOLDEN_DEP_GRAPHS = { |
| "dev-libs/A-2" : { "needs" : { "dev-libs/B-2" : "runtime" }, |
| "action" : "merge" }, |
| "dev-libs/B-2" : { "needs" : { "dev-libs/C-2" : "runtime" } }, |
| "dev-libs/C-2" : { "needs" : { } }, |
| "dev-libs/D-2" : { "needs" : { } }, |
| "dev-libs/E-3" : { "needs" : { } }, |
| "chromeos-base/libcros-1" : { "needs" : { |
| "dev-libs/B-2" : "runtime/buildtime", |
| "dev-libs/C-2" : "runtime/buildtime", |
| "chromeos-base/libchrome-57098-r4" : "buildtime", |
| "chromeos-base/flimflam-0.0.1-r228" : "runtime/buildtime" |
| } }, |
| "chromeos-base/flimflam-0.0.1-r228" : { "needs" : { |
| "dev-libs/D-2" : "runtime" |
| } }, |
| "chromeos-base/libchrome-57098-r4" : { "needs" : { |
| "dev-libs/E-3" : "runtime" |
| } }, |
| } |
| |
| # For verifying dependency list results |
| GOLDEN_DEP_LISTS = { |
| "dev-libs/A" : ['dev-libs/A-2', 'dev-libs/B-2', 'dev-libs/C-2'], |
| "dev-libs/B" : ['dev-libs/B-2', 'dev-libs/C-2'], |
| "dev-libs/C" : ['dev-libs/C-2'], |
| "virtual/libusb" : ['virtual/libusb-1', 'dev-libs/libusb-1.0.5'], |
| "chromeos-base/libcros" : ['chromeos-base/libcros-1', |
| 'chromeos-base/libchrome-57098-r4', |
| 'dev-libs/E-3', |
| 'dev-libs/B-2', |
| 'dev-libs/C-2', |
| 'chromeos-base/flimflam-0.0.1-r228', |
| 'dev-libs/D-2', |
| ], |
| } |
| |
| def _GetGoldenDepsList(pkg): |
| """Retrieve the golden dependency list for |pkg| from GOLDEN_DEP_LISTS.""" |
| return GOLDEN_DEP_LISTS.get(pkg, None) |
| |
| def _VerifyDepsGraph(deps_graph, pkg): |
| """Verfication function for Mox to validate deps graph for |pkg|.""" |
| if deps_graph is None: |
| print "Error: no dependency graph passed into _GetPreOrderDepGraph" |
| return False |
| |
| if type(deps_graph) != dict: |
| print "Error: dependency graph is expected to be a dict. Instead: " |
| print repr(deps_graph) |
| return False |
| |
| validated = True |
| |
| # Verify size |
| golden_deps_list = _GetGoldenDepsList(pkg) |
| if golden_deps_list == None: |
| print("Error: golden dependency list not configured for %s package" % |
| (pkg)) |
| validated = False |
| elif len(deps_graph) != len(golden_deps_list): |
| print("Error: expected %d dependencies for %s package, not %d" % |
| (len(golden_deps_list), pkg, len(deps_graph))) |
| validated = False |
| |
| # Verify dependencies, by comparing them to GOLDEN_DEP_GRAPHS |
| for p in deps_graph: |
| golden_pkg_info = None |
| try: |
| golden_pkg_info = GOLDEN_DEP_GRAPHS[p] |
| except KeyError: |
| print("Error: golden dependency graph not configured for %s package" % |
| (p)) |
| validated = False |
| continue |
| |
| pkg_info = deps_graph[p] |
| for key in golden_pkg_info: |
| golden_value = golden_pkg_info[key] |
| value = pkg_info[key] |
| if not value == golden_value: |
| print("Error: while verifying '%s' value for %s package," |
| " expected:\n%r\nBut instead found:\n%r" |
| % (key, p, golden_value, value)) |
| validated = False |
| |
| if not validated: |
| print("Error: dependency graph for %s is not as expected. Instead:\n%r" % |
| (pkg, deps_graph)) |
| |
| return validated |
| |
| def _GenDepsGraphVerifier(pkg): |
| """Generate a graph verification function for the given package.""" |
| return lambda deps_graph: _VerifyDepsGraph(deps_graph, pkg) |
| |
| #################### |
| ### UpgraderTest ### |
| #################### |
| |
| class UpgraderTest(mox.MoxTestBase): |
| """Test the Upgrader class from cros_portage_upgrade.""" |
| |
| def setUp(self): |
| mox.MoxTestBase.setUp(self) |
| |
| TODO(mtennant): Upgrader does not have a sense of _board anymore, |
| only for each call to runBoard. Test setup must change. |
| def _MockUpgrader(self, board='test_board', package='test_package', |
| verbose=False, rdeps=None, srcroot=None, |
| stable_repo=None, upstream_repo=None, csv_file=None): |
| """Set up a mocked Upgrader object with the given args.""" |
| upgrader = self.mox.CreateMock(cpu.Upgrader) |
| |
| upgrader._args = [package] |
| upgrader._curr_board = board |
| upgrader._verbose = verbose |
| upgrader._rdeps = rdeps |
| upgrader._stable_repo = stable_repo |
| upgrader._upstream_repo = upstream_repo |
| upgrader._csv_file = csv_file |
| |
| return upgrader |
| |
| def _MockUpgraderOptions(self, board='test_board', package='test_package', |
| srcroot=None, upstream=None, |
| verbose=False, rdeps=None): |
| """Mock optparse.Values for use with Upgrader, and create args list. |
| |
| Returns tuple with (options, args).""" |
| |
| if not srcroot: |
| srcroot = '%s/trunk/src' % os.environ['HOME'] |
| |
| options = self.mox.CreateMock(optparse.Values) |
| |
| # Make sure all attributes are initialized. |
| for opt in cpu.Upgrader.OPT_SLOTS: |
| setattr(options, opt, None) |
| |
| # Set the attributes we care about for testing. |
| options.board = board |
| options.verbose = verbose |
| options.rdeps = rdeps |
| options.srcroot = srcroot |
| options.upstream = upstream |
| args = [package] |
| |
| return (options, args) |
| |
| def _SetUpEmerge(self): |
| """Prepare the temporary ebuild playground and emerge variables. |
| |
| This leverages test code in existing Portage modules to create an ebuild |
| hierarchy. This can be a little slow.""" |
| |
| # TODO(mtennant): Support multiple overlays? This essentially |
| # creates just a default overlay. |
| self._playground = respgnd.ResolverPlayground(ebuilds=EBUILDS, |
| installed=INSTALLED) |
| |
| # Set all envvars needed by emerge, since --board is being skipped. |
| eroot = self._playground.eroot |
| if eroot[-1:] == '/': |
| eroot = eroot[:-1] |
| os.environ["PORTAGE_CONFIGROOT"] = eroot |
| os.environ["PORTAGE_SYSROOT"] = eroot |
| os.environ["SYSROOT"] = eroot |
| os.environ.setdefault("CHROMEOS_ROOT", "%s/trunk" % os.environ["HOME"]) |
| os.environ["PORTDIR"] = "%s/usr/portage" % eroot |
| |
| def _GetPortageDBAPI(self): |
| portroot = self._playground.settings["ROOT"] |
| porttree = self._playground.trees[portroot]['porttree'] |
| return porttree.dbapi |
| |
| def _TearDownEmerge(self): |
| """Delete the temporary ebuild playground files.""" |
| try: |
| self._playground.cleanup() |
| except AttributeError: |
| pass |
| |
| def _GetParallelEmergeArgv(self, mocked_upgrader): |
| return cpu.Upgrader._GenParallelEmergeArgv(mocked_upgrader) |
| |
| # |
| # _GetCurrentVersions testing |
| # |
| |
| def _TestGetCurrentVersions(self, pkg): |
| """Test the behavior of the Upgrader._GetCurrentVersions method. |
| |
| This basically confirms that it uses the parallel_emerge module to |
| assemble the expected dependency graph.""" |
| mocked_upgrader = self._MockUpgrader(board=None, package=pkg, verbose=False) |
| pm_argv = self._GetParallelEmergeArgv(mocked_upgrader) |
| self._SetUpEmerge() |
| |
| # Add test-specific mocks/stubs. |
| self.mox.StubOutWithMock(cpu.Upgrader, '_GetPreOrderDepGraph') |
| |
| # Replay script |
| verifier = _GenDepsGraphVerifier(pkg) |
| mocked_upgrader._GenParallelEmergeArgv().AndReturn(pm_argv) |
| mocked_upgrader._SetPortTree(mox.IsA(portcfg.config), mox.IsA(dict)) |
| cpu.Upgrader._GetPreOrderDepGraph(mox.Func(verifier)).AndReturn(['ignore']) |
| self.mox.ReplayAll() |
| |
| # Verify |
| graph = cpu.Upgrader._GetCurrentVersions(mocked_upgrader) |
| self.mox.VerifyAll() |
| |
| self._TearDownEmerge() |
| |
| def testGetCurrentVersionsDevLibsA(self): |
| return self._TestGetCurrentVersions('dev-libs/A') |
| |
| def testGetCurrentVersionsDevLibsB(self): |
| return self._TestGetCurrentVersions('dev-libs/B') |
| |
| def testGetCurrentVersionsCrosbaseLibcros(self): |
| return self._TestGetCurrentVersions('chromeos-base/libcros') |
| |
| # |
| # _GetPreOrderDepGraph testing |
| # |
| |
| def _TestGetPreOrderDepGraph(self, pkg): |
| """Test the behavior of the Upgrader._GetPreOrderDepGraph method.""" |
| |
| mocked_upgrader = self._MockUpgrader(board=None, package=pkg, verbose=False) |
| pm_argv = self._GetParallelEmergeArgv(mocked_upgrader) |
| self._SetUpEmerge() |
| |
| # Replay script |
| self.mox.ReplayAll() |
| |
| # Verify |
| deps = parallel_emerge.DepGraphGenerator() |
| deps.Initialize(pm_argv) |
| deps_tree, deps_info = deps.GenDependencyTree() |
| deps_graph = deps.GenDependencyGraph(deps_tree, deps_info) |
| |
| deps_list = cpu.Upgrader._GetPreOrderDepGraph(deps_graph) |
| golden_deps_list = _GetGoldenDepsList(pkg) |
| self.assertEquals(deps_list, golden_deps_list) |
| self.mox.VerifyAll() |
| |
| self._TearDownEmerge() |
| |
| def testGetPreOrderDepGraphDevLibsA(self): |
| return self._TestGetPreOrderDepGraph('dev-libs/A') |
| |
| def testGetPreOrderDepGraphDevLibsC(self): |
| return self._TestGetPreOrderDepGraph('dev-libs/C') |
| |
| def testGetPreOrderDepGraphVirtualLibusb(self): |
| return self._TestGetPreOrderDepGraph('virtual/libusb') |
| |
| def testGetPreOrderDepGraphCrosbaseLibcros(self): |
| return self._TestGetPreOrderDepGraph('chromeos-base/libcros') |
| |
| # |
| # _SplitEBuildPath testing |
| # |
| |
| def _TestSplitEBuildPath(self, ebuild_path, golden_result): |
| """Test the behavior of the Upgrader._SplitEBuildPath method.""" |
| mocked_upgrader = self._MockUpgrader() |
| |
| # Replay script |
| self.mox.ReplayAll() |
| |
| # Verify |
| result = cpu.Upgrader._SplitEBuildPath(mocked_upgrader, |
| ebuild_path) |
| self.assertEquals(result, golden_result) |
| self.mox.VerifyAll() |
| |
| def testSplitEBuildPath1(self): |
| return self._TestSplitEBuildPath('/foo/bar/portage/dev-libs/A/A-2.ebuild', |
| ('portage', 'dev-libs', 'A', 'A-2')) |
| |
| def testSplitEBuildPath2(self): |
| return self._TestSplitEBuildPath('/foo/ooo/ccc/ppp/ppp-1.2.3-r123.ebuild', |
| ('ooo', 'ccc', 'ppp', 'ppp-1.2.3-r123')) |
| |
| |
| # |
| # _GetInfoListWithOverlays testing |
| # |
| |
| def _TestGetInfoListWithOverlays(self, pkg): |
| """Test the behavior of the Upgrader._GetInfoListWithOverlays method.""" |
| |
| self._SetUpEmerge() |
| |
| # Add test-specific mocks/stubs |
| |
| # Replay script, if any |
| self.mox.ReplayAll() |
| |
| # Verify |
| cpvlist = _GetGoldenDepsList(pkg) |
| (options, args) = self._MockUpgraderOptions(board=None, |
| package=pkg, |
| verbose=False) |
| upgrader = cpu.Upgrader(options, args) |
| upgrader._SetPortTree(self._playground.settings, self._playground.trees) |
| |
| cpvinfolist = upgrader._GetInfoListWithOverlays(cpvlist) |
| self.mox.VerifyAll() |
| |
| # Verify the overlay that was found for each cpv. Always "portage" for now, |
| # because that is what is created by the temporary ebuild creator. |
| # TODO(mtennant): Support multiple overlays somehow. |
| for cpvinfo in cpvinfolist: |
| self.assertEquals('portage', cpvinfo['overlay']) |
| |
| self._TearDownEmerge() |
| |
| def testGetInfoListWithOverlaysDevLibsA(self): |
| return self._TestGetInfoListWithOverlays('dev-libs/A') |
| |
| def testGetInfoListWithOverlaysCrosbaseLibcros(self): |
| return self._TestGetInfoListWithOverlays('chromeos-base/libcros') |
| |
| # |
| # _UpgradePackages testing |
| # |
| # TODO(mtennant): Implement this. It will require some cleverness. |
| |
| # |
| # _ToCSV testing |
| # |
| # TODO(mtennant): Implement tests for CSV output functionality. |
| |
| # |
| # _ToHTML testing |
| # |
| # TODO(mtennant): Implement tests for HTML output functionality. |
| |
| ################ |
| ### MainTest ### |
| ################ |
| |
| class MainTest(mox.MoxTestBase): |
| """Test argument handling at the main method level.""" |
| |
| def setUp(self): |
| """Setup for all tests in this class.""" |
| mox.MoxTestBase.setUp(self) |
| |
| def _StartCapturingOutput(self): |
| """Begin capturing stdout and stderr.""" |
| self._stdout = sys.stdout |
| self._stderr = sys.stderr |
| sys.stdout = self._stdout_cap = cStringIO.StringIO() |
| sys.stderr = self._stderr_cap = cStringIO.StringIO() |
| |
| def _RetrieveCapturedOutput(self): |
| """Return captured output so far as (stdout, stderr) tuple.""" |
| try: |
| return (self._stdout_cap.getvalue(), self._stderr_cap.getvalue()) |
| except AttributeError: |
| # This will happen if output capturing isn't on. |
| return None |
| |
| def _StopCapturingOutput(self): |
| """Stop capturing stdout and stderr.""" |
| try: |
| sys.stdout = self._stdout |
| sys.stderr = self._stderr |
| except AttributeError: |
| # This will happen if output capturing wasn't on. |
| pass |
| |
| def _PrepareArgv(self, *args): |
| """Prepare command line for calling cros_portage_upgrade.main""" |
| sys.argv = [ re.sub("_unittest", "", sys.argv[0]) ] |
| sys.argv.extend(args) |
| |
| def testHelp(self): |
| """Test that --help is functioning""" |
| self._PrepareArgv("--help") |
| |
| # Capture stdout/stderr so it can be verified later |
| self._StartCapturingOutput() |
| |
| # Running with --help should exit with code==0 |
| try: |
| cpu.main() |
| except exceptions.SystemExit, e: |
| self.assertEquals(e.args[0], 0) |
| |
| # Verify that a message beginning with "Usage: " was printed |
| (stdout, stderr) = self._RetrieveCapturedOutput() |
| self._StopCapturingOutput() |
| self.assertTrue(stdout.startswith("Usage: ")) |
| |
| def testMissingBoard(self): |
| """Test that running without --board exits with an error.""" |
| self._PrepareArgv("") |
| |
| # Capture stdout/stderr so it can be verified later |
| self._StartCapturingOutput() |
| |
| # Running without --board should exit with code!=0 |
| try: |
| cpu.main() |
| except exceptions.SystemExit, e: |
| self.assertNotEquals(e.args[0], 0) |
| |
| # Verify that a message containing "ERROR: " was printed |
| (stdout, stderr) = self._RetrieveCapturedOutput() |
| self._StopCapturingOutput() |
| self.assertTrue("ERROR:" in stderr) |
| |
| def testMissingPackage(self): |
| """Test that running without a package argument exits with an error.""" |
| self._PrepareArgv("--board=any-board") |
| |
| # Capture stdout/stderr so it can be verified later |
| self._StartCapturingOutput() |
| |
| # Running without a package should exit with code!=0 |
| try: |
| cpu.main() |
| except exceptions.SystemExit, e: |
| self.assertNotEquals(e.args[0], 0) |
| |
| # Verify that a message containing "ERROR: " was printed |
| (stdout, stderr) = self._RetrieveCapturedOutput() |
| self._StopCapturingOutput() |
| self.assertTrue("ERROR:" in stderr) |
| |
| def testUpgraderRun(self): |
| """Verify that running main method launches Upgrader.RunBoard""" |
| self.mox.StubOutWithMock(cpu, '_BoardIsSetUp') |
| self.mox.StubOutWithMock(cpu.Upgrader, '_FindBoardArch') |
| self.mox.StubOutWithMock(cpu.Upgrader, 'RunBoard') |
| cpu._BoardIsSetUp('any-board').AndReturn(True) |
| cpu.Upgrader._FindBoardArch(mox.IgnoreArg()).AndReturn('x86') |
| cpu.Upgrader.RunBoard() |
| self.mox.ReplayAll() |
| |
| self._PrepareArgv("--board=any-board", "any-package") |
| cpu.main() |
| self.mox.VerifyAll() |
| |
| if __name__ == '__main__': |
| unittest.main() |