Commit 32b50786 authored by Wez's avatar Wez Committed by Commit Bot

[base] Verify that TestLauncher batches do not leak tests.

Allow the test batch a grace period after which all of its processes and
jobs must have terminated.

Bug: 1094369
Change-Id: Ia2df0ea4e3fdfbd8c6b99b3c7268171db79f33cb
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2360079
Auto-Submit: Wez <wez@chromium.org>
Commit-Queue: Ilia Samsonov <isamsonov@google.com>
Reviewed-by: default avatarIlia Samsonov <isamsonov@google.com>
Cr-Commit-Position: refs/heads/master@{#802739}
parent 372300ab
...@@ -73,6 +73,7 @@ ...@@ -73,6 +73,7 @@
#if defined(OS_FUCHSIA) #if defined(OS_FUCHSIA)
#include <lib/fdio/namespace.h> #include <lib/fdio/namespace.h>
#include <lib/zx/job.h> #include <lib/zx/job.h>
#include <lib/zx/time.h>
#include "base/atomic_sequence_num.h" #include "base/atomic_sequence_num.h"
#include "base/base_paths_fuchsia.h" #include "base/base_paths_fuchsia.h"
#include "base/fuchsia/default_job.h" #include "base/fuchsia/default_job.h"
...@@ -143,6 +144,22 @@ TestLauncherTracer* GetTestLauncherTracer() { ...@@ -143,6 +144,22 @@ TestLauncherTracer* GetTestLauncherTracer() {
return tracer; return tracer;
} }
#if defined(OS_FUCHSIA)
zx_status_t WaitForJobExit(const zx::job& job) {
zx::time deadline =
zx::deadline_after(zx::duration(kOutputTimeout.ToZxDuration()));
zx_signals_t to_wait_for = ZX_JOB_NO_JOBS | ZX_JOB_NO_PROCESSES;
while (to_wait_for) {
zx_signals_t observed = 0;
zx_status_t status = job.wait_one(to_wait_for, deadline, &observed);
if (status != ZX_OK)
return status;
to_wait_for &= ~observed;
}
return ZX_OK;
}
#endif // defined(OS_FUCHSIA)
#if defined(OS_POSIX) #if defined(OS_POSIX)
// Self-pipe that makes it possible to do complex shutdown handling // Self-pipe that makes it possible to do complex shutdown handling
// outside of the signal handler. // outside of the signal handler.
...@@ -425,6 +442,14 @@ int LaunchChildTestProcessWithOptions(const CommandLine& command_line, ...@@ -425,6 +442,14 @@ int LaunchChildTestProcessWithOptions(const CommandLine& command_line,
} }
} }
#if defined(OS_FUCHSIA)
zx_status_t wait_status = WaitForJobExit(job_handle);
if (wait_status != ZX_OK) {
LOG(ERROR) << "Batch leaked jobs or processes.";
exit_code = -1;
}
#endif // defined(OS_FUCHSIA)
{ {
// Note how we grab the log before issuing a possibly broad process kill. // Note how we grab the log before issuing a possibly broad process kill.
// Other code parts that grab the log kill processes, so avoid trying // Other code parts that grab the log kill processes, so avoid trying
......
...@@ -15,12 +15,14 @@ ...@@ -15,12 +15,14 @@
#include "base/test/launcher/test_launcher.h" #include "base/test/launcher/test_launcher.h"
#include "base/test/launcher/test_launcher_test_utils.h" #include "base/test/launcher/test_launcher_test_utils.h"
#include "base/test/launcher/unit_test_launcher.h" #include "base/test/launcher/unit_test_launcher.h"
#include "base/test/multiprocess_test.h"
#include "base/test/task_environment.h" #include "base/test/task_environment.h"
#include "base/test/test_timeouts.h" #include "base/test/test_timeouts.h"
#include "base/threading/thread_task_runner_handle.h" #include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "testing/gmock/include/gmock/gmock.h" #include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "testing/multiprocess_func_list.h"
#if defined(OS_WIN) #if defined(OS_WIN)
#include "base/win/windows_version.h" #include "base/win/windows_version.h"
...@@ -764,6 +766,65 @@ TEST_F(UnitTestLauncherDelegateTester, RunMockTests) { ...@@ -764,6 +766,65 @@ TEST_F(UnitTestLauncherDelegateTester, RunMockTests) {
iteration_val, "MockUnitTests.NoRunTest", "NOTRUN", 0u)); iteration_val, "MockUnitTests.NoRunTest", "NOTRUN", 0u));
} }
// TODO(crbug.com/1094369): Enable leaked-child checks on other platforms.
#if defined(OS_FUCHSIA)
// Test that leaves a child process running. The test is DISABLED_, so it can
// be launched explicitly by RunMockLeakProcessTest
MULTIPROCESS_TEST_MAIN(LeakChildProcess) {
while (true)
PlatformThread::Sleep(base::TimeDelta::FromSeconds(1));
}
TEST(LeakedChildProcessTest, DISABLED_LeakChildProcess) {
Process child_process = SpawnMultiProcessTestChild(
"LeakChildProcess", GetMultiProcessTestChildBaseCommandLine(),
LaunchOptions());
ASSERT_TRUE(child_process.IsValid());
// Don't wait for the child process to exit.
}
// Validate that a test that leaks a process causes the batch to have an
// error exit_code.
TEST_F(UnitTestLauncherDelegateTester, LeakedChildProcess) {
CommandLine command_line(CommandLine::ForCurrentProcess()->GetProgram());
command_line.AppendSwitchASCII(
"gtest_filter", "LeakedChildProcessTest.DISABLED_LeakChildProcess");
ASSERT_TRUE(dir.CreateUniqueTempDir());
FilePath path = dir.GetPath().AppendASCII("SaveSummaryResult.json");
command_line.AppendSwitchPath("test-launcher-summary-output", path);
command_line.AppendSwitch("gtest_also_run_disabled_tests");
command_line.AppendSwitchASCII("test-launcher-retry-limit", "0");
#if defined(OS_WIN)
// In Windows versions prior to Windows 8, nested job objects are
// not allowed and cause this test to fail.
if (win::GetVersion() < win::Version::WIN8) {
command_line.AppendSwitch(kDontUseJobObjectFlag);
}
#endif // defined(OS_WIN)
std::string output;
int exit_code = 0;
GetAppOutputWithExitCode(command_line, &output, &exit_code);
// Validate that we actually ran a test.
Optional<Value> root = test_launcher_utils::ReadSummary(path);
ASSERT_TRUE(root);
Value* val = root->FindDictKey("test_locations");
ASSERT_TRUE(val);
EXPECT_EQ(1u, val->DictSize());
EXPECT_TRUE(test_launcher_utils::ValidateTestLocations(
val, "LeakedChildProcessTest"));
// Validate that the leaked child caused the batch to error-out.
EXPECT_EQ(exit_code, 1);
}
#endif // defined(OS_FUCHSIA)
// Validate GetTestOutputSnippetTest assigns correct output snippet. // Validate GetTestOutputSnippetTest assigns correct output snippet.
TEST(TestLauncherTools, GetTestOutputSnippetTest) { TEST(TestLauncherTools, GetTestOutputSnippetTest) {
const std::string output = const std::string output =
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment