1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "base/android/application_status_listener.h" 6 7 #include <memory> 8 9 #include "base/bind.h" 10 #include "base/callback_forward.h" 11 #include "base/logging.h" 12 #include "base/message_loop/message_loop.h" 13 #include "base/run_loop.h" 14 #include "base/synchronization/waitable_event.h" 15 #include "base/threading/thread.h" 16 #include "testing/gtest/include/gtest/gtest.h" 17 18 namespace base { 19 namespace android { 20 21 namespace { 22 23 using base::android::ScopedJavaLocalRef; 24 25 // An invalid ApplicationState value. 26 const ApplicationState kInvalidApplicationState = 27 static_cast<ApplicationState>(100); 28 29 // Used to generate a callback that stores the new state at a given location. 30 void StoreStateTo(ApplicationState* target, ApplicationState state) { 31 *target = state; 32 } 33 34 void RunTasksUntilIdle() { 35 RunLoop run_loop; 36 run_loop.RunUntilIdle(); 37 } 38 39 // Shared state for the multi-threaded test. 40 // This uses a thread to register for events and listen to them, while state 41 // changes are forced on the main thread. 42 class MultiThreadedTest { 43 public: 44 MultiThreadedTest() 45 : state_(kInvalidApplicationState), 46 event_(WaitableEvent::ResetPolicy::AUTOMATIC, 47 WaitableEvent::InitialState::NOT_SIGNALED), 48 thread_("ApplicationStatusTest thread"), 49 main_() {} 50 51 void Run() { 52 // Start the thread and tell it to register for events. 53 thread_.Start(); 54 thread_.task_runner()->PostTask( 55 FROM_HERE, base::Bind(&MultiThreadedTest::RegisterThreadForEvents, 56 base::Unretained(this))); 57 58 // Wait for its completion. 59 event_.Wait(); 60 61 // Change state, then wait for the thread to modify state. 62 ApplicationStatusListener::NotifyApplicationStateChange( 63 APPLICATION_STATE_HAS_RUNNING_ACTIVITIES); 64 event_.Wait(); 65 EXPECT_EQ(APPLICATION_STATE_HAS_RUNNING_ACTIVITIES, state_); 66 67 // Again 68 ApplicationStatusListener::NotifyApplicationStateChange( 69 APPLICATION_STATE_HAS_DESTROYED_ACTIVITIES); 70 event_.Wait(); 71 EXPECT_EQ(APPLICATION_STATE_HAS_DESTROYED_ACTIVITIES, state_); 72 } 73 74 private: 75 void ExpectOnThread() { 76 EXPECT_EQ(thread_.message_loop(), base::MessageLoop::current()); 77 } 78 79 void RegisterThreadForEvents() { 80 ExpectOnThread(); 81 listener_.reset(new ApplicationStatusListener(base::Bind( 82 &MultiThreadedTest::StoreStateAndSignal, base::Unretained(this)))); 83 EXPECT_TRUE(listener_.get()); 84 event_.Signal(); 85 } 86 87 void StoreStateAndSignal(ApplicationState state) { 88 ExpectOnThread(); 89 state_ = state; 90 event_.Signal(); 91 } 92 93 ApplicationState state_; 94 base::WaitableEvent event_; 95 base::Thread thread_; 96 base::MessageLoop main_; 97 std::unique_ptr<ApplicationStatusListener> listener_; 98 }; 99 100 } // namespace 101 102 TEST(ApplicationStatusListenerTest, SingleThread) { 103 MessageLoop message_loop; 104 105 ApplicationState result = kInvalidApplicationState; 106 107 // Create a new listener that stores the new state into |result| on every 108 // state change. 109 ApplicationStatusListener listener( 110 base::Bind(&StoreStateTo, base::Unretained(&result))); 111 112 EXPECT_EQ(kInvalidApplicationState, result); 113 114 ApplicationStatusListener::NotifyApplicationStateChange( 115 APPLICATION_STATE_HAS_RUNNING_ACTIVITIES); 116 RunTasksUntilIdle(); 117 EXPECT_EQ(APPLICATION_STATE_HAS_RUNNING_ACTIVITIES, result); 118 119 ApplicationStatusListener::NotifyApplicationStateChange( 120 APPLICATION_STATE_HAS_DESTROYED_ACTIVITIES); 121 RunTasksUntilIdle(); 122 EXPECT_EQ(APPLICATION_STATE_HAS_DESTROYED_ACTIVITIES, result); 123 } 124 125 TEST(ApplicationStatusListenerTest, TwoThreads) { 126 MultiThreadedTest test; 127 test.Run(); 128 } 129 130 } // namespace android 131 } // namespace base 132