blob: 67238e66c71633ca0c3b5e1930cfd5a8697b4e4a [file] [log] [blame]
// Copyright (c) 2012 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.
#include "base/allocator/buildflags.h"
#include "base/json/json_reader.h"
#include "base/run_loop.h"
#include "base/threading/thread_restrictions.h"
#include "base/trace_event/trace_buffer.h"
#include "base/trace_event/trace_log.h"
#include "build/build_config.h"
#include "chrome/browser/profiling_host/profiling_process_host.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/heap_profiling/test_driver.h"
#include "components/services/heap_profiling/public/cpp/settings.h"
#include "components/services/heap_profiling/public/cpp/switches.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/browser_test.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/zlib/zlib.h"
// Some builds don't support memlog in which case the tests won't function.
#if BUILDFLAG(USE_ALLOCATOR_SHIM)
namespace heap_profiling {
struct TestParam {
Mode mode;
mojom::StackMode stack_mode;
bool stream_samples;
bool start_profiling_with_command_line_flag;
bool should_sample;
bool sample_everything;
};
class MemlogBrowserTest : public InProcessBrowserTest,
public testing::WithParamInterface<TestParam> {
void SetUpDefaultCommandLine(base::CommandLine* command_line) override {
InProcessBrowserTest::SetUpDefaultCommandLine(command_line);
if (GetParam().start_profiling_with_command_line_flag) {
if (GetParam().mode == Mode::kAllRenderers) {
command_line->AppendSwitchASCII(
heap_profiling::kMemlog, heap_profiling::kMemlogModeAllRenderers);
} else if (GetParam().mode == Mode::kAll) {
command_line->AppendSwitchASCII(heap_profiling::kMemlog,
heap_profiling::kMemlogModeAll);
} else {
NOTREACHED();
}
if (!GetParam().stream_samples)
command_line->AppendSwitch(heap_profiling::kMemlogInProcess);
if (!GetParam().should_sample) {
command_line->AppendSwitchASCII(heap_profiling::kMemlogSamplingRate,
"1");
}
if (GetParam().stack_mode == mojom::StackMode::PSEUDO) {
command_line->AppendSwitchASCII(heap_profiling::kMemlogStackMode,
heap_profiling::kMemlogStackModePseudo);
} else if (GetParam().stack_mode ==
mojom::StackMode::NATIVE_WITH_THREAD_NAMES) {
command_line->AppendSwitchASCII(
heap_profiling::kMemlogStackMode,
heap_profiling::kMemlogStackModeNativeWithThreadNames);
} else if (GetParam().stack_mode ==
mojom::StackMode::NATIVE_WITHOUT_THREAD_NAMES) {
command_line->AppendSwitchASCII(heap_profiling::kMemlogStackMode,
heap_profiling::kMemlogStackModeNative);
} else if (GetParam().stack_mode == mojom::StackMode::MIXED) {
command_line->AppendSwitchASCII(heap_profiling::kMemlogStackMode,
heap_profiling::kMemlogStackModeMixed);
} else {
NOTREACHED();
}
}
}
};
// Ensure invocations via TracingController can generate a valid JSON file with
// expected data.
// https://crbug.com/944429
#if defined(OS_MACOSX)
#define MAYBE_EndToEnd DISABLED_EndToEnd
#else
#define MAYBE_EndToEnd EndToEnd
#endif
IN_PROC_BROWSER_TEST_P(MemlogBrowserTest, MAYBE_EndToEnd) {
LOG(INFO) << "Memlog mode: " << static_cast<int>(GetParam().mode);
LOG(INFO) << "Memlog stack mode: " << static_cast<int>(GetParam().stack_mode);
LOG(INFO) << "Stream samples: " << GetParam().stream_samples;
LOG(INFO) << "Started via command line flag: "
<< GetParam().start_profiling_with_command_line_flag;
LOG(INFO) << "Should sample: " << GetParam().should_sample;
LOG(INFO) << "Sample everything: " << GetParam().sample_everything;
TestDriver driver;
TestDriver::Options options;
options.mode = GetParam().mode;
options.stack_mode = GetParam().stack_mode;
options.stream_samples = GetParam().stream_samples;
options.profiling_already_started =
GetParam().start_profiling_with_command_line_flag;
options.should_sample = GetParam().should_sample;
options.sample_everything = GetParam().sample_everything;
EXPECT_TRUE(driver.RunTest(options));
}
// TODO(ajwong): Test what happens if profiling process crashes.
// http://crbug.com/780955
std::vector<TestParam> GetParams() {
std::vector<TestParam> params;
std::vector<Mode> dynamic_start_modes;
dynamic_start_modes.push_back(Mode::kNone);
dynamic_start_modes.push_back(Mode::kMinimal);
dynamic_start_modes.push_back(Mode::kBrowser);
dynamic_start_modes.push_back(Mode::kGpu);
std::vector<mojom::StackMode> stack_modes;
stack_modes.push_back(mojom::StackMode::MIXED);
stack_modes.push_back(mojom::StackMode::NATIVE_WITHOUT_THREAD_NAMES);
stack_modes.push_back(mojom::StackMode::PSEUDO);
for (bool stream_samples : (bool[]){true, false}) {
for (const auto& mode : dynamic_start_modes) {
for (const auto& stack_mode : stack_modes) {
params.push_back({mode, stack_mode, stream_samples,
false /* start_profiling_with_command_line_flag */,
true /* should_sample */,
false /* sample_everything*/});
}
}
// For unknown reasons, renderer profiling has become flaky on ChromeOS. This is
// likely happening because the renderers are never being given the signal to
// start profiling. It's unclear why this happens. https://crbug.com/843843.
// https://crbug.com/843467.
#if !defined(OS_CHROMEOS)
// Non-browser processes must be profiled with a command line flag, since
// otherwise, profiling will start after the relevant processes have been
// created, thus that process will be not be profiled.
std::vector<Mode> command_line_start_modes;
command_line_start_modes.push_back(Mode::kAll);
command_line_start_modes.push_back(Mode::kAllRenderers);
for (const auto& mode : command_line_start_modes) {
for (const auto& stack_mode : stack_modes) {
params.push_back({mode, stack_mode, stream_samples,
true /* start_profiling_with_command_line_flag */,
true /* should_sample */,
false /* sample_everything*/});
}
}
#endif // defined(OS_CHROMEOS)
}
return params;
}
INSTANTIATE_TEST_SUITE_P(Memlog,
MemlogBrowserTest,
::testing::ValuesIn(GetParams()));
} // namespace heap_profiling
#endif // BUILDFLAG(USE_ALLOCATOR_SHIM)