| # 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. |
| |
| """Apptest runner specific to the particular gtest-based apptest framework in |
| /mojo/public/cpp/application/tests/, built on top of the general apptest |
| runner.""" |
| |
| import logging |
| import re |
| |
| from devtoolslib.apptest import run_apptest |
| |
| |
| _logger = logging.getLogger() |
| |
| |
| def _gtest_apptest_output_test(output): |
| # Fail on output with gtest's "[ FAILED ]" or a lack of "[ PASSED ]". |
| # The latter condition ensures failure on broken command lines or output. |
| # Check output instead of exit codes because mojo_shell always exits with 0. |
| if (output is None or |
| (output.find("[ FAILED ]") != -1 or output.find("[ PASSED ]") == -1)): |
| return False |
| return True |
| |
| |
| def run_gtest_apptest(shell, shell_args, apptest_url, apptest_args, timeout, |
| isolate): |
| """Runs a gtest apptest. |
| |
| Args: |
| shell: Wrapper around concrete Mojo shell, implementing devtools Shell |
| interface. |
| shell_args: The arguments for mojo_shell. |
| apptest_url: Url of the apptest app to run. |
| apptest_args: Parameters to be passed to the apptest app. |
| isolate: Iff True, each test in the app will be run in a separate shell run. |
| |
| Returns: |
| True iff the test succeeded, False otherwise. |
| """ |
| |
| if not isolate: |
| return run_apptest(shell, shell_args, apptest_url, apptest_args, timeout, |
| _gtest_apptest_output_test) |
| |
| # List the apptest fixtures so they can be run independently for isolation. |
| fixtures = get_fixtures(shell, shell_args, apptest_url) |
| if not fixtures: |
| print "No tests to run found in %s." % apptest_url |
| return False |
| |
| apptest_result = True |
| for fixture in fixtures: |
| isolated_apptest_args = apptest_args + ["--gtest_filter=%s" % fixture] |
| success = run_apptest(shell, shell_args, apptest_url, isolated_apptest_args, |
| timeout, _gtest_apptest_output_test) |
| |
| if not success: |
| apptest_result = False |
| |
| return apptest_result |
| |
| |
| def get_fixtures(shell, shell_args, apptest): |
| """Returns the "Test.Fixture" list from an apptest using mojo_shell. |
| |
| Tests are listed by running the given apptest in mojo_shell and passing |
| --gtest_list_tests. The output is parsed and reformatted into a list like |
| [TestSuite.TestFixture, ... ] |
| An empty list is returned on failure, with errors logged. |
| |
| Args: |
| apptest: The URL of the test application to run. |
| """ |
| arguments = [] |
| arguments.extend(shell_args) |
| arguments.append("--args-for=%s %s" % (apptest, "--gtest_list_tests")) |
| arguments.append(apptest) |
| |
| (exit_code, output, did_time_out) = shell.run_and_get_output(arguments) |
| if exit_code or did_time_out: |
| command_line = "mojo_shell " + " ".join(["%r" % x for x in arguments]) |
| print "Failed to get test fixtures: %r" % command_line |
| print 72 * '-' |
| print output |
| print 72 * '-' |
| return [] |
| |
| _logger.debug("Tests listed:\n%s" % output) |
| return _gtest_list_tests(output) |
| |
| |
| def _gtest_list_tests(gtest_list_tests_output): |
| """Returns a list of strings formatted as TestSuite.TestFixture from the |
| output of running --gtest_list_tests on a GTEST application.""" |
| |
| # Remove log lines. |
| gtest_list_tests_output = re.sub("^(\[|WARNING: linker:).*\n", |
| "", |
| gtest_list_tests_output, |
| flags=re.MULTILINE) |
| |
| if not re.match("^(\w*\.\r?\n( \w*\r?\n)+)+", gtest_list_tests_output): |
| raise Exception("Unrecognized --gtest_list_tests output:\n%s" % |
| gtest_list_tests_output) |
| |
| output_lines = gtest_list_tests_output.split("\n") |
| |
| test_list = [] |
| for line in output_lines: |
| if not line: |
| continue |
| if line[0] != " ": |
| suite = line.strip() |
| continue |
| test_list.append(suite + line.strip()) |
| |
| return test_list |