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 18namespace base { 19namespace android { 20 21namespace { 22 23using base::android::ScopedJavaLocalRef; 24 25// An invalid ApplicationState value. 26const ApplicationState kInvalidApplicationState = 27 static_cast<ApplicationState>(100); 28 29// Used to generate a callback that stores the new state at a given location. 30void StoreStateTo(ApplicationState* target, ApplicationState state) { 31 *target = state; 32} 33 34void 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. 42class 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 102TEST(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 125TEST(ApplicationStatusListenerTest, TwoThreads) { 126 MultiThreadedTest test; 127 test.Run(); 128} 129 130} // namespace android 131} // namespace base 132