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

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: Address Marcus' nits + 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/scoped_ptr.h"
11 #include "base/message_loop/message_loop_proxy.h"
12 #include "base/run_loop.h"
13 #include "base/synchronization/waitable_event.h"
14 #include "base/threading/thread.h"
15
16 #include "testing/gtest/include/gtest/gtest.h"
17
18 namespace base {
19 namespace android {
20
21 // This is equivalent to what the JNI generator would output if
joth 2013/04/26 20:29:10 At first I thought this comment (specifically, "Th
digit1 2013/04/29 12:22:10 Yes, I've refactored this a bit. Thanks.
22 // ActivityStatus.onStateChange() was tagged with @CalledByNative.
23 // because this is only useful for unit-testing, there is no point in
24 // making this permanent for production code.
25 using base::android::ScopedJavaLocalRef;
26
27 namespace {
28
29 const char kActivityStatusClassPath[] = "org/chromium/base/ActivityStatus";
30 jclass g_ActivityStatus_clazz = NULL;
31
32 base::subtle::AtomicWord g_ActivityStatus_onStateChange = 0;
33
34 void Java_ActivityStatus_onStateChange(JNIEnv* env,
35 jobject activity,
36 jint newState) {
37 // Ensure g_ActivityStatus_clazz is initialized
38 if (g_ActivityStatus_clazz == NULL) {
39 g_ActivityStatus_clazz = reinterpret_cast<jclass>(env->NewGlobalRef(
40 base::android::GetClass(env, kActivityStatusClassPath).obj()));
41 DCHECK(g_ActivityStatus_clazz);
42 }
43 jmethodID method_id =
44 base::android::MethodID::LazyGet<
45 base::android::MethodID::TYPE_STATIC>(
46 env, g_ActivityStatus_clazz,
47 "onStateChange",
48 "("
49 "Landroid/app/Activity;"
50 "I"
51 ")"
52 "V",
53 &g_ActivityStatus_onStateChange);
54
55 env->CallStaticVoidMethod(g_ActivityStatus_clazz,
56 method_id, activity, newState);
57 base::android::CheckException(env);
58 }
59
60 // Change the activity state, return true on success, false otherwise.
61 bool ForceActivityStateTo(ActivityState state) {
62 JNIEnv* env = base::android::AttachCurrentThread();
63 if (!env)
64 return false;
65
66 RunLoop run_loop;
67 Java_ActivityStatus_onStateChange(env, NULL, static_cast<int>(state));
68 run_loop.RunUntilIdle();
69 return true;
70 }
71
72 // Used to generate a callback that stores the new state at a given
73 // location.
74 void StoreStateTo(ActivityState* target, ActivityState state) {
75 *target = state;
76 }
77
78 // An invalid ActivityState value.
79 const ActivityState kInvalidActivityState = static_cast<ActivityState>(100);
80
81 // Shared state for the multi-threaded test.
82 // This uses a thread to register for events and listen to them,
83 // while state changes are forced on the main thread.
84 class MultiThreadedTest {
85 public:
86 MultiThreadedTest()
87 : state_(kInvalidActivityState),
88 event_(false, false),
89 thread_("ActivityStatusTest thread"),
90 main_(),
91 listener_(NULL) {
92 }
93
94 void Run() {
95 RunLoop loop;
96
97 // Start the thread and tell it to register for events.
98 thread_.Start();
99 thread_.message_loop()->PostTask(
100 FROM_HERE,
101 base::Bind(&MultiThreadedTest::RegisterThreadForEvents,
102 base::Unretained(this)));
103
104 // Wait for its completion.
105 event_.Wait();
106
107 // Change state, then wait for the thread to modify state.
108 EXPECT_TRUE(ForceActivityStateTo(ACTIVITY_STATE_CREATED));
109 event_.Wait();
110 EXPECT_EQ(ACTIVITY_STATE_CREATED, state_);
111
112 // Again
113 EXPECT_TRUE(ForceActivityStateTo(ACTIVITY_STATE_DESTROYED));
114 event_.Wait();
115 EXPECT_EQ(ACTIVITY_STATE_DESTROYED, state_);
116 }
117
118 private:
119 void ExpectOnThread() {
120 EXPECT_EQ(thread_.message_loop(),
121 base::MessageLoop::current());
122 }
123
124 void RegisterThreadForEvents() {
125 ExpectOnThread();
126 listener_.reset(
127 new ActivityStatus::Listener(
128 base::Bind(&MultiThreadedTest::StoreStateAndSignal,
129 base::Unretained(this))));
130 EXPECT_TRUE(listener_.get());
131 event_.Signal();
132 }
133
134 void StoreStateAndSignal(ActivityState state) {
135 ExpectOnThread();
136 state_ = state;
137 event_.Signal();
138 }
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 ASSERT_TRUE(ForceActivityStateTo(ACTIVITY_STATE_CREATED));
164 EXPECT_EQ(ACTIVITY_STATE_CREATED, result);
165
166 ASSERT_TRUE(ForceActivityStateTo(ACTIVITY_STATE_DESTROYED));
167 EXPECT_EQ(ACTIVITY_STATE_DESTROYED, result);
168 }
169
170 TEST(ActivityStatusTest, TwoThreads) {
171 MultiThreadedTest test;
172 test.Run();
173 }
174
175 } // namespace android
176 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698