Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(16)

Side by Side Diff: base/android/activity_status_unittest.cc

Issue 14373019: Add base/android/activity_status.cc (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: formatting Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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/android/jni_android.h"
7 #include "base/bind.h"
8 #include "base/callback_forward.h"
9 #include "base/logging.h"
10 #include "base/memory/ref_counted.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/message_loop/message_loop_proxy.h"
13 #include "base/run_loop.h"
14 #include "base/synchronization/waitable_event.h"
15 #include "base/threading/thread.h"
16
17 #include "testing/gtest/include/gtest/gtest.h"
18
19 namespace base {
20 namespace android {
21
22 // This is equivalent to what the JNI generator would output if
23 // ActivityStatus.onStateChange() was tagged with @CalledByNative.
24 // because this is only useful for unit-testing, there is no point in
25 // making this permanent for production code.
26 using base::android::ScopedJavaLocalRef;
27
28 namespace {
29
30 const char kActivityStatusClassPath[] = "org/chromium/base/ActivityStatus";
31 jclass g_ActivityStatus_clazz = NULL;
32
33 base::subtle::AtomicWord g_ActivityStatus_onStateChange = 0;
34
35 void Java_ActivityStatus_onStateChange(JNIEnv* env,
36 jobject activity,
37 jint newState) {
38 // Ensure g_ActivityStatus_clazz is initialized
39 if (g_ActivityStatus_clazz == NULL) {
40 g_ActivityStatus_clazz = reinterpret_cast<jclass>(env->NewGlobalRef(
41 base::android::GetClass(env, kActivityStatusClassPath).obj()));
42 DCHECK(g_ActivityStatus_clazz);
43 }
44 jmethodID method_id =
45 base::android::MethodID::LazyGet<
46 base::android::MethodID::TYPE_STATIC>(
47 env, g_ActivityStatus_clazz,
48 "onStateChange",
49 "("
50 "Landroid/app/Activity;"
51 "I"
52 ")"
53 "V",
54 &g_ActivityStatus_onStateChange);
55
56 env->CallStaticVoidMethod(g_ActivityStatus_clazz,
57 method_id, activity, newState);
58 base::android::CheckException(env);
59 }
60
61 void ForceActivityStateTo(ActivityState state) {
62 JNIEnv* env = base::android::AttachCurrentThread();
63 ASSERT_TRUE(env);
64 RunLoop run_loop;
65 Java_ActivityStatus_onStateChange(env, NULL, static_cast<int>(state));
66 run_loop.RunUntilIdle();
67 }
68
69 // Used to generate a callback that stores the new state at a given
70 // location.
71 void StoreStateTo(ActivityState* target, ActivityState state) {
72 *target = state;
73 }
74
75 // An invalid ActivityState value.
76 const ActivityState kInvalidActivityState = static_cast<ActivityState>(100);
77
78 // Shared state for the multi-threaded test.
79 // This uses a thread to register for events and listen to them,
80 // while state changes are forced on the main thread.
81 class MultiThreadedTest
82 : public base::RefCountedThreadSafe<MultiThreadedTest> {
83 public:
84 MultiThreadedTest()
85 : state_(kInvalidActivityState),
86 event_(false, false),
87 thread_("ActivityStatusTest thread"),
88 main_(),
89 listener_(NULL) {
90 }
91
92 void Run() {
93 RunLoop loop;
94
95 // Start the thread and tell it to register for events.
96 thread_.Start();
97 thread_.message_loop()->PostTask(
98 FROM_HERE,
99 base::Bind(&MultiThreadedTest::RegisterThreadForEvents, this));
100
101 // Wait for its completion.
102 event_.Wait();
103
104 // Change state, then wait for the thread to modify state.
105 ForceActivityStateTo(ACTIVITY_STATE_CREATED);
106 event_.Wait();
107 EXPECT_EQ(ACTIVITY_STATE_CREATED, state_);
108
109 // Again
110 ForceActivityStateTo(ACTIVITY_STATE_DESTROYED);
111 event_.Wait();
112 EXPECT_EQ(ACTIVITY_STATE_DESTROYED, state_);
113 }
114
115 private:
116 virtual ~MultiThreadedTest() {}
117
118 void AssertOnThread() {
119 ASSERT_EQ(thread_.message_loop(),
120 base::MessageLoop::current());
121 }
122
123 void RegisterThreadForEvents() {
124 AssertOnThread();
125 listener_.reset(
126 new ActivityStatus::Listener(
127 base::Bind(&MultiThreadedTest::StoreStateAndSignal, this)));
128 ASSERT_TRUE(listener_.get());
129 event_.Signal();
130 }
131
132 void StoreStateAndSignal(ActivityState state) {
133 AssertOnThread();
134 state_ = state;
135 event_.Signal();
136 }
137
138 friend class base::RefCountedThreadSafe<MultiThreadedTest>;
139
140 ActivityState state_;
141 base::WaitableEvent event_;
142 base::Thread thread_;
143 base::MessageLoop main_;
144 scoped_ptr<ActivityStatus::Listener> listener_;
145 };
146
147 } // namespace
148
149 TEST(ActivityStatusTest, SingleThread) {
150 MessageLoop message_loop;
151
152 ActivityState result = kInvalidActivityState;
153
154 // Create a new listener that stores the new state into |result|
155 // on every state change.
156 scoped_ptr<ActivityStatus::Listener> listener(
157 new ActivityStatus::Listener(
158 base::Bind(&StoreStateTo, base::Unretained(&result))));
159 ASSERT_TRUE(listener.get());
160
161 EXPECT_EQ(kInvalidActivityState, result);
162
163 ForceActivityStateTo(ACTIVITY_STATE_CREATED);
164 EXPECT_EQ(ACTIVITY_STATE_CREATED, result);
165
166 ForceActivityStateTo(ACTIVITY_STATE_DESTROYED);
167 EXPECT_EQ(ACTIVITY_STATE_DESTROYED, result);
168 }
169
170 TEST(ActivityStatusTest, TwoThreads) {
171 scoped_refptr<MultiThreadedTest> test(new MultiThreadedTest());
172 test->Run();
173 }
174
175 } // namespace android
176 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698