Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(75)

Unified Diff: extensions/browser/api/runtime/restart_after_delay_api_unittest.cc

Issue 1970613003: Add a new app API to enable watchdog behavior restarts in kiosk apps (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Comments Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: extensions/browser/api/runtime/restart_after_delay_api_unittest.cc
diff --git a/extensions/browser/api/runtime/restart_after_delay_api_unittest.cc b/extensions/browser/api/runtime/restart_after_delay_api_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..96bdc1a22ac07cbb338c5e54fc16cd6f60cf1940
--- /dev/null
+++ b/extensions/browser/api/runtime/restart_after_delay_api_unittest.cc
@@ -0,0 +1,185 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/callback_helpers.h"
+#include "base/run_loop.h"
+#include "components/pref_registry/pref_registry_syncable.h"
+#include "extensions/browser/api/runtime/runtime_api.h"
+#include "extensions/browser/api_test_utils.h"
+#include "extensions/browser/api_unittest.h"
+#include "extensions/browser/test_extensions_browser_client.h"
+
+namespace extensions {
+
+namespace {
+
+// An intercepter of the real RuntimeAPIDelegate that simulates a successful
+// restart request every time.
+class RestartOnWatchdogApiDelegate : public RuntimeAPIDelegate {
Devlin 2016/06/03 21:26:47 Could we just inherit from TestRuntimeAPIDelegate
afakhry 2016/06/03 23:06:41 Done. This was needed for the browser tests as I n
+ public:
+ // Takes ownership of the |real_api_delegate|.
+ RestartOnWatchdogApiDelegate(
+ std::unique_ptr<RuntimeAPIDelegate> real_api_delegate)
+ : real_api_delegate_(std::move(real_api_delegate)) {}
+ ~RestartOnWatchdogApiDelegate() override {}
+
+ // RuntimeAPIDelegate:
+ void AddUpdateObserver(UpdateObserver* observer) override {
+ real_api_delegate_->AddUpdateObserver(observer);
+ }
+
+ void RemoveUpdateObserver(UpdateObserver* observer) override {
+ real_api_delegate_->RemoveUpdateObserver(observer);
+ }
+
+ base::Version GetPreviousExtensionVersion(
+ const Extension* extension) override {
+ return real_api_delegate_->GetPreviousExtensionVersion(extension);
+ }
+
+ void ReloadExtension(const std::string& extension_id) override {
+ real_api_delegate_->ReloadExtension(extension_id);
+ }
+
+ bool CheckForUpdates(const std::string& extension_id,
+ const UpdateCheckCallback& callback) override {
+ return real_api_delegate_->CheckForUpdates(extension_id, callback);
+ }
+
+ void OpenURL(const GURL& uninstall_url) override {
+ real_api_delegate_->OpenURL(uninstall_url);
+ }
+
+ bool GetPlatformInfo(api::runtime::PlatformInfo* info) override {
+ return real_api_delegate_->GetPlatformInfo(info);
+ }
+
+ bool RestartDevice(std::string* error_message) override {
+ if (!quit_closure_.is_null())
+ base::ResetAndReturn(&quit_closure_).Run();
+
+ *error_message = "Success.";
+ restart_done_ = true;
+ return true;
+ }
+
+ base::TimeTicks WaitForSuccessfulRestart() {
+ if (!restart_done_) {
+ base::RunLoop run_loop;
+ quit_closure_ = run_loop.QuitClosure();
+ run_loop.Run();
+ }
+ restart_done_ = false;
+ return base::TimeTicks::Now();
+ }
+
+ private:
+ std::unique_ptr<RuntimeAPIDelegate> real_api_delegate_;
+
+ base::Closure quit_closure_;
+
+ bool restart_done_ = false;
+
+ DISALLOW_COPY_AND_ASSIGN(RestartOnWatchdogApiDelegate);
+};
+
+} // namespace
+
+class RestartAfterDelayApiTest : public ApiUnitTest {
+ public:
+ RestartAfterDelayApiTest() : api_delegate_(nullptr) {}
+ ~RestartAfterDelayApiTest() override {}
+
+ void SetUp() override {
+ ApiUnitTest::SetUp();
+
+ RuntimeAPI* runtime_api =
+ RuntimeAPI::GetFactoryInstance()->Get(browser_context());
+ api_delegate_ =
+ new RestartOnWatchdogApiDelegate(std::move(runtime_api->delegate_));
+ runtime_api->delegate_.reset(api_delegate_);
+ runtime_api->set_min_duration_between_restarts_for_testing(
+ base::TimeDelta::FromSeconds(2));
+ runtime_api->AllowNonKiostAppsInRestartOnWatchdogForTesting();
+
+ RuntimeAPI::RegisterPrefs(
+ extensions_browser_client()->testing_pref_service()->registry());
+ }
+
+ base::TimeTicks WaitForSuccessfulRestart() {
+ return api_delegate_->WaitForSuccessfulRestart();
+ }
+
+ bool IsWatchdogTimerRunning() {
+ return RuntimeAPI::GetFactoryInstance()
+ ->Get(browser_context())
+ ->watchdog_timer_.IsRunning();
+ }
+
+ base::TimeTicks desired_restart_time() {
+ return RuntimeAPI::GetFactoryInstance()
+ ->Get(browser_context())
+ ->watchdog_timer_.desired_run_time();
+ }
+
+ void RunFunctionAssertNoError(UIThreadExtensionFunction* function,
+ const std::string& args) {
+ scoped_refptr<ExtensionFunction> function_owner(function);
+ function->set_extension(extension());
+ function->set_has_callback(true);
+ api_test_utils::RunFunction(function, args, browser_context());
+ ASSERT_TRUE(function->GetError().empty()) << function->GetError();
+ }
+
+ private:
+ RestartOnWatchdogApiDelegate* api_delegate_; // Not Owned.
+
+ DISALLOW_COPY_AND_ASSIGN(RestartAfterDelayApiTest);
+};
+
+TEST_F(RestartAfterDelayApiTest, RestartAfterDelayTest) {
+ RunFunctionAssertNoError(new RuntimeRestartAfterDelayFunction(), "[-1]");
+ ASSERT_FALSE(IsWatchdogTimerRunning());
Devlin 2016/06/03 21:26:47 nit: let's add a test for -2, and, optionally, a "
afakhry 2016/06/03 23:06:41 Both done.
+
+ // Request a restart after 3 seconds.
+ base::TimeTicks now = base::TimeTicks::Now();
+ RunFunctionAssertNoError(new RuntimeRestartAfterDelayFunction(), "[3]");
+ ASSERT_TRUE(IsWatchdogTimerRunning());
+ ASSERT_GE(desired_restart_time() - now, base::TimeDelta::FromSeconds(3));
+
+ // Request another restart after 4 seconds. It should reschedule the previous
+ // request.
+ now = base::TimeTicks::Now();
+ RunFunctionAssertNoError(new RuntimeRestartAfterDelayFunction(), "[4]");
+ ASSERT_TRUE(IsWatchdogTimerRunning());
+ ASSERT_GE(desired_restart_time() - now, base::TimeDelta::FromSeconds(4));
+
+ // Cancel restart requests.
+ RunFunctionAssertNoError(new RuntimeRestartAfterDelayFunction(), "[-1]");
+ ASSERT_FALSE(IsWatchdogTimerRunning());
+
+ // Schedule a restart and wait for it to happen.
+ now = base::TimeTicks::Now();
+ RunFunctionAssertNoError(new RuntimeRestartAfterDelayFunction(), "[1]");
+ ASSERT_TRUE(IsWatchdogTimerRunning());
+ ASSERT_GE(desired_restart_time() - now, base::TimeDelta::FromSeconds(1));
+ base::TimeTicks last_restart_time = WaitForSuccessfulRestart();
+ ASSERT_FALSE(IsWatchdogTimerRunning());
+ ASSERT_GE(base::TimeTicks::Now() - now, base::TimeDelta::FromSeconds(1));
+
+ // This is a restart request that will be throttled, because it happens too
+ // soon after a successful restart.
+ RunFunctionAssertNoError(new RuntimeRestartAfterDelayFunction(), "[1]");
+ ASSERT_TRUE(IsWatchdogTimerRunning());
+ // Restart will happen 2 seconds later, even though the request was just one
+ // second.
+ ASSERT_NEAR((desired_restart_time() - last_restart_time).InSecondsF(),
+ base::TimeDelta::FromSeconds(2).InSecondsF(), 0.01);
+ base::TimeTicks this_restart_time = WaitForSuccessfulRestart();
Devlin 2016/06/03 21:26:47 Do we need to wait for this restart, if we already
afakhry 2016/06/03 23:06:41 Right. We don't have to wait for it. Done. Tests o
+ ASSERT_FALSE(IsWatchdogTimerRunning());
+ ASSERT_NEAR((this_restart_time - last_restart_time).InSecondsF(),
+ base::TimeDelta::FromSeconds(2).InSecondsF(), 0.01);
+}
+
+} // namespace extensions

Powered by Google App Engine
This is Rietveld 408576698