blob: c786ededc1f53b51d81f7a6296cee075e5136f84 [file] [log] [blame]
Mike Frysingerf1ba7ad2022-09-12 05:42:57 -04001# Copyright 2014 The ChromiumOS Authors
Nam T. Nguyenf3816362014-06-13 09:26:27 -07002# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Script to mount a built image and run tests on it."""
6
Nam T. Nguyenf3816362014-06-13 09:26:27 -07007import os
Nam T. Nguyenf3816362014-06-13 09:26:27 -07008import unittest
9
Nam T. Nguyenf3816362014-06-13 09:26:27 -070010from chromite.lib import commandline
Mike Frysinger807d8282022-04-28 22:45:17 -040011from chromite.lib import constants
Mike Nicholsa8e8f242019-09-09 14:10:29 -060012from chromite.lib import image_lib
Nam T. Nguyenc8ef7742015-06-01 13:34:35 -070013from chromite.lib import image_test_lib
Nam T. Nguyenf3816362014-06-13 09:26:27 -070014from chromite.lib import osutils
Gilad Arnold1c8eda52015-05-04 22:32:38 -070015from chromite.lib import path_util
Nam T. Nguyenf3816362014-06-13 09:26:27 -070016
17
18def ParseArgs(args):
Alex Klein1699fab2022-09-08 08:46:06 -060019 """Return parsed commandline arguments."""
Nam T. Nguyenf3816362014-06-13 09:26:27 -070020
Alex Klein1699fab2022-09-08 08:46:06 -060021 parser = commandline.ArgumentParser(description=__doc__)
22 parser.add_argument(
23 "--test_results_root",
24 type="path",
25 help="Directory to store test results",
26 )
27 parser.add_argument("--board", type=str, help="Board (wolf, beaglebone...)")
28 parser.add_argument(
29 "image",
30 type="path",
Mike Frysinger2a0deba2022-12-30 00:03:38 -050031 help="Image directory or file to test",
Alex Klein1699fab2022-09-08 08:46:06 -060032 )
Mike Frysinger6dd14f42017-10-18 18:33:35 -040033
Alex Klein1699fab2022-09-08 08:46:06 -060034 parser.add_argument(
35 "-l",
36 "--list",
37 default=False,
38 action="store_true",
39 help="List all the available tests",
40 )
41 parser.add_argument(
42 "tests",
43 nargs="*",
44 metavar="test",
45 help="Specific tests to run (default runs all)",
46 )
Mike Frysinger6dd14f42017-10-18 18:33:35 -040047
Alex Klein1699fab2022-09-08 08:46:06 -060048 opts = parser.parse_args(args)
49 opts.Freeze()
50 return opts
Nam T. Nguyenf3816362014-06-13 09:26:27 -070051
52
53def FindImage(image_path):
Alex Klein1699fab2022-09-08 08:46:06 -060054 """Return the path to the image file.
Nam T. Nguyenf3816362014-06-13 09:26:27 -070055
Alex Klein1699fab2022-09-08 08:46:06 -060056 Args:
Trent Apted66736d82023-05-25 10:38:28 +100057 image_path: A path to the image file, or a directory containing the base
58 image.
Nam T. Nguyenf3816362014-06-13 09:26:27 -070059
Alex Klein1699fab2022-09-08 08:46:06 -060060 Returns:
Trent Apted66736d82023-05-25 10:38:28 +100061 ImageFileAndMountScripts containing absolute paths to the image,
Alex Klein1699fab2022-09-08 08:46:06 -060062 the mount and umount invocation commands
63 """
Nam T. Nguyenf3816362014-06-13 09:26:27 -070064
Alex Klein1699fab2022-09-08 08:46:06 -060065 if os.path.isdir(image_path):
66 # Assume base image.
67 image_file = os.path.join(
68 image_path, constants.BASE_IMAGE_NAME + ".bin"
69 )
70 if not os.path.exists(image_file):
71 raise ValueError("Cannot find base image %s" % image_file)
72 elif os.path.isfile(image_path):
73 image_file = image_path
74 else:
75 raise ValueError("%s is neither a directory nor a file" % image_path)
Nam T. Nguyenf3816362014-06-13 09:26:27 -070076
Alex Klein1699fab2022-09-08 08:46:06 -060077 return image_file
Nam T. Nguyenf3816362014-06-13 09:26:27 -070078
79
80def main(args):
Alex Klein1699fab2022-09-08 08:46:06 -060081 opts = ParseArgs(args)
Nam T. Nguyenf3816362014-06-13 09:26:27 -070082
Alex Klein1699fab2022-09-08 08:46:06 -060083 # Build up test suites.
84 loader = unittest.TestLoader()
85 loader.suiteClass = image_test_lib.ImageTestSuite
86 # We use a different prefix here so that unittest DO NOT pick up the
87 # image tests automatically because they depend on a proper environment.
88 loader.testMethodPrefix = "Test"
89 tests_namespace = "chromite.cros.test.image_test"
90 if opts.tests:
91 tests = ["%s.%s" % (tests_namespace, x) for x in opts.tests]
92 else:
93 tests = (tests_namespace,)
94 all_tests = loader.loadTestsFromNames(tests)
Mike Frysinger6dd14f42017-10-18 18:33:35 -040095
Alex Klein1699fab2022-09-08 08:46:06 -060096 # If they just want to see the lists of tests, show them now.
97 if opts.list:
Mike Frysinger6dd14f42017-10-18 18:33:35 -040098
Alex Klein1699fab2022-09-08 08:46:06 -060099 def _WalkSuite(suite):
100 for test in suite:
101 if isinstance(test, unittest.BaseTestSuite):
102 for result in _WalkSuite(test):
103 yield result
104 else:
105 yield (
106 test.id()[len(tests_namespace) + 1 :],
107 test.shortDescription() or "",
108 )
Nam T. Nguyenf3816362014-06-13 09:26:27 -0700109
Alex Klein1699fab2022-09-08 08:46:06 -0600110 test_list = list(_WalkSuite(all_tests))
111 maxlen = max(len(x[0]) for x in test_list)
112 for name, desc in test_list:
113 print("%-*s %s" % (maxlen, name, desc))
114 return
Nam T. Nguyenf3816362014-06-13 09:26:27 -0700115
Alex Klein1699fab2022-09-08 08:46:06 -0600116 # Run them in the image directory.
117 runner = image_test_lib.ImageTestRunner()
118 runner.SetBoard(opts.board)
119 runner.SetResultDir(opts.test_results_root)
120 image_file = FindImage(opts.image)
121 tmp_in_chroot = path_util.FromChrootPath("/tmp")
122 with osutils.TempDir(base_dir=tmp_in_chroot) as temp_dir:
123 with image_lib.LoopbackPartitions(image_file, temp_dir) as image:
124 # Due to the lack of mount context, we mount the partitions
125 # but do not reference directly. This will be removed with the
126 # submission of http://crrev/c/1795578
127 _ = image.Mount((constants.PART_ROOT_A,))[0]
128 _ = image.Mount((constants.PART_STATE,))[0]
129 with osutils.ChdirContext(temp_dir):
130 result = runner.run(all_tests)
131
132 if result and not result.wasSuccessful():
133 return 1
134 return 0