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