// Copyright 2011 Google Inc. All Rights Reserved.

#include "src/common_test.h"
#include "src/class_linker.h"
#include "src/dex_file.h"
#include "src/heap.h"
#include "gtest/gtest.h"

namespace art {

class ClassLinkerTest : public RuntimeTest {};

TEST_F(ClassLinkerTest, FindClassNonexistent) {
  scoped_ptr<DexFile> dex(OpenDexFileBase64(kMyClassDex));
  ASSERT_TRUE(dex != NULL);

  scoped_ptr<ClassLinker> linker(ClassLinker::Create());
  linker->AppendToClassPath(dex.get());

  Class* result1 = linker.get()->FindClass("NoSuchClass;", NULL);
  EXPECT_TRUE(result1 == NULL);
  Class* result2 = linker.get()->FindClass("LNoSuchClass;", NULL);
  EXPECT_TRUE(result2 == NULL);
}

TEST_F(ClassLinkerTest, FindClassNested) {
  scoped_ptr<DexFile> objectDex(OpenDexFileBase64(kJavaLangDex));
  ASSERT_TRUE(objectDex != NULL);
  scoped_ptr<DexFile> nestedDex(OpenDexFileBase64(kNestedDex));
  ASSERT_TRUE(nestedDex != NULL);

  scoped_ptr<ClassLinker> linker(ClassLinker::Create());
  linker->AppendToClassPath(objectDex.get());
  linker->AppendToClassPath(nestedDex.get());

  Class* outer = linker.get()->FindClass("LNested;", NULL);
  ASSERT_TRUE(outer != NULL);
  EXPECT_EQ(0U, outer->NumVirtualMethods());
  EXPECT_EQ(1U, outer->NumDirectMethods());

  Class* inner = linker.get()->FindClass("LNested$Inner;", NULL);
  ASSERT_TRUE(inner != NULL);
  EXPECT_EQ(0U, inner->NumVirtualMethods());
  EXPECT_EQ(1U, inner->NumDirectMethods());
}

static void AssertNonExistantClass(ClassLinker* linker, const StringPiece& descriptor) {
  EXPECT_TRUE(linker->FindClass(descriptor, NULL) == NULL);
}

static void AssertPrimitiveClass(ClassLinker* linker, const StringPiece& descriptor) {
  Class* primitive = linker->FindClass(descriptor, NULL);
  ASSERT_TRUE(primitive != NULL);
  ASSERT_TRUE(primitive->GetClass() != NULL);
  ASSERT_EQ(primitive->GetClass(), primitive->GetClass()->GetClass());
  EXPECT_TRUE(primitive->GetClass()->GetSuperClass() != NULL);
  ASSERT_EQ(descriptor, primitive->GetDescriptor());
  EXPECT_TRUE(primitive->GetSuperClass() == NULL);
  EXPECT_FALSE(primitive->HasSuperClass());
  EXPECT_TRUE(primitive->GetComponentType() == NULL);
  EXPECT_TRUE(primitive->GetStatus() == Class::kStatusInitialized);
  EXPECT_FALSE(primitive->IsErroneous());
  EXPECT_TRUE(primitive->IsVerified());
  EXPECT_TRUE(primitive->IsLinked());
  EXPECT_FALSE(primitive->IsArray());
  EXPECT_EQ(0, primitive->array_rank_);
  EXPECT_FALSE(primitive->IsInterface());
  EXPECT_TRUE(primitive->IsPublic());
  EXPECT_TRUE(primitive->IsFinal());
  EXPECT_TRUE(primitive->IsPrimitive());
  EXPECT_EQ(0U, primitive->NumDirectMethods());
  EXPECT_EQ(0U, primitive->NumVirtualMethods());
  EXPECT_EQ(0U, primitive->NumInstanceFields());
  EXPECT_EQ(0U, primitive->NumStaticFields());
  EXPECT_EQ(0U, primitive->interface_count_);
}

static void AssertArrayClass(ClassLinker* linker,
                             const StringPiece& array_descriptor,
                             int32_t array_rank,
                             const StringPiece& component_type) {
  Class* array = linker->FindClass(array_descriptor, NULL);
  ASSERT_TRUE(array != NULL);
  ASSERT_TRUE(array->GetClass() != NULL);
  ASSERT_EQ(array->GetClass(), array->GetClass()->GetClass());
  EXPECT_TRUE(array->GetClass()->GetSuperClass() != NULL);
  ASSERT_EQ(array_descriptor, array->GetDescriptor());
  EXPECT_TRUE(array->GetSuperClass() != NULL);
  EXPECT_EQ(linker->FindSystemClass("Ljava/lang/Object;"), array->GetSuperClass());
  EXPECT_TRUE(array->HasSuperClass());
  ASSERT_TRUE(array->GetComponentType() != NULL);
  ASSERT_TRUE(array->GetComponentType()->GetDescriptor() != NULL);
  EXPECT_EQ(component_type, array->GetComponentType()->GetDescriptor());
  EXPECT_TRUE(array->GetStatus() == Class::kStatusInitialized);
  EXPECT_FALSE(array->IsErroneous());
  EXPECT_TRUE(array->IsVerified());
  EXPECT_TRUE(array->IsLinked());
  EXPECT_TRUE(array->IsArray());
  EXPECT_EQ(array_rank, array->array_rank_);
  EXPECT_FALSE(array->IsInterface());
  EXPECT_EQ(array->GetComponentType()->IsPublic(), array->IsPublic());
  EXPECT_TRUE(array->IsFinal());
  EXPECT_FALSE(array->IsPrimitive());
  EXPECT_EQ(0U, array->NumDirectMethods());
  EXPECT_EQ(0U, array->NumVirtualMethods());
  EXPECT_EQ(0U, array->NumInstanceFields());
  EXPECT_EQ(0U, array->NumStaticFields());
  EXPECT_EQ(2U, array->interface_count_);
}

TEST_F(ClassLinkerTest, FindClass) {
  scoped_ptr<ClassLinker> linker(ClassLinker::Create());

  StringPiece expected = "BCDFIJSZV";
  for (int ch = 0; ch < 255; ch++) {
    char* s = reinterpret_cast<char*>(&ch);
    StringPiece descriptor(s, 1);
    if (expected.find(ch) == StringPiece::npos) {
      AssertNonExistantClass(linker.get(), descriptor);
    } else {
      AssertPrimitiveClass(linker.get(), descriptor);
    }
  }

  scoped_ptr<DexFile> dex(OpenDexFileBase64(kMyClassDex));
  ASSERT_TRUE(dex != NULL);
  linker->AppendToClassPath(dex.get());

  Class* JavaLangObject = linker->FindClass("Ljava/lang/Object;", NULL);
  ASSERT_TRUE(JavaLangObject != NULL);
  ASSERT_TRUE(JavaLangObject->GetClass() != NULL);
  ASSERT_EQ(JavaLangObject->GetClass(), JavaLangObject->GetClass()->GetClass());
  EXPECT_EQ(JavaLangObject, JavaLangObject->GetClass()->GetSuperClass());
  ASSERT_TRUE(JavaLangObject->GetDescriptor() == "Ljava/lang/Object;");
  EXPECT_TRUE(JavaLangObject->GetSuperClass() == NULL);
  EXPECT_FALSE(JavaLangObject->HasSuperClass());
  EXPECT_TRUE(JavaLangObject->GetComponentType() == NULL);
  EXPECT_FALSE(JavaLangObject->IsErroneous());
  EXPECT_FALSE(JavaLangObject->IsVerified());
  EXPECT_TRUE(JavaLangObject->IsLinked());
  EXPECT_FALSE(JavaLangObject->IsArray());
  EXPECT_EQ(0, JavaLangObject->array_rank_);
  EXPECT_FALSE(JavaLangObject->IsInterface());
  EXPECT_TRUE(JavaLangObject->IsPublic());
  EXPECT_FALSE(JavaLangObject->IsFinal());
  EXPECT_FALSE(JavaLangObject->IsPrimitive());
  EXPECT_EQ(1U, JavaLangObject->NumDirectMethods());
  EXPECT_EQ(0U, JavaLangObject->NumVirtualMethods());
  EXPECT_EQ(0U, JavaLangObject->NumInstanceFields());
  EXPECT_EQ(0U, JavaLangObject->NumStaticFields());
  EXPECT_EQ(0U, JavaLangObject->interface_count_);


  Class* MyClass = linker->FindClass("LMyClass;", NULL);
  ASSERT_TRUE(MyClass != NULL);
  ASSERT_TRUE(MyClass->GetClass() != NULL);
  ASSERT_EQ(MyClass->GetClass(), MyClass->GetClass()->GetClass());
  EXPECT_EQ(JavaLangObject, MyClass->GetClass()->GetSuperClass());
  ASSERT_TRUE(MyClass->GetDescriptor() == "LMyClass;");
  EXPECT_TRUE(MyClass->GetSuperClass() == JavaLangObject);
  EXPECT_TRUE(MyClass->HasSuperClass());
  EXPECT_TRUE(MyClass->GetComponentType() == NULL);
  EXPECT_TRUE(MyClass->GetStatus() == Class::kStatusResolved);
  EXPECT_FALSE(MyClass->IsErroneous());
  EXPECT_FALSE(MyClass->IsVerified());
  EXPECT_TRUE(MyClass->IsLinked());
  EXPECT_FALSE(MyClass->IsArray());
  EXPECT_EQ(0, JavaLangObject->array_rank_);
  EXPECT_FALSE(MyClass->IsInterface());
  EXPECT_FALSE(MyClass->IsPublic());
  EXPECT_FALSE(MyClass->IsFinal());
  EXPECT_FALSE(MyClass->IsPrimitive());
  EXPECT_EQ(1U, MyClass->NumDirectMethods());
  EXPECT_EQ(0U, MyClass->NumVirtualMethods());
  EXPECT_EQ(0U, MyClass->NumInstanceFields());
  EXPECT_EQ(0U, MyClass->NumStaticFields());
  EXPECT_EQ(0U, MyClass->interface_count_);

  EXPECT_EQ(JavaLangObject->GetClass()->GetClass(), MyClass->GetClass()->GetClass());

  // created by class_linker
  AssertArrayClass(linker.get(), "[C", 1, "C");
  // synthesized on the fly
  AssertArrayClass(linker.get(), "[[C", 2, "C");
  AssertArrayClass(linker.get(), "[[[LMyClass;", 3, "LMyClass;");
  // or not available at all
  AssertNonExistantClass(linker.get(), "[[[[LNonExistantClass;");
}

}  // namespace art
