Home | History | Annotate | Download | only in android
      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