1 // Copyright 2016 The Chromium Authors
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 "components/cronet/android/test/cronet_test_util.h"
6
7 #include "base/android/jni_android.h"
8 #include "base/android/jni_string.h"
9 #include "base/functional/bind.h"
10 #include "base/message_loop/message_pump.h"
11 #include "base/message_loop/message_pump_type.h"
12 #include "base/synchronization/waitable_event.h"
13 #include "base/task/sequence_manager/sequence_manager.h"
14 #include "base/task/single_thread_task_runner.h"
15 #include "base/test/bind.h"
16 #include "components/cronet/android/cronet_context_adapter.h"
17 #include "components/cronet/android/cronet_test_apk_jni/CronetTestUtil_jni.h"
18 #include "components/cronet/android/cronet_url_request_adapter.h"
19 #include "components/cronet/cronet_context.h"
20 #include "components/cronet/cronet_url_request.h"
21 #include "net/http/http_server_properties.h"
22 #include "net/socket/socket_test_util.h"
23 #include "net/url_request/url_request.h"
24 #include "net/url_request/url_request_context.h"
25
26 namespace cronet {
27 namespace {
28
29 using ::base::MessagePump;
30 using ::base::MessagePumpType;
31 using ::base::android::JavaParamRef;
32 using ::base::sequence_manager::SequenceManager;
33
34 SequenceManager* g_sequence_manager = nullptr;
35
36 } // namespace
37
JNI_CronetTestUtil_GetLoadFlags(JNIEnv * env,const jlong jurl_request_adapter)38 jint JNI_CronetTestUtil_GetLoadFlags(JNIEnv* env,
39 const jlong jurl_request_adapter) {
40 return TestUtil::GetURLRequest(jurl_request_adapter)->load_flags();
41 }
42
JNI_CronetTestUtil_URLRequestContextExistsForTesting(JNIEnv * env,jlong jcontext_adapter,jlong jnetwork_handle)43 jboolean JNI_CronetTestUtil_URLRequestContextExistsForTesting(
44 JNIEnv* env,
45 jlong jcontext_adapter,
46 jlong jnetwork_handle) {
47 return TestUtil::GetURLRequestContexts(jcontext_adapter)
48 ->contains(jnetwork_handle);
49 }
50
JNI_CronetTestUtil_FlushWritePropertiesForTesting(JNIEnv * env,jlong jcontext_adapter)51 void JNI_CronetTestUtil_FlushWritePropertiesForTesting(JNIEnv* env,
52 jlong jcontext_adapter) {
53 base::WaitableEvent wait_for_callback;
54 TestUtil::GetTaskRunner(jcontext_adapter)
55 ->PostTask(
56 FROM_HERE, base::BindLambdaForTesting([&]() {
57 TestUtil::GetURLRequestContext(jcontext_adapter)
58 ->http_server_properties()
59 ->FlushWritePropertiesForTesting(base::BindLambdaForTesting(
60 [&wait_for_callback]() { wait_for_callback.Signal(); }));
61 }));
62 wait_for_callback.Wait();
63 }
64
65 // static
66 base::flat_map<net::handles::NetworkHandle,
67 std::unique_ptr<net::URLRequestContext>>*
GetURLRequestContexts(jlong jcontext_adapter)68 TestUtil::GetURLRequestContexts(jlong jcontext_adapter) {
69 CronetContextAdapter* context_adapter =
70 reinterpret_cast<CronetContextAdapter*>(jcontext_adapter);
71 return &context_adapter->context_->network_tasks_->contexts_;
72 }
73
74 // static
GetTaskRunner(jlong jcontext_adapter)75 scoped_refptr<base::SingleThreadTaskRunner> TestUtil::GetTaskRunner(
76 jlong jcontext_adapter) {
77 CronetContextAdapter* context_adapter =
78 reinterpret_cast<CronetContextAdapter*>(jcontext_adapter);
79 return context_adapter->context_->network_task_runner_;
80 }
81
82 // static
GetURLRequestContext(jlong jcontext_adapter)83 net::URLRequestContext* TestUtil::GetURLRequestContext(jlong jcontext_adapter) {
84 CronetContextAdapter* context_adapter =
85 reinterpret_cast<CronetContextAdapter*>(jcontext_adapter);
86 return context_adapter->context_->network_tasks_->default_context_;
87 }
88
89 // static
RunAfterContextInitOnNetworkThread(jlong jcontext_adapter,base::OnceClosure task)90 void TestUtil::RunAfterContextInitOnNetworkThread(jlong jcontext_adapter,
91 base::OnceClosure task) {
92 CronetContextAdapter* context_adapter =
93 reinterpret_cast<CronetContextAdapter*>(jcontext_adapter);
94 if (context_adapter->context_->network_tasks_
95 ->is_default_context_initialized_) {
96 std::move(task).Run();
97 } else {
98 context_adapter->context_->network_tasks_->tasks_waiting_for_context_.push(
99 std::move(task));
100 }
101 }
102
103 // static
RunAfterContextInit(jlong jcontext_adapter,base::OnceClosure task)104 void TestUtil::RunAfterContextInit(jlong jcontext_adapter,
105 base::OnceClosure task) {
106 GetTaskRunner(jcontext_adapter)
107 ->PostTask(FROM_HERE,
108 base::BindOnce(&TestUtil::RunAfterContextInitOnNetworkThread,
109 jcontext_adapter, std::move(task)));
110 }
111
112 // static
GetURLRequest(jlong jrequest_adapter)113 net::URLRequest* TestUtil::GetURLRequest(jlong jrequest_adapter) {
114 CronetURLRequestAdapter* request_adapter =
115 reinterpret_cast<CronetURLRequestAdapter*>(jrequest_adapter);
116 return request_adapter->request_->network_tasks_.url_request_.get();
117 }
118
PrepareNetworkThreadOnNetworkThread(jlong jcontext_adapter)119 static void PrepareNetworkThreadOnNetworkThread(jlong jcontext_adapter) {
120 g_sequence_manager =
121 base::sequence_manager::CreateSequenceManagerOnCurrentThreadWithPump(
122 MessagePump::Create(MessagePumpType::IO),
123 SequenceManager::Settings::Builder()
124 .SetMessagePumpType(MessagePumpType::IO)
125 .Build())
126 .release();
127 g_sequence_manager->SetDefaultTaskRunner(
128 TestUtil::GetTaskRunner(jcontext_adapter));
129 }
130
131 // Tests need to call into libcronet.so code on libcronet.so threads.
132 // libcronet.so's threads are registered with static tables for MessageLoops
133 // and SingleThreadTaskRunners in libcronet.so, so libcronet_test.so
134 // functions that try and access these tables will find missing entries in
135 // the corresponding static tables in libcronet_test.so. Fix this by
136 // initializing a MessageLoop and SingleThreadTaskRunner in libcronet_test.so
137 // for these threads. Called from Java CronetTestUtil class.
JNI_CronetTestUtil_PrepareNetworkThread(JNIEnv * env,jlong jcontext_adapter)138 void JNI_CronetTestUtil_PrepareNetworkThread(JNIEnv* env,
139 jlong jcontext_adapter) {
140 TestUtil::GetTaskRunner(jcontext_adapter)
141 ->PostTask(FROM_HERE, base::BindOnce(&PrepareNetworkThreadOnNetworkThread,
142 jcontext_adapter));
143 }
144
CleanupNetworkThreadOnNetworkThread()145 static void CleanupNetworkThreadOnNetworkThread() {
146 DCHECK(g_sequence_manager);
147 delete g_sequence_manager;
148 g_sequence_manager = nullptr;
149 }
150
151 // Called from Java CronetTestUtil class.
JNI_CronetTestUtil_CleanupNetworkThread(JNIEnv * env,jlong jcontext_adapter)152 void JNI_CronetTestUtil_CleanupNetworkThread(JNIEnv* env,
153 jlong jcontext_adapter) {
154 TestUtil::RunAfterContextInit(
155 jcontext_adapter, base::BindOnce(&CleanupNetworkThreadOnNetworkThread));
156 }
157
JNI_CronetTestUtil_CanGetTaggedBytes(JNIEnv * env)158 jboolean JNI_CronetTestUtil_CanGetTaggedBytes(JNIEnv* env) {
159 return net::CanGetTaggedBytes();
160 }
161
JNI_CronetTestUtil_GetTaggedBytes(JNIEnv * env,jint jexpected_tag)162 jlong JNI_CronetTestUtil_GetTaggedBytes(JNIEnv* env, jint jexpected_tag) {
163 return net::GetTaggedBytes(jexpected_tag);
164 }
165
166 } // namespace cronet
167