/*
 * Copyright (C) 2016 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 "class_table-inl.h"

#include "art_field-inl.h"
#include "art_method-inl.h"
#include "class_linker-inl.h"
#include "common_runtime_test.h"
#include "dex/dex_file.h"
#include "gc/accounting/card_table-inl.h"
#include "gc/heap.h"
#include "handle_scope-inl.h"
#include "mirror/class-alloc-inl.h"
#include "obj_ptr.h"
#include "scoped_thread_state_change-inl.h"

namespace art {
namespace mirror {

class CollectRootVisitor {
 public:
  CollectRootVisitor() {}

  template <class MirrorType>
  ALWAYS_INLINE void VisitRootIfNonNull(GcRoot<MirrorType>& root) const
      REQUIRES_SHARED(Locks::mutator_lock_) {
    if (!root.IsNull()) {
      VisitRoot(root);
    }
  }

  template <class MirrorType>
  ALWAYS_INLINE void VisitRootIfNonNull(mirror::CompressedReference<MirrorType>* root) const
      REQUIRES_SHARED(Locks::mutator_lock_) {
    if (!root->IsNull()) {
      VisitRoot(root);
    }
  }

  template <class MirrorType>
  void VisitRoot(GcRoot<MirrorType>& root) const REQUIRES_SHARED(Locks::mutator_lock_) {
    VisitRoot(root.AddressWithoutBarrier());
  }

  template <class MirrorType>
  void VisitRoot(mirror::CompressedReference<MirrorType>* root) const
      REQUIRES_SHARED(Locks::mutator_lock_) {
    roots_.insert(root->AsMirrorPtr());
  }

  mutable std::set<mirror::Object*> roots_;
};


class ClassTableTest : public CommonRuntimeTest {};

TEST_F(ClassTableTest, ClassTable) {
  ScopedObjectAccess soa(Thread::Current());
  jobject jclass_loader = LoadDex("XandY");
  VariableSizedHandleScope hs(soa.Self());
  Handle<ClassLoader> class_loader(hs.NewHandle(soa.Decode<ClassLoader>(jclass_loader)));
  const char* descriptor_x = "LX;";
  const char* descriptor_y = "LY;";
  Handle<mirror::Class> h_X(
      hs.NewHandle(class_linker_->FindClass(soa.Self(), descriptor_x, class_loader)));
  Handle<mirror::Class> h_Y(
      hs.NewHandle(class_linker_->FindClass(soa.Self(), descriptor_y, class_loader)));
  Handle<mirror::Object> obj_X = hs.NewHandle(h_X->AllocObject(soa.Self()));
  ASSERT_TRUE(obj_X != nullptr);
  ClassTable table;
  EXPECT_EQ(table.NumZygoteClasses(class_loader.Get()), 0u);
  EXPECT_EQ(table.NumNonZygoteClasses(class_loader.Get()), 0u);

  // Add h_X to the class table.
  table.Insert(h_X.Get());
  EXPECT_OBJ_PTR_EQ(table.LookupByDescriptor(h_X.Get()), h_X.Get());
  EXPECT_OBJ_PTR_EQ(table.Lookup(descriptor_x, ComputeModifiedUtf8Hash(descriptor_x)), h_X.Get());
  EXPECT_TRUE(table.Lookup("NOT_THERE", ComputeModifiedUtf8Hash("NOT_THERE")) == nullptr);
  EXPECT_EQ(table.NumZygoteClasses(class_loader.Get()), 0u);
  EXPECT_EQ(table.NumNonZygoteClasses(class_loader.Get()), 1u);

  // Create the zygote snapshot and ensure the accounting is correct.
  table.FreezeSnapshot();
  EXPECT_EQ(table.NumZygoteClasses(class_loader.Get()), 1u);
  EXPECT_EQ(table.NumNonZygoteClasses(class_loader.Get()), 0u);

  // Test inserting and related lookup functions.
  EXPECT_TRUE(table.LookupByDescriptor(h_Y.Get()) == nullptr);
  table.Insert(h_Y.Get());
  EXPECT_OBJ_PTR_EQ(table.LookupByDescriptor(h_X.Get()), h_X.Get());
  EXPECT_OBJ_PTR_EQ(table.LookupByDescriptor(h_Y.Get()), h_Y.Get());

  EXPECT_EQ(table.NumZygoteClasses(class_loader.Get()), 1u);
  EXPECT_EQ(table.NumNonZygoteClasses(class_loader.Get()), 1u);

  // Test adding / clearing strong roots.
  EXPECT_TRUE(table.InsertStrongRoot(obj_X.Get()));
  EXPECT_FALSE(table.InsertStrongRoot(obj_X.Get()));
  table.ClearStrongRoots();
  EXPECT_TRUE(table.InsertStrongRoot(obj_X.Get()));

  // Collect all the roots and make sure there is nothing missing.
  CollectRootVisitor roots;
  table.VisitRoots(roots);
  EXPECT_TRUE(roots.roots_.find(h_X.Get()) != roots.roots_.end());
  EXPECT_TRUE(roots.roots_.find(h_Y.Get()) != roots.roots_.end());
  EXPECT_TRUE(roots.roots_.find(obj_X.Get()) != roots.roots_.end());

  // Checks that vising only classes works.
  std::set<mirror::Class*> classes;
  table.Visit([&classes](ObjPtr<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_) {
    classes.insert(klass.Ptr());
    return true;
  });
  EXPECT_TRUE(classes.find(h_X.Get()) != classes.end());
  EXPECT_TRUE(classes.find(h_Y.Get()) != classes.end());
  EXPECT_EQ(classes.size(), 2u);
  classes.clear();
  table.Visit([&classes](ObjPtr<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_) {
    classes.insert(klass.Ptr());
    // Return false to exit the Visit early.
    return false;
  });
  EXPECT_EQ(classes.size(), 1u);

  // Test that reading a class set from memory works.
  ClassTable::ClassSet temp_set;
  table.Visit([&temp_set](ObjPtr<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_) {
    temp_set.insert(ClassTable::TableSlot(klass));
    return true;
  });
  const size_t count = temp_set.WriteToMemory(nullptr);
  std::unique_ptr<uint8_t[]> buffer(new uint8_t[count]());
  ASSERT_EQ(temp_set.WriteToMemory(&buffer[0]), count);
  ClassTable table2;
  size_t count2 = table2.ReadFromMemory(&buffer[0]);
  EXPECT_EQ(count, count2);
  // Strong roots are not serialized, only classes.
  EXPECT_OBJ_PTR_EQ(table2.LookupByDescriptor(h_X.Get()), h_X.Get());
  EXPECT_OBJ_PTR_EQ(table2.LookupByDescriptor(h_Y.Get()), h_Y.Get());

  // TODO: Add tests for UpdateClass, InsertOatFile.
}

}  // namespace mirror
}  // namespace art
