| // Copyright 2015 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 <utility> |
| |
| #include "base/bind.h" |
| #include "base/command_line.h" |
| #include "base/files/file_path.h" |
| #include "base/files/file_path_watcher.h" |
| #include "base/files/file_util.h" |
| #include "base/files/scoped_temp_dir.h" |
| #include "base/json/json_writer.h" |
| #include "base/run_loop.h" |
| #include "base/strings/pattern.h" |
| #include "base/test/bind.h" |
| #include "base/threading/thread_restrictions.h" |
| #include "build/build_config.h" |
| #include "build/chromeos_buildflags.h" |
| #include "chrome/app/chrome_command_ids.h" |
| #include "chrome/browser/browser_process.h" |
| #include "chrome/browser/tracing/chrome_tracing_delegate.h" |
| #include "chrome/browser/ui/browser.h" |
| #include "chrome/browser/ui/browser_commands.h" |
| #include "chrome/browser/ui/browser_list.h" |
| #include "chrome/common/pref_names.h" |
| #include "chrome/test/base/in_process_browser_test.h" |
| #include "components/metrics/metrics_pref_names.h" |
| #include "components/prefs/pref_service.h" |
| #include "components/tracing/common/trace_startup_config.h" |
| #include "components/variations/variations_params_manager.h" |
| #include "content/public/browser/background_tracing_config.h" |
| #include "content/public/browser/background_tracing_manager.h" |
| #include "content/public/browser/browser_task_traits.h" |
| #include "content/public/browser/browser_thread.h" |
| #include "content/public/browser/tracing_controller.h" |
| #include "content/public/test/browser_test.h" |
| #include "content/public/test/test_utils.h" |
| #include "services/tracing/public/cpp/tracing_features.h" |
| |
| class ChromeTracingDelegateBrowserTest : public InProcessBrowserTest { |
| public: |
| ChromeTracingDelegateBrowserTest() |
| : receive_count_(0), |
| started_finalizations_count_(0), |
| last_on_started_finalizing_success_(false) {} |
| |
| #if !BUILDFLAG(IS_CHROMEOS_ASH) |
| void SetUpOnMainThread() override { |
| InProcessBrowserTest::SetUpOnMainThread(); |
| |
| PrefService* local_state = g_browser_process->local_state(); |
| DCHECK(local_state); |
| local_state->SetBoolean(metrics::prefs::kMetricsReportingEnabled, true); |
| content::TracingController::GetInstance(); // Create tracing agents. |
| } |
| #endif |
| |
| bool StartPreemptiveScenario( |
| content::BackgroundTracingManager::DataFiltering data_filtering, |
| base::StringPiece scenario_name = "TestScenario", |
| bool with_crash_scenario = false) { |
| base::Value dict(base::Value::Type::DICTIONARY); |
| |
| dict.SetStringKey("scenario_name", scenario_name); |
| dict.SetStringKey("mode", "PREEMPTIVE_TRACING_MODE"); |
| dict.SetStringKey("custom_categories", |
| tracing::TraceStartupConfig::kDefaultStartupCategories); |
| |
| base::Value rules_list(base::Value::Type::LIST); |
| { |
| base::Value rules_dict(base::Value::Type::DICTIONARY); |
| rules_dict.SetStringKey("rule", "MONITOR_AND_DUMP_WHEN_TRIGGER_NAMED"); |
| rules_dict.SetStringKey("trigger_name", "test"); |
| rules_list.Append(std::move(rules_dict)); |
| } |
| if (with_crash_scenario) { |
| base::Value rules_dict(base::Value::Type::DICTIONARY); |
| rules_dict.SetStringKey("rule", "MONITOR_AND_DUMP_WHEN_TRIGGER_NAMED"); |
| rules_dict.SetStringKey("trigger_name", "test_crash"); |
| rules_dict.SetBoolKey("is_crash", true); |
| rules_list.Append(std::move(rules_dict)); |
| } |
| dict.SetKey("configs", std::move(rules_list)); |
| |
| std::unique_ptr<content::BackgroundTracingConfig> config( |
| content::BackgroundTracingConfig::FromDict(std::move(dict))); |
| DCHECK(config); |
| |
| return content::BackgroundTracingManager::GetInstance()->SetActiveScenario( |
| std::move(config), data_filtering); |
| } |
| |
| bool StartPreemptiveScenarioWithCrash( |
| content::BackgroundTracingManager::DataFiltering data_filtering, |
| base::StringPiece scenario_name = "TestScenario") { |
| return StartPreemptiveScenario(data_filtering, scenario_name, |
| /*with_crash_scenario=*/true); |
| } |
| |
| void TriggerPreemptiveScenario( |
| base::OnceClosure on_started_finalization_callback, |
| base::StringPiece trigger_name = "test") { |
| on_started_finalization_callback_ = |
| std::move(on_started_finalization_callback); |
| trigger_handle_ = |
| content::BackgroundTracingManager::GetInstance()->RegisterTriggerType( |
| trigger_name); |
| |
| content::BackgroundTracingManager::StartedFinalizingCallback |
| started_finalizing_callback = base::BindOnce( |
| &ChromeTracingDelegateBrowserTest::OnStartedFinalizing, |
| base::Unretained(this)); |
| content::BackgroundTracingManager::GetInstance()->TriggerNamedEvent( |
| trigger_handle_, std::move(started_finalizing_callback)); |
| } |
| |
| void TriggerPreemptiveScenarioWithCrash( |
| base::OnceClosure on_started_finalization_callback) { |
| TriggerPreemptiveScenario(std::move(on_started_finalization_callback), |
| "test_crash"); |
| } |
| |
| void WaitForUpload() { |
| // No ReceiveCallback set, so wait for SetTraceToUpload to be called. |
| auto* manager = content::BackgroundTracingManager::GetInstance(); |
| while (!manager->HasTraceToUpload()) { |
| base::RunLoop().RunUntilIdle(); |
| } |
| EXPECT_FALSE(manager->GetLatestTraceToUpload().empty()); |
| receive_count_++; |
| } |
| |
| int get_receive_count() const { return receive_count_; } |
| bool get_started_finalizations() const { |
| return started_finalizations_count_; |
| } |
| bool get_last_started_finalization_success() const { |
| return last_on_started_finalizing_success_; |
| } |
| |
| private: |
| void OnStartedFinalizing(bool success) { |
| started_finalizations_count_++; |
| last_on_started_finalizing_success_ = success; |
| |
| if (!on_started_finalization_callback_.is_null()) { |
| content::GetUIThreadTaskRunner({})->PostTask( |
| FROM_HERE, std::move(on_started_finalization_callback_)); |
| } |
| } |
| |
| base::OnceClosure on_started_finalization_callback_; |
| int receive_count_; |
| int started_finalizations_count_; |
| content::BackgroundTracingManager::TriggerHandle trigger_handle_; |
| bool last_on_started_finalizing_success_; |
| }; |
| |
| std::string GetSessionStateJson() { |
| PrefService* local_state = g_browser_process->local_state(); |
| DCHECK(local_state); |
| const base::Value* state = |
| local_state->GetDictionary(prefs::kBackgroundTracingSessionState); |
| std::string json; |
| EXPECT_TRUE(base::JSONWriter::Write(*state, &json)); |
| return json; |
| } |
| |
| IN_PROC_BROWSER_TEST_F(ChromeTracingDelegateBrowserTest, |
| BackgroundTracingTimeThrottled) { |
| EXPECT_TRUE(StartPreemptiveScenario( |
| content::BackgroundTracingManager::NO_DATA_FILTERING)); |
| |
| TriggerPreemptiveScenario(base::OnceClosure()); |
| |
| WaitForUpload(); |
| EXPECT_TRUE(get_receive_count() == 1); |
| |
| std::string state = GetSessionStateJson(); |
| EXPECT_TRUE(base::MatchPattern( |
| state, |
| R"({"state":3,"upload_times":[{"scenario":"TestScenario","time":"*"}]})")) |
| << "Actual: " << state; |
| |
| content::BackgroundTracingManager::GetInstance()->AbortScenarioForTesting(); |
| base::RunLoop wait_for_abort; |
| content::BackgroundTracingManager::GetInstance()->WhenIdle( |
| wait_for_abort.QuitClosure()); |
| wait_for_abort.Run(); |
| |
| EXPECT_FALSE( |
| content::BackgroundTracingManager::GetInstance()->HasActiveScenario()); |
| EXPECT_FALSE(base::trace_event::TraceLog::GetInstance()->IsEnabled()); |
| |
| // We should not be able to start a new reactive scenario immediately after |
| // a previous one gets uploaded. |
| EXPECT_FALSE(StartPreemptiveScenario( |
| content::BackgroundTracingManager::NO_DATA_FILTERING)); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(ChromeTracingDelegateBrowserTest, |
| BackgroundTracingTimeThrottledAfterPreviousDay) { |
| std::string state = GetSessionStateJson(); |
| EXPECT_EQ(state, "{}"); |
| |
| base::Time upload_time = base::Time::Now() - base::Days(1); |
| ChromeTracingDelegate::ScenarioUploadTimestampMap upload_times; |
| upload_times["TestScenario"] = upload_time; |
| ChromeTracingDelegate::BackgroundTracingStateManager::SaveState( |
| upload_times, |
| ChromeTracingDelegate::BackgroundTracingState::NOT_ACTIVATED); |
| |
| EXPECT_FALSE(StartPreemptiveScenario( |
| content::BackgroundTracingManager::NO_DATA_FILTERING)); |
| |
| state = GetSessionStateJson(); |
| EXPECT_TRUE(base::MatchPattern( |
| state, |
| R"({"state":0,"upload_times":[{"scenario":"TestScenario","time":"*"}]})")) |
| << "Actual: " << state; |
| } |
| |
| IN_PROC_BROWSER_TEST_F(ChromeTracingDelegateBrowserTest, |
| BackgroundTracingTimeThrottledUpdatedScenario) { |
| std::string state = GetSessionStateJson(); |
| EXPECT_EQ(state, "{}"); |
| |
| base::Time upload_time = base::Time::Now() - base::Days(1); |
| ChromeTracingDelegate::ScenarioUploadTimestampMap upload_times; |
| upload_times["TestScenario10"] = upload_time; |
| upload_times["TestingScenario1"] = upload_time; |
| ChromeTracingDelegate::BackgroundTracingStateManager::SaveState( |
| upload_times, |
| ChromeTracingDelegate::BackgroundTracingState::NOT_ACTIVATED); |
| |
| EXPECT_FALSE(StartPreemptiveScenario( |
| content::BackgroundTracingManager::NO_DATA_FILTERING, "TestScenario12")); |
| |
| state = GetSessionStateJson(); |
| EXPECT_TRUE(base::MatchPattern( |
| state, |
| R"({"state":0,"upload_times":[{"scenario":"TestScenario","time":"*"},)" |
| R"({"scenario":"TestingScenario","time":"*"}]})")) |
| << "Actual: " << state; |
| } |
| |
| IN_PROC_BROWSER_TEST_F(ChromeTracingDelegateBrowserTest, |
| BackgroundTracingTimeThrottledDifferentScenario) { |
| std::string state = GetSessionStateJson(); |
| EXPECT_EQ(state, "{}"); |
| |
| base::Time upload_time = base::Time::Now() - base::Days(1); |
| ChromeTracingDelegate::ScenarioUploadTimestampMap upload_times; |
| upload_times["TestScenario10"] = upload_time; |
| upload_times["TestingScenario1"] = upload_time; |
| ChromeTracingDelegate::BackgroundTracingStateManager::SaveState( |
| upload_times, |
| ChromeTracingDelegate::BackgroundTracingState::NOT_ACTIVATED); |
| |
| EXPECT_TRUE(StartPreemptiveScenario( |
| content::BackgroundTracingManager::NO_DATA_FILTERING, "OtherScenario")); |
| |
| state = GetSessionStateJson(); |
| EXPECT_TRUE(base::MatchPattern( |
| state, |
| R"({"state":1,"upload_times":[{"scenario":"TestScenario","time":"*"},)" |
| R"({"scenario":"TestingScenario","time":"*"}]})")) |
| << "Actual: " << state; |
| |
| TriggerPreemptiveScenario(base::OnceClosure()); |
| |
| WaitForUpload(); |
| EXPECT_TRUE(get_receive_count() == 1); |
| |
| state = GetSessionStateJson(); |
| EXPECT_TRUE(base::MatchPattern( |
| state, |
| R"({"state":3,"upload_times":[{"scenario":"OtherScenario","time":"*"},)" |
| R"({"scenario":"TestScenario","time":"*"},)" |
| R"({"scenario":"TestingScenario","time":"*"}]})")) |
| << "Actual: " << state; |
| } |
| |
| IN_PROC_BROWSER_TEST_F(ChromeTracingDelegateBrowserTest, |
| BackgroundTracingThrottleTimeElapsed) { |
| std::string state = GetSessionStateJson(); |
| EXPECT_EQ(state, "{}"); |
| |
| base::Time upload_time = base::Time::Now() - base::Days(8); |
| ChromeTracingDelegate::ScenarioUploadTimestampMap upload_times; |
| upload_times["TestScenario"] = upload_time; |
| ChromeTracingDelegate::BackgroundTracingStateManager::SaveState( |
| upload_times, |
| ChromeTracingDelegate::BackgroundTracingState::NOT_ACTIVATED); |
| |
| EXPECT_TRUE(StartPreemptiveScenario( |
| content::BackgroundTracingManager::NO_DATA_FILTERING)); |
| state = GetSessionStateJson(); |
| // Older entries are discarded. |
| EXPECT_EQ(state, R"({"state":1,"upload_times":[]})"); |
| } |
| |
| // Test how crash scenarios behave when uploads are throttled: tracing starts if |
| // a crash scenario exists, and the trace is uploaded if the crash scenario is |
| // triggered. |
| IN_PROC_BROWSER_TEST_F(ChromeTracingDelegateBrowserTest, |
| BackgroundTracingCrashScenarioNotThrottled) { |
| EXPECT_TRUE(StartPreemptiveScenario( |
| content::BackgroundTracingManager::NO_DATA_FILTERING)); |
| |
| TriggerPreemptiveScenario(base::OnceClosure()); |
| |
| WaitForUpload(); |
| EXPECT_EQ(get_receive_count(), 1); |
| |
| content::BackgroundTracingManager::GetInstance()->AbortScenarioForTesting(); |
| base::RunLoop wait_for_abort; |
| content::BackgroundTracingManager::GetInstance()->WhenIdle( |
| wait_for_abort.QuitClosure()); |
| wait_for_abort.Run(); |
| |
| EXPECT_FALSE( |
| content::BackgroundTracingManager::GetInstance()->HasActiveScenario()); |
| |
| // We should immediately be able to start a new scenario that includes a |
| // crash scenario. |
| EXPECT_TRUE(StartPreemptiveScenarioWithCrash( |
| content::BackgroundTracingManager::NO_DATA_FILTERING)); |
| TriggerPreemptiveScenarioWithCrash(base::OnceClosure()); |
| |
| WaitForUpload(); |
| EXPECT_EQ(get_receive_count(), 2); |
| } |
| |
| // Test how crash scenarios behave when uploads are throttled: tracing starts if |
| // a crash scenario exists, but if a different scenario is triggered the upload |
| // should still be throttled. |
| IN_PROC_BROWSER_TEST_F(ChromeTracingDelegateBrowserTest, |
| BackgroundTracingCrashScenarioUploadThrottled) { |
| EXPECT_TRUE(StartPreemptiveScenario( |
| content::BackgroundTracingManager::NO_DATA_FILTERING)); |
| |
| TriggerPreemptiveScenario(base::OnceClosure()); |
| |
| WaitForUpload(); |
| EXPECT_EQ(get_receive_count(), 1); |
| |
| content::BackgroundTracingManager::GetInstance()->AbortScenarioForTesting(); |
| base::RunLoop wait_for_abort; |
| content::BackgroundTracingManager::GetInstance()->WhenIdle( |
| wait_for_abort.QuitClosure()); |
| wait_for_abort.Run(); |
| |
| EXPECT_FALSE( |
| content::BackgroundTracingManager::GetInstance()->HasActiveScenario()); |
| |
| // We should immediately be able to start a new scenario that includes a |
| // crash scenario. |
| EXPECT_TRUE(StartPreemptiveScenarioWithCrash( |
| content::BackgroundTracingManager::NO_DATA_FILTERING)); |
| |
| base::RunLoop wait_for_finalization_start; |
| TriggerPreemptiveScenario(wait_for_finalization_start.QuitClosure()); |
| wait_for_finalization_start.Run(); |
| |
| EXPECT_EQ(get_started_finalizations(), 1); |
| EXPECT_FALSE(get_last_started_finalization_success()); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(ChromeTracingDelegateBrowserTest, |
| BackgroundTracingUnexpectedSessionEnd) { |
| std::string state = GetSessionStateJson(); |
| EXPECT_EQ(state, "{}"); |
| |
| ChromeTracingDelegate::ScenarioUploadTimestampMap upload_times; |
| ChromeTracingDelegate::BackgroundTracingStateManager::SaveState( |
| upload_times, ChromeTracingDelegate::BackgroundTracingState::STARTED); |
| |
| EXPECT_FALSE(StartPreemptiveScenario( |
| content::BackgroundTracingManager::NO_DATA_FILTERING)); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(ChromeTracingDelegateBrowserTest, |
| BackgroundTracingSessionRanLong) { |
| std::string state = GetSessionStateJson(); |
| EXPECT_EQ(state, "{}"); |
| |
| ChromeTracingDelegate::ScenarioUploadTimestampMap upload_times; |
| ChromeTracingDelegate::BackgroundTracingStateManager::SaveState( |
| upload_times, |
| ChromeTracingDelegate::BackgroundTracingState::RAN_30_SECONDS); |
| |
| EXPECT_TRUE(StartPreemptiveScenario( |
| content::BackgroundTracingManager::NO_DATA_FILTERING)); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(ChromeTracingDelegateBrowserTest, |
| BackgroundTracingFinalizationStarted) { |
| std::string state = GetSessionStateJson(); |
| EXPECT_EQ(state, "{}"); |
| |
| ChromeTracingDelegate::ScenarioUploadTimestampMap upload_times; |
| ChromeTracingDelegate::BackgroundTracingStateManager::SaveState( |
| upload_times, |
| ChromeTracingDelegate::BackgroundTracingState::FINALIZATION_STARTED); |
| |
| EXPECT_TRUE(StartPreemptiveScenario( |
| content::BackgroundTracingManager::NO_DATA_FILTERING)); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(ChromeTracingDelegateBrowserTest, |
| BackgroundTracingFinalizationBefore30Seconds) { |
| std::string state = GetSessionStateJson(); |
| EXPECT_EQ(state, "{}"); |
| |
| ChromeTracingDelegate::ScenarioUploadTimestampMap upload_times; |
| ChromeTracingDelegate::BackgroundTracingStateManager::SaveState( |
| upload_times, |
| ChromeTracingDelegate::BackgroundTracingState::FINALIZATION_STARTED); |
| |
| // State does not update from finalization started to ran 30 seconds. |
| ChromeTracingDelegate::BackgroundTracingStateManager::SaveState( |
| upload_times, |
| ChromeTracingDelegate::BackgroundTracingState::RAN_30_SECONDS); |
| state = GetSessionStateJson(); |
| EXPECT_EQ(state, R"({"state":2,"upload_times":[]})"); |
| } |
| |
| // If we need a PII-stripped trace, any existing OTR session should block the |
| // trace. |
| IN_PROC_BROWSER_TEST_F(ChromeTracingDelegateBrowserTest, |
| ExistingIncognitoSessionBlockingTraceStart) { |
| EXPECT_TRUE(chrome::ExecuteCommand(browser(), IDC_NEW_INCOGNITO_WINDOW)); |
| EXPECT_TRUE(BrowserList::IsOffTheRecordBrowserActive()); |
| EXPECT_FALSE(StartPreemptiveScenario( |
| content::BackgroundTracingManager::ANONYMIZE_DATA)); |
| } |
| |
| // If we need a PII-stripped trace, OTR sessions that ended before tracing |
| // should block the trace (because traces could theoretically include stale |
| // memory from those sessions). |
| IN_PROC_BROWSER_TEST_F(ChromeTracingDelegateBrowserTest, |
| FinishedIncognitoSessionBlockingTraceStart) { |
| Browser* incognito_browser = CreateIncognitoBrowser(browser()->profile()); |
| EXPECT_TRUE(BrowserList::IsOffTheRecordBrowserActive()); |
| CloseBrowserSynchronously(incognito_browser); |
| EXPECT_FALSE(BrowserList::IsOffTheRecordBrowserActive()); |
| } |
| |
| // If we need a PII-stripped trace, any new OTR session during tracing should |
| // block the finalization of the trace. |
| IN_PROC_BROWSER_TEST_F(ChromeTracingDelegateBrowserTest, |
| NewIncognitoSessionBlockingTraceFinalization) { |
| EXPECT_TRUE(StartPreemptiveScenario( |
| content::BackgroundTracingManager::ANONYMIZE_DATA)); |
| |
| EXPECT_TRUE(chrome::ExecuteCommand(browser(), IDC_NEW_INCOGNITO_WINDOW)); |
| EXPECT_TRUE(BrowserList::IsOffTheRecordBrowserActive()); |
| |
| base::RunLoop wait_for_finalization_start; |
| TriggerPreemptiveScenario(wait_for_finalization_start.QuitClosure()); |
| wait_for_finalization_start.Run(); |
| |
| EXPECT_TRUE(get_started_finalizations() == 1); |
| EXPECT_FALSE(get_last_started_finalization_success()); |
| } |
| |
| // If we need a PII-stripped trace, any OTR session that starts and ends during |
| // tracing should block the finalization of the trace. |
| IN_PROC_BROWSER_TEST_F(ChromeTracingDelegateBrowserTest, |
| ShortIncognitoSessionBlockingTraceFinalization) { |
| EXPECT_TRUE(StartPreemptiveScenario( |
| content::BackgroundTracingManager::ANONYMIZE_DATA)); |
| |
| Browser* incognito_browser = CreateIncognitoBrowser(browser()->profile()); |
| EXPECT_TRUE(BrowserList::IsOffTheRecordBrowserActive()); |
| CloseBrowserSynchronously(incognito_browser); |
| EXPECT_FALSE(BrowserList::IsOffTheRecordBrowserActive()); |
| |
| base::RunLoop wait_for_finalization_start; |
| TriggerPreemptiveScenario(wait_for_finalization_start.QuitClosure()); |
| wait_for_finalization_start.Run(); |
| |
| EXPECT_TRUE(get_started_finalizations() == 1); |
| EXPECT_FALSE(get_last_started_finalization_success()); |
| } |
| |
| namespace { |
| static const char* const kDefaultConfigText = R"({ |
| "mode": "PREEMPTIVE_TRACING_MODE", |
| "scenario_name": "TestScenario", |
| "custom_categories": "base,toplevel", |
| "configs": [{"rule": "MONITOR_AND_DUMP_WHEN_TRIGGER_NAMED", |
| "trigger_name": "test"}] |
| })"; |
| } // namespace |
| |
| class ChromeTracingDelegateBrowserTestOnStartup |
| : public ChromeTracingDelegateBrowserTest { |
| protected: |
| ChromeTracingDelegateBrowserTestOnStartup() {} |
| |
| static std::string FieldTrialConfigTextFilter( |
| const std::string& config_text) { |
| // We need to replace the config JSON with the full one here, as we can't |
| // pass JSON through the fieldtrial switch parsing. |
| if (config_text == "default_config_for_testing") { |
| return kDefaultConfigText; |
| } |
| return config_text; |
| } |
| |
| void SetUpCommandLine(base::CommandLine* command_line) override { |
| variations::testing::VariationParamsManager::AppendVariationParams( |
| "BackgroundTracing", "TestGroup", |
| {{"config", "default_config_for_testing"}}, command_line); |
| } |
| |
| void CreatedBrowserMainParts( |
| content::BrowserMainParts* browser_main_parts) override { |
| content::BackgroundTracingManager::GetInstance() |
| ->SetConfigTextFilterForTesting( |
| base::BindRepeating(&FieldTrialConfigTextFilter)); |
| } |
| }; |
| |
| IN_PROC_BROWSER_TEST_F(ChromeTracingDelegateBrowserTestOnStartup, |
| PRE_ScenarioSetFromFieldtrial) { |
| // This test would enable tracing and shutdown browser before 30 seconds |
| // elapses. So, the profile would store incomplete state for next session. |
| EXPECT_TRUE( |
| content::BackgroundTracingManager::GetInstance()->HasActiveScenario()); |
| // State 1 = STARTED. |
| EXPECT_EQ(GetSessionStateJson(), R"({"state":1,"upload_times":[]})"); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(ChromeTracingDelegateBrowserTestOnStartup, |
| ScenarioSetFromFieldtrial) { |
| // Scenario should be inactive even though we have a config because last |
| // session shut down unexpectedly. |
| EXPECT_FALSE( |
| content::BackgroundTracingManager::GetInstance()->HasActiveScenario()); |
| // State 0 = NOT_ACTIVATED, current session is inactive. |
| EXPECT_EQ(GetSessionStateJson(), R"({"state":0,"upload_times":[]})"); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(ChromeTracingDelegateBrowserTestOnStartup, |
| PRE_StartupTracingThrottle) { |
| EXPECT_TRUE( |
| content::BackgroundTracingManager::GetInstance()->HasActiveScenario()); |
| EXPECT_EQ(GetSessionStateJson(), R"({"state":1,"upload_times":[]})"); |
| |
| TriggerPreemptiveScenario(base::OnceClosure()); |
| |
| // This updates the upload time for the test scenario to current time. |
| WaitForUpload(); |
| EXPECT_TRUE(get_receive_count() == 1); |
| |
| std::string state = GetSessionStateJson(); |
| EXPECT_TRUE(base::MatchPattern( |
| state, |
| R"({"state":3,"upload_times":[{"scenario":"TestScenario","time":"*"}]})")) |
| << "Actual: " << state; |
| } |
| |
| IN_PROC_BROWSER_TEST_F(ChromeTracingDelegateBrowserTestOnStartup, |
| StartupTracingThrottle) { |
| // The startup scenario should *not* be started, since not enough |
| // time has elapsed since the last upload (set in the PRE_ above). |
| EXPECT_FALSE( |
| content::BackgroundTracingManager::GetInstance()->HasActiveScenario()); |
| std::string state = GetSessionStateJson(); |
| EXPECT_TRUE(base::MatchPattern( |
| state, |
| R"({"state":0,"upload_times":[{"scenario":"TestScenario","time":"*"}]})")) |
| << "Actual: " << state; |
| } |
| |
| class ChromeTracingDelegateBrowserTestFromCommandLine |
| : public ChromeTracingDelegateBrowserTest { |
| protected: |
| void SetUpCommandLine(base::CommandLine* command_line) override { |
| ChromeTracingDelegateBrowserTest::SetUpCommandLine(command_line); |
| ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); |
| |
| base::FilePath config_path( |
| temp_dir_.GetPath().Append(FILE_PATH_LITERAL("config.json"))); |
| ASSERT_TRUE(base::WriteFile(config_path, kDefaultConfigText)); |
| command_line->AppendSwitchPath("enable-background-tracing", config_path); |
| |
| output_path_ = base::FilePath( |
| temp_dir_.GetPath().Append(FILE_PATH_LITERAL("output.perfetto.gz"))); |
| command_line->AppendSwitchPath("background-tracing-output-file", |
| output_path_); |
| } |
| |
| bool OutputPathExists() const { |
| base::ScopedAllowBlockingForTesting allow_blocking; |
| return base::PathExists(output_path_); |
| } |
| |
| void TriggerScenarioAndWaitForOutput() { |
| base::ScopedAllowBlockingForTesting allow_blocking; |
| |
| // Wait for the output file to appear instead of for the trigger callback |
| // (which just means the data is ready to write). |
| base::FilePathWatcher output_watcher; |
| base::RunLoop run_loop; |
| output_watcher.Watch( |
| output_path_, base::FilePathWatcher::Type::kNonRecursive, |
| base::BindLambdaForTesting( |
| [&run_loop](const base::FilePath&, bool) { run_loop.Quit(); })); |
| TriggerPreemptiveScenario(base::OnceClosure()); |
| run_loop.Run(); |
| } |
| |
| private: |
| base::ScopedTempDir temp_dir_; |
| base::FilePath output_path_; |
| }; |
| |
| IN_PROC_BROWSER_TEST_F(ChromeTracingDelegateBrowserTestFromCommandLine, |
| ScenarioFromCommandLine) { |
| ASSERT_FALSE(OutputPathExists()); |
| |
| EXPECT_TRUE( |
| content::BackgroundTracingManager::GetInstance()->HasActiveScenario()); |
| // State 1 = STARTED. |
| EXPECT_EQ(GetSessionStateJson(), R"({"state":1,"upload_times":[]})"); |
| |
| // The scenario should also be "uploaded" (actually written to the output |
| // file). |
| TriggerScenarioAndWaitForOutput(); |
| EXPECT_TRUE(OutputPathExists()); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(ChromeTracingDelegateBrowserTestFromCommandLine, |
| PRE_IgnoreThrottle) { |
| EXPECT_TRUE( |
| content::BackgroundTracingManager::GetInstance()->HasActiveScenario()); |
| EXPECT_EQ(GetSessionStateJson(), R"({"state":1,"upload_times":[]})"); |
| |
| // This updates the upload time for the test scenario to the current time, |
| // even though the output is actually written to a file. |
| TriggerScenarioAndWaitForOutput(); |
| EXPECT_TRUE(OutputPathExists()); |
| |
| std::string state = GetSessionStateJson(); |
| EXPECT_TRUE(base::MatchPattern( |
| state, |
| R"({"state":3,"upload_times":[{"scenario":"TestScenario","time":"*"}]})")) |
| << "Actual: " << state; |
| } |
| |
| IN_PROC_BROWSER_TEST_F(ChromeTracingDelegateBrowserTestFromCommandLine, |
| IgnoreThrottle) { |
| // The scenario from the command-line should be started even though not |
| // enough time has elapsed since the last upload (set in the PRE_ above). |
| ASSERT_FALSE(OutputPathExists()); |
| |
| EXPECT_TRUE( |
| content::BackgroundTracingManager::GetInstance()->HasActiveScenario()); |
| // State 1 = STARTED. |
| std::string state = GetSessionStateJson(); |
| EXPECT_TRUE(base::MatchPattern( |
| state, |
| R"({"state":1,"upload_times":[{"scenario":"TestScenario","time":"*"}]})")) |
| << "Actual: " << state; |
| |
| // The scenario should also be "uploaded" (actually written to the output |
| // file). |
| TriggerScenarioAndWaitForOutput(); |
| EXPECT_TRUE(OutputPathExists()); |
| } |