mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
153 lines
4.8 KiB
Python
Executable File
153 lines
4.8 KiB
Python
Executable File
#!/usr/bin/env python
|
|
# Copyright 2014 The Chromium Authors. All rights reserved.
|
|
# Use of this source code is governed by a BSD-style license that can be
|
|
# found in the LICENSE file.
|
|
|
|
"""A "smart" test runner for gtest unit tests (that caches successes)."""
|
|
|
|
import argparse
|
|
import logging
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
|
|
from mopy import gtest
|
|
from mopy.config import Config
|
|
from mopy.gn import ConfigForGNArgs, ParseGNConfig
|
|
from mopy.log import InitLogging
|
|
from mopy.paths import Paths
|
|
from mopy.transitive_hash import file_hash, transitive_hash
|
|
|
|
|
|
_logger = logging.getLogger()
|
|
_paths = Paths()
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(
|
|
description="A 'smart' test runner for gtest unit tests (that caches "
|
|
"successes).")
|
|
|
|
parser.add_argument("--verbose", help="be verbose (multiple times for more)",
|
|
default=0, dest="verbose_count", action="count")
|
|
parser.add_argument("--successes-cache",
|
|
help="the file caching test results (empty to not cache)",
|
|
default="mojob_test_successes")
|
|
parser.add_argument("test_list_file",
|
|
help="the file containing the tests to run", type=file)
|
|
parser.add_argument("root_dir", help="the build directory")
|
|
args = parser.parse_args()
|
|
|
|
InitLogging(args.verbose_count)
|
|
config = ConfigForGNArgs(ParseGNConfig(args.root_dir))
|
|
|
|
_logger.debug("Test list file: %s", args.test_list_file)
|
|
execution_globals = {"config": config}
|
|
exec args.test_list_file in execution_globals
|
|
test_list = execution_globals["tests"]
|
|
_logger.debug("Test list: %s" % test_list)
|
|
|
|
print "Running tests in directory: %s" % args.root_dir
|
|
os.chdir(args.root_dir)
|
|
|
|
if args.successes_cache:
|
|
print "Successes cache file: %s" % args.successes_cache
|
|
else:
|
|
print "No successes cache file (will run all tests unconditionally)"
|
|
|
|
if args.successes_cache:
|
|
# This file simply contains a list of transitive hashes of tests that
|
|
# succeeded.
|
|
try:
|
|
_logger.debug("Trying to read successes cache file: %s",
|
|
args.successes_cache)
|
|
with open(args.successes_cache, 'rb') as f:
|
|
successes = set([x.strip() for x in f.readlines()])
|
|
_logger.debug("Successes: %s", successes)
|
|
except IOError:
|
|
# Just assume that it didn't exist, or whatever.
|
|
print ("Failed to read successes cache file %s (will create)" %
|
|
args.successes_cache)
|
|
successes = set()
|
|
|
|
gtest.set_color()
|
|
|
|
exit_code = 0
|
|
successes_cache_file = (open(args.successes_cache, "ab")
|
|
if args.successes_cache else None)
|
|
for test_dict in test_list:
|
|
test = test_dict["test"]
|
|
test_name = test_dict.get("name", test)
|
|
# TODO(vtl): Add type.
|
|
cacheable = test_dict.get("cacheable", True)
|
|
if not cacheable:
|
|
_logger.debug("%s is marked as non-cacheable" % test_name)
|
|
|
|
gtest_file = test
|
|
if config.target_os == Config.OS_ANDROID:
|
|
gtest_file = test + "_apk/" + test + "-debug.apk"
|
|
|
|
if successes_cache_file and cacheable:
|
|
_logger.debug("Getting transitive hash for %s ... " % test_name)
|
|
try:
|
|
if config.target_os == Config.OS_ANDROID:
|
|
gtest_hash = file_hash(gtest_file)
|
|
else:
|
|
gtest_hash = transitive_hash(gtest_file)
|
|
except subprocess.CalledProcessError:
|
|
print "Failed to get transitive hash for %s" % test_name
|
|
exit_code = 1
|
|
continue
|
|
_logger.debug(" Transitive hash: %s" % gtest_hash)
|
|
|
|
if gtest_hash in successes:
|
|
print "Skipping %s (previously succeeded)" % test_name
|
|
continue
|
|
|
|
_logger.info("Will start: %s" % test_name)
|
|
print "Running %s...." % test_name,
|
|
sys.stdout.flush()
|
|
try:
|
|
if config.target_os == Config.OS_ANDROID:
|
|
command = [
|
|
"python",
|
|
os.path.join(_paths.src_root, "build", "android", "test_runner.py"),
|
|
"gtest",
|
|
"--output-directory",
|
|
args.root_dir,
|
|
"-s",
|
|
test,
|
|
]
|
|
else:
|
|
command = ["./" + test]
|
|
_logger.debug("Command: %s" % command)
|
|
subprocess.check_output(command, stderr=subprocess.STDOUT)
|
|
print "Succeeded"
|
|
# Record success.
|
|
if args.successes_cache and cacheable:
|
|
successes.add(gtest_hash)
|
|
successes_cache_file.write(gtest_hash + "\n")
|
|
successes_cache_file.flush()
|
|
except subprocess.CalledProcessError as e:
|
|
print "Failed with exit code %d and output:" % e.returncode
|
|
print 72 * "-"
|
|
print e.output
|
|
print 72 * "-"
|
|
exit_code = 1
|
|
continue
|
|
except OSError as e:
|
|
print " Failed to start test"
|
|
exit_code = 1
|
|
continue
|
|
_logger.info("Completed: %s" % test_name)
|
|
if exit_code == 0:
|
|
print "All tests succeeded"
|
|
if successes_cache_file:
|
|
successes_cache_file.close()
|
|
|
|
return exit_code
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|