Add the equals method to IceServer.

Bug: None
Change-Id: I4bac54489a44a4577cc221ba51351e4a3a92e69b
Reviewed-on: https://webrtc-review.googlesource.com/c/116081
Commit-Queue: Qingsi Wang <qingsi@webrtc.org>
Reviewed-by: Honghai Zhang <honghaiz@webrtc.org>
Reviewed-by: Alex Glaznev <glaznev@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#26271}
diff --git a/sdk/android/api/org/webrtc/PeerConnection.java b/sdk/android/api/org/webrtc/PeerConnection.java
index db973f2..0dc5c63 100644
--- a/sdk/android/api/org/webrtc/PeerConnection.java
+++ b/sdk/android/api/org/webrtc/PeerConnection.java
@@ -12,6 +12,7 @@
 
 import android.support.annotation.Nullable;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 import org.webrtc.DataChannel;
@@ -222,6 +223,31 @@
           + "] [" + tlsAlpnProtocols + "] [" + tlsEllipticCurves + "]";
     }
 
+    @Override
+    public boolean equals(@Nullable Object obj) {
+      if (obj == null) {
+        return false;
+      }
+      if (obj == this) {
+        return true;
+      }
+      if (!(obj instanceof IceServer)) {
+        return false;
+      }
+      IceServer other = (IceServer) obj;
+      return (uri.equals(other.uri) && urls.equals(other.urls) && username.equals(other.username)
+          && password.equals(other.password) && tlsCertPolicy.equals(other.tlsCertPolicy)
+          && hostname.equals(other.hostname) && tlsAlpnProtocols.equals(other.tlsAlpnProtocols)
+          && tlsEllipticCurves.equals(other.tlsEllipticCurves));
+    }
+
+    @Override
+    public int hashCode() {
+      Object[] values = {uri, urls, username, password, tlsCertPolicy, hostname, tlsAlpnProtocols,
+          tlsEllipticCurves};
+      return Arrays.hashCode(values);
+    }
+
     public static Builder builder(String uri) {
       return new Builder(Collections.singletonList(uri));
     }
diff --git a/sdk/android/instrumentationtests/src/org/webrtc/PeerConnectionTest.java b/sdk/android/instrumentationtests/src/org/webrtc/PeerConnectionTest.java
index 21dcd15..e8859e0 100644
--- a/sdk/android/instrumentationtests/src/org/webrtc/PeerConnectionTest.java
+++ b/sdk/android/instrumentationtests/src/org/webrtc/PeerConnectionTest.java
@@ -10,6 +10,7 @@
 
 package org.webrtc;
 
+import static java.util.Collections.singletonList;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
@@ -47,6 +48,7 @@
 import org.webrtc.PeerConnection.IceGatheringState;
 import org.webrtc.PeerConnection.PeerConnectionState;
 import org.webrtc.PeerConnection.SignalingState;
+import org.webrtc.PeerConnection.TlsCertPolicy;
 
 /** End-to-end tests for PeerConnection.java. */
 @RunWith(BaseJUnit4ClassRunner.class)
@@ -651,6 +653,109 @@
     // Thread.sleep(100);
   }
 
