// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "platform/assert.h"
#include "vm/class_finalizer.h"
#include "vm/symbols.h"
#include "vm/unit_test.h"

namespace dart {


static RawClass* CreateTestClass(const char* name) {
  const String& class_name =
      String::Handle(Symbols::New(Thread::Current(), name));
  const Script& script = Script::Handle();
  const Class& cls = Class::Handle(Class::New(
      Library::Handle(), class_name, script, TokenPosition::kNoSource));
  cls.set_interfaces(Object::empty_array());
  cls.SetFunctions(Object::empty_array());
  cls.SetFields(Object::empty_array());
  return cls.raw();
}


TEST_CASE(ClassFinalizer) {
  Zone* zone = thread->zone();
  Isolate* isolate = thread->isolate();
  ObjectStore* object_store = isolate->object_store();
  const GrowableObjectArray& pending_classes =
      GrowableObjectArray::Handle(zone, object_store->pending_classes());
  GrowableArray<const Class*> classes_1;
  classes_1.Add(&Class::Handle(CreateTestClass("BMW")));
  pending_classes.Add(*classes_1[0]);
  classes_1.Add(&Class::Handle(CreateTestClass("Porsche")));
  pending_classes.Add(*classes_1[1]);

  GrowableArray<const Class*> classes_2;
  classes_2.Add(&Class::ZoneHandle(CreateTestClass("Ferrari")));
  pending_classes.Add(*classes_2[0]);
  classes_2.Add(&Class::ZoneHandle(CreateTestClass("Fiat")));
  pending_classes.Add(*classes_2[1]);
  classes_2.Add(&Class::ZoneHandle(CreateTestClass("Alfa")));
  pending_classes.Add(*classes_2[2]);
  EXPECT(ClassFinalizer::ProcessPendingClasses());
  for (int i = 0; i < classes_1.length(); i++) {
    EXPECT(classes_1[i]->is_type_finalized());
  }
  for (int i = 0; i < classes_2.length(); i++) {
    EXPECT(classes_2[i]->is_type_finalized());
  }
  EXPECT(ClassFinalizer::AllClassesFinalized());
  EXPECT(ClassFinalizer::ProcessPendingClasses());
}


TEST_CASE(ClassFinalize_Cycles) {
  Zone* zone = thread->zone();
  Isolate* isolate = thread->isolate();
  ObjectStore* object_store = isolate->object_store();
  const GrowableObjectArray& pending_classes =
      GrowableObjectArray::Handle(zone, object_store->pending_classes());
  GrowableArray<const Class*> classes;
  classes.Add(&Class::Handle(CreateTestClass("Jungfrau")));
  pending_classes.Add(*classes[0]);
  classes.Add(&Class::Handle(CreateTestClass("Eiger")));
  pending_classes.Add(*classes[1]);
  // Create a cycle.
  classes[0]->set_super_type(
      Type::Handle(Type::NewNonParameterizedType(*classes[1])));
  classes[1]->set_super_type(
      Type::Handle(Type::NewNonParameterizedType(*classes[0])));
  EXPECT(!ClassFinalizer::ProcessPendingClasses());
}


static RawLibrary* NewLib(const char* url_chars) {
  String& url = String::ZoneHandle(Symbols::New(Thread::Current(), url_chars));
  return Library::New(url);
}


TEST_CASE(ClassFinalize_Resolve) {
  Zone* zone = thread->zone();
  Isolate* isolate = thread->isolate();
  ObjectStore* object_store = isolate->object_store();
  const GrowableObjectArray& pending_classes =
      GrowableObjectArray::Handle(zone, object_store->pending_classes());
  Class& rhb = Class::Handle(CreateTestClass("RhB"));
  pending_classes.Add(rhb);
  Class& sbb = Class::Handle(CreateTestClass("SBB"));
  pending_classes.Add(sbb);
  Library& lib = Library::Handle(NewLib("TestLib"));
  lib.AddClass(rhb);
  lib.AddClass(sbb);
  const String& superclass_name = String::Handle(sbb.Name());
  const UnresolvedClass& unresolved =
      UnresolvedClass::Handle(UnresolvedClass::New(
          LibraryPrefix::Handle(), superclass_name, TokenPosition::kNoSource));
  const TypeArguments& type_arguments = TypeArguments::Handle();
  rhb.set_super_type(
      Type::Handle(Type::New(Object::Handle(unresolved.raw()), type_arguments,
                             TokenPosition::kNoSource)));
  EXPECT(ClassFinalizer::ProcessPendingClasses());
}

}  // namespace dart
