Skip to content

Commit

Permalink
[grid][java] do not rely on .hashCode for .equals (#12361)
Browse files Browse the repository at this point in the history
Co-authored-by: Diego Molina <diemol@users.noreply.github.com>
  • Loading branch information
joerg1985 and diemol committed Jul 17, 2023
1 parent f13370b commit 6865f1c
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 6 deletions.
20 changes: 14 additions & 6 deletions java/src/org/openqa/selenium/SharedCapabilitiesMethods.java
Expand Up @@ -17,31 +17,39 @@

package org.openqa.selenium;

import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.openqa.selenium.logging.LogLevelMapping;
import org.openqa.selenium.logging.LoggingPreferences;

class SharedCapabilitiesMethods {

private static final String[] EMPTY_ARRAY = new String[0];

private SharedCapabilitiesMethods() {
// Utility class
}

static int hashCode(Capabilities caps) {
return caps.getCapabilityNames().stream()
.sorted()
.mapToInt(name -> Objects.hash(name, caps.getCapability(name)))
.reduce(0, (l, r) -> l ^ r);
String[] sortedNames = caps.getCapabilityNames().toArray(EMPTY_ARRAY);
Arrays.sort(sortedNames, String::compareTo);
// we only use the names to generate a hash code, this might result in hash collisions. thanks to the
// moz:firefoxOptions, goog:chromeOptions and ms:edgeOptions, these hash collisions should not happen too often.
return Arrays.hashCode(sortedNames);
}

static boolean equals(Capabilities left, Capabilities right) {
return left.hashCode() == right.hashCode();
if (left == right) {
return true;
}
// deeply compare the keys & values, usually only called when the hash codes of two objects are identical.
// note: there should be no arrays (directly or nested) inside the map, otherwise the equals will not work.
return left.asMap().equals(right.asMap());
}

static void setCapability(Map<String, Object> caps, String key, Object value) {
Expand Down
9 changes: 9 additions & 0 deletions java/test/org/openqa/selenium/CapabilitiesTest.java
Expand Up @@ -129,4 +129,13 @@ void ensureHashCodesAreEqual() {
assertThat(one.hashCode()).isEqualTo(three.hashCode());
assertThat(two.hashCode()).isEqualTo(three.hashCode());
}

@Test
void ensureEqualHashCodesMightBeNotEqual() {
Capabilities one = new ImmutableCapabilities("key", "DB");
Capabilities two = new ImmutableCapabilities("key", "Ca");

assertThat(one.hashCode()).isEqualTo(two.hashCode());
assertThat(one).isNotEqualTo(two);
}
}

0 comments on commit 6865f1c

Please sign in to comment.