James Robinson | 646469d | 2014-10-03 15:33:28 -0700 | [diff] [blame] | 1 | #!/usr/bin/env python |
| 2 | # Copyright 2014 The Chromium Authors. All rights reserved. |
| 3 | # Use of this source code is governed by a BSD-style license that can be |
| 4 | # found in the LICENSE file. |
| 5 | |
| 6 | """A "smart" test runner for gtest unit tests (that caches successes).""" |
| 7 | |
Benjamin Lerman | f4583a8 | 2014-11-26 10:54:39 +0100 | [diff] [blame] | 8 | import argparse |
James Robinson | 646469d | 2014-10-03 15:33:28 -0700 | [diff] [blame] | 9 | import logging |
| 10 | import os |
| 11 | import subprocess |
| 12 | import sys |
| 13 | |
Viet-Trung Luu | bd9af43 | 2015-04-16 10:47:55 -0700 | [diff] [blame] | 14 | from mopy import gtest |
Benjamin Lerman | b96671e | 2015-01-29 11:05:54 +0100 | [diff] [blame] | 15 | from mopy.config import Config |
| 16 | from mopy.gn import ConfigForGNArgs, ParseGNConfig |
Viet-Trung Luu | daab6d7 | 2015-04-08 13:51:28 -0700 | [diff] [blame] | 17 | from mopy.log import InitLogging |
Benjamin Lerman | f4583a8 | 2014-11-26 10:54:39 +0100 | [diff] [blame] | 18 | from mopy.paths import Paths |
| 19 | from mopy.transitive_hash import file_hash, transitive_hash |
James Robinson | 646469d | 2014-10-03 15:33:28 -0700 | [diff] [blame] | 20 | |
Viet-Trung Luu | daab6d7 | 2015-04-08 13:51:28 -0700 | [diff] [blame] | 21 | |
| 22 | _logger = logging.getLogger() |
| 23 | _paths = Paths() |
| 24 | |
Benjamin Lerman | f4583a8 | 2014-11-26 10:54:39 +0100 | [diff] [blame] | 25 | |
| 26 | def main(): |
Benjamin Lerman | f4583a8 | 2014-11-26 10:54:39 +0100 | [diff] [blame] | 27 | parser = argparse.ArgumentParser( |
| 28 | description="A 'smart' test runner for gtest unit tests (that caches " |
| 29 | "successes).") |
James Robinson | 646469d | 2014-10-03 15:33:28 -0700 | [diff] [blame] | 30 | |
Viet-Trung Luu | bd9af43 | 2015-04-16 10:47:55 -0700 | [diff] [blame] | 31 | parser.add_argument("--verbose", help="be verbose (multiple times for more)", |
Viet-Trung Luu | daab6d7 | 2015-04-08 13:51:28 -0700 | [diff] [blame] | 32 | default=0, dest="verbose_count", action="count") |
Viet-Trung Luu | bd9af43 | 2015-04-16 10:47:55 -0700 | [diff] [blame] | 33 | parser.add_argument("--successes-cache", |
| 34 | help="the file caching test results (empty to not cache)", |
| 35 | default="mojob_test_successes") |
| 36 | parser.add_argument("test_list_file", |
| 37 | help="the file containing the tests to run", type=file) |
| 38 | parser.add_argument("root_dir", help="the build directory") |
Benjamin Lerman | f4583a8 | 2014-11-26 10:54:39 +0100 | [diff] [blame] | 39 | args = parser.parse_args() |
| 40 | |
Viet-Trung Luu | daab6d7 | 2015-04-08 13:51:28 -0700 | [diff] [blame] | 41 | InitLogging(args.verbose_count) |
Benjamin Lerman | b96671e | 2015-01-29 11:05:54 +0100 | [diff] [blame] | 42 | config = ConfigForGNArgs(ParseGNConfig(args.root_dir)) |
| 43 | |
Viet-Trung Luu | bd9af43 | 2015-04-16 10:47:55 -0700 | [diff] [blame] | 44 | _logger.debug("Test list file: %s", args.test_list_file) |
| 45 | execution_globals = {"config": config} |
| 46 | exec args.test_list_file in execution_globals |
| 47 | test_list = execution_globals["tests"] |
| 48 | _logger.debug("Test list: %s" % test_list) |
Benjamin Lerman | 75b3034 | 2015-02-04 16:54:56 +0100 | [diff] [blame] | 49 | |
Benjamin Lerman | f4583a8 | 2014-11-26 10:54:39 +0100 | [diff] [blame] | 50 | print "Running tests in directory: %s" % args.root_dir |
| 51 | os.chdir(args.root_dir) |
James Robinson | 646469d | 2014-10-03 15:33:28 -0700 | [diff] [blame] | 52 | |
Viet-Trung Luu | bd9af43 | 2015-04-16 10:47:55 -0700 | [diff] [blame] | 53 | if args.successes_cache: |
| 54 | print "Successes cache file: %s" % args.successes_cache |
James Robinson | 646469d | 2014-10-03 15:33:28 -0700 | [diff] [blame] | 55 | else: |
James Robinson | 646469d | 2014-10-03 15:33:28 -0700 | [diff] [blame] | 56 | print "No successes cache file (will run all tests unconditionally)" |
| 57 | |
Viet-Trung Luu | bd9af43 | 2015-04-16 10:47:55 -0700 | [diff] [blame] | 58 | if args.successes_cache: |
James Robinson | 646469d | 2014-10-03 15:33:28 -0700 | [diff] [blame] | 59 | # This file simply contains a list of transitive hashes of tests that |
| 60 | # succeeded. |
| 61 | try: |
Viet-Trung Luu | daab6d7 | 2015-04-08 13:51:28 -0700 | [diff] [blame] | 62 | _logger.debug("Trying to read successes cache file: %s", |
Viet-Trung Luu | bd9af43 | 2015-04-16 10:47:55 -0700 | [diff] [blame] | 63 | args.successes_cache) |
| 64 | with open(args.successes_cache, 'rb') as f: |
James Robinson | 646469d | 2014-10-03 15:33:28 -0700 | [diff] [blame] | 65 | successes = set([x.strip() for x in f.readlines()]) |
Viet-Trung Luu | daab6d7 | 2015-04-08 13:51:28 -0700 | [diff] [blame] | 66 | _logger.debug("Successes: %s", successes) |
Viet-Trung Luu | ec5ef2f | 2014-10-22 15:53:25 -0700 | [diff] [blame] | 67 | except IOError: |
James Robinson | 646469d | 2014-10-03 15:33:28 -0700 | [diff] [blame] | 68 | # Just assume that it didn't exist, or whatever. |
Benjamin Lerman | f4583a8 | 2014-11-26 10:54:39 +0100 | [diff] [blame] | 69 | print ("Failed to read successes cache file %s (will create)" % |
Viet-Trung Luu | bd9af43 | 2015-04-16 10:47:55 -0700 | [diff] [blame] | 70 | args.successes_cache) |
James Robinson | 646469d | 2014-10-03 15:33:28 -0700 | [diff] [blame] | 71 | successes = set() |
| 72 | |
Viet-Trung Luu | bd9af43 | 2015-04-16 10:47:55 -0700 | [diff] [blame] | 73 | gtest.set_color() |
James Robinson | 646469d | 2014-10-03 15:33:28 -0700 | [diff] [blame] | 74 | |
Viet-Trung Luu | bd9af43 | 2015-04-16 10:47:55 -0700 | [diff] [blame] | 75 | exit_code = 0 |
| 76 | successes_cache_file = (open(args.successes_cache, "ab") |
| 77 | if args.successes_cache else None) |
| 78 | for test_dict in test_list: |
| 79 | test = test_dict["test"] |
| 80 | test_name = test_dict.get("name", test) |
| 81 | # TODO(vtl): Add type. |
| 82 | cacheable = test_dict.get("cacheable", True) |
Benjamin Lerman | 5291598 | 2014-12-04 09:33:02 +0100 | [diff] [blame] | 83 | if not cacheable: |
Viet-Trung Luu | bd9af43 | 2015-04-16 10:47:55 -0700 | [diff] [blame] | 84 | _logger.debug("%s is marked as non-cacheable" % test_name) |
James Robinson | 646469d | 2014-10-03 15:33:28 -0700 | [diff] [blame] | 85 | |
Viet-Trung Luu | bd9af43 | 2015-04-16 10:47:55 -0700 | [diff] [blame] | 86 | gtest_file = test |
Benjamin Lerman | b96671e | 2015-01-29 11:05:54 +0100 | [diff] [blame] | 87 | if config.target_os == Config.OS_ANDROID: |
Viet-Trung Luu | bd9af43 | 2015-04-16 10:47:55 -0700 | [diff] [blame] | 88 | gtest_file = test + "_apk/" + test + "-debug.apk" |
John Abd-El-Malek | 0f0b4f0 | 2014-11-11 12:42:38 -0800 | [diff] [blame] | 89 | |
James Robinson | 646469d | 2014-10-03 15:33:28 -0700 | [diff] [blame] | 90 | if successes_cache_file and cacheable: |
Viet-Trung Luu | bd9af43 | 2015-04-16 10:47:55 -0700 | [diff] [blame] | 91 | _logger.debug("Getting transitive hash for %s ... " % test_name) |
James Robinson | 646469d | 2014-10-03 15:33:28 -0700 | [diff] [blame] | 92 | try: |
Benjamin Lerman | b96671e | 2015-01-29 11:05:54 +0100 | [diff] [blame] | 93 | if config.target_os == Config.OS_ANDROID: |
Benjamin Lerman | f4583a8 | 2014-11-26 10:54:39 +0100 | [diff] [blame] | 94 | gtest_hash = file_hash(gtest_file) |
| 95 | else: |
| 96 | gtest_hash = transitive_hash(gtest_file) |
Viet-Trung Luu | ec5ef2f | 2014-10-22 15:53:25 -0700 | [diff] [blame] | 97 | except subprocess.CalledProcessError: |
Viet-Trung Luu | bd9af43 | 2015-04-16 10:47:55 -0700 | [diff] [blame] | 98 | print "Failed to get transitive hash for %s" % test_name |
| 99 | exit_code = 1 |
| 100 | continue |
Viet-Trung Luu | daab6d7 | 2015-04-08 13:51:28 -0700 | [diff] [blame] | 101 | _logger.debug(" Transitive hash: %s" % gtest_hash) |
James Robinson | 646469d | 2014-10-03 15:33:28 -0700 | [diff] [blame] | 102 | |
| 103 | if gtest_hash in successes: |
Viet-Trung Luu | bd9af43 | 2015-04-16 10:47:55 -0700 | [diff] [blame] | 104 | print "Skipping %s (previously succeeded)" % test_name |
James Robinson | 646469d | 2014-10-03 15:33:28 -0700 | [diff] [blame] | 105 | continue |
| 106 | |
Viet-Trung Luu | bd9af43 | 2015-04-16 10:47:55 -0700 | [diff] [blame] | 107 | _logger.info("Will start: %s" % test_name) |
| 108 | print "Running %s...." % test_name, |
James Robinson | 646469d | 2014-10-03 15:33:28 -0700 | [diff] [blame] | 109 | sys.stdout.flush() |
| 110 | try: |
Benjamin Lerman | b96671e | 2015-01-29 11:05:54 +0100 | [diff] [blame] | 111 | if config.target_os == Config.OS_ANDROID: |
Benjamin Lerman | f4583a8 | 2014-11-26 10:54:39 +0100 | [diff] [blame] | 112 | command = [ |
| 113 | "python", |
Viet-Trung Luu | daab6d7 | 2015-04-08 13:51:28 -0700 | [diff] [blame] | 114 | os.path.join(_paths.src_root, "build", "android", "test_runner.py"), |
Benjamin Lerman | f4583a8 | 2014-11-26 10:54:39 +0100 | [diff] [blame] | 115 | "gtest", |
| 116 | "--output-directory", |
| 117 | args.root_dir, |
| 118 | "-s", |
Viet-Trung Luu | bd9af43 | 2015-04-16 10:47:55 -0700 | [diff] [blame] | 119 | test, |
Benjamin Lerman | f4583a8 | 2014-11-26 10:54:39 +0100 | [diff] [blame] | 120 | ] |
| 121 | else: |
Viet-Trung Luu | bd9af43 | 2015-04-16 10:47:55 -0700 | [diff] [blame] | 122 | command = ["./" + test] |
Viet-Trung Luu | daab6d7 | 2015-04-08 13:51:28 -0700 | [diff] [blame] | 123 | _logger.debug("Command: %s" % command) |
Benjamin Lerman | f4583a8 | 2014-11-26 10:54:39 +0100 | [diff] [blame] | 124 | subprocess.check_output(command, stderr=subprocess.STDOUT) |
James Robinson | 646469d | 2014-10-03 15:33:28 -0700 | [diff] [blame] | 125 | print "Succeeded" |
| 126 | # Record success. |
Viet-Trung Luu | bd9af43 | 2015-04-16 10:47:55 -0700 | [diff] [blame] | 127 | if args.successes_cache and cacheable: |
James Robinson | 646469d | 2014-10-03 15:33:28 -0700 | [diff] [blame] | 128 | successes.add(gtest_hash) |
Viet-Trung Luu | daab6d7 | 2015-04-08 13:51:28 -0700 | [diff] [blame] | 129 | successes_cache_file.write(gtest_hash + "\n") |
James Robinson | 646469d | 2014-10-03 15:33:28 -0700 | [diff] [blame] | 130 | successes_cache_file.flush() |
| 131 | except subprocess.CalledProcessError as e: |
| 132 | print "Failed with exit code %d and output:" % e.returncode |
Viet-Trung Luu | daab6d7 | 2015-04-08 13:51:28 -0700 | [diff] [blame] | 133 | print 72 * "-" |
James Robinson | 646469d | 2014-10-03 15:33:28 -0700 | [diff] [blame] | 134 | print e.output |
Viet-Trung Luu | daab6d7 | 2015-04-08 13:51:28 -0700 | [diff] [blame] | 135 | print 72 * "-" |
Viet-Trung Luu | bd9af43 | 2015-04-16 10:47:55 -0700 | [diff] [blame] | 136 | exit_code = 1 |
| 137 | continue |
James Robinson | 646469d | 2014-10-03 15:33:28 -0700 | [diff] [blame] | 138 | except OSError as e: |
| 139 | print " Failed to start test" |
Viet-Trung Luu | bd9af43 | 2015-04-16 10:47:55 -0700 | [diff] [blame] | 140 | exit_code = 1 |
| 141 | continue |
| 142 | _logger.info("Completed: %s" % test_name) |
| 143 | if exit_code == 0: |
| 144 | print "All tests succeeded" |
James Robinson | 646469d | 2014-10-03 15:33:28 -0700 | [diff] [blame] | 145 | if successes_cache_file: |
| 146 | successes_cache_file.close() |
| 147 | |
Viet-Trung Luu | bd9af43 | 2015-04-16 10:47:55 -0700 | [diff] [blame] | 148 | return exit_code |
James Robinson | 646469d | 2014-10-03 15:33:28 -0700 | [diff] [blame] | 149 | |
Viet-Trung Luu | daab6d7 | 2015-04-08 13:51:28 -0700 | [diff] [blame] | 150 | |
| 151 | if __name__ == "__main__": |
Benjamin Lerman | f4583a8 | 2014-11-26 10:54:39 +0100 | [diff] [blame] | 152 | sys.exit(main()) |