/* 
 * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; version 2 of the
 * License.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301  USA
 */

#include "tut_stdafx.h"

#include "testgrt.h"
#include "structs.test.h"

#include "grtpp_module_cpp.h"
#include "grtpp_module_lua.h"

BEGIN_TEST_DATA_CLASS(grt_module)
public:
  GRT grt;
END_TEST_DATA_CLASS

TEST_MODULE(grt_module, "GRT: module functionality");

TEST_FUNCTION(1)
{
  grt.load_metaclasses("data/structs.test.xml");
  grt.end_loading_metaclasses();
}

TEST_FUNCTION(2)
{
  ensure("Make it compile", false);
/*
    // Test function spec parsing for Lua.
    LuaModuleLoader loader(&grt);
    LuaModule module(&loader);
  
    ensure("Parse lua function", module.add_parse_function_spec("func1:i:l<i>,r,s"));
    
    const std::vector<Module::Function> &functions= module.get_functions();
    ensure_equals("Function count", functions.size(), 1);
  
    Module::Function function= functions[0];
    ensure_equals("func1 name", function.name, "func1");
  
    TypeSpec type= function.ret_type;
    ensure_equals("func1 return value", type.base.type, IntegerType);
    ensure_equals("func1 param count", function.arg_types.size(), 3);
  
    ArgSpec argument= function.arg_types[0];
    ensure_equals("func1 param 1", argument.type.base.type, ListType);
    ensure_equals("func1 param 1 l", argument.type.content.type, IntegerType);
  
    argument= function.arg_types[1];
    ensure_equals("func1 param 2", argument.type.base.type, DoubleType);
  
    argument= function.arg_types[2];
    ensure_equals("func1 param 3", argument.type.base.type, StringType);
  
    // And another function.
    ensure("Parse lua function", module.add_parse_function_spec("func2:d:d,d<i>"));
    ensure_equals("Function count", functions.size(), 2);
  
    function= functions[1];
    ensure_equals("func2 name", function.name, "func2");
  
    type= function.ret_type;
    ensure_equals("func2 return value", type.base.type, DictType);
    ensure_equals("func2 param count", function.arg_types.size(), 2);
  
    argument= function.arg_types[0];
    ensure_equals("func2 param 1", argument.type.base.type, DictType);
    ensure_equals("func2 param 1 d", argument.type.content.type, AnyType);
  
    argument= function.arg_types[1];
    ensure_equals("func2 param 2", argument.type.base.type, DictType);
    ensure_equals("func2 param 2 d", argument.type.content.type, IntegerType);
  
    // A third function.
    ensure("Parse lua function", module.add_parse_function_spec("func_3:a:l<o@StructName> argname"));
    ensure_equals("Function count", functions.size(), 3);
  
    function= functions[2];
    ensure_equals("func3 name", function.name, "func_3");
  
    type= function.ret_type;
    ensure_equals("func3 return value", type.base.type, AnyType);
    ensure_equals("func3 param count", function.arg_types.size(), 1);
  
    argument= function.arg_types[0];
    ensure_equals("func3 param 1", argument.type.base.type, ListType);
    ensure_equals("func3 param 1 c", argument.type.content.type, ::grt::ObjectType);
    ensure_equals("func3 param 1 cs", argument.type.content.object_class, "StructName");
    ensure_equals("func3 param 1 name", argument.name, "argname");*/
  
}