+  @Test
+  @SmallTest
+  public void testIceServerChanged() throws Exception {
+    PeerConnection.IceServer iceServer1 =
+        PeerConnection.IceServer.builder("turn:fake.example.com")
+            .setUsername("fakeUsername")
+            .setPassword("fakePassword")
+            .setTlsCertPolicy(TlsCertPolicy.TLS_CERT_POLICY_SECURE)
+            .setHostname("fakeHostname")
+            .setTlsAlpnProtocols(singletonList("fakeTlsAlpnProtocol"))
+            .setTlsEllipticCurves(singletonList("fakeTlsEllipticCurve"))
+            .createIceServer();
+    // Same as iceServer1.
+    PeerConnection.IceServer iceServer2 =
+        PeerConnection.IceServer.builder("turn:fake.example.com")
+            .setUsername("fakeUsername")
+            .setPassword("fakePassword")
+            .setTlsCertPolicy(TlsCertPolicy.TLS_CERT_POLICY_SECURE)
+            .setHostname("fakeHostname")
+            .setTlsAlpnProtocols(singletonList("fakeTlsAlpnProtocol"))
+            .setTlsEllipticCurves(singletonList("fakeTlsEllipticCurve"))
+            .createIceServer();
+    // Differs from iceServer1 by the url.
+    PeerConnection.IceServer iceServer3 =
+        PeerConnection.IceServer.builder("turn:fake.example2.com")
+            .setUsername("fakeUsername")
+            .setPassword("fakePassword")
+            .setTlsCertPolicy(TlsCertPolicy.TLS_CERT_POLICY_SECURE)
+            .setHostname("fakeHostname")
+            .setTlsAlpnProtocols(singletonList("fakeTlsAlpnProtocol"))
+            .setTlsEllipticCurves(singletonList("fakeTlsEllipticCurve"))
+            .createIceServer();
+    // Differs from iceServer1 by the username.
+    PeerConnection.IceServer iceServer4 =
+        PeerConnection.IceServer.builder("turn:fake.example.com")
+            .setUsername("fakeUsername2")
+            .setPassword("fakePassword")
+            .setTlsCertPolicy(TlsCertPolicy.TLS_CERT_POLICY_SECURE)
+            .setHostname("fakeHostname")
+            .setTlsAlpnProtocols(singletonList("fakeTlsAlpnProtocol"))
+            .setTlsEllipticCurves(singletonList("fakeTlsEllipticCurve"))
+            .createIceServer();
+    // Differs from iceServer1 by the password.
+    PeerConnection.IceServer iceServer5 =
+        PeerConnection.IceServer.builder("turn:fake.example.com")
+            .setUsername("fakeUsername")
+            .setPassword("fakePassword2")
+            .setTlsCertPolicy(TlsCertPolicy.TLS_CERT_POLICY_SECURE)
+            .setHostname("fakeHostname")
+            .setTlsAlpnProtocols(singletonList("fakeTlsAlpnProtocol"))
+            .setTlsEllipticCurves(singletonList("fakeTlsEllipticCurve"))
+            .createIceServer();
+    // Differs from iceServer1 by the TLS certificate policy.
+    PeerConnection.IceServer iceServer6 =
+        PeerConnection.IceServer.builder("turn:fake.example.com")
+            .setUsername("fakeUsername")
+            .setPassword("fakePassword")
+            .setTlsCertPolicy(TlsCertPolicy.TLS_CERT_POLICY_INSECURE_NO_CHECK)
+            .setHostname("fakeHostname")
+            .setTlsAlpnProtocols(singletonList("fakeTlsAlpnProtocol"))
+            .setTlsEllipticCurves(singletonList("fakeTlsEllipticCurve"))
+            .createIceServer();
+    // Differs from iceServer1 by the hostname.
+    PeerConnection.IceServer iceServer7 =
+        PeerConnection.IceServer.builder("turn:fake.example.com")
+            .setUsername("fakeUsername")
+            .setPassword("fakePassword")
+            .setTlsCertPolicy(TlsCertPolicy.TLS_CERT_POLICY_INSECURE_NO_CHECK)
+            .setHostname("fakeHostname2")
+            .setTlsAlpnProtocols(singletonList("fakeTlsAlpnProtocol"))
+            .setTlsEllipticCurves(singletonList("fakeTlsEllipticCurve"))
+            .createIceServer();
+    // Differs from iceServer1 by the TLS ALPN.
+    PeerConnection.IceServer iceServer8 =
+        PeerConnection.IceServer.builder("turn:fake.example.com")
+            .setUsername("fakeUsername")
+            .setPassword("fakePassword")
+            .setTlsCertPolicy(TlsCertPolicy.TLS_CERT_POLICY_INSECURE_NO_CHECK)
+            .setHostname("fakeHostname")
+            .setTlsAlpnProtocols(singletonList("fakeTlsAlpnProtocol2"))
+            .setTlsEllipticCurves(singletonList("fakeTlsEllipticCurve"))
+            .createIceServer();
+    // Differs from iceServer1 by the TLS elliptic curve.
+    PeerConnection.IceServer iceServer9 =
+        PeerConnection.IceServer.builder("turn:fake.example.com")
+            .setUsername("fakeUsername")
+            .setPassword("fakePassword")
+            .setTlsCertPolicy(TlsCertPolicy.TLS_CERT_POLICY_INSECURE_NO_CHECK)
+            .setHostname("fakeHostname")
+            .setTlsAlpnProtocols(singletonList("fakeTlsAlpnProtocol"))
+            .setTlsEllipticCurves(singletonList("fakeTlsEllipticCurve2"))
+            .createIceServer();
+
+    assertTrue(iceServer1.equals(iceServer2));
+    assertFalse(iceServer1.equals(iceServer3));
+    assertFalse(iceServer1.equals(iceServer4));
+    assertFalse(iceServer1.equals(iceServer5));
+    assertFalse(iceServer1.equals(iceServer6));
+    assertFalse(iceServer1.equals(iceServer7));
+    assertFalse(iceServer1.equals(iceServer8));
+    assertFalse(iceServer1.equals(iceServer9));
+  }
+
   // TODO(fischman) MOAR test ideas:
   // - Test that PC.removeStream() works; requires a second
   //   createOffer/createAnswer dance.