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

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: Removed un-necessary RunLoop nesting in unit test. Created 7 years, 7 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 namespace {
22
23 using base::android::ScopedJavaLocalRef;
24
25 // Call org.chromium.base.ActivityStatus.onStateChange() from C++.
26 // |env| is the current JNI environment pointer.
27 // |activity| is a JNI reference to an activity object. Can be NULL
28 // during unit-testing.
29 // |newState| is the new state, as an integer.
30 //
31 // The code below is equivalent to what the JNI generator would output if
32 // ActivityStatus.onStateChange() was tagged with @CalledByNative.
33 // because this is only useful for unit-testing, there is no point in
34 // making this permanent for production code.
35 void Java_ActivityStatus_onStateChange(JNIEnv* env,
36 jobject activity,
37 jint newState) {
38 static const char kActivityStatusClassPath[] =
39 "org/chromium/base/ActivityStatus";
40 static jclass g_ActivityStatus_clazz = NULL;
41 static base::subtle::AtomicWord g_ActivityStatus_onStateChange = 0;
42
43 // Ensure g_ActivityStatus_clazz is initialized
44 if (g_ActivityStatus_clazz == NULL) {
45 g_ActivityStatus_clazz = reinterpret_cast<jclass>(env->NewGlobalRef(
46 base::android::GetClass(env, kActivityStatusClassPath).obj()));
47 DCHECK(g_ActivityStatus_clazz);
48 }
49 jmethodID method_id =
50 base::android::MethodID::LazyGet<base::android::MethodID::TYPE_STATIC>(
51 env,
52 g_ActivityStatus_clazz,
53 "onStateChange",
54 "("
55 "Landroid/app/Activity;"
56 "I"
57 ")"
58 "V",
59 &g_ActivityStatus_onStateChange);
60
61 env->CallStaticVoidMethod(
62 g_ActivityStatus_clazz, method_id, activity, newState);
63 base::android::CheckException(env);
64 }
65
66 // Change the activity state, return true on success, false otherwise.
67 bool ForceActivityStateTo(ActivityState state) {
68 JNIEnv* env = base::android::AttachCurrentThread();
69 if (!env)
70 return false;
71
72 RunLoop run_loop;
73 Java_ActivityStatus_onStateChange(env, NULL, static_cast<int>(state));
74 run_loop.RunUntilIdle();
75 return true;
76 }
77
78 // Used to generate a callback that stores the new state at a given
79 // location.
80 void StoreStateTo(ActivityState* target, ActivityState state) {
81 *target = state;
82 }
83
84 // An invalid ActivityState value.
85 const ActivityState kInvalidActivityState = static_cast<ActivityState>(100);
86
87 // Shared state for the multi-threaded test.
88 // This uses a thread to register for events and listen to them,
89 // while state changes are forced on the main thread.
90 class MultiThreadedTest {
91 public:
92 MultiThreadedTest()
93 : state_(kInvalidActivityState),
94 event_(false, false),
95 thread_("ActivityStatusTest thread"),
96 main_(),
97 listener_(NULL) {}
98
99 void Run() {
100 // Start the thread and tell it to register for events.
101 thread_.Start();
102 thread_.message_loop()
103 ->PostTask(FROM_HERE,
104 base::Bind(&MultiThreadedTest::RegisterThreadForEvents,
105 base::Unretained(this)));
106
107 // Wait for its completion.
108 event_.Wait();
109
110 // Change state, then wait for the thread to modify state.
111 EXPECT_TRUE(ForceActivityStateTo(ACTIVITY_STATE_CREATED));
112 event_.Wait();
113 EXPECT_EQ(ACTIVITY_STATE_CREATED, state_);
114
115 // Again
116 EXPECT_TRUE(ForceActivityStateTo(ACTIVITY_STATE_DESTROYED));
117 event_.Wait();
118 EXPECT_EQ(ACTIVITY_STATE_DESTROYED, state_);
119 }
120
121 private:
122 void ExpectOnThread() {
123 EXPECT_EQ(thread_.message_loop(), base::MessageLoop::current());
124 }
125
126 void RegisterThreadForEvents() {
127 ExpectOnThread();
128 listener_.reset(new ActivityStatus::Listener(base::Bind(
129 &MultiThreadedTest::StoreStateAndSignal, 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(new ActivityStatus::Listener(
157 base::Bind(&StoreStateTo, base::Unretained(&result))));
158 ASSERT_TRUE(listener.get());
159
160 EXPECT_EQ(kInvalidActivityState, result);
161
162 ASSERT_TRUE(ForceActivityStateTo(ACTIVITY_STATE_CREATED));
163 EXPECT_EQ(ACTIVITY_STATE_CREATED, result);
164
165 ASSERT_TRUE(ForceActivityStateTo(ACTIVITY_STATE_DESTROYED));
166 EXPECT_EQ(ACTIVITY_STATE_DESTROYED, result);
167 }
168
169 TEST(ActivityStatusTest, TwoThreads) {
170 MultiThreadedTest test;
171 test.Run();
172 }
173
174 } // namespace android
175 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698