You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by jb...@apache.org on 2021/02/03 16:59:44 UTC
[geode-native] branch develop updated: GEODE-8910: Corrects hashing
between .NET and Java (#740)
This is an automated email from the ASF dual-hosted git repository.
jbarrett pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/geode-native.git
The following commit(s) were added to refs/heads/develop by this push:
new 798aafb GEODE-8910: Corrects hashing between .NET and Java (#740)
798aafb is described below
commit 798aafb8e43536a07a809940a05cdd846d94cc93
Author: Jacob Barrett <jb...@pivotal.io>
AuthorDate: Wed Feb 3 08:59:36 2021 -0800
GEODE-8910: Corrects hashing between .NET and Java (#740)
* Adds Objects util similar to Java's Objects util.
* Adds test to validate consistency with Java.
---
clicache/integration-test2/PositionKey.cs | 4 +-
clicache/src/CMakeLists.txt | 2 +
clicache/src/CacheableDate.cpp | 6 +-
clicache/src/Objects.cpp | 162 +++++++++++++++
clicache/src/Objects.hpp | 178 +++++++++++++++++
clicache/test2/CMakeLists.txt | 11 +-
clicache/test2/ObjectsTests.cs | 316 ++++++++++++++++++++++++++++++
tests/javaobject/cli/PositionKey.java | 7 +-
8 files changed, 669 insertions(+), 17 deletions(-)
diff --git a/clicache/integration-test2/PositionKey.cs b/clicache/integration-test2/PositionKey.cs
index 02c6163..3c1c21b 100644
--- a/clicache/integration-test2/PositionKey.cs
+++ b/clicache/integration-test2/PositionKey.cs
@@ -92,9 +92,7 @@ namespace Apache.Geode.Client.IntegrationTests
public override int GetHashCode()
{
- int hash = 11;
- hash = 31 * hash + (int)m_positionId;
- return hash;
+ return Objects.Hash(m_positionId);
}
}
}
diff --git a/clicache/src/CMakeLists.txt b/clicache/src/CMakeLists.txt
index 8ad3b32..eddf595 100644
--- a/clicache/src/CMakeLists.txt
+++ b/clicache/src/CMakeLists.txt
@@ -152,6 +152,8 @@ add_library(Apache.Geode SHARED
native_conditional_unique_ptr.hpp
native_shared_ptr.hpp
native_unique_ptr.hpp
+ Objects.cpp
+ Objects.hpp
PdxIdentityFieldAttribute.hpp
Pool.cpp
Pool.hpp
diff --git a/clicache/src/CacheableDate.cpp b/clicache/src/CacheableDate.cpp
index c2f2064..9421489 100644
--- a/clicache/src/CacheableDate.cpp
+++ b/clicache/src/CacheableDate.cpp
@@ -20,6 +20,7 @@
#include "DataInput.hpp"
#include "DataOutput.hpp"
#include "Log.hpp"
+#include "Objects.hpp"
using namespace System;
@@ -82,10 +83,7 @@ namespace Apache
System::Int32 CacheableDate::GetHashCode()
{
if (m_hashcode == 0) {
- TimeSpan epochSpan = m_dateTime - EpochTime;
- System::Int64 millitime =
- epochSpan.Ticks / TimeSpan::TicksPerMillisecond;
- m_hashcode = (int)millitime ^ (int)((System::Int64)millitime >> 32);
+ m_hashcode = Objects::GetHashCode(m_dateTime);
}
return m_hashcode;
}
diff --git a/clicache/src/Objects.cpp b/clicache/src/Objects.cpp
new file mode 100644
index 0000000..ee587df
--- /dev/null
+++ b/clicache/src/Objects.cpp
@@ -0,0 +1,162 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Objects.hpp"
+
+#include "CacheableDate.hpp"
+#include "ICacheableKey.hpp"
+
+using namespace System;
+using namespace System::Collections;
+using namespace Apache::Geode::Client;
+
+namespace Apache {
+namespace Geode {
+
+Int32 Objects::Hash(... array<Object^>^ values) {
+ return Objects::GetHashCode(values);
+}
+
+Int32 Objects::GetHashCode(Object^ value) {
+ if (nullptr == value) {
+ return 0;
+ } else if (auto s = dynamic_cast<String^>(value)) {
+ return GetHashCode(s);
+ } else if (auto i = dynamic_cast<Int32^>(value)) {
+ return GetHashCode(*i);
+ } else if (auto l = dynamic_cast<Int64^>(value)) {
+ return GetHashCode(*l);
+ } else if (auto s = dynamic_cast<Int16^>(value)) {
+ return GetHashCode(*s);
+ } else if (auto s = dynamic_cast<Char^>(value)) {
+ return GetHashCode(*s);
+ } else if (auto d = dynamic_cast<DateTime^>(value)) {
+ return GetHashCode(*d);
+ } else if (auto b = dynamic_cast<SByte^>(value)) {
+ return GetHashCode(*b);
+ } else if (auto s = dynamic_cast<Single^>(value)) {
+ return GetHashCode(*s);
+ } else if (auto d = dynamic_cast<Double^>(value)) {
+ return GetHashCode(*d);
+ } else if (auto b = dynamic_cast<Boolean^>(value)) {
+ return GetHashCode(*b);
+ } else if (auto k = dynamic_cast<ICacheableKey^>(value)) {
+ return k->GetHashCode();
+ } else if (auto c = dynamic_cast<IDictionary^>(value)) {
+ return GetHashCode(c);
+ } else if (auto c = dynamic_cast<ICollection^>(value)) {
+ return GetHashCode(c);
+ }
+
+ return value->GetHashCode();
+}
+
+Int32 Objects::GetHashCode(String^ value) {
+ Int32 hash = 0;
+ for each(auto c in value) {
+ hash = 31 * hash + c;
+ }
+ return hash;
+}
+
+Int32 Objects::GetHashCode(Char value) { return value; }
+
+Int32 Objects::GetHashCode(Boolean value) { return value ? 1231 : 1237; }
+
+Int32 Objects::GetHashCode(SByte value) { return value; }
+
+Int32 Objects::GetHashCode(Int16 value) { return value; }
+
+Int32 Objects::GetHashCode(Int32 value) { return value; }
+
+Int32 Objects::GetHashCode(Int64 value) {
+ return static_cast<Int32>(value ^ (value >> 32));
+}
+
+union float_int64_t {
+ float f;
+ int32_t u;
+};
+
+constexpr auto kJavaFloatNaN = 0x7fc00000;
+
+Int32 Objects::GetHashCode(Single value) {
+ float_int64_t v;
+ if (Single::IsNaN(value)) {
+ // .NET and Java don't aggree on NaN encoding
+ v.u = kJavaFloatNaN;
+ } else {
+ v.f = value;
+ }
+ return GetHashCode(v.u);
+}
+
+union double_int64_t {
+ double d;
+ int64_t u;
+};
+
+constexpr auto kJavaDoubleNaN = 0x7ff8000000000000L;
+
+Int32 Objects::GetHashCode(Double value) {
+ double_int64_t v;
+ if (Double::IsNaN(value)) {
+ // .NET and Java don't aggree on NaN encoding
+ v.u = kJavaDoubleNaN;
+ } else {
+ v.d = value;
+ }
+ return GetHashCode(v.u);
+}
+
+Int32 Objects::GetHashCode(DateTime^ value) {
+ if (value == nullptr) {
+ return 0;
+ }
+
+ return GetHashCode(*value);
+}
+
+Int32 Objects::GetHashCode(DateTime value) {
+ auto timeSpanSinceEpoch = value - CacheableDate::EpochTime;
+ auto milliseconds = timeSpanSinceEpoch.Ticks / TimeSpan::TicksPerMillisecond;
+ return GetHashCode(milliseconds);
+}
+
+Int32 Objects::GetHashCode(ICollection^ value) {
+ if (value == nullptr) {
+ return 0;
+ }
+
+ int result = 1;
+ for each (auto element in value) {
+ result = 31 * result + Objects::GetHashCode(element);
+ }
+ return result;
+}
+
+Int32 Objects::GetHashCode(System::Collections::IDictionary^ dictionary) {
+ int h = 0;
+ for each(System::Collections::DictionaryEntry^ entry in dictionary)
+ {
+ h = h + (GetHashCode(entry->Key) ^ GetHashCode(entry->Value));
+ }
+ return h;
+}
+
+} // namespace Geode
+} // namespace Apache
diff --git a/clicache/src/Objects.hpp b/clicache/src/Objects.hpp
new file mode 100644
index 0000000..01d9ad8
--- /dev/null
+++ b/clicache/src/Objects.hpp
@@ -0,0 +1,178 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+using namespace System;
+
+namespace Apache {
+namespace Geode {
+
+/// <summary>
+/// Provides hash code functions similar to those used by Geode server in
+/// Java's java.util.Objects and java.util.Arrays classes.
+///
+/// Example:
+/// <pre>
+/// class CustomKey
+/// {
+/// private int a;
+/// private double b;
+/// private String c;
+///
+/// public CustomKey(int a, double b, String c)
+/// {
+/// this.a = a;
+/// this.b = b;
+/// this.c = c;
+/// }
+///
+/// override public int GetHashCode()
+/// {
+/// return Objects.Hash(a, b, c);
+/// }
+/// };
+/// </pre>
+/// </summary>
+ public ref class Objects {
+ public:
+ /// <summary>
+ /// Hashes consistent with java.util.Objects.hash(Object ...).
+ /// </summary>
+ /// <param name="values">
+ /// Variable arguments to combine into hash.
+ /// </param>
+ static Int32 Hash(... array<Object^>^ values);
+
+
+ /// <summary>
+ /// Hashes consistent with java.util.Objects.hashCode(Object).
+ /// </summary>
+ /// <param name="value">
+ /// Object to hash.
+ /// </param>
+ static Int32 GetHashCode(Object^ value);
+
+
+ /// <summary>
+ /// Hashes consistent with java.lang.String.hashCode().
+ /// </summary>
+ /// <param name="value">
+ /// String to hash.
+ /// </param>
+ static Int32 GetHashCode(String^ value);
+
+ /// <summary>
+ /// Hashes consistent with java.lang.Character.hashCode().
+ /// </summary>
+ /// <param name="value">
+ /// Character to hash.
+ /// </param>
+ static Int32 GetHashCode(Char value);
+
+ /// <summary>
+ /// Hashes consistent with java.lang.Boolean.hashCode().
+ /// </summary>
+ /// <param name="value">
+ /// Boolean to hash.
+ /// </param>
+ static Int32 GetHashCode(Boolean value);
+
+ /// <summary>
+ /// Hashes consistent with java.lang.Byte.hashCode().
+ /// </summary>
+ /// <param name="value">
+ /// Byte to hash.
+ /// </param>
+ static Int32 GetHashCode(SByte value);
+
+ /// <summary>
+ /// Hashes consistent with java.lang.Short.hashCode().
+ /// </summary>
+ /// <param name="value">
+ /// Short to hash.
+ /// </param>
+ static Int32 GetHashCode(Int16 value);
+
+ /// <summary>
+ /// Hashes consistent with java.lang.Integer.hashCode().
+ /// </summary>
+ /// <param name="value">
+ /// Integer to hash.
+ /// </param>
+ static Int32 GetHashCode(Int32 value);
+
+ /// <summary>
+ /// Hashes consistent with java.lang.Long.hashCode().
+ /// </summary>
+ /// <param name="value">
+ /// Long to hash.
+ /// </param>
+ static Int32 GetHashCode(Int64 value);
+
+ /// <summary>
+ /// Hashes consistent with java.lang.Float.hashCode().
+ /// </summary>
+ /// <param name="value">
+ /// FLoat to hash.
+ /// </param>
+ static Int32 GetHashCode(Single value);
+
+ /// <summary>
+ /// Hashes consistent with java.lang.Double.hashCode().
+ /// </summary>
+ /// <param name="value">
+ /// Double to hash.
+ /// </param>
+ static Int32 GetHashCode(Double value);
+
+ /// <summary>
+ /// Hashes consistent with java.util.Date.hashCode().
+ /// </summary>
+ /// <param name="value">
+ /// Date to hash.
+ /// </param>
+ static Int32 GetHashCode(DateTime^ value);
+
+ /// <summary>
+ /// Hashes consistent with java.lang.Date.hashCode().
+ /// </summary>
+ /// <param name="value">
+ /// Date to hash.
+ /// </param>
+ static Int32 GetHashCode(DateTime value);
+
+ /// <summary>
+ /// Hashes consistent with java.util.Arrays.hashCode(Object[]) or
+ /// java.util.List.hashCode().
+ /// </summary>
+ /// <param name="value">
+ /// Array or List like collection to hash.
+ /// </param>
+ static Int32 GetHashCode(System::Collections::ICollection^ collection);
+
+ /// <summary>
+ /// Hashes consistent with java.util.Map.hashCode().
+ /// </summary>
+ /// <param name="dictionary">
+ /// Map to hash.
+ /// </param>
+ static Int32 GetHashCode(System::Collections::IDictionary^ dictionary);
+};
+
+} // namespace Geode
+} // namespace Apache
diff --git a/clicache/test2/CMakeLists.txt b/clicache/test2/CMakeLists.txt
index cd022c6..5a316df 100644
--- a/clicache/test2/CMakeLists.txt
+++ b/clicache/test2/CMakeLists.txt
@@ -20,8 +20,9 @@ set(CMAKE_CSharp_FLAGS "/langversion:5")
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/packages.config ${CMAKE_CURRENT_BINARY_DIR}/packages.config COPYONLY)
-add_library( ${PROJECT_NAME} SHARED
+add_library(Apache.Geode.Tests2 SHARED
Tests2.cs
+ ObjectsTests.cs
xunit.runner.json
packages.config
)
@@ -31,12 +32,12 @@ set_source_files_properties(cache.xml xunit.runner.json geode.properties PROPERT
VS_TOOL_OVERRIDE "None"
)
-target_link_libraries(${PROJECT_NAME}
+target_link_libraries(Apache.Geode.Tests2
PUBLIC
Apache.Geode
)
-set_target_properties( ${PROJECT_NAME} PROPERTIES
+set_target_properties(Apache.Geode.Tests2 PROPERTIES
COMMON_LANGUAGE_RUNTIME ""
VS_GLOBAL_ROOTNAMESPACE ${PROJECT_NAME}
VS_GLOBAL_TreatWarningsAsErrors True
@@ -54,10 +55,10 @@ set_target_properties( ${PROJECT_NAME} PROPERTIES
)
if(NOT "${STRONG_NAME_KEY}" STREQUAL "")
- set_target_properties( ${PROJECT_NAME} PROPERTIES
+ set_target_properties(Apache.Geode.Tests2 PROPERTIES
VS_GLOBAL_SignAssembly "true"
VS_GLOBAL_AssemblyOriginatorKeyFile ${STRONG_NAME_KEY}
)
endif()
-add_dependencies(${PROJECT_NAME} nuget-restore)
+add_dependencies(Apache.Geode.Tests2 nuget-restore)
diff --git a/clicache/test2/ObjectsTests.cs b/clicache/test2/ObjectsTests.cs
new file mode 100644
index 0000000..6859491
--- /dev/null
+++ b/clicache/test2/ObjectsTests.cs
@@ -0,0 +1,316 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Collections;
+using Xunit;
+
+namespace Apache.Geode
+{
+
+
+ /// <summary>
+ /// Asserts consistent hash results with Java server.
+ ///
+ /// See Java class org.apache.geode.cache.util.ObjectsTest for test parity.
+ /// </summary>
+ public class ObjectsTests
+ {
+
+ [Fact]
+ public void GetHashCodeNullObjectIsZero()
+ {
+ Assert.Equal(0, Objects.GetHashCode((Object)null));
+ }
+
+ [Fact]
+ public void GetHashCodeOfEmptyArrayIs1()
+ {
+ Assert.Equal(1, Objects.GetHashCode(new Object[0]));
+ }
+
+ [Fact]
+ public void HashCodeEmptyArgsIs1()
+ {
+ Assert.Equal(1, Objects.Hash());
+ }
+
+ [Fact]
+ public void HashOfString()
+ {
+ Assert.Equal(0, Objects.GetHashCode(""));
+ Assert.Equal(48, Objects.GetHashCode("0"));
+ Assert.Equal(57, Objects.GetHashCode("9"));
+ Assert.Equal(97, Objects.GetHashCode("a"));
+ Assert.Equal(122, Objects.GetHashCode("z"));
+ Assert.Equal(65, Objects.GetHashCode("A"));
+ Assert.Equal(90, Objects.GetHashCode("Z"));
+
+ Assert.Equal(1077910243, Objects.GetHashCode("supercalifragilisticexpialidocious"));
+
+ Assert.Equal(1544552287, Objects.GetHashCode("You had me at meat tornad\u00F6!\U000F0000"));
+
+ Assert.Equal(701776767, Objects.GetHashCode("You had me at\0meat tornad\u00F6!\U000F0000"));
+
+ Assert.Equal(
+ 512895612,
+ Objects.GetHashCode("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do "
+ + "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut "
+ + "enim ad minim veniam, quis nostrud exercitation ullamco laboris "
+ + "nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in "
+ + "reprehenderit in voluptate velit esse cillum dolore eu fugiat "
+ + "nulla pariatur. Excepteur sint occaecat cupidatat non proident, "
+ + "sunt in culpa qui officia deserunt mollit anim id est laborum."));
+
+ Assert.Equal(
+ -1425027716,
+ Objects.GetHashCode("\u16bb\u16d6\u0020\u16b3\u16b9\u16ab\u16a6\u0020\u16a6\u16ab"
+ + "\u16cf\u0020\u16bb\u16d6\u0020\u16d2\u16a2\u16de\u16d6\u0020"
+ + "\u16a9\u16be\u0020\u16a6\u16ab\u16d7\u0020\u16da\u16aa\u16be"
+ + "\u16de\u16d6\u0020\u16be\u16a9\u16b1\u16a6\u16b9\u16d6\u16aa"
+ + "\u16b1\u16de\u16a2\u16d7\u0020\u16b9\u16c1\u16a6\u0020\u16a6"
+ + "\u16aa\u0020\u16b9\u16d6\u16e5\u16ab"));
+ }
+
+ [Fact]
+ public void HashOf1String()
+ {
+ Assert.Equal(121, Objects.Hash("Z"));
+ }
+
+ [Fact]
+ public void GetHashCodeOfChar()
+ {
+ Assert.Equal(48, Objects.GetHashCode('0'));
+ Assert.Equal(57, Objects.GetHashCode('9'));
+ Assert.Equal(97, Objects.GetHashCode('a'));
+ Assert.Equal(122, Objects.GetHashCode('z'));
+ Assert.Equal(65, Objects.GetHashCode('A'));
+ Assert.Equal(90, Objects.GetHashCode('Z'));
+ }
+
+ [Fact]
+ public void HashOf1Char()
+ {
+ Assert.Equal(121, Objects.Hash('Z'));
+ }
+
+ [Fact]
+ public void GetHashCodeOfBoolean()
+ {
+ Assert.Equal(1237, Objects.GetHashCode(false));
+ Assert.Equal(1231, Objects.GetHashCode(true));
+ }
+
+ [Fact]
+ public void HashOf1Boolean()
+ {
+ Assert.Equal(1262, Objects.Hash(true));
+ }
+
+ [Fact]
+ public void GetHashCodeOfByte()
+ {
+ Assert.Equal(0, Objects.GetHashCode((SByte)0));
+ Assert.Equal(1, Objects.GetHashCode((SByte)1));
+ Assert.Equal(-1, Objects.GetHashCode((SByte)(-1)));
+ Assert.Equal(SByte.MaxValue, Objects.GetHashCode(SByte.MaxValue));
+ Assert.Equal(SByte.MinValue, Objects.GetHashCode(SByte.MinValue));
+ }
+
+ [Fact]
+ public void HashOf1Byte()
+ {
+ Assert.Equal(158, Objects.Hash(SByte.MaxValue));
+ }
+
+ [Fact]
+ public void GetHashCodeOfInt16()
+ {
+ Assert.Equal(0, Objects.GetHashCode((Int16)0));
+ Assert.Equal(1, Objects.GetHashCode((Int16)1));
+ Assert.Equal(-1, Objects.GetHashCode((Int16)(-1)));
+ Assert.Equal(Int16.MaxValue, Objects.GetHashCode(Int16.MaxValue));
+ Assert.Equal(Int16.MinValue, Objects.GetHashCode(Int16.MinValue));
+ }
+
+ [Fact]
+ public void HashOf1Int16()
+ {
+ Assert.Equal(32798, Objects.Hash(Int16.MaxValue));
+ }
+
+ [Fact]
+ public void GetHashCodeOfInt32()
+ {
+ Assert.Equal(0, Objects.GetHashCode(0));
+ Assert.Equal(1, Objects.GetHashCode(1));
+ Assert.Equal(-1, Objects.GetHashCode(-1));
+ Assert.Equal(Int32.MaxValue, Objects.GetHashCode(Int32.MaxValue));
+ Assert.Equal(Int32.MinValue, Objects.GetHashCode(Int32.MinValue));
+ }
+
+ [Fact]
+ public void HashOf1Int32()
+ {
+ Assert.Equal(-2147483618, Objects.Hash(Int32.MaxValue));
+ }
+
+ [Fact]
+ public void GetHashCodeOfInt64()
+ {
+ Assert.Equal(0, Objects.GetHashCode(0L));
+ Assert.Equal(1, Objects.GetHashCode(1L));
+ Assert.Equal(0, Objects.GetHashCode(-1L));
+ Assert.Equal(-2147483648, Objects.GetHashCode(((Int64)Int32.MaxValue) + 1));
+ Assert.Equal(-2147483648, Objects.GetHashCode(((Int64)Int32.MinValue) - 1));
+ Assert.Equal(-2147483648, Objects.GetHashCode(Int64.MaxValue));
+ Assert.Equal(-2147483648, Objects.GetHashCode(Int64.MinValue));
+ Assert.Equal(-1073741824, Objects.GetHashCode(Int64.MaxValue >> 1));
+ Assert.Equal(-1073741824, Objects.GetHashCode(Int64.MinValue >> 1));
+ Assert.Equal(-536870912, Objects.GetHashCode(Int64.MaxValue >> 2));
+ Assert.Equal(-536870912, Objects.GetHashCode(Int64.MinValue >> 2));
+ Assert.Equal(0, Objects.GetHashCode(-9223372034707292160L));
+ }
+
+ [Fact]
+ public void HashOf1Int64()
+ {
+ Assert.Equal(-2147483617, Objects.Hash(Int64.MaxValue));
+ }
+
+ [Fact]
+ public void GetHashCodeOfFloat()
+ {
+ Assert.Equal(0, Objects.GetHashCode(0.0f));
+ Assert.Equal(-2147483648, Objects.GetHashCode(-0.0f));
+ Assert.Equal(1065353216, Objects.GetHashCode(1.0f));
+ Assert.Equal(-1082130432, Objects.GetHashCode(-1.0f));
+ Assert.Equal(2139095039, Objects.GetHashCode(Single.MaxValue));
+ Assert.Equal(1, Objects.GetHashCode(Single.Epsilon));
+ Assert.Equal(-8388609, Objects.GetHashCode(Single.MinValue));
+ Assert.Equal(2139095040, Objects.GetHashCode(Single.PositiveInfinity));
+ Assert.Equal(-8388608, Objects.GetHashCode(Single.NegativeInfinity));
+ Assert.Equal(8388608, Objects.GetHashCode(1.17549435E-38f));
+ Assert.Equal(2143289344, Objects.GetHashCode(Single.NaN));
+ }
+
+ [Fact]
+ public void HashOf1Float()
+ {
+ Assert.Equal(2139095070, Objects.Hash(Single.MaxValue));
+ }
+
+ [Fact]
+ public void GetHashCodeOfDouble()
+ {
+ Assert.Equal(0, Objects.GetHashCode(0.0d));
+ Assert.Equal(-2147483648, Objects.GetHashCode(-0.0d));
+ Assert.Equal(1072693248, Objects.GetHashCode(1.0d));
+ Assert.Equal(-1074790400, Objects.GetHashCode(-1.0d));
+ Assert.Equal(-2146435072, Objects.GetHashCode(Double.MaxValue));
+ Assert.Equal(1, Objects.GetHashCode(Double.Epsilon));
+ Assert.Equal(1048576, Objects.GetHashCode(Double.MinValue));
+ Assert.Equal(2146435072, Objects.GetHashCode(Double.PositiveInfinity));
+ Assert.Equal(-1048576, Objects.GetHashCode(Double.NegativeInfinity));
+ Assert.Equal(1048576, Objects.GetHashCode(2.2250738585072014E-308d));
+ Assert.Equal(2146959360, Objects.GetHashCode(Double.NaN));
+ }
+
+ [Fact]
+ public void HashOf1Double()
+ {
+ Assert.Equal(-2146435041, Objects.Hash(Double.MaxValue));
+ }
+
+
+ [Fact]
+ public void GetHashCodeOfDate()
+ {
+ Assert.Equal(0, Objects.GetHashCode(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)));
+ Assert.Equal(1583802735, Objects.GetHashCode(new DateTime(2020, 1, 1, 0, 0, 0, DateTimeKind.Utc)));
+ Assert.Equal(-927080926, Objects.GetHashCode(new DateTime(3020, 1, 1, 0, 0, 0, DateTimeKind.Utc)));
+ Assert.Equal(1670202000, Objects.GetHashCode(new DateTime(1920, 1, 1, 0, 0, 0, DateTimeKind.Utc)));
+ Assert.Equal(542840753, Objects.GetHashCode(new DateTime(1820, 1, 1, 0, 0, 0, DateTimeKind.Utc)));
+ }
+
+ [Fact]
+ public void HashOf1DateTime()
+ {
+ Assert.Equal(31, Objects.Hash(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)));
+ }
+
+ [Fact]
+ public void GetHashCodeOfArrays()
+ {
+ Assert.Equal(955331, Objects.GetHashCode(new SByte[] { 1, 2, 3, 4 }));
+ Assert.Equal(955331, Objects.GetHashCode(new Int16[] { 1, 2, 3, 4 }));
+ Assert.Equal(955331, Objects.GetHashCode(new Int32[] { 1, 2, 3, 4 }));
+ Assert.Equal(955331, Objects.GetHashCode(new Int64[] { 1L, 2L, 3L, 4L }));
+ Assert.Equal(265164673, Objects.GetHashCode(new Single[] { 0.0f, 1.0f, -1.0f, Single.NaN }));
+ Assert.Equal(-1039788159, Objects.GetHashCode(new Double[] { 0.0d, 1.0d, -1.0d, Double.NaN }));
+ Assert.Equal(3910595, Objects.GetHashCode(new String[] { "a", "b", "c", "d"}));
+ Assert.Equal(3910595, Objects.GetHashCode(new Char[] { 'a', 'b', 'c', 'd' }));
+ }
+
+
+ [Fact]
+ public void GetHashCodeOfList()
+ {
+ Assert.Equal(955331, Objects.GetHashCode(new List<int> { 1, 2, 3, 4 }));
+ Assert.Equal(955331, Objects.GetHashCode(new ArrayList { 1, 2, 3, 4 }));
+ Assert.Equal(955331, Objects.GetHashCode(new LinkedList<int>(new int[] { 1, 2, 3, 4 })));
+ Assert.Equal(955331, Objects.GetHashCode(new Stack<int>(new int[] { 4, 3, 2, 1 })));
+ Assert.Equal(955331, Objects.GetHashCode(new Stack(new int[] { 4, 3, 2, 1 })));
+ }
+
+ [Fact]
+ public void GetHashCodeOfMap()
+ {
+ Assert.Equal(10, Objects.GetHashCode(new Hashtable { { 1, 2 }, { 3, 4 } }));
+ Assert.Equal(10, Objects.GetHashCode(new Dictionary<int, int> { { 1, 2 }, { 3, 4 } }));
+ }
+
+ class CustomKey
+ {
+ private int a;
+ private double b;
+ private String c;
+
+ public CustomKey(int a, double b, String c)
+ {
+ this.a = a;
+ this.b = b;
+ this.c = c;
+ }
+
+ override public int GetHashCode()
+ {
+ return Objects.Hash(a, b, c);
+ }
+ };
+
+ [Fact]
+ public void hashOfCustomKey()
+ {
+ Assert.Equal(-1073604993, Objects.GetHashCode(new CustomKey(1, 2.0, "key")));
+ }
+
+ }
+
+};
diff --git a/tests/javaobject/cli/PositionKey.java b/tests/javaobject/cli/PositionKey.java
index 2a0ce2b..9921ad0 100644
--- a/tests/javaobject/cli/PositionKey.java
+++ b/tests/javaobject/cli/PositionKey.java
@@ -52,11 +52,8 @@ public class PositionKey implements DataSerializable {
out.writeLong(this.positionId);
}
- public int hashCode()
- {
- final int prime = 31;
- int result = prime * (int)positionId;
- return result;
+ public int hashCode() {
+ return Objects.hash(positionId);
}
public boolean equals(final Object obj)