Skip to content

Commit

Permalink
[vm/test] Test CanonicalizeHash hashCode equality
Browse files Browse the repository at this point in the history
Test some of the assumptions from go/dart-vm-const-maps about
`CanonicalizeHash` in the VM being equal to Dart's `hashCode`.

In this CL this is true for integers, doubles, booleans, strings, null,
and type consts.

In this CL this is not true yet for Symbols, and user-defined const
instances.

Bug: #45908

TEST=runtime/vm/object_test.cc

Change-Id: Ic3b4495942177ad90aa4365eb7691ca731572cb5
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/206240
Commit-Queue: Daco Harkes <[email protected]>
Reviewed-by: Tess Strickland <[email protected]>
  • Loading branch information
dcharkes authored and [email protected] committed Jul 9, 2021

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
1 parent f5e59f8 commit 0f94869
Showing 1 changed file with 160 additions and 0 deletions.
160 changes: 160 additions & 0 deletions runtime/vm/object_test.cc
Original file line number Diff line number Diff line change
@@ -4766,6 +4766,166 @@ TEST_CASE(HashCode) {
EXPECT(result.IsIdenticalTo(expected));
}

const uint32_t kCalculateCanonizalizeHash = 0;

// Checks that the .hashCode equals the VM CanonicalizeHash() for keys in
// constant maps.
//
// Expects a script with a method named `value`.
//
// If `hashcode_canonicalize_vm` is non-zero, the VM CanonicalizeHash()
// is not executed but the provided value is used.
static bool HashCodeEqualsCanonicalizeHash(
const char* value_script,
uint32_t hashcode_canonicalize_vm = kCalculateCanonizalizeHash,
bool check_identity = true,
bool check_hashcode = true,
bool print_failure = true) {
auto kScriptChars = Utils::CStringUniquePtr(
OS::SCreate(nullptr,
"%s"
"\n"
"valueHashCode() {\n"
" return value().hashCode;\n"
"}\n"
"\n"
"valueIdentityHashCode() {\n"
" return identityHashCode(value());\n"
"}\n",
value_script),
std::free);

Dart_Handle lib = TestCase::LoadTestScript(kScriptChars.get(), nullptr);
EXPECT_VALID(lib);
Dart_Handle value_result = Dart_Invoke(lib, NewString("value"), 0, nullptr);
EXPECT_VALID(value_result);
Dart_Handle hashcode_result;
if (check_hashcode) {
hashcode_result = Dart_Invoke(lib, NewString("valueHashCode"), 0, nullptr);
EXPECT_VALID(hashcode_result);
}
Dart_Handle identity_hashcode_result =
Dart_Invoke(lib, NewString("valueIdentityHashCode"), 0, nullptr);
EXPECT_VALID(identity_hashcode_result);

TransitionNativeToVM transition(Thread::Current());

const auto& value_dart = Instance::CheckedHandle(
Thread::Current()->zone(), Api::UnwrapHandle(value_result));
int64_t hashcode_dart;
if (check_hashcode) {
hashcode_dart =
Integer::Cast(Object::Handle(Api::UnwrapHandle(hashcode_result)))
.AsInt64Value();
}
const int64_t identity_hashcode_dart =
Integer::Cast(Object::Handle(Api::UnwrapHandle(identity_hashcode_result)))
.AsInt64Value();
if (hashcode_canonicalize_vm == 0) {
hashcode_canonicalize_vm = Instance::Cast(value_dart).CanonicalizeHash();
}

bool success = true;

if (check_hashcode) {
success &= hashcode_dart == hashcode_canonicalize_vm;
}
if (check_identity) {
success &= identity_hashcode_dart == hashcode_canonicalize_vm;
}

if (!success && print_failure) {
LogBlock lb;
THR_Print(
"Dart hashCode or Dart identityHashCode does not equal VM "
"CanonicalizeHash for %s\n",
value_dart.ToCString());
THR_Print("Dart hashCode %" Px64 " %" Pd64 "\n", hashcode_dart,
hashcode_dart);
THR_Print("Dart identityHashCode %" Px64 " %" Pd64 "\n",
identity_hashcode_dart, identity_hashcode_dart);
THR_Print("VM CanonicalizeHash %" Px32 " %" Pd32 "\n",
hashcode_canonicalize_vm, hashcode_canonicalize_vm);
}

return success;
}

TEST_CASE(HashCode_Double) {
const char* kScript =
"value() {\n"
" return 1.0;\n"
"}\n";
// Double VM CanonicalizeHash is not equal to hashCode, because doubles
// cannot be used as keys in constant sets and maps. However, doubles
// _can_ be used for lookups in which case they are equal to their integer
// value.
const uint32_t kInt1HashCode = 1;
EXPECT(HashCodeEqualsCanonicalizeHash(kScript, kInt1HashCode));
}

TEST_CASE(HashCode_Mint) {
const char* kScript =
"value() {\n"
" return 0x8000000;\n"
"}\n";
EXPECT(HashCodeEqualsCanonicalizeHash(kScript));
}

TEST_CASE(HashCode_Null) {
const char* kScript =
"value() {\n"
" return null;\n"
"}\n";
EXPECT(HashCodeEqualsCanonicalizeHash(kScript));
}

TEST_CASE(HashCode_Smi) {
const char* kScript =
"value() {\n"
" return 123;\n"
"}\n";
EXPECT(HashCodeEqualsCanonicalizeHash(kScript));
}

TEST_CASE(HashCode_String) {
const char* kScript =
"value() {\n"
" return 'asdf';\n"
"}\n";
EXPECT(HashCodeEqualsCanonicalizeHash(kScript));
}

TEST_CASE(HashCode_True) {
const char* kScript =
"value() {\n"
" return true;\n"
"}\n";
EXPECT(HashCodeEqualsCanonicalizeHash(kScript));
}

TEST_CASE(HashCode_Type_Dynamic) {
const char* kScript =
"const type = dynamic;\n"
"\n"
"value() {\n"
" return type;\n"
"}\n";
EXPECT(HashCodeEqualsCanonicalizeHash(kScript, kCalculateCanonizalizeHash,
/*check_identity=*/false));
}

TEST_CASE(HashCode_Type_Int) {
const char* kScript =
"const type = int;\n"
"\n"
"value() {\n"
" return type;\n"
"}\n";
EXPECT(HashCodeEqualsCanonicalizeHash(kScript, kCalculateCanonizalizeHash,
/*check_identity=*/false));
}

TEST_CASE(LinkedHashMap_iteration) {
const char* kScript =
"makeMap() {\n"

0 comments on commit 0f94869

Please sign in to comment.