12faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes/*
22faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Copyright (C) 2011 The Android Open Source Project
32faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
42faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
52faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * you may not use this file except in compliance with the License.
62faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * You may obtain a copy of the License at
72faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
82faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
92faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
102faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Unless required by applicable law or agreed to in writing, software
112faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
122faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * See the License for the specific language governing permissions and
142faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * limitations under the License.
152faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes */
167e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom
177e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom#include "intern_table.h"
187e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom
1921f2364f11a709c7c22320588abe2adc91c69b6aAlexey Grebenkin#include "base/hash_set.h"
20a1ce1fef2d49d1d537776a5308ace7102a815fe5Brian Carlstrom#include "common_runtime_test.h"
210225f8e2939a9340cb7dcebfcfe7996a2bd9bce9David Sehr#include "dex/utf.h"
22c15a2f4f45661a7f5f542e406282c146ea1a968dAndreas Gampe#include "gc_root-inl.h"
23eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier#include "handle_scope-inl.h"
248cf9cb386cd9286d67e879f1ee501ec00d72a4e1Andreas Gampe#include "mirror/object.h"
25e63db27db913f1a88e2095a1ee8239b2bb9124e8Ian Rogers#include "mirror/string.h"
260795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier#include "scoped_thread_state_change-inl.h"
277e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom
287e93b50433cde2a44d99212e8040299bde498546Brian Carlstromnamespace art {
297e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom
30a1ce1fef2d49d1d537776a5308ace7102a815fe5Brian Carlstromclass InternTableTest : public CommonRuntimeTest {};
317e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom
327e93b50433cde2a44d99212e8040299bde498546Brian CarlstromTEST_F(InternTableTest, Intern) {
3300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ScopedObjectAccess soa(Thread::Current());
347e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom  InternTable intern_table;
35eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier  StackHandleScope<4> hs(soa.Self());
36eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier  Handle<mirror::String> foo_1(hs.NewHandle(intern_table.InternStrong(3, "foo")));
37eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier  Handle<mirror::String> foo_2(hs.NewHandle(intern_table.InternStrong(3, "foo")));
38eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier  Handle<mirror::String> foo_3(
39eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier      hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "foo")));
40eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier  Handle<mirror::String> bar(hs.NewHandle(intern_table.InternStrong(3, "bar")));
41fa4333dcb481e564f54726b4e6f8153612df835eAndreas Gampe  ASSERT_TRUE(foo_1 != nullptr);
42fa4333dcb481e564f54726b4e6f8153612df835eAndreas Gampe  ASSERT_TRUE(foo_2 != nullptr);
43fa4333dcb481e564f54726b4e6f8153612df835eAndreas Gampe  ASSERT_TRUE(foo_3 != nullptr);
44fa4333dcb481e564f54726b4e6f8153612df835eAndreas Gampe  ASSERT_TRUE(bar != nullptr);
45cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  EXPECT_EQ(foo_1.Get(), foo_2.Get());
467e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom  EXPECT_TRUE(foo_1->Equals("foo"));
477e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom  EXPECT_TRUE(foo_2->Equals("foo"));
487e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom  EXPECT_TRUE(foo_3->Equals("foo"));
49eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier  EXPECT_NE(foo_1.Get(), bar.Get());
50eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier  EXPECT_NE(foo_2.Get(), bar.Get());
51eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier  EXPECT_NE(foo_3.Get(), bar.Get());
527e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom}
537e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom
54cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott HughesTEST_F(InternTableTest, Size) {
5500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ScopedObjectAccess soa(Thread::Current());
56cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes  InternTable t;
57cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes  EXPECT_EQ(0U, t.Size());
58cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes  t.InternStrong(3, "foo");
59eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier  StackHandleScope<1> hs(soa.Self());
60eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier  Handle<mirror::String> foo(
61eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier      hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "foo")));
62eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier  t.InternWeak(foo.Get());
63cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes  EXPECT_EQ(1U, t.Size());
64cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes  t.InternStrong(3, "bar");
65cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes  EXPECT_EQ(2U, t.Size());
66cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes}
67cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes
6821f2364f11a709c7c22320588abe2adc91c69b6aAlexey Grebenkin// Check if table indexes match on 64 and 32 bit machines.
6921f2364f11a709c7c22320588abe2adc91c69b6aAlexey Grebenkin// This is done by ensuring hash values are the same on every machine and limited to 32-bit wide.
7021f2364f11a709c7c22320588abe2adc91c69b6aAlexey Grebenkin// Otherwise cross compilation can cause a table to be filled on host using one indexing algorithm
7121f2364f11a709c7c22320588abe2adc91c69b6aAlexey Grebenkin// and later on a device with different sizeof(size_t) can use another indexing algorithm.
7221f2364f11a709c7c22320588abe2adc91c69b6aAlexey Grebenkin// Thus the table may provide wrong data.
7321f2364f11a709c7c22320588abe2adc91c69b6aAlexey GrebenkinTEST_F(InternTableTest, CrossHash) {
7421f2364f11a709c7c22320588abe2adc91c69b6aAlexey Grebenkin  ScopedObjectAccess soa(Thread::Current());
7521f2364f11a709c7c22320588abe2adc91c69b6aAlexey Grebenkin  InternTable t;
7621f2364f11a709c7c22320588abe2adc91c69b6aAlexey Grebenkin
7721f2364f11a709c7c22320588abe2adc91c69b6aAlexey Grebenkin  // A string that has a negative hash value.
7821f2364f11a709c7c22320588abe2adc91c69b6aAlexey Grebenkin  GcRoot<mirror::String> str(mirror::String::AllocFromModifiedUtf8(soa.Self(), "00000000"));
7921f2364f11a709c7c22320588abe2adc91c69b6aAlexey Grebenkin
8021f2364f11a709c7c22320588abe2adc91c69b6aAlexey Grebenkin  MutexLock mu(Thread::Current(), *Locks::intern_table_lock_);
8121f2364f11a709c7c22320588abe2adc91c69b6aAlexey Grebenkin  for (InternTable::Table::UnorderedSet& table : t.strong_interns_.tables_) {
8221f2364f11a709c7c22320588abe2adc91c69b6aAlexey Grebenkin    // The negative hash value shall be 32-bit wide on every host.
8321f2364f11a709c7c22320588abe2adc91c69b6aAlexey Grebenkin    ASSERT_TRUE(IsUint<32>(table.hashfn_(str)));
8421f2364f11a709c7c22320588abe2adc91c69b6aAlexey Grebenkin  }
8521f2364f11a709c7c22320588abe2adc91c69b6aAlexey Grebenkin}
8621f2364f11a709c7c22320588abe2adc91c69b6aAlexey Grebenkin
8797509954404d031594b2ecbda607314d169d512eMathieu Chartierclass TestPredicate : public IsMarkedVisitor {
88410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes public:
89bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe  mirror::Object* IsMarked(mirror::Object* s) OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
90410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes    bool erased = false;
9102e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier    for (auto it = expected_.begin(), end = expected_.end(); it != end; ++it) {
92410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes      if (*it == s) {
93410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes        expected_.erase(it);
94410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes        erased = true;
95410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes        break;
96410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes      }
97cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes    }
98410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes    EXPECT_TRUE(erased);
9997509954404d031594b2ecbda607314d169d512eMathieu Chartier    return nullptr;
100cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes  }
101410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes
1022dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  void Expect(const mirror::String* s) {
103410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes    expected_.push_back(s);
104410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes  }
105410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes
106410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes  ~TestPredicate() {
107410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes    EXPECT_EQ(0U, expected_.size());
108410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes  }
109410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes
110410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes private:
1112dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  mutable std::vector<const mirror::String*> expected_;
112410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes};
113cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes
114c33a32bccc4c66ed82ce3a580b16636399385cb4Elliott HughesTEST_F(InternTableTest, SweepInternTableWeaks) {
11500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ScopedObjectAccess soa(Thread::Current());
116cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes  InternTable t;
117cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes  t.InternStrong(3, "foo");
118cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes  t.InternStrong(3, "bar");
119eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier  StackHandleScope<5> hs(soa.Self());
120eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier  Handle<mirror::String> hello(
121eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier      hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "hello")));
122eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier  Handle<mirror::String> world(
123eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier      hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "world")));
124eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier  Handle<mirror::String> s0(hs.NewHandle(t.InternWeak(hello.Get())));
125eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier  Handle<mirror::String> s1(hs.NewHandle(t.InternWeak(world.Get())));
126cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes
127cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes  EXPECT_EQ(4U, t.Size());
128cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes
129cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes  // We should traverse only the weaks...
130410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes  TestPredicate p;
131eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier  p.Expect(s0.Get());
132eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier  p.Expect(s1.Get());
13300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  {
1341f5393447b9f45be7918042d9ee7b521376de866Ian Rogers    ReaderMutexLock mu(soa.Self(), *Locks::heap_bitmap_lock_);
13597509954404d031594b2ecbda607314d169d512eMathieu Chartier    t.SweepInternTableWeaks(&p);
13600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
137cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes
138cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes  EXPECT_EQ(2U, t.Size());
139cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes
140e5448b5a12003b405b22cde3b94f962ab4888a87Elliott Hughes  // Just check that we didn't corrupt the map.
141eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier  Handle<mirror::String> still_here(
142eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier      hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "still here")));
143eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier  t.InternWeak(still_here.Get());
144cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes  EXPECT_EQ(3U, t.Size());
145cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes}
146cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes
147cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott HughesTEST_F(InternTableTest, ContainsWeak) {
14800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ScopedObjectAccess soa(Thread::Current());
149cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes  {
150cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes    // Strongs are never weak.
151cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes    InternTable t;
152eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier    StackHandleScope<2> hs(soa.Self());
153eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier    Handle<mirror::String> interned_foo_1(hs.NewHandle(t.InternStrong(3, "foo")));
154eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier    EXPECT_FALSE(t.ContainsWeak(interned_foo_1.Get()));
155eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier    Handle<mirror::String> interned_foo_2(hs.NewHandle(t.InternStrong(3, "foo")));
156eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier    EXPECT_FALSE(t.ContainsWeak(interned_foo_2.Get()));
157eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier    EXPECT_EQ(interned_foo_1.Get(), interned_foo_2.Get());
158cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes  }
159cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes
160cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes  {
161cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes    // Weaks are always weak.
162cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes    InternTable t;
163eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier    StackHandleScope<4> hs(soa.Self());
164eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier    Handle<mirror::String> foo_1(
165eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier        hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "foo")));
166eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier    Handle<mirror::String> foo_2(
167eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier        hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "foo")));
168eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier    EXPECT_NE(foo_1.Get(), foo_2.Get());
169eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier    Handle<mirror::String> interned_foo_1(hs.NewHandle(t.InternWeak(foo_1.Get())));
170eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier    Handle<mirror::String> interned_foo_2(hs.NewHandle(t.InternWeak(foo_2.Get())));
171eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier    EXPECT_TRUE(t.ContainsWeak(interned_foo_2.Get()));
172eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier    EXPECT_EQ(interned_foo_1.Get(), interned_foo_2.Get());
173cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes  }
174cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes
175cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes  {
176cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes    // A weak can be promoted to a strong.
177cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes    InternTable t;
178eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier    StackHandleScope<3> hs(soa.Self());
179eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier    Handle<mirror::String> foo(
180eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier        hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "foo")));
181eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier    Handle<mirror::String> interned_foo_1(hs.NewHandle(t.InternWeak(foo.Get())));
182eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier    EXPECT_TRUE(t.ContainsWeak(interned_foo_1.Get()));
183eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier    Handle<mirror::String> interned_foo_2(hs.NewHandle(t.InternStrong(3, "foo")));
184eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier    EXPECT_FALSE(t.ContainsWeak(interned_foo_2.Get()));
185eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier    EXPECT_EQ(interned_foo_1.Get(), interned_foo_2.Get());
186cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes  }
187cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes
188cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes  {
189cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes    // Interning a weak after a strong gets you the strong.
190cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes    InternTable t;
191eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier    StackHandleScope<3> hs(soa.Self());
192eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier    Handle<mirror::String> interned_foo_1(hs.NewHandle(t.InternStrong(3, "foo")));
193eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier    EXPECT_FALSE(t.ContainsWeak(interned_foo_1.Get()));
194eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier    Handle<mirror::String> foo(
195eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier        hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "foo")));
196eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier    Handle<mirror::String> interned_foo_2(hs.NewHandle(t.InternWeak(foo.Get())));
197eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier    EXPECT_FALSE(t.ContainsWeak(interned_foo_2.Get()));
198eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier    EXPECT_EQ(interned_foo_1.Get(), interned_foo_2.Get());
199cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes  }
200cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes}
201cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes
202cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir MarkoTEST_F(InternTableTest, LookupStrong) {
203cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  ScopedObjectAccess soa(Thread::Current());
204cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  InternTable intern_table;
205cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  StackHandleScope<3> hs(soa.Self());
206cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  Handle<mirror::String> foo(hs.NewHandle(intern_table.InternStrong(3, "foo")));
207cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  Handle<mirror::String> bar(hs.NewHandle(intern_table.InternStrong(3, "bar")));
208cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  Handle<mirror::String> foobar(hs.NewHandle(intern_table.InternStrong(6, "foobar")));
209fa4333dcb481e564f54726b4e6f8153612df835eAndreas Gampe  ASSERT_TRUE(foo != nullptr);
210fa4333dcb481e564f54726b4e6f8153612df835eAndreas Gampe  ASSERT_TRUE(bar != nullptr);
211fa4333dcb481e564f54726b4e6f8153612df835eAndreas Gampe  ASSERT_TRUE(foobar != nullptr);
212cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  ASSERT_TRUE(foo->Equals("foo"));
213cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  ASSERT_TRUE(bar->Equals("bar"));
214cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  ASSERT_TRUE(foobar->Equals("foobar"));
215cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  ASSERT_NE(foo.Get(), bar.Get());
216cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  ASSERT_NE(foo.Get(), foobar.Get());
217cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  ASSERT_NE(bar.Get(), foobar.Get());
2189e868098b4a5d666570e3924518978d7abd3542eMathieu Chartier  ObjPtr<mirror::String> lookup_foo = intern_table.LookupStrong(soa.Self(), 3, "foo");
2199e868098b4a5d666570e3924518978d7abd3542eMathieu Chartier  EXPECT_OBJ_PTR_EQ(lookup_foo, foo.Get());
2209e868098b4a5d666570e3924518978d7abd3542eMathieu Chartier  ObjPtr<mirror::String> lookup_bar = intern_table.LookupStrong(soa.Self(), 3, "bar");
2219e868098b4a5d666570e3924518978d7abd3542eMathieu Chartier  EXPECT_OBJ_PTR_EQ(lookup_bar, bar.Get());
2229e868098b4a5d666570e3924518978d7abd3542eMathieu Chartier  ObjPtr<mirror::String> lookup_foobar = intern_table.LookupStrong(soa.Self(), 6, "foobar");
2239e868098b4a5d666570e3924518978d7abd3542eMathieu Chartier  EXPECT_OBJ_PTR_EQ(lookup_foobar, foobar.Get());
2249e868098b4a5d666570e3924518978d7abd3542eMathieu Chartier  ObjPtr<mirror::String> lookup_foox = intern_table.LookupStrong(soa.Self(), 4, "foox");
225cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  EXPECT_TRUE(lookup_foox == nullptr);
2269e868098b4a5d666570e3924518978d7abd3542eMathieu Chartier  ObjPtr<mirror::String> lookup_fooba = intern_table.LookupStrong(soa.Self(), 5, "fooba");
227cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  EXPECT_TRUE(lookup_fooba == nullptr);
2289e868098b4a5d666570e3924518978d7abd3542eMathieu Chartier  ObjPtr<mirror::String> lookup_foobaR = intern_table.LookupStrong(soa.Self(), 6, "foobaR");
229cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  EXPECT_TRUE(lookup_foobaR == nullptr);
230cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  // Try a hash conflict.
231cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  ASSERT_EQ(ComputeUtf16HashFromModifiedUtf8("foobar", 6),
232cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko            ComputeUtf16HashFromModifiedUtf8("foobbS", 6));
2339e868098b4a5d666570e3924518978d7abd3542eMathieu Chartier  ObjPtr<mirror::String> lookup_foobbS = intern_table.LookupStrong(soa.Self(), 6, "foobbS");
234cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  EXPECT_TRUE(lookup_foobbS == nullptr);
235cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko}
236cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko
2377e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom}  // namespace art
238