diff options
author | Torne (Richard Coles) <torne@google.com> | 2014-08-12 13:47:38 +0100 |
---|---|---|
committer | Torne (Richard Coles) <torne@google.com> | 2014-08-12 13:47:38 +0100 |
commit | 5f1c94371a64b3196d4be9466099bb892df9b88e (patch) | |
tree | 60a287ed27d1328d7806d12433d789b66ad91805 /chrome/test | |
parent | 43165a58c6167882aabb62f470c4e4d21f807d79 (diff) | |
download | chromium_org-5f1c94371a64b3196d4be9466099bb892df9b88e.tar.gz |
Merge from Chromium at DEPS revision 288042
This commit was generated by merge_to_master.py.
Change-Id: I583602ff16d735199f1810565c9296e970ce2854
Diffstat (limited to 'chrome/test')
56 files changed, 917 insertions, 366 deletions
diff --git a/chrome/test/android/unit_tests_apk/AndroidManifest.xml b/chrome/test/android/unit_tests_apk/AndroidManifest.xml index 43b015e272..ac76d61864 100644 --- a/chrome/test/android/unit_tests_apk/AndroidManifest.xml +++ b/chrome/test/android/unit_tests_apk/AndroidManifest.xml @@ -10,7 +10,7 @@ found in the LICENSE file. android:versionCode="1" android:versionName="1.0"> - <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="19" /> + <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="20" /> <application android:label="ChromeNativeTests" android:name="org.chromium.chrome.unit_tests_apk.ChromeNativeTestApplication"> diff --git a/chrome/test/base/extension_load_waiter_one_shot.cc b/chrome/test/base/extension_load_waiter_one_shot.cc index 5da086e1b8..ccd3661006 100644 --- a/chrome/test/base/extension_load_waiter_one_shot.cc +++ b/chrome/test/base/extension_load_waiter_one_shot.cc @@ -25,7 +25,7 @@ void ExtensionLoadWaiterOneShot::WaitForExtension(const char* extension_id, extension_id_ = extension_id; load_looper_ = new content::MessageLoopRunner(); registrar_.Add(this, - chrome::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING, + extensions::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING, content::NotificationService::AllSources()); load_cb.Run(); load_looper_->Run(); @@ -35,15 +35,16 @@ void ExtensionLoadWaiterOneShot::Observe(int type, const content::NotificationSource& source, const content::NotificationDetails& details) { switch (type) { - case chrome::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING: { + case extensions::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING: { extensions::ExtensionHost* host = content::Details<extensions::ExtensionHost>(details).ptr(); if (host->extension_id() == extension_id_) { browser_context_ = host->browser_context(); CHECK(browser_context_); - registrar_.Remove(this, - chrome::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING, - content::NotificationService::AllSources()); + registrar_.Remove( + this, + extensions::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING, + content::NotificationService::AllSources()); load_looper_->Quit(); } break; diff --git a/chrome/test/base/in_process_browser_test.cc b/chrome/test/base/in_process_browser_test.cc index c6811cec5a..9fa29b50bb 100644 --- a/chrome/test/base/in_process_browser_test.cc +++ b/chrome/test/base/in_process_browser_test.cc @@ -432,7 +432,7 @@ void InProcessBrowserTest::RunTestOnMainThreadLoop() { // Invoke cleanup and quit even if there are failures. This is similar to // gtest in that it invokes TearDown even if Setup fails. - CleanUpOnMainThread(); + TearDownOnMainThread(); #if defined(OS_MACOSX) autorelease_pool_->Recycle(); #endif diff --git a/chrome/test/base/in_process_browser_test.h b/chrome/test/base/in_process_browser_test.h index 925846eb03..b0217d90cd 100644 --- a/chrome/test/base/in_process_browser_test.h +++ b/chrome/test/base/in_process_browser_test.h @@ -66,7 +66,7 @@ class ContentRendererClient; // related to the browser object and associated window, like opening a new Tab // with a testing page loaded. // -// CleanUpOnMainThread() is called just after executing the real test code to +// TearDownOnMainThread() is called just after executing the real test code to // do necessary cleanup before the browser is torn down. // // TearDownInProcessBrowserTestFixture() is called after BrowserMain() exits to @@ -122,10 +122,6 @@ class InProcessBrowserTest : public content::BrowserTestBase { // successful. virtual bool SetUpUserDataDirectory() WARN_UNUSED_RESULT; - // Override this to add any custom cleanup code that needs to be done on the - // main thread before the browser is torn down. - virtual void CleanUpOnMainThread() {} - // BrowserTestBase: virtual void RunTestOnMainThreadLoop() OVERRIDE; diff --git a/chrome/test/base/test_browser_window.h b/chrome/test/base/test_browser_window.h index 5e33fede9a..b1d9fd5b71 100644 --- a/chrome/test/base/test_browser_window.h +++ b/chrome/test/base/test_browser_window.h @@ -105,9 +105,11 @@ class TestBrowserWindow : public BrowserWindow { virtual void ShowBookmarkAppBubble( const WebApplicationInfo& web_app_info, const std::string& extension_id) OVERRIDE {} - virtual void ShowTranslateBubble(content::WebContents* contents, - translate::TranslateStep step, - TranslateErrors::Type error_type) OVERRIDE {} + virtual void ShowTranslateBubble( + content::WebContents* contents, + translate::TranslateStep step, + translate::TranslateErrors::Type error_type, + bool is_user_gesture) OVERRIDE {} #if defined(ENABLE_ONE_CLICK_SIGNIN) virtual void ShowOneClickSigninBubble( OneClickSigninBubbleType type, diff --git a/chrome/test/base/test_chrome_web_ui_controller_factory_browsertest.cc b/chrome/test/base/test_chrome_web_ui_controller_factory_browsertest.cc index c58eace1c1..4449b3f160 100644 --- a/chrome/test/base/test_chrome_web_ui_controller_factory_browsertest.cc +++ b/chrome/test/base/test_chrome_web_ui_controller_factory_browsertest.cc @@ -52,7 +52,7 @@ class TestChromeWebUIControllerFactoryTest : public InProcessBrowserTest { GURL(kChromeTestChromeWebUIControllerFactory).host(), &mock_provider_); } - virtual void CleanUpOnMainThread() OVERRIDE { + virtual void TearDownOnMainThread() OVERRIDE { test_factory_->RemoveFactoryOverride( GURL(kChromeTestChromeWebUIControllerFactory).host()); content::WebUIControllerFactory::UnregisterFactoryForTesting( diff --git a/chrome/test/base/testing_browser_process.cc b/chrome/test/base/testing_browser_process.cc index ebcfa8056b..4ab486da4a 100644 --- a/chrome/test/base/testing_browser_process.cc +++ b/chrome/test/base/testing_browser_process.cc @@ -8,13 +8,13 @@ #include "base/strings/string_util.h" #include "base/time/default_tick_clock.h" #include "build/build_config.h" -#include "chrome/browser/apps/chrome_apps_client.h" #include "chrome/browser/background/background_mode_manager.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process_impl.h" #include "chrome/browser/extensions/chrome_extensions_browser_client.h" #include "chrome/browser/printing/print_job_manager.h" #include "chrome/browser/profiles/profile_manager.h" +#include "chrome/browser/ui/apps/chrome_apps_client.h" #include "chrome/test/base/testing_browser_process_platform_part.h" #include "components/network_time/network_time_tracker.h" #include "content/public/browser/notification_service.h" diff --git a/chrome/test/base/testing_profile.cc b/chrome/test/base/testing_profile.cc index be72393f90..d49df37d25 100644 --- a/chrome/test/base/testing_profile.cc +++ b/chrome/test/base/testing_profile.cc @@ -19,7 +19,6 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/content_settings/host_content_settings_map.h" -#include "chrome/browser/extensions/extension_special_storage_policy.h" #include "chrome/browser/extensions/extension_system_factory.h" #include "chrome/browser/extensions/test_extension_system.h" #include "chrome/browser/favicon/chrome_favicon_client_factory.h" @@ -84,6 +83,7 @@ #endif // defined(ENABLE_CONFIGURATION_POLICY) #if defined(ENABLE_EXTENSIONS) +#include "chrome/browser/extensions/extension_special_storage_policy.h" #include "chrome/browser/guest_view/guest_view_manager.h" #include "extensions/browser/extension_system.h" #endif @@ -138,7 +138,9 @@ class TestExtensionURLRequestContext : public net::URLRequestContext { set_cookie_store(cookie_monster); } - virtual ~TestExtensionURLRequestContext() {} + virtual ~TestExtensionURLRequestContext() { + AssertNoURLRequests(); + } }; class TestExtensionURLRequestContextGetter @@ -242,7 +244,9 @@ TestingProfile::TestingProfile(const base::FilePath& path, TestingProfile::TestingProfile( const base::FilePath& path, Delegate* delegate, +#if defined(ENABLE_EXTENSIONS) scoped_refptr<ExtensionSpecialStoragePolicy> extension_policy, +#endif scoped_ptr<PrefServiceSyncable> prefs, bool incognito, bool guest_session, @@ -258,7 +262,9 @@ TestingProfile::TestingProfile( guest_session_(guest_session), supervised_user_id_(supervised_user_id), last_session_exited_cleanly_(true), +#if defined(ENABLE_EXTENSIONS) extension_special_storage_policy_(extension_policy), +#endif profile_path_(path), browser_context_dependency_manager_( BrowserContextDependencyManager::GetInstance()), @@ -656,16 +662,22 @@ bool TestingProfile::IsSupervised() { return !supervised_user_id_.empty(); } +#if defined(ENABLE_EXTENSIONS) void TestingProfile::SetExtensionSpecialStoragePolicy( ExtensionSpecialStoragePolicy* extension_special_storage_policy) { extension_special_storage_policy_ = extension_special_storage_policy; } +#endif ExtensionSpecialStoragePolicy* TestingProfile::GetExtensionSpecialStoragePolicy() { +#if defined(ENABLE_EXTENSIONS) if (!extension_special_storage_policy_.get()) extension_special_storage_policy_ = new ExtensionSpecialStoragePolicy(NULL); return extension_special_storage_policy_.get(); +#else + return NULL; +#endif } net::CookieMonster* TestingProfile::GetCookieMonster() { @@ -849,7 +861,10 @@ void TestingProfile::BlockUntilHistoryProcessesPendingRequests() { DCHECK(base::MessageLoop::current()); base::CancelableTaskTracker tracker; - history_service->ScheduleDBTask(new QuittingHistoryDBTask(), &tracker); + history_service->ScheduleDBTask( + scoped_ptr<history::HistoryDBTask>( + new QuittingHistoryDBTask()), + &tracker); base::MessageLoop::current()->Run(); } @@ -878,7 +893,15 @@ PrefService* TestingProfile::GetOffTheRecordPrefs() { } quota::SpecialStoragePolicy* TestingProfile::GetSpecialStoragePolicy() { +#if defined(ENABLE_EXTENSIONS) return GetExtensionSpecialStoragePolicy(); +#else + return NULL; +#endif +} + +content::SSLHostStateDelegate* TestingProfile::GetSSLHostStateDelegate() { + return NULL; } bool TestingProfile::WasCreatedByVersionOrLater(const std::string& version) { @@ -911,10 +934,12 @@ void TestingProfile::Builder::SetDelegate(Delegate* delegate) { delegate_ = delegate; } +#if defined(ENABLE_EXTENSIONS) void TestingProfile::Builder::SetExtensionSpecialStoragePolicy( scoped_refptr<ExtensionSpecialStoragePolicy> policy) { extension_policy_ = policy; } +#endif void TestingProfile::Builder::SetPrefService( scoped_ptr<PrefServiceSyncable> prefs) { @@ -952,7 +977,9 @@ scoped_ptr<TestingProfile> TestingProfile::Builder::Build() { return scoped_ptr<TestingProfile>(new TestingProfile( path_, delegate_, +#if defined(ENABLE_EXTENSIONS) extension_policy_, +#endif pref_service_.Pass(), incognito_, guest_session_, diff --git a/chrome/test/base/testing_profile.h b/chrome/test/base/testing_profile.h index 97e4d19238..272841ccf9 100644 --- a/chrome/test/base/testing_profile.h +++ b/chrome/test/base/testing_profile.h @@ -16,6 +16,7 @@ namespace content { class MockResourceContext; +class SSLHostStateDelegate; } namespace history { @@ -83,10 +84,12 @@ class TestingProfile : public Profile { BrowserContextKeyedServiceFactory* service_factory, BrowserContextKeyedServiceFactory::TestingFactoryFunction callback); +#if defined(ENABLE_EXTENSIONS) // Sets the ExtensionSpecialStoragePolicy to be returned by // GetExtensionSpecialStoragePolicy(). void SetExtensionSpecialStoragePolicy( scoped_refptr<ExtensionSpecialStoragePolicy> policy); +#endif // Sets the path to the directory to be used to hold profile data. void SetPath(const base::FilePath& path); @@ -116,7 +119,9 @@ class TestingProfile : public Profile { // Various staging variables where values are held until Build() is invoked. scoped_ptr<PrefServiceSyncable> pref_service_; +#if defined(ENABLE_EXTENSIONS) scoped_refptr<ExtensionSpecialStoragePolicy> extension_policy_; +#endif base::FilePath path_; Delegate* delegate_; bool incognito_; @@ -145,7 +150,9 @@ class TestingProfile : public Profile { // Callers should use Builder::Build() instead of invoking this constructor. TestingProfile(const base::FilePath& path, Delegate* delegate, +#if defined(ENABLE_EXTENSIONS) scoped_refptr<ExtensionSpecialStoragePolicy> extension_policy, +#endif scoped_ptr<PrefServiceSyncable> prefs, bool incognito, bool guest_session, @@ -218,6 +225,7 @@ class TestingProfile : public Profile { virtual content::BrowserPluginGuestManager* GetGuestManager() OVERRIDE; virtual quota::SpecialStoragePolicy* GetSpecialStoragePolicy() OVERRIDE; virtual content::PushMessagingService* GetPushMessagingService() OVERRIDE; + virtual content::SSLHostStateDelegate* GetSSLHostStateDelegate() OVERRIDE; virtual TestingProfile* AsTestingProfile() OVERRIDE; @@ -242,7 +250,6 @@ class TestingProfile : public Profile { force_incognito_ = force_incognito; } - // Assumes ownership. virtual void SetOffTheRecordProfile(scoped_ptr<Profile> profile); virtual void SetOriginalProfile(Profile* profile); virtual Profile* GetOffTheRecordProfile() OVERRIDE; @@ -250,8 +257,10 @@ class TestingProfile : public Profile { virtual bool HasOffTheRecordProfile() OVERRIDE; virtual Profile* GetOriginalProfile() OVERRIDE; virtual bool IsSupervised() OVERRIDE; +#if defined(ENABLE_EXTENSIONS) void SetExtensionSpecialStoragePolicy( ExtensionSpecialStoragePolicy* extension_special_storage_policy); +#endif virtual ExtensionSpecialStoragePolicy* GetExtensionSpecialStoragePolicy() OVERRIDE; // TODO(ajwong): Remove this API in favor of directly retrieving the @@ -365,8 +374,10 @@ class TestingProfile : public Profile { base::FilePath last_selected_directory_; scoped_refptr<history::TopSites> top_sites_; // For history and thumbnails. +#if defined(ENABLE_EXTENSIONS) scoped_refptr<ExtensionSpecialStoragePolicy> extension_special_storage_policy_; +#endif // The proxy prefs tracker. scoped_ptr<PrefProxyConfigTracker> pref_proxy_config_tracker_; diff --git a/chrome/test/base/tracing.cc b/chrome/test/base/tracing.cc index 87e6aaa343..03a53f1e1d 100644 --- a/chrome/test/base/tracing.cc +++ b/chrome/test/base/tracing.cc @@ -4,6 +4,7 @@ #include "chrome/test/base/tracing.h" +#include "base/debug/trace_event.h" #include "base/file_util.h" #include "base/files/file_path.h" #include "base/memory/singleton.h" @@ -32,7 +33,8 @@ class InProcessTraceController { bool BeginTracing(const std::string& category_patterns) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); return content::TracingController::GetInstance()->EnableRecording( - category_patterns, content::TracingController::DEFAULT_OPTIONS, + base::debug::CategoryFilter(category_patterns), + base::debug::TraceOptions(), content::TracingController::EnableRecordingDoneCallback()); } @@ -50,7 +52,8 @@ class InProcessTraceController { return false; } if (!content::TracingController::GetInstance()->EnableRecording( - category_patterns, content::TracingController::DEFAULT_OPTIONS, + base::debug::CategoryFilter(category_patterns), + base::debug::TraceOptions(), base::Bind(&InProcessTraceController::OnEnableTracingComplete, base::Unretained(this)))) { return false; diff --git a/chrome/test/base/web_ui_browser_test.cc b/chrome/test/base/web_ui_browser_test.cc index 7451f2bf9f..cf9a2aa645 100644 --- a/chrome/test/base/web_ui_browser_test.cc +++ b/chrome/test/base/web_ui_browser_test.cc @@ -382,7 +382,7 @@ void WebUIBrowserTest::SetUpOnMainThread() { mock_provider_.Pointer()); } -void WebUIBrowserTest::CleanUpOnMainThread() { +void WebUIBrowserTest::TearDownOnMainThread() { logging::SetLogMessageHandler(NULL); test_factory_->RemoveFactoryOverride(GURL(kDummyURL).host()); diff --git a/chrome/test/base/web_ui_browser_test.h b/chrome/test/base/web_ui_browser_test.h index 9aff3c221f..3220442553 100644 --- a/chrome/test/base/web_ui_browser_test.h +++ b/chrome/test/base/web_ui_browser_test.h @@ -113,7 +113,7 @@ class WebUIBrowserTest : public JavaScriptBrowserTest { // Set up & tear down console error catching. virtual void SetUpOnMainThread() OVERRIDE; - virtual void CleanUpOnMainThread() OVERRIDE; + virtual void TearDownOnMainThread() OVERRIDE; // Set a WebUI instance to run tests on. void SetWebUIInstance(content::WebUI* web_ui); diff --git a/chrome/test/chromedriver/alert_commands.cc b/chrome/test/chromedriver/alert_commands.cc index 199e7bc451..f75e440a51 100644 --- a/chrome/test/chromedriver/alert_commands.cc +++ b/chrome/test/chromedriver/alert_commands.cc @@ -59,7 +59,7 @@ Status ExecuteGetAlertText( web_view->GetJavaScriptDialogManager()->GetDialogMessage(&message); if (status.IsError()) return status; - value->reset(base::Value::CreateStringValue(message)); + value->reset(new base::StringValue(message)); return Status(kOk); } diff --git a/chrome/test/chromedriver/capabilities.cc b/chrome/test/chromedriver/capabilities.cc index b30e871d4b..ad11603a46 100644 --- a/chrome/test/chromedriver/capabilities.cc +++ b/chrome/test/chromedriver/capabilities.cc @@ -302,6 +302,48 @@ Status ParseLoggingPrefs(const base::Value& option, return Status(kOk); } +Status ParseInspectorDomainStatus( + PerfLoggingPrefs::InspectorDomainStatus* to_set, + const base::Value& option, + Capabilities* capabilities) { + bool desired_value; + if (!option.GetAsBoolean(&desired_value)) + return Status(kUnknownError, "must be a boolean"); + if (desired_value) + *to_set = PerfLoggingPrefs::InspectorDomainStatus::kExplicitlyEnabled; + else + *to_set = PerfLoggingPrefs::InspectorDomainStatus::kExplicitlyDisabled; + return Status(kOk); +} + +Status ParsePerfLoggingPrefs(const base::Value& option, + Capabilities* capabilities) { + const base::DictionaryValue* perf_logging_prefs = NULL; + if (!option.GetAsDictionary(&perf_logging_prefs)) + return Status(kUnknownError, "must be a dictionary"); + + std::map<std::string, Parser> parser_map; + parser_map["enableNetwork"] = base::Bind( + &ParseInspectorDomainStatus, &capabilities->perf_logging_prefs.network); + parser_map["enablePage"] = base::Bind( + &ParseInspectorDomainStatus, &capabilities->perf_logging_prefs.page); + parser_map["enableTimeline"] = base::Bind( + &ParseInspectorDomainStatus, &capabilities->perf_logging_prefs.timeline); + parser_map["traceCategories"] = base::Bind( + &ParseString, &capabilities->perf_logging_prefs.trace_categories); + + for (base::DictionaryValue::Iterator it(*perf_logging_prefs); !it.IsAtEnd(); + it.Advance()) { + if (parser_map.find(it.key()) == parser_map.end()) + return Status(kUnknownError, "unrecognized performance logging " + "option: " + it.key()); + Status status = parser_map[it.key()].Run(it.value(), capabilities); + if (status.IsError()) + return Status(kUnknownError, "cannot parse " + it.key(), status); + } + return Status(kOk); +} + Status ParseChromeOptions( const base::Value& capability, Capabilities* capabilities) { @@ -318,6 +360,9 @@ Status ParseChromeOptions( parser_map["args"] = base::Bind(&IgnoreCapability); parser_map["binary"] = base::Bind(&IgnoreCapability); parser_map["extensions"] = base::Bind(&IgnoreCapability); + + parser_map["perfLoggingPrefs"] = base::Bind(&ParsePerfLoggingPrefs); + if (is_android) { parser_map["androidActivity"] = base::Bind(&ParseString, &capabilities->android_activity); @@ -473,6 +518,14 @@ std::string Switches::ToString() const { return str; } +PerfLoggingPrefs::PerfLoggingPrefs() + : network(InspectorDomainStatus::kDefaultEnabled), + page(InspectorDomainStatus::kDefaultEnabled), + timeline(InspectorDomainStatus::kDefaultEnabled), + trace_categories() {} + +PerfLoggingPrefs::~PerfLoggingPrefs() {} + Capabilities::Capabilities() : android_use_running_app(false), detach(false), @@ -504,5 +557,16 @@ Status Capabilities::Parse(const base::DictionaryValue& desired_caps) { } } } + // Perf log must be enabled if perf log prefs are specified; otherwise, error. + LoggingPrefs::const_iterator iter = logging_prefs.find( + WebDriverLog::kPerformanceType); + if (iter == logging_prefs.end() || iter->second == Log::kOff) { + const base::DictionaryValue* chrome_options = NULL; + if (desired_caps.GetDictionary("chromeOptions", &chrome_options) && + chrome_options->HasKey("perfLoggingPrefs")) { + return Status(kUnknownError, "perfLoggingPrefs specified, " + "but performance logging was not enabled"); + } + } return Status(kOk); } diff --git a/chrome/test/chromedriver/capabilities.h b/chrome/test/chromedriver/capabilities.h index edef9baeac..b521e44429 100644 --- a/chrome/test/chromedriver/capabilities.h +++ b/chrome/test/chromedriver/capabilities.h @@ -60,6 +60,27 @@ class Switches { typedef std::map<std::string, Log::Level> LoggingPrefs; +struct PerfLoggingPrefs { + PerfLoggingPrefs(); + ~PerfLoggingPrefs(); + + // We must distinguish between a log domain being set by default and being + // explicitly set. Otherwise, |PerformanceLogger| could only handle 3 of 4 + // possible combinations (tracing enabled/disabled + Timeline on/off). + enum InspectorDomainStatus { + kDefaultEnabled, + kDefaultDisabled, + kExplicitlyEnabled, + kExplicitlyDisabled + }; + + InspectorDomainStatus network; + InspectorDomainStatus page; + InspectorDomainStatus timeline; + + std::string trace_categories; // Non-empty string enables tracing. +}; + struct Capabilities { Capabilities(); ~Capabilities(); @@ -114,6 +135,8 @@ struct Capabilities { // If set, enable minidump for chrome crashes and save to this directory. std::string minidump_path; + PerfLoggingPrefs perf_logging_prefs; + scoped_ptr<base::DictionaryValue> prefs; Switches switches; diff --git a/chrome/test/chromedriver/capabilities_unittest.cc b/chrome/test/chromedriver/capabilities_unittest.cc index 7f77fb10bc..e687802626 100644 --- a/chrome/test/chromedriver/capabilities_unittest.cc +++ b/chrome/test/chromedriver/capabilities_unittest.cc @@ -7,6 +7,7 @@ #include "base/values.h" #include "chrome/test/chromedriver/chrome/log.h" #include "chrome/test/chromedriver/chrome/status.h" +#include "chrome/test/chromedriver/logging.h" #include "testing/gtest/include/gtest/gtest.h" TEST(Switches, Empty) { @@ -336,6 +337,92 @@ TEST(ParseCapabilities, LoggingPrefsNotDict) { ASSERT_FALSE(status.IsOk()); } +TEST(ParseCapabilities, PerfLoggingPrefsInspectorDomainStatus) { + Capabilities capabilities; + // Perf log must be enabled if performance log preferences are specified. + base::DictionaryValue logging_prefs; + logging_prefs.SetString(WebDriverLog::kPerformanceType, "INFO"); + base::DictionaryValue desired_caps; + desired_caps.Set("loggingPrefs", logging_prefs.DeepCopy()); + ASSERT_EQ(PerfLoggingPrefs::InspectorDomainStatus::kDefaultEnabled, + capabilities.perf_logging_prefs.network); + ASSERT_EQ(PerfLoggingPrefs::InspectorDomainStatus::kDefaultEnabled, + capabilities.perf_logging_prefs.page); + ASSERT_EQ(PerfLoggingPrefs::InspectorDomainStatus::kDefaultEnabled, + capabilities.perf_logging_prefs.timeline); + base::DictionaryValue perf_logging_prefs; + perf_logging_prefs.SetBoolean("enableNetwork", true); + perf_logging_prefs.SetBoolean("enablePage", false); + desired_caps.Set("chromeOptions.perfLoggingPrefs", + perf_logging_prefs.DeepCopy()); + Status status = capabilities.Parse(desired_caps); + ASSERT_TRUE(status.IsOk()); + ASSERT_EQ(PerfLoggingPrefs::InspectorDomainStatus::kExplicitlyEnabled, + capabilities.perf_logging_prefs.network); + ASSERT_EQ(PerfLoggingPrefs::InspectorDomainStatus::kExplicitlyDisabled, + capabilities.perf_logging_prefs.page); + ASSERT_EQ(PerfLoggingPrefs::InspectorDomainStatus::kDefaultEnabled, + capabilities.perf_logging_prefs.timeline); +} + +TEST(ParseCapabilities, PerfLoggingPrefsTraceCategories) { + Capabilities capabilities; + // Perf log must be enabled if performance log preferences are specified. + base::DictionaryValue logging_prefs; + logging_prefs.SetString(WebDriverLog::kPerformanceType, "INFO"); + base::DictionaryValue desired_caps; + desired_caps.Set("loggingPrefs", logging_prefs.DeepCopy()); + ASSERT_EQ("", capabilities.perf_logging_prefs.trace_categories); + base::DictionaryValue perf_logging_prefs; + perf_logging_prefs.SetString("traceCategories", "benchmark,webkit.console"); + desired_caps.Set("chromeOptions.perfLoggingPrefs", + perf_logging_prefs.DeepCopy()); + Status status = capabilities.Parse(desired_caps); + ASSERT_TRUE(status.IsOk()); + ASSERT_EQ("benchmark,webkit.console", + capabilities.perf_logging_prefs.trace_categories); +} + +TEST(ParseCapabilities, PerfLoggingPrefsNotDict) { + Capabilities capabilities; + // Perf log must be enabled if performance log preferences are specified. + base::DictionaryValue logging_prefs; + logging_prefs.SetString(WebDriverLog::kPerformanceType, "INFO"); + base::DictionaryValue desired_caps; + desired_caps.Set("loggingPrefs", logging_prefs.DeepCopy()); + desired_caps.SetString("chromeOptions.perfLoggingPrefs", "traceCategories"); + Status status = capabilities.Parse(desired_caps); + ASSERT_FALSE(status.IsOk()); +} + +TEST(ParseCapabilities, PerfLoggingPrefsNoPerfLogLevel) { + Capabilities capabilities; + base::DictionaryValue desired_caps; + base::DictionaryValue perf_logging_prefs; + perf_logging_prefs.SetBoolean("enableNetwork", true); + desired_caps.Set("chromeOptions.perfLoggingPrefs", + perf_logging_prefs.DeepCopy()); + // Should fail because perf log must be enabled if perf log prefs specified. + Status status = capabilities.Parse(desired_caps); + ASSERT_FALSE(status.IsOk()); +} + +TEST(ParseCapabilities, PerfLoggingPrefsPerfLogOff) { + Capabilities capabilities; + base::DictionaryValue logging_prefs; + // Disable performance log by setting logging level to OFF. + logging_prefs.SetString(WebDriverLog::kPerformanceType, "OFF"); + base::DictionaryValue desired_caps; + desired_caps.Set("loggingPrefs", logging_prefs.DeepCopy()); + base::DictionaryValue perf_logging_prefs; + perf_logging_prefs.SetBoolean("enableNetwork", true); + desired_caps.Set("chromeOptions.perfLoggingPrefs", + perf_logging_prefs.DeepCopy()); + // Should fail because perf log must be enabled if perf log prefs specified. + Status status = capabilities.Parse(desired_caps); + ASSERT_FALSE(status.IsOk()); +} + TEST(ParseCapabilities, ExcludeSwitches) { Capabilities capabilities; base::ListValue exclude_switches; diff --git a/chrome/test/chromedriver/chrome/chrome_android_impl.cc b/chrome/test/chromedriver/chrome/chrome_android_impl.cc index 9cbbe55783..cccb9b7238 100644 --- a/chrome/test/chromedriver/chrome/chrome_android_impl.cc +++ b/chrome/test/chromedriver/chrome/chrome_android_impl.cc @@ -5,16 +5,19 @@ #include "chrome/test/chromedriver/chrome/chrome_android_impl.h" #include "chrome/test/chromedriver/chrome/device_manager.h" +#include "chrome/test/chromedriver/chrome/devtools_client.h" #include "chrome/test/chromedriver/chrome/devtools_http_client.h" #include "chrome/test/chromedriver/chrome/status.h" #include "chrome/test/chromedriver/net/port_server.h" ChromeAndroidImpl::ChromeAndroidImpl( - scoped_ptr<DevToolsHttpClient> client, + scoped_ptr<DevToolsHttpClient> http_client, + scoped_ptr<DevToolsClient> websocket_client, ScopedVector<DevToolsEventListener>& devtools_event_listeners, scoped_ptr<PortReservation> port_reservation, scoped_ptr<Device> device) - : ChromeImpl(client.Pass(), + : ChromeImpl(http_client.Pass(), + websocket_client.Pass(), devtools_event_listeners, port_reservation.Pass()), device_(device.Pass()) {} diff --git a/chrome/test/chromedriver/chrome/chrome_android_impl.h b/chrome/test/chromedriver/chrome/chrome_android_impl.h index 39da9da575..87d0e9f0c1 100644 --- a/chrome/test/chromedriver/chrome/chrome_android_impl.h +++ b/chrome/test/chromedriver/chrome/chrome_android_impl.h @@ -12,12 +12,14 @@ #include "chrome/test/chromedriver/chrome/chrome_impl.h" class Device; +class DevToolsClient; class DevToolsHttpClient; class ChromeAndroidImpl : public ChromeImpl { public: ChromeAndroidImpl( - scoped_ptr<DevToolsHttpClient> client, + scoped_ptr<DevToolsHttpClient> http_client, + scoped_ptr<DevToolsClient> websocket_client, ScopedVector<DevToolsEventListener>& devtools_event_listeners, scoped_ptr<PortReservation> port_reservation, scoped_ptr<Device> device); diff --git a/chrome/test/chromedriver/chrome/chrome_desktop_impl.cc b/chrome/test/chromedriver/chrome/chrome_desktop_impl.cc index d7372499fe..14d596ea54 100644 --- a/chrome/test/chromedriver/chrome/chrome_desktop_impl.cc +++ b/chrome/test/chromedriver/chrome/chrome_desktop_impl.cc @@ -62,14 +62,16 @@ bool KillProcess(base::ProcessHandle process_id) { } // namespace ChromeDesktopImpl::ChromeDesktopImpl( - scoped_ptr<DevToolsHttpClient> client, + scoped_ptr<DevToolsHttpClient> http_client, + scoped_ptr<DevToolsClient> websocket_client, ScopedVector<DevToolsEventListener>& devtools_event_listeners, scoped_ptr<PortReservation> port_reservation, base::ProcessHandle process, const CommandLine& command, base::ScopedTempDir* user_data_dir, base::ScopedTempDir* extension_dir) - : ChromeImpl(client.Pass(), + : ChromeImpl(http_client.Pass(), + websocket_client.Pass(), devtools_event_listeners, port_reservation.Pass()), process_(process), diff --git a/chrome/test/chromedriver/chrome/chrome_desktop_impl.h b/chrome/test/chromedriver/chrome/chrome_desktop_impl.h index d4484196dc..c36fafdbd2 100644 --- a/chrome/test/chromedriver/chrome/chrome_desktop_impl.h +++ b/chrome/test/chromedriver/chrome/chrome_desktop_impl.h @@ -19,6 +19,7 @@ class TimeDelta; } class AutomationExtension; +class DevToolsClient; class DevToolsHttpClient; class Status; class WebView; @@ -26,7 +27,8 @@ class WebView; class ChromeDesktopImpl : public ChromeImpl { public: ChromeDesktopImpl( - scoped_ptr<DevToolsHttpClient> client, + scoped_ptr<DevToolsHttpClient> http_client, + scoped_ptr<DevToolsClient> websocket_client, ScopedVector<DevToolsEventListener>& devtools_event_listeners, scoped_ptr<PortReservation> port_reservation, base::ProcessHandle process, diff --git a/chrome/test/chromedriver/chrome/chrome_impl.cc b/chrome/test/chromedriver/chrome/chrome_impl.cc index 7f796d2e65..da85877eef 100644 --- a/chrome/test/chromedriver/chrome/chrome_impl.cc +++ b/chrome/test/chromedriver/chrome/chrome_impl.cc @@ -140,11 +140,13 @@ Status ChromeImpl::Quit() { } ChromeImpl::ChromeImpl( - scoped_ptr<DevToolsHttpClient> client, + scoped_ptr<DevToolsHttpClient> http_client, + scoped_ptr<DevToolsClient> websocket_client, ScopedVector<DevToolsEventListener>& devtools_event_listeners, scoped_ptr<PortReservation> port_reservation) : quit_(false), - devtools_http_client_(client.Pass()), + devtools_http_client_(http_client.Pass()), + devtools_websocket_client_(websocket_client.Pass()), port_reservation_(port_reservation.Pass()) { devtools_event_listeners_.swap(devtools_event_listeners); } diff --git a/chrome/test/chromedriver/chrome/chrome_impl.h b/chrome/test/chromedriver/chrome/chrome_impl.h index d852351411..01a5345e31 100644 --- a/chrome/test/chromedriver/chrome/chrome_impl.h +++ b/chrome/test/chromedriver/chrome/chrome_impl.h @@ -16,6 +16,7 @@ class AutomationExtension; struct BrowserInfo; +class DevToolsClient; class DevToolsEventListener; class DevToolsHttpClient; class JavaScriptDialogManager; @@ -42,7 +43,8 @@ class ChromeImpl : public Chrome { protected: ChromeImpl( - scoped_ptr<DevToolsHttpClient> client, + scoped_ptr<DevToolsHttpClient> http_client, + scoped_ptr<DevToolsClient> websocket_client, ScopedVector<DevToolsEventListener>& devtools_event_listeners, scoped_ptr<PortReservation> port_reservation); @@ -50,6 +52,7 @@ class ChromeImpl : public Chrome { bool quit_; scoped_ptr<DevToolsHttpClient> devtools_http_client_; + scoped_ptr<DevToolsClient> devtools_websocket_client_; private: typedef std::list<linked_ptr<WebViewImpl> > WebViewList; diff --git a/chrome/test/chromedriver/chrome/chrome_remote_impl.cc b/chrome/test/chromedriver/chrome/chrome_remote_impl.cc index f475d36158..ffdfef6774 100644 --- a/chrome/test/chromedriver/chrome/chrome_remote_impl.cc +++ b/chrome/test/chromedriver/chrome/chrome_remote_impl.cc @@ -3,14 +3,17 @@ // found in the LICENSE file. #include "chrome/test/chromedriver/chrome/chrome_remote_impl.h" +#include "chrome/test/chromedriver/chrome/devtools_client.h" #include "chrome/test/chromedriver/chrome/devtools_http_client.h" #include "chrome/test/chromedriver/chrome/status.h" #include "chrome/test/chromedriver/net/port_server.h" ChromeRemoteImpl::ChromeRemoteImpl( - scoped_ptr<DevToolsHttpClient> client, + scoped_ptr<DevToolsHttpClient> http_client, + scoped_ptr<DevToolsClient> websocket_client, ScopedVector<DevToolsEventListener>& devtools_event_listeners) - : ChromeImpl(client.Pass(), + : ChromeImpl(http_client.Pass(), + websocket_client.Pass(), devtools_event_listeners, scoped_ptr<PortReservation>()) {} diff --git a/chrome/test/chromedriver/chrome/chrome_remote_impl.h b/chrome/test/chromedriver/chrome/chrome_remote_impl.h index 9c2117128d..7981477fc8 100644 --- a/chrome/test/chromedriver/chrome/chrome_remote_impl.h +++ b/chrome/test/chromedriver/chrome/chrome_remote_impl.h @@ -11,12 +11,14 @@ #include "base/memory/scoped_ptr.h" #include "chrome/test/chromedriver/chrome/chrome_impl.h" +class DevToolsClient; class DevToolsHttpClient; class ChromeRemoteImpl : public ChromeImpl { public: ChromeRemoteImpl( - scoped_ptr<DevToolsHttpClient> client, + scoped_ptr<DevToolsHttpClient> http_client, + scoped_ptr<DevToolsClient> websocket_client, ScopedVector<DevToolsEventListener>& devtools_event_listeners); virtual ~ChromeRemoteImpl(); diff --git a/chrome/test/chromedriver/chrome/devtools_client_impl.cc b/chrome/test/chromedriver/chrome/devtools_client_impl.cc index b3e8e0e1f1..5c28526457 100644 --- a/chrome/test/chromedriver/chrome/devtools_client_impl.cc +++ b/chrome/test/chromedriver/chrome/devtools_client_impl.cc @@ -53,6 +53,10 @@ Status ConditionIsMet(bool* is_condition_met) { return Status(kOk); } +Status FakeCloseFrontends() { + return Status(kOk); +} + } // namespace namespace internal { @@ -67,6 +71,22 @@ InspectorCommandResponse::~InspectorCommandResponse() {} } // namespace internal +const char DevToolsClientImpl::kBrowserwideDevToolsClientId[] = "browser"; + +DevToolsClientImpl::DevToolsClientImpl( + const SyncWebSocketFactory& factory, + const std::string& url, + const std::string& id) + : socket_(factory.Run().Pass()), + url_(url), + crashed_(false), + id_(id), + frontend_closer_func_(base::Bind(&FakeCloseFrontends)), + parser_func_(base::Bind(&internal::ParseInspectorMessage)), + unnotified_event_(NULL), + next_id_(1), + stack_count_(0) {} + DevToolsClientImpl::DevToolsClientImpl( const SyncWebSocketFactory& factory, const std::string& url, @@ -454,16 +474,19 @@ bool ParseInspectorMessage( } else if (message_dict->GetInteger("id", &id)) { base::DictionaryValue* unscoped_error = NULL; base::DictionaryValue* unscoped_result = NULL; - if (!message_dict->GetDictionary("error", &unscoped_error) && - !message_dict->GetDictionary("result", &unscoped_result)) - return false; - *type = kCommandResponseMessageType; command_response->id = id; - if (unscoped_result) + // As per Chromium issue 392577, DevTools does not necessarily return a + // "result" dictionary for every valid response. In particular, + // Tracing.start and Tracing.end command responses do not contain one. + // So, if neither "error" nor "result" keys are present, just provide + // a blank result dictionary. + if (message_dict->GetDictionary("result", &unscoped_result)) command_response->result.reset(unscoped_result->DeepCopy()); - else + else if (message_dict->GetDictionary("error", &unscoped_error)) base::JSONWriter::Write(unscoped_error, &command_response->error); + else + command_response->result.reset(new base::DictionaryValue()); return true; } return false; diff --git a/chrome/test/chromedriver/chrome/devtools_client_impl.h b/chrome/test/chromedriver/chrome/devtools_client_impl.h index d26de29f03..34bb203efb 100644 --- a/chrome/test/chromedriver/chrome/devtools_client_impl.h +++ b/chrome/test/chromedriver/chrome/devtools_client_impl.h @@ -52,6 +52,12 @@ class SyncWebSocket; class DevToolsClientImpl : public DevToolsClient { public: + static const char kBrowserwideDevToolsClientId[]; + + DevToolsClientImpl(const SyncWebSocketFactory& factory, + const std::string& url, + const std::string& id); + typedef base::Callback<Status()> FrontendCloserFunc; DevToolsClientImpl(const SyncWebSocketFactory& factory, const std::string& url, diff --git a/chrome/test/chromedriver/chrome/devtools_client_impl_unittest.cc b/chrome/test/chromedriver/chrome/devtools_client_impl_unittest.cc index 08482d8c74..75efe88fed 100644 --- a/chrome/test/chromedriver/chrome/devtools_client_impl_unittest.cc +++ b/chrome/test/chromedriver/chrome/devtools_client_impl_unittest.cc @@ -569,8 +569,12 @@ TEST(ParseInspectorMessage, CommandNoErrorOrResult) { internal::InspectorMessageType type; internal::InspectorEvent event; internal::InspectorCommandResponse response; - ASSERT_FALSE(internal::ParseInspectorMessage( + // As per Chromium issue 392577, DevTools does not necessarily return a + // "result" dictionary for every valid response. If neither "error" nor + // "result" keys are present, a blank result dictionary should be inferred. + ASSERT_TRUE(internal::ParseInspectorMessage( "{\"id\":1}", 0, &type, &event, &response)); + ASSERT_TRUE(response.result->empty()); } TEST(ParseInspectorMessage, CommandError) { diff --git a/chrome/test/chromedriver/chrome/devtools_event_listener.cc b/chrome/test/chromedriver/chrome/devtools_event_listener.cc index 00d4487276..d21149eb99 100644 --- a/chrome/test/chromedriver/chrome/devtools_event_listener.cc +++ b/chrome/test/chromedriver/chrome/devtools_event_listener.cc @@ -23,3 +23,7 @@ Status DevToolsEventListener::OnCommandSuccess( const std::string& method) { return Status(kOk); } + +bool DevToolsEventListener::subscribes_to_browser() { + return false; +} diff --git a/chrome/test/chromedriver/chrome/devtools_event_listener.h b/chrome/test/chromedriver/chrome/devtools_event_listener.h index 8060fb85bb..2d2f1599ac 100644 --- a/chrome/test/chromedriver/chrome/devtools_event_listener.h +++ b/chrome/test/chromedriver/chrome/devtools_event_listener.h @@ -31,6 +31,12 @@ class DevToolsEventListener { // Called when a command success response is received. virtual Status OnCommandSuccess(DevToolsClient* client, const std::string& method); + + // True if the listener should be added to the browser-wide |DevToolsClient| + // in addition to all webview |DevToolsClient|s. False by default. If set to + // true, listener can use |client|->GetId() to distinguish between browser- + // wide |DevToolsClient| and webview |DevToolsClient|s. + virtual bool subscribes_to_browser(); }; #endif // CHROME_TEST_CHROMEDRIVER_CHROME_DEVTOOLS_EVENT_LISTENER_H_ diff --git a/chrome/test/chromedriver/chrome/devtools_http_client.cc b/chrome/test/chromedriver/chrome/devtools_http_client.cc index 99ff945641..9397872852 100644 --- a/chrome/test/chromedriver/chrome/devtools_http_client.cc +++ b/chrome/test/chromedriver/chrome/devtools_http_client.cc @@ -22,14 +22,6 @@ #include "chrome/test/chromedriver/net/net_util.h" #include "chrome/test/chromedriver/net/url_request_context_getter.h" -namespace { - -Status FakeCloseFrontends() { - return Status(kOk); -} - -} // namespace - WebViewInfo::WebViewInfo(const std::string& id, const std::string& debugger_url, const std::string& url, @@ -252,8 +244,7 @@ Status DevToolsHttpClient::CloseFrontends(const std::string& for_client_id) { scoped_ptr<DevToolsClient> client(new DevToolsClientImpl( socket_factory_, web_socket_url_prefix_ + *it, - *it, - base::Bind(&FakeCloseFrontends))); + *it)); scoped_ptr<WebViewImpl> web_view( new WebViewImpl(*it, &browser_info_, client.Pass(), NULL)); diff --git a/chrome/test/chromedriver/chrome/mobile_emulation_override_manager.cc b/chrome/test/chromedriver/chrome/mobile_emulation_override_manager.cc index 0e35b906dd..6d28899488 100644 --- a/chrome/test/chromedriver/chrome/mobile_emulation_override_manager.cc +++ b/chrome/test/chromedriver/chrome/mobile_emulation_override_manager.cc @@ -46,13 +46,13 @@ Status MobileEmulationOverrideManager::ApplyOverrideIfNeeded() { // Old revisions of Blink expect a parameter named |emulateViewport| but in // Blink revision 177367 (Chromium revision 281046, build number 2081) this // was renamed to |mobile|. - std::string tmp = "mobile"; + std::string mobile_param_name = "mobile"; if (browser_info_->browser_name == "chrome") { if (browser_info_->build_no <= 2081) - tmp = "emulateViewport"; + mobile_param_name = "emulateViewport"; } else { if (browser_info_->blink_revision < 177367) - tmp = "emulateViewport"; + mobile_param_name = "emulateViewport"; } base::DictionaryValue params; @@ -60,7 +60,7 @@ Status MobileEmulationOverrideManager::ApplyOverrideIfNeeded() { params.SetInteger("height", overridden_device_metrics_->height); params.SetDouble("deviceScaleFactor", overridden_device_metrics_->device_scale_factor); - params.SetBoolean(tmp, overridden_device_metrics_->mobile); + params.SetBoolean(mobile_param_name, overridden_device_metrics_->mobile); params.SetBoolean("fitWindow", overridden_device_metrics_->fit_window); params.SetBoolean("textAutosizing", overridden_device_metrics_->text_autosizing); diff --git a/chrome/test/chromedriver/chrome_launcher.cc b/chrome/test/chromedriver/chrome_launcher.cc index edccc5111f..480332c5ec 100644 --- a/chrome/test/chromedriver/chrome_launcher.cc +++ b/chrome/test/chromedriver/chrome_launcher.cc @@ -9,6 +9,7 @@ #include "base/base64.h" #include "base/basictypes.h" +#include "base/bind.h" #include "base/command_line.h" #include "base/file_util.h" #include "base/files/file_path.h" @@ -32,6 +33,8 @@ #include "chrome/test/chromedriver/chrome/chrome_finder.h" #include "chrome/test/chromedriver/chrome/chrome_remote_impl.h" #include "chrome/test/chromedriver/chrome/device_manager.h" +#include "chrome/test/chromedriver/chrome/devtools_client_impl.h" +#include "chrome/test/chromedriver/chrome/devtools_event_listener.h" #include "chrome/test/chromedriver/chrome/devtools_http_client.h" #include "chrome/test/chromedriver/chrome/embedded_automation_extension.h" #include "chrome/test/chromedriver/chrome/status.h" @@ -190,6 +193,40 @@ Status WaitForDevToolsAndCheckVersion( return Status(kUnknownError, "unable to discover open pages"); } +Status CreateBrowserwideDevToolsClientAndConnect( + const NetAddress& address, + const PerfLoggingPrefs& perf_logging_prefs, + const SyncWebSocketFactory& socket_factory, + ScopedVector<DevToolsEventListener>& devtools_event_listeners, + scoped_ptr<DevToolsClient>* browser_client) { + scoped_ptr<DevToolsClient> client(new DevToolsClientImpl( + socket_factory, base::StringPrintf("ws://%s/devtools/browser/", + address.ToString().c_str()), + DevToolsClientImpl::kBrowserwideDevToolsClientId)); + for (ScopedVector<DevToolsEventListener>::const_iterator it = + devtools_event_listeners.begin(); + it != devtools_event_listeners.end(); + ++it) { + // Only add listeners that subscribe to the browser-wide |DevToolsClient|. + // Otherwise, listeners will think this client is associated with a webview, + // and will send unrecognized commands to it. + if ((*it)->subscribes_to_browser()) + client->AddListener(*it); + } + // Provide the client regardless of whether it connects, so that Chrome always + // has a valid |devtools_websocket_client_|. If not connected, no listeners + // will be notified, and client will just return kDisconnected errors if used. + *browser_client = client.Pass(); + // To avoid unnecessary overhead, only connect if tracing is enabled, since + // the browser-wide client is currently only used for tracing. + if (!perf_logging_prefs.trace_categories.empty()) { + Status status = (*browser_client)->ConnectIfNecessary(); + if (status.IsError()) + return status; + } + return Status(kOk); +} + Status LaunchRemoteChromeSession( URLRequestContextGetter* context_getter, const SyncWebSocketFactory& socket_factory, @@ -197,16 +234,27 @@ Status LaunchRemoteChromeSession( ScopedVector<DevToolsEventListener>& devtools_event_listeners, scoped_ptr<Chrome>* chrome) { Status status(kOk); - scoped_ptr<DevToolsHttpClient> devtools_client; + scoped_ptr<DevToolsHttpClient> devtools_http_client; status = WaitForDevToolsAndCheckVersion( capabilities.debugger_address, context_getter, socket_factory, - NULL, &devtools_client); + NULL, &devtools_http_client); if (status.IsError()) { return Status(kUnknownError, "cannot connect to chrome at " + capabilities.debugger_address.ToString(), status); } - chrome->reset(new ChromeRemoteImpl(devtools_client.Pass(), + + scoped_ptr<DevToolsClient> devtools_websocket_client; + status = CreateBrowserwideDevToolsClientAndConnect( + capabilities.debugger_address, capabilities.perf_logging_prefs, + socket_factory, devtools_event_listeners, &devtools_websocket_client); + if (status.IsError()) { + LOG(WARNING) << "Browser-wide DevTools client failed to connect: " + << status.message(); + } + + chrome->reset(new ChromeRemoteImpl(devtools_http_client.Pass(), + devtools_websocket_client.Pass(), devtools_event_listeners)); return Status(kOk); } @@ -282,10 +330,10 @@ Status LaunchDesktopChrome( if (!base::LaunchProcess(command, options, &process)) return Status(kUnknownError, "chrome failed to start"); - scoped_ptr<DevToolsHttpClient> devtools_client; + scoped_ptr<DevToolsHttpClient> devtools_http_client; status = WaitForDevToolsAndCheckVersion( NetAddress(port), context_getter, socket_factory, &capabilities, - &devtools_client); + &devtools_http_client); if (status.IsError()) { int exit_code; @@ -321,8 +369,19 @@ Status LaunchDesktopChrome( } return status; } + + scoped_ptr<DevToolsClient> devtools_websocket_client; + status = CreateBrowserwideDevToolsClientAndConnect( + NetAddress(port), capabilities.perf_logging_prefs, socket_factory, + devtools_event_listeners, &devtools_websocket_client); + if (status.IsError()) { + LOG(WARNING) << "Browser-wide DevTools client failed to connect: " + << status.message(); + } + scoped_ptr<ChromeDesktopImpl> chrome_desktop( - new ChromeDesktopImpl(devtools_client.Pass(), + new ChromeDesktopImpl(devtools_http_client.Pass(), + devtools_websocket_client.Pass(), devtools_event_listeners, port_reservation.Pass(), process, @@ -381,18 +440,28 @@ Status LaunchAndroidChrome( return status; } - scoped_ptr<DevToolsHttpClient> devtools_client; + scoped_ptr<DevToolsHttpClient> devtools_http_client; status = WaitForDevToolsAndCheckVersion(NetAddress(port), context_getter, socket_factory, &capabilities, - &devtools_client); + &devtools_http_client); if (status.IsError()) { device->TearDown(); return status; } - chrome->reset(new ChromeAndroidImpl(devtools_client.Pass(), + scoped_ptr<DevToolsClient> devtools_websocket_client; + status = CreateBrowserwideDevToolsClientAndConnect( + NetAddress(port), capabilities.perf_logging_prefs, socket_factory, + devtools_event_listeners, &devtools_websocket_client); + if (status.IsError()) { + LOG(WARNING) << "Browser-wide DevTools client failed to connect: " + << status.message(); + } + + chrome->reset(new ChromeAndroidImpl(devtools_http_client.Pass(), + devtools_websocket_client.Pass(), devtools_event_listeners, port_reservation.Pass(), device.Pass())); diff --git a/chrome/test/chromedriver/commands.cc b/chrome/test/chromedriver/commands.cc index 6b7e247d6d..dc1ef83e60 100644 --- a/chrome/test/chromedriver/commands.cc +++ b/chrome/test/chromedriver/commands.cc @@ -153,57 +153,64 @@ void ExecuteSessionCommandOnSessionThread( } // Notify |session|'s |CommandListener|s of the command. - NotifySessionListenersBeforeCommand(session, command_name); + // Will mark |session| for deletion if an error is encountered. + Status status = NotifyCommandListenersBeforeCommand(session, command_name); + // Only run the command if we were able to notify all listeners successfully. + // Otherwise, pass error to callback, delete |session|, and do not continue. scoped_ptr<base::Value> value; - Status status = command.Run(session, *params, &value); + if (status.IsError()) { + LOG(ERROR) << status.message(); + } else { + status = command.Run(session, *params, &value); - if (status.IsError() && session->chrome) { - if (!session->quit && session->chrome->HasCrashedWebView()) { - session->quit = true; - std::string message("session deleted because of page crash"); - if (!session->detach) { - Status quit_status = session->chrome->Quit(); - if (quit_status.IsError()) - message += ", but failed to kill browser:" + quit_status.message(); + if (status.IsError() && session->chrome) { + if (!session->quit && session->chrome->HasCrashedWebView()) { + session->quit = true; + std::string message("session deleted because of page crash"); + if (!session->detach) { + Status quit_status = session->chrome->Quit(); + if (quit_status.IsError()) + message += ", but failed to kill browser:" + quit_status.message(); + } + status = Status(kUnknownError, message, status); + } else if (status.code() == kDisconnected) { + // Some commands, like clicking a button or link which closes the + // window, may result in a kDisconnected error code. + std::list<std::string> web_view_ids; + Status status_tmp = session->chrome->GetWebViewIds(&web_view_ids); + if (status_tmp.IsError() && status_tmp.code() != kChromeNotReachable) { + status.AddDetails( + "failed to check if window was closed: " + status_tmp.message()); + } else if (std::find(web_view_ids.begin(), + web_view_ids.end(), + session->window) == web_view_ids.end()) { + status = Status(kOk); + } } - status = Status(kUnknownError, message, status); - } else if (status.code() == kDisconnected) { - // Some commands, like clicking a button or link which closes the window, - // may result in a kDisconnected error code. - std::list<std::string> web_view_ids; - Status status_tmp = session->chrome->GetWebViewIds(&web_view_ids); - if (status_tmp.IsError() && status_tmp.code() != kChromeNotReachable) { - status.AddDetails( - "failed to check if window was closed: " + status_tmp.message()); - } else if (std::find(web_view_ids.begin(), - web_view_ids.end(), - session->window) == web_view_ids.end()) { - status = Status(kOk); + if (status.IsError()) { + const BrowserInfo* browser_info = session->chrome->GetBrowserInfo(); + status.AddDetails("Session info: " + browser_info->browser_name + "=" + + browser_info->browser_version); } } - if (status.IsError()) { - const BrowserInfo* browser_info = session->chrome->GetBrowserInfo(); - status.AddDetails("Session info: " + browser_info->browser_name + "=" + - browser_info->browser_version); - } - } - if (IsVLogOn(0)) { - std::string result; - if (status.IsError()) { - result = status.message(); - } else if (value) { - result = FormatValueForDisplay(*value); + if (IsVLogOn(0)) { + std::string result; + if (status.IsError()) { + result = status.message(); + } else if (value) { + result = FormatValueForDisplay(*value); + } + VLOG(0) << "RESPONSE " << command_name + << (result.length() ? " " + result : ""); } - VLOG(0) << "RESPONSE " << command_name - << (result.length() ? " " + result : ""); - } - if (status.IsOk() && session->auto_reporting_enabled) { - std::string message = session->GetFirstBrowserError(); - if (!message.empty()) - status = Status(kUnknownError, message); + if (status.IsOk() && session->auto_reporting_enabled) { + std::string message = session->GetFirstBrowserError(); + if (!message.empty()) + status = Status(kUnknownError, message); + } } cmd_task_runner->PostTask( diff --git a/chrome/test/chromedriver/commands_unittest.cc b/chrome/test/chromedriver/commands_unittest.cc index c34f197fa0..324c09320e 100644 --- a/chrome/test/chromedriver/commands_unittest.cc +++ b/chrome/test/chromedriver/commands_unittest.cc @@ -601,7 +601,7 @@ void OnSessionCommand( } // namespace -TEST(CommandsTest, SessionNotifiedOfCommand) { +TEST(CommandsTest, SuccessNotifyingCommandListeners) { SessionThreadMap map; linked_ptr<base::Thread> thread(new base::Thread("1")); ASSERT_TRUE(thread->Start()); @@ -609,6 +609,7 @@ TEST(CommandsTest, SessionNotifiedOfCommand) { thread->message_loop()->PostTask( FROM_HERE, base::Bind(&internal::CreateSessionOnSessionThreadForTesting, id)); + map[id] = thread; base::DictionaryValue params; @@ -617,8 +618,7 @@ TEST(CommandsTest, SessionNotifiedOfCommand) { // We add |proxy| to the session instead of adding |listener| directly so that // after the session is destroyed by ExecuteQuitSessionCommand, we can still // verify the listener was called. The session owns and will destroy |proxy|. - SessionCommand cmd = base::Bind( - &ExecuteAddListenerToSessionCommand, proxy); + SessionCommand cmd = base::Bind(&ExecuteAddListenerToSessionCommand, proxy); base::MessageLoop loop; base::RunLoop run_loop_addlistener; @@ -632,15 +632,13 @@ TEST(CommandsTest, SessionNotifiedOfCommand) { false, params, id, - base::Bind(&OnSessionCommand, - &run_loop_addlistener)); + base::Bind(&OnSessionCommand, &run_loop_addlistener)); run_loop_addlistener.Run(); listener->VerifyNotCalled(); base::RunLoop run_loop_testlistener; - cmd = base::Bind( - &ExecuteQuitSessionCommand); + cmd = base::Bind(&ExecuteQuitSessionCommand); // |listener| was added to |session| by ExecuteAddListenerToSessionCommand // and should be notified before the next command, ExecuteQuitSessionCommand. @@ -651,9 +649,82 @@ TEST(CommandsTest, SessionNotifiedOfCommand) { false, params, id, - base::Bind(&OnSessionCommand, - &run_loop_testlistener)); + base::Bind(&OnSessionCommand, &run_loop_testlistener)); run_loop_testlistener.Run(); listener->VerifyCalled(); } + +namespace { + +class FailingCommandListener : public CommandListener { + public: + FailingCommandListener() {} + virtual ~FailingCommandListener() {} + + virtual Status BeforeCommand(const std::string& command_name) OVERRIDE { + return Status(kUnknownError); + } +}; + +void AddListenerToSessionIfSessionExists(CommandListener* listener) { + Session* session = GetThreadLocalSession(); + if (session) { + session->command_listeners.push_back(listener); + } +} + +void OnFailBecauseErrorNotifyingListeners( + base::RunLoop* run_loop, + const Status& status, + scoped_ptr<base::Value> value, + const std::string& session_id) { + EXPECT_EQ(kUnknownError, status.code()); + EXPECT_FALSE(value.get()); + run_loop->Quit(); +} + +void VerifySessionWasDeleted() { + ASSERT_FALSE(GetThreadLocalSession()); +} + +} // namespace + +TEST(CommandsTest, ErrorNotifyingCommandListeners) { + SessionThreadMap map; + linked_ptr<base::Thread> thread(new base::Thread("1")); + ASSERT_TRUE(thread->Start()); + std::string id("id"); + thread->message_loop()->PostTask( + FROM_HERE, + base::Bind(&internal::CreateSessionOnSessionThreadForTesting, id)); + map[id] = thread; + + // In SuccessNotifyingCommandListenersBeforeCommand, we verified BeforeCommand + // was called before (as opposed to after) command execution. We don't need to + // verify this again, so we can just add |listener| with PostTask. + CommandListener* listener = new FailingCommandListener(); + thread->message_loop()->PostTask( + FROM_HERE, + base::Bind(&AddListenerToSessionIfSessionExists, listener)); + + base::DictionaryValue params; + // The command should never be executed if BeforeCommand fails for a listener. + SessionCommand cmd = base::Bind(&ShouldNotBeCalled); + base::MessageLoop loop; + base::RunLoop run_loop; + + ExecuteSessionCommand( + &map, + "cmd", + cmd, + false, + params, + id, + base::Bind(&OnFailBecauseErrorNotifyingListeners, &run_loop)); + run_loop.Run(); + + thread->message_loop()->PostTask( + FROM_HERE, + base::Bind(&VerifySessionWasDeleted)); +} diff --git a/chrome/test/chromedriver/logging.cc b/chrome/test/chromedriver/logging.cc index f0ac778f46..be1d5c3d7b 100644 --- a/chrome/test/chromedriver/logging.cc +++ b/chrome/test/chromedriver/logging.cc @@ -257,8 +257,11 @@ Status CreateLogs(const Capabilities& capabilities, if (level != Log::kOff) { WebDriverLog* log = new WebDriverLog(type, Log::kAll); logs.push_back(log); - PerformanceLogger* perf_log = new PerformanceLogger(log); + PerformanceLogger* perf_log = + new PerformanceLogger(log, capabilities.perf_logging_prefs); // We use a proxy for |perf_log|'s |CommandListener| interface. + // Otherwise, |perf_log| would be owned by both session->chrome and + // |session|, which would lead to memory errors on destruction. // session->chrome will own |perf_log|, and |session| will own |proxy|. // session->command_listeners (the proxy) will be destroyed first. CommandListenerProxy* proxy = new CommandListenerProxy(perf_log); diff --git a/chrome/test/chromedriver/performance_logger.cc b/chrome/test/chromedriver/performance_logger.cc index 708200d6e1..44d837b9be 100644 --- a/chrome/test/chromedriver/performance_logger.cc +++ b/chrome/test/chromedriver/performance_logger.cc @@ -2,12 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <string> +#include <vector> + #include "chrome/test/chromedriver/performance_logger.h" #include "base/json/json_writer.h" #include "base/strings/string_util.h" #include "base/values.h" #include "chrome/test/chromedriver/chrome/devtools_client.h" +#include "chrome/test/chromedriver/chrome/devtools_client_impl.h" #include "chrome/test/chromedriver/chrome/log.h" #include "chrome/test/chromedriver/chrome/status.h" @@ -16,10 +20,6 @@ namespace { // DevTools event domain prefixes to intercept. const char* const kDomains[] = {"Network.", "Page.", "Timeline."}; -const char* const kDomainEnableCommands[] = { - "Network.enable", "Page.enable", "Timeline.start" -}; - // Returns whether the event belongs to one of kDomains. bool ShouldLogEvent(const std::string& method) { for (size_t i_domain = 0; i_domain < arraysize(kDomains); ++i_domain) { @@ -29,15 +29,53 @@ bool ShouldLogEvent(const std::string& method) { return false; } +bool IsEnabled(const PerfLoggingPrefs::InspectorDomainStatus& domain_status) { + return (domain_status == + PerfLoggingPrefs::InspectorDomainStatus::kDefaultEnabled || + domain_status == + PerfLoggingPrefs::InspectorDomainStatus::kExplicitlyEnabled); +} + } // namespace PerformanceLogger::PerformanceLogger(Log* log) : log_(log) {} +PerformanceLogger::PerformanceLogger(Log* log, const PerfLoggingPrefs& prefs) + : log_(log), + prefs_(prefs) { + if (!prefs_.trace_categories.empty()) { + LOG(WARNING) << "Ignoring trace categories because tracing support not yet " + << "implemented: " << prefs_.trace_categories; + prefs_.trace_categories = ""; + } +} + +bool PerformanceLogger::subscribes_to_browser() { + return true; +} + Status PerformanceLogger::OnConnected(DevToolsClient* client) { - base::DictionaryValue params; // All our enable commands have empty params. - for (size_t i_cmd = 0; i_cmd < arraysize(kDomainEnableCommands); ++i_cmd) { - Status status = client->SendCommand(kDomainEnableCommands[i_cmd], params); + if (client->GetId() == DevToolsClientImpl::kBrowserwideDevToolsClientId) { + // TODO(johnmoore): Implement tracing log. + return Status(kOk); + } + std::vector<std::string> enable_commands; + if (IsEnabled(prefs_.network)) + enable_commands.push_back("Network.enable"); + if (IsEnabled(prefs_.page)) + enable_commands.push_back("Page.enable"); + if (IsEnabled(prefs_.timeline)) { + // Timeline feed implicitly disabled when trace categories are specified. + // So even if kDefaultEnabled, don't enable unless empty |trace_categories|. + if (prefs_.trace_categories.empty() || prefs_.timeline == + PerfLoggingPrefs::InspectorDomainStatus::kExplicitlyEnabled) + enable_commands.push_back("Timeline.start"); + } + for (std::vector<std::string>::const_iterator it = enable_commands.begin(); + it != enable_commands.end(); ++it) { + base::DictionaryValue params; // All the enable commands have empty params. + Status status = client->SendCommand(*it, params); if (status.IsError()) return status; } diff --git a/chrome/test/chromedriver/performance_logger.h b/chrome/test/chromedriver/performance_logger.h index 1f33598b67..f316879084 100644 --- a/chrome/test/chromedriver/performance_logger.h +++ b/chrome/test/chromedriver/performance_logger.h @@ -5,8 +5,11 @@ #ifndef CHROME_TEST_CHROMEDRIVER_PERFORMANCE_LOGGER_H_ #define CHROME_TEST_CHROMEDRIVER_PERFORMANCE_LOGGER_H_ +#include <string> + #include "base/basictypes.h" #include "base/compiler_specific.h" +#include "chrome/test/chromedriver/capabilities.h" #include "chrome/test/chromedriver/chrome/devtools_event_listener.h" #include "chrome/test/chromedriver/command_listener.h" @@ -21,10 +24,13 @@ class Log; // } class PerformanceLogger : public DevToolsEventListener, public CommandListener { public: - // Creates a PerformanceLogger that creates entries in the given Log object. - // The log is owned elsewhere and must not be null. + // Creates a |PerformanceLogger| with default preferences that creates entries + // in the given Log object. The log is owned elsewhere and must not be null. explicit PerformanceLogger(Log* log); + // Creates a |PerformanceLogger| with specific preferences. + PerformanceLogger(Log* log, const PerfLoggingPrefs& prefs); + // Enables Page,Network,Timeline events for client, which must not be null. virtual Status OnConnected(DevToolsClient* client) OVERRIDE; // Translates an event into a log entry. @@ -34,8 +40,12 @@ class PerformanceLogger : public DevToolsEventListener, public CommandListener { virtual Status BeforeCommand(const std::string& command_name) OVERRIDE; + // PerformanceLogger subscribes to browser-wide |DevToolsClient| for tracing. + virtual bool subscribes_to_browser() OVERRIDE; + private: Log* log_; // The log where to create entries. + PerfLoggingPrefs prefs_; DISALLOW_COPY_AND_ASSIGN(PerformanceLogger); }; diff --git a/chrome/test/chromedriver/performance_logger_unittest.cc b/chrome/test/chromedriver/performance_logger_unittest.cc index cab92c85b9..2d6c7488a8 100644 --- a/chrome/test/chromedriver/performance_logger_unittest.cc +++ b/chrome/test/chromedriver/performance_logger_unittest.cc @@ -188,3 +188,22 @@ TEST(PerformanceLogger, TwoWebViews) { ValidateLogEntry(log.GetEntries()[0], "webview-1", "Page.gaga1"); ValidateLogEntry(log.GetEntries()[1], "webview-2", "Timeline.gaga2"); } + +TEST(PerformanceLogger, PerfLoggingPrefs) { + FakeDevToolsClient client("webview-1"); + FakeLog log; + PerfLoggingPrefs prefs; + ASSERT_EQ(PerfLoggingPrefs::InspectorDomainStatus::kDefaultEnabled, + prefs.network); + prefs.network = PerfLoggingPrefs::InspectorDomainStatus::kExplicitlyDisabled; + // Trace categories should be ignored until tracing support is implemented. + prefs.trace_categories = "benchmark,webkit.console"; + PerformanceLogger logger(&log, prefs); + + client.AddListener(&logger); + logger.OnConnected(&client); + EXPECT_EQ("Page.enable", client.PopSentCommand()); + // Trace categories ignored, so Timeline shouldn't be implicitly disabled. + EXPECT_EQ("Timeline.start", client.PopSentCommand()); + EXPECT_TRUE(client.PopSentCommand().empty()); +} diff --git a/chrome/test/chromedriver/session_commands.cc b/chrome/test/chromedriver/session_commands.cc index 39eac7f2a8..8f519c9ca3 100644 --- a/chrome/test/chromedriver/session_commands.cc +++ b/chrome/test/chromedriver/session_commands.cc @@ -130,7 +130,8 @@ Status InitSessionHelper( ScopedVector<CommandListener> command_listeners; status = CreateLogs(capabilities, &session->devtools_logs, - &devtools_event_listeners, &command_listeners); + &devtools_event_listeners, + &command_listeners); if (status.IsError()) return status; diff --git a/chrome/test/chromedriver/test/run_py_tests.py b/chrome/test/chromedriver/test/run_py_tests.py index 33a73191b3..71b225a8b6 100755 --- a/chrome/test/chromedriver/test/run_py_tests.py +++ b/chrome/test/chromedriver/test/run_py_tests.py @@ -735,8 +735,9 @@ class ChromeDriverAndroidTest(ChromeDriverBaseTest): for v in l['versions']: if (('stable' in v['channel'] and 'stable' in _ANDROID_PACKAGE_KEY) or ('beta' in v['channel'] and 'beta' in _ANDROID_PACKAGE_KEY)): - self.assertEquals(v['version'], - self._driver.capabilities['version']) + omaha = map(int, v['version'].split('.')) + device = map(int, self._driver.capabilities['version'].split('.')) + self.assertTrue(omaha <= device) return raise RuntimeError('Malformed omaha JSON') except urllib2.URLError as e: diff --git a/chrome/test/chromedriver/test/test_environment.py b/chrome/test/chromedriver/test/test_environment.py index b3e0cc2447..190721a8c4 100644 --- a/chrome/test/chromedriver/test/test_environment.py +++ b/chrome/test/chromedriver/test/test_environment.py @@ -18,8 +18,10 @@ _THIS_DIR = os.path.abspath(os.path.dirname(__file__)) if util.IsLinux(): sys.path.insert(0, os.path.join(chrome_paths.GetSrc(), 'build', 'android')) + from pylib import android_commands from pylib import forwarder from pylib import valgrind_tools + from pylib.device import device_errors from pylib.device import device_utils ANDROID_TEST_HTTP_PORT = 2311 @@ -94,7 +96,12 @@ class AndroidTestEnvironment(DesktopTestEnvironment): def GlobalSetUp(self): os.putenv('TEST_HTTP_PORT', str(ANDROID_TEST_HTTP_PORT)) os.putenv('TEST_HTTPS_PORT', str(ANDROID_TEST_HTTPS_PORT)) - self._device = device_utils.DeviceUtils(None) + devices = android_commands.GetAttachedDevices() + if not devices: + raise device_errors.NoDevicesError() + elif len(devices) > 1: + logging.warning('Multiple devices attached. Using %s.' % devices[0]) + self._device = device_utils.DeviceUtils(devices[0]) forwarder.Forwarder.Map( [(ANDROID_TEST_HTTP_PORT, ANDROID_TEST_HTTP_PORT), (ANDROID_TEST_HTTPS_PORT, ANDROID_TEST_HTTPS_PORT)], @@ -102,7 +109,8 @@ class AndroidTestEnvironment(DesktopTestEnvironment): # override def GlobalTearDown(self): - forwarder.Forwarder.UnmapAllDevicePorts(self._device) + if self._device: + forwarder.Forwarder.UnmapAllDevicePorts(self._device) # override def GetOS(self): diff --git a/chrome/test/chromedriver/test/webview_shell/java/AndroidManifest.xml b/chrome/test/chromedriver/test/webview_shell/java/AndroidManifest.xml index 63c3f105a6..c42928a0c9 100644 --- a/chrome/test/chromedriver/test/webview_shell/java/AndroidManifest.xml +++ b/chrome/test/chromedriver/test/webview_shell/java/AndroidManifest.xml @@ -9,7 +9,7 @@ package="org.chromium.chromedriver_webview_shell" android:versionCode="1" android:versionName="1.0"> - <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="19" /> + <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="20" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> diff --git a/chrome/test/chromedriver/util.cc b/chrome/test/chromedriver/util.cc index 7671cc7670..3c1ab86962 100644 --- a/chrome/test/chromedriver/util.cc +++ b/chrome/test/chromedriver/util.cc @@ -16,8 +16,10 @@ #include "base/strings/stringprintf.h" #include "base/third_party/icu/icu_utf.h" #include "base/values.h" +#include "chrome/test/chromedriver/chrome/chrome.h" #include "chrome/test/chromedriver/chrome/status.h" #include "chrome/test/chromedriver/chrome/ui_events.h" +#include "chrome/test/chromedriver/chrome/version.h" #include "chrome/test/chromedriver/chrome/web_view.h" #include "chrome/test/chromedriver/command_listener.h" #include "chrome/test/chromedriver/key_converter.h" @@ -405,14 +407,35 @@ Status UnzipSoleFile(const base::FilePath& unzip_dir, return Status(kOk); } -void NotifySessionListenersBeforeCommand(Session* session, - const std::string& command_name) { +Status NotifyCommandListenersBeforeCommand(Session* session, + const std::string& command_name) { for (ScopedVector<CommandListener>::const_iterator it = session->command_listeners.begin(); it != session->command_listeners.end(); ++it) { Status status = (*it)->BeforeCommand(command_name); - if (status.IsError()) - LOG(ERROR) << "Error when notifying listener of command"; + if (status.IsError()) { + // Do not continue if an error is encountered. Mark session for deletion, + // quit Chrome if necessary, and return a detailed error. + if (!session->quit) { + session->quit = true; + std::string message = base::StringPrintf("session deleted because " + "error encountered when notifying listeners of '%s' command", + command_name.c_str()); + if (session->chrome && !session->detach) { + Status quit_status = session->chrome->Quit(); + if (quit_status.IsError()) + message += ", but failed to kill browser:" + quit_status.message(); + } + status = Status(kUnknownError, message, status); + } + if (session->chrome) { + const BrowserInfo* browser_info = session->chrome->GetBrowserInfo(); + status.AddDetails("Session info: " + browser_info->browser_name + "=" + + browser_info->browser_version); + } + return status; + } } + return Status(kOk); } diff --git a/chrome/test/chromedriver/util.h b/chrome/test/chromedriver/util.h index d2b6962782..111ced4816 100644 --- a/chrome/test/chromedriver/util.h +++ b/chrome/test/chromedriver/util.h @@ -41,7 +41,8 @@ Status UnzipSoleFile(const base::FilePath& unzip_dir, base::FilePath* file); // Calls BeforeCommand for each of |session|'s |CommandListener|s. -void NotifySessionListenersBeforeCommand(Session* session, - const std::string& command_name); +// If an error is encountered, will mark |session| for deletion and return. +Status NotifyCommandListenersBeforeCommand(Session* session, + const std::string& command_name); #endif // CHROME_TEST_CHROMEDRIVER_UTIL_H_ diff --git a/chrome/test/chromeos/autotest/files/client/deps/chrome_test/setup_test_links.sh b/chrome/test/chromeos/autotest/files/client/deps/chrome_test/setup_test_links.sh index 48ef6e74d2..a47b005f0f 100755 --- a/chrome/test/chromeos/autotest/files/client/deps/chrome_test/setup_test_links.sh +++ b/chrome/test/chromeos/autotest/files/client/deps/chrome_test/setup_test_links.sh @@ -21,7 +21,6 @@ ln -f -s /opt/google/chrome/*.pak "$this_dir/" ln -f -s /opt/google/chrome/nacl_helper "$this_dir/" ln -f -s /opt/google/chrome/nacl_helper_bootstrap "$this_dir/" ln -f -s /opt/google/chrome/nacl_irt_*.nexe "$this_dir/" -ln -f -s /opt/google/chrome/libppGoogleNaClPluginChrome.so "$this_dir/" # Create links to resources from pyauto_dep. diff --git a/chrome/test/mini_installer/config/config.config b/chrome/test/mini_installer/config/config.config index 2aee7dcde8..550f67edf5 100644 --- a/chrome/test/mini_installer/config/config.config +++ b/chrome/test/mini_installer/config/config.config @@ -40,19 +40,25 @@ "python uninstall_chrome.py --chrome-long-name=\"$CHROME_LONG_NAME\" --system-level"] ], "tests": [ - [ - "clean", - "install_chrome_user", "chrome_user_installed_not_inuse", - "launch_chrome_user", "chrome_user_installed_inuse", - "quit_chrome_user", "chrome_user_installed_not_inuse", - "uninstall_chrome_user", "clean" - ], - [ - "clean", - "install_chrome_system", "chrome_system_installed_not_inuse", - "launch_chrome_system", "chrome_system_installed_inuse", - "quit_chrome_system", "chrome_system_installed_not_inuse", - "uninstall_chrome_system", "clean" - ] + { + "name": "ChromeUserLevel", + "traversal": [ + "clean", + "install_chrome_user", "chrome_user_installed_not_inuse", + "launch_chrome_user", "chrome_user_installed_inuse", + "quit_chrome_user", "chrome_user_installed_not_inuse", + "uninstall_chrome_user", "clean" + ] + }, + { + "name": "ChromeSystemLevel", + "traversal": [ + "clean", + "install_chrome_system", "chrome_system_installed_not_inuse", + "launch_chrome_system", "chrome_system_installed_inuse", + "quit_chrome_system", "chrome_system_installed_not_inuse", + "uninstall_chrome_system", "clean" + ] + } ] } diff --git a/chrome/test/mini_installer/test_installer.py b/chrome/test/mini_installer/test_installer.py index 25f5baff8a..2ce2dd9d45 100644 --- a/chrome/test/mini_installer/test_installer.py +++ b/chrome/test/mini_installer/test_installer.py @@ -9,11 +9,12 @@ each command match the expected machine states. For more details, take a look at the design documentation at http://goo.gl/Q0rGM6 """ +import argparse import json -import optparse import os import subprocess import sys +import time import unittest from variable_expander import VariableExpander @@ -39,16 +40,18 @@ class Config: class InstallerTest(unittest.TestCase): """Tests a test case in the config file.""" - def __init__(self, test, config, variable_expander): + def __init__(self, name, test, config, variable_expander): """Constructor. Args: + name: The name of this test. test: An array of alternating state names and action names, starting and ending with state names. config: The Config object. variable_expander: A VariableExpander object. """ super(InstallerTest, self).__init__() + self._name = name self._test = test self._config = config self._variable_expander = variable_expander @@ -62,7 +65,14 @@ class InstallerTest(unittest.TestCase): A string created by joining state names and action names together with ' -> ', for example, 'Test: clean -> install chrome -> chrome_installed'. """ - return 'Test: %s\n' % (' -> '.join(self._test)) + return '%s: %s\n' % (self._name, ' -> '.join(self._test)) + + def id(self): + """Returns the name of the test.""" + # Overridden from unittest.TestCase so that id() contains the name of the + # test case from the config file in place of the name of this class's test + # function. + return unittest.TestCase.id(self).replace(self._testMethodName, self._name) def runTest(self): """Run the test case.""" @@ -208,7 +218,8 @@ def ParseConfigFile(filename): Returns: A Config object. """ - config_data = json.load(open(filename, 'r')) + with open(filename, 'r') as fp: + config_data = json.load(fp) directory = os.path.dirname(os.path.abspath(filename)) config = Config() @@ -221,27 +232,6 @@ def ParseConfigFile(filename): return config -def RunTests(mini_installer_path, config, force_clean): - """Tests the installer using the given Config object. - - Args: - mini_installer_path: The path to mini_installer.exe. - config: A Config object. - force_clean: A boolean indicating whether to force cleaning existing - installations. - - Returns: - True if all the tests passed, or False otherwise. - """ - suite = unittest.TestSuite() - variable_expander = VariableExpander(mini_installer_path) - RunCleanCommand(force_clean, variable_expander) - for test in config.tests: - suite.addTest(InstallerTest(test, config, variable_expander)) - result = unittest.TextTestRunner(verbosity=2).run(suite) - return result.wasSuccessful() - - def IsComponentBuild(mini_installer_path): """ Invokes the mini_installer asking whether it is a component build. @@ -251,43 +241,132 @@ def IsComponentBuild(mini_installer_path): Returns: True if the mini_installer is a component build, False otherwise. """ - query_command = mini_installer_path + ' --query-component-build' - script_dir = os.path.dirname(os.path.abspath(__file__)) - exit_status = subprocess.call(query_command, shell=True, cwd=script_dir) + query_command = [ mini_installer_path, '--query-component-build' ] + exit_status = subprocess.call(query_command) return exit_status == 0 def main(): - usage = 'usage: %prog [options] config_filename' - parser = optparse.OptionParser(usage, description='Test the installer.') - parser.add_option('--build-dir', default='out', - help='Path to main build directory (the parent of the ' - 'Release or Debug directory)') - parser.add_option('--target', default='Release', - help='Build target (Release or Debug)') - parser.add_option('--force-clean', action='store_true', dest='force_clean', - default=False, help='Force cleaning existing installations') - options, args = parser.parse_args() - if len(args) != 1: - parser.error('Incorrect number of arguments.') - config_filename = args[0] - - mini_installer_path = os.path.join(options.build_dir, options.target, + parser = argparse.ArgumentParser() + parser.add_argument('--build-dir', default='out', + help='Path to main build directory (the parent of the ' + 'Release or Debug directory)') + parser.add_argument('--target', default='Release', + help='Build target (Release or Debug)') + parser.add_argument('--force-clean', action='store_true', default=False, + help='Force cleaning existing installations') + parser.add_argument('-v', '--verbose', action='count', default=0, + help='Increase test runner verbosity level') + parser.add_argument('--write-full-results-to', metavar='FILENAME', + help='Path to write the list of full results to.') + parser.add_argument('--config', metavar='FILENAME', + help='Path to test configuration file') + parser.add_argument('test', nargs='*', + help='Name(s) of tests to run.') + args = parser.parse_args() + if not args.config: + parser.error('missing mandatory --config FILENAME argument') + + mini_installer_path = os.path.join(args.build_dir, args.target, 'mini_installer.exe') assert os.path.exists(mini_installer_path), ('Could not find file %s' % mini_installer_path) + suite = unittest.TestSuite() + # Set the env var used by mini_installer.exe to decide to not show UI. os.environ['MINI_INSTALLER_TEST'] = '1' - if IsComponentBuild(mini_installer_path): + is_component_build = IsComponentBuild(mini_installer_path) + if not is_component_build: + config = ParseConfigFile(args.config) + + variable_expander = VariableExpander(mini_installer_path) + RunCleanCommand(args.force_clean, variable_expander) + for test in config.tests: + # If tests were specified via |tests|, their names are formatted like so: + test_name = '%s.%s.%s' % (InstallerTest.__module__, + InstallerTest.__name__, + test['name']) + if not args.test or test_name in args.test: + suite.addTest(InstallerTest(test['name'], test['traversal'], config, + variable_expander)) + + result = unittest.TextTestRunner(verbosity=(args.verbose + 1)).run(suite) + if is_component_build: print ('Component build is currently unsupported by the mini_installer: ' 'http://crbug.com/377839') - return 0 + if args.write_full_results_to: + with open(args.write_full_results_to, 'w') as fp: + json.dump(_FullResults(suite, result, {}), fp, indent=2) + fp.write("\n") + return 0 if result.wasSuccessful() else 1 + + +# TODO(dpranke): Find a way for this to be shared with the mojo and other tests. +TEST_SEPARATOR = '.' + + +def _FullResults(suite, result, metadata): + """Convert the unittest results to the Chromium JSON test result format. + + This matches run-webkit-tests (the layout tests) and the flakiness dashboard. + """ + + full_results = {} + full_results['interrupted'] = False + full_results['path_delimiter'] = TEST_SEPARATOR + full_results['version'] = 3 + full_results['seconds_since_epoch'] = time.time() + for md in metadata: + key, val = md.split('=', 1) + full_results[key] = val + + all_test_names = _AllTestNames(suite) + failed_test_names = _FailedTestNames(result) + + full_results['num_failures_by_type'] = { + 'FAIL': len(failed_test_names), + 'PASS': len(all_test_names) - len(failed_test_names), + } + + full_results['tests'] = {} + + for test_name in all_test_names: + value = {} + value['expected'] = 'PASS' + if test_name in failed_test_names: + value['actual'] = 'FAIL' + value['is_unexpected'] = True + else: + value['actual'] = 'PASS' + _AddPathToTrie(full_results['tests'], test_name, value) + + return full_results + + +def _AllTestNames(suite): + test_names = [] + # _tests is protected pylint: disable=W0212 + for test in suite._tests: + if isinstance(test, unittest.suite.TestSuite): + test_names.extend(_AllTestNames(test)) + else: + test_names.append(test.id()) + return test_names + + +def _FailedTestNames(result): + return set(test.id() for test, _ in result.failures + result.errors) + - config = ParseConfigFile(config_filename) - if not RunTests(mini_installer_path, config, options.force_clean): - return 1 - return 0 +def _AddPathToTrie(trie, path, value): + if TEST_SEPARATOR not in path: + trie[path] = value + return + directory, rest = path.split(TEST_SEPARATOR, 1) + if directory not in trie: + trie[directory] = {} + _AddPathToTrie(trie[directory], rest, value) if __name__ == '__main__': diff --git a/chrome/test/nacl/nacl_browsertest.cc b/chrome/test/nacl/nacl_browsertest.cc index 377640d460..30b6053091 100644 --- a/chrome/test/nacl/nacl_browsertest.cc +++ b/chrome/test/nacl/nacl_browsertest.cc @@ -18,6 +18,7 @@ #include "base/process/launch.h" #include "base/strings/string_number_conversions.h" #include "base/win/windows_version.h" +#include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" #include "chrome/test/nacl/nacl_browsertest_util.h" #include "components/nacl/browser/nacl_browser.h" @@ -174,7 +175,7 @@ base::FilePath::StringType NumberOfCoresAsFilePathString() { SYSTEM_INFO system_info; GetSystemInfo(&system_info); #if TELEMETRY - fprintf(stderr, "browser says nprocessors = %d\n", + fprintf(stderr, "browser says nprocessors = %lu\n", system_info.dwNumberOfProcessors); fflush(NULL); #endif @@ -263,9 +264,8 @@ class NaClBrowserTestPnaclDebug : public NaClBrowserTestPnacl { // lets the app continue, so that the load progress event completes. CommandLine cmd(base::FilePath(FILE_PATH_LITERAL("python"))); base::FilePath script; - PathService::Get(base::DIR_SOURCE_ROOT, &script); - script = script.AppendASCII( - "chrome/browser/nacl_host/test/debug_stub_browser_tests.py"); + PathService::Get(chrome::DIR_TEST_DATA, &script); + script = script.AppendASCII("nacl/debug_stub_browser_tests.py"); cmd.AppendArgPath(script); cmd.AppendArg(base::IntToString(debug_stub_port)); cmd.AppendArg("continue"); @@ -370,17 +370,13 @@ IN_PROC_BROWSER_TEST_F(NaClBrowserTestPnacl, IN_PROC_BROWSER_TEST_F(NaClBrowserTestPnacl, MAYBE_PNACL(PnaclExceptionHandlingDisabled)) { RunNaClIntegrationTest(FILE_PATH_LITERAL( - "pnacl_exception_handling_disabled.html")); + "pnacl_hw_eh_disabled.html")); } IN_PROC_BROWSER_TEST_F(NaClBrowserTestPnacl, PnaclMimeType) { RunLoadTest(FILE_PATH_LITERAL("pnacl_mime_type.html")); } -IN_PROC_BROWSER_TEST_F(NaClBrowserTestPnaclDisabled, PnaclMimeType) { - RunLoadTest(FILE_PATH_LITERAL("pnacl_mime_type.html")); -} - class NaClBrowserTestNewlibStdoutPM : public NaClBrowserTestNewlib { public: virtual void SetUpInProcessBrowserTestFixture() OVERRIDE { @@ -444,13 +440,8 @@ IN_PROC_BROWSER_TEST_F(NaClBrowserTestNewlibStderrPM, RedirectBg1) { } // TODO(ncbray) support glibc and PNaCl -#if defined(OS_MACOSX) -// crbug.com/375894 -#define MAYBE_MimeHandler DISABLED_MimeHandler -#else -#define MAYBE_MimeHandler MimeHandler -#endif -IN_PROC_BROWSER_TEST_F(NaClBrowserTestNewlibExtension, MAYBE_MimeHandler) { +// flaky: crbug.com/375894 +IN_PROC_BROWSER_TEST_F(NaClBrowserTestNewlibExtension, DISABLED_MimeHandler) { RunNaClIntegrationTest(FILE_PATH_LITERAL( "ppapi_extension_mime_handler.html")); } diff --git a/chrome/test/nacl/nacl_browsertest_util.cc b/chrome/test/nacl/nacl_browsertest_util.cc index 9c1d57d8ac..2112893003 100644 --- a/chrome/test/nacl/nacl_browsertest_util.cc +++ b/chrome/test/nacl/nacl_browsertest_util.cc @@ -188,15 +188,6 @@ static void AddPnaclParm(const base::FilePath::StringType& url, } } -static void AddPnaclDisabledParm(const base::FilePath::StringType& url, - base::FilePath::StringType* url_with_parm) { - if (url.find(FILE_PATH_LITERAL("?")) == base::FilePath::StringType::npos) { - *url_with_parm = url + FILE_PATH_LITERAL("?pnacl_disabled=1"); - } else { - *url_with_parm = url + FILE_PATH_LITERAL("&pnacl_disabled=1"); - } -} - NaClBrowserTestBase::NaClBrowserTestBase() { } @@ -208,11 +199,6 @@ void NaClBrowserTestBase::SetUpCommandLine(base::CommandLine* command_line) { } void NaClBrowserTestBase::SetUpOnMainThread() { - // Sanity check. - base::FilePath plugin_lib; - ASSERT_TRUE(PathService::Get(chrome::FILE_NACL_PLUGIN, &plugin_lib)); - ASSERT_TRUE(base::PathExists(plugin_lib)) << plugin_lib.value(); - ASSERT_TRUE(StartTestServer()) << "Cannot start test server."; } @@ -224,10 +210,6 @@ bool NaClBrowserTestBase::IsAPnaclTest() { return false; } -bool NaClBrowserTestBase::IsPnaclDisabled() { - return false; -} - GURL NaClBrowserTestBase::TestURL( const base::FilePath::StringType& url_fragment) { base::FilePath expanded_url = base::FilePath(FILE_PATH_LITERAL("files")); @@ -253,9 +235,6 @@ void NaClBrowserTestBase::RunLoadTest( AddPnaclParm(test_file, &test_file_with_pnacl); } base::FilePath::StringType test_file_with_both = test_file_with_pnacl; - if (IsPnaclDisabled()) { - AddPnaclDisabledParm(test_file_with_pnacl, &test_file_with_both); - } bool ok = RunJavascriptTest(TestURL(test_file_with_both), &handler); ASSERT_TRUE(ok) << handler.error_message(); ASSERT_TRUE(handler.test_passed()) << "Test failed."; @@ -269,9 +248,6 @@ void NaClBrowserTestBase::RunNaClIntegrationTest( AddPnaclParm(url_fragment, &url_fragment_with_pnacl); } base::FilePath::StringType url_fragment_with_both = url_fragment_with_pnacl; - if (IsPnaclDisabled()) { - AddPnaclDisabledParm(url_fragment_with_pnacl, &url_fragment_with_both); - } bool ok = RunJavascriptTest(full_url ? GURL(url_fragment_with_both) : TestURL(url_fragment_with_both), @@ -308,23 +284,6 @@ bool NaClBrowserTestPnacl::IsAPnaclTest() { return true; } -base::FilePath::StringType NaClBrowserTestPnaclDisabled::Variant() { - return FILE_PATH_LITERAL("pnacl"); -} - -bool NaClBrowserTestPnaclDisabled::IsAPnaclTest() { - return true; -} - -bool NaClBrowserTestPnaclDisabled::IsPnaclDisabled() { - return true; -} -void NaClBrowserTestPnaclDisabled::SetUpCommandLine( - base::CommandLine* command_line) { - NaClBrowserTestBase::SetUpCommandLine(command_line); - command_line->AppendSwitch(switches::kDisablePnacl); -} - base::FilePath::StringType NaClBrowserTestNonSfiMode::Variant() { return FILE_PATH_LITERAL("libc-free"); } diff --git a/chrome/test/nacl/nacl_browsertest_util.h b/chrome/test/nacl/nacl_browsertest_util.h index 7f74379d94..c972c2f72c 100644 --- a/chrome/test/nacl/nacl_browsertest_util.h +++ b/chrome/test/nacl/nacl_browsertest_util.h @@ -76,8 +76,6 @@ class NaClBrowserTestBase : public InProcessBrowserTest { virtual bool IsAPnaclTest(); - virtual bool IsPnaclDisabled(); - // Map a file relative to the variant directory to a URL served by the test // web server. GURL TestURL(const base::FilePath::StringType& url_fragment); @@ -132,19 +130,6 @@ class NaClBrowserTestPnaclNonSfi : public NaClBrowserTestBase { virtual base::FilePath::StringType Variant() OVERRIDE; }; -// Class used to test that when --disable-pnacl is specified the PNaCl mime -// type is not available. -class NaClBrowserTestPnaclDisabled : public NaClBrowserTestBase { - public: - virtual void SetUpCommandLine(base::CommandLine* command_line) OVERRIDE; - - virtual base::FilePath::StringType Variant() OVERRIDE; - - virtual bool IsAPnaclTest() OVERRIDE; - - virtual bool IsPnaclDisabled() OVERRIDE; -}; - class NaClBrowserTestNonSfiMode : public NaClBrowserTestBase { public: virtual void SetUpCommandLine(base::CommandLine* command_line) OVERRIDE; @@ -183,8 +168,10 @@ class NaClBrowserTestNewlibExtension : public NaClBrowserTestNewlib { # define MAYBE_GLIBC(test_name) DISABLED_##test_name #endif -// ASan does not work with libc-free context, so disable the test. -#if defined(OS_LINUX) && !defined(ADDRESS_SANITIZER) +// Sanitizers internally use some syscalls which non-SFI NaCl disallows. +#if defined(OS_LINUX) && !defined(ADDRESS_SANITIZER) && \ + !defined(THREAD_SANITIZER) && !defined(MEMORY_SANITIZER) && \ + !defined(LEAK_SANITIZER) # define MAYBE_NONSFI(test_case) test_case #else # define MAYBE_NONSFI(test_case) DISABLED_##test_case diff --git a/chrome/test/ppapi/ppapi_browsertest.cc b/chrome/test/ppapi/ppapi_browsertest.cc index 7735b40974..bece9c7a06 100644 --- a/chrome/test/ppapi/ppapi_browsertest.cc +++ b/chrome/test/ppapi/ppapi_browsertest.cc @@ -612,7 +612,13 @@ TEST_PPAPI_NACL(VarResource) #undef PostMessage #endif -IN_PROC_BROWSER_TEST_F(OutOfProcessPPAPITest, PostMessage) { +#if defined(OS_WIN) +// http://crbug.com/95557 +#define MAYBE_PostMessage DISABLED_PostMessage +#else +#define MAYBE_PostMessage PostMessage +#endif +IN_PROC_BROWSER_TEST_F(OutOfProcessPPAPITest, MAYBE_PostMessage) { RUN_POSTMESSAGE_SUBTESTS; } IN_PROC_BROWSER_TEST_F(PPAPINaClNewlibTest, PostMessage) { @@ -674,19 +680,13 @@ IN_PROC_BROWSER_TEST_F(OutOfProcessPPAPIPrivateTest, MAYBE_FileIO_Private) { RUN_FILEIO_PRIVATE_SUBTESTS; } -// Flaky on XP; times out, http://crbug.com/313401 -#if defined(OS_WIN) -#define MAYBE_NaCl_Newlib_FileIO DISABLED_FileIO -#define MAYBE_NaCl_Newlib_FileIO_Private DISABLED_FileIO_Private -#else -#define MAYBE_NaCl_Newlib_FileIO FileIO -#define MAYBE_NaCl_Newlib_FileIO_Private FileIO_Private -#endif -IN_PROC_BROWSER_TEST_F(PPAPINaClNewlibTest, MAYBE_NaCl_Newlib_FileIO) { +// http://crbug.com/313401 +IN_PROC_BROWSER_TEST_F(PPAPINaClNewlibTest, DISABLED_FileIO) { RUN_FILEIO_SUBTESTS; } +// http://crbug.com/313401 IN_PROC_BROWSER_TEST_F(PPAPIPrivateNaClNewlibTest, - MAYBE_NaCl_Newlib_FileIO_Private) { + DISABLED_NaCl_Newlib_FileIO_Private) { RUN_FILEIO_PRIVATE_SUBTESTS; } @@ -699,18 +699,12 @@ IN_PROC_BROWSER_TEST_F(PPAPIPrivateNaClGLibcTest, DISABLED_FileIO_Private) { RUN_FILEIO_PRIVATE_SUBTESTS; } -// Flaky on XP; times out, http://crbug.com/313205 -#if defined(OS_WIN) -#define MAYBE_PNaCl_FileIO DISABLED_FileIO -#define MAYBE_PNaCl_FileIO_Private DISABLED_FileIO_Private -#else -#define MAYBE_PNaCl_FileIO FileIO -#define MAYBE_PNaCl_FileIO_Private FileIO_Private -#endif -IN_PROC_BROWSER_TEST_F(PPAPINaClPNaClTest, MAYBE_PNaCl_FileIO) { +// http://crbug.com/313205 +IN_PROC_BROWSER_TEST_F(PPAPINaClPNaClTest, DISABLED_FileIO) { RUN_FILEIO_SUBTESTS; } -IN_PROC_BROWSER_TEST_F(PPAPIPrivateNaClPNaClTest, MAYBE_PNaCl_FileIO_Private) { +IN_PROC_BROWSER_TEST_F(PPAPIPrivateNaClPNaClTest, + DISABLED_PNaCl_FileIO_Private) { RUN_FILEIO_PRIVATE_SUBTESTS; } @@ -994,53 +988,34 @@ IN_PROC_BROWSER_TEST_F(OutOfProcessPPAPITest, Flash) { LIST_TEST(WebSocket_UtilityBufferedAmount) \ ) -// Repeatedly flaky on WinXP Tests(1): http://crbug.com/389084 -#if defined(OS_WIN) -#define MAYBE_WebSocket1 DISABLED_WebSocket1 -#else -#define MAYBE_WebSocket1 WebSocket1 -#endif -IN_PROC_BROWSER_TEST_F(PPAPITest, MAYBE_WebSocket1) { +IN_PROC_BROWSER_TEST_F(PPAPITest, WebSocket1) { RUN_WEBSOCKET_SUBTESTS_1; } - -// Repeatedly flaky on Win7 Tests(1): http://crbug.com/389084 -#if defined(OS_WIN) -#define MAYBE_WebSocket2 DISABLED_WebSocket2 -#else -#define MAYBE_WebSocket2 WebSocket2 -#endif -IN_PROC_BROWSER_TEST_F(PPAPITest, MAYBE_WebSocket2) { +IN_PROC_BROWSER_TEST_F(PPAPITest, WebSocket2) { RUN_WEBSOCKET_SUBTESTS_2; } -IN_PROC_BROWSER_TEST_F(OutOfProcessPPAPITest, MAYBE_WebSocket1) { +IN_PROC_BROWSER_TEST_F(OutOfProcessPPAPITest, WebSocket1) { RUN_WEBSOCKET_SUBTESTS_1; } -IN_PROC_BROWSER_TEST_F(OutOfProcessPPAPITest, MAYBE_WebSocket2) { +IN_PROC_BROWSER_TEST_F(OutOfProcessPPAPITest, WebSocket2) { RUN_WEBSOCKET_SUBTESTS_2; } -IN_PROC_BROWSER_TEST_F(PPAPINaClNewlibTest, WebSocket1) { +IN_PROC_BROWSER_TEST_F(PPAPINaClGLibcTest, MAYBE_GLIBC(WebSocket1)) { RUN_WEBSOCKET_SUBTESTS_1; } -IN_PROC_BROWSER_TEST_F(PPAPINaClNewlibTest, WebSocket2) { +IN_PROC_BROWSER_TEST_F(PPAPINaClGLibcTest, MAYBE_GLIBC(WebSocket2)) { RUN_WEBSOCKET_SUBTESTS_2; } -IN_PROC_BROWSER_TEST_F(PPAPINaClGLibcTest, MAYBE_GLIBC(WebSocket1)) { +IN_PROC_BROWSER_TEST_F(PPAPINaClNewlibTest, WebSocket1) { RUN_WEBSOCKET_SUBTESTS_1; } -IN_PROC_BROWSER_TEST_F(PPAPINaClGLibcTest, MAYBE_GLIBC(WebSocket2)) { +IN_PROC_BROWSER_TEST_F(PPAPINaClNewlibTest, WebSocket2) { RUN_WEBSOCKET_SUBTESTS_2; } IN_PROC_BROWSER_TEST_F(PPAPINaClPNaClTest, WebSocket1) { RUN_WEBSOCKET_SUBTESTS_1; } -// Flaky on XP Tests (3): http://crbug.com/389084 -#if defined(OS_WIN) -#define MAYBE_WebSocket2 DISABLED_WebSocket2 -#else -#define MAYBE_WebSocket2 WebSocket2 -#endif -IN_PROC_BROWSER_TEST_F(PPAPINaClPNaClTest, MAYBE_WebSocket2) { +IN_PROC_BROWSER_TEST_F(PPAPINaClPNaClTest, WebSocket2) { RUN_WEBSOCKET_SUBTESTS_2; } IN_PROC_BROWSER_TEST_F(PPAPINaClPNaClNonSfiTest, @@ -1322,7 +1297,8 @@ TEST_PPAPI_OUT_OF_PROCESS(FlashFile) // Mac/Aura reach NOTIMPLEMENTED/time out. // mac: http://crbug.com/96767 // aura: http://crbug.com/104384 -#if defined(OS_MACOSX) +// cros: http://crbug.com/396502 +#if defined(OS_MACOSX) || defined(OS_CHROMEOS) #define MAYBE_FlashFullscreen DISABLED_FlashFullscreen #else #define MAYBE_FlashFullscreen FlashFullscreen diff --git a/chrome/test/ppapi/ppapi_test.cc b/chrome/test/ppapi/ppapi_test.cc index 9a951458a7..1e35de14d5 100644 --- a/chrome/test/ppapi/ppapi_test.cc +++ b/chrome/test/ppapi/ppapi_test.cc @@ -342,9 +342,6 @@ void PPAPINaClTest::SetUpCommandLine(base::CommandLine* command_line) { } void PPAPINaClTest::SetUpOnMainThread() { - base::FilePath plugin_lib; - EXPECT_TRUE(PathService::Get(chrome::FILE_NACL_PLUGIN, &plugin_lib)); - EXPECT_TRUE(base::PathExists(plugin_lib)); } void PPAPINaClTest::RunTest(const std::string& test_case) { @@ -464,8 +461,4 @@ std::string PPAPINaClTestDisallowedSockets::BuildQuery( void PPAPIBrokerInfoBarTest::SetUpOnMainThread() { // The default content setting for the PPAPI broker is ASK. We purposefully // don't call PPAPITestBase::SetUpOnMainThread() to keep it that way. - - base::FilePath plugin_lib; - EXPECT_TRUE(PathService::Get(chrome::FILE_NACL_PLUGIN, &plugin_lib)); - EXPECT_TRUE(base::PathExists(plugin_lib)); } diff --git a/chrome/test/remoting/me2me_browsertest.cc b/chrome/test/remoting/me2me_browsertest.cc index 3d784ff2ec..a8bc82ba5d 100644 --- a/chrome/test/remoting/me2me_browsertest.cc +++ b/chrome/test/remoting/me2me_browsertest.cc @@ -16,17 +16,12 @@ class Me2MeBrowserTest : public RemoteDesktopBrowserTest { void ConnectPinlessAndCleanupPairings(bool cleanup_all); bool IsPairingSpinnerHidden(); + bool WaitForFullscreenChange(bool expect_fullscreen); }; IN_PROC_BROWSER_TEST_F(Me2MeBrowserTest, MANUAL_Me2Me_Connect_Local_Host) { - VerifyInternetAccess(); - Install(); - LaunchChromotingApp(); - - // Authorize, Authenticate, and Approve. - Auth(); - ExpandMe2Me(); + SetUpTestForMe2Me(); ConnectToLocalHost(false); @@ -60,6 +55,19 @@ IN_PROC_BROWSER_TEST_F(Me2MeBrowserTest, IN_PROC_BROWSER_TEST_F(Me2MeBrowserTest, MANUAL_Me2Me_Connect_Pinless) { + SetUpTestForMe2Me(); + + ASSERT_FALSE(HtmlElementVisible("paired-client-manager-message")) + << "The host must have no pairings before running the pinless test."; + + // Test that cleanup works with either the Delete or Delete all buttons. + ConnectPinlessAndCleanupPairings(false); + ConnectPinlessAndCleanupPairings(true); + + Cleanup(); +} + +IN_PROC_BROWSER_TEST_F(Me2MeBrowserTest, MANUAL_Me2Me_Fullscreen) { VerifyInternetAccess(); Install(); LaunchChromotingApp(); @@ -68,12 +76,29 @@ IN_PROC_BROWSER_TEST_F(Me2MeBrowserTest, Auth(); ExpandMe2Me(); - ASSERT_FALSE(HtmlElementVisible("paired-client-manager-message")) - << "The host must have no pairings before running the pinless test."; + ConnectToLocalHost(false); - // Test that cleanup works with either the Delete or Delete all buttons. - ConnectPinlessAndCleanupPairings(false); - ConnectPinlessAndCleanupPairings(true); + // Verify that we're initially not full-screen. + EXPECT_FALSE(ExecuteScriptAndExtractBool( + "remoting.fullscreen.isActive()")); + + // Click the full-screen button and verify that it activates full-screen mode. + ClickOnControl("toggle-full-screen"); + EXPECT_TRUE(WaitForFullscreenChange(true)); + + // Click the full-screen button again and verify that it deactivates + // full-screen mode. + ClickOnControl("toggle-full-screen"); + EXPECT_TRUE(WaitForFullscreenChange(false)); + + // Enter full-screen mode again, then disconnect and verify that full-screen + // mode is deactivated upon disconnection. + // TODO(jamiewalch): For the v2 app, activate full-screen mode indirectly by + // maximizing the window for the second test. + ClickOnControl("toggle-full-screen"); + EXPECT_TRUE(WaitForFullscreenChange(true)); + DisconnectMe2Me(); + EXPECT_TRUE(WaitForFullscreenChange(false)); Cleanup(); } @@ -162,4 +187,17 @@ bool Me2MeBrowserTest::IsPairingSpinnerHidden() { return !HtmlElementVisible("paired-client-manager-dialog-working"); } +bool Me2MeBrowserTest::WaitForFullscreenChange(bool expect_fullscreen) { + std::string javascript = expect_fullscreen ? + "remoting.fullscreen.isActive()" : + "!remoting.fullscreen.isActive()"; + ConditionalTimeoutWaiter waiter( + base::TimeDelta::FromSeconds(10), + base::TimeDelta::FromMilliseconds(500), + base::Bind(&RemoteDesktopBrowserTest::IsHostActionComplete, + active_web_contents(), + javascript)); + return waiter.Wait(); +} + } // namespace remoting diff --git a/chrome/test/remoting/pin_browsertest.cc b/chrome/test/remoting/pin_browsertest.cc index eac2a3f3d3..742113ee28 100644 --- a/chrome/test/remoting/pin_browsertest.cc +++ b/chrome/test/remoting/pin_browsertest.cc @@ -29,7 +29,8 @@ IN_PROC_BROWSER_TEST_F(RemoteDesktopBrowserTest, MANUAL_Invalid_PIN) { LoadScript(content, FILE_PATH_LITERAL("invalid_pin_browser_test.js")); RunJavaScriptTest(content, "Invalid_PIN", "{" - "pin: '" + me2me_pin() + "'" + // Append arbitrary characters after the pin to make it invalid. + "pin: '" + me2me_pin() + "ABC'" "}"); Cleanup(); diff --git a/chrome/test/remoting/remote_desktop_browsertest.cc b/chrome/test/remoting/remote_desktop_browsertest.cc index 8cd1e50570..6510489bb7 100644 --- a/chrome/test/remoting/remote_desktop_browsertest.cc +++ b/chrome/test/remoting/remote_desktop_browsertest.cc @@ -120,7 +120,7 @@ void RemoteDesktopBrowserTest::InstallChromotingAppUnpacked() { installer->set_prompt_for_plugins(false); content::WindowedNotificationObserver observer( - chrome::NOTIFICATION_EXTENSION_LOADED_DEPRECATED, + extensions::NOTIFICATION_EXTENSION_LOADED_DEPRECATED, content::NotificationService::AllSources()); installer->Load(webapp_unpacked_); @@ -343,27 +343,12 @@ void RemoteDesktopBrowserTest::ExpandMe2Me() { EXPECT_TRUE(HtmlElementVisible("me2me-content")); EXPECT_FALSE(HtmlElementVisible("me2me-first-run")); - - // Wait until localHost is initialized. This can take a while. - ConditionalTimeoutWaiter waiter( - base::TimeDelta::FromSeconds(3), - base::TimeDelta::FromSeconds(1), - base::Bind(&RemoteDesktopBrowserTest::IsLocalHostReady, this)); - EXPECT_TRUE(waiter.Wait()); - - EXPECT_TRUE(ExecuteScriptAndExtractBool( - "remoting.hostList.localHost_.hostName && " - "remoting.hostList.localHost_.hostId && " - "remoting.hostList.localHost_.status && " - "remoting.hostList.localHost_.status == 'ONLINE'")); } void RemoteDesktopBrowserTest::DisconnectMe2Me() { // The chromoting extension should be installed. ASSERT_TRUE(extension_); - // The active tab should have the chromoting app loaded. - ASSERT_EQ(Chromoting_Main_URL(), GetCurrentURL()); ASSERT_TRUE(RemoteDesktopBrowserTest::IsSessionConnected()); ClickOnControl("toolbar-stub"); @@ -483,9 +468,10 @@ void RemoteDesktopBrowserTest::SetUpTestForMe2Me() { VerifyInternetAccess(); Install(); LaunchChromotingApp(); + LoadScript(app_web_content(), FILE_PATH_LITERAL("browser_test.js")); Auth(); ExpandMe2Me(); - LoadScript(app_web_content(), FILE_PATH_LITERAL("browser_test.js")); + EnsureRemoteConnectionEnabled(); } void RemoteDesktopBrowserTest::Auth() { @@ -494,6 +480,20 @@ void RemoteDesktopBrowserTest::Auth() { Approve(); } +void RemoteDesktopBrowserTest::EnsureRemoteConnectionEnabled() { + // browser_test.ensureRemoteConnectionEnabled is defined in + // browser_test.js, which must be loaded before calling this function. + // TODO(kelvinp): This function currently only works on linux when the user is + // already part of the chrome-remote-desktop group. Extend this functionality + // to Mac (https://crbug.com/397576) and Windows (https://crbug.com/397575). + bool result; + EXPECT_TRUE(content::ExecuteScriptAndExtractBool( + app_web_content(), + "browserTest.ensureRemoteConnectionEnabled(" + me2me_pin() + ")", + &result)); + EXPECT_TRUE(result) << "Cannot start the host with Pin:" << me2me_pin(); +} + void RemoteDesktopBrowserTest::ConnectToLocalHost(bool remember_pin) { // Verify that the local host is online. ASSERT_TRUE(ExecuteScriptAndExtractBool( diff --git a/chrome/test/remoting/remote_desktop_browsertest.h b/chrome/test/remoting/remote_desktop_browsertest.h index 10755b8c27..e5659945c9 100644 --- a/chrome/test/remoting/remote_desktop_browsertest.h +++ b/chrome/test/remoting/remote_desktop_browsertest.h @@ -143,6 +143,10 @@ class RemoteDesktopBrowserTest : public extensions::PlatformAppBrowserTest { // on the chromoting main page authenticated and ready to go. void Auth(); + // Ensures that the host is started locally with |me2me_pin()|. + // Browser_test.js must be loaded before calling this function. + void EnsureRemoteConnectionEnabled(); + // Connect to the local host through Me2Me. void ConnectToLocalHost(bool remember_pin); |