/*
 * 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_file.h"
#include "gc/accounting/card_table-inl.h"
#include "gc/heap.h"
#include "handle_scope-inl.h"
#include "mirror/class-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.Get() != 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_EQ(table.LookupByDescriptor(h_X.Get()), h_X.Get());
  EXPECT_EQ(table.Lookup(descriptor_x, ComputeModifiedUtf8Hash(descriptor_x)), h_X.Get());
  EXPECT_EQ(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_EQ(table.LookupByDescriptor(h_Y.Get()), nullptr);
  EXPECT_FALSE(table.Contains(h_Y.Get()));
  table.Insert(h_Y.Get());
  EXPECT_EQ(table.LookupByDescriptor(h_X.Get()), h_X.Get());
  EXPECT_EQ(table.LookupByDescriptor(h_Y.Get()), h_Y.Get());
  EXPECT_TRUE(table.Contains(h_X.Get()));
  EXPECT_TRUE(table.Contains(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 remove.
  table.Remove(descriptor_x);
  EXPECT_FALSE(table.Contains(h_X.Get()));

  // Test that WriteToMemory and ReadFromMemory work.
  table.Insert(h_X.Get());
  const size_t count = table.WriteToMemory(nullptr);
  std::unique_ptr<uint8_t[]> buffer(new uint8_t[count]());
  ASSERT_EQ(table.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_TRUE(table2.Contains(h_X.Get()));
  EXPECT_TRUE(table2.Contains(h_Y.Get()));

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

}  // namespace mirror
}  // namespace art
