1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package org.chromium.net.test;
17 
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertNotNull;
20 import static org.junit.Assert.assertTrue;
21 import static org.junit.Assert.fail;
22 
23 import android.content.Context;
24 import android.net.ConnectivityManager;
25 import android.os.Handler;
26 import android.os.Looper;
27 import androidx.annotation.NonNull;
28 import androidx.annotation.Nullable;
29 import androidx.test.platform.app.InstrumentationRegistry;
30 import androidx.test.runner.AndroidJUnit4;
31 
32 import java.nio.ByteBuffer;
33 import java.util.concurrent.CountDownLatch;
34 import java.util.concurrent.Executor;
35 import java.util.concurrent.TimeUnit;
36 
37 import org.chromium.net.CronetEngine;
38 import org.chromium.net.CronetException;
39 import org.chromium.net.UrlRequest;
40 import org.chromium.net.UrlResponseInfo;
41 import org.junit.Before;
42 import org.junit.Test;
43 import org.junit.runner.RunWith;
44 
45 @RunWith(AndroidJUnit4.class)
46 public class CronetApiTest {
47     private static final String TAG = CronetApiTest.class.getSimpleName();
48     static final String TEST_DOMAIN = "www.google.com";
49     static final String HTTPS_PREFIX = "https://";
50     static final int TIMEOUT_MS = 12_000;
51 
52     @NonNull
53     private CronetEngine mCronetEngine;
54     @NonNull
55     private ConnectivityManager mCm;
56     @NonNull
57     private Executor mExecutor;
58 
59     @Before
setUp()60     public void setUp() throws Exception {
61         Context context = InstrumentationRegistry.getInstrumentation().getContext();
62         mCm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
63         CronetEngine.Builder builder = new CronetEngine.Builder(context);
64         builder.enableHttpCache(CronetEngine.Builder.HTTP_CACHE_IN_MEMORY, 100 * 1024)
65                 .enableHttp2(true)
66                 //.enableBrotli(true)
67                 .enableQuic(true);
68         mCronetEngine = builder.build();
69         mExecutor = new Handler(Looper.getMainLooper())::post;
70     }
71 
assertGreaterThan(String msg, int first, int second)72     static private void assertGreaterThan(String msg, int first, int second) {
73         assertTrue(msg + " Excepted " + first + " to be greater than " + second, first > second);
74     }
75 
assertHasTestableNetworks()76     private void assertHasTestableNetworks() {
77         assertNotNull("This test requires a working Internet connection",
78             mCm.getActiveNetwork());
79     }
80 
81     class VerifyUrlRequestCallback extends UrlRequest.Callback {
82         private final CountDownLatch mLatch = new CountDownLatch(1);
83         private final String mUrl;
84 
VerifyUrlRequestCallback(@onNull String url)85         VerifyUrlRequestCallback(@NonNull String url) {
86             this.mUrl = url;
87         }
88 
waitForAnswer()89         public boolean waitForAnswer() throws InterruptedException {
90             return mLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
91         }
92 
93         @Override
onRedirectReceived( UrlRequest request, UrlResponseInfo info, String newLocationUrl)94         public void onRedirectReceived(
95                 UrlRequest request, UrlResponseInfo info, String newLocationUrl) {
96             request.followRedirect();
97         }
98 
99         @Override
onResponseStarted(UrlRequest request, UrlResponseInfo info)100         public void onResponseStarted(UrlRequest request, UrlResponseInfo info) {
101             request.read(ByteBuffer.allocateDirect(32 * 1024));
102         }
103 
104         @Override
onReadCompleted( UrlRequest request, UrlResponseInfo info, ByteBuffer byteBuffer)105         public void onReadCompleted(
106             UrlRequest request, UrlResponseInfo info, ByteBuffer byteBuffer) {
107             byteBuffer.clear();
108             request.read(byteBuffer);
109         }
110 
111 
112         @Override
onSucceeded(UrlRequest request, UrlResponseInfo info)113         public void onSucceeded(UrlRequest request, UrlResponseInfo info) {
114             assertEquals("Unexpected http status code", info.getHttpStatusCode(), 200);
115             assertGreaterThan("Received byte is 0", (int)info.getReceivedByteCount(), 0);
116             mLatch.countDown();
117         }
118 
119         @Override
onFailed(UrlRequest request, UrlResponseInfo info, CronetException error)120         public void onFailed(UrlRequest request, UrlResponseInfo info, CronetException error) {
121             fail(mUrl + error.getMessage());
122         }
123     }
124 
125     @Test
testUrlGet()126     public void testUrlGet() throws Exception {
127         assertHasTestableNetworks();
128         String url = HTTPS_PREFIX + TEST_DOMAIN;
129         VerifyUrlRequestCallback callback = new VerifyUrlRequestCallback(url);
130         UrlRequest.Builder builder = mCronetEngine.newUrlRequestBuilder(url, callback, mExecutor);
131         builder.build().start();
132         assertTrue(url + " but not complete after " + TIMEOUT_MS + "ms.",
133                 callback.waitForAnswer());
134     }
135 
136 }
137