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