http-client-branch: review comment - HttpHeaders::hashCode implementation doesn't obey its specification
--- a/src/java.net.http/share/classes/java/net/http/HttpHeaders.java Tue Jun 19 16:33:07 2018 +0100
+++ b/src/java.net.http/share/classes/java/net/http/HttpHeaders.java Wed Jun 20 11:52:31 2018 +0100
@@ -153,7 +153,11 @@
* @return the hash-code value for this HTTP headers
*/
public final int hashCode() {
- return map().hashCode();
+ int h = 0;
+ for (Map.Entry<String, List<String>> e : map().entrySet()) {
+ h += entryHash(e);
+ }
+ return h;
}
/**
@@ -218,6 +222,15 @@
this.headers = headers;
}
+ private static final int entryHash(Map.Entry<String, List<String>> e) {
+ String key = e.getKey();
+ List<String> value = e.getValue();
+ // we know that by construction key and values can't be null
+ int keyHash = key.toLowerCase(Locale.ROOT).hashCode();
+ int valueHash = value.hashCode();
+ return keyHash ^ valueHash;
+ }
+
// Returns a new HTTP headers after performing a structural copy and filtering.
private static HttpHeaders headersOf(Map<String,List<String>> map,
BiPredicate<String,String> filter) {
--- a/test/jdk/java/net/httpclient/HttpHeadersOf.java Tue Jun 19 16:33:07 2018 +0100
+++ b/test/jdk/java/net/httpclient/HttpHeadersOf.java Wed Jun 20 11:52:31 2018 +0100
@@ -195,6 +195,32 @@
}
}
+ @Test
+ public void testEqualsAndHashCode() {
+ List<Map<String, List<String>>> maps = List.of(
+ Map.of("Accept-Encoding", List.of("gzip, deflate")),
+ Map.of("accept-encoding", List.of("gzip, deflate")),
+ Map.of("AccePT-ENCoding", List.of("gzip, deflate")),
+ Map.of("ACCept-EncodING", List.of("gzip, deflate")),
+ Map.of("ACCEPT-ENCODING", List.of("gzip, deflate"))
+ );
+ int mapDiffer = 0;
+ int mapHashDiffer = 0;
+ for (Map<String, List<String>> m1 : maps) {
+ HttpHeaders h1 = HttpHeaders.of(m1, ACCEPT_ALL);
+ for (Map<String, List<String>> m2 : maps) {
+ HttpHeaders h2 = HttpHeaders.of(m2, ACCEPT_ALL);
+ if (!m1.equals(m2)) mapDiffer++;
+ if (m1.hashCode() != m2.hashCode()) mapHashDiffer++;
+ assertEquals(h1, h2, "HttpHeaders differ");
+ assertEquals(h1.hashCode(), h2.hashCode(),
+ "hashCode differ for " + List.of(m1,m2));
+ }
+ }
+ assertTrue(mapDiffer > 0, "all maps were equal!");
+ assertTrue(mapHashDiffer > 0, "all maps had same hashCode!");
+ }
+
@DataProvider(name = "valueAsLong")
public Object[][] valueAsLong() {
return new Object[][] {