summaryrefslogtreecommitdiffstats
path: root/base/test
diff options
context:
space:
mode:
authorPaweł Hajdan, Jr <phajdan.jr@chromium.org>2015-01-28 12:03:14 +0100
committerPaweł Hajdan, Jr <phajdan.jr@chromium.org>2015-01-28 11:04:59 +0000
commit9471d2a13c88409c7155a22dda9b84217190e889 (patch)
treeab28308fb753169ef0831a5496a31352b9a16f84 /base/test
parent0d6e89ba9d5d66adf5dcd8c46682c5a1901844c3 (diff)
downloadchromium_src-9471d2a13c88409c7155a22dda9b84217190e889.zip
chromium_src-9471d2a13c88409c7155a22dda9b84217190e889.tar.gz
chromium_src-9471d2a13c88409c7155a22dda9b84217190e889.tar.bz2
Refactoring in unit_test_launcher.cc:
- expose RunUnitTestsSerially and RunUnitTestsBatch - hide private static ProcessTestResults in anonymous namespace This will be used to implement ios-specific unit test relaunch logic. Exposing the helpers makes it possible to re-use them in ios code. BUG=426870 R=sky@chromium.org Review URL: https://codereview.chromium.org/879883002 Cr-Commit-Position: refs/heads/master@{#313476}
Diffstat (limited to 'base/test')
-rw-r--r--base/test/launcher/unit_test_launcher.cc467
-rw-r--r--base/test/launcher/unit_test_launcher.h54
2 files changed, 255 insertions, 266 deletions
diff --git a/base/test/launcher/unit_test_launcher.cc b/base/test/launcher/unit_test_launcher.cc
index 2a4e748..1ded464 100644
--- a/base/test/launcher/unit_test_launcher.cc
+++ b/base/test/launcher/unit_test_launcher.cc
@@ -216,230 +216,9 @@ void InitGoogleTestWChar(int* argc, wchar_t** argv) {
}
#endif // defined(OS_WIN)
-} // namespace
-
-int LaunchUnitTests(int argc,
- char** argv,
- const RunTestSuiteCallback& run_test_suite) {
- CommandLine::Init(argc, argv);
- return LaunchUnitTestsInternal(run_test_suite, SysInfo::NumberOfProcessors(),
- true, Bind(&InitGoogleTestChar, &argc, argv));
-}
-
-int LaunchUnitTestsSerially(int argc,
- char** argv,
- const RunTestSuiteCallback& run_test_suite) {
- CommandLine::Init(argc, argv);
- return LaunchUnitTestsInternal(run_test_suite, 1, true,
- Bind(&InitGoogleTestChar, &argc, argv));
-}
-
-#if defined(OS_WIN)
-int LaunchUnitTests(int argc,
- wchar_t** argv,
- bool use_job_objects,
- const RunTestSuiteCallback& run_test_suite) {
- // Windows CommandLine::Init ignores argv anyway.
- CommandLine::Init(argc, NULL);
- return LaunchUnitTestsInternal(run_test_suite, SysInfo::NumberOfProcessors(),
- use_job_objects,
- Bind(&InitGoogleTestWChar, &argc, argv));
-}
-#endif // defined(OS_WIN)
-
-UnitTestLauncherDelegate::UnitTestLauncherDelegate(
- UnitTestPlatformDelegate* platform_delegate,
- size_t batch_limit,
- bool use_job_objects)
- : platform_delegate_(platform_delegate),
- batch_limit_(batch_limit),
- use_job_objects_(use_job_objects) {
-}
-
-UnitTestLauncherDelegate::~UnitTestLauncherDelegate() {
- DCHECK(thread_checker_.CalledOnValidThread());
-}
-
-UnitTestLauncherDelegate::GTestCallbackState::GTestCallbackState() {
-}
-
-UnitTestLauncherDelegate::GTestCallbackState::~GTestCallbackState() {
-}
-
-bool UnitTestLauncherDelegate::GetTests(std::vector<SplitTestName>* output) {
- DCHECK(thread_checker_.CalledOnValidThread());
- return platform_delegate_->GetTests(output);
-}
-
-bool UnitTestLauncherDelegate::ShouldRunTest(const std::string& test_case_name,
- const std::string& test_name) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- // There is no additional logic to disable specific tests.
- return true;
-}
-
-size_t UnitTestLauncherDelegate::RunTests(
- TestLauncher* test_launcher,
- const std::vector<std::string>& test_names) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- std::vector<std::string> batch;
- for (size_t i = 0; i < test_names.size(); i++) {
- batch.push_back(test_names[i]);
-
- // Use 0 to indicate unlimited batch size.
- if (batch.size() >= batch_limit_ && batch_limit_ != 0) {
- RunBatch(test_launcher, batch);
- batch.clear();
- }
- }
-
- RunBatch(test_launcher, batch);
-
- return test_names.size();
-}
-
-size_t UnitTestLauncherDelegate::RetryTests(
- TestLauncher* test_launcher,
- const std::vector<std::string>& test_names) {
- MessageLoop::current()->PostTask(
- FROM_HERE, Bind(&UnitTestLauncherDelegate::RunSerially, Unretained(this),
- test_launcher, test_names));
- return test_names.size();
-}
-
-void UnitTestLauncherDelegate::RunSerially(
- TestLauncher* test_launcher,
- const std::vector<std::string>& test_names) {
- if (test_names.empty())
- return;
-
- std::vector<std::string> new_test_names(test_names);
- std::string test_name(new_test_names.back());
- new_test_names.pop_back();
-
- // Create a dedicated temporary directory to store the xml result data
- // per run to ensure clean state and make it possible to launch multiple
- // processes in parallel.
- base::FilePath output_file;
- CHECK(platform_delegate_->CreateTemporaryFile(&output_file));
-
- std::vector<std::string> current_test_names;
- current_test_names.push_back(test_name);
- CommandLine cmd_line(platform_delegate_->GetCommandLineForChildGTestProcess(
- current_test_names, output_file));
-
- GTestCallbackState callback_state;
- callback_state.test_launcher = test_launcher;
- callback_state.test_names = current_test_names;
- callback_state.output_file = output_file;
-
- test_launcher->LaunchChildGTestProcess(
- cmd_line,
- platform_delegate_->GetWrapperForChildGTestProcess(),
- TestTimeouts::test_launcher_timeout(),
- use_job_objects_ ? TestLauncher::USE_JOB_OBJECTS : 0,
- Bind(&UnitTestLauncherDelegate::SerialGTestCallback, Unretained(this),
- callback_state, new_test_names));
-}
-
-void UnitTestLauncherDelegate::RunBatch(
- TestLauncher* test_launcher,
- const std::vector<std::string>& test_names) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- if (test_names.empty())
- return;
-
- // Create a dedicated temporary directory to store the xml result data
- // per run to ensure clean state and make it possible to launch multiple
- // processes in parallel.
- base::FilePath output_file;
- CHECK(platform_delegate_->CreateTemporaryFile(&output_file));
-
- CommandLine cmd_line(platform_delegate_->GetCommandLineForChildGTestProcess(
- test_names, output_file));
-
- // Adjust the timeout depending on how many tests we're running
- // (note that e.g. the last batch of tests will be smaller).
- // TODO(phajdan.jr): Consider an adaptive timeout, which can change
- // depending on how many tests ran and how many remain.
- // Note: do NOT parse child's stdout to do that, it's known to be
- // unreliable (e.g. buffering issues can mix up the output).
- base::TimeDelta timeout =
- test_names.size() * TestTimeouts::test_launcher_timeout();
-
- GTestCallbackState callback_state;
- callback_state.test_launcher = test_launcher;
- callback_state.test_names = test_names;
- callback_state.output_file = output_file;
-
- test_launcher->LaunchChildGTestProcess(
- cmd_line,
- platform_delegate_->GetWrapperForChildGTestProcess(),
- timeout,
- use_job_objects_ ? TestLauncher::USE_JOB_OBJECTS : 0,
- Bind(&UnitTestLauncherDelegate::GTestCallback, Unretained(this),
- callback_state));
-}
-
-void UnitTestLauncherDelegate::GTestCallback(
- const GTestCallbackState& callback_state,
- int exit_code,
- const TimeDelta& elapsed_time,
- bool was_timeout,
- const std::string& output) {
- DCHECK(thread_checker_.CalledOnValidThread());
- std::vector<std::string> tests_to_relaunch;
- ProcessTestResults(callback_state.test_launcher, callback_state.test_names,
- callback_state.output_file, output, exit_code, was_timeout,
- &tests_to_relaunch);
-
- // Relaunch requested tests in parallel, but only use single
- // test per batch for more precise results (crashes, test passes
- // but non-zero exit codes etc).
- for (size_t i = 0; i < tests_to_relaunch.size(); i++) {
- std::vector<std::string> batch;
- batch.push_back(tests_to_relaunch[i]);
- RunBatch(callback_state.test_launcher, batch);
- }
-
- // The temporary file's directory is also temporary.
- DeleteFile(callback_state.output_file.DirName(), true);
-}
-
-void UnitTestLauncherDelegate::SerialGTestCallback(
- const GTestCallbackState& callback_state,
- const std::vector<std::string>& test_names,
- int exit_code,
- const TimeDelta& elapsed_time,
- bool was_timeout,
- const std::string& output) {
- DCHECK(thread_checker_.CalledOnValidThread());
- std::vector<std::string> tests_to_relaunch;
- bool called_any_callbacks =
- ProcessTestResults(callback_state.test_launcher,
- callback_state.test_names, callback_state.output_file,
- output, exit_code, was_timeout, &tests_to_relaunch);
-
- // There is only one test, there cannot be other tests to relaunch
- // due to a crash.
- DCHECK(tests_to_relaunch.empty());
-
- // There is only one test, we should have called back with its result.
- DCHECK(called_any_callbacks);
-
- // The temporary file's directory is also temporary.
- DeleteFile(callback_state.output_file.DirName(), true);
-
- MessageLoop::current()->PostTask(
- FROM_HERE, Bind(&UnitTestLauncherDelegate::RunSerially, Unretained(this),
- callback_state.test_launcher, test_names));
-}
-
-// static
-bool UnitTestLauncherDelegate::ProcessTestResults(
+// Interprets test results and reports to the test launcher. Returns true
+// on success.
+bool ProcessTestResults(
TestLauncher* test_launcher,
const std::vector<std::string>& test_names,
const base::FilePath& output_file,
@@ -574,4 +353,244 @@ bool UnitTestLauncherDelegate::ProcessTestResults(
return called_any_callback;
}
+// TODO(phajdan.jr): Pass parameters directly with C++11 variadic templates.
+struct GTestCallbackState {
+ TestLauncher* test_launcher;
+ UnitTestPlatformDelegate* platform_delegate;
+ std::vector<std::string> test_names;
+ int launch_flags;
+ FilePath output_file;
+};
+
+void GTestCallback(
+ const GTestCallbackState& callback_state,
+ int exit_code,
+ const TimeDelta& elapsed_time,
+ bool was_timeout,
+ const std::string& output) {
+ std::vector<std::string> tests_to_relaunch;
+ ProcessTestResults(callback_state.test_launcher, callback_state.test_names,
+ callback_state.output_file, output, exit_code, was_timeout,
+ &tests_to_relaunch);
+
+ // Relaunch requested tests in parallel, but only use single
+ // test per batch for more precise results (crashes, test passes
+ // but non-zero exit codes etc).
+ for (size_t i = 0; i < tests_to_relaunch.size(); i++) {
+ std::vector<std::string> batch;
+ batch.push_back(tests_to_relaunch[i]);
+ RunUnitTestsBatch(callback_state.test_launcher,
+ callback_state.platform_delegate,
+ batch,
+ callback_state.launch_flags);
+ }
+
+ // The temporary file's directory is also temporary.
+ DeleteFile(callback_state.output_file.DirName(), true);
+}
+
+void SerialGTestCallback(
+ const GTestCallbackState& callback_state,
+ const std::vector<std::string>& test_names,
+ int exit_code,
+ const TimeDelta& elapsed_time,
+ bool was_timeout,
+ const std::string& output) {
+ std::vector<std::string> tests_to_relaunch;
+ bool called_any_callbacks =
+ ProcessTestResults(callback_state.test_launcher,
+ callback_state.test_names, callback_state.output_file,
+ output, exit_code, was_timeout, &tests_to_relaunch);
+
+ // There is only one test, there cannot be other tests to relaunch
+ // due to a crash.
+ DCHECK(tests_to_relaunch.empty());
+
+ // There is only one test, we should have called back with its result.
+ DCHECK(called_any_callbacks);
+
+ // The temporary file's directory is also temporary.
+ DeleteFile(callback_state.output_file.DirName(), true);
+
+ MessageLoop::current()->PostTask(
+ FROM_HERE,
+ Bind(&RunUnitTestsSerially,
+ callback_state.test_launcher,
+ callback_state.platform_delegate,
+ test_names,
+ callback_state.launch_flags));
+}
+
+} // namespace
+
+int LaunchUnitTests(int argc,
+ char** argv,
+ const RunTestSuiteCallback& run_test_suite) {
+ CommandLine::Init(argc, argv);
+ return LaunchUnitTestsInternal(run_test_suite, SysInfo::NumberOfProcessors(),
+ true, Bind(&InitGoogleTestChar, &argc, argv));
+}
+
+int LaunchUnitTestsSerially(int argc,
+ char** argv,
+ const RunTestSuiteCallback& run_test_suite) {
+ CommandLine::Init(argc, argv);
+ return LaunchUnitTestsInternal(run_test_suite, 1, true,
+ Bind(&InitGoogleTestChar, &argc, argv));
+}
+
+#if defined(OS_WIN)
+int LaunchUnitTests(int argc,
+ wchar_t** argv,
+ bool use_job_objects,
+ const RunTestSuiteCallback& run_test_suite) {
+ // Windows CommandLine::Init ignores argv anyway.
+ CommandLine::Init(argc, NULL);
+ return LaunchUnitTestsInternal(run_test_suite, SysInfo::NumberOfProcessors(),
+ use_job_objects,
+ Bind(&InitGoogleTestWChar, &argc, argv));
+}
+#endif // defined(OS_WIN)
+
+void RunUnitTestsSerially(
+ TestLauncher* test_launcher,
+ UnitTestPlatformDelegate* platform_delegate,
+ const std::vector<std::string>& test_names,
+ int launch_flags) {
+ if (test_names.empty())
+ return;
+
+ std::vector<std::string> new_test_names(test_names);
+ std::string test_name(new_test_names.back());
+ new_test_names.pop_back();
+
+ // Create a dedicated temporary directory to store the xml result data
+ // per run to ensure clean state and make it possible to launch multiple
+ // processes in parallel.
+ base::FilePath output_file;
+ CHECK(platform_delegate->CreateTemporaryFile(&output_file));
+
+ std::vector<std::string> current_test_names;
+ current_test_names.push_back(test_name);
+ CommandLine cmd_line(platform_delegate->GetCommandLineForChildGTestProcess(
+ current_test_names, output_file));
+
+ GTestCallbackState callback_state;
+ callback_state.test_launcher = test_launcher;
+ callback_state.platform_delegate = platform_delegate;
+ callback_state.test_names = current_test_names;
+ callback_state.launch_flags = launch_flags;
+ callback_state.output_file = output_file;
+
+ test_launcher->LaunchChildGTestProcess(
+ cmd_line,
+ platform_delegate->GetWrapperForChildGTestProcess(),
+ TestTimeouts::test_launcher_timeout(),
+ launch_flags,
+ Bind(&SerialGTestCallback, callback_state, new_test_names));
+}
+
+void RunUnitTestsBatch(
+ TestLauncher* test_launcher,
+ UnitTestPlatformDelegate* platform_delegate,
+ const std::vector<std::string>& test_names,
+ int launch_flags) {
+ if (test_names.empty())
+ return;
+
+ // Create a dedicated temporary directory to store the xml result data
+ // per run to ensure clean state and make it possible to launch multiple
+ // processes in parallel.
+ base::FilePath output_file;
+ CHECK(platform_delegate->CreateTemporaryFile(&output_file));
+
+ CommandLine cmd_line(platform_delegate->GetCommandLineForChildGTestProcess(
+ test_names, output_file));
+
+ // Adjust the timeout depending on how many tests we're running
+ // (note that e.g. the last batch of tests will be smaller).
+ // TODO(phajdan.jr): Consider an adaptive timeout, which can change
+ // depending on how many tests ran and how many remain.
+ // Note: do NOT parse child's stdout to do that, it's known to be
+ // unreliable (e.g. buffering issues can mix up the output).
+ base::TimeDelta timeout =
+ test_names.size() * TestTimeouts::test_launcher_timeout();
+
+ GTestCallbackState callback_state;
+ callback_state.test_launcher = test_launcher;
+ callback_state.platform_delegate = platform_delegate;
+ callback_state.test_names = test_names;
+ callback_state.launch_flags = launch_flags;
+ callback_state.output_file = output_file;
+
+ test_launcher->LaunchChildGTestProcess(
+ cmd_line,
+ platform_delegate->GetWrapperForChildGTestProcess(),
+ timeout,
+ launch_flags,
+ Bind(&GTestCallback, callback_state));
+}
+
+UnitTestLauncherDelegate::UnitTestLauncherDelegate(
+ UnitTestPlatformDelegate* platform_delegate,
+ size_t batch_limit,
+ bool use_job_objects)
+ : platform_delegate_(platform_delegate),
+ batch_limit_(batch_limit),
+ use_job_objects_(use_job_objects) {
+}
+
+UnitTestLauncherDelegate::~UnitTestLauncherDelegate() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+}
+
+bool UnitTestLauncherDelegate::GetTests(std::vector<SplitTestName>* output) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return platform_delegate_->GetTests(output);
+}
+
+bool UnitTestLauncherDelegate::ShouldRunTest(const std::string& test_case_name,
+ const std::string& test_name) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ // There is no additional logic to disable specific tests.
+ return true;
+}
+
+size_t UnitTestLauncherDelegate::RunTests(
+ TestLauncher* test_launcher,
+ const std::vector<std::string>& test_names) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ int launch_flags = use_job_objects_ ? TestLauncher::USE_JOB_OBJECTS : 0;
+
+ std::vector<std::string> batch;
+ for (size_t i = 0; i < test_names.size(); i++) {
+ batch.push_back(test_names[i]);
+
+ // Use 0 to indicate unlimited batch size.
+ if (batch.size() >= batch_limit_ && batch_limit_ != 0) {
+ RunUnitTestsBatch(test_launcher, platform_delegate_, batch, launch_flags);
+ batch.clear();
+ }
+ }
+
+ RunUnitTestsBatch(test_launcher, platform_delegate_, batch, launch_flags);
+
+ return test_names.size();
+}
+
+size_t UnitTestLauncherDelegate::RetryTests(
+ TestLauncher* test_launcher,
+ const std::vector<std::string>& test_names) {
+ MessageLoop::current()->PostTask(
+ FROM_HERE,
+ Bind(&RunUnitTestsSerially,
+ test_launcher,
+ platform_delegate_,
+ test_names,
+ use_job_objects_ ? TestLauncher::USE_JOB_OBJECTS : 0));
+ return test_names.size();
+}
+
} // namespace base
diff --git a/base/test/launcher/unit_test_launcher.h b/base/test/launcher/unit_test_launcher.h
index e4997a0..5b5f240 100644
--- a/base/test/launcher/unit_test_launcher.h
+++ b/base/test/launcher/unit_test_launcher.h
@@ -59,6 +59,18 @@ class UnitTestPlatformDelegate {
~UnitTestPlatformDelegate() {}
};
+// Runs tests serially, each in its own process.
+void RunUnitTestsSerially(TestLauncher* test_launcher,
+ UnitTestPlatformDelegate* platform_delegate,
+ const std::vector<std::string>& test_names,
+ int launch_flags);
+
+// Runs tests in batches (each batch in its own process).
+void RunUnitTestsBatch(TestLauncher* test_launcher,
+ UnitTestPlatformDelegate* platform_delegate,
+ const std::vector<std::string>& test_names,
+ int launch_flags);
+
// Test launcher delegate for unit tests (mostly to support batching).
class UnitTestLauncherDelegate : public TestLauncherDelegate {
public:
@@ -68,15 +80,6 @@ class UnitTestLauncherDelegate : public TestLauncherDelegate {
~UnitTestLauncherDelegate() override;
private:
- struct GTestCallbackState {
- GTestCallbackState();
- ~GTestCallbackState();
-
- TestLauncher* test_launcher;
- std::vector<std::string> test_names;
- FilePath output_file;
- };
-
// TestLauncherDelegate:
bool GetTests(std::vector<SplitTestName>* output) override;
bool ShouldRunTest(const std::string& test_case_name,
@@ -86,39 +89,6 @@ class UnitTestLauncherDelegate : public TestLauncherDelegate {
size_t RetryTests(TestLauncher* test_launcher,
const std::vector<std::string>& test_names) override;
- // Runs tests serially, each in its own process.
- void RunSerially(TestLauncher* test_launcher,
- const std::vector<std::string>& test_names);
-
- // Runs tests in batches (each batch in its own process).
- void RunBatch(TestLauncher* test_launcher,
- const std::vector<std::string>& test_names);
-
- // Callback for batched tests.
- void GTestCallback(const GTestCallbackState& callback_state,
- int exit_code,
- const TimeDelta& elapsed_time,
- bool was_timeout,
- const std::string& output);
-
- // Callback for serialized tests.
- void SerialGTestCallback(const GTestCallbackState& callback_state,
- const std::vector<std::string>& test_names,
- int exit_code,
- const TimeDelta& elapsed_time,
- bool was_timeout,
- const std::string& output);
-
- // Interprets test results and reports to the test launcher. Returns true
- // on success.
- static bool ProcessTestResults(TestLauncher* test_launcher,
- const std::vector<std::string>& test_names,
- const base::FilePath& output_file,
- const std::string& output,
- int exit_code,
- bool was_timeout,
- std::vector<std::string>* tests_to_relaunch);
-
ThreadChecker thread_checker_;
UnitTestPlatformDelegate* platform_delegate_;