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