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

Unified Diff: athena/content/app_activity_unittest.cc

Issue 477523002: Athena: Adding basic resource management framework (un-/re-loading) of V2 applications (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Aaaand another rebase. Created 6 years, 4 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
« no previous file with comments | « athena/content/app_activity_registry.cc ('k') | athena/content/app_registry_impl.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: athena/content/app_activity_unittest.cc
diff --git a/athena/content/app_activity_unittest.cc b/athena/content/app_activity_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..f94cc85f1626f6f104dd15cf0f3bce7d155fa99e
--- /dev/null
+++ b/athena/content/app_activity_unittest.cc
@@ -0,0 +1,412 @@
+/// Copyright 2014 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 "athena/activity/public/activity_factory.h"
+#include "athena/activity/public/activity_manager.h"
+#include "athena/content/app_activity.h"
+#include "athena/content/app_activity_registry.h"
+#include "athena/content/public/app_content_control_delegate.h"
+#include "athena/content/public/app_registry.h"
+#include "athena/test/athena_test_base.h"
+#include "extensions/shell/browser/shell_app_window.h"
+#include "ui/aura/window.h"
+#include "ui/views/view.h"
+#include "ui/views/widget/widget.h"
+
+
+namespace content {
+class BrowserContext;
+}
+
+namespace athena {
+namespace test {
+
+namespace {
+
+// An identifier for the running apps.
+const char kDummyApp1[] = "aaaaaaa";
+const char kDummyApp2[] = "bbbbbbb";
+
+// A dummy test app activity which works without content / ShellAppWindow.
+class TestAppActivity : public AppActivity {
+ public:
+ explicit TestAppActivity(const std::string& app_id) :
+ AppActivity(NULL),
+ app_id_(app_id),
+ view_(new views::View()),
+ current_state_(ACTIVITY_VISIBLE) {
+ app_activity_registry_ =
+ AppRegistry::Get()->GetAppActivityRegistry(app_id, NULL);
+ app_activity_registry_->RegisterAppActivity(this);
+ }
+ virtual ~TestAppActivity() {
+ app_activity_registry_->UnregisterAppActivity(this);
+ }
+
+ AppActivityRegistry* app_activity_registry() {
+ return app_activity_registry_;
+ }
+
+ // Activity:
+ virtual ActivityViewModel* GetActivityViewModel() OVERRIDE {
+ return this;
+ }
+ virtual void SetCurrentState(Activity::ActivityState state) OVERRIDE {
+ current_state_ = state;
+ }
+ virtual ActivityState GetCurrentState() OVERRIDE {
+ return current_state_;
+ }
+ virtual bool IsVisible() OVERRIDE {
+ return true;
+ }
+ virtual ActivityMediaState GetMediaState() OVERRIDE {
+ return Activity::ACTIVITY_MEDIA_STATE_NONE;
+ }
+ virtual aura::Window* GetWindow() OVERRIDE {
+ return view_->GetWidget()->GetNativeWindow();
+ }
+
+ // ActivityViewModel:
+ virtual void Init() OVERRIDE {}
+ virtual SkColor GetRepresentativeColor() const OVERRIDE { return 0; }
+ virtual base::string16 GetTitle() const OVERRIDE { return title_; }
+ virtual bool UsesFrame() const OVERRIDE { return true; }
+ virtual views::View* GetContentsView() OVERRIDE { return view_; }
+ virtual void CreateOverviewModeImage() OVERRIDE {}
+
+ private:
+ // If known the registry which holds all activities for the associated app.
+ AppActivityRegistry* app_activity_registry_;
+
+ // The application ID.
+ const std::string& app_id_;
+
+ // The title of the activity.
+ base::string16 title_;
+
+ // Our view.
+ views::View* view_;
+
+ // The current state for this activity.
+ ActivityState current_state_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestAppActivity);
+};
+
+// An AppContentDelegateClass which we can query for call stats.
+class TestAppContentControlDelegate : public AppContentControlDelegate {
+ public:
+ TestAppContentControlDelegate() : unload_called_(0),
+ restart_called_(0) {}
+ virtual ~TestAppContentControlDelegate() {}
+
+ int unload_called() { return unload_called_; }
+ int restart_called() { return restart_called_; }
+ void SetExtensionID(const std::string& extension_id) {
+ extension_id_to_return_ = extension_id;
+ }
+
+ // Unload an application. Returns true when unloaded.
+ virtual bool UnloadApplication(
+ const std::string& app_id,
+ content::BrowserContext* browser_context) OVERRIDE {
+ unload_called_++;
+ // Since we did not close anything we let the framework clean up.
+ return false;
+ }
+ // Restarts an application. Returns true when the restart was initiated.
+ virtual bool RestartApplication(
+ const std::string& app_id,
+ content::BrowserContext* browser_context) OVERRIDE {
+ restart_called_++;
+ return true;
+ }
+ // Returns the application ID (or an empty string) for a given web content.
+ virtual std::string GetApplicationID(
+ content::WebContents* web_contents) OVERRIDE {
+ return extension_id_to_return_;
+ }
+
+ private:
+ int unload_called_;
+ int restart_called_;
+ std::string extension_id_to_return_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestAppContentControlDelegate);
+};
+
+} // namespace
+
+// Our testing base.
+class AppActivityTest : public AthenaTestBase {
+ public:
+ AppActivityTest() : test_app_content_control_delegate_(NULL) {}
+ virtual ~AppActivityTest() {}
+
+ // AthenaTestBase:
+ virtual void SetUp() OVERRIDE {
+ AthenaTestBase::SetUp();
+ // Create and install our TestAppContentDelegate with instrumentation.
+ test_app_content_control_delegate_ = new TestAppContentControlDelegate();
+ AppRegistry::Get()->SetDelegate(test_app_content_control_delegate_);
+ }
+
+ // A function to create an Activity.
+ TestAppActivity* CreateAppActivity(const std::string& app_id) {
+ TestAppActivity* activity = new TestAppActivity(app_id);
+ ActivityManager::Get()->AddActivity(activity);
+ return activity;
+ }
+
+ void CloseActivity(Activity* activity) {
+ delete activity;
+ RunAllPendingInMessageLoop();
+ }
+
+ // Get the position of the activity in the navigation history.
+ int GetActivityPosition(Activity* activity) {
+ aura::Window* window = activity->GetActivityViewModel()->GetContentsView()
+ ->GetWidget()->GetNativeWindow();
+ aura::Window::Windows windows = activity->GetWindow()->parent()->children();
+ for (size_t i = 0; i < windows.size(); i++) {
+ if (windows[i] == window)
+ return i;
+ }
+ return -1;
+ }
+
+ protected:
+ TestAppContentControlDelegate* test_app_content_control_delegate() {
+ return test_app_content_control_delegate_;
+ }
+
+ private:
+ TestAppContentControlDelegate* test_app_content_control_delegate_;
+
+ DISALLOW_COPY_AND_ASSIGN(AppActivityTest);
+};
+
+// Only creates one activity and destroys it.
+TEST_F(AppActivityTest, OneAppActivity) {
+ EXPECT_EQ(0, AppRegistry::Get()->NumberOfApplications());
+ {
+ TestAppActivity* app_activity = CreateAppActivity(kDummyApp1);
+ EXPECT_EQ(1, AppRegistry::Get()->NumberOfApplications());
+ EXPECT_EQ(1, app_activity->app_activity_registry()->NumberOfActivities());
+ EXPECT_EQ(AppRegistry::Get()->GetAppActivityRegistry(kDummyApp1, NULL),
+ app_activity->app_activity_registry());
+ CloseActivity(app_activity);
+ }
+ EXPECT_EQ(0, AppRegistry::Get()->NumberOfApplications());
+ EXPECT_EQ(0, test_app_content_control_delegate()->unload_called());
+ EXPECT_EQ(0, test_app_content_control_delegate()->restart_called());
+}
+
+// Test running of two applications.
+TEST_F(AppActivityTest, TwoAppsWithOneActivityEach) {
+ EXPECT_EQ(0, AppRegistry::Get()->NumberOfApplications());
+ {
+ TestAppActivity* app_activity1 = CreateAppActivity(kDummyApp1);
+ EXPECT_EQ(1, AppRegistry::Get()->NumberOfApplications());
+ EXPECT_EQ(1, app_activity1->app_activity_registry()->NumberOfActivities());
+ TestAppActivity* app_activity2 = CreateAppActivity(kDummyApp2);
+ EXPECT_EQ(2, AppRegistry::Get()->NumberOfApplications());
+ EXPECT_EQ(1, app_activity2->app_activity_registry()->NumberOfActivities());
+ EXPECT_EQ(1, app_activity1->app_activity_registry()->NumberOfActivities());
+ CloseActivity(app_activity1);
+ CloseActivity(app_activity2);
+ }
+ EXPECT_EQ(0, AppRegistry::Get()->NumberOfApplications());
+ EXPECT_EQ(0, test_app_content_control_delegate()->unload_called());
+ EXPECT_EQ(0, test_app_content_control_delegate()->restart_called());
+}
+
+// Create and destroy two activities for the same application.
+TEST_F(AppActivityTest, TwoAppActivities) {
+ EXPECT_EQ(0, AppRegistry::Get()->NumberOfApplications());
+ {
+ TestAppActivity* app_activity1 = CreateAppActivity(kDummyApp1);
+ TestAppActivity* app_activity2 = CreateAppActivity(kDummyApp1);
+ EXPECT_EQ(1, AppRegistry::Get()->NumberOfApplications());
+ EXPECT_EQ(2, app_activity1->app_activity_registry()->NumberOfActivities());
+ EXPECT_EQ(app_activity1->app_activity_registry(),
+ app_activity2->app_activity_registry());
+ CloseActivity(app_activity1);
+ EXPECT_EQ(1, AppRegistry::Get()->NumberOfApplications());
+ EXPECT_EQ(1, app_activity2->app_activity_registry()->NumberOfActivities());
+ CloseActivity(app_activity2);
+ }
+ EXPECT_EQ(0, AppRegistry::Get()->NumberOfApplications());
+ {
+ TestAppActivity* app_activity1 = CreateAppActivity(kDummyApp1);
+ TestAppActivity* app_activity2 = CreateAppActivity(kDummyApp1);
+ EXPECT_EQ(1, AppRegistry::Get()->NumberOfApplications());
+ EXPECT_EQ(2, app_activity1->app_activity_registry()->NumberOfActivities());
+ EXPECT_EQ(app_activity1->app_activity_registry(),
+ app_activity2->app_activity_registry());
+ CloseActivity(app_activity2);
+ EXPECT_EQ(1, AppRegistry::Get()->NumberOfApplications());
+ EXPECT_EQ(1, app_activity1->app_activity_registry()->NumberOfActivities());
+ CloseActivity(app_activity1);
+ }
+ EXPECT_EQ(0, AppRegistry::Get()->NumberOfApplications());
+ EXPECT_EQ(0, test_app_content_control_delegate()->unload_called());
+ EXPECT_EQ(0, test_app_content_control_delegate()->restart_called());
+}
+
+// Test unload and the creation of the proxy, then "closing the activity".
+TEST_F(AppActivityTest, TestUnloadFollowedByClose) {
+ EXPECT_EQ(0, AppRegistry::Get()->NumberOfApplications());
+
+ TestAppActivity* app_activity = CreateAppActivity(kDummyApp1);
+ EXPECT_EQ(1, AppRegistry::Get()->NumberOfApplications());
+ AppActivityRegistry* app_activity_registry =
+ app_activity->app_activity_registry();
+ EXPECT_EQ(1, app_activity_registry->NumberOfActivities());
+ EXPECT_EQ(Activity::ACTIVITY_VISIBLE, app_activity->GetCurrentState());
+
+ // Calling Unload now should not do anything since at least one activity in
+ // the registry is still visible.
+ app_activity_registry->Unload();
+ EXPECT_EQ(0, test_app_content_control_delegate()->unload_called());
+
+ // After setting our activity to unloaded however the application should get
+ // unloaded as requested.
+ app_activity->SetCurrentState(Activity::ACTIVITY_UNLOADED);
+ app_activity_registry->Unload();
+ EXPECT_EQ(1, test_app_content_control_delegate()->unload_called());
+
+ // Check that our created application is gone, and instead a proxy got
+ // created.
+ ASSERT_EQ(1, AppRegistry::Get()->NumberOfApplications());
+ ASSERT_EQ(app_activity_registry,
+ AppRegistry::Get()->GetAppActivityRegistry(kDummyApp1, NULL));
+ EXPECT_EQ(0, app_activity_registry->NumberOfActivities());
+ Activity* activity_proxy =
+ app_activity_registry->unloaded_activity_proxy_for_test();
+ ASSERT_TRUE(activity_proxy);
+ EXPECT_NE(app_activity, activity_proxy);
+ EXPECT_EQ(Activity::ACTIVITY_UNLOADED, activity_proxy->GetCurrentState());
+
+ // Close the proxy object and make sure that nothing bad happens.
+ CloseActivity(activity_proxy);
+
+ EXPECT_EQ(0, AppRegistry::Get()->NumberOfApplications());
+ EXPECT_EQ(1, test_app_content_control_delegate()->unload_called());
+ EXPECT_EQ(0, test_app_content_control_delegate()->restart_called());
+}
+
+// Test that when unloading an app while multiple apps / activities are present,
+// the proxy gets created in the correct location.
+TEST_F(AppActivityTest, TestUnloadProxyLocation) {
+ // Set up some activities for some applications.
+ TestAppActivity* app_activity1a = CreateAppActivity(kDummyApp1);
+ TestAppActivity* app_activity2a = CreateAppActivity(kDummyApp2);
+ TestAppActivity* app_activity2b = CreateAppActivity(kDummyApp2);
+ TestAppActivity* app_activity1b = CreateAppActivity(kDummyApp1);
+ EXPECT_EQ(3, GetActivityPosition(app_activity1b));
+ EXPECT_EQ(2, GetActivityPosition(app_activity2b));
+ EXPECT_EQ(1, GetActivityPosition(app_activity2a));
+ EXPECT_EQ(0, GetActivityPosition(app_activity1a));
+
+ // Unload an app and make sure that the proxy is in the newest activity slot.
+ AppActivityRegistry* app_activity_registry =
+ app_activity2a->app_activity_registry();
+ app_activity2a->SetCurrentState(Activity::ACTIVITY_UNLOADED);
+ app_activity2b->SetCurrentState(Activity::ACTIVITY_UNLOADED);
+ app_activity2a->app_activity_registry()->Unload();
+ EXPECT_EQ(0, app_activity_registry->NumberOfActivities());
+ Activity* activity_proxy =
+ app_activity_registry->unloaded_activity_proxy_for_test();
+ RunAllPendingInMessageLoop();
+
+ EXPECT_EQ(2, GetActivityPosition(app_activity1b));
+ EXPECT_EQ(1, GetActivityPosition(activity_proxy));
+ EXPECT_EQ(0, GetActivityPosition(app_activity1a));
+
+ CloseActivity(activity_proxy);
+ CloseActivity(app_activity1b);
+ CloseActivity(app_activity1a);
+}
+
+// Test that an unload with multiple activities of the same app will only unload
+// when all activities were marked for unloading.
+TEST_F(AppActivityTest, TestMultipleActivityUnloadLock) {
+ EXPECT_EQ(0, AppRegistry::Get()->NumberOfApplications());
+
+ TestAppActivity* app_activity1 = CreateAppActivity(kDummyApp1);
+ TestAppActivity* app_activity2 = CreateAppActivity(kDummyApp1);
+ TestAppActivity* app_activity3 = CreateAppActivity(kDummyApp1);
+
+ // Check that we have 3 activities of the same application.
+ EXPECT_EQ(1, AppRegistry::Get()->NumberOfApplications());
+ AppActivityRegistry* app_activity_registry =
+ app_activity1->app_activity_registry();
+ EXPECT_EQ(app_activity_registry, app_activity2->app_activity_registry());
+ EXPECT_EQ(app_activity_registry, app_activity3->app_activity_registry());
+ EXPECT_EQ(3, app_activity_registry->NumberOfActivities());
+ EXPECT_EQ(Activity::ACTIVITY_VISIBLE, app_activity1->GetCurrentState());
+ EXPECT_EQ(Activity::ACTIVITY_VISIBLE, app_activity2->GetCurrentState());
+ EXPECT_EQ(Activity::ACTIVITY_VISIBLE, app_activity3->GetCurrentState());
+
+ // After setting all activities to UNLOADED the application should unload.
+ app_activity1->SetCurrentState(Activity::ACTIVITY_UNLOADED);
+ app_activity1->app_activity_registry()->Unload();
+ EXPECT_EQ(0, test_app_content_control_delegate()->unload_called());
+ app_activity2->SetCurrentState(Activity::ACTIVITY_UNLOADED);
+ app_activity2->app_activity_registry()->Unload();
+ EXPECT_EQ(0, test_app_content_control_delegate()->unload_called());
+ app_activity3->SetCurrentState(Activity::ACTIVITY_UNLOADED);
+ app_activity3->app_activity_registry()->Unload();
+ EXPECT_EQ(1, test_app_content_control_delegate()->unload_called());
+
+ // Now there should only be the proxy activity left.
+ ASSERT_EQ(1, AppRegistry::Get()->NumberOfApplications());
+ ASSERT_EQ(app_activity_registry,
+ AppRegistry::Get()->GetAppActivityRegistry(kDummyApp1, NULL));
+ EXPECT_EQ(0, app_activity_registry->NumberOfActivities());
+ Activity* activity_proxy =
+ app_activity_registry->unloaded_activity_proxy_for_test();
+ ASSERT_TRUE(activity_proxy);
+ EXPECT_NE(app_activity1, activity_proxy);
+ EXPECT_NE(app_activity2, activity_proxy);
+ EXPECT_NE(app_activity3, activity_proxy);
+ EXPECT_EQ(Activity::ACTIVITY_UNLOADED, activity_proxy->GetCurrentState());
+
+ // Close the proxy object and make sure that nothing bad happens.
+ CloseActivity(activity_proxy);
+
+ EXPECT_EQ(0, AppRegistry::Get()->NumberOfApplications());
+ EXPECT_EQ(1, test_app_content_control_delegate()->unload_called());
+ EXPECT_EQ(0, test_app_content_control_delegate()->restart_called());
+}
+
+// Test that activating the proxy will reload the application.
+TEST_F(AppActivityTest, TestUnloadWithReload) {
+ EXPECT_EQ(0, AppRegistry::Get()->NumberOfApplications());
+
+ TestAppActivity* app_activity = CreateAppActivity(kDummyApp1);
+ AppActivityRegistry* app_activity_registry =
+ app_activity->app_activity_registry();
+
+ // Unload the activity.
+ app_activity->SetCurrentState(Activity::ACTIVITY_UNLOADED);
+ app_activity_registry->Unload();
+ EXPECT_EQ(1, test_app_content_control_delegate()->unload_called());
+
+ // Try to activate the activity again. This will force the application to
+ // reload.
+ Activity* activity_proxy =
+ app_activity_registry->unloaded_activity_proxy_for_test();
+ activity_proxy->SetCurrentState(Activity::ACTIVITY_VISIBLE);
+ EXPECT_EQ(1, test_app_content_control_delegate()->restart_called());
+
+ // However - the restart in this test framework does not really restart and
+ // all objects should be gone now.
+ EXPECT_EQ(0, AppRegistry::Get()->NumberOfApplications());
+}
+
+} // namespace test
+} // namespace athena
« no previous file with comments | « athena/content/app_activity_registry.cc ('k') | athena/content/app_registry_impl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698