Home | History | Annotate | Download | only in runtime
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "intern_table.h"
     18 
     19 #include "common_test.h"
     20 #include "mirror/object.h"
     21 #include "sirt_ref.h"
     22 
     23 namespace art {
     24 
     25 class InternTableTest : public CommonTest {};
     26 
     27 TEST_F(InternTableTest, Intern) {
     28   ScopedObjectAccess soa(Thread::Current());
     29   InternTable intern_table;
     30   SirtRef<mirror::String> foo_1(soa.Self(), intern_table.InternStrong(3, "foo"));
     31   SirtRef<mirror::String> foo_2(soa.Self(), intern_table.InternStrong(3, "foo"));
     32   SirtRef<mirror::String> foo_3(soa.Self(), mirror::String::AllocFromModifiedUtf8(soa.Self(), "foo"));
     33   SirtRef<mirror::String> bar(soa.Self(), intern_table.InternStrong(3, "bar"));
     34   EXPECT_TRUE(foo_1->Equals("foo"));
     35   EXPECT_TRUE(foo_2->Equals("foo"));
     36   EXPECT_TRUE(foo_3->Equals("foo"));
     37   EXPECT_TRUE(foo_1.get() != NULL);
     38   EXPECT_TRUE(foo_2.get() != NULL);
     39   EXPECT_EQ(foo_1.get(), foo_2.get());
     40   EXPECT_NE(foo_1.get(), bar.get());
     41   EXPECT_NE(foo_2.get(), bar.get());
     42   EXPECT_NE(foo_3.get(), bar.get());
     43 }
     44 
     45 TEST_F(InternTableTest, Size) {
     46   ScopedObjectAccess soa(Thread::Current());
     47   InternTable t;
     48   EXPECT_EQ(0U, t.Size());
     49   t.InternStrong(3, "foo");
     50   SirtRef<mirror::String> foo(soa.Self(), mirror::String::AllocFromModifiedUtf8(soa.Self(), "foo"));
     51   t.InternWeak(foo.get());
     52   EXPECT_EQ(1U, t.Size());
     53   t.InternStrong(3, "bar");
     54   EXPECT_EQ(2U, t.Size());
     55 }
     56 
     57 class TestPredicate {
     58  public:
     59   bool IsMarked(const mirror::Object* s) const {
     60     bool erased = false;
     61     for (auto it = expected_.begin(), end = expected_.end(); it != end; ++it) {
     62       if (*it == s) {
     63         expected_.erase(it);
     64         erased = true;
     65         break;
     66       }
     67     }
     68     EXPECT_TRUE(erased);
     69     return false;
     70   }
     71 
     72   void Expect(const mirror::String* s) {
     73     expected_.push_back(s);
     74   }
     75 
     76   ~TestPredicate() {
     77     EXPECT_EQ(0U, expected_.size());
     78   }
     79 
     80  private:
     81   mutable std::vector<const mirror::String*> expected_;
     82 };
     83 
     84 bool IsMarked(const mirror::Object* object, void* arg) {
     85   return reinterpret_cast<TestPredicate*>(arg)->IsMarked(object);
     86 }
     87 
     88 TEST_F(InternTableTest, SweepInternTableWeaks) {
     89   ScopedObjectAccess soa(Thread::Current());
     90   InternTable t;
     91   t.InternStrong(3, "foo");
     92   t.InternStrong(3, "bar");
     93   SirtRef<mirror::String> hello(soa.Self(),
     94                                 mirror::String::AllocFromModifiedUtf8(soa.Self(), "hello"));
     95   SirtRef<mirror::String> world(soa.Self(),
     96                                 mirror::String::AllocFromModifiedUtf8(soa.Self(), "world"));
     97   SirtRef<mirror::String> s0(soa.Self(), t.InternWeak(hello.get()));
     98   SirtRef<mirror::String> s1(soa.Self(), t.InternWeak(world.get()));
     99 
    100   EXPECT_EQ(4U, t.Size());
    101 
    102   // We should traverse only the weaks...
    103   TestPredicate p;
    104   p.Expect(s0.get());
    105   p.Expect(s1.get());
    106   {
    107     ReaderMutexLock mu(soa.Self(), *Locks::heap_bitmap_lock_);
    108     t.SweepInternTableWeaks(IsMarked, &p);
    109   }
    110 
    111   EXPECT_EQ(2U, t.Size());
    112 
    113   // Just check that we didn't corrupt the map.
    114   SirtRef<mirror::String> still_here(soa.Self(),
    115                                      mirror::String::AllocFromModifiedUtf8(soa.Self(), "still here"));
    116   t.InternWeak(still_here.get());
    117   EXPECT_EQ(3U, t.Size());
    118 }
    119 
    120 TEST_F(InternTableTest, ContainsWeak) {
    121   ScopedObjectAccess soa(Thread::Current());
    122   {
    123     // Strongs are never weak.
    124     InternTable t;
    125     SirtRef<mirror::String> interned_foo_1(soa.Self(), t.InternStrong(3, "foo"));
    126     EXPECT_FALSE(t.ContainsWeak(interned_foo_1.get()));
    127     SirtRef<mirror::String> interned_foo_2(soa.Self(), t.InternStrong(3, "foo"));
    128     EXPECT_FALSE(t.ContainsWeak(interned_foo_2.get()));
    129     EXPECT_EQ(interned_foo_1.get(), interned_foo_2.get());
    130   }
    131 
    132   {
    133     // Weaks are always weak.
    134     InternTable t;
    135     SirtRef<mirror::String> foo_1(soa.Self(),
    136                                   mirror::String::AllocFromModifiedUtf8(soa.Self(), "foo"));
    137     SirtRef<mirror::String> foo_2(soa.Self(),
    138                                   mirror::String::AllocFromModifiedUtf8(soa.Self(), "foo"));
    139     EXPECT_NE(foo_1.get(), foo_2.get());
    140     SirtRef<mirror::String> interned_foo_1(soa.Self(), t.InternWeak(foo_1.get()));
    141     SirtRef<mirror::String> interned_foo_2(soa.Self(), t.InternWeak(foo_2.get()));
    142     EXPECT_TRUE(t.ContainsWeak(interned_foo_2.get()));
    143     EXPECT_EQ(interned_foo_1.get(), interned_foo_2.get());
    144   }
    145 
    146   {
    147     // A weak can be promoted to a strong.
    148     InternTable t;
    149     SirtRef<mirror::String> foo(soa.Self(), mirror::String::AllocFromModifiedUtf8(soa.Self(), "foo"));
    150     SirtRef<mirror::String> interned_foo_1(soa.Self(), t.InternWeak(foo.get()));
    151     EXPECT_TRUE(t.ContainsWeak(interned_foo_1.get()));
    152     SirtRef<mirror::String> interned_foo_2(soa.Self(), t.InternStrong(3, "foo"));
    153     EXPECT_FALSE(t.ContainsWeak(interned_foo_2.get()));
    154     EXPECT_EQ(interned_foo_1.get(), interned_foo_2.get());
    155   }
    156 
    157   {
    158     // Interning a weak after a strong gets you the strong.
    159     InternTable t;
    160     SirtRef<mirror::String> interned_foo_1(soa.Self(), t.InternStrong(3, "foo"));
    161     EXPECT_FALSE(t.ContainsWeak(interned_foo_1.get()));
    162     SirtRef<mirror::String> foo(soa.Self(),
    163                                 mirror::String::AllocFromModifiedUtf8(soa.Self(), "foo"));
    164     SirtRef<mirror::String> interned_foo_2(soa.Self(), t.InternWeak(foo.get()));
    165     EXPECT_FALSE(t.ContainsWeak(interned_foo_2.get()));
    166     EXPECT_EQ(interned_foo_1.get(), interned_foo_2.get());
    167   }
    168 }
    169 
    170 }  // namespace art
    171