• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 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 
17 package com.android.odp.module.common.http;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 
21 import static org.junit.Assert.assertEquals;
22 
23 import static java.nio.charset.StandardCharsets.UTF_8;
24 
25 import com.android.modules.utils.testing.ExtendedMockitoRule;
26 
27 import com.google.common.util.concurrent.MoreExecutors;
28 
29 import org.junit.Rule;
30 import org.junit.Test;
31 import org.junit.runner.RunWith;
32 import org.junit.runners.JUnit4;
33 import org.mockito.Spy;
34 import org.mockito.quality.Strictness;
35 
36 import java.io.IOException;
37 import java.util.Arrays;
38 import java.util.HashMap;
39 import java.util.List;
40 import java.util.Map;
41 import java.util.concurrent.atomic.AtomicInteger;
42 
43 @RunWith(JUnit4.class)
44 public final class HttpClientTest {
45     @Rule
46     public final ExtendedMockitoRule extendedMockitoRule =
47             new ExtendedMockitoRule.Builder(this).setStrictness(Strictness.LENIENT).build();
48 
49     private static final int DEFAULT_RETRY_LIMIT = 3;
50     private static final int HTTP_UNAVAILABLE = 503;
51     private static final int HTTP_OK = 200;
52 
53     @Spy
54     private HttpClient mHttpClient =
55             new HttpClient(DEFAULT_RETRY_LIMIT, MoreExecutors.newDirectExecutorService());
56 
57     @Test
testPerformGetRequestFailsWithRetry()58     public void testPerformGetRequestFailsWithRetry() throws Exception {
59         String failureMessage = "FAIL!";
60         OdpHttpResponse testFailedResponse =
61                 new OdpHttpResponse.Builder()
62                         .setHeaders(new HashMap<>())
63                         .setPayload(failureMessage.getBytes(UTF_8))
64                         .setStatusCode(HTTP_UNAVAILABLE)
65                         .build();
66         TestHttpIOSupplier testSupplier = new TestHttpIOSupplier(testFailedResponse);
67 
68         OdpHttpResponse returnedResponse = mHttpClient.performRequestWithRetry(testSupplier);
69 
70         assertEquals(DEFAULT_RETRY_LIMIT, testSupplier.mCallCount.get());
71         assertThat(returnedResponse.getStatusCode()).isEqualTo(HTTP_UNAVAILABLE);
72         assertThat(returnedResponse.getHeaders()).isEmpty();
73         assertThat(returnedResponse.getPayload()).isEqualTo(failureMessage.getBytes(UTF_8));
74     }
75 
76     @Test
testPerformGetRequestSuccessWithRetry()77     public void testPerformGetRequestSuccessWithRetry() throws Exception {
78         Map<String, List<String>> mockHeaders = new HashMap<>();
79         mockHeaders.put("Header1", Arrays.asList("Value1"));
80         String failureMessage = "FAIL!";
81         String successMessage = "Success!";
82         OdpHttpResponse testFailedResponse =
83                 new OdpHttpResponse.Builder()
84                         .setHeaders(new HashMap<>())
85                         .setPayload(failureMessage.getBytes(UTF_8))
86                         .setStatusCode(HTTP_UNAVAILABLE)
87                         .build();
88         OdpHttpResponse testSuccessfulResponse =
89                 new OdpHttpResponse.Builder()
90                         .setPayload(successMessage.getBytes(UTF_8))
91                         .setStatusCode(HTTP_OK)
92                         .setHeaders(mockHeaders)
93                         .build();
94         TestHttpIOSupplier testSupplier =
95                 new TestHttpIOSupplier(
96                         testSuccessfulResponse, testFailedResponse, DEFAULT_RETRY_LIMIT - 1);
97 
98         OdpHttpResponse response = mHttpClient.performRequestWithRetry(testSupplier);
99 
100         assertEquals(DEFAULT_RETRY_LIMIT, testSupplier.mCallCount.get());
101         assertThat(response.getStatusCode()).isEqualTo(HTTP_OK);
102         assertThat(response.getHeaders()).isEqualTo(mockHeaders);
103     }
104 
105     private static final class TestHttpIOSupplier
106             implements HttpClient.HttpIOSupplier<OdpHttpResponse> {
107         private final AtomicInteger mCallCount = new AtomicInteger(0);
108 
109         private final OdpHttpResponse mSuccessfulResponse;
110         private final OdpHttpResponse mFailedResponse;
111         private final int mNumFailedCalls;
112 
TestHttpIOSupplier(OdpHttpResponse failedResponse)113         private TestHttpIOSupplier(OdpHttpResponse failedResponse) {
114             this(null, failedResponse, 0);
115         }
116 
TestHttpIOSupplier( OdpHttpResponse successfulResponse, OdpHttpResponse failedResponse, int numFailedCalls)117         private TestHttpIOSupplier(
118                 OdpHttpResponse successfulResponse,
119                 OdpHttpResponse failedResponse,
120                 int numFailedCalls) {
121             this.mSuccessfulResponse = successfulResponse;
122             this.mFailedResponse = failedResponse;
123             this.mNumFailedCalls = numFailedCalls;
124         }
125 
126         @Override
get()127         public OdpHttpResponse get() throws IOException {
128             int callCount = mCallCount.incrementAndGet();
129             if (mSuccessfulResponse == null) {
130                 return mFailedResponse;
131             }
132 
133             return callCount > mNumFailedCalls ? mSuccessfulResponse : mFailedResponse;
134         }
135     }
136 }
137