/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed 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 "intern_table.h"

#include "common_test.h"
#include "mirror/object.h"
#include "sirt_ref.h"

namespace art {

class InternTableTest : public CommonTest {};

TEST_F(InternTableTest, Intern) {
  ScopedObjectAccess soa(Thread::Current());
  InternTable intern_table;
  SirtRef<mirror::String> foo_1(soa.Self(), intern_table.InternStrong(3, "foo"));
  SirtRef<mirror::String> foo_2(soa.Self(), intern_table.InternStrong(3, "foo"));
  SirtRef<mirror::String> foo_3(soa.Self(), mirror::String::AllocFromModifiedUtf8(soa.Self(), "foo"));
  SirtRef<mirror::String> bar(soa.Self(), intern_table.InternStrong(3, "bar"));
  EXPECT_TRUE(foo_1->Equals("foo"));
  EXPECT_TRUE(foo_2->Equals("foo"));
  EXPECT_TRUE(foo_3->Equals("foo"));
  EXPECT_TRUE(foo_1.get() != NULL);
  EXPECT_TRUE(foo_2.get() != NULL);
  EXPECT_EQ(foo_1.get(), foo_2.get());
  EXPECT_NE(foo_1.get(), bar.get());
  EXPECT_NE(foo_2.get(), bar.get());
  EXPECT_NE(foo_3.get(), bar.get());
}

TEST_F(InternTableTest, Size) {
  ScopedObjectAccess soa(Thread::Current());
  InternTable t;
  EXPECT_EQ(0U, t.Size());
  t.InternStrong(3, "foo");
  SirtRef<mirror::String> foo(soa.Self(), mirror::String::AllocFromModifiedUtf8(soa.Self(), "foo"));
  t.InternWeak(foo.get());
  EXPECT_EQ(1U, t.Size());
  t.InternStrong(3, "bar");
  EXPECT_EQ(2U, t.Size());
}

class TestPredicate {
 public:
  bool IsMarked(const mirror::Object* s) const {
    bool erased = false;
    typedef std::vector<const mirror::String*>::iterator It; // TODO: C++0x auto
    for (It it = expected_.begin(), end = expected_.end(); it != end; ++it) {
      if (*it == s) {
        expected_.erase(it);
        erased = true;
        break;
      }
    }
    EXPECT_TRUE(erased);
    return false;
  }

  void Expect(const mirror::String* s) {
    expected_.push_back(s);
  }

  ~TestPredicate() {
    EXPECT_EQ(0U, expected_.size());
  }

 private:
  mutable std::vector<const mirror::String*> expected_;
};

bool IsMarked(const mirror::Object* object, void* arg) {
  return reinterpret_cast<TestPredicate*>(arg)->IsMarked(object);
}

TEST_F(InternTableTest, SweepInternTableWeaks) {
  ScopedObjectAccess soa(Thread::Current());
  InternTable t;
  t.InternStrong(3, "foo");
  t.InternStrong(3, "bar");
  SirtRef<mirror::String> hello(soa.Self(),
                                mirror::String::AllocFromModifiedUtf8(soa.Self(), "hello"));
  SirtRef<mirror::String> world(soa.Self(),
                                mirror::String::AllocFromModifiedUtf8(soa.Self(), "world"));
  SirtRef<mirror::String> s0(soa.Self(), t.InternWeak(hello.get()));
  SirtRef<mirror::String> s1(soa.Self(), t.InternWeak(world.get()));

  EXPECT_EQ(4U, t.Size());

  // We should traverse only the weaks...
  TestPredicate p;
  p.Expect(s0.get());
  p.Expect(s1.get());
  {
    ReaderMutexLock mu(soa.Self(), *Locks::heap_bitmap_lock_);
    t.SweepInternTableWeaks(IsMarked, &p);
  }

  EXPECT_EQ(2U, t.Size());

  // Just check that we didn't corrupt the map.
  SirtRef<mirror::String> still_here(soa.Self(),
                                     mirror::String::AllocFromModifiedUtf8(soa.Self(), "still here"));
  t.InternWeak(still_here.get());
  EXPECT_EQ(3U, t.Size());
}

TEST_F(InternTableTest, ContainsWeak) {
  ScopedObjectAccess soa(Thread::Current());
  {
    // Strongs are never weak.
    InternTable t;
    SirtRef<mirror::String> interned_foo_1(soa.Self(), t.InternStrong(3, "foo"));
    EXPECT_FALSE(t.ContainsWeak(interned_foo_1.get()));
    SirtRef<mirror::String> interned_foo_2(soa.Self(), t.InternStrong(3, "foo"));
    EXPECT_FALSE(t.ContainsWeak(interned_foo_2.get()));
    EXPECT_EQ(interned_foo_1.get(), interned_foo_2.get());
  }

  {
    // Weaks are always weak.
    InternTable t;
    SirtRef<mirror::String> foo_1(soa.Self(),
                                  mirror::String::AllocFromModifiedUtf8(soa.Self(), "foo"));
    SirtRef<mirror::String> foo_2(soa.Self(),
                                  mirror::String::AllocFromModifiedUtf8(soa.Self(), "foo"));
    EXPECT_NE(foo_1.get(), foo_2.get());
    SirtRef<mirror::String> interned_foo_1(soa.Self(), t.InternWeak(foo_1.get()));
    SirtRef<mirror::String> interned_foo_2(soa.Self(), t.InternWeak(foo_2.get()));
    EXPECT_TRUE(t.ContainsWeak(interned_foo_2.get()));
    EXPECT_EQ(interned_foo_1.get(), interned_foo_2.get());
  }

  {
    // A weak can be promoted to a strong.
    InternTable t;
    SirtRef<mirror::String> foo(soa.Self(), mirror::String::AllocFromModifiedUtf8(soa.Self(), "foo"));
    SirtRef<mirror::String> interned_foo_1(soa.Self(), t.InternWeak(foo.get()));
    EXPECT_TRUE(t.ContainsWeak(interned_foo_1.get()));
    SirtRef<mirror::String> interned_foo_2(soa.Self(), t.InternStrong(3, "foo"));
    EXPECT_FALSE(t.ContainsWeak(interned_foo_2.get()));
    EXPECT_EQ(interned_foo_1.get(), interned_foo_2.get());
  }

  {
    // Interning a weak after a strong gets you the strong.
    InternTable t;
    SirtRef<mirror::String> interned_foo_1(soa.Self(), t.InternStrong(3, "foo"));
    EXPECT_FALSE(t.ContainsWeak(interned_foo_1.get()));
    SirtRef<mirror::String> foo(soa.Self(),
                                mirror::String::AllocFromModifiedUtf8(soa.Self(), "foo"));
    SirtRef<mirror::String> interned_foo_2(soa.Self(), t.InternWeak(foo.get()));
    EXPECT_FALSE(t.ContainsWeak(interned_foo_2.get()));
    EXPECT_EQ(interned_foo_1.get(), interned_foo_2.get());
  }
}

}  // namespace art