/* QQQ, Argument validation is not yet ported. Do we ever need this?
TEST_FUNCTION(3)
{
  IntegerRef ivalue(10);
  DoubleRef dvalue(11.1);
  StringRef svalue("hi");
  TypeSpec spec;
  int r;

  // Test argument validation.
  spec.base.type= IntegerType;

  r= myx_grt_validate_argument(grt.grt(), &spec, ivalue.valueptr());
  ensure("validate int", r!=0);

  r= myx_grt_validate_argument(grt.grt(), &spec, svalue.valueptr());
  ensure("validate !int", r==0);

  
  spec.type= DoubleType;

  r= myx_grt_validate_argument(grt.grt(), &spec, dvalue.valueptr());
  ensure("validate double", r!=0);

  r= myx_grt_validate_argument(grt.grt(), &spec, ivalue.valueptr());
  ensure("validate !double", r==0);

  r= myx_grt_validate_argument(grt.grt(), &spec, svalue.valueptr());
  ensure("validate !double", r==0);


  spec.type= StringType;

  r= myx_grt_validate_argument(grt.grt(), &spec, svalue.valueptr());
  ensure("validate str", r!=0);

  r= myx_grt_validate_argument(grt.grt(), &spec, ivalue.valueptr());
  ensure("validate !str", r==0);

  
  BaseListRef iblist(&grt, AnyType);
  iblist.ginsert(IntegerRef(0));
  iblist.ginsert(IntegerRef(1));

  BaseListRef siblist(&grt, AnyType);
  siblist.ginsert(IntegerRef(0));
  siblist.ginsert(StringRef("hai"));

  IntegerListRef ilist(&grt);
  ListRef<test_Book> blist(&grt);

  spec.type= ListType;
  spec.content_type= IntegerType;

  r= myx_grt_validate_argument(grt.grt(), &spec, ilist.valueptr());

  ensure("validate list<int>", r!=0);

  r= myx_grt_validate_argument(grt.grt(), &spec, ivalue.valueptr());
  ensure("validate !list<int>", r==0);

  r= myx_grt_validate_argument(grt.grt(), &spec, siblist.valueptr());
  ensure("validate !list<int>", r==0);

  r= myx_grt_validate_argument(grt.grt(), &spec, iblist.valueptr());
  ensure("validate list<int>", r!=0);

  
  
  test_Book book(&grt);
  spec.type= ObjectType;
  spec.object_struct= "test.Book";
  
  r= myx_grt_validate_argument(grt.grt(), &spec, book.valueptr());
  ensure("validate book", r!=0);

  r= myx_grt_validate_argument(grt.grt(), &spec, blist.valueptr());
  ensure("validate !book", r==0);

  r= myx_grt_validate_argument(grt.grt(), &spec, iblist.valueptr());
  ensure("validate !book", r==0);

  
  
  
  spec.type= ListType;
  spec.content_type= ObjectType;
  spec.content_object_struct= "test.Book";

  r= myx_grt_validate_argument(grt.grt(), &spec, blist.valueptr());
  ensure("validate blist", r!=0);
  
  r= myx_grt_validate_argument(grt.grt(), &spec, ilist.valueptr());
  ensure("validate !blist", r==0);


  spec.type= ListType;
  spec.content_type= ObjectType;
  spec.content_object_struct= "test_Book";

  r= myx_grt_validate_argument(grt.grt(), &spec, blist.valueptr());
  ensure("validate !blist", r==0);
  
  r= myx_grt_validate_argument(grt.grt(), &spec, ilist.valueptr());
  ensure("validate !blist", r==0);



  spec.type= AnyType;

  r= myx_grt_validate_argument(grt.grt(), &spec, svalue.valueptr());
  ensure("validate any", r!=0);

  r= myx_grt_validate_argument(grt.grt(), &spec, ivalue.valueptr());
  ensure("validate any", r!=0);

  r= myx_grt_validate_argument(grt.grt(), &spec, dvalue.valueptr());
  ensure("validate any", r!=0);

  r= myx_grt_validate_argument(grt.grt(), &spec, blist.valueptr());
  ensure("validate any", r!=0);

  r= myx_grt_validate_argument(grt.grt(), &spec, siblist.valueptr());
  ensure("validate any", r!=0);
}


TEST_FUNCTION(4)
{
  // bug: check typed object lists

  MYX_GRT_TYPE_SPEC spec;

  spec.type= ListType;
  spec.content_type= ObjectType;
  spec.content_object_struct= "test.Book";

  grt::ListRef<test_Base> objects1(&grt);

  objects1.insert(test_Book(&grt));
  ensure("object list", myx_grt_validate_argument(grt.grt(), &spec, objects1.valueptr())!=0);

  objects1.insert(test_Author(&grt));
  ensure("object list", !myx_grt_validate_argument(grt.grt(), &spec, objects1.valueptr())!=0);

  spec.content_object_struct= "test.Base";
  grt::ListRef<test_Book> objects2(&grt);

  objects2.insert(test_Book(&grt));
  ensure("object list", myx_grt_validate_argument(grt.grt(), &spec, objects2.valueptr())!=0);
}
*/

END_TESTS
