1 /* 2 * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* 25 * @test 26 * @summary HttpRequest[.Builder] API and behaviour checks 27 * @run testng RequestBuilderTest 28 */ 29 30 import java.net.URI; 31 import java.util.List; 32 import jdk.incubator.http.HttpRequest; 33 import static java.time.Duration.ofNanos; 34 import static java.time.Duration.ofMinutes; 35 import static java.time.Duration.ofSeconds; 36 import static java.time.Duration.ZERO; 37 import static jdk.incubator.http.HttpClient.Version.HTTP_1_1; 38 import static jdk.incubator.http.HttpClient.Version.HTTP_2; 39 import static jdk.incubator.http.HttpRequest.BodyPublisher.fromString; 40 import static jdk.incubator.http.HttpRequest.BodyPublisher.noBody; 41 import static jdk.incubator.http.HttpRequest.newBuilder; 42 import static org.testng.Assert.*; 43 import org.testng.annotations.Test; 44 45 public class RequestBuilderTest { 46 47 static final URI uri = URI.create("http://foo.com/"); 48 static final Class<NullPointerException> NPE = NullPointerException.class; 49 static final Class<IllegalArgumentException> IAE = IllegalArgumentException.class; 50 static final Class<IllegalStateException> ISE = IllegalStateException.class; 51 static final Class<NumberFormatException> NFE = NumberFormatException.class; 52 static final Class<UnsupportedOperationException> UOE = UnsupportedOperationException.class; 53 54 @Test 55 public void testDefaults() { 56 List<HttpRequest.Builder> builders = List.of(newBuilder().uri(uri), 57 newBuilder(uri)); 58 for (HttpRequest.Builder builder : builders) { 59 assertFalse(builder.build().expectContinue()); 60 assertEquals(builder.build().method(), "GET"); 61 assertFalse(builder.build().bodyPublisher().isPresent()); 62 assertFalse(builder.build().version().isPresent()); 63 assertFalse(builder.build().timeout().isPresent()); 64 assertTrue(builder.build().headers() != null); 65 assertEquals(builder.build().headers().map().size(), 0); 66 } 67 } 68 69 @Test 70 public void testNull() { 71 HttpRequest.Builder builder = newBuilder(); 72 73 assertThrows(NPE, () -> newBuilder(null).build()); 74 assertThrows(NPE, () -> newBuilder(uri).uri(null).build()); 75 assertThrows(NPE, () -> builder.uri(null)); 76 assertThrows(NPE, () -> builder.version(null)); 77 assertThrows(NPE, () -> builder.header(null, null)); 78 assertThrows(NPE, () -> builder.header("name", null)); 79 assertThrows(NPE, () -> builder.header(null, "value")); 80 assertThrows(NPE, () -> builder.headers(null)); 81 assertThrows(NPE, () -> builder.headers(new String[] { null, null })); 82 assertThrows(NPE, () -> builder.headers(new String[] { "name", null })); 83 assertThrows(NPE, () -> builder.headers(new String[] { null, "value" })); 84 assertThrows(NPE, () -> builder.method(null, null)); 85 assertThrows(NPE, () -> builder.method("GET", null)); 86 assertThrows(NPE, () -> builder.method("POST", null)); 87 assertThrows(NPE, () -> builder.method("PUT", null)); 88 assertThrows(NPE, () -> builder.method("DELETE", null)); 89 assertThrows(NPE, () -> builder.setHeader(null, null)); 90 assertThrows(NPE, () -> builder.setHeader("name", null)); 91 assertThrows(NPE, () -> builder.setHeader(null, "value")); 92 assertThrows(NPE, () -> builder.timeout(null)); 93 assertThrows(NPE, () -> builder.DELETE(null)); 94 assertThrows(NPE, () -> builder.POST(null)); 95 assertThrows(NPE, () -> builder.PUT(null)); 96 } 97 98 @Test 99 public void testURI() { 100 assertThrows(ISE, () -> newBuilder().build()); 101 List<URI> uris = List.of( 102 URI.create("ws://foo.com"), 103 URI.create("wss://foo.com"), 104 URI.create("ftp://foo.com"), 105 URI.create("gopher://foo.com"), 106 URI.create("mailto:a@b.com"), 107 URI.create("scheme:example.com"), 108 URI.create("scheme:example.com"), 109 URI.create("scheme:example.com/path"), 110 URI.create("path"), 111 URI.create("/path") 112 ); 113 for (URI u : uris) { 114 assertThrows(IAE, () -> newBuilder(u)); 115 assertThrows(IAE, () -> newBuilder().uri(u)); 116 } 117 118 assertEquals(newBuilder(uri).build().uri(), uri); 119 assertEquals(newBuilder().uri(uri).build().uri(), uri); 120 URI https = URI.create("https://foo.com"); 121 assertEquals(newBuilder(https).build().uri(), https); 122 assertEquals(newBuilder().uri(https).build().uri(), https); 123 } 124 125 @Test 126 public void testMethod() { 127 HttpRequest request = newBuilder(uri).build(); 128 assertEquals(request.method(), "GET"); 129 assertTrue(!request.bodyPublisher().isPresent()); 130 131 request = newBuilder(uri).GET().build(); 132 assertEquals(request.method(), "GET"); 133 assertTrue(!request.bodyPublisher().isPresent()); 134 135 request = newBuilder(uri).POST(fromString("")).GET().build(); 136 assertEquals(request.method(), "GET"); 137 assertTrue(!request.bodyPublisher().isPresent()); 138 139 request = newBuilder(uri).PUT(fromString("")).GET().build(); 140 assertEquals(request.method(), "GET"); 141 assertTrue(!request.bodyPublisher().isPresent()); 142 143 request = newBuilder(uri).DELETE(fromString("")).GET().build(); 144 assertEquals(request.method(), "GET"); 145 assertTrue(!request.bodyPublisher().isPresent()); 146 147 request = newBuilder(uri).POST(fromString("")).build(); 148 assertEquals(request.method(), "POST"); 149 assertTrue(request.bodyPublisher().isPresent()); 150 151 request = newBuilder(uri).PUT(fromString("")).build(); 152 assertEquals(request.method(), "PUT"); 153 assertTrue(request.bodyPublisher().isPresent()); 154 155 request = newBuilder(uri).DELETE(fromString("")).build(); 156 assertEquals(request.method(), "DELETE"); 157 assertTrue(request.bodyPublisher().isPresent()); 158 159 request = newBuilder(uri).GET().POST(fromString("")).build(); 160 assertEquals(request.method(), "POST"); 161 assertTrue(request.bodyPublisher().isPresent()); 162 163 request = newBuilder(uri).GET().PUT(fromString("")).build(); 164 assertEquals(request.method(), "PUT"); 165 assertTrue(request.bodyPublisher().isPresent()); 166 167 request = newBuilder(uri).GET().DELETE(fromString("")).build(); 168 assertEquals(request.method(), "DELETE"); 169 assertTrue(request.bodyPublisher().isPresent()); 170 171 // CONNECT is disallowed in the implementation, since it is used for 172 // tunneling, and is handled separately for security checks. 173 assertThrows(IAE, () -> newBuilder(uri).method("CONNECT", noBody()).build()); 174 175 request = newBuilder(uri).method("GET", noBody()).build(); 176 assertEquals(request.method(), "GET"); 177 assertTrue(request.bodyPublisher().isPresent()); 178 179 request = newBuilder(uri).method("POST", fromString("")).build(); 180 assertEquals(request.method(), "POST"); 181 assertTrue(request.bodyPublisher().isPresent()); 182 } 183 184 @Test 185 public void testHeaders() { 186 HttpRequest.Builder builder = newBuilder(uri); 187 188 String[] empty = new String[0]; 189 assertThrows(IAE, () -> builder.headers(empty).build()); 190 assertThrows(IAE, () -> builder.headers("1").build()); 191 assertThrows(IAE, () -> builder.headers("1", "2", "3").build()); 192 assertThrows(IAE, () -> builder.headers("1", "2", "3", "4", "5").build()); 193 assertEquals(builder.build().headers().map().size(),0); 194 195 List<HttpRequest> requests = List.of( 196 // same header built from different combinations of the API 197 newBuilder(uri).header("A", "B").build(), 198 newBuilder(uri).headers("A", "B").build(), 199 newBuilder(uri).setHeader("A", "B").build(), 200 newBuilder(uri).header("A", "F").setHeader("A", "B").build(), 201 newBuilder(uri).headers("A", "F").setHeader("A", "B").build() 202 ); 203 204 for (HttpRequest r : requests) { 205 assertEquals(r.headers().map().size(), 1); 206 assertTrue(r.headers().firstValue("A").isPresent()); 207 assertEquals(r.headers().firstValue("A").get(), "B"); 208 assertEquals(r.headers().allValues("A"), List.of("B")); 209 assertEquals(r.headers().allValues("C").size(), 0); 210 assertEquals(r.headers().map().get("A"), List.of("B")); 211 assertThrows(NFE, () -> r.headers().firstValueAsLong("A")); 212 assertFalse(r.headers().firstValue("C").isPresent()); 213 // a non-exhaustive list of mutators 214 assertThrows(UOE, () -> r.headers().map().put("Z", List.of("Z"))); 215 assertThrows(UOE, () -> r.headers().map().remove("A")); 216 assertThrows(UOE, () -> r.headers().map().remove("A", "B")); 217 assertThrows(UOE, () -> r.headers().map().clear()); 218 assertThrows(UOE, () -> r.headers().allValues("A").remove("B")); 219 assertThrows(UOE, () -> r.headers().allValues("A").remove(1)); 220 assertThrows(UOE, () -> r.headers().allValues("A").clear()); 221 assertThrows(UOE, () -> r.headers().allValues("A").add("Z")); 222 assertThrows(UOE, () -> r.headers().allValues("A").addAll(List.of("Z"))); 223 assertThrows(UOE, () -> r.headers().allValues("A").add(1, "Z")); 224 } 225 226 requests = List.of( 227 // same headers built from different combinations of the API 228 newBuilder(uri).header("A", "B") 229 .header("C", "D").build(), 230 newBuilder(uri).header("A", "B") 231 .headers("C", "D").build(), 232 newBuilder(uri).header("A", "B") 233 .setHeader("C", "D").build(), 234 newBuilder(uri).headers("A", "B") 235 .headers("C", "D").build(), 236 newBuilder(uri).headers("A", "B") 237 .header("C", "D").build(), 238 newBuilder(uri).headers("A", "B") 239 .setHeader("C", "D").build(), 240 newBuilder(uri).setHeader("A", "B") 241 .setHeader("C", "D").build(), 242 newBuilder(uri).setHeader("A", "B") 243 .header("C", "D").build(), 244 newBuilder(uri).setHeader("A", "B") 245 .headers("C", "D").build(), 246 newBuilder(uri).headers("A", "B", "C", "D").build() 247 ); 248 249 for (HttpRequest r : requests) { 250 assertEquals(r.headers().map().size(), 2); 251 assertTrue(r.headers().firstValue("A").isPresent()); 252 assertEquals(r.headers().firstValue("A").get(), "B"); 253 assertEquals(r.headers().allValues("A"), List.of("B")); 254 assertTrue(r.headers().firstValue("C").isPresent()); 255 assertEquals(r.headers().firstValue("C").get(), "D"); 256 assertEquals(r.headers().allValues("C"), List.of("D")); 257 assertEquals(r.headers().map().get("C"), List.of("D")); 258 assertThrows(NFE, () -> r.headers().firstValueAsLong("C")); 259 assertFalse(r.headers().firstValue("E").isPresent()); 260 // a smaller non-exhaustive list of mutators 261 assertThrows(UOE, () -> r.headers().map().put("Z", List.of("Z"))); 262 assertThrows(UOE, () -> r.headers().map().remove("C")); 263 assertThrows(UOE, () -> r.headers().allValues("A").remove("B")); 264 assertThrows(UOE, () -> r.headers().allValues("A").clear()); 265 assertThrows(UOE, () -> r.headers().allValues("C").add("Z")); 266 } 267 268 requests = List.of( 269 // same multi-value headers built from different combinations of the API 270 newBuilder(uri).header("A", "B") 271 .header("A", "C").build(), 272 newBuilder(uri).header("A", "B") 273 .headers("A", "C").build(), 274 newBuilder(uri).headers("A", "B") 275 .headers("A", "C").build(), 276 newBuilder(uri).headers("A", "B") 277 .header("A", "C").build(), 278 newBuilder(uri).setHeader("A", "B") 279 .header("A", "C").build(), 280 newBuilder(uri).setHeader("A", "B") 281 .headers("A", "C").build(), 282 newBuilder(uri).header("A", "D") 283 .setHeader("A", "B") 284 .headers("A", "C").build(), 285 newBuilder(uri).headers("A", "B", "A", "C").build() 286 ); 287 288 for (HttpRequest r : requests) { 289 assertEquals(r.headers().map().size(), 1); 290 assertTrue(r.headers().firstValue("A").isPresent()); 291 assertTrue(r.headers().allValues("A").containsAll(List.of("B", "C"))); 292 assertEquals(r.headers().allValues("C").size(), 0); 293 assertEquals(r.headers().map().get("A"), List.of("B", "C")); 294 assertThrows(NFE, () -> r.headers().firstValueAsLong("A")); 295 assertFalse(r.headers().firstValue("C").isPresent()); 296 // a non-exhaustive list of mutators 297 assertThrows(UOE, () -> r.headers().map().put("Z", List.of("Z"))); 298 assertThrows(UOE, () -> r.headers().map().remove("A")); 299 assertThrows(UOE, () -> r.headers().map().remove("A", "B")); 300 assertThrows(UOE, () -> r.headers().map().clear()); 301 assertThrows(UOE, () -> r.headers().allValues("A").remove("B")); 302 assertThrows(UOE, () -> r.headers().allValues("A").remove(1)); 303 assertThrows(UOE, () -> r.headers().allValues("A").clear()); 304 assertThrows(UOE, () -> r.headers().allValues("A").add("Z")); 305 assertThrows(UOE, () -> r.headers().allValues("A").addAll(List.of("Z"))); 306 assertThrows(UOE, () -> r.headers().allValues("A").add(1, "Z")); 307 } 308 } 309 310 @Test 311 public void testCopy() { 312 HttpRequest.Builder builder = newBuilder(uri).expectContinue(true) 313 .header("A", "B") 314 .POST(fromString("")) 315 .timeout(ofSeconds(30)) 316 .version(HTTP_1_1); 317 HttpRequest.Builder copy = builder.copy(); 318 assertTrue(builder != copy); 319 320 // modify the original builder before building from the copy 321 builder.GET().timeout(ofSeconds(5)).version(HTTP_2).setHeader("A", "C"); 322 323 HttpRequest copyRequest = copy.build(); 324 assertEquals(copyRequest.uri(), uri); 325 assertEquals(copyRequest.expectContinue(), true); 326 assertEquals(copyRequest.headers().map().get("A"), List.of("B")); 327 assertEquals(copyRequest.method(), "POST"); 328 assertEquals(copyRequest.bodyPublisher().isPresent(), true); 329 assertEquals(copyRequest.timeout().get(), ofSeconds(30)); 330 assertTrue(copyRequest.version().isPresent()); 331 assertEquals(copyRequest.version().get(), HTTP_1_1); 332 } 333 334 @Test 335 public void testTimeout() { 336 HttpRequest.Builder builder = newBuilder(uri); 337 assertThrows(IAE, () -> builder.timeout(ZERO)); 338 assertThrows(IAE, () -> builder.timeout(ofSeconds(0))); 339 assertThrows(IAE, () -> builder.timeout(ofSeconds(-1))); 340 assertThrows(IAE, () -> builder.timeout(ofNanos(-100))); 341 assertEquals(builder.timeout(ofNanos(15)).build().timeout().get(), ofNanos(15)); 342 assertEquals(builder.timeout(ofSeconds(50)).build().timeout().get(), ofSeconds(50)); 343 assertEquals(builder.timeout(ofMinutes(30)).build().timeout().get(), ofMinutes(30)); 344 } 345 346 @Test 347 public void testExpect() { 348 HttpRequest.Builder builder = newBuilder(uri); 349 assertEquals(builder.build().expectContinue(), false); 350 assertEquals(builder.expectContinue(true).build().expectContinue(), true); 351 assertEquals(builder.expectContinue(false).build().expectContinue(), false); 352 assertEquals(builder.expectContinue(true).build().expectContinue(), true); 353 } 354 355 @Test 356 public void testEquals() { 357 assertNotEquals(newBuilder(URI.create("http://foo.com")), 358 newBuilder(URI.create("http://bar.com"))); 359 360 HttpRequest.Builder builder = newBuilder(uri); 361 assertEquals(builder.build(), builder.build()); 362 assertEquals(builder.build(), newBuilder(uri).build()); 363 364 builder.POST(noBody()); 365 assertEquals(builder.build(), builder.build()); 366 assertEquals(builder.build(), newBuilder(uri).POST(noBody()).build()); 367 assertEquals(builder.build(), newBuilder(uri).POST(fromString("")).build()); 368 assertNotEquals(builder.build(), newBuilder(uri).build()); 369 assertNotEquals(builder.build(), newBuilder(uri).GET().build()); 370 assertNotEquals(builder.build(), newBuilder(uri).PUT(noBody()).build()); 371 372 builder = newBuilder(uri).header("x", "y"); 373 assertEquals(builder.build(), builder.build()); 374 assertEquals(builder.build(), newBuilder(uri).header("x", "y").build()); 375 assertNotEquals(builder.build(), newBuilder(uri).header("x", "Z").build()); 376 assertNotEquals(builder.build(), newBuilder(uri).header("z", "y").build()); 377 } 378 }