1 /* 2 * Copyright (C) 2012 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.volley.toolbox; 18 19 import static org.junit.Assert.assertEquals; 20 import static org.junit.Assert.fail; 21 import static org.mockito.ArgumentMatchers.anyString; 22 import static org.mockito.Mockito.never; 23 import static org.mockito.Mockito.verify; 24 import static org.mockito.Mockito.when; 25 26 import com.android.volley.Header; 27 import com.android.volley.Request.Method; 28 import com.android.volley.mock.TestRequest; 29 import java.io.ByteArrayInputStream; 30 import java.io.ByteArrayOutputStream; 31 import java.io.IOException; 32 import java.net.HttpURLConnection; 33 import java.net.SocketTimeoutException; 34 import java.net.URL; 35 import java.nio.charset.StandardCharsets; 36 import java.util.ArrayList; 37 import java.util.Collections; 38 import java.util.HashMap; 39 import java.util.List; 40 import java.util.Map; 41 import org.junit.Before; 42 import org.junit.Test; 43 import org.junit.runner.RunWith; 44 import org.mockito.Mock; 45 import org.mockito.MockitoAnnotations; 46 import org.robolectric.RobolectricTestRunner; 47 48 @RunWith(RobolectricTestRunner.class) 49 public class HurlStackTest { 50 51 @Mock private HttpURLConnection mMockConnection; 52 private HurlStack mHurlStack; 53 54 @Before setUp()55 public void setUp() throws Exception { 56 MockitoAnnotations.initMocks(this); 57 when(mMockConnection.getOutputStream()).thenReturn(new ByteArrayOutputStream()); 58 59 mHurlStack = 60 new HurlStack() { 61 @Override 62 protected HttpURLConnection createConnection(URL url) { 63 return mMockConnection; 64 } 65 }; 66 } 67 68 @Test connectionForDeprecatedGetRequest()69 public void connectionForDeprecatedGetRequest() throws Exception { 70 TestRequest.DeprecatedGet request = new TestRequest.DeprecatedGet(); 71 assertEquals(request.getMethod(), Method.DEPRECATED_GET_OR_POST); 72 73 HurlStack.setConnectionParametersForRequest(mMockConnection, request); 74 verify(mMockConnection, never()).setRequestMethod(anyString()); 75 verify(mMockConnection, never()).setDoOutput(true); 76 } 77 78 @Test connectionForDeprecatedPostRequest()79 public void connectionForDeprecatedPostRequest() throws Exception { 80 TestRequest.DeprecatedPost request = new TestRequest.DeprecatedPost(); 81 assertEquals(request.getMethod(), Method.DEPRECATED_GET_OR_POST); 82 83 HurlStack.setConnectionParametersForRequest(mMockConnection, request); 84 verify(mMockConnection).setRequestMethod("POST"); 85 verify(mMockConnection).setDoOutput(true); 86 } 87 88 @Test connectionForGetRequest()89 public void connectionForGetRequest() throws Exception { 90 TestRequest.Get request = new TestRequest.Get(); 91 assertEquals(request.getMethod(), Method.GET); 92 93 HurlStack.setConnectionParametersForRequest(mMockConnection, request); 94 verify(mMockConnection).setRequestMethod("GET"); 95 verify(mMockConnection, never()).setDoOutput(true); 96 } 97 98 @Test connectionForPostRequest()99 public void connectionForPostRequest() throws Exception { 100 TestRequest.Post request = new TestRequest.Post(); 101 assertEquals(request.getMethod(), Method.POST); 102 103 HurlStack.setConnectionParametersForRequest(mMockConnection, request); 104 verify(mMockConnection).setRequestMethod("POST"); 105 verify(mMockConnection, never()).setDoOutput(true); 106 } 107 108 @Test connectionForPostWithBodyRequest()109 public void connectionForPostWithBodyRequest() throws Exception { 110 TestRequest.PostWithBody request = new TestRequest.PostWithBody(); 111 assertEquals(request.getMethod(), Method.POST); 112 113 HurlStack.setConnectionParametersForRequest(mMockConnection, request); 114 verify(mMockConnection).setRequestMethod("POST"); 115 verify(mMockConnection).setDoOutput(true); 116 } 117 118 @Test connectionForPutRequest()119 public void connectionForPutRequest() throws Exception { 120 TestRequest.Put request = new TestRequest.Put(); 121 assertEquals(request.getMethod(), Method.PUT); 122 123 HurlStack.setConnectionParametersForRequest(mMockConnection, request); 124 verify(mMockConnection).setRequestMethod("PUT"); 125 verify(mMockConnection, never()).setDoOutput(true); 126 } 127 128 @Test connectionForPutWithBodyRequest()129 public void connectionForPutWithBodyRequest() throws Exception { 130 TestRequest.PutWithBody request = new TestRequest.PutWithBody(); 131 assertEquals(request.getMethod(), Method.PUT); 132 133 HurlStack.setConnectionParametersForRequest(mMockConnection, request); 134 verify(mMockConnection).setRequestMethod("PUT"); 135 verify(mMockConnection).setDoOutput(true); 136 } 137 138 @Test connectionForDeleteRequest()139 public void connectionForDeleteRequest() throws Exception { 140 TestRequest.Delete request = new TestRequest.Delete(); 141 assertEquals(request.getMethod(), Method.DELETE); 142 143 HurlStack.setConnectionParametersForRequest(mMockConnection, request); 144 verify(mMockConnection).setRequestMethod("DELETE"); 145 verify(mMockConnection, never()).setDoOutput(true); 146 } 147 148 @Test connectionForHeadRequest()149 public void connectionForHeadRequest() throws Exception { 150 TestRequest.Head request = new TestRequest.Head(); 151 assertEquals(request.getMethod(), Method.HEAD); 152 153 HurlStack.setConnectionParametersForRequest(mMockConnection, request); 154 verify(mMockConnection).setRequestMethod("HEAD"); 155 verify(mMockConnection, never()).setDoOutput(true); 156 } 157 158 @Test connectionForOptionsRequest()159 public void connectionForOptionsRequest() throws Exception { 160 TestRequest.Options request = new TestRequest.Options(); 161 assertEquals(request.getMethod(), Method.OPTIONS); 162 163 HurlStack.setConnectionParametersForRequest(mMockConnection, request); 164 verify(mMockConnection).setRequestMethod("OPTIONS"); 165 verify(mMockConnection, never()).setDoOutput(true); 166 } 167 168 @Test connectionForTraceRequest()169 public void connectionForTraceRequest() throws Exception { 170 TestRequest.Trace request = new TestRequest.Trace(); 171 assertEquals(request.getMethod(), Method.TRACE); 172 173 HurlStack.setConnectionParametersForRequest(mMockConnection, request); 174 verify(mMockConnection).setRequestMethod("TRACE"); 175 verify(mMockConnection, never()).setDoOutput(true); 176 } 177 178 @Test connectionForPatchRequest()179 public void connectionForPatchRequest() throws Exception { 180 TestRequest.Patch request = new TestRequest.Patch(); 181 assertEquals(request.getMethod(), Method.PATCH); 182 183 HurlStack.setConnectionParametersForRequest(mMockConnection, request); 184 verify(mMockConnection).setRequestMethod("PATCH"); 185 verify(mMockConnection, never()).setDoOutput(true); 186 } 187 188 @Test connectionForPatchWithBodyRequest()189 public void connectionForPatchWithBodyRequest() throws Exception { 190 TestRequest.PatchWithBody request = new TestRequest.PatchWithBody(); 191 assertEquals(request.getMethod(), Method.PATCH); 192 193 HurlStack.setConnectionParametersForRequest(mMockConnection, request); 194 verify(mMockConnection).setRequestMethod("PATCH"); 195 verify(mMockConnection).setDoOutput(true); 196 } 197 198 @Test executeRequestClosesConnection_connectionError()199 public void executeRequestClosesConnection_connectionError() throws Exception { 200 when(mMockConnection.getResponseCode()).thenThrow(new SocketTimeoutException()); 201 try { 202 mHurlStack.executeRequest( 203 new TestRequest.Get(), Collections.<String, String>emptyMap()); 204 fail("Should have thrown exception"); 205 } catch (IOException e) { 206 verify(mMockConnection).disconnect(); 207 } 208 } 209 210 @Test executeRequestClosesConnection_invalidResponseCode()211 public void executeRequestClosesConnection_invalidResponseCode() throws Exception { 212 when(mMockConnection.getResponseCode()).thenReturn(-1); 213 try { 214 mHurlStack.executeRequest( 215 new TestRequest.Get(), Collections.<String, String>emptyMap()); 216 fail("Should have thrown exception"); 217 } catch (IOException e) { 218 verify(mMockConnection).disconnect(); 219 } 220 } 221 222 @Test executeRequestClosesConnection_noResponseBody()223 public void executeRequestClosesConnection_noResponseBody() throws Exception { 224 when(mMockConnection.getResponseCode()).thenReturn(HttpURLConnection.HTTP_NO_CONTENT); 225 mHurlStack.executeRequest(new TestRequest.Get(), Collections.<String, String>emptyMap()); 226 verify(mMockConnection).disconnect(); 227 } 228 229 @Test executeRequestClosesConnection_hasResponseBody()230 public void executeRequestClosesConnection_hasResponseBody() throws Exception { 231 when(mMockConnection.getResponseCode()).thenReturn(HttpURLConnection.HTTP_OK); 232 when(mMockConnection.getInputStream()) 233 .thenReturn(new ByteArrayInputStream("hello".getBytes(StandardCharsets.UTF_8))); 234 HttpResponse response = 235 mHurlStack.executeRequest( 236 new TestRequest.Get(), Collections.<String, String>emptyMap()); 237 // Shouldn't be disconnected until the stream is consumed. 238 verify(mMockConnection, never()).disconnect(); 239 response.getContent().close(); 240 verify(mMockConnection).disconnect(); 241 } 242 243 @Test convertHeaders()244 public void convertHeaders() { 245 Map<String, List<String>> headers = new HashMap<>(); 246 headers.put(null, Collections.singletonList("Ignored")); 247 headers.put("HeaderA", Collections.singletonList("ValueA")); 248 List<String> values = new ArrayList<>(); 249 values.add("ValueB_1"); 250 values.add("ValueB_2"); 251 headers.put("HeaderB", values); 252 List<Header> result = HurlStack.convertHeaders(headers); 253 List<Header> expected = new ArrayList<>(); 254 expected.add(new Header("HeaderA", "ValueA")); 255 expected.add(new Header("HeaderB", "ValueB_1")); 256 expected.add(new Header("HeaderB", "ValueB_2")); 257 assertEquals(expected, result); 258 } 259 } 260