Mike Frysinger | f1ba7ad | 2022-09-12 05:42:57 -0400 | [diff] [blame] | 1 | # Copyright 2014 The ChromiumOS Authors |
Nam T. Nguyen | f381636 | 2014-06-13 09:26:27 -0700 | [diff] [blame] | 2 | # 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. Nguyen | f381636 | 2014-06-13 09:26:27 -0700 | [diff] [blame] | 7 | import os |
Nam T. Nguyen | f381636 | 2014-06-13 09:26:27 -0700 | [diff] [blame] | 8 | import unittest |
| 9 | |
Nam T. Nguyen | f381636 | 2014-06-13 09:26:27 -0700 | [diff] [blame] | 10 | from chromite.lib import commandline |
Mike Frysinger | 807d828 | 2022-04-28 22:45:17 -0400 | [diff] [blame] | 11 | from chromite.lib import constants |
Mike Nichols | a8e8f24 | 2019-09-09 14:10:29 -0600 | [diff] [blame] | 12 | from chromite.lib import image_lib |
Nam T. Nguyen | c8ef774 | 2015-06-01 13:34:35 -0700 | [diff] [blame] | 13 | from chromite.lib import image_test_lib |
Nam T. Nguyen | f381636 | 2014-06-13 09:26:27 -0700 | [diff] [blame] | 14 | from chromite.lib import osutils |
Gilad Arnold | 1c8eda5 | 2015-05-04 22:32:38 -0700 | [diff] [blame] | 15 | from chromite.lib import path_util |
Nam T. Nguyen | f381636 | 2014-06-13 09:26:27 -0700 | [diff] [blame] | 16 | |
| 17 | |
| 18 | def ParseArgs(args): |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 19 | """Return parsed commandline arguments.""" |
Nam T. Nguyen | f381636 | 2014-06-13 09:26:27 -0700 | [diff] [blame] | 20 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 21 | 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", |
| 31 | help="Image directory (or file) with mount_image.sh and " |
| 32 | "umount_image.sh", |
| 33 | ) |
Mike Frysinger | 6dd14f4 | 2017-10-18 18:33:35 -0400 | [diff] [blame] | 34 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 35 | parser.add_argument( |
| 36 | "-l", |
| 37 | "--list", |
| 38 | default=False, |
| 39 | action="store_true", |
| 40 | help="List all the available tests", |
| 41 | ) |
| 42 | parser.add_argument( |
| 43 | "tests", |
| 44 | nargs="*", |
| 45 | metavar="test", |
| 46 | help="Specific tests to run (default runs all)", |
| 47 | ) |
Mike Frysinger | 6dd14f4 | 2017-10-18 18:33:35 -0400 | [diff] [blame] | 48 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 49 | opts = parser.parse_args(args) |
| 50 | opts.Freeze() |
| 51 | return opts |
Nam T. Nguyen | f381636 | 2014-06-13 09:26:27 -0700 | [diff] [blame] | 52 | |
| 53 | |
| 54 | def FindImage(image_path): |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 55 | """Return the path to the image file. |
Nam T. Nguyen | f381636 | 2014-06-13 09:26:27 -0700 | [diff] [blame] | 56 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 57 | Args: |
| 58 | image_path: A path to the image file, or a directory containing the base |
| 59 | image. |
Nam T. Nguyen | f381636 | 2014-06-13 09:26:27 -0700 | [diff] [blame] | 60 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 61 | Returns: |
| 62 | ImageFileAndMountScripts containing absolute paths to the image, |
| 63 | the mount and umount invocation commands |
| 64 | """ |
Nam T. Nguyen | f381636 | 2014-06-13 09:26:27 -0700 | [diff] [blame] | 65 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 66 | if os.path.isdir(image_path): |
| 67 | # Assume base image. |
| 68 | image_file = os.path.join( |
| 69 | image_path, constants.BASE_IMAGE_NAME + ".bin" |
| 70 | ) |
| 71 | if not os.path.exists(image_file): |
| 72 | raise ValueError("Cannot find base image %s" % image_file) |
| 73 | elif os.path.isfile(image_path): |
| 74 | image_file = image_path |
| 75 | else: |
| 76 | raise ValueError("%s is neither a directory nor a file" % image_path) |
Nam T. Nguyen | f381636 | 2014-06-13 09:26:27 -0700 | [diff] [blame] | 77 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 78 | return image_file |
Nam T. Nguyen | f381636 | 2014-06-13 09:26:27 -0700 | [diff] [blame] | 79 | |
| 80 | |
| 81 | def main(args): |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 82 | opts = ParseArgs(args) |
Nam T. Nguyen | f381636 | 2014-06-13 09:26:27 -0700 | [diff] [blame] | 83 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 84 | # Build up test suites. |
| 85 | loader = unittest.TestLoader() |
| 86 | loader.suiteClass = image_test_lib.ImageTestSuite |
| 87 | # We use a different prefix here so that unittest DO NOT pick up the |
| 88 | # image tests automatically because they depend on a proper environment. |
| 89 | loader.testMethodPrefix = "Test" |
| 90 | tests_namespace = "chromite.cros.test.image_test" |
| 91 | if opts.tests: |
| 92 | tests = ["%s.%s" % (tests_namespace, x) for x in opts.tests] |
| 93 | else: |
| 94 | tests = (tests_namespace,) |
| 95 | all_tests = loader.loadTestsFromNames(tests) |
Mike Frysinger | 6dd14f4 | 2017-10-18 18:33:35 -0400 | [diff] [blame] | 96 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 97 | # If they just want to see the lists of tests, show them now. |
| 98 | if opts.list: |
Mike Frysinger | 6dd14f4 | 2017-10-18 18:33:35 -0400 | [diff] [blame] | 99 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 100 | def _WalkSuite(suite): |
| 101 | for test in suite: |
| 102 | if isinstance(test, unittest.BaseTestSuite): |
| 103 | for result in _WalkSuite(test): |
| 104 | yield result |
| 105 | else: |
| 106 | yield ( |
| 107 | test.id()[len(tests_namespace) + 1 :], |
| 108 | test.shortDescription() or "", |
| 109 | ) |
Nam T. Nguyen | f381636 | 2014-06-13 09:26:27 -0700 | [diff] [blame] | 110 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 111 | test_list = list(_WalkSuite(all_tests)) |
| 112 | maxlen = max(len(x[0]) for x in test_list) |
| 113 | for name, desc in test_list: |
| 114 | print("%-*s %s" % (maxlen, name, desc)) |
| 115 | return |
Nam T. Nguyen | f381636 | 2014-06-13 09:26:27 -0700 | [diff] [blame] | 116 | |
Alex Klein | 1699fab | 2022-09-08 08:46:06 -0600 | [diff] [blame] | 117 | # Run them in the image directory. |
| 118 | runner = image_test_lib.ImageTestRunner() |
| 119 | runner.SetBoard(opts.board) |
| 120 | runner.SetResultDir(opts.test_results_root) |
| 121 | image_file = FindImage(opts.image) |
| 122 | tmp_in_chroot = path_util.FromChrootPath("/tmp") |
| 123 | with osutils.TempDir(base_dir=tmp_in_chroot) as temp_dir: |
| 124 | with image_lib.LoopbackPartitions(image_file, temp_dir) as image: |
| 125 | # Due to the lack of mount context, we mount the partitions |
| 126 | # but do not reference directly. This will be removed with the |
| 127 | # submission of http://crrev/c/1795578 |
| 128 | _ = image.Mount((constants.PART_ROOT_A,))[0] |
| 129 | _ = image.Mount((constants.PART_STATE,))[0] |
| 130 | with osutils.ChdirContext(temp_dir): |
| 131 | result = runner.run(all_tests) |
| 132 | |
| 133 | if result and not result.wasSuccessful(): |
| 134 | return 1 |
| 135 | return 0 |