// 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/assembler.h"
#include "vm/class_finalizer.h"
#include "vm/compiler.h"
#include "vm/dart_entry.h"
#include "vm/object.h"
#include "vm/resolver.h"
#include "vm/symbols.h"
#include "vm/unit_test.h"

namespace dart {

// Only ia32 and x64 can run execution tests.
#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64)

TEST_CASE(DartEntry) {
  const char* kScriptChars =
      "class A {\n"
      "  static foo() { return 42; }\n"
      "}\n";
  String& url = String::Handle(String::New("dart-test:DartEntry"));
  String& source = String::Handle(String::New(kScriptChars));
  Script& script = Script::Handle(Script::New(url,
                                              source,
                                              RawScript::kScriptTag));
  Library& lib = Library::Handle(Library::CoreLibrary());
  EXPECT_EQ(true, CompilerTest::TestCompileScript(lib, script));
  EXPECT(ClassFinalizer::FinalizePendingClasses());
  Class& cls = Class::Handle(
      lib.LookupClass(String::Handle(Symbols::New("A"))));
  EXPECT(!cls.IsNull());
  String& name = String::Handle(String::New("foo"));
  Function& function = Function::Handle(cls.LookupStaticFunction(name));
  EXPECT(!function.IsNull());

  EXPECT(CompilerTest::TestCompileFunction(function));
  EXPECT(function.HasCode());
  const Smi& retval = Smi::Handle(reinterpret_cast<RawSmi*>(
      DartEntry::InvokeStatic(function, Object::empty_array())));
  EXPECT_EQ(Smi::New(42), retval.raw());
}


TEST_CASE(InvokeStatic_CompileError) {
  const char* kScriptChars =
      "class A {\n"
      "  static foo() { return ++++; }\n"
      "}\n";
  String& url = String::Handle(String::New("dart-test:DartEntry"));
  String& source = String::Handle(String::New(kScriptChars));
  Script& script = Script::Handle(Script::New(url,
                                              source,
                                              RawScript::kScriptTag));
  Library& lib = Library::Handle(Library::CoreLibrary());
  EXPECT_EQ(true, CompilerTest::TestCompileScript(lib, script));
  EXPECT(ClassFinalizer::FinalizePendingClasses());
  Class& cls = Class::Handle(
      lib.LookupClass(String::Handle(Symbols::New("A"))));
  EXPECT(!cls.IsNull());
  String& name = String::Handle(String::New("foo"));
  Function& function = Function::Handle(cls.LookupStaticFunction(name));
  EXPECT(!function.IsNull());
  GrowableArray<const Object*> arguments;
  const Object& retval = Object::Handle(
      DartEntry::InvokeStatic(function, Object::empty_array()));
  EXPECT(retval.IsError());
  EXPECT_SUBSTRING("++++", Error::Cast(retval).ToErrorCString());
}


TEST_CASE(InvokeDynamic_CompileError) {
  const char* kScriptChars =
      "class A {\n"
      "  foo() { return ++++; }\n"
      "}\n";
  String& url = String::Handle(String::New("dart-test:DartEntry"));
  String& source = String::Handle(String::New(kScriptChars));
  Script& script = Script::Handle(Script::New(url,
                                              source,
                                              RawScript::kScriptTag));
  Library& lib = Library::Handle(Library::CoreLibrary());
  EXPECT_EQ(true, CompilerTest::TestCompileScript(lib, script));
  EXPECT(ClassFinalizer::FinalizePendingClasses());
  Class& cls = Class::Handle(
      lib.LookupClass(String::Handle(Symbols::New("A"))));
  EXPECT(!cls.IsNull());

  // Invoke the constructor.
  const Instance& instance = Instance::Handle(Instance::New(cls));
  const Array& constructor_arguments = Array::Handle(Array::New(2));
  constructor_arguments.SetAt(0, instance);
  constructor_arguments.SetAt(
      1, Smi::Handle(Smi::New(Function::kCtorPhaseAll)));
  String& constructor_name = String::Handle(Symbols::New("A."));
  Function& constructor =
    Function::Handle(cls.LookupConstructor(constructor_name));
  ASSERT(!constructor.IsNull());
  DartEntry::InvokeStatic(constructor, constructor_arguments);

  // Call foo.
  String& name = String::Handle(String::New("foo"));
  Function& function = Function::Handle(cls.LookupDynamicFunction(name));
  EXPECT(!function.IsNull());
  const Array& args = Array::Handle(Array::New(1));
  args.SetAt(0, instance);
  const Object& retval = Object::Handle(DartEntry::InvokeDynamic(function,
                                                                 args));
  EXPECT(retval.IsError());
  EXPECT_SUBSTRING("++++", Error::Cast(retval).ToErrorCString());
}

#endif  // TARGET_ARCH_IA32 || TARGET_ARCH_X64.

}  // namespace dart
