1 /* 2 * Copyright (c) 2018, 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 Tests for HttpHeaders.of factory method 27 * @run testng HttpHeadersOf 28 */ 29 30 import java.net.http.HttpHeaders; 31 import java.util.ArrayList; 32 import java.util.LinkedList; 33 import java.util.List; 34 import java.util.Map; 35 import java.util.function.BiPredicate; 36 import org.testng.annotations.DataProvider; 37 import org.testng.annotations.Test; 38 import static org.testng.Assert.assertFalse; 39 import static org.testng.Assert.assertEquals; 40 import static org.testng.Assert.assertThrows; 41 import static org.testng.Assert.assertTrue; 42 import static org.testng.Assert.fail; 43 44 public class HttpHeadersOf { 45 46 static final Class<NullPointerException> NPE = NullPointerException.class; 47 static final Class<NumberFormatException> NFE = NumberFormatException.class; 48 static final Class<UnsupportedOperationException> UOE = UnsupportedOperationException.class; 49 50 static final BiPredicate<String,String> ACCEPT_ALL = 51 new BiPredicate<>() { 52 @Override public boolean test(String name, String value) { return true; } 53 @Override public String toString() { return "ACCEPT_ALL"; } 54 }; 55 56 static final BiPredicate<String,String> REJECT_ALL = 57 new BiPredicate<>() { 58 @Override public boolean test(String name, String value) { return false; } 59 @Override public String toString() { return "REJECT_ALL"; } 60 }; 61 62 @DataProvider(name = "predicates") 63 public Object[][] predicates() { 64 return new Object[][] { { ACCEPT_ALL }, { REJECT_ALL } }; 65 } 66 67 @Test(dataProvider = "predicates") 68 public void testNull(BiPredicate<String,String> filter) { 69 assertThrows(NPE, () -> HttpHeaders.of(null, null)); 70 assertThrows(NPE, () -> HttpHeaders.of(null, filter)); 71 assertThrows(NPE, () -> HttpHeaders.of(Map.of(), null)); 72 assertThrows(NPE, () -> HttpHeaders.of(Map.of("name", List.of("value")), null)); 73 74 // nulls in the Map 75 assertThrows(NPE, () -> HttpHeaders.of(Map.of(null, List.of("value)")), filter)); 76 assertThrows(NPE, () -> HttpHeaders.of(Map.of("name", null), filter)); 77 assertThrows(NPE, () -> HttpHeaders.of(Map.of("name", List.of(null)), filter)); 78 assertThrows(NPE, () -> HttpHeaders.of(Map.of("name", List.of("aValue", null)), filter)); 79 assertThrows(NPE, () -> HttpHeaders.of(Map.of("name", List.of(null, "aValue")), filter)); 80 } 81 82 83 @DataProvider(name = "filterMaps") 84 public Object[][] filterMaps() { 85 List<Map<String, List<String>>> maps = List.of( 86 Map.of("A", List.of("B"), "X", List.of("Y", "Z")), 87 Map.of("A", List.of("B", "C"), "X", List.of("Y", "Z")), 88 Map.of("A", List.of("B", "C", "D"), "X", List.of("Y", "Z")) 89 ); 90 return maps.stream().map(p -> new Object[] { p }).toArray(Object[][]::new); 91 } 92 93 @Test(dataProvider = "filterMaps") 94 public void testFilter(Map<String,List<String>> map) { 95 HttpHeaders headers = HttpHeaders.of(map, REJECT_ALL); 96 assertEquals(headers.map().size(), 0); 97 assertFalse(headers.firstValue("A").isPresent()); 98 assertEquals(headers.allValues("A").size(), 0); 99 100 headers = HttpHeaders.of(map, (name, value) -> { 101 if (name.equals("A")) return true; else return false; }); 102 assertEquals(headers.map().size(), 1); 103 assertTrue(headers.firstValue("A").isPresent()); 104 assertEquals(headers.allValues("A"), map.get("A")); 105 assertEquals(headers.allValues("A").size(), map.get("A").size()); 106 assertFalse(headers.firstValue("X").isPresent()); 107 108 headers = HttpHeaders.of(map, (name, value) -> { 109 if (name.equals("X")) return true; else return false; }); 110 assertEquals(headers.map().size(), 1); 111 assertTrue(headers.firstValue("X").isPresent()); 112 assertEquals(headers.allValues("X"), map.get("X")); 113 assertEquals(headers.allValues("X").size(), map.get("X").size()); 114 assertFalse(headers.firstValue("A").isPresent()); 115 } 116 117 118 @DataProvider(name = "mapValues") 119 public Object[][] mapValues() { 120 List<Map<String, List<String>>> maps = List.of( 121 Map.of("A", List.of("B")), 122 Map.of("A", List.of("B", "C")), 123 Map.of("A", List.of("B", "C", "D")), 124 125 Map.of("A", List.of("B"), "X", List.of("Y", "Z")), 126 Map.of("A", List.of("B", "C"), "X", List.of("Y", "Z")), 127 Map.of("A", List.of("B", "C", "D"), "X", List.of("Y", "Z")), 128 129 Map.of("A", List.of("B"), "X", List.of("Y", "Z")), 130 Map.of("A", List.of("B", "C"), "X", List.of("Y", "Z")), 131 Map.of("A", List.of("B", "C", "D"), "X", List.of("Y", "Z")), 132 133 Map.of("X", List.of("Y", "Z"), "A", List.of("B")), 134 Map.of("X", List.of("Y", "Z"), "A", List.of("B", "C")), 135 Map.of("X", List.of("Y", "Z"), "A", List.of("B", "C", "D")) 136 ); 137 return maps.stream().map(p -> new Object[] { p }).toArray(Object[][]::new); 138 } 139 140 @Test(dataProvider = "mapValues") 141 public void testMapValues(Map<String,List<String>> map) { 142 HttpHeaders headers = HttpHeaders.of(map, ACCEPT_ALL); 143 144 assertEquals(headers.map().size(), map.size()); 145 assertTrue(headers.firstValue("A").isPresent()); 146 assertTrue(headers.firstValue("a").isPresent()); 147 assertEquals(headers.firstValue("A").get(), "B"); 148 assertEquals(headers.firstValue("a").get(), "B"); 149 assertEquals(headers.allValues("A"), map.get("A")); 150 assertEquals(headers.allValues("a"), map.get("A")); 151 assertEquals(headers.allValues("F").size(), 0); 152 assertTrue(headers.map().get("A").contains("B")); 153 assertFalse(headers.map().get("A").contains("F")); 154 assertThrows(NFE, () -> headers.firstValueAsLong("A")); 155 156 // a non-exhaustive list of mutators 157 assertThrows(UOE, () -> headers.map().put("Z", List.of("Z"))); 158 assertThrows(UOE, () -> headers.map().remove("A")); 159 assertThrows(UOE, () -> headers.map().remove("A", "B")); 160 assertThrows(UOE, () -> headers.map().clear()); 161 assertThrows(UOE, () -> headers.allValues("A").remove("B")); 162 assertThrows(UOE, () -> headers.allValues("A").remove(1)); 163 assertThrows(UOE, () -> headers.allValues("A").clear()); 164 assertThrows(UOE, () -> headers.allValues("A").add("Z")); 165 assertThrows(UOE, () -> headers.allValues("A").addAll(List.of("Z"))); 166 assertThrows(UOE, () -> headers.allValues("A").add(1, "Z")); 167 } 168 169 170 @DataProvider(name = "caseInsensitivity") 171 public Object[][] caseInsensitivity() { 172 List<Map<String, List<String>>> maps = List.of( 173 Map.of("Accept-Encoding", List.of("gzip, deflate")), 174 Map.of("accept-encoding", List.of("gzip, deflate")), 175 Map.of("AccePT-ENCoding", List.of("gzip, deflate")), 176 Map.of("ACCept-EncodING", List.of("gzip, deflate")), 177 Map.of("ACCEPT-ENCODING", List.of("gzip, deflate")) 178 ); 179 return maps.stream().map(p -> new Object[] { p }).toArray(Object[][]::new); 180 } 181 182 @Test(dataProvider = "caseInsensitivity") 183 public void testCaseInsensitivity(Map<String,List<String>> map) { 184 HttpHeaders headers = HttpHeaders.of(map, ACCEPT_ALL); 185 186 for (String name : List.of("Accept-Encoding", "accept-encoding", 187 "aCCept-EnCODing", "accepT-encodinG")) { 188 assertTrue(headers.firstValue(name).isPresent()); 189 assertTrue(headers.allValues(name).contains("gzip, deflate")); 190 assertEquals(headers.firstValue(name).get(), "gzip, deflate"); 191 assertEquals(headers.allValues(name).size(), 1); 192 assertEquals(headers.map().size(), 1); 193 assertEquals(headers.map().get(name).size(), 1); 194 assertEquals(headers.map().get(name).get(0), "gzip, deflate"); 195 } 196 } 197 198 @DataProvider(name = "valueAsLong") 199 public Object[][] valueAsLong() { 200 return new Object[][] { 201 new Object[] { Map.of("Content-Length", List.of("10")), 10l }, 202 new Object[] { Map.of("Content-Length", List.of("101")), 101l }, 203 new Object[] { Map.of("Content-Length", List.of("56789")), 56789l }, 204 new Object[] { Map.of("Content-Length", List.of(Long.toString(Long.MAX_VALUE))), Long.MAX_VALUE }, 205 new Object[] { Map.of("Content-Length", List.of(Long.toString(Long.MIN_VALUE))), Long.MIN_VALUE } 206 }; 207 } 208 209 @Test(dataProvider = "valueAsLong") 210 public void testValueAsLong(Map<String,List<String>> map, long expected) { 211 HttpHeaders headers = HttpHeaders.of(map, ACCEPT_ALL); 212 assertEquals(headers.firstValueAsLong("Content-Length").getAsLong(), expected); 213 } 214 215 216 @DataProvider(name = "duplicateNames") 217 public Object[][] duplicateNames() { 218 List<Map<String, List<String>>> maps = List.of( 219 Map.of("X-name", List.of(), 220 "x-name", List.of()), 221 Map.of("X-name", List.of(""), 222 "x-name", List.of("")), 223 Map.of("X-name", List.of("C"), 224 "x-name", List.of("D")), 225 Map.of("X-name", List.of("E"), 226 "Y-name", List.of("F"), 227 "X-Name", List.of("G")), 228 Map.of("X-chegar", List.of("H"), 229 "y-dfuchs", List.of("I"), 230 "Y-dfuchs", List.of("J")), 231 Map.of("X-name ", List.of("K"), 232 "X-Name", List.of("L")), 233 Map.of("X-name", List.of("M"), 234 "\rX-Name", List.of("N")) 235 ); 236 return maps.stream().map(p -> new Object[] { p }).toArray(Object[][]::new); 237 } 238 239 @Test(dataProvider = "duplicateNames") 240 public void testDuplicates(Map<String,List<String>> map) { 241 HttpHeaders headers; 242 try { 243 headers = HttpHeaders.of(map, ACCEPT_ALL); 244 fail("UNEXPECTED: " + headers); 245 } catch (IllegalArgumentException iae) { 246 System.out.println("caught EXPECTED IAE:" + iae); 247 assertTrue(iae.getMessage().contains("duplicate")); 248 } 249 } 250 251 252 @DataProvider(name = "noSplittingJoining") 253 public Object[][] noSplittingJoining() { 254 List<Map<String, List<String>>> maps = List.of( 255 Map.of("A", List.of("B")), 256 Map.of("A", List.of("B", "C")), 257 Map.of("A", List.of("B", "C", "D")), 258 Map.of("A", List.of("B", "C", "D", "E")), 259 Map.of("A", List.of("B", "C", "D", "E", "F")), 260 Map.of("A", List.of("B, C")), 261 Map.of("A", List.of("B, C, D")), 262 Map.of("A", List.of("B, C, D, E")), 263 Map.of("A", List.of("B, C, D, E, F")), 264 Map.of("A", List.of("B, C", "D", "E", "F")), 265 Map.of("A", List.of("B", "C, D", "E", "F")), 266 Map.of("A", List.of("B", "C, D", "E, F")), 267 Map.of("A", List.of("B", "C, D, E", "F")), 268 Map.of("A", List.of("B", "C, D, E, F")) 269 ); 270 return maps.stream().map(p -> new Object[] { p }).toArray(Object[][]::new); 271 } 272 273 @Test(dataProvider = "noSplittingJoining") 274 public void testNoSplittingJoining(Map<String,List<String>> map) { 275 HttpHeaders headers = HttpHeaders.of(map, ACCEPT_ALL); 276 Map<String,List<String>> headersMap = headers.map(); 277 278 assertEquals(headers.map().size(), map.size()); 279 for (Map.Entry<String,List<String>> entry : map.entrySet()) { 280 String headerName = entry.getKey(); 281 List<String> headerValues = entry.getValue(); 282 assertEquals(headerValues, headersMap.get(headerName)); 283 assertEquals(headerValues, headers.allValues(headerName)); 284 assertEquals(headerValues.get(0), headers.firstValue(headerName).get()); 285 } 286 } 287 288 289 @DataProvider(name = "trimming") 290 public Object[][] trimming() { 291 List<Map<String, List<String>>> maps = List.of( 292 Map.of("A", List.of("B")), 293 Map.of(" A", List.of("B")), 294 Map.of("A ", List.of("B")), 295 Map.of("A", List.of(" B")), 296 Map.of("A", List.of("B ")), 297 Map.of("\tA", List.of("B")), 298 Map.of("A\t", List.of("B")), 299 Map.of("A", List.of("\tB")), 300 Map.of("A", List.of("B\t")), 301 Map.of("A\r", List.of("B")), 302 Map.of("A\n", List.of("B")), 303 Map.of("A\r\n", List.of("B")) 304 ); 305 return maps.stream().map(p -> new Object[] { p }).toArray(Object[][]::new); 306 } 307 308 @Test(dataProvider = "trimming") 309 public void testTrimming(Map<String,List<String>> map) { 310 HttpHeaders headers = HttpHeaders.of(map, (name, value) -> { 311 assertEquals(name, "A"); 312 assertEquals(value, "B"); 313 return true; 314 }); 315 316 assertEquals(headers.map().size(), 1); 317 assertEquals(headers.firstValue("A").get(), "B"); 318 assertEquals(headers.allValues("A"), List.of("B")); 319 assertTrue(headers.map().get("A").equals(List.of("B"))); 320 } 321 322 323 @DataProvider(name = "emptyKey") 324 public Object[][] emptyKey() { 325 List<Map<String, List<String>>> maps = List.of( 326 Map.of("", List.of("B")), 327 Map.of(" ", List.of("B")), 328 Map.of(" ", List.of("B")), 329 Map.of("\t", List.of("B")), 330 Map.of("\t\t", List.of("B")) 331 ); 332 return maps.stream().map(p -> new Object[] { p }).toArray(Object[][]::new); 333 } 334 335 @Test(dataProvider = "emptyKey") 336 public void testEmptyKey(Map<String,List<String>> map) { 337 HttpHeaders headers; 338 try { 339 headers = HttpHeaders.of(map, ACCEPT_ALL); 340 fail("UNEXPECTED: " + headers); 341 } catch (IllegalArgumentException iae) { 342 System.out.println("caught EXPECTED IAE:" + iae); 343 assertTrue(iae.getMessage().contains("empty")); 344 } 345 } 346 347 348 @DataProvider(name = "emptyValue") 349 public Object[][] emptyValue() { 350 List<Map<String, List<String>>> maps = List.of( 351 Map.of("A", List.of("")), 352 Map.of("A", List.of("", "")), 353 Map.of("A", List.of("", "", " ")), 354 Map.of("A", List.of("\t")), 355 Map.of("A", List.of("\t\t")) 356 ); 357 return maps.stream().map(p -> new Object[] { p }).toArray(Object[][]::new); 358 } 359 360 @Test(dataProvider = "emptyValue") 361 public void testEmptyValue(Map<String,List<String>> map) { 362 HttpHeaders headers = HttpHeaders.of(map, (name, value) -> { 363 assertEquals(value, ""); 364 return true; 365 }); 366 assertEquals(headers.map().size(), map.size()); 367 assertEquals(headers.map().get("A").get(0), ""); 368 headers.allValues("A").forEach(v -> assertEquals(v, "")); 369 assertEquals(headers.firstValue("A").get(), ""); 370 } 371 372 373 @DataProvider(name = "noValues") 374 public Object[][] noValues() { 375 List<Map<String, List<String>>> maps = List.of( 376 Map.of("A", List.of()), 377 Map.of("A", List.of(), "B", List.of()), 378 Map.of("A", List.of(), "B", List.of(), "C", List.of()), 379 Map.of("A", new ArrayList()), 380 Map.of("A", new LinkedList()) 381 ); 382 return maps.stream().map(p -> new Object[] { p }).toArray(Object[][]::new); 383 } 384 385 @Test(dataProvider = "noValues") 386 public void testNoValues(Map<String,List<String>> map) { 387 HttpHeaders headers = HttpHeaders.of(map, (name, value) -> { 388 fail("UNEXPECTED call to filter"); 389 return true; 390 }); 391 assertEquals(headers.map().size(), 0); 392 assertEquals(headers.map().get("A"), null); 393 assertEquals(headers.allValues("A").size(), 0); 394 assertFalse(headers.firstValue("A").isPresent()); 395 } 396 }