コード例 #1
0
bool Test()
{
	bool fail = false;
	int r;
	CBufferedOutStream bout;
	COutStream out;

	float val;

	//------------
	// Test global properties
	asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);

	r = engine->BeginConfigGroup("group"); assert( r >= 0 );
	r = engine->RegisterGlobalProperty("float val", &val); assert( r >= 0 );
	r = engine->EndConfigGroup(); assert( r >= 0 );

	// Make sure the default access is granted
	r = engine->ExecuteString(0, "val = 1.3f"); 
	if( r < 0 )
		fail = true;

	// Make sure the default access can be turned off
	engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL);
	r = engine->SetConfigGroupModuleAccess("group", asALL_MODULES, false); assert( r >= 0 );

	r = engine->ExecuteString(0, "val = 1.0f");
	if( r >= 0 )
		fail = true;

	if( bout.buffer != "ExecuteString (1, 1) : Error   : 'val' is not declared\n"
/*		               "ExecuteString (1, 5) : Error   : Reference is read-only\n"
		               "ExecuteString (1, 5) : Error   : Not a valid lvalue\n"*/)
		fail = true;

	// Make sure the default access can be overridden
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
	r = engine->SetConfigGroupModuleAccess("group", 0, true); assert( r >= 0 );

	r = engine->ExecuteString(0, "val = 1.0f");
	if( r < 0 )
		fail = true;

	engine->Release();

	//----------
	// Test global functions
	engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);

	r = engine->BeginConfigGroup("group"); assert( r >= 0 );
	r = engine->RegisterGlobalFunction("void Func()", asFUNCTION(Func), asCALL_GENERIC); assert( r >= 0 );
	r = engine->EndConfigGroup(); assert( r >= 0 );

	r = engine->SetConfigGroupModuleAccess("group", "m", false); assert( r >= 0 );

	engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL);
	bout.buffer = "";
	r = engine->ExecuteString("m", "Func()");
	if( r >= 0 )
		fail = true;

	if( bout.buffer != "ExecuteString (1, 1) : Error   : No matching signatures to 'Func()'\n" )
		fail = true;

	r = engine->SetConfigGroupModuleAccess("group", "m", true); assert( r >= 0 );

	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
	r = engine->ExecuteString("m", "Func()");
	if( r < 0 )
		fail = true;

	engine->Release();

	//------------
	// Test object types
	engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);

	r = engine->BeginConfigGroup("group"); assert( r >= 0 );
	r = engine->RegisterObjectType("mytype", sizeof(int), asOBJ_PRIMITIVE); assert( r >= 0 );
	r = engine->EndConfigGroup(); assert( r >= 0 );

	r = engine->SetConfigGroupModuleAccess("group", 0, false); assert( r >= 0 );

	engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL);
	bout.buffer = "";
	r = engine->ExecuteString(0, "mytype a");
	if( r >= 0 )
		fail = true;

	if( bout.buffer != "ExecuteString (1, 1) : Error   : Type 'mytype' is not available for this module\n")
		fail = true;

	engine->Release();

	//------------
	// Test global operators
	engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);

	r = engine->RegisterObjectType("mytype", sizeof(int), asOBJ_PRIMITIVE); assert( r >= 0 );

	r = engine->BeginConfigGroup("group"); assert( r >= 0 );
	r = engine->RegisterGlobalBehaviour(asBEHAVE_ADD, "mytype f(mytype &in, mytype &in)", asFUNCTION(TypeAdd), asCALL_GENERIC); assert( r >= 0 );
	r = engine->EndConfigGroup(); assert( r >= 0 );

	r = engine->SetConfigGroupModuleAccess("group", 0, false); assert( r >= 0 );

	engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL);
	bout.buffer = "";
	r = engine->ExecuteString(0, "mytype a; a + a;");
	if( r >= 0 )
		fail = true;

	if( bout.buffer != "ExecuteString (1, 13) : Error   : No matching operator that takes the type 'mytype&' found\n")
		fail = true;

	engine->Release();

	// Success
	return fail;
}
コード例 #2
0
bool Test()
{
	bool fail = false;
	int r;

 	asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);

	RegisterScriptString_Generic(engine);
	RegisterScriptAny(engine);

	engine->RegisterGlobalFunction("void Assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);
	engine->RegisterGlobalFunction("void print(const string &in)", asFUNCTION(print), asCALL_GENERIC);
	engine->RegisterGlobalFunction("void Analyze(any &inout)", asFUNCTION(Analyze), asCALL_GENERIC);

	COutStream out;
	CBufferedOutStream bout;
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);

	asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection(TESTNAME, script1, strlen(script1), 0);
	r = mod->Build();
	if( r < 0 ) TEST_FAILED;

	asIScriptContext *ctx = engine->CreateContext();
	r = ExecuteString(engine, "Test()", mod, ctx);
	if( r != asEXECUTION_FINISHED ) 
	{
		if( r == asEXECUTION_EXCEPTION ) PrintException(ctx);
		TEST_FAILED;
	}
	if( ctx ) ctx->Release();

	// Make sure that the error message for wrong constructor name works
	bout.buffer = "";
	engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL);
	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection(TESTNAME, "class t{ s() {} };", 18, 0);
	r = mod->Build();
	if( r >= 0 ) TEST_FAILED;
	if( bout.buffer != "TestScriptClassMethod (1, 10) : Error   : The name of constructors and destructors must be the same as the class\n" ) 
	{
		printf("%s", bout.buffer.c_str());
		TEST_FAILED;
	}

	// Make sure the default constructor can be overloaded
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
	mod = engine->GetModule("test", asGM_ALWAYS_CREATE);
	mod->AddScriptSection(TESTNAME, script2, strlen(script2), 0);
	r = mod->Build();
	if( r < 0 ) TEST_FAILED;

	r = ExecuteString(engine, "Test()", mod);
	if( r != asEXECUTION_FINISHED )
	{
		TEST_FAILED;
	}

	asIObjectType *type = engine->GetModule("test")->GetObjectTypeByName("myclass");
	asIScriptObject *s = (asIScriptObject*)engine->CreateScriptObject(type);
	if( s == 0 ) 
		TEST_FAILED;
	else
	{
		// Validate the property
		int *v = 0;
		int n = s->GetPropertyCount();
		for( int c = 0; c < n; c++ )
		{
			std::string str = "value";
			if( str == s->GetPropertyName(c) )
			{	
				v = (int*)s->GetAddressOfProperty(c);
				if( *v != 1 ) TEST_FAILED;
			}
		}

		// Call the script class method
		if( type->GetMethodCount() != 2 ) 
			TEST_FAILED;
		asIScriptFunction *method = type->GetMethodByDecl("void method2()");
		if( method == 0 ) 
			TEST_FAILED;
		else
		{
			asIScriptContext *ctx = engine->CreateContext();
			ctx->Prepare(method);
			ctx->SetObject(s);
			int r = ctx->Execute();
			if( r != asEXECUTION_FINISHED )
				TEST_FAILED;

			if( (!v) || (*v != 3) ) 
				TEST_FAILED;

			ctx->Release();
		}

		s->Release();
	}

	engine->Release();

	//----------------------------------
	engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
	RegisterScriptAny(engine);
	engine->RegisterGlobalFunction("void Assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection("test3", script3, strlen(script3), 0);
	r = mod->Build();
	if( r < 0 ) TEST_FAILED;

	int typeId = engine->GetModule(0)->GetTypeIdByDecl("myclass");
	type = engine->GetObjectTypeById(typeId);
	asIScriptFunction *mtd = type->GetMethodByDecl("void func()");
	asIScriptObject *obj = (asIScriptObject *)engine->GetModule(0)->GetAddressOfGlobalVar(engine->GetModule(0)->GetGlobalVarIndexByName("c"));

	if( mtd == 0 || obj == 0 ) TEST_FAILED;
	else
	{
		asIScriptContext *ctx = engine->CreateContext();
		ctx->Prepare(mtd);
		ctx->SetObject(obj);
		r = ctx->Execute();
		if( r != asEXECUTION_FINISHED ) TEST_FAILED;
		ctx->Release();
	}

	type = engine->GetObjectTypeById(typeId);
	mtd = type->GetMethodByDecl("void func(int, int)");
	if( mtd == 0 || obj == 0 ) TEST_FAILED;
	else
	{
		asIScriptContext *ctx = engine->CreateContext();
		ctx->Prepare(mtd);
		ctx->SetObject(obj);
		ctx->SetArgDWord(0, 1);
		ctx->SetArgDWord(1, 1);
		r = ctx->Execute();
		if( r != asEXECUTION_FINISHED ) TEST_FAILED;
		ctx->Release();
	}

	engine->Release();

	//----------------------------
	// Verify that global functions and class methods with the same name doesn't conflict
	engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
	RegisterScriptAny(engine);
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection("test4", script4, strlen(script4), 0);
	r = mod->Build();
	if( r < 0 ) TEST_FAILED;
	
	asIScriptFunction *func = mod->GetFunctionByDecl("void func()");
	if( func == 0 ) TEST_FAILED;

	engine->Release();

	//----------------------------
	// Accessing member variables without this
	engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
	RegisterScriptAny(engine);
	engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);
	engine->RegisterGlobalFunction("void Assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);
	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection("test5", script5, strlen(script5), 0);
	r = mod->Build();
	if( r < 0 ) TEST_FAILED;

	r = ExecuteString(engine, "test()", mod);
	if( r != asEXECUTION_FINISHED )
	{
		TEST_FAILED;
	}

	engine->Release();

	//-----------------------------
	// Name conflict with class method and object type
	engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
	engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);
	RegisterScriptString(engine);
	engine->RegisterGlobalFunction("void print(const string &in)", asFUNCTION(print), asCALL_GENERIC);
	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection("test6", script6, strlen(script6), 0);
	r = mod->Build();
	if( r < 0 ) TEST_FAILED;

	outbuffer = "";
	r = ExecuteString(engine, "Test t; t.Set(1); t.Test2();", mod);
	if( r != asEXECUTION_FINISHED )
	{
		TEST_FAILED;
	}
	if( outbuffer != "Test::Set\nTest::Set\nSet::Set\n" )
	{
		printf("%s", outbuffer.c_str());
		TEST_FAILED;
	}

	engine->Release();

	//------------------------------
	// The scope operator should permit calling global functions if the class has a method of the same name
	engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
	engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);
	engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);
	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	const char *script = 
		"class A { \n"
		"  void func() { \n"
		"    g = 0; \n"
		"    testScope(); \n"
		"    assert(g == 3); \n"
        "    ::testScope(); \n"
		"    assert(g == 2); \n"
		"  } \n"
        "  void testScope() { g = 3; } \n"
		"} \n"
		"void testScope() { g = 2; } \n"
		"int g; \n";
	mod->AddScriptSection("script", script);
	r = mod->Build();
	if( r < 0 )
	{
		TEST_FAILED;
	}
	r = ExecuteString(engine, "A a; a.func(); assert( g == 2 );", mod);
	if( r != asEXECUTION_FINISHED )
	{
		TEST_FAILED;
	}
	engine->Release();

	//---------------------------
	// It should not be possible to declare a method with the same name as the class
	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(CBufferedOutStream, Callback), &bout, asCALL_THISCALL);
		mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
		const char *script = 
			"class A { \n"
			"  void A() {} \n"
			"} \n";
		mod->AddScriptSection("script", script);
		bout.buffer = "";
		r = mod->Build();
		if( r >= 0 )
			TEST_FAILED;
		if( bout.buffer != "script (2, 3) : Error   : The method cannot be named with the class name\n" )
		{
			printf("%s", bout.buffer.c_str());
			TEST_FAILED;
		}
		engine->Release();
	}

	// Success
	return fail;
}
コード例 #3
0
bool TestNotComplexStdcall()
{
	if( strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY") )
	{
		printf("%s: Skipped due to AS_MAX_PORTABILITY\n", TESTNAME);
		return false;
	}

	bool fail = false;

	asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);

	engine->RegisterObjectType("class1", sizeof(Class1), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS | asOBJ_APP_CLASS_ALLINTS);
	engine->RegisterObjectType("class2", sizeof(Class2), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS | asOBJ_APP_CLASS_ALLINTS);
	engine->RegisterObjectType("class3", sizeof(Class3), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS | asOBJ_APP_CLASS_ALLINTS);
	
	engine->RegisterGlobalProperty("class1 c1", &c1);
	engine->RegisterGlobalProperty("class2 c2", &c2);
	engine->RegisterGlobalProperty("class3 c3", &c3);

	engine->RegisterGlobalFunction("class1 notComplex1()", asFUNCTION(notComplex1), asCALL_STDCALL);
	engine->RegisterGlobalFunction("class2 notComplex2()", asFUNCTION(notComplex2), asCALL_STDCALL);
	engine->RegisterGlobalFunction("class3 notComplex3()", asFUNCTION(notComplex3), asCALL_STDCALL);

	COutStream out;

	c1.a = 0;
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);

	int r = ExecuteString(engine, "c1 = notComplex1();");
	if( r < 0 )
	{
		printf("%s: ExecuteString() failed %d\n", TESTNAME, r);
		TEST_FAILED;
	}

	if( c1.a != 0xDEADC0DE )
	{
		printf("%s: Failed to assign object returned from function. c1.a = %X\n", TESTNAME, (unsigned int)c1.a);
		TEST_FAILED;
	}


	c2.a = 0;
	c2.b = 0;

	r = ExecuteString(engine, "c2 = notComplex2();");
	if( r < 0 )
	{
		printf("%s: ExecuteString() failed %d\n", TESTNAME, r);
		TEST_FAILED;
	}

	if( c2.a != 0xDEADC0DE )
	{
		printf("%s: Failed to assign object returned from function. c2.a = %X\n", TESTNAME, (unsigned int)c2.a);
		TEST_FAILED;
	}

	if( c2.b != 0x01234567 )
	{
		printf("%s: Failed to assign object returned from function. c2.b = %X\n", TESTNAME, (unsigned int)c2.b);
		TEST_FAILED;
	}

	c3.a = 0;
	c3.b = 0;
	c3.c = 0;

	r = ExecuteString(engine, "c3 = notComplex3();");
	if( r < 0 )
	{
		printf("%s: ExecuteString() failed %d\n", TESTNAME, r);
		TEST_FAILED;
	}

	if( c3.a != 0xDEADC0DE )
	{
		printf("%s: Failed to assign object returned from function. c3.a = %X\n", TESTNAME, (unsigned int)c3.a);
		TEST_FAILED;
	}

	if( c3.b != 0x01234567 )
	{
		printf("%s: Failed to assign object returned from function. c3.b = %X\n", TESTNAME, (unsigned int)c3.b);
		TEST_FAILED;
	}

	if( c3.c != 0x89ABCDEF )
	{
		printf("%s: Failed to assign object returned from function. c3.c = %X\n", TESTNAME, (unsigned int)c3.c);
		TEST_FAILED;
	}

	engine->Release();

	return fail;
}
コード例 #4
0
ファイル: test_bool.cpp プロジェクト: Kaperstone/warsow
bool Test()
{
	if( strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY") )
	{
		printf("%s: Skipped due to AS_MAX_PORTABILITY\n", TESTNAME);
		return false;
	}

	bool fail = false;
	int r;
	COutStream out;

 	asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
	
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
	RegisterScriptArray(engine, true);
	RegisterScriptString(engine);
	engine->RegisterGlobalFunction("void Assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);


	// TEST 1
	engine->RegisterGlobalFunction("void CFunc(float, bool, bool, const string &in)", asFUNCTION(CFunc), asCALL_CDECL);

	asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection("decl", declarations, strlen(declarations));
	mod->AddScriptSection("script", script, strlen(script));
	r = mod->Build();
	if( r < 0 ) TEST_FAILED;

	r = ExecuteString(engine, "MyTest()", mod);
	if( r != asEXECUTION_FINISHED ) TEST_FAILED;

	
	// TEST 2
	mod->AddScriptSection("script", script2, strlen(script2));
	r = mod->Build();
	if( r < 0 ) TEST_FAILED;

	int idx = engine->GetModule(0)->GetGlobalVarIndexByName("gFlag");
	bool *flag = (bool*)engine->GetModule(0)->GetAddressOfGlobalVar(idx);
	*(int*)flag = 0xCDCDCDCD;

	ExecuteString(engine, "Set()", mod);
	if( *flag != true )
		TEST_FAILED;
	ExecuteString(engine, "Assert(gFlag == true)", mod);

	ExecuteString(engine, "gFlag = false; DoNothing()", mod);
	if( *flag != false )
		fail = false;
	ExecuteString(engine, "Assert(gFlag == false)", mod);

	ExecuteString(engine, "gFlag = true; DoNothing()", mod);
	if( *flag != true )
		fail = false;
	ExecuteString(engine, "Assert(gFlag == true)", mod);

	// TEST 3
	// It was reported that if( t.test_f() ) would always be true, even though the method returns false
	// The bug was that the function didn't return 0 in the upper bytes, thus the 32bit value was not 0, even though the low byte was
	engine->RegisterObjectType("tst", sizeof(tst), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS);
	engine->RegisterObjectMethod("tst", "bool test_f(uint)", asMETHOD(tst, test_f), asCALL_THISCALL);
	
	r = ExecuteString(engine, "tst t; if( t.test_f(2000) == true ) Assert(false);");
	if( r != asEXECUTION_FINISHED ) TEST_FAILED;
	
	r = ExecuteString(engine, "tst t; if( !(t.test_f(2000) == false) ) Assert(false);");
	if( r != asEXECUTION_FINISHED ) TEST_FAILED;
	
//	engine->SetEngineProperty(asEP_OPTIMIZE_BYTECODE, 0);
	r = ExecuteString(engine, "tst t; if( t.test_f(2000) ) Assert(false);");
	if( r != asEXECUTION_FINISHED ) TEST_FAILED;
		
	engine->RegisterGlobalFunction("bool test_t()", asFUNCTION(test_t), asCALL_CDECL);
	r = ExecuteString(engine, "Assert( test_t() );");
	if( r != asEXECUTION_FINISHED ) TEST_FAILED;
		
	// TEST 4
	// Return a false value as out parameter. The value must be properly interpreted, even with trash in upper bytes
	engine->RegisterGlobalFunction("void GiveFalse(bool &out)", asFUNCTION(GiveFalse), asCALL_CDECL);
	r = ExecuteString(engine, "bool f; GiveFalse(f); Assert( !f );");
	if( r != asEXECUTION_FINISHED ) TEST_FAILED;
	r = ExecuteString(engine, "bool f; GiveFalse(f); if( f ) Assert(false);");
	if( r != asEXECUTION_FINISHED ) TEST_FAILED;
	r = ExecuteString(engine, "bool f, f2 = false; GiveFalse(f); Assert( !(f || f2) );");
	if( r != asEXECUTION_FINISHED ) TEST_FAILED;

	// TEST 5
	// The same test with global variable
	int falseValue = 0;
	if( sizeof(bool) == 1 )
		falseValue = 0x00FFFF00;
	engine->RegisterGlobalProperty("bool falseValue", &falseValue);
	r = ExecuteString(engine, "Assert( !falseValue );");
	if( r != asEXECUTION_FINISHED ) TEST_FAILED;
	r = ExecuteString(engine, "if( falseValue ) Assert(false);");
	if( r != asEXECUTION_FINISHED ) TEST_FAILED;
	r = ExecuteString(engine, "bool f2 = false; Assert( !(falseValue || f2) );");
	if( r != asEXECUTION_FINISHED ) TEST_FAILED;

	// TEST 6
	// Test to make sure bools can be passed to member functions properly
	engine->RegisterObjectType("BoolTester", sizeof(TestBoolClass), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS);
	engine->RegisterObjectMethod("BoolTester", "void TestTrue(bool)", asMETHOD(TestBoolClass, TestTrue), asCALL_THISCALL);
	engine->RegisterObjectMethod("BoolTester", "void TestFalse(bool)", asMETHOD(TestBoolClass, TestFalse), asCALL_THISCALL);	
	TestBoolClass testBool;
	r = engine->RegisterGlobalProperty("BoolTester TestBoolClass", &testBool );
	if( r < 0 ) TEST_FAILED;
	mod->AddScriptSection("script", script3, strlen(script3));
	r = mod->Build();
	if( r < 0 )
	{
		TEST_FAILED;
	}
	else
	{
		r = ExecuteString(engine, "TestBoolToMember();", mod);
		if( r != asEXECUTION_FINISHED ) TEST_FAILED;

		if( testBool.m_fail ) TEST_FAILED;
	}

	// TEST 7
	engine->RegisterGlobalFunction("void Print(const string &in)", asFUNCTION(Print), asCALL_CDECL); assert( r >= 0 );
	mod->AddScriptSection("script", script4, strlen(script4));
	r = mod->Build();
	if( r < 0 )
	{
		TEST_FAILED;
	}
	else
	{
		r = ExecuteString(engine, "test();", mod);
		if( r != asEXECUTION_FINISHED ) TEST_FAILED;

		if( buf != "false\ntrue\nfalse\n" )
			TEST_FAILED;
	}


	// The tokenizer must not mistake '!isTrue' for '!is' + 'True' instead of '!' + 'isTrue'
	const char *script5 = 
		"class CTest                        \n"
		"{                                  \n"
		"  bool isTrue() { return true; }   \n"
		"  void func() { if( !isTrue() ) {} } \n"
		"}                                  \n";

	mod->AddScriptSection("script", script5, strlen(script5));
	r = mod->Build();
	if( r < 0 )
		TEST_FAILED;

	engine->Release();

	return fail;
}
コード例 #5
0
bool TestExecute32Args()
{
	bool ret = false;

 	asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
	if( strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY") )
		engine->RegisterGlobalFunction("void cfunction(int, int, int, int,"
													  "int, int, int, int,"
													  "int, int, int, int,"
													  "int, int, int, int,"
													  "int, int, int, int,"
													  "int, int, int, int,"
													  "int, int, int, int,"
													  "int, int, int, int)", 
									   asFUNCTION(cfunction_gen), asCALL_GENERIC);
	else		
	{
		engine->RegisterGlobalFunction("void cfunction(int, int, int, int,"
													  "int, int, int, int,"
													  "int, int, int, int,"
													  "int, int, int, int,"
													  "int, int, int, int,"
													  "int, int, int, int,"
													  "int, int, int, int,"
													  "int, int, int, int)", 
									   asFUNCTION(cfunction), asCALL_CDECL);

		engine->RegisterGlobalFunction("void cfunctionf(float, float, float, float,"
													  "float, float, float, float,"
													  "float, float, float, float,"
													  "float, float, float, float,"
													  "float, float, float, float,"
													  "float, float, float, float,"
													  "float, float, float, float,"
													  "float, float, float, float)", 
									   asFUNCTION(cfunctionf), asCALL_CDECL);

		engine->RegisterGlobalFunction("void cfunctiond(double, double, double, double,"
													  "double, double, double, double,"
													  "double, double, double, double,"
													  "double, double, double, double,"
													  "double, double, double, double,"
													  "double, double, double, double,"
													  "double, double, double, double,"
													  "double, double, double, double)", 
									   asFUNCTION(cfunctiond), asCALL_CDECL);
	}

	ExecuteString(engine, "cfunction( 1,  2,  3,  4,"
	                                " 5,  6,  7,  8,"
	                                " 9, 10, 11, 12,"
	                                "13, 14, 15, 16,"
	                                "17, 18, 19, 20,"
	                                "21, 22, 23, 24,"
	                                "25, 26, 27, 28,"
	                                "29, 30, 31, 32)");

	if( !called ) 
	{
		// failure
		printf("\n%s: cfunction not called from script\n\n", TESTNAME);
		ret = true;
	} 
	else if( !testVal ) 
	{
		// failure
		printf("\n%s: testVal is not of expected value. Got:\n\n", TESTNAME);
		for (int i = 0; i < 32; i++) 
			printf("value %d: %d\n", i, values[i]);
		
		ret = true;
	}
	
	if( !strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY") )
	{
		called = false;
		testVal = false;
		
		ExecuteString(engine, "cfunctionf( 1,  2,  3,  4,"
	                                " 5,  6,  7,  8,"
	                                " 9, 10, 11, 12,"
	                                "13, 14, 15, 16,"
	                                "17, 18, 19, 20,"
	                                "21, 22, 23, 24,"
	                                "25, 26, 27, 28,"
	                                "29, 30, 31, 32)");
		
		if( !called ) 
		{
			// failure
			printf("\n%s: cfunction not called from script\n\n", TESTNAME);
			ret = true;
		} 
		else if( !testVal ) 
		{
			// failure
			printf("\n%s: testVal is not of expected value. Got:\n\n", TESTNAME);
			for (int i = 0; i < 32; i++) 
				printf("value %d: %f\n", i, fvalues[i]);
		
			ret = true;
		}
		
		called = false;
		testVal = false;
		
		ExecuteString(engine, "cfunctiond( 1,  2,  3,  4,"
	                                " 5,  6,  7,  8,"
	                                " 9, 10, 11, 12,"
	                                "13, 14, 15, 16,"
	                                "17, 18, 19, 20,"
	                                "21, 22, 23, 24,"
	                                "25, 26, 27, 28,"
	                                "29, 30, 31, 32)");
		
		if( !called ) 
		{
			// failure
			printf("\n%s: cfunction not called from script\n\n", TESTNAME);
			ret = true;
		} 
		else if( !testVal ) 
		{
			// failure
			printf("\n%s: testVal is not of expected value. Got:\n\n", TESTNAME);
			for (int i = 0; i < 32; i++) 
				printf("value %d: %f\n", i, dvalues[i]);
		
			ret = true;
		}
	}

	engine->Release();
	
	// Success
	return ret;
}
コード例 #6
0
bool Test()
{
	RET_ON_MAX_PORT

	bool fail = false;
	int r;
	COutStream out;
	CBufferedOutStream bout;

	// Safe bool issue (where a value with boolean conversion is accidentally used for other purpose)
	// ref: http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Safe_bool

	// Testing implicit casts to bool from primitives (not allowed)
	{
		asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL);
		engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);

		bout.buffer = "";
		const char *script = 
			"  int a = 1; \n"
			"  bool correct = false; \n"
			"  if( a ) \n"                 // implicit conversion to bool is not allowed by default
			"    correct = true; \n"
			"  assert( correct ); \n"
			"  correct = false; \n"
			"  if( bool(a) ) \n"           // explicit conversion to bool is not available by default
			"    correct = true; \n"
			"  assert( correct ); \n"
			"  correct = false; \n"
			"  if( a && true ) \n"         // binary logical operator
			"    correct = true; \n"
			"  assert( correct ); \n"
			"  correct = false; \n"
			"  if( !a == false ) \n"       // unary logical operator
			"    correct = true; \n"
			"  assert( correct ); \n";

		r = ExecuteString(engine, script);
		if( r >= 0 )
			TEST_FAILED;

		if( bout.buffer != "ExecuteString (3, 7) : Error   : Expression must be of boolean type\n"
						   "ExecuteString (7, 7) : Error   : No conversion from 'const int' to 'const bool' available.\n"
						   "ExecuteString (7, 7) : Error   : Expression must be of boolean type\n"
						   "ExecuteString (11, 9) : Error   : No conversion from 'int' to 'bool' available.\n"
						   "ExecuteString (15, 7) : Error   : Illegal operation on this datatype\n" )
		{
			PRINTF("%s", bout.buffer.c_str());
			TEST_FAILED;
		}
/*
		// TODO: Should I allow implicit conversion of bool to/from math primitives?
		engine->SetEngineProperty(asEP_ALT_BOOL_CONV, 1); // allow bool to be used as arithmetic type, and also to allow arithmetic types to be used as bools

		r = ExecuteString(engine, script);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;
*/
		engine->Release();
	}

	// Value types should allow bool opImplConv() to be used
	// http://www.gamedev.net/topic/662813-opconv-and-opimplconv-with-bool/
	{
		asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);

		engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);
		engine->RegisterObjectType("MyBool", sizeof(int), asOBJ_APP_PRIMITIVE | asOBJ_VALUE | asOBJ_POD);
		engine->RegisterObjectMethod("MyBool", "bool opImplConv() const", asFUNCTION(ConvToBool), asCALL_CDECL_OBJLAST);
		engine->RegisterObjectBehaviour("MyBool", asBEHAVE_CONSTRUCT, "void f(bool)", asFUNCTION(ConstructFromBool), asCALL_CDECL_OBJLAST);
		engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);

		r = ExecuteString(engine, 
			"MyBool b = false; \n"
			"assert( !b ); \n"
			"b = true; \n"
			"bool correct = false; \n"
			"if( b ) correct = true; \n"
			"assert( correct ); \n"
			"assert( b ); \n"
			"correct = false; \n"
			"if( b && true ) correct = true; \n"
			"assert( correct ); \n");
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;

		engine->Release();
	}


	// TODO: Test with ref object types
	// For ref types with bool opImplConv() it should only be possible to directly convert if engine property is set
	// For ref types, if the handle is null an exception will be thrown, so the compiler should warn on the implicit conversion
	// if( @expr ) would be the same as if( expr !is null ) if the engine property is turned on

 	asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
	
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
	RegisterScriptArray(engine, true);
	RegisterScriptString(engine);
	engine->RegisterGlobalFunction("void Assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);


	// TEST 1
	engine->RegisterGlobalFunction("void CFunc(float, bool, bool, const string &in)", asFUNCTION(CFunc), asCALL_CDECL);

	asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection("decl", declarations, strlen(declarations));
	mod->AddScriptSection("script", script, strlen(script));
	r = mod->Build();
	if( r < 0 ) TEST_FAILED;

	r = ExecuteString(engine, "MyTest()", mod);
	if( r != asEXECUTION_FINISHED ) TEST_FAILED;

	
	// TEST 2
	mod->AddScriptSection("script", script2, strlen(script2));
	r = mod->Build();
	if( r < 0 ) TEST_FAILED;

	int idx = engine->GetModule(0)->GetGlobalVarIndexByName("gFlag");
	bool *flag = (bool*)engine->GetModule(0)->GetAddressOfGlobalVar(idx);
	*(int*)flag = 0xCDCDCDCD;

	ExecuteString(engine, "Set()", mod);
	if( *flag != true )
		TEST_FAILED;
	ExecuteString(engine, "Assert(gFlag == true)", mod);

	ExecuteString(engine, "gFlag = false; DoNothing()", mod);
	if( *flag != false )
		fail = false;
	ExecuteString(engine, "Assert(gFlag == false)", mod);

	ExecuteString(engine, "gFlag = true; DoNothing()", mod);
	if( *flag != true )
		fail = false;
	ExecuteString(engine, "Assert(gFlag == true)", mod);

	// TEST 3
	// It was reported that if( t.test_f() ) would always be true, even though the method returns false
	// The bug was that the function didn't return 0 in the upper bytes, thus the 32bit value was not 0, even though the low byte was
	engine->RegisterObjectType("tst", sizeof(tst), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS);
	engine->RegisterObjectMethod("tst", "bool test_f(uint)", asMETHOD(tst, test_f), asCALL_THISCALL);
	
	r = ExecuteString(engine, "tst t; if( t.test_f(2000) == true ) Assert(false);");
	if( r != asEXECUTION_FINISHED ) TEST_FAILED;
	
	r = ExecuteString(engine, "tst t; if( !(t.test_f(2000) == false) ) Assert(false);");
	if( r != asEXECUTION_FINISHED ) TEST_FAILED;
	
//	engine->SetEngineProperty(asEP_OPTIMIZE_BYTECODE, 0);
	r = ExecuteString(engine, "tst t; if( t.test_f(2000) ) Assert(false);");
	if( r != asEXECUTION_FINISHED ) TEST_FAILED;
		
	engine->RegisterGlobalFunction("bool test_t()", asFUNCTION(test_t), asCALL_CDECL);
	r = ExecuteString(engine, "Assert( test_t() );");
	if( r != asEXECUTION_FINISHED ) TEST_FAILED;
		
	// TEST 4
	// Return a false value as out parameter. The value must be properly interpreted, even with trash in upper bytes
	engine->RegisterGlobalFunction("void GiveFalse(bool &out)", asFUNCTION(GiveFalse), asCALL_CDECL);
	r = ExecuteString(engine, "bool f; GiveFalse(f); Assert( !f );");
	if( r != asEXECUTION_FINISHED ) TEST_FAILED;
	r = ExecuteString(engine, "bool f; GiveFalse(f); if( f ) Assert(false);");
	if( r != asEXECUTION_FINISHED ) TEST_FAILED;
	r = ExecuteString(engine, "bool f, f2 = false; GiveFalse(f); Assert( !(f || f2) );");
	if( r != asEXECUTION_FINISHED ) TEST_FAILED;

	// TEST 5
	// The same test with global variable
	int falseValue = 0;
	if( sizeof(bool) == 1 )
		falseValue = 0x00FFFF00;
	engine->RegisterGlobalProperty("bool falseValue", &falseValue);
	r = ExecuteString(engine, "Assert( !falseValue );");
	if( r != asEXECUTION_FINISHED ) TEST_FAILED;
	r = ExecuteString(engine, "if( falseValue ) Assert(false);");
	if( r != asEXECUTION_FINISHED ) TEST_FAILED;
	r = ExecuteString(engine, "bool f2 = false; Assert( !(falseValue || f2) );");
	if( r != asEXECUTION_FINISHED ) TEST_FAILED;

	// TEST 6
	// Test to make sure bools can be passed to member functions properly
	engine->RegisterObjectType("BoolTester", sizeof(TestBoolClass), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS);
	engine->RegisterObjectMethod("BoolTester", "void TestTrue(bool)", asMETHOD(TestBoolClass, TestTrue), asCALL_THISCALL);
	engine->RegisterObjectMethod("BoolTester", "void TestFalse(bool)", asMETHOD(TestBoolClass, TestFalse), asCALL_THISCALL);	
	TestBoolClass testBool;
	r = engine->RegisterGlobalProperty("BoolTester TestBoolClass", &testBool );
	if( r < 0 ) TEST_FAILED;
	mod->AddScriptSection("script", script3, strlen(script3));
	r = mod->Build();
	if( r < 0 )
	{
		TEST_FAILED;
	}
	else
	{
		r = ExecuteString(engine, "TestBoolToMember();", mod);
		if( r != asEXECUTION_FINISHED ) TEST_FAILED;

		if( testBool.m_fail ) TEST_FAILED;
	}

	// TEST 7
	engine->RegisterGlobalFunction("void Print(const string &in)", asFUNCTION(Print), asCALL_CDECL); assert( r >= 0 );
	mod->AddScriptSection("script", script4, strlen(script4));
	r = mod->Build();
	if( r < 0 )
	{
		TEST_FAILED;
	}
	else
	{
		r = ExecuteString(engine, "test();", mod);
		if( r != asEXECUTION_FINISHED ) TEST_FAILED;

		if( buf != "false\ntrue\nfalse\n" )
			TEST_FAILED;
	}


	// The tokenizer must not mistake '!isTrue' for '!is' + 'True' instead of '!' + 'isTrue'
	const char *script5 = 
		"class CTest                        \n"
		"{                                  \n"
		"  bool isTrue() { return true; }   \n"
		"  void func() { if( !isTrue() ) {} } \n"
		"}                                  \n";

	mod->AddScriptSection("script", script5, strlen(script5));
	r = mod->Build();
	if( r < 0 )
		TEST_FAILED;

	engine->Release();

	return fail;
}
コード例 #7
0
bool Test()
{
	RET_ON_MAX_PORT

	bool fail = false;
	int r;
	COutStream out;
	CBufferedOutStream bout;
 	asIScriptEngine *engine = 0;
	asIScriptModule *mod = 0;
	asIScriptContext *ctx = 0;

	// Test behaviour of var type with unsafe references
	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
		engine->SetEngineProperty(asEP_ALLOW_UNSAFE_REFERENCES, true);

		static bool expectNullRef;
		static bool expectHandleType;
		struct Test {
			static void Func(void *ref, int typeId) 
			{
				assert( (expectNullRef && ref == 0) || (!expectNullRef && ref != 0) );
				assert( (expectHandleType && (typeId & asTYPEID_OBJHANDLE)) || (!expectHandleType && (typeId & asTYPEID_OBJHANDLE) == 0) );
			}
		};

		engine->RegisterGlobalFunction("void funcO(?& out)", asFUNCTION(Test::Func), asCALL_CDECL);
		engine->RegisterGlobalFunction("void funcIO(?&)", asFUNCTION(Test::Func), asCALL_CDECL);

		const char *script = "class ScriptClass { int a = 0; } \n";
		mod = engine->GetModule("test", asGM_ALWAYS_CREATE);
		mod->AddScriptSection("test", script);
		r = mod->Build();
		if( r < 0 )
			TEST_FAILED;

		ctx = engine->CreateContext();

		expectNullRef = false;
		expectHandleType = false;
		r = ExecuteString(engine, "ScriptClass @t = ScriptClass(); funcO(t);", mod, ctx);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;
		if( r == asEXECUTION_EXCEPTION )
			PrintException(ctx);

		expectNullRef = true;
		expectHandleType = false;
		r = ExecuteString(engine, "ScriptClass @t; funcIO(t);", mod, ctx);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;
		if( r == asEXECUTION_EXCEPTION )
			PrintException(ctx);

		expectNullRef = false;
		expectHandleType = true;
		r = ExecuteString(engine, "ScriptClass @t; funcO(@t);", mod, ctx);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;
		if( r == asEXECUTION_EXCEPTION )
			PrintException(ctx);

		expectNullRef = false;
		expectHandleType = true;
		r = ExecuteString(engine, "ScriptClass @t; funcIO(@t);", mod, ctx);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;
		if( r == asEXECUTION_EXCEPTION )
			PrintException(ctx);

		// When disallowing value assignments, only the handle is passed to var args
		engine->SetEngineProperty(asEP_DISALLOW_VALUE_ASSIGN_FOR_REF_TYPE, true);

		expectNullRef = false;
		expectHandleType = true;
		r = ExecuteString(engine, "ScriptClass @t; funcO(t); funcO(@t); funcIO(t); funcIO(@t);", mod, ctx);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;
		if( r == asEXECUTION_EXCEPTION )
			PrintException(ctx);

		ctx->Release();
		engine->Release();
	}

	// It must not be possible to declare global variables of the var type ?
	engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
	engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL);
	const char *script1 = "? globvar;";
	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection("script", script1);
	r = mod->Build();
	if( r >= 0 ) TEST_FAILED;
	if( bout.buffer != "script (1, 1) : Error   : Unexpected token '?'\n" ) TEST_FAILED;
	bout.buffer = "";

	// It must not be possible to declare local variables of the var type ?
	const char *script2 = "void func() {? localvar;}";
	mod->AddScriptSection("script", script2);
	r = mod->Build();
	if( r >= 0 ) TEST_FAILED;
	if( bout.buffer != "script (1, 1) : Info    : Compiling void func()\n"
                       "script (1, 14) : Error   : Expected expression value\n"
					   "script (1, 14) : Error   : Instead found '?'\n" )
	{
		PRINTF("%s", bout.buffer.c_str());
		TEST_FAILED;
	}
	bout.buffer = "";

	// It must not be possible to register global properties of the var type ?
	r = engine->RegisterGlobalProperty("? prop", (void*)1);
	if( r >= 0 ) TEST_FAILED;
	if( bout.buffer != "Property (1, 1) : Error   : Expected data type\n"
		               "Property (1, 1) : Error   : Instead found '?'\n"
	                   " (0, 0) : Error   : Failed in call to function 'RegisterGlobalProperty' with '? prop' (Code: -10)\n" ) 
	{
		PRINTF("%s", bout.buffer.c_str());
		TEST_FAILED;
	}
	bout.buffer = "";
	engine->Release();

	// It must not be possible to register object members of the var type ?
	engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
	engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL);
	r = engine->RegisterObjectType("test", 0, asOBJ_REF); assert( r >= 0 );
	r = engine->RegisterObjectProperty("test", "? prop", 0);
	if( r >= 0 ) TEST_FAILED;
	if( bout.buffer != "Property (1, 1) : Error   : Expected data type\n"
		               "Property (1, 1) : Error   : Instead found '?'\n"
		               " (0, 0) : Error   : Failed in call to function 'RegisterObjectProperty' with 'test' and '? prop' (Code: -10)\n" )
	{
		PRINTF("%s", bout.buffer.c_str());
		TEST_FAILED;
	}
	bout.buffer = "";
	engine->Release();

	// It must not be possible to declare script class members of the var type ?
	engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
	engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL);
	const char *script3 = "class c {? member;}";
	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection("script", script3);
	r = mod->Build();
	if( r >= 0 ) TEST_FAILED;
	if( bout.buffer != "script (1, 10) : Error   : Expected method or property\n"
		               "script (1, 10) : Error   : Instead found '?'\n"
		               "script (1, 19) : Error   : Unexpected token '}'\n" )
	{
		PRINTF("%s", bout.buffer.c_str());
		TEST_FAILED;
	}
	bout.buffer = "";
	
	// It must not be possible to declare script functions that take the var type ? as parameter 
	const char *script4 = "void func(?&in a) {}";
	mod->AddScriptSection("script", script4);
	r = mod->Build();
	if( r >= 0 ) TEST_FAILED;
	if( bout.buffer != "script (1, 11) : Error   : Expected data type\n"
		               "script (1, 11) : Error   : Instead found '?'\n")
	{
		PRINTF("%s", bout.buffer.c_str());
		TEST_FAILED;
	}
	bout.buffer = "";

	// It must not be possible to declare script functions that return the var type ?
	const char *script5 = "? func() {}";
	mod->AddScriptSection("script", script5);
	r = mod->Build();
	if( r >= 0 ) TEST_FAILED;
	if( bout.buffer != "script (1, 1) : Error   : Unexpected token '?'\n" ) TEST_FAILED;
	bout.buffer = "";

	// It must not be possible to declare script class methods that take the var type ? as parameter
	const char *script6 = "class c {void method(?& in a) {}}";
	mod->AddScriptSection("script", script6);
	r = mod->Build();
	if( r >= 0 ) TEST_FAILED;
	if( bout.buffer != "script (1, 22) : Error   : Expected data type\n" 
		               "script (1, 22) : Error   : Instead found '?'\n"
					   "script (1, 33) : Error   : Unexpected token '}'\n" ) 
	{
		PRINTF("%s", bout.buffer.c_str());
		TEST_FAILED;
	}
	bout.buffer = "";

	// It must not be possible to declare script class methods that return the var type ?
	const char *script7 = "class c {? method() {}}";
	mod->AddScriptSection("script", script7);
	r = mod->Build();
	if( r >= 0 ) TEST_FAILED;
	if( bout.buffer != "script (1, 10) : Error   : Expected method or property\n"
		               "script (1, 10) : Error   : Instead found '?'\n"
		               "script (1, 23) : Error   : Unexpected token '}'\n" )
	{
		PRINTF("%s", bout.buffer.c_str());
		TEST_FAILED;
	}
	bout.buffer = "";

	// It must not be possible to declare arrays of the var type ?
	const char *script8 = "void func() { ?[] array; }";
	mod->AddScriptSection("script", script8);
	r = mod->Build();
	if( r >= 0 ) TEST_FAILED;
	if( bout.buffer != "script (1, 1) : Info    : Compiling void func()\n"
		               "script (1, 15) : Error   : Expected expression value\n"
					   "script (1, 15) : Error   : Instead found '?'\n" )
	{
		PRINTF("%s", bout.buffer.c_str());
		TEST_FAILED;
	}
	bout.buffer = "";

	// It must not be possible to declare handles of the var type ?
	const char *script9 = "void func() { ?@ handle; }";
	mod->AddScriptSection("script", script9);
	r = mod->Build();
	if( r >= 0 ) TEST_FAILED;
	if( bout.buffer != "script (1, 1) : Info    : Compiling void func()\n"
		               "script (1, 15) : Error   : Expected expression value\n"
					   "script (1, 15) : Error   : Instead found '?'\n" )
	{
		PRINTF("%s", bout.buffer.c_str());
		TEST_FAILED;
	}
	bout.buffer = "";

	// It must not be possible to register functions that return the var type ?
	r = engine->RegisterGlobalFunction("? testFunc()", asFUNCTION(testFuncI), asCALL_GENERIC);
	if( r >= 0 ) TEST_FAILED;
	if( bout.buffer != "System function (1, 1) : Error   : Expected data type\n"
					   "System function (1, 1) : Error   : Instead found '?'\n"
		               " (0, 0) : Error   : Failed in call to function 'RegisterGlobalFunction' with '? testFunc()' (Code: -10)\n" )
	{
		PRINTF("%s", bout.buffer.c_str());
		TEST_FAILED;
	}
	bout.buffer = "";
	engine->Release();

	// It must be possible to register functions that take the var type ? as parameter
	// Only when the expression is explicitly sent as @ should the type id be @
	// const ? & in
	// ? & in
	// TODO: 2.29.0: Should have syntax to inform that only handle or only non-handle can be informed
	//               Maybe 'const ? @ & in' for only handle 
	//                     '? @- & in' for only non-handle
	//                     '? @+ & in' for only handle with auto-handle
	engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
	RegisterScriptString(engine);
	r = engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);

	r = engine->RegisterGlobalFunction("void testFuncI(?& in)", asFUNCTION(testFuncI), asCALL_GENERIC);
	if( r < 0 ) TEST_FAILED;
	r = engine->RegisterGlobalFunction("void testFuncCI(const?&in)", asFUNCTION(testFuncI), asCALL_GENERIC);
	if( r < 0 ) TEST_FAILED;
	r = engine->RegisterGlobalFunction("void testFuncS(string &in)", asFUNCTION(testFuncS), asCALL_GENERIC);

	r = ExecuteString(engine, "int a = 42; testFuncI(a);");
	if( r != asEXECUTION_FINISHED ) TEST_FAILED;
	r = ExecuteString(engine, "string a = \"test\"; testFuncI(a);");
	if( r != asEXECUTION_FINISHED ) TEST_FAILED;
	r = ExecuteString(engine, "string @a = @\"test\"; testFuncI(@a);");
	if( r != asEXECUTION_FINISHED ) TEST_FAILED;
	r = ExecuteString(engine, "testFuncI(null);");
	if( r != asEXECUTION_FINISHED ) TEST_FAILED;

	// Both functions should receive the string by reference
	r = ExecuteString(engine, "string a = 'test'; testFuncI(a); testFuncS(a);");
	if( r != asEXECUTION_FINISHED ) TEST_FAILED;

	// It must be possible to register with 'out' references
	// ? & out
	// TODO: 2.29.0: Should have syntax to inform that only handle or only non-handle can be informed
	//               Maybe '? @ & out' for only handle
	//                     '? @- & out' for non-handle
	//                     '? @+ & out' for auto handle
	r = engine->RegisterGlobalFunction("void testFuncO(?&out)", asFUNCTION(testFuncO), asCALL_GENERIC);
	if( r < 0 ) TEST_FAILED;

	r = ExecuteString(engine, "testFuncO(0)"); // skip out value
	if( r != asEXECUTION_FINISHED ) TEST_FAILED;
	r = ExecuteString(engine, "testFuncO(void)"); // skip out value
	if( r != asEXECUTION_FINISHED ) TEST_FAILED;
	r = ExecuteString(engine, "testFuncO(null)"); // skip out value
	if( r != asEXECUTION_FINISHED ) TEST_FAILED;
	r = ExecuteString(engine, "int a; testFuncO(a); assert(a == 42);");
	if( r != asEXECUTION_FINISHED ) TEST_FAILED;
	r = ExecuteString(engine, "string a; testFuncO(a); assert(a == \"test\");");
	if( r != asEXECUTION_FINISHED ) TEST_FAILED;
	r = ExecuteString(engine, "string @a; testFuncO(@a); assert(a == \"test\");");
	if( r != asEXECUTION_FINISHED ) TEST_FAILED;

	// It must be possible to mix normal parameter types with the var type ?
	// e.g. func(const string &in, const ?& in), or func(const ?& in, const string &in)
	r = engine->RegisterGlobalFunction("void testFuncIS(?& in, const string &in)", asFUNCTION(testFuncIS_generic), asCALL_GENERIC);
	if( r < 0 ) TEST_FAILED;
	r = engine->RegisterGlobalFunction("void testFuncSI(const string &in, ?& in)", asFUNCTION(testFuncSI_generic), asCALL_GENERIC);
	if( r < 0 ) TEST_FAILED;

	r = ExecuteString(engine, "int a = 42; testFuncIS(a, \"test\");");
	if( r != asEXECUTION_FINISHED ) TEST_FAILED;
	r = ExecuteString(engine, "int a = 42; testFuncSI(\"test\", a);");
	if( r != asEXECUTION_FINISHED ) TEST_FAILED;
	r = ExecuteString(engine, "string a = \"t\"; testFuncIS(a, \"test\");");
	if( r != asEXECUTION_FINISHED ) TEST_FAILED;
	r = ExecuteString(engine, "string a = \"t\"; testFuncIS(@a, \"test\");");
	if( r != asEXECUTION_FINISHED ) TEST_FAILED;


	// It must be possible to use native functions
	SKIP_ON_MAX_PORT
	{
		r = engine->RegisterGlobalFunction("void _testFuncIS(?& in, const string &in)", asFUNCTION(testFuncIS), asCALL_CDECL);
		if( r < 0 ) TEST_FAILED;
		r = engine->RegisterGlobalFunction("void _testFuncSI(const string &in, ?& in)", asFUNCTION(testFuncSI), asCALL_CDECL);
		if( r < 0 ) TEST_FAILED;

		r = ExecuteString(engine, "int a = 42; _testFuncIS(a, \"test\");");
		if( r != asEXECUTION_FINISHED ) TEST_FAILED;
		r = ExecuteString(engine, "int a = 42; _testFuncSI(\"test\", a);");
		if( r != asEXECUTION_FINISHED ) TEST_FAILED;
		r = ExecuteString(engine, "string a = \"t\"; _testFuncIS(a, \"test\");");
		if( r != asEXECUTION_FINISHED ) TEST_FAILED;
		r = ExecuteString(engine, "string a = \"t\"; _testFuncIS(@a, \"test\");");
		if( r != asEXECUTION_FINISHED ) TEST_FAILED;
	}

	// Don't give error on passing reference to const to ?&out
	engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL);
	const char *script = 
	"class C { string @a; } \n";
	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection("script", script);
	mod->Build();
	r = ExecuteString(engine, "const C c; testFuncO(@c.a);", mod);
	if( r != asEXECUTION_FINISHED ) TEST_FAILED;
	if( bout.buffer != "ExecuteString (1, 23) : Warning : Argument cannot be assigned. Output will be discarded.\n" ) TEST_FAILED;
	bout.buffer = "";

	// ?& with opAssign is allowed, but won't be used with the assignment operator
	// TODO: Support ?& with the operators as well
	engine->RegisterObjectType("type", sizeof(int), asOBJ_VALUE | asOBJ_APP_PRIMITIVE);
	r = engine->RegisterObjectMethod("type", "type &opAssign(const ?& in)", asFUNCTION(testFuncSI_generic), asCALL_GENERIC);
	if( r < 0 )
		TEST_FAILED;
	// TODO: This is a valid class method, but should perhaps not be allowed to be used as operator
	/*
	r = engine->RegisterObjectMethod("type", "type opAdd(const ?& in)", asFUNCTION(testFuncSI_generic), asCALL_GENERIC);
	if( r >= 0 )
		TEST_FAILED;
	*/
	
	// Don't allow use of ? without being reference
	r = engine->RegisterGlobalFunction("void testFunc_err(const ?)", asFUNCTION(testFuncSI_generic), asCALL_GENERIC);
	if( r >= 0 )
		TEST_FAILED;

	// Don't allow use of 'inout' reference, yet
	// ? & [inout]
	// const ? & [inout]
	r = engine->RegisterGlobalFunction("void testFuncIO(?&)", asFUNCTION(testFuncSI_generic), asCALL_GENERIC);
	if( r >= 0 ) TEST_FAILED;
	r = engine->RegisterGlobalFunction("void testFuncCIO(const?&)", asFUNCTION(testFuncSI_generic), asCALL_GENERIC);
	if( r >= 0 ) TEST_FAILED;

	engine->Release();

	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
		RegisterScriptString(engine);
		r = engine->RegisterObjectType("obj", sizeof(int), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_PRIMITIVE); assert( r >= 0 );
		r = engine->RegisterObjectMethod("obj", "string @fmt(const string &in, ?&in, ?&in, ?&in, ?&in, ?&in, ?&in, ?&in, ?&in, ?&in, ?&in, ?&in, ?&in, ?&in, ?&in, ?&in, ?&in, ?&in, ?&in, ?&in, ?&in)", asFUNCTION(testFuncSI_generic), asCALL_GENERIC); assert( r >= 0 );

		asIScriptModule *mod = engine->GetModule("1", asGM_ALWAYS_CREATE);
		mod->AddScriptSection("script", 
			"class App {\n"
			"	int Run() {\n"
			"		return 0;\n"
			"	}\n"
			"}\n");
		r = mod->Build();
		if( r < 0 )
			TEST_FAILED;

		engine->Release();
	}

	return fail;
}
コード例 #8
0
bool Test()
{
	bool fail = Test2();
	int r;
	COutStream out;
	CBufferedOutStream bout;
	asIScriptContext *ctx;

 	asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
	
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);

	RegisterScriptString(engine);
	RegisterScriptArray(engine);

	engine->RegisterGlobalFunction("void Assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);


	asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection(TESTNAME, script1, strlen(script1), 0);
	r = mod->Build();
	if( r < 0 )
	{
		fail = true;
		printf("%s: Failed to compile the script\n", TESTNAME);
	}

	ctx = engine->CreateContext();
	r = ExecuteString(engine, "TestArray()", mod, ctx);
	if( r != asEXECUTION_FINISHED )
	{
		if( r == asEXECUTION_EXCEPTION )
			PrintException(ctx);

		printf("%s: Failed to execute script\n", TESTNAME);
		fail = true;
	}
	if( ctx ) ctx->Release();

	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection(TESTNAME, script2, strlen(script2), 0);
	r = mod->Build();
	if( r < 0 )
	{
		fail = true;
		printf("%s: Failed to compile the script\n", TESTNAME);
	}

	r = ExecuteString(engine, "TestArrayException()", mod);
	if( r != asEXECUTION_EXCEPTION )
	{
		printf("%s: No exception\n", TESTNAME);
		fail = true;
	}

	// Must be possible to declare array of arrays
	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection(TESTNAME, script3, strlen(script3), 0);
	r = mod->Build();
	if( r < 0 )
	{
		fail = true;
		printf("%s: Failed to compile the script\n", TESTNAME);
	}

	ctx = engine->CreateContext();
	r = ExecuteString(engine, "TestArrayMulti()", mod, ctx);
	if( r != asEXECUTION_FINISHED )
	{
		printf("%s: Failure\n", TESTNAME);
		fail = true;
	}
	if( r == asEXECUTION_EXCEPTION )
	{
		PrintException(ctx);
	}
	if( ctx ) ctx->Release();
	ctx = 0;


	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection(TESTNAME, script4, strlen(script4), 0);
	r = mod->Build();
	if( r < 0 )
	{
		fail = true;
		printf("%s: Failed to compile the script\n", TESTNAME);
	}
	ctx = engine->CreateContext();
	r = ExecuteString(engine, "TestArrayChar()", mod, ctx);
	if( r != asEXECUTION_FINISHED )
	{
		printf("%s: Failure\n", TESTNAME);
		fail = true;
	}
	if( r == asEXECUTION_EXCEPTION )
	{
		PrintException(ctx);
	}

	if( ctx ) ctx->Release();

	// Initialization lists must work for array template
	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection(TESTNAME, script5, strlen(script5), 0);
	r = mod->Build();
	if( r < 0 ) fail = true;
	ctx = engine->CreateContext();
	r = ExecuteString(engine, "TestArrayInitList()", mod, ctx);
	if( r != asEXECUTION_FINISHED ) fail = true;
	if( r == asEXECUTION_EXCEPTION )
		PrintException(ctx);

	if( ctx ) ctx->Release();

	engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL);
	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection(TESTNAME, script6, strlen(script6), 0);
	r = mod->Build();
	if( r >= 0 ) fail = true;
	if( bout.buffer != "Test_Addon_ScriptArray (1, 1) : Info    : Compiling void Test()\n"
	                   "Test_Addon_ScriptArray (3, 20) : Error   : Initialization lists cannot be used with 'array<int>@'\n"
	                   "Test_Addon_ScriptArray (4, 21) : Error   : Initialization lists cannot be used with 'int'\n" )
	{
		printf(bout.buffer.c_str());
		fail = true;
	}

	// Array object must call default constructor of the script classes
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection(TESTNAME, script7, strlen(script7), 0);
	r = mod->Build();
	if( r < 0 ) 
		fail = true;
	r = ExecuteString(engine, "Test()", mod);
	if( r != asEXECUTION_FINISHED )
		fail = true;
		
	// Test bool[] on Mac OS X with PPC CPU
	// Submitted by Edward Rudd
	const char *script8 =
	"array<bool> f(10);         \n"
	"for (int i=0; i<10; i++) { \n"
	"	f[i] = false;           \n"
	"}                          \n"
	"Assert(f[0] == false);     \n"
	"Assert(f[1] == false);     \n"
	"f[0] = true;               \n"
	"Assert(f[0] == true);      \n"
	"Assert(f[1] == false);     \n";
	
	r = ExecuteString(engine, script8, mod);
	if( r != asEXECUTION_FINISHED )
		fail = true;

	// Make sure it is possible to do multiple assignments with the array type
	r = ExecuteString(engine, "array<int> a, b, c; a = b = c;");
	if( r < 0 )
		fail = true;

	// Must support syntax as: array<array<int>>, i.e. without white space between the closing angled brackets.
	r = ExecuteString(engine, "array<array<int>> a(2); Assert( a.length() == 2 );");
	if( r < 0 )
		fail = true;

	// Must support arrays of handles
	r = ExecuteString(engine, "array<array<int>@> a(1); @a[0] = @array<int>(4);");
	if( r < 0 )
		fail = true;

	// Do not allow the instantiation of a template with a subtype that cannot be created
	bout.buffer = "";
	engine->SetMessageCallback(asMETHOD(CBufferedOutStream, Callback), &bout, asCALL_THISCALL);
	engine->RegisterObjectType("single", 0, asOBJ_REF | asOBJ_NOHANDLE);
	r = ExecuteString(engine, "array<single> a;");
	if( r >= 0 )
		fail = true;
	if( bout.buffer != "ExecuteString (1, 7) : Error   : Can't instanciate template 'array' with subtype 'single'\n" )
	{
		printf(bout.buffer.c_str());
		fail = true;
	}

	engine->Release();

	// Test too large arrays
	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		RegisterScriptArray(engine);

		ctx = engine->CreateContext();
		r = ExecuteString(engine, "array<int> a; a.resize(0xFFFFFFFF);", 0, ctx);
		if( r != asEXECUTION_EXCEPTION )
		{
			fail = true;
		}
		else if( strcmp(ctx->GetExceptionString(), "Too large array size") != 0 )
		{
			fail = true;
		}

		r = ExecuteString(engine, "array<int> a(0xFFFFFFFF);", 0, ctx);
		if( r != asEXECUTION_EXCEPTION )
		{
			fail = true;
		}
		else if( strcmp(ctx->GetExceptionString(), "Too large array size") != 0 )
		{
			fail = true;
		}

		ctx->Release();
		engine->Release();
	}


	// Success
	return fail;
}
コード例 #9
0
bool TestCDecl_Class()
{
	if( strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY") )
	{
		printf("%s: Skipped due to AS_MAX_PORTABILITY\n", TESTNAME);
		return false;
	}

	bool fail = false;

	asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);

	engine->RegisterObjectType("class1", sizeof(Class1), asOBJ_CLASS);
	engine->RegisterObjectType("class2", sizeof(Class2), asOBJ_CLASS);
	engine->RegisterObjectType("class3", sizeof(Class3), asOBJ_CLASS);
	
	engine->RegisterGlobalProperty("class1 c1", &c1);
	engine->RegisterGlobalProperty("class2 c2", &c2);
	engine->RegisterGlobalProperty("class3 c3", &c3);

	engine->RegisterGlobalFunction("class1 _class1()", asFUNCTION(class1), asCALL_CDECL);
	engine->RegisterGlobalFunction("class2 _class2()", asFUNCTION(class2), asCALL_CDECL);
	engine->RegisterGlobalFunction("class3 _class3()", asFUNCTION(class3), asCALL_CDECL);

	COutStream out;

	c1.a = 0;

	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
	int r = engine->ExecuteString(0, "c1 = _class1();");
	if( r < 0 )
	{
		printf("%s: ExecuteString() failed %d\n", TESTNAME, r);
		fail = true;
	}

	if( c1.a != 0xDEADC0DE )
	{
		printf("%s: Failed to assign object returned from function. c1.a = %X\n", TESTNAME, c1.a);
		fail = true;
	}


	c2.a = 0;
	c2.b = 0;

	r = engine->ExecuteString(0, "c2 = _class2();");
	if( r < 0 )
	{
		printf("%s: ExecuteString() failed %d\n", TESTNAME, r);
		fail = true;
	}

	if( c2.a != 0xDEADC0DE )
	{
		printf("%s: Failed to assign object returned from function. c2.a = %X\n", TESTNAME, c2.a);
		fail = true;
	}

	if( c2.b != 0x01234567 )
	{
		printf("%s: Failed to assign object returned from function. c2.b = %X\n", TESTNAME, c2.b);
		fail = true;
	}

	c3.a = 0;
	c3.b = 0;
	c3.c = 0;

	r = engine->ExecuteString(0, "c3 = _class3();");
	if( r < 0 )
	{
		printf("%s: ExecuteString() failed %d\n", TESTNAME, r);
		fail = true;
	}

	if( c3.a != 0xDEADC0DE )
	{
		printf("%s: Failed to assign object returned from function. c3.a = %X\n", TESTNAME, c3.a);
		fail = true;
	}

	if( c3.b != 0x01234567 )
	{
		printf("%s: Failed to assign object returned from function. c3.b = %X\n", TESTNAME, c3.b);
		fail = true;
	}

	if( c3.c != 0x89ABCDEF )
	{
		printf("%s: Failed to assign object returned from function. c3.c = %X\n", TESTNAME, c3.c);
		fail = true;
	}

	engine->Release();

	return fail;
}
コード例 #10
0
bool Test()
{
	bool fail = Test2();
	int r;

	asIScriptModule *mod = 0;

	asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
	RegisterScriptArray(engine, true);
	RegisterScriptString(engine);

	engine->RegisterGlobalFunction("void Assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);

	COutStream out;
	CBufferedOutStream bout;
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);

	// Test declaring multiple properties in same declaration separated by ,
	{
		mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
		mod->AddScriptSection(TESTNAME, 
			"class A { \n"
			"  int a, b, c; \n"
			"  void f() { a = b = c; } \n"
			"} \n");

		r = mod->Build();
		if( r < 0 ) TEST_FAILED;
	}


	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection(TESTNAME, script1);
	r = mod->Build();
	if( r < 0 ) TEST_FAILED;

	// Verify that GetObjectTypeByIndex recognizes the script class
	if( mod->GetObjectTypeCount() != 1 )
		TEST_FAILED;
	asIObjectType *type = mod->GetObjectTypeByIndex(0);
	if( strcmp(type->GetName(), "Test") != 0 )
		TEST_FAILED;

	asIScriptContext *ctx = engine->CreateContext();
	r = ExecuteString(engine, "TestStruct()", mod, ctx);
	if( r != asEXECUTION_FINISHED ) 
	{
		if( r == asEXECUTION_EXCEPTION ) PrintException(ctx);
		TEST_FAILED;
	}
	if( ctx ) ctx->Release();

	bout.buffer = "";
	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection(TESTNAME, script2);
	engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL);
	r = mod->Build();
	if( r >= 0 || bout.buffer != "TestScriptStruct (3, 4) : Error   : Class properties cannot be declared as const\n" ) TEST_FAILED;

	mod->AddScriptSection(TESTNAME, script3);
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
	r = mod->Build();
	if( r < 0 ) TEST_FAILED;
	r = ExecuteString(engine, "TestArrayInStruct()", mod);
	if( r != 0 ) TEST_FAILED;

	mod->AddScriptSection(TESTNAME, script4, strlen(script4), 0);
	r = mod->Build();
	if( r < 0 ) TEST_FAILED;
	r = ExecuteString(engine, "Test()", mod);
	if( r != 0 ) TEST_FAILED;

	bout.buffer = "";
	mod->AddScriptSection(TESTNAME, script5, strlen(script5), 0);
	engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL);
	r = mod->Build();
	if( r >= 0 || bout.buffer != 
		"TestScriptStruct (2, 7) : Error   : Name conflict. 'A' is a class.\n"
		"TestScriptStruct (6, 9) : Error   : Name conflict. 'a' is an object property.\n" ) TEST_FAILED;

	bout.buffer = "";
	mod->AddScriptSection(TESTNAME, script6, strlen(script6), 0);
	r = mod->Build();
	if( r >= 0 || bout.buffer !=
		"TestScriptStruct (1, 7) : Error   : Illegal member type\n"
		"TestScriptStruct (5, 7) : Error   : Illegal member type\n" ) TEST_FAILED;

	mod->AddScriptSection(TESTNAME, script7, strlen(script7), 0);
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
	r = mod->Build();
	if( r < 0 ) TEST_FAILED;
	ctx = engine->CreateContext();
	r = ExecuteString(engine, "TestHandleInStruct()", mod, ctx);
	if( r != 0 )
	{
		if( r == asEXECUTION_EXCEPTION )
		{
			printf("%s\n", ctx->GetExceptionString());
		}
		TEST_FAILED;
	}
	if( ctx ) ctx->Release();

	mod->AddScriptSection(TESTNAME, script8, strlen(script8), 0);
	r = mod->Build();
	if( r < 0 ) TEST_FAILED;
	r = ExecuteString(engine, "TestHandleInStruct2()", mod);
	if( r != 0 ) TEST_FAILED;

	mod->AddScriptSection(TESTNAME, script9, strlen(script9), 0);
	r = mod->Build();
	if( r < 0 ) TEST_FAILED;
	r = ExecuteString(engine, "Test()", mod);
	if( r != 0 ) TEST_FAILED;

	bout.buffer = "";
	mod->AddScriptSection(TESTNAME, script10, strlen(script10), 0);
	engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL);
	r = mod->Build();
	if( r >= 0 ) TEST_FAILED;
	if( bout.buffer != "TestScriptStruct (1, 7) : Error   : Illegal member type\n" ) TEST_FAILED;

	bout.buffer = "";
	mod->AddScriptSection(TESTNAME, script11, strlen(script11), 0);
	r = mod->Build();
	if( r >= 0 ) TEST_FAILED;
	if( bout.buffer != "TestScriptStruct (5, 1) : Info    : Compiling void Test()\nTestScriptStruct (9, 11) : Error   : Reference is read-only\n" ) TEST_FAILED;

	mod->AddScriptSection(TESTNAME, script12, strlen(script12), 0);
	mod->AddScriptSection(TESTNAME, script13, strlen(script13), 0);
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
	r = mod->Build();
	if( r < 0 ) TEST_FAILED;

	// The garbage collection doesn't have to be invoked immediately. Modules
	// can even be discarded before calling the garbage collector.
	engine->GarbageCollect();
	
	// Make sure it is possible to copy a script class that contains an object handle
	mod->AddScriptSection(TESTNAME, script14, strlen(script14), 0);
	r = mod->Build();
	if( r < 0 ) TEST_FAILED;
	r = ExecuteString(engine, "A a; B b; @a.b = @b; b.val = 1; A a2; a2 = a; Assert(a2.b.val == 1);", mod);
	if( r != asEXECUTION_FINISHED )
		TEST_FAILED;

	// Make sure it is possible to copy a script class that contains an array
	const char *script15 = 
		"class Some \n"
        "{ \n"
        "    int[] i; // need be array \n"
        "} \n"
        "void main() \n"
        "{ \n"
        "    Some e; \n"
        "    e=some(e); // crash \n"
        "} \n"
        "Some@ some(Some@ e) \n"
        "{ \n"
        "    return e; \n"
        "} \n";

	mod->AddScriptSection(TESTNAME, script15);
	r = mod->Build();
	if( r < 0 ) TEST_FAILED;
	r = ExecuteString(engine, "main()", mod);
	if( r != asEXECUTION_FINISHED )
		TEST_FAILED;

	engine->Release();

	// A script class must be able to have a registered ref type as a local member
	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL);
		RegisterScriptString(engine);

		const char *script = "class C { string s; }";
		mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
		mod->AddScriptSection("s", script);

		bout.buffer = "";
		r = mod->Build();
		if( r < 0 ) 
			TEST_FAILED;

		if( bout.buffer != "" )
		{
			printf("%s", bout.buffer.c_str());
			TEST_FAILED;
		}

		if( !fail )
		{
			r = ExecuteString(engine, "C c; c.s = 'test';", mod);
			if( r != asEXECUTION_FINISHED )
			{
				TEST_FAILED;
			}
		}

		engine->Release();
	}

	// Test private properties
	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL);

		const char *script = "class C { \n"
			                 "private int a; \n"
							 "void func() { a = 1; } }\n"
							 "void main() { C c; c.a = 2; }";
		mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
		mod->AddScriptSection("s", script);

		bout.buffer = "";
		r = mod->Build();
		if( r >= 0 ) 
			TEST_FAILED;

		if( bout.buffer != "s (4, 1) : Info    : Compiling void main()\n"
		                   "s (4, 21) : Error   : Illegal access to private property 'a'\n" )
		{
			printf("%s", bout.buffer.c_str());
			TEST_FAILED;
		}

		engine->Release();
	}

	// Test private methods
	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(CBufferedOutStream, Callback), &bout, asCALL_THISCALL);

		const char *script = "class C { \n"
							 "  private void func() {} \n"
							 "  void func2() { func(); } } \n"
							 "void main() { C c; c.func(); } \n";
		mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
		mod->AddScriptSection("s", script);

		bout.buffer = "";
		r = mod->Build();
		if( r >= 0 )
			TEST_FAILED;

		if( bout.buffer != "s (4, 1) : Info    : Compiling void main()\n"
		                   "s (4, 20) : Error   : Illegal call to private method 'void C::func()'\n" )
		{
			printf("%s", bout.buffer.c_str());
			TEST_FAILED;
		}

		engine->Release();
	}

	// Test private methods that return a value
	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(CBufferedOutStream, Callback), &bout, asCALL_THISCALL);
		engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);

		const char *script = "class C { \n"
			"  int a(int i) { return ABS(i); } \n"
			"  private int ABS(int i) \n"
			"  { \n"
			"    if(i <= 0) return (-1 * i); \n"
			"    else return i; \n"
			"  } \n"
			"} \n";

		mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
		mod->AddScriptSection("s", script);

		bout.buffer = "";
		r = mod->Build();
		if( r < 0 )
			TEST_FAILED;

		if( bout.buffer != "" )
		{
			printf("%s", bout.buffer.c_str());
			TEST_FAILED;
		}

		r = ExecuteString(engine, "C c; assert( c.a(-10) == 10 );", mod);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;

		engine->Release();
	}

	// Test private methods with inheritance
	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(CBufferedOutStream, Callback), &bout, asCALL_THISCALL);
		engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);

		const char *script = 
			"bool alreadyCalled = false; \n"
			"class CBar \n"
			"{ \n"
			" CBar() \n"
			" { \n"
			"  assert(alreadyCalled == false); \n"
			"  alreadyCalled = true; \n"
			" } \n"
			" void Foo() \n"
			" { \n"
			" } \n"
			"}; \n"
			"class CDerivedBar : CBar \n"
			"{ \n"
			" CDerivedBar() \n"
			" { \n"
			" } \n"
			" private void ImNotAnOverrideOfTheBaseClass() \n"
			" { \n"
			" } \n"
			" private void Foo() \n" 
			" { \n"
			" } \n"
			"}; \n";

		asIScriptModule *mod = engine->GetModule("t", asGM_ALWAYS_CREATE);
		mod->AddScriptSection("script", script);
		mod->Build();

		asIScriptContext *ctx = engine->CreateContext();
		r = ExecuteString(engine, "CDerivedBar bar; bar.Foo(); ", mod, ctx);
		if( r != asEXECUTION_FINISHED )
		{
			if( r == asEXECUTION_EXCEPTION )
				PrintException(ctx, true);
			TEST_FAILED;
		}
		ctx->Release();
 
		engine->Release();
	}

	// Default constructor and opAssign shouldn't be provided if a non-default constructor is implemented
	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(CBufferedOutStream, Callback), &bout, asCALL_THISCALL);

		const char *script = 
			"class CBar \n"
			"{ \n"
			" CBar(int a) {}\n"
			"}; \n"
			"void func() \n"
			"{ \n"
			"  CBar a; \n" // not ok
			"  CBar b(1); \n" // ok
			"  CBar c = CBar(1); \n" // not ok
			"  b = b; \n" // not ok
			"  CBar d(CBar()); \n" // not ok
			"}; \n";

		asIScriptModule *mod = engine->GetModule("t", asGM_ALWAYS_CREATE);
		mod->AddScriptSection("script", script);

		bout.buffer = "";
		r = mod->Build();
		if( r >= 0 )
			TEST_FAILED;

		if( bout.buffer != "script (5, 1) : Info    : Compiling void func()\n"
						   "script (7, 8) : Error   : No default constructor for object of type 'CBar'.\n"
						   "script (9, 8) : Error   : No default constructor for object of type 'CBar'.\n"
						   "script (9, 8) : Error   : There is no copy operator for the type 'CBar' available.\n"
						   "script (10, 5) : Error   : There is no copy operator for the type 'CBar' available.\n"
						   "script (11, 10) : Error   : No matching signatures to 'CBar()'\n"
						   "script (11, 10) : Info    : Candidates are:\n"
						   "script (11, 10) : Info    : CBar@ CBar(int)\n" )
		{
			printf("%s", bout.buffer.c_str());
			TEST_FAILED;
		}
 
		engine->Release();
	}

	// Success
	return fail;
}
コード例 #11
0
ファイル: test_dump.cpp プロジェクト: quarnster/angelscript
bool Test()
{
    bool fail = false;
    int r;
    COutStream out;

    const char *script =
        "void Test() {} \n"
        "class A : I { void i(float) {} void a(int) {} float f; } \n"
        "class B : A { B(int) {} } \n"
        "interface I { void i(float); } \n"
        "float a; \n"
        "const float aConst = 3.141592f; \n"
        "I@ i; \n"
        "enum E { eval = 0, eval2 = 2 } \n"
        "E e; \n"
        "typedef float real; \n"
        "real pi = 3.14f; \n"
        "import void ImpFunc() from \"mod\"; \n";

    asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
    engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);

    RegisterScriptArray(engine, true);
    RegisterStdString(engine);

    float f;
    engine->RegisterTypedef("myFloat", "float");
    engine->RegisterGlobalProperty("myFloat f", &f);
    engine->RegisterGlobalProperty("const float myConst", &f);
    engine->RegisterGlobalFunction("void func(int &in)", asFUNCTION(0), asCALL_GENERIC);

    engine->BeginConfigGroup("test");
    engine->RegisterGlobalFunction("void func2()", asFUNCTION(0), asCALL_GENERIC);
    engine->EndConfigGroup();

    engine->RegisterEnum("myEnum");
    engine->RegisterEnumValue("myEnum", "value1", 1);
    engine->RegisterEnumValue("myEnum", "value2", 2);

    engine->RegisterFuncdef("void Callback(int a, int b)");

    engine->RegisterInterface("MyIntf");
    engine->RegisterInterfaceMethod("MyIntf", "void func() const");

    asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE);

    mod->AddScriptSection("script", script);
    r = mod->Build();
    if( r < 0 )
        TEST_FAILED;

    WriteConfigToFile(engine, "AS_DEBUG/config.txt");

    DumpModule(mod);

    // Save/Restore the bytecode and then test again for the loaded bytecode
    CBytecodeStream stream(__FILE__"1");
    mod->SaveByteCode(&stream);

    mod = engine->GetModule("2", asGM_ALWAYS_CREATE);
    mod->LoadByteCode(&stream);

    DumpModule(mod);

    engine->Release();

    return fail;
}
コード例 #12
0
ファイル: test_unsaferef.cpp プロジェクト: Kaperstone/warsow
bool Test()
{
	bool fail = false;
	int r;

	COutStream out;
	CBufferedOutStream bout;

 	asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
	engine->SetEngineProperty(asEP_ALLOW_UNSAFE_REFERENCES, 1);
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
	RegisterScriptArray(engine, true);
	RegisterScriptString(engine);

	r = engine->RegisterGlobalFunction("void Assert(bool)", asFUNCTION(Assert), asCALL_GENERIC); assert( r >= 0 );

	asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection(TESTNAME, script1);
	r = mod->Build();
	if( r < 0 )
	{
		TEST_FAILED;
		printf("%s: Failed to compile the script\n", TESTNAME);
	}
	asIScriptContext *ctx = engine->CreateContext();
	r = ExecuteString(engine, "Test()", mod, ctx);
	if( r != asEXECUTION_FINISHED )
	{
		TEST_FAILED;
		printf("%s: Execution failed: %d\n", TESTNAME, r);
	}

	if( ctx ) ctx->Release();

	engine->Release();

	// Test value class with unsafe ref
	{
		asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetEngineProperty(asEP_ALLOW_UNSAFE_REFERENCES, 1);
		engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
		RegisterScriptMath3D(engine);

		asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
		mod->AddScriptSection(TESTNAME, 
			"class Good \n"
			"{ \n"
			"  vector3 _val; \n"
			"  Good(const vector3& in val) \n"
			"  { \n"
			"    _val = val; \n"
			"  }  \n"
			"};  \n"
			"class Bad  \n"
			"{  \n"
			"  vector3 _val;  \n"
			"  Bad(const vector3& val)  \n"
			"  {  \n"
			"    _val = val;  \n"
			"  }  \n"
			"}; \n"
			"void test()  \n"
			"{ \n"
			"  // runs fine  \n"
			"  for (int i = 0; i < 2; i++)  \n"
			"    Good(vector3(1, 2, 3));  \n"
			"  // causes vm stack corruption  \n"
			"  for (int i = 0; i < 2; i++)  \n"
			"    Bad(vector3(1, 2, 3));  \n"
			"} \n");

		r = mod->Build();
		if( r < 0 )
			TEST_FAILED;

		r = ExecuteString(engine, "test()", mod);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;

		engine->Release();
	}

	// Test ref to primitives
	{
		bout.buffer = "";
		asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetEngineProperty(asEP_ALLOW_UNSAFE_REFERENCES, 1);
		engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL);

		asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
		mod->AddScriptSection(TESTNAME, 
			"void func(){ \n"
			"  float a; \n"
			"  uint8 b; \n"
			"  int c; \n"
			"  funcA(c, a, b); \n"
			"} \n"
			"void funcA(float& a, uint8& b, int& c) {} \n");

		r = mod->Build();
		if( r >= 0 )
			TEST_FAILED;

		if( bout.buffer != "TestUnsafeRef (1, 1) : Info    : Compiling void func()\n"
		                   "TestUnsafeRef (5, 3) : Error   : No matching signatures to 'funcA(int, float, uint8)'\n"
		                   "TestUnsafeRef (5, 3) : Info    : Candidates are:\n"
		                   "TestUnsafeRef (5, 3) : Info    : void funcA(float&inout, uint8&inout, int&inout)\n" )
		{
			printf("%s", bout.buffer.c_str());
			TEST_FAILED;
		}

		engine->Release();
	}

	// Test problem found by TheAtom
	// Passing an inout reference to a handle to a function wasn't working properly
	{
		bout.buffer = "";
		asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetEngineProperty(asEP_ALLOW_UNSAFE_REFERENCES, 1);
		engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL);
		engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);

		asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
		mod->AddScriptSection(TESTNAME, 
			"class T { int a; } \n"
			"void f(T@& p) { \n"
			"  T t; \n"
			"  t.a = 42; \n"
			"  @p = t; \n" // or p=t; in which case t is copied
			"} \n");

		r = mod->Build();
		if( r < 0 )
			TEST_FAILED;

		if( bout.buffer != "" )
		{
			printf("%s", bout.buffer.c_str());
			TEST_FAILED;
		}

		r = ExecuteString(engine, "T @t; f(t); assert( t.a == 42 );\n", mod);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;

		engine->Release();		
	}

	// Success
	return fail;
}
コード例 #13
0
bool Test()
{
	if( strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY") )
	{
		// Skipping this due to not supporting native calling conventions
		printf("Skipped due to AS_MAX_PORTABILITY\n");
		return false;
	}

	bool fail = false;
	int r;
	int suspendId, exceptionId;

 	asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);

	engine->RegisterObjectType("Object", sizeof(CObject), asOBJ_VALUE | asOBJ_APP_CLASS_CD);	
	r = engine->RegisterObjectType("RefObj", sizeof(CRefObject), asOBJ_REF); assert(r >= 0);
	if( strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY") )
	{
		engine->RegisterObjectBehaviour("Object", asBEHAVE_CONSTRUCT, "void f(int)", asFUNCTION(Construct2), asCALL_GENERIC);
		engine->RegisterObjectBehaviour("Object", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(Construct_gen), asCALL_GENERIC);
		engine->RegisterObjectBehaviour("Object", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(Destruct_gen), asCALL_GENERIC);
		engine->RegisterObjectMethod("Object", "Object &opAssign(const Object &in)", asFUNCTION(Assign_gen), asCALL_GENERIC);
		r = engine->RegisterObjectBehaviour("RefObj", asBEHAVE_FACTORY, "RefObj@ f()", asFUNCTION(RefObjFactory_gen), asCALL_GENERIC); assert(r >= 0);
		r = engine->RegisterObjectBehaviour("RefObj", asBEHAVE_ADDREF, "void f()", asFUNCTION(AddRef_gen), asCALL_GENERIC); assert(r >= 0);
		r = engine->RegisterObjectBehaviour("RefObj", asBEHAVE_RELEASE, "void f()", asFUNCTION(Release_gen), asCALL_GENERIC); assert(r >= 0);
		engine->RegisterGlobalFunction("void RaiseException()", asFUNCTION(RaiseException), asCALL_GENERIC);
		suspendId   = engine->RegisterGlobalFunction("Object SuspendObj()", asFUNCTION(SuspendObj_gen), asCALL_GENERIC);
		exceptionId = engine->RegisterGlobalFunction("Object ExceptionObj()", asFUNCTION(ExceptionObj_gen), asCALL_GENERIC);
		engine->RegisterGlobalFunction("RefObj@ ExceptionHandle()", asFUNCTION(ExceptionHandle_gen), asCALL_GENERIC);
	}
	else
	{
		engine->RegisterObjectBehaviour("Object", asBEHAVE_CONSTRUCT, "void f(int)", asFUNCTION(Construct2), asCALL_GENERIC);
		engine->RegisterObjectBehaviour("Object", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(Construct), asCALL_CDECL_OBJLAST);
		engine->RegisterObjectBehaviour("Object", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(Destruct), asCALL_CDECL_OBJLAST);
		engine->RegisterObjectMethod("Object", "Object &opAssign(const Object &in)", asFUNCTION(Assign_gen), asCALL_GENERIC);
		r = engine->RegisterObjectBehaviour("RefObj", asBEHAVE_FACTORY, "RefObj@ f()", asFUNCTION(RefObjFactory), asCALL_CDECL); assert(r >= 0);
		r = engine->RegisterObjectBehaviour("RefObj", asBEHAVE_ADDREF, "void f()", asMETHOD(CRefObject, AddRef), asCALL_THISCALL); assert(r >= 0);
		r = engine->RegisterObjectBehaviour("RefObj", asBEHAVE_RELEASE, "void f()", asMETHOD(CRefObject, Release), asCALL_THISCALL); assert(r >= 0);
		engine->RegisterGlobalFunction("void RaiseException()", asFUNCTION(RaiseException), asCALL_CDECL);
		suspendId   = engine->RegisterGlobalFunction("Object SuspendObj()", asFUNCTION(SuspendObj), asCALL_CDECL);
		exceptionId = engine->RegisterGlobalFunction("Object ExceptionObj()", asFUNCTION(ExceptionObj), asCALL_CDECL);
		engine->RegisterGlobalFunction("RefObj@ ExceptionHandle()", asFUNCTION(ExceptionHandle), asCALL_CDECL);
	}



	COutStream out;

	asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection(TESTNAME, script1, strlen(script1), 0);
	mod->AddScriptSection(TESTNAME, script2, strlen(script2), 0);
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
	r = mod->Build();
	if( r < 0 )
	{
		TEST_FAILED;
		printf("%s: Failed to compile the script\n", TESTNAME);
	}

	// The object has been initialized
	r = ExecuteString(engine, "Test1()", mod);
	if( r != asEXECUTION_EXCEPTION )
	{
		printf("%s: Failed\n", TESTNAME);
		TEST_FAILED;
	}

	// The object has not yet been initialized
	r = ExecuteString(engine, "Test2()", mod);
	if( r != asEXECUTION_EXCEPTION )
	{
		printf("%s: Failed\n", TESTNAME);
		TEST_FAILED;
	}

	// An object has been initialized and passed by value to function that throws exception
	r = ExecuteString(engine, "Test3()", mod);
	if( r != asEXECUTION_EXCEPTION )
	{
		printf("%s: Failed\n", TESTNAME);
		TEST_FAILED;
	}

	// An object has been initialized and passed by value to a function, but 
	// the function cannot be called due to the stack being full
	engine->SetEngineProperty(asEP_MAX_STACK_SIZE, sizeof(void*));
	r = ExecuteString(engine, "Test3()", mod);
	if( r != asEXECUTION_EXCEPTION )
	{
		printf("%s: Failed\n", TESTNAME);
		TEST_FAILED;
	}

	// An object is allocated and initialized with a call to 
	// a function that returns an object by value. The function 
	// suspends the thread. The context is then aborted.
	asIScriptContext *ctx = engine->CreateContext();
	engine->SetEngineProperty(asEP_MAX_STACK_SIZE, 0);
	r = ExecuteString(engine, "Test4()", mod, ctx);
	if( r != asEXECUTION_SUSPENDED )
	{
		printf("%s: Failed\n", TESTNAME);
		TEST_FAILED;
	}
	ctx->Abort();
	ctx->Release();

	// An object is allocated and initialized with a call to 
	// a function that returns an object by value. The function 
	// sets a script exception.
	r = ExecuteString(engine, "Test5()", mod);
	if( r != asEXECUTION_EXCEPTION )
	{
		printf("%s: Failed\n", TESTNAME);
		TEST_FAILED;
	}

	// The object constructor sets the exception
	r = ExecuteString(engine, "Test6()", mod);
	if( r != asEXECUTION_EXCEPTION )
	{
		printf("%s: Failed\n", TESTNAME);
		TEST_FAILED;
	}

	// A function that is supposed to return a handle sets an exception
	r = ExecuteString(engine, "Test7()", mod);
	if( r != asEXECUTION_EXCEPTION )
	{
		printf("%s: Failed\n", TESTNAME);
		TEST_FAILED;
	}

    // Attempt to call method on null class pointer
	mod->AddScriptSection("script", script3, strlen(script3));
	r = mod->Build();
	if( r < 0 ) TEST_FAILED;
	r = ExecuteString(engine, "calc()", mod);
	if( r != asEXECUTION_EXCEPTION )
	{
		printf("%s: Failed\n", TESTNAME);
		TEST_FAILED;
	}

	// Exception happens after value object has already been destroyed
	r = ExecuteString(engine, "{\n"
		                      "  Object o;\n"
                              "}\n"
							  "RaiseException();");
	if( r != asEXECUTION_EXCEPTION )
		TEST_FAILED;

	// Exception happens after the value object has been destroyed and, 
	// the same position would also be used again after the exception
	r = ExecuteString(engine, "{ Object o; } \n"
		                      "RaiseException(); \n"
							  "Object o; \n");
	if( r != asEXECUTION_EXCEPTION )
		TEST_FAILED;

	// The code has two places where the object is destroyed, one in the if case, and 
	// and one at the end of the function. If the code doesn't go in to the if case,
	// and the exception happens afterwards, the exception handler must not think the
	// object was already destroyed.
	r = ExecuteString(engine, "Object o; bool a = false; \n"
		                      "if( a ) return; \n"
							  "RaiseException(); \n");
	if( r != asEXECUTION_EXCEPTION )
		TEST_FAILED;

	// Calling a function that returns an object directly must release the object upon releasing the context
	ctx = engine->CreateContext();
	ctx->Prepare(engine->GetFunctionById(suspendId));
	ctx->Execute();
	ctx->Release();

	// Calling a function that returns an object but raised an exception shouldn't try to destroy the object
	ctx = engine->CreateContext();
	ctx->Prepare(engine->GetFunctionById(exceptionId));
	ctx->Execute();
	ctx->Release();

 	engine->Release();

	// Test proper release of function pointers on exception
	{
		COutStream out;

		asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);

		engine->RegisterGlobalFunction("void RaiseException()", asFUNCTION(RaiseException), asCALL_CDECL);

		asIScriptModule *mod = engine->GetModule("mod", asGM_ALWAYS_CREATE);
		mod->AddScriptSection("script", 
			"funcdef void func_t(); \n"
			"void main() \n"
			"{ \n"
			"  func_t @f = main; \n"
			"  RaiseException(); \n"
			"} \n");

		r = mod->Build();
		if( r < 0 )
			TEST_FAILED;

		r = ExecuteString(engine, "main()", mod);
		if( r != asEXECUTION_EXCEPTION )
			TEST_FAILED;
		
		engine->Release();
	}

	// Test problem reported by FDsagizi
	// http://www.gamedev.net/topic/631801-pod-type-and-null-pointer-exception-bug-with-call-destructor/
	{
		COutStream out;
		asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);

		engine->RegisterObjectType("TestLink", sizeof(CObject), asOBJ_VALUE | asOBJ_APP_CLASS_CD);	
		engine->RegisterObjectBehaviour("TestLink", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(Construct), asCALL_CDECL_OBJLAST);
		engine->RegisterObjectBehaviour("TestLink", asBEHAVE_CONSTRUCT, "void f(const TestLink &in)", asFUNCTION(CopyConstruct), asCALL_CDECL_OBJLAST);
		engine->RegisterObjectBehaviour("TestLink", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(Destruct), asCALL_CDECL_OBJLAST);

		asIScriptModule *mod = engine->GetModule("mod", asGM_ALWAYS_CREATE);
		mod->AddScriptSection("test",
			"class Object3 \n"
			"{ \n"
			"    Object3( TestLink str ) \n"
			"    { \n"
			"        Object3 @null_object = null; \n"
			"        null_object.Do(); \n"
			"    } \n"
			"    void Do() {} \n"
			"} \n"
			"void Main() \n"
			"{ \n"
			"   Object3 @oo = Object3( TestLink() ); \n"
			"} \n");
		r = mod->Build();
		if( r < 0 )
			TEST_FAILED;

		CObject_constructCount = 0;
		CObject_destructCount = 0;

		asIScriptContext *ctx = engine->CreateContext();
		r = ExecuteString(engine, "Main()", mod, ctx);
		if( r != asEXECUTION_EXCEPTION )
			TEST_FAILED;

		if( CObject_constructCount != 2 ||
			CObject_destructCount != 1 )
			TEST_FAILED;

		ctx->Release();

		if( CObject_constructCount != 2 ||
			CObject_destructCount != 2 )
			TEST_FAILED;

		CBytecodeStream stream(__FILE__"1");
		r = mod->SaveByteCode(&stream);
		if( r < 0 )
			TEST_FAILED;
		
		r = mod->LoadByteCode(&stream); 
		if( r < 0 )
			TEST_FAILED;

		CObject_constructCount = 0;
		CObject_destructCount = 0;

		ctx = engine->CreateContext();
		r = ExecuteString(engine, "Main()", mod, ctx);
		if( r != asEXECUTION_EXCEPTION )
			TEST_FAILED;

		if( CObject_constructCount != 2 ||
			CObject_destructCount != 1 )
			TEST_FAILED;

		ctx->Release();

		engine->Release();
	}

	// Test failure when allocating very large array
	{
		COutStream out;
		asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);

		RegisterScriptArray(engine, true);

		asIScriptModule *mod = engine->GetModule("mod", asGM_ALWAYS_CREATE);
		mod->AddScriptSection("script",
			"class test\n"
			"{\n"
			"  double x;\n"
			"  double y;\n"
			"  double z;\n"
			"  double other;\n"
			"}\n"
			"void main()\n"
			"{\n"
			"  test[] list(1000000000);\n"
			"}\n");

		r = mod->Build();
		if( r < 0 )
			TEST_FAILED;

		r = ExecuteString(engine, "main()", mod);
		if( r != asEXECUTION_EXCEPTION )
			TEST_FAILED;

		engine->Release();
	}

	// Success
	return fail;
}
コード例 #14
0
bool Test()
{
	bool fail = Test2();
	int r;

	asIScriptModule *mod = 0;

	asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);

	RegisterScriptString_Generic(engine);

	engine->RegisterGlobalFunction("void Assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);

	COutStream out;
	CBufferedOutStream bout;
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);

	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection(TESTNAME, script1);
	r = mod->Build();
	if( r < 0 ) fail = true;

	// Verify that GetObjectTypeByIndex recognizes the script class
	if( mod->GetObjectTypeCount() != 1 )
		fail = true;
	asIObjectType *type = mod->GetObjectTypeByIndex(0);
	if( strcmp(type->GetName(), "Test") != 0 )
		fail = true;

	asIScriptContext *ctx = 0;
	r = engine->ExecuteString(0, "TestStruct()", &ctx);
	if( r != asEXECUTION_FINISHED ) 
	{
		if( r == asEXECUTION_EXCEPTION ) PrintException(ctx);
		fail = true;
	}
	if( ctx ) ctx->Release();

	bout.buffer = "";
	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection(TESTNAME, script2);
	engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL);
	r = mod->Build();
	if( r >= 0 || bout.buffer != "TestScriptStruct (3, 4) : Error   : Class properties cannot be declared as const\n" ) fail = true;

	mod->AddScriptSection(TESTNAME, script3);
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
	r = mod->Build();
	if( r < 0 ) fail = true;
	r = engine->ExecuteString(0, "TestArrayInStruct()");
	if( r != 0 ) fail = true;

	mod->AddScriptSection(TESTNAME, script4, strlen(script4), 0);
	r = mod->Build();
	if( r < 0 ) fail = true;
	r = engine->ExecuteString(0, "Test()");
	if( r != 0 ) fail = true;

	bout.buffer = "";
	mod->AddScriptSection(TESTNAME, script5, strlen(script5), 0);
	engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL);
	r = mod->Build();
	if( r >= 0 || bout.buffer != 
		"TestScriptStruct (2, 7) : Error   : Name conflict. 'A' is a class.\n"
		"TestScriptStruct (6, 9) : Error   : Name conflict. 'a' is an object property.\n" ) fail = true;

	bout.buffer = "";
	mod->AddScriptSection(TESTNAME, script6, strlen(script6), 0);
	r = mod->Build();
	if( r >= 0 || bout.buffer !=
		"TestScriptStruct (1, 7) : Error   : Illegal member type\n"
		"TestScriptStruct (5, 7) : Error   : Illegal member type\n" ) fail = true;

	mod->AddScriptSection(TESTNAME, script7, strlen(script7), 0);
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
	r = mod->Build();
	if( r < 0 ) fail = true;
	r = engine->ExecuteString(0, "TestHandleInStruct()", &ctx);
	if( r != 0 )
	{
		if( r == asEXECUTION_EXCEPTION )
		{
			printf("%s\n", ctx->GetExceptionString());
		}
		fail = true;
	}
	if( ctx ) ctx->Release();

	mod->AddScriptSection(TESTNAME, script8, strlen(script8), 0);
	r = mod->Build();
	if( r < 0 ) fail = true;
	r = engine->ExecuteString(0, "TestHandleInStruct2()");
	if( r != 0 ) fail = true;

	mod->AddScriptSection(TESTNAME, script9, strlen(script9), 0);
	r = mod->Build();
	if( r < 0 ) fail = true;
	r = engine->ExecuteString(0, "Test()");
	if( r != 0 ) fail = true;

	bout.buffer = "";
	mod->AddScriptSection(TESTNAME, script10, strlen(script10), 0);
	engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL);
	r = mod->Build();
	if( r >= 0 ) fail = true;
	if( bout.buffer != "TestScriptStruct (1, 7) : Error   : Illegal member type\n" ) fail = true;

	bout.buffer = "";
	mod->AddScriptSection(TESTNAME, script11, strlen(script11), 0);
	r = mod->Build();
	if( r >= 0 ) fail = true;
	if( bout.buffer != "TestScriptStruct (5, 1) : Info    : Compiling void Test()\nTestScriptStruct (9, 11) : Error   : Reference is read-only\n" ) fail = true;

	mod->AddScriptSection(TESTNAME, script12, strlen(script12), 0);
	mod->AddScriptSection(TESTNAME, script13, strlen(script13), 0);
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
	r = mod->Build();
	if( r < 0 ) fail = true;

	// The garbage collection doesn't have to be invoked immediately. Modules
	// can even be discarded before calling the garbage collector.
	engine->GarbageCollect();
	
	// Make sure it is possible to copy a script class that contains an object handle
	mod->AddScriptSection(TESTNAME, script14, strlen(script14), 0);
	r = mod->Build();
	if( r < 0 ) fail = true;
	r = engine->ExecuteString(0, "A a; B b; @a.b = @b; b.val = 1; A a2; a2 = a; Assert(a2.b.val == 1);");
	if( r != asEXECUTION_FINISHED )
		fail = true;

	// Make sure it is possible to copy a script class that contains an array
	const char *script15 = 
		"class Some \n"
        "{ \n"
        "    int[] i; // need be array \n"
        "} \n"
        "void main() \n"
        "{ \n"
        "    Some e; \n"
        "    e=some(e); // crash \n"
        "} \n"
        "Some@ some(Some@ e) \n"
        "{ \n"
        "    return e; \n"
        "} \n";

	mod->AddScriptSection(TESTNAME, script15);
	r = mod->Build();
	if( r < 0 ) fail = true;
	r = engine->ExecuteString(0, "main()");
	if( r != asEXECUTION_FINISHED )
		fail = true;

	engine->Release();

	// Success
	return fail;
}
コード例 #15
0
bool Test2()
{
	bool fail = false;

	int r;
	COutStream out;
	CBufferedOutStream bout;

	asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
	engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);
	engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);

	// Try calling a const method on a const object (success)
	const char *script = 
	"class MyType                  \n"
	"{                             \n"
	"   int val;                   \n"
	"   void TestConst() const     \n"
	"   {                          \n"
	"      assert(val == 5);       \n"
	"   }                          \n"
	"}                             \n"
	"void Func(const MyType &in a) \n"
	"{                             \n"
	"   a.TestConst();             \n"
	"}                             \n";

	asIScriptModule *mod = engine->GetModule("module", asGM_ALWAYS_CREATE);
	mod->AddScriptSection("script", script, strlen(script));
	r = mod->Build();
	if( r < 0 )
	{
		TEST_FAILED;
	}

	// Try calling a non-const method on a const object (should fail)
	script =
	"class MyType                  \n"
	"{                             \n"
	"   int val;                   \n"
	"   void TestConst()           \n"
	"   {                          \n"
	"      assert(val == 5);       \n"
	"   }                          \n"
	"}                             \n"
	"void Func(const MyType &in a) \n"
	"{                             \n"
	"   a.TestConst();             \n"
	"}                             \n";

	engine->SetMessageCallback(asMETHOD(CBufferedOutStream, Callback), &bout, asCALL_THISCALL);

	bout.buffer = "";
	mod->AddScriptSection("script", script, strlen(script));
	r = mod->Build();
	if( r >= 0 )
	{
		TEST_FAILED;
	}
	if( bout.buffer != "script (9, 1) : Info    : Compiling void Func(const MyType&in)\n"
					   "script (11, 6) : Error   : No matching signatures to 'MyType::TestConst() const'\n" )
	{
		printf("%s", bout.buffer.c_str());
		TEST_FAILED;
	}

	// Try modifying self in a const method (should fail)
	script = 
	"class MyType                  \n"
	"{                             \n"
	"   int val;                   \n"
	"   void TestConst() const     \n"
	"   {                          \n"
	"      val = 5;                \n"
	"   }                          \n"
	"}                             \n";
	
	bout.buffer = "";
	mod->AddScriptSection("script", script, strlen(script));
	r = mod->Build();
	if( r >= 0 )
	{
		TEST_FAILED;
	}
	if( bout.buffer != "script (4, 4) : Info    : Compiling void MyType::TestConst() const\n"
					   "script (6, 11) : Error   : Reference is read-only\n" )
	{
		printf("%s", bout.buffer.c_str());
		TEST_FAILED;
	}

	// Try modifying self via 'this' in a const method (should fail)
	script = 
	"class MyType                  \n"
	"{                             \n"
	"   int val;                   \n"
	"   void TestConst() const     \n"
	"   {                          \n"
	"      this.val = 5;           \n"
	"   }                          \n"
	"}                             \n";
	
	bout.buffer = "";
	mod->AddScriptSection("script", script, strlen(script));
	r = mod->Build();
	if( r >= 0 )
	{
		TEST_FAILED;
	}
	if( bout.buffer != "script (4, 4) : Info    : Compiling void MyType::TestConst() const\n"
					   "script (6, 16) : Error   : Reference is read-only\n" )
	{
		printf("%s", bout.buffer.c_str());
		TEST_FAILED;
	}

	engine->Release();

	return fail;
}
コード例 #16
0
bool Test()
{
	RET_ON_MAX_PORT

	bool fail = Test2();
	int r;
	int funcId;

 	asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);

	engine->RegisterGlobalFunction("void Assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);

	engine->RegisterObjectType("Object", sizeof(CObject), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS_CD);	
	engine->RegisterObjectBehaviour("Object", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(Construct), asCALL_CDECL_OBJLAST);
	engine->RegisterObjectBehaviour("Object", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(Destruct), asCALL_CDECL_OBJLAST);
	funcId = engine->RegisterObjectMethod("Object", "void Set(int)", asMETHOD(CObject, Set), asCALL_THISCALL);
	engine->RegisterObjectMethod("Object", "int Get()", asMETHOD(CObject, Get), asCALL_THISCALL);
	engine->RegisterObjectProperty("Object", "int val", asOFFSET(CObject, val));
	r = engine->RegisterObjectMethod("Object", "int &GetRef()", asMETHOD(CObject, GetRef), asCALL_THISCALL); assert( r >= 0 );

	engine->RegisterObjectType("Object2", sizeof(CObject2), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS);
	engine->RegisterObjectBehaviour("Object2", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(Construct2), asCALL_CDECL_OBJLAST);
	engine->RegisterObjectBehaviour("Object2", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(Destruct2), asCALL_CDECL_OBJLAST);
	engine->RegisterObjectProperty("Object2", "Object obj", asOFFSET(CObject2, obj));

	engine->RegisterGlobalFunction("Object TestReturnObject()", asFUNCTION(TestReturnObject), asCALL_CDECL);
	engine->RegisterGlobalFunction("Object &TestReturnObjectRef()", asFUNCTION(TestReturnObjectRef), asCALL_CDECL);
	engine->RegisterGlobalFunction("void TestSysArgVal(Object)", asFUNCTION(TestSysArgVal), asCALL_CDECL);
	engine->RegisterGlobalFunction("void TestSysArgRef(Object &out)", asFUNCTION(TestSysArgRef), asCALL_CDECL);

	engine->RegisterGlobalProperty("Object obj", &obj);

	// Test objects with no default constructor
	engine->RegisterObjectType("ObjNoConstruct", sizeof(int), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_PRIMITIVE);

	COutStream out;

	asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection(TESTNAME, script1, strlen(script1), 0);
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
	r = mod->Build();
	if( r < 0 )
	{
		TEST_FAILED;
		PRINTF("%s: Failed to compile the script\n", TESTNAME);
	}

	asIScriptContext *ctx = engine->CreateContext();
	r = ExecuteString(engine, "TestObject()", mod, ctx);
	if( r != asEXECUTION_FINISHED )
	{
		if( r == asEXECUTION_EXCEPTION )
			PRINTF("%s", GetExceptionInfo(ctx).c_str());

		PRINTF("%s: Failed to execute script\n", TESTNAME);
		TEST_FAILED;
	}
	if( ctx ) ctx->Release();

	ExecuteString(engine, "ObjNoConstruct a; a = ObjNoConstruct();");
	if( r != 0 )
	{
		TEST_FAILED;
		PRINTF("%s: Failed\n", TESTNAME);
	}

	CBufferedOutStream bout;
	engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL);
	r = ExecuteString(engine, "Object obj; float r = 0; obj = r;");
	if( r >= 0 || bout.buffer != "ExecuteString (1, 32) : Error   : Can't implicitly convert from 'float' to 'const Object&'.\n" )
	{
		PRINTF("%s: Didn't fail to compile as expected\n", TESTNAME);
		PRINTF("%s", bout.buffer.c_str());
		TEST_FAILED;
	}

	// Verify that the registered types can be enumerated
	int count = engine->GetObjectTypeCount();
	if( count != 3 )
		TEST_FAILED;
	asIObjectType *type = engine->GetObjectTypeByIndex(0);
	if( strcmp(type->GetName(), "Object") != 0 )
		TEST_FAILED;
	
	// Test calling an application registered method directly with context
	ctx = engine->CreateContext();
	ctx->Prepare(engine->GetFunctionById(funcId));
	ctx->SetObject(&obj);
	ctx->SetArgDWord(0, 42);
	r = ctx->Execute();
	if( r != asEXECUTION_FINISHED )
		TEST_FAILED;
	if( obj.val != 42 )
		TEST_FAILED;
	ctx->Release();

	// Test GetObjectTypeCount for the module
	const char *script2 = "class ScriptType {}";
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection("script", script2);
	mod->Build();

	count = engine->GetObjectTypeCount();
	if( count != 3 )
		TEST_FAILED;

	count = engine->GetModule(0)->GetObjectTypeCount();
	if( count != 1 )
		TEST_FAILED;


	// Test assigning value to reference returned by class method where the reference points to a member of the class
	// This test attempts to verify that the object isn't freed before the reference goes out of scope.
	r = ExecuteString(engine, "Object o; o.GetRef() = 10;");
	if( r != asEXECUTION_FINISHED )
	{
		TEST_FAILED;
	}

	engine->SetMessageCallback(asMETHOD(CBufferedOutStream, Callback), &bout, asCALL_THISCALL);
	bout.buffer = "";
	r = ExecuteString(engine, "Object().GetRef() = 10;");
	if( r != asEXECUTION_FINISHED )
	{
		TEST_FAILED;
	}
	if( bout.buffer != "" )
	{
		PRINTF("%s", bout.buffer.c_str());
		TEST_FAILED;
	}

	// TODO: Make the same test with the index operator

	engine->Release();

	// Success
	return fail;
}
コード例 #17
0
bool Test()
{
	bool fail = false;
	int r;
	CBufferedOutStream bout;
	COutStream out;
	asIScriptModule *mod;
	asIScriptEngine *engine;

	// Test auto when it is not possible to determine type from expression
	// http://www.gamedev.net/topic/677273-various-unexpected-behaviors-of-angelscript-2310/
	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(CBufferedOutStream, Callback), &bout, asCALL_THISCALL);
		bout.buffer = "";

		mod = engine->GetModule("Test", asGM_ALWAYS_CREATE);
		mod->AddScriptSection("test", "void func() { auto var = null; }");
		r = mod->Build();
		if (r >= 0)
			TEST_FAILED;

		if (bout.buffer != "test (1, 1) : Info    : Compiling void func()\n"
						   "test (1, 20) : Error   : Data type can't be '<null handle>'\n")
		{
			PRINTF("%s", bout.buffer.c_str());
			TEST_FAILED;
		}

		engine->Release();
	}

	// Test that anonymous functions with auto generates proper error
	// http://www.gamedev.net/topic/671632-auto-causes-crash-with-anonymous-functions/
	{
		const char *script =
			"auto g_cb2 = function() {}; \n"
			"auto @g_cb3 = function() {}; \n"
			"void test() { \n"
			" auto cb2 = function() {}; \n"
			" auto @cb3 = function() {}; \n"
			"} \n";

		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(CBufferedOutStream, Callback), &bout, asCALL_THISCALL);
		bout.buffer = "";

		mod = engine->GetModule("Test", asGM_ALWAYS_CREATE);
		mod->AddScriptSection("test", script);
		r = mod->Build();
		if (r >= 0)
			TEST_FAILED;

		if (bout.buffer != "test (1, 6) : Info    : Compiling <auto> g_cb2\n"
						   "test (1, 6) : Error   : Unable to resolve auto type\n"
						   "test (2, 7) : Info    : Compiling <auto>@ g_cb3\n"
						   "test (2, 7) : Error   : Unable to resolve auto type\n"
						   "test (3, 1) : Info    : Compiling void test()\n"
						   "test (4, 7) : Error   : Unable to resolve auto type\n"
						   "test (5, 8) : Error   : Unable to resolve auto type\n")
		{
			PRINTF("%s", bout.buffer.c_str());
			TEST_FAILED;
		}

		engine->Release();
	}

	//Test auto from literals
	{
		const char *script =
			"void test() {\n"
			"  auto anInt = 18; assert(anInt == 18);\n"
			"  auto aFloat = 1.24f; assert(aFloat == 1.24f);\n"
			"  auto aString = \"test\"; assert(aString == \"test\");\n"
			"}\n"
			"\n";

		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);
		RegisterStdString(engine);
		engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);

		mod = engine->GetModule("Test", asGM_ALWAYS_CREATE);
		mod->AddScriptSection("test", script);
		r = mod->Build();
		if( r < 0 )
			TEST_FAILED;

		r = ExecuteString(engine, "test();", mod);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;

		engine->Release();
	}

	//Test auto from expressions
	{
		const char *script =
			"int getInt() { return 18; }\n"
			"float getFloat() { return 18.f; }\n"
			"void test() {\n"
			"  auto anInt = getInt(); assert(anInt == 18);\n"
			"  auto aFloat = getFloat(); assert(aFloat == 18.f);\n"
			"  auto combined = anInt + aFloat; assert(combined == (18 + 18.f));\n"
			"}\n"
			"\n";

		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);
		RegisterStdString(engine);
		engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);

		mod = engine->GetModule("Test", asGM_ALWAYS_CREATE);
		mod->AddScriptSection("test", script);
		r = mod->Build();
		if( r < 0 )
			TEST_FAILED;

		r = ExecuteString(engine, "test();", mod);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;

		engine->Release();
	}

	//Test global auto
	{
		const char *script =
			"const auto aConstant = 18;\n"
			"auto str = \"some string\";\n"
			"auto concat = str + aConstant;\n"
			"void test() {\n"
			"  assert(aConstant == 18);\n"
			"  assert(str == \"some string\");\n"
			"  assert(concat == \"some string18\");\n"
			"}\n"
			"\n";

		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);
		RegisterStdString(engine);
		engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);

		mod = engine->GetModule("Test", asGM_ALWAYS_CREATE);
		mod->AddScriptSection("test", script);
		r = mod->Build();
		if( r < 0 )
			TEST_FAILED;

		r = ExecuteString(engine, "test();", mod);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;

		engine->Release();
	}

	//Test handles to auto
	{
		const char *script =
			"class Object {}\n"
			"Object obj;\n"
			"Object@ getHandleOf() { return obj; }\n"
			"Object& getReferenceOf() { return obj; }\n"
			"Object getValueOf() { return obj; }\n"
			"void test() {\n"
			"  auto copy = obj; assert(copy !is obj);\n"
			"  auto@ handle = obj; assert(handle is obj);\n"
			"  auto handleReturn = getHandleOf(); assert(handleReturn is obj);\n"
			"  auto@ explicitHandle = getHandleOf(); assert(explicitHandle is obj);\n"
			"  auto copyReturn = getReferenceOf(); assert(copyReturn !is obj);\n"
			"  auto valueReturn = getValueOf(); assert(valueReturn !is obj);\n"
			"  auto@ handleToReference = getReferenceOf(); assert(handleToReference is obj);\n"
			"  auto@ handleToCopy = getValueOf(); assert(handleToCopy !is obj);\n"
			"}\n"
			"\n";

		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);
		RegisterStdString(engine);
		engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);

		mod = engine->GetModule("Test", asGM_ALWAYS_CREATE);
		mod->AddScriptSection("test", script);
		r = mod->Build();
		if( r < 0 )
			TEST_FAILED;

		r = ExecuteString(engine, "test();", mod);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;

		engine->Release();
	}

	//Test that auto cannot be used in class bodies
	// This is because class member initialization is done inside the constructor,
	// and can access arguments from the constructor. There is no sane way to auto-resolve those.
	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(CBufferedOutStream, Callback), &bout, asCALL_THISCALL);
		bout.buffer = "";

		mod = engine->GetModule("mod1", asGM_ALWAYS_CREATE);
		mod->AddScriptSection("test",
			"class Object {\n"
			"  auto member = 1;\n"
			"}\n"
			"\n");

		r = mod->Build();
		if( r >= 0 )
			TEST_FAILED;

		if( bout.buffer != "test (2, 3) : Error   : Auto is not allowed here\n"
						   "test (3, 1) : Error   : Unexpected token '}'\n"
						   )
		{
			PRINTF("%s", bout.buffer.c_str());
			TEST_FAILED;
		}

		engine->Release();
	}

	//Test that circular autos in globals fails
	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(CBufferedOutStream, Callback), &bout, asCALL_THISCALL);
		bout.buffer = "";

		mod = engine->GetModule("mod1", asGM_ALWAYS_CREATE);
		mod->AddScriptSection("test",
			"auto x = y;"
			"auto y = x;"
			"\n");

		r = mod->Build();
		if( r >= 0 )
			TEST_FAILED;

		if( bout.buffer != "test (1, 6) : Info    : Compiling <auto> x\n"
						   "test (1, 10) : Error   : 'y' is not declared\n"
						   "test (1, 17) : Info    : Compiling <auto> y\n"
						   "test (1, 21) : Error   : 'x' is not declared\n" )
		{
			PRINTF("%s", bout.buffer.c_str());
			TEST_FAILED;
		}

		engine->Release();
	}

	// Test error when no expression is given
	// http://www.gamedev.net/topic/655641-assert-when-compiling-with-auto/
	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(CBufferedOutStream, Callback), &bout, asCALL_THISCALL);
		bout.buffer = "";

		r = ExecuteString(engine, "auto i;");
		if( r >= 0 )
			TEST_FAILED;

		if( bout.buffer != "ExecuteString (1, 6) : Error   : Unable to resolve auto type\n" )
		{
			PRINTF("%s", bout.buffer.c_str());
			TEST_FAILED;
		}

		engine->Release();
	}

	// Success
	return fail;
}
コード例 #18
0
ファイル: as.cpp プロジェクト: flickenmaste/Old_GameEngine
int as::RunApplication()
{
	int r;

	// Create the script engine
	asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
	if( engine == 0 )
	{
		cout << "Failed to create script engine." << endl;
		return -1;
	}

	// The script compiler will write any compiler messages to the callback.
	engine->SetMessageCallback(asFUNCTION(MessageCallback), 0, asCALL_CDECL);

	// Configure the script engine with all the functions, 
	// and variables that the script should be able to use.
	ConfigureEngine(engine);
	
	// Compile the script code
	r = CompileScript(engine);
	if( r < 0 )
	{
		engine->Release();
		return -1;
	}

	// Create a context that will execute the script.
	asIScriptContext *ctx = engine->CreateContext();
	if( ctx == 0 ) 
	{
		cout << "Failed to create the context." << endl;
		engine->Release();
		return -1;
	}

	// We don't want to allow the script to hang the application, e.g. with an
	// infinite loop, so we'll use the line callback function to set a timeout
	// that will abort the script after a certain time. Before executing the 
	// script the timeOut variable will be set to the time when the script must 
	// stop executing. 
	DWORD timeOut;
	r = ctx->SetLineCallback(asFUNCTION(LineCallback), &timeOut, asCALL_CDECL);
	if( r < 0 )
	{
		cout << "Failed to set the line callback function." << endl;
		ctx->Release();
		engine->Release();
		return -1;
	}

	// Find the function for the function we want to execute.
	asIScriptFunction *func = engine->GetModule(0)->GetFunctionByDecl("void printWord()");
	if( func == 0 )
	{
		cout << "The function 'void printWord()' was not found." << endl;
		ctx->Release();
		engine->Release();
		return -1;
	}

	// Prepare the script context with the function we wish to execute. Prepare()
	// must be called on the context before each new script function that will be
	// executed. Note, that if you intend to execute the same function several 
	// times, it might be a good idea to store the function returned by 
	// GetFunctionByDecl(), so that this relatively slow call can be skipped.
	r = ctx->Prepare(func);
	if( r < 0 ) 
	{
		cout << "Failed to prepare the context." << endl;
		ctx->Release();
		engine->Release();
		return -1;
	}

	// Set the timeout before executing the function. Give the function 1 sec
	// to return before we'll abort it.
	timeOut = timeGetTime() + 1000;

	// Execute the function
	cout << "Executing the script." << endl;
	cout << "---" << endl;
	r = ctx->Execute();
	cout << "---" << endl;
	if( r != asEXECUTION_FINISHED )
	{
		// The execution didn't finish as we had planned. Determine why.
		if( r == asEXECUTION_ABORTED )
			cout << "The script was aborted before it could finish. Probably it timed out." << endl;
		else if( r == asEXECUTION_EXCEPTION )
		{
			cout << "The script ended with an exception." << endl;

			// Write some information about the script exception
			asIScriptFunction *func = ctx->GetExceptionFunction();
			cout << "func: " << func->GetDeclaration() << endl;
			cout << "modl: " << func->GetModuleName() << endl;
			cout << "sect: " << func->GetScriptSectionName() << endl;
			cout << "line: " << ctx->GetExceptionLineNumber() << endl;
			cout << "desc: " << ctx->GetExceptionString() << endl;
		}
		else
			cout << "The script ended for some unforeseen reason (" << r << ")." << endl;
	}
	else
	{
		// Retrieve the return value from the context
		float returnValue = ctx->GetReturnFloat();
		cout << "The script function returned: " << returnValue << endl;
	}

	// We must release the contexts when no longer using them
	ctx->Release();

	// Release the engine
	engine->Release();

	return 0;
}
コード例 #19
0
bool Test()
{
	bool fail = false;
	int r;
	COutStream out;
	asIScriptContext *ctx;

 	asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
	
	r = engine->SetCommonObjectMemoryFunctions(ScriptAlloc, ScriptFree);
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);

	RegisterScriptString_Generic(engine);
	engine->RegisterGlobalFunction("void Assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);


	engine->AddScriptSection(0, TESTNAME, script1, strlen(script1), 0, false);
	r = engine->Build(0);
	if( r < 0 )
	{
		fail = true;
		printf("%s: Failed to compile the script\n", TESTNAME);
	}

	r = engine->ExecuteString(0, "TestArray()", &ctx);
	if( r != asEXECUTION_FINISHED )
	{
		if( r == asEXECUTION_EXCEPTION )
			PrintException(ctx);

		printf("%s: Failed to execute script\n", TESTNAME);
		fail = true;
	}
	if( ctx ) ctx->Release();

	engine->AddScriptSection(0, TESTNAME, script2, strlen(script2), 0, false);
	r = engine->Build(0);
	if( r < 0 )
	{
		fail = true;
		printf("%s: Failed to compile the script\n", TESTNAME);
	}

	r = engine->ExecuteString(0, "TestArrayException()");
	if( r != asEXECUTION_EXCEPTION )
	{
		printf("%s: No exception\n", TESTNAME);
		fail = true;
	}

	engine->AddScriptSection(0, TESTNAME, script3, strlen(script3), 0, false);
	r = engine->Build(0);
	if( r < 0 )
	{
		fail = true;
		printf("%s: Failed to compile the script\n", TESTNAME);
	}

	r = engine->ExecuteString(0, "TestArrayMulti()", &ctx);
	if( r != asEXECUTION_FINISHED )
	{
		printf("%s: Failure\n", TESTNAME);
		fail = true;
	}
	if( r == asEXECUTION_EXCEPTION )
	{
		PrintException(ctx);
	}
	if( ctx ) ctx->Release();
	ctx = 0;

	engine->AddScriptSection(0, TESTNAME, script4, strlen(script4), 0, false);
	r = engine->Build(0);
	if( r < 0 )
	{
		fail = true;
		printf("%s: Failed to compile the script\n", TESTNAME);
	}
	r = engine->ExecuteString(0, "TestArrayChar()", &ctx);
	if( r != asEXECUTION_FINISHED )
	{
		printf("%s: Failure\n", TESTNAME);
		fail = true;
	}
	if( r == asEXECUTION_EXCEPTION )
	{
		PrintException(ctx);
	}

	if( ctx ) ctx->Release();

	engine->AddScriptSection(0, TESTNAME, script5, strlen(script5), 0, false);
	r = engine->Build(0);
	if( r < 0 ) fail = true;
	r = engine->ExecuteString(0, "TestArrayInitList()", &ctx);
	if( r != asEXECUTION_FINISHED ) fail = true;
	if( r == asEXECUTION_EXCEPTION )
		PrintException(ctx);

	if( ctx ) ctx->Release();

	CBufferedOutStream bout;
	engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL);
	engine->AddScriptSection(0, TESTNAME, script6, strlen(script6), 0, false);
	r = engine->Build(0);
	if( r >= 0 ) fail = true;
	if( bout.buffer != "TestArray (1, 1) : Info    : Compiling void Test()\n"
	                   "TestArray (3, 15) : Error   : Initialization lists cannot be used with 'int[]@'\n"
	                   "TestArray (4, 16) : Error   : Initialization lists cannot be used with 'int'\n" )
		fail = true;

	engine->Release();

	// Success
	return fail;
}
コード例 #20
0
bool Test()
{
	RET_ON_MAX_PORT

	bool fail = false;
	int r;
	COutStream out;
	asIScriptEngine *engine;
	asIScriptModule *mod;
	asIScriptContext *ctx;
	CBufferedOutStream bout;
	const char *script;

	// Test invalid use of function pointer
	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(CBufferedOutStream, Callback), &bout, asCALL_THISCALL);

		bout.buffer = "";
		mod = engine->GetModule("mod", asGM_ALWAYS_CREATE);
		mod->AddScriptSection("test",
			"void func2() { \n"
			"  func; \n"
			"} \n"
			"void func() {} \n");
		r = mod->Build();
		if( r >= 0 )
			TEST_FAILED;

		if( bout.buffer != "test (1, 1) : Info    : Compiling void func2()\n"
						   "test (2, 3) : Error   : Invalid expression: ambiguous name\n" )
		{
			PRINTF("%s", bout.buffer.c_str());
			TEST_FAILED;
		}

		engine->Release();
	}

	// Test value comparison for function pointers
/*
	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);

		engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);

		mod = engine->GetModule("mod", asGM_ALWAYS_CREATE);
		mod->AddScriptSection("test",
			"funcdef void CALLBACK(); \n"
			"void func1() {} \n"
			"void func2() {} \n");
		r = mod->Build();
		if( r < 0 )
			TEST_FAILED;

		r = ExecuteString(engine, "CALLBACK@ c1 = func1, c2 = func1; \n"
								  "assert( c1 == c2 ); \n", mod);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;

		// TODO: Test that two different function pointers give false
		// TODO: Test for delegate objects

		engine->Release();
	}
*/

	// Proper error message when trying to pass class method as function pointer directly
	// http://www.gamedev.net/topic/655390-is-there-a-bug-with-function-callbacks/
	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(CBufferedOutStream, Callback), &bout, asCALL_THISCALL);
		
		bout.buffer = "";

		mod = engine->GetModule("mod", asGM_ALWAYS_CREATE);
		mod->AddScriptSection("test",
			"funcdef void CALLBACK(int); \n"
			"class Test { \n"
			"  void Init() { \n"
			"    SetCallback(MyCallback); \n" // This should fail, since delegate is necessary
			"  } \n"
			"  void MyCallback(int) {} \n"
			"} \n"
			"void SetCallback(CALLBACK @) {} \n");
		r = mod->Build();
		if( r >= 0 )
			TEST_FAILED;

		if( bout.buffer != "test (3, 3) : Info    : Compiling void Test::Init()\n"
						   "test (4, 5) : Error   : No matching signatures to 'SetCallback(Test::MyCallback)'\n"
						   "test (4, 5) : Error   : Can't pass class method as arg directly. Use a delegate object instead\n" )
		{
			PRINTF("%s", bout.buffer.c_str());
			TEST_FAILED;
		}

		engine->Release();
	}

	// opEquals with funcdef
	// http://www.gamedev.net/topic/647797-difference-between-xopequalsy-and-xy-with-funcdefs/
	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);
		engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);

		mod = engine->GetModule("mod", asGM_ALWAYS_CREATE);
		mod->AddScriptSection("test",
			"funcdef void CALLBACK(); \n"
			"class Test { \n"
			"  bool opEquals(CALLBACK @f) { \n"
			"    return f is func; \n"
			"  } \n"
			"  CALLBACK @func; \n"
			"} \n"
			"void func() {} \n");
		r = mod->Build();
		if( r < 0 )
			TEST_FAILED;

		r = ExecuteString(engine, "Test t; \n"
			                      "@t.func = func; \n"
								  "assert( t == func );", mod);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;

		mod = engine->GetModule("mod", asGM_ALWAYS_CREATE);
		mod->AddScriptSection("test",
			"funcdef void CALLBACK(); \n"
			"class Test { \n"
			"  bool opEquals(CALLBACK @f) { \n"
			"    return f is func; \n"
			"  } \n"
			"  CALLBACK @func; \n"
			"} \n"
			"namespace ns { \n"
			"void func() {} \n"
			"} \n");
		r = mod->Build();
		if( r < 0 )
			TEST_FAILED;

		r = ExecuteString(engine, "Test t; \n"
								  "@t.func = ns::func; \n"
								  "assert( t == ns::func );", mod);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;

		engine->Release();
	}

	// Test funcdefs and namespaces
	// http://www.gamedev.net/topic/644586-application-function-returning-a-funcdef-handle-crashes-when-called-in-as/
	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);
		engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);

		mod = engine->GetModule("mod", asGM_ALWAYS_CREATE);
		mod->AddScriptSection("test",
			"bool called = false; \n"
			"funcdef void simpleFuncDef(); \n"
			"namespace foo { \n"
			"  void simpleFunction() { called = true; } \n"
			"} \n"
			"void takeSimpleFuncDef(simpleFuncDef@ f) { f(); } \n"
			"void main() { \n"
			"  takeSimpleFuncDef(foo::simpleFunction); \n"
			"  assert( called ); \n"
			"} \n");
		r = mod->Build();
		if( r < 0 )
			TEST_FAILED;
		r = ExecuteString(engine, "main()", mod);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;

		mod->AddScriptSection("test",
			"bool called = false; \n"
			"funcdef void simpleFuncDef();\n"
			"namespace foo {\n"
			"  void simpleFunction() { called = true; }\n"
			"}\n"
			"void main() {\n"
			"  simpleFuncDef@ bar = foo::simpleFunction;\n"
			"  bar(); \n"
			"  assert( called ); \n"
			"}\n");
		r = mod->Build();
		if( r < 0 )
			TEST_FAILED;
		r = ExecuteString(engine, "main()", mod);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;
		engine->Release();
	}

	// Test registering global property of funcdef type
	// http://www.gamedev.net/topic/644586-application-function-returning-a-funcdef-handle-crashes-when-called-in-as/
	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);

		asIScriptFunction *f = 0;
		engine->RegisterFuncdef("void myfunc()");
		r = engine->RegisterGlobalProperty("myfunc @f", &f);
		if( r < 0 )
			TEST_FAILED;

		mod = engine->GetModule("mod", asGM_ALWAYS_CREATE);
		mod->AddScriptSection("test",
			"void func() {} \n");
		mod->Build();

		r = ExecuteString(engine, "@f = func; \n", mod);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;

		if( f == 0 )
			TEST_FAILED;
		if( strcmp(f->GetName(), "func") != 0 )
			TEST_FAILED;

		f->Release();
		f = 0;

		engine->Release();
	}

	// Test casting with funcdefs
	// http://www.gamedev.net/topic/644586-application-function-returning-a-funcdef-handle-crashes-when-called-in-as/
	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);
		engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);

		mod = engine->GetModule("mod", asGM_ALWAYS_CREATE);
		mod->AddScriptSection("test",
			"funcdef void myfunc1(); \n"
			"funcdef void myfunc2(); \n"
			"funcdef void myfunc3(); \n"
			"bool called = false; \n"
			"void func() { called = true; } \n"
			"void main() \n"
			"{ \n"
			"  myfunc1 @f1 = func; \n"
			"  myfunc2 @f2 = cast<myfunc2>(f1); \n" // explicit cast
			"  myfunc3 @f3 = f2; \n"                // implicit cast
			"  assert( f1 is f2 ); \n"
			"  assert( f2 is f3 ); \n"
			"  assert( f3 is func ); \n"
			"  f3(); \n"
			"  assert( called ); \n"
			"} \n");
		r = mod->Build();
		if( r < 0 )
			TEST_FAILED;

		r = ExecuteString(engine, "main()", mod);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;

		engine->Release();
	}

	// Don't allow application to register additional behaviours to funcdefs
	// http://www.gamedev.net/topic/644586-application-function-returning-a-funcdef-handle-crashes-when-called-in-as/
	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(CBufferedOutStream, Callback), &bout, asCALL_THISCALL);
		bout.buffer = "";

		engine->RegisterObjectType("jjOBJ", 0, asOBJ_REF | asOBJ_NOCOUNT);
		engine->RegisterFuncdef("void jjBEHAVIOR(jjOBJ@)");
		engine->RegisterFuncdef("void DifferentFunctionPointer()");
		r = engine->RegisterObjectBehaviour("jjBEHAVIOR", asBEHAVE_IMPLICIT_REF_CAST, "DifferentFunctionPointer@ a()", asFUNCTION(0), asCALL_CDECL_OBJLAST);
		if( r >= 0 )
			TEST_FAILED;

		if( bout.buffer != " (0, 0) : Error   : Failed in call to function 'RegisterObjectBehaviour' with 'jjBEHAVIOR' and 'DifferentFunctionPointer@ a()' (Code: -12)\n" )
			TEST_FAILED;

		engine->Release();
	}

	// Test delegate function pointers for object methods
	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(CBufferedOutStream, Callback), &bout, asCALL_THISCALL);
		bout.buffer = "";

		RegisterScriptArray(engine, false);
		engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);
		RegisterStdString(engine);

		mod = engine->GetModule("test", asGM_ALWAYS_CREATE);
		mod->AddScriptSection("test",
			"class Test { \n"
			"  void method() {} \n"
			"  int func(int) { return 0; } \n"
			"  void func() { called = true; } \n" // The compiler should pick the right overload
			"  bool called = false; \n"
			"} \n"
			"funcdef void CALLBACK(); \n"
			"void main() { \n"
			"  Test t; \n"
			"  CALLBACK @cb = CALLBACK(t.func); \n" // instanciate a delegate
			"  cb(); \n" // invoke the delegate
			"  assert( t.called ); \n"
			"} \n");
		r = mod->Build();
		if( r < 0 )
			TEST_FAILED;

		if( bout.buffer != "" )
		{
			PRINTF("%s", bout.buffer.c_str());
			TEST_FAILED;
		}

		r = ExecuteString(engine, "main()", mod);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;

		// Must be possible to save/load bytecode
		CBytecodeStream stream("test");
		mod->SaveByteCode(&stream);

		mod = engine->GetModule("test2", asGM_ALWAYS_CREATE);
		r = mod->LoadByteCode(&stream);
		if( r < 0 )
			TEST_FAILED;

		r = ExecuteString(engine, "main()", mod);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;

		// Must be possible to create delegate from within class method, i.e. implicit this.method
		bout.buffer = "";
		mod->AddScriptSection("test",
			"funcdef void CALL(); \n"
			"class Test { \n"
			"  bool called = false; \n"
			"  void callMe() { called = true; } \n"
			"  CALL @GetCallback() { return CALL(callMe); } \n"
			"} \n"
			"void main() { \n"
			"  Test t; \n"
			"  CALL @cb = t.GetCallback(); \n"
			"  cb(); \n"
			"  assert( t.called ); \n"
			"} \n");
		r = mod->Build();
		if( r < 0 )
			TEST_FAILED;

		if( bout.buffer != "" )
		{
			PRINTF("%s", bout.buffer.c_str());
			TEST_FAILED;
		}

		r = ExecuteString(engine, "main()", mod);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;

		// A delegate to own method held as member of class must be properly resolved by gc
		bout.buffer = "";
		mod->AddScriptSection("test",
			"funcdef void CALL(); \n"
			"class Test { \n"
			"  void call() {}; \n"
			"  CALL @c; \n"
			"} \n"
			"void main() { \n"
			"  Test t; \n"
			"  @t.c = CALL(t.call); \n"
			"} \n");
		r = mod->Build();
		if( r < 0 )
			TEST_FAILED;
		if( bout.buffer != "" )
		{
			PRINTF("%s", bout.buffer.c_str());
			TEST_FAILED;
		}

		engine->GarbageCollect();

		asUINT currSize, totalDestr, totalDetect;
		engine->GetGCStatistics(&currSize, &totalDestr, &totalDetect);

		r = ExecuteString(engine, "main()", mod);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;

		engine->GarbageCollect();

		asUINT currSize2, totalDestr2, totalDetect2;
		engine->GetGCStatistics(&currSize2, &totalDestr2, &totalDetect2);

		if( totalDetect2 == totalDetect )
			TEST_FAILED;

		// Must be possible to call delegate from application
		mod->AddScriptSection("test",
			"funcdef void CALL(); \n"
			"class Test { \n"
			"  bool called = false; \n"
			"  void call() { called = true; } \n"
			"} \n"
			"Test t; \n"
			"CALL @callback = CALL(t.call); \n");
		r = mod->Build();
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;

		int idx = mod->GetGlobalVarIndexByDecl("CALL @callback");
		if( idx < 0 )
			TEST_FAILED;

		asIScriptFunction *callback = *(asIScriptFunction**)mod->GetAddressOfGlobalVar(idx);
		if( callback == 0 )
			TEST_FAILED;
		if( callback->GetFuncType() != asFUNC_DELEGATE )
			TEST_FAILED;
		if( callback->GetDelegateObject() == 0 )
			TEST_FAILED;
		if( std::string(callback->GetDelegateFunction()->GetDeclaration()) != "void Test::call()" )
			TEST_FAILED;

		ctx = engine->CreateContext();
		ctx->Prepare(callback);
		r = ctx->Execute();
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;
		ctx->Release();

		r = ExecuteString(engine, "assert( t.called );", mod);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;

		// Must be possible to create the delegate from the application
		asIScriptObject *obj = (asIScriptObject*)mod->GetAddressOfGlobalVar(mod->GetGlobalVarIndexByDecl("Test t"));
		asIScriptFunction *func = obj->GetObjectType()->GetMethodByName("call");
		asIScriptFunction *delegate = engine->CreateDelegate(func, obj);
		if( delegate == 0 )
			TEST_FAILED;
		delegate->Release();

		// Must be possible to create delegate for registered type too
		mod->AddScriptSection("test",
			"funcdef bool EMPTY(); \n"
			"void main() { \n"
			"  array<int> a; \n"
			"  EMPTY @empty = EMPTY(a.isEmpty); \n"
			"  assert( empty() == true ); \n"
			"  a.insertLast(42); \n"
			"  assert( empty() == false ); \n"
			"} \n");
		r = mod->Build();
		if( r < 0 )
			TEST_FAILED;

		r = ExecuteString(engine, "main()", mod);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;

		// Must not be possible to create delegate with const object and non-const method
		bout.buffer = "";
		mod->AddScriptSection("test",
			"funcdef void F(); \n"
			"class Test { \n"
			"  void f() {} \n"
			"} \n"
			"void main() { \n"
			" const Test @t; \n"
			" F @f = F(t.f); \n" // t is read-only, so this delegate must not be allowed
			"} \n");
		r = mod->Build();
		if( r >= 0 )
			TEST_FAILED;

		// TODO: Error message should be better, so it is understood that the error is because of const object
		if( bout.buffer != "test (5, 1) : Info    : Compiling void main()\n"
		                   "test (7, 9) : Error   : No matching signatures to 'void F()'\n" )
		{
			PRINTF("%s", bout.buffer.c_str());
			TEST_FAILED;
		}

		// Must not be possible to create delegates for non-reference types
		bout.buffer = "";
		mod->AddScriptSection("test",
			"funcdef bool CB(); \n"
			"string s; \n"
			"CB @cb = CB(s.isEmpty); \n");
		r = mod->Build();
		if( r >= 0 )
			TEST_FAILED;

		if( bout.buffer != "test (3, 5) : Info    : Compiling CB@ cb\n"
		                   "test (3, 10) : Error   : Can't create delegate for types that do not support handles\n" )
		{
			PRINTF("%s", bout.buffer.c_str());
			TEST_FAILED;
		}

		engine->Release();
	}

	// Test ordinary function pointers for global functions
	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);
		engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);
		mod = engine->GetModule(0, asGM_ALWAYS_CREATE);

		// Test the declaration of new function signatures
		script = "funcdef void functype();\n"
		// It must be possible to declare variables of the funcdef type
				 "functype @myFunc = null;\n"
		// It must be possible to initialize the function pointer directly
				 "functype @myFunc1 = @func;\n"
		 		 "void func() { called = true; }\n"
				 "bool called = false;\n"
		// It must be possible to compare the function pointer with another
				 "void main() { \n"
				 "  assert( myFunc1 !is null ); \n"
				 "  assert( myFunc1 is func ); \n"
		// It must be possible to call a function through the function pointer
	    		 "  myFunc1(); \n"
				 "  assert( called ); \n"
		// Local function pointer variables are also possible
				 "  functype @myFunc2 = @func;\n"
				 "} \n";
		mod->AddScriptSection("script", script);
		r = mod->Build();
		if( r != 0 )
			TEST_FAILED;
		r = ExecuteString(engine, "main()", mod);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;

		// It must be possible to save the byte code with function handles
		CBytecodeStream bytecode(__FILE__"1");
		mod->SaveByteCode(&bytecode);
		{
			asIScriptModule *mod2 = engine->GetModule("mod2", asGM_ALWAYS_CREATE);
			mod2->LoadByteCode(&bytecode);
			r = ExecuteString(engine, "main()", mod2);
			if( r != asEXECUTION_FINISHED )
				TEST_FAILED;
		}

		// Test function pointers as members of classes. It should be possible to call the function
		// from within a class method. It should also be possible to call it from outside through the . operator.
		script = "funcdef void FUNC();       \n"
				 "class CMyObj               \n"
				 "{                          \n"
				 "  CMyObj() { @f = @func; } \n"
				 "  FUNC@ f;                 \n"
				 "  void test()              \n"
				 "  {                        \n"
				 "    this.f();              \n"
				 "    f();                   \n"
				 "    CMyObj o;              \n"
				 "    o.f();                 \n"
				 "    main();                \n"
				 "    assert( called == 4 ); \n"
				 "  }                        \n"
				 "}                          \n"
				 "void main()                \n"
				 "{                          \n"
				 "  CMyObj o;                \n"
				 "  o.f();                   \n"
				 "}                          \n"
				 "int called = 0;            \n"
				 "void func() { called++; }  \n";
		mod->AddScriptSection("script", script);
		r = mod->Build();
		if( r < 0 )
			TEST_FAILED;
		asIScriptContext *ctx = engine->CreateContext();
		r = ExecuteString(engine, "CMyObj o; o.test();", mod, ctx);
		if( r != asEXECUTION_FINISHED )
		{
			TEST_FAILED;
			if( r == asEXECUTION_EXCEPTION )
				PrintException(ctx);
		}
		ctx->Release();

		// It must not be possible to declare a non-handle variable of the funcdef type
		engine->SetMessageCallback(asMETHOD(CBufferedOutStream, Callback), &bout, asCALL_THISCALL);
		bout.buffer = "";
		script = "funcdef void functype();\n"
				 "functype myFunc;\n";
		mod->AddScriptSection("script", script);
		r = mod->Build();
		if( r >= 0 )
			TEST_FAILED;
		if( bout.buffer != "script (2, 1) : Error   : Data type can't be 'functype'\n"
						   "script (2, 10) : Info    : Compiling functype myFunc\n"
						   "script (2, 10) : Error   : No default constructor for object of type 'functype'.\n" )
		{
			PRINTF("%s", bout.buffer.c_str());
			TEST_FAILED;
		}

		// It must not be possible to invoke the funcdef
		bout.buffer = "";
		script = "funcdef void functype();\n"
				 "void func() { functype(); } \n";
		mod->AddScriptSection("script", script);
		r = mod->Build();
		if( r >= 0 )
			TEST_FAILED;
		if( bout.buffer != "script (2, 1) : Info    : Compiling void func()\n"
						   "script (2, 15) : Error   : No matching signatures to 'functype()'\n" )
		{
			PRINTF("%s", bout.buffer.c_str());
			TEST_FAILED;
		}

		// Test that a funcdef can't have the same name as other global entities
		bout.buffer = "";
		script = "funcdef void test();  \n"
				 "int test; \n";
		mod->AddScriptSection("script", script);
		r = mod->Build();
		if( r >= 0 )
			TEST_FAILED;
		if( bout.buffer != "script (2, 5) : Error   : Name conflict. 'test' is a funcdef.\n" )
		{
			PRINTF("%s", bout.buffer.c_str());
			TEST_FAILED;
		}

		// It is possible to take the address of class methods, but not to assign to funcdef variable
		bout.buffer = "";
		script = 
			"funcdef void F(); \n"
		    "class t { \n"
			"  void func() { \n"
			"    @func; \n"
			"    F @f = @func; \n"
            "    } \n"
			"} \n";
		mod->AddScriptSection("script", script);
		r = mod->Build();
		if( r >= 0 )
			TEST_FAILED;
		// TODO: The error message should be better
		if( bout.buffer != "script (3, 3) : Info    : Compiling void t::func()\n"
			               "script (4, 5) : Error   : Invalid expression: ambiguous name\n"
		                   "script (5, 12) : Error   : Can't implicitly convert from 't' to 'F@&'.\n" )
		{
			PRINTF("%s", bout.buffer.c_str());
			TEST_FAILED;
		}

		// A more complex sample
		bout.buffer = "";
		script = 
			"funcdef bool CALLBACK(int, int); \n"
			"funcdef bool CALLBACK2(CALLBACK @); \n"
			"void main() \n"
			"{ \n"
			"	CALLBACK @func = @myCompare; \n"
			"	CALLBACK2 @func2 = @test; \n"
			"	func2(func); \n"
			"} \n"
			"bool test(CALLBACK @func) \n"
			"{ \n"
			"	return func(1, 2); \n"
			"} \n"
			"bool myCompare(int a, int b) \n"
			"{ \n"
			"	return a > b; \n"
			"} \n";
		mod->AddScriptSection("script", script);
		r = mod->Build();
		if( r < 0 )
			TEST_FAILED;
		if( bout.buffer != "" )
		{
			PRINTF("%s", bout.buffer.c_str());
			TEST_FAILED;
		}
		r = ExecuteString(engine, "main()", mod);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;

		// It must be possible to register the function signature from the application
		r = engine->RegisterFuncdef("void AppCallback()");
		if( r < 0 )
			TEST_FAILED;

		r = engine->RegisterGlobalFunction("void ReceiveFuncPtr(AppCallback @)", asFUNCTION(ReceiveFuncPtr), asCALL_CDECL); assert( r >= 0 );

		// It must be possible to use the registered funcdef
		// It must be possible to receive a function pointer for a registered func def
		bout.buffer = "";
		script = 
			"void main() \n"
			"{ \n"
			"	AppCallback @func = @test; \n"
			"   func(); \n"
			"   ReceiveFuncPtr(func); \n"
			"} \n"
			"void test() \n"
			"{ \n"
			"} \n";
		mod->AddScriptSection("script", script);
		r = mod->Build();
		if( r < 0 )
			TEST_FAILED;
		if( bout.buffer != "" )
		{
			PRINTF("%s", bout.buffer.c_str());
			TEST_FAILED;
		}

		r = ExecuteString(engine, "main()", mod);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;

		if( !receivedFuncPtrIsOK )
			TEST_FAILED;

		mod->SaveByteCode(&bytecode);
		{
			receivedFuncPtrIsOK = false;
			asIScriptModule *mod2 = engine->GetModule("mod2", asGM_ALWAYS_CREATE);
			mod2->LoadByteCode(&bytecode);
			r = ExecuteString(engine, "main()", mod2);
			if( r != asEXECUTION_FINISHED )
				TEST_FAILED;

			if( !receivedFuncPtrIsOK )
				TEST_FAILED;
		}

		// The compiler should be able to determine the right function overload
		// by the destination of the function pointer
		bout.buffer = "";
		mod->AddScriptSection("test",
		         "funcdef void f(); \n"
				 "f @fp = @func;  \n"
				 "bool called = false; \n"
				 "void func() { called = true; }    \n"
				 "void func(int) {} \n");
		r = mod->Build();
		if( r < 0 )
			TEST_FAILED;
		if( bout.buffer != "" )
		{
			PRINTF("%s", bout.buffer.c_str());
			TEST_FAILED;
		}
		r = ExecuteString(engine, "fp(); assert( called );", mod);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;

		//----------------------------------------------------------
		// TODO: Future improvements below

		// If the function referred to when taking a function pointer is removed from the module,
		// the code must not be invalidated. After removing func() from the module, it must still 
		// be possible to execute func2()
		script = "funcdef void FUNC(); \n"
				 "void func() {} \n";
				 "void func2() { FUNC@ f = @func; f(); } \n";

		// Test that the function in a function pointer isn't released while the function 
		// is being executed, even though the function pointer itself is cleared
		script = "DYNFUNC@ funcPtr;        \n"
				 "funcdef void DYNFUNC(); \n"
				 "@funcPtr = @CompileDynFunc('void func() { @funcPtr = null; }'); \n";

		// Test that it is possible to declare the function signatures out of order
		// This also tests the circular reference between the function signatures
		script = "funcdef void f1(f2@) \n"
				 "funcdef void f2(f1@) \n";

		// It must be possible to identify a function handle type from the type id

		// It must be possible enumerate the function definitions in the module, 
		// and to enumerate the parameters the function accepts

		// A funcdef defined in multiple modules must share the id and signature so that a function implemented 
		// in one module can be called from another module by storing the handle in the funcdef variable

		// An interface that takes a funcdef as parameter must still have its typeid shared if the funcdef can also be shared
		// If the funcdef takes an interface as parameter, it must still be shared

		// Must have a generic function pointer that can store any signature. The function pointer
		// can then be dynamically cast to the correct function signature so that the function it points
		// to can be invoked.

		engine->Release();
	}

	// Test function pointers with virtual property accessors
	// http://www.gamedev.net/topic/639243-funcdef-inside-shared-interface-interface-already-implement-warning/
	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);

		engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);

		mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
		mod->AddScriptSection("test",
			"funcdef void funcdef1( ifuncdef1_1& i ); \n"
			"shared interface ifuncdef1_1 \n"
			"{ \n"
			"    ifuncdef1_2@ events { get; set; } \n"
			"    void crashme(); \n"
			"} \n"
			"shared interface ifuncdef1_2 \n"
			"{ \n"
			"    funcdef1@ f { get; set; } \n"
			"} \n"
			"class cfuncdef1_1 : ifuncdef1_1 \n"
			"{ \n"
			"    ifuncdef1_2@ _events_; \n"
			"    cfuncdef1_1() { @this._events_ = cfuncdef1_2(); } \n"
			"    ifuncdef1_2@ get_events() { return( this._events_ ); } \n"
			"    void set_events( ifuncdef1_2@ events ) { @this._events_ = events; } \n"
			"    void crashme() \n"
			"    { \n"
			"         if( this._events_ !is null && this._events_.f !is null ) \n"
			"         { \n"
			"            this.events.f( this ); \n"
//			"            this.get_events().get_f()( this ); \n" // This should produce the same bytecode as the above
			"         } \n"
			"    } \n"
			"} \n"
			"class cfuncdef1_2 : ifuncdef1_2 \n"
			"{ \n"
			"    funcdef1@ ff; \n"
			"    cfuncdef1_2() { @ff = null; } \n"
			"    funcdef1@ get_f() { return( @this.ff ); } \n"
			"    void set_f( funcdef1@ _f ) { @this.ff = _f; } \n"
			"} \n"
			"void start() \n"
			"{ \n"
			"    ifuncdef1_1@ i = cfuncdef1_1(); \n"
			"    @i.events.f = end; \n" // TODO: Shouldn't this give an error? It's attempting to do an value assignment to a function pointer
			"    i.crashme(); \n"
			"} \n"
			"bool called = false; \n"
			"void end( ifuncdef1_1& i  ) \n"
			"{ \n"
			"    called = true; \n"
			"} \n");

		r = mod->Build(); 
		if( r < 0 )
			TEST_FAILED;

		ctx = engine->CreateContext();
		r = ExecuteString(engine, "start(); assert( called );", mod, ctx);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;
		if( r == asEXECUTION_EXCEPTION )
			PrintException(ctx, true);
		ctx->Release();

		CBytecodeStream stream(__FILE__"1");
		
		r = mod->SaveByteCode(&stream);
		if( r < 0 )
			TEST_FAILED;
		
		engine->Release();

		// Load the bytecode 
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
		engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);

		stream.Restart();
		mod = engine->GetModule("A", asGM_ALWAYS_CREATE);
		r = mod->LoadByteCode(&stream);
		if( r < 0 )
			TEST_FAILED;

		ctx = engine->CreateContext();
		r = ExecuteString(engine, "start(); assert( called );", mod);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;
		ctx->Release();

		stream.Restart();
		mod = engine->GetModule("B", asGM_ALWAYS_CREATE);
		r = mod->LoadByteCode(&stream);
		if( r < 0 )
			TEST_FAILED;

		ctx = engine->CreateContext();
		r = ExecuteString(engine, "start(); assert( called );", mod);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;
		ctx->Release();

		engine->Release();
	}

	// Test clean up with registered function definitions
	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		RegisterScriptString(engine);
		r = engine->RegisterFuncdef("void MSG_NOTIFY_CB(const string& strCommand, const string& strTarget)"); assert(r>=0);

		engine->Release();
	}

	// Test registering function pointer as property
	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		r = engine->RegisterFuncdef("void fptr()");
		r = engine->RegisterGlobalProperty("fptr f", 0);
		if( r >= 0 ) TEST_FAILED;
		engine->RegisterObjectType("obj", 0, asOBJ_REF);
		r = engine->RegisterObjectProperty("obj", "fptr f", 0);
		if( r >= 0 ) TEST_FAILED;

		engine->Release();
	}

	// Test passing handle to function pointer
	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);

		engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);
		mod = engine->GetModule(0, asGM_ALWAYS_CREATE);

		mod->AddScriptSection("script",
			"class CTempObj             \n"
			"{                          \n"
			"  int Temp;                \n"
			"}                          \n"
			"funcdef void FUNC2(CTempObj@);\n"
			"class CMyObj               \n"
			"{                          \n"
			"  CMyObj() { @f2= @func2; }\n"
			"  FUNC2@ f2;               \n"
			"}                          \n"
			"void main()                \n"
			"{                          \n"
			"  CMyObj o;                \n"
			"  CTempObj t;              \n"
			"  o.f2(t);                 \n"
			"  assert( called == 1 );   \n"
			"}                          \n"
			"int called = 0;            \n"
			"void func2(CTempObj@ Obj)  \n"
			"{ called++; }              \n");

		r = mod->Build();
		if( r < 0 )
			TEST_FAILED;

		r = ExecuteString(engine, "main()", mod);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;

		engine->Release();
	}

	// Test out of order declaration with function pointers
	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);
		mod = engine->GetModule(0, asGM_ALWAYS_CREATE);

		mod->AddScriptSection("script",
			"funcdef void FUNC2(CTempObj@);\n"
			"class CTempObj {}             \n");

		r = mod->Build();
		if( r < 0 )
			TEST_FAILED;

		engine->Release();
	}

	// It must be possible calling system functions through pointers too
	{
		asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);

		engine->RegisterFuncdef("bool fun(bool)");
		engine->RegisterGlobalFunction("bool assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);

		r = ExecuteString(engine, "fun @f = assert; f(true);");
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;

		engine->Release();
	}

	// It should be possible to call functions through function pointers returned by an expression
	// http://www.gamedev.net/topic/627386-bug-with-parsing-of-callable-expressions/
	{
		asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);
		RegisterScriptArray(engine, false);
		engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);

		mod = engine->GetModule(0, asGM_ALWAYS_CREATE);

		mod->AddScriptSection("Test",
			"funcdef void F(int); \n"
			"array<F@> arr(1); \n"
			"F@ g()            \n"
			"{                 \n"
			"  return test;    \n"
			"}                 \n"
			"void test(int a)  \n"
			"{                 \n"
			"  assert(a == 42); \n"
			"  called++;       \n"
			"}                 \n"
			"int called = 0;   \n"
			"void f()          \n"
			"{                 \n"
			"  @arr[0] = test; \n"
			"  arr[0](42);     \n"
			"  g()(42);        \n"
			"  F@ p; \n"
			"  (@p = arr[0])(42);     \n"
			"  (@p = g())(42);        \n"
			"}                        \n");

	//	engine->SetEngineProperty(asEP_OPTIMIZE_BYTECODE, false);
		r = mod->Build();
		if( r < 0 )
			TEST_FAILED;

		r = ExecuteString(engine, "f()", mod);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;

		int idx = mod->GetGlobalVarIndexByName("called");
		int *called = (int*)mod->GetAddressOfGlobalVar(idx);
		if( *called != 4 )
			TEST_FAILED;

		engine->Release();
	}

	// Global function pointers must not overload local class methods
	// Local variables take precedence over class methods
	// http://www.gamedev.net/topic/626746-function-call-operators-in-the-future/
	{
		const char *script = 
			"funcdef void FUNC(); \n"
			"FUNC @func; \n"
			"class Class \n"
			"{ \n"
			"  void func() {} \n"
			"  void method() \n"
			"  { \n"
			"    func(); \n"       // Should call Class::func()
			"  } \n"
			"  void func2() {} \n"
			"  void method2() \n"
			"  { \n"
			"    FUNC @func2; \n"
			"    func2(); \n"      // Should call variable func2
			"  } \n"
			"} \n";

		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);

		engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);

		mod = engine->GetModule("test", asGM_ALWAYS_CREATE);
		mod->AddScriptSection("test", script);
		r = mod->Build();
		if( r < 0 )
			TEST_FAILED;

		r = ExecuteString(engine, "Class c; c.method();", mod);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;

		r = ExecuteString(engine, "Class c; c.method2();", mod);
		if( r != asEXECUTION_EXCEPTION )
			TEST_FAILED;

		engine->Release();
	}

	// Success
 	return fail;
}
コード例 #21
0
bool TestCDecl_ClassD()
{
	RET_ON_MAX_PORT

	bool fail = false;

	asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);

	engine->RegisterObjectType("class1", sizeof(ClassD1), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS_D);
	engine->RegisterObjectType("class2", sizeof(ClassD2), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS_D);
	engine->RegisterObjectType("class3", sizeof(ClassD3), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS_D);

	engine->RegisterGlobalProperty("class1 c1", &c1);
	engine->RegisterGlobalProperty("class2 c2", &c2);
	engine->RegisterGlobalProperty("class3 c3", &c3);

	engine->RegisterGlobalFunction("class1 _class1()", asFUNCTION(classD1), asCALL_CDECL);
	engine->RegisterGlobalFunction("class2 _class2()", asFUNCTION(classD2), asCALL_CDECL);
	engine->RegisterGlobalFunction("class3 _class3()", asFUNCTION(classD3), asCALL_CDECL);


	COutStream out;
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);

	c1.a = 0;

	int r = ExecuteString(engine, "c1 = _class1();");
	if( r < 0 )
	{
		PRINTF("%s: ExecuteString() failed %d\n", TESTNAME, r);
		TEST_FAILED;
	}

	if( c1.a != 0xDEADC0DE )
	{
		PRINTF("%s: Failed to assign object returned from function. c1.a = %X\n", TESTNAME, (unsigned int)c1.a);
		TEST_FAILED;
	}


	c2.a = 0;
	c2.b = 0;

	r = ExecuteString(engine, "c2 = _class2();");
	if( r < 0 )
	{
		PRINTF("%s: ExecuteString() failed %d\n", TESTNAME, r);
		TEST_FAILED;
	}

	if( c2.a != 0xDEADC0DE )
	{
		PRINTF("%s: Failed to assign object returned from function. c2.a = %X\n", TESTNAME, (unsigned int)c2.a);
		TEST_FAILED;
	}

	if( c2.b != 0x01234567 )
	{
		PRINTF("%s: Failed to assign object returned from function. c2.b = %X\n", TESTNAME, (unsigned int)c2.b);
		TEST_FAILED;
	}

	c3.a = 0;
	c3.b = 0;
	c3.c = 0;

	r = ExecuteString(engine, "c3 = _class3();");
	if( r < 0 )
	{
		PRINTF("%s: ExecuteString() failed %d\n", TESTNAME, r);
		TEST_FAILED;
	}

	if( c3.a != 0xDEADC0DE )
	{
		PRINTF("%s: Failed to assign object returned from function. c3.a = %X\n", TESTNAME, (unsigned int)c3.a);
		TEST_FAILED;
	}

	if( c3.b != 0x01234567 )
	{
		PRINTF("%s: Failed to assign object returned from function. c3.b = %X\n", TESTNAME, (unsigned int)c3.b);
		TEST_FAILED;
	}

	if( c3.c != 0x89ABCDEF )
	{
		PRINTF("%s: Failed to assign object returned from function. c3.c = %X\n", TESTNAME, (unsigned int)c3.c);
		TEST_FAILED;
	}

	// Test passing the object types by value to a system function
	r = engine->RegisterGlobalFunction("void class1ByVal(class1)", asFUNCTION(class1ByVal), asCALL_CDECL); assert( r >= 0 );
	r = ExecuteString(engine, "class1 c = _class1(); class1ByVal(c)");
	if( r != asEXECUTION_FINISHED )
		TEST_FAILED;

	r = engine->RegisterGlobalFunction("void class2ByVal(class2)", asFUNCTION(class2ByVal), asCALL_CDECL); assert( r >= 0 );
	r = ExecuteString(engine, "class2 c = _class2(); class2ByVal(c)");
	if( r != asEXECUTION_FINISHED )
		TEST_FAILED;

	r = engine->RegisterGlobalFunction("void class3ByVal(class3)", asFUNCTION(class3ByVal), asCALL_CDECL); assert( r >= 0 );
	r = ExecuteString(engine, "class3 c = _class3(); class3ByVal(c)");
	if( r != asEXECUTION_FINISHED )
		TEST_FAILED;

	// Test returning the same object that was passed in
	// http://www.gamedev.net/topic/667966-calling-convention-bug/
	r = engine->RegisterGlobalFunction("class2 test(class2)", asFUNCTION(test), asCALL_CDECL); assert( r >= 0 );
	r = ExecuteString(engine, "class2 c = _class2(); c = test(c); class2ByVal(c)");
	if( r != asEXECUTION_FINISHED )
		TEST_FAILED;

	engine->Release();

	return fail;
}
コード例 #22
0
bool Test()
{
	bool fail = false;

    // Create the script engine
    asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
 
    // Register Function
    RegisterScriptString(engine);
    engine->RegisterGlobalFunction("void Print(string &in)", asFUNCTION(PrintString_Generic), asCALL_GENERIC);
 
    // Compile
    asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
    mod->AddScriptSection("script", 
        "class Obj{};"
        "class Hoge"
        "{"
        "    Hoge(){ Print('ctor\\n'); }"
        "    ~Hoge(){ Print('dtor\\n'); }"
        "    Obj@ obj;"
        "};"
        "void main()"
        "{"
        "    Hoge hoge;"
        "};"
        , 0);
    mod->Build();
 
    // Context Create
    asIScriptContext *ctx = engine->CreateContext();
 
    // Loop
    for( asUINT n = 0; n < 3; n++ )
    {
        // Execute
        //printf("----- execute\n");
        ctx->Prepare(mod->GetFunctionIdByDecl("void main()"));
        ctx->Execute();
 
        // GC
        const int GC_STEP_COUNT_PER_FRAME = 100;
        for ( int i = 0; i < GC_STEP_COUNT_PER_FRAME; ++i )
        {
            engine->GarbageCollect(asGC_ONE_STEP);
        }
        
        // Check status
        {
            asUINT currentSize = asUINT();
            asUINT totalDestroyed = asUINT();
            asUINT totalDetected = asUINT();
            engine->GetGCStatistics(&currentSize , &totalDestroyed , &totalDetected );
			if( currentSize    != 8 ||
				totalDestroyed != n+1 ||
				totalDetected  != 0 )
				TEST_FAILED;
            //printf("(%lu,%lu,%lu)\n" , currentSize , totalDestroyed , totalDetected );
        }
    }

    // Release 
    ctx->Release();
    engine->Release();

	// Test 
	{	
		COutStream out;
		int r;

		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);
		RegisterScriptArray(engine, true);

		mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
		mod->AddScriptSection(0, 
			"interface ITest\n"
			"{\n"
			"}\n"
			"class Test : ITest\n"
			"{\n"
			"	ITest@[] arr;\n"
			"	void Set(ITest@ e)\n"
			"	{\n"
			"		arr.resize(1);\n"
			"		@arr[0]=e;\n"
			"	}\n"
			"}\n"
			"void main()\n"
			"{\n"
			"	Test@ t=Test();\n"
			"	t.Set(t);\n"
			"}\n");
		r = mod->Build();
		if( r < 0 )
			TEST_FAILED;

		asUINT currentSize;
		engine->GetGCStatistics(&currentSize);
		
		r = ExecuteString(engine, "main()", mod);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;

		engine->GetGCStatistics(&currentSize);

		engine->Release();
	}

	// Test attempted access of global variable after it has been destroyed
	{	
		COutStream out;
		int r;

		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);
		RegisterScriptArray(engine, true);
		RegisterStdString(engine);
		engine->RegisterGlobalFunction("void Log(const string &in)", asFUNCTION(PrintString_Generic), asCALL_GENERIC);

		mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
		mod->AddScriptSection(0, 
			"class Big \n"
			"{ \n"
			"  Big() \n"
			"  { \n"
			"    Log('Big instance created\\n'); \n"
			"  } \n"
			"  ~Big() \n"
			"  { \n"
			"    Log('Big instance being destroyed\\n'); \n"
			"  } \n"
			"  void exec() \n"
			"  { \n"
			"    Log('executed\\n'); \n"
			"  } \n"
			"} \n"
			"Big big; \n" // Global object
			"class SomeClass \n"
			"{ \n"
			"  SomeClass@ handle; \n" // Make sure SomeClass is garbage collected
			"  SomeClass() {} \n"
			"  ~SomeClass() \n"
			"  { \n"
			"    Log('Before attempting access to global var\\n'); \n"
			"    big.exec(); \n" // As the module has already been destroyed, the global variable won't exist anymore, thus raising a null pointer exception here
			"    Log('SomeClass instance being destroyed\\n'); \n" // This won't be called
			"  } \n"
			"} \n"
			"void test_main() \n"
			"{ \n"
			"  SomeClass @something = @SomeClass(); \n" // Instanciate the object. It will only be destroyed by the GC
			"} \n");
		r = mod->Build();
		if( r < 0 )
			TEST_FAILED;

		r = ExecuteString(engine, "test_main()", mod);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;

		// The global variables in the module will be destroyed first. The objects in the GC that 
		// tries to access them should throw exception, but should not cause the application to crash
		called = 0;
		engine->Release();
		if( called != 2 )
			TEST_FAILED;
	}
/*
	{
		// This test forces a memory leak due to not registering the GC behaviours for the CFoo class
		COutStream out;
		int r;

		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);

		engine->RegisterInterface("IMyInterface"); 
		engine->RegisterObjectType("CFoo", sizeof(CFoo), asOBJ_REF); 
		engine->RegisterObjectBehaviour("CFoo", asBEHAVE_ADDREF, "void f()", asMETHOD(CFoo, AddRef), asCALL_THISCALL); 
		engine->RegisterObjectBehaviour("CFoo", asBEHAVE_RELEASE, "void f()", asMETHOD(CFoo, Release), asCALL_THISCALL); 
		engine->RegisterObjectBehaviour("CFoo", asBEHAVE_FACTORY, "CFoo@ f()", asFUNCTION(&CFoo::CreateObject), asCALL_CDECL);       
		engine->RegisterObjectMethod("CFoo", "void SetObject(IMyInterface@)", asMETHOD(CFoo, SetScriptObject), asCALL_THISCALL); 

		const char *script = 
			"CBar test; \n"
			"class CBase : IMyInterface \n"
			"{ \n"
			"  IMyInterface@ m_dummy; \n" // Comment only this and everything is ok
			"} \n"
			"class CBar : CBase \n"
			"{ \n"
			"  CBar() \n"
			"  { \n"
			"    m_foo.SetObject(this); \n" // Comment only this and everything is ok
			"  } \n"
			"  CFoo m_foo; \n"
			"}; ";

		asIScriptModule *mod = engine->GetModule("test", asGM_ALWAYS_CREATE);
		mod->AddScriptSection("test", script);
		r = mod->Build();

		engine->Release();
	}
*/
	return fail;
}
コード例 #23
0
bool Test()
{
	bool fail = false;

 	asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
	engine->RegisterGlobalFunction("void Assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);

	COutStream out;
	CBufferedOutStream bout;

	float f = 0;
	double d = 0;
	asUINT ui = 0;
	asINT64 i64 = 0;
	int i = 0;
	signed char i8 = 0;
	asQWORD ui64 = 0;
	short i16 = 0;
	unsigned char ui8 = 0;
	unsigned short ui16 = 0;
	engine->RegisterGlobalProperty("float f", &f);
	engine->RegisterGlobalProperty("double d", &d);
	engine->RegisterGlobalProperty("uint ui", &ui);
	engine->RegisterGlobalProperty("uint8 ui8", &ui8);
	engine->RegisterGlobalProperty("uint16 ui16", &ui16);
	engine->RegisterGlobalProperty("uint64 ui64", &ui64);
	engine->RegisterGlobalProperty("int i", &i);
	engine->RegisterGlobalProperty("int8 i8", &i8);
	engine->RegisterGlobalProperty("int16 i16", &i16);
	engine->RegisterGlobalProperty("int64 i64", &i64);

	engine->RegisterGlobalFunction("void TestDouble(double)", asFUNCTION(TestDouble), asCALL_GENERIC);
	engine->RegisterGlobalFunction("void TestFloat(float)", asFUNCTION(TestFloat), asCALL_GENERIC);
	engine->RegisterGlobalFunction("void TestI64(int16)", asFUNCTION(TestI64), asCALL_GENERIC);
	engine->RegisterGlobalFunction("void TestInt(int)", asFUNCTION(TestInt), asCALL_GENERIC);
	engine->RegisterGlobalFunction("void TestI16(int16)", asFUNCTION(TestI16), asCALL_GENERIC);
	engine->RegisterGlobalFunction("void TestI8(int8)", asFUNCTION(TestI8), asCALL_GENERIC);
	engine->RegisterGlobalFunction("void TestUI64(uint)", asFUNCTION(TestUI64), asCALL_GENERIC);
	engine->RegisterGlobalFunction("void TestUInt(uint)", asFUNCTION(TestUInt), asCALL_GENERIC);
	engine->RegisterGlobalFunction("void TestUI16(uint16)", asFUNCTION(TestUI16), asCALL_GENERIC);
	engine->RegisterGlobalFunction("void TestUI8(uint8)", asFUNCTION(TestUI8), asCALL_GENERIC);

	engine->RegisterGlobalFunction("void TestDoubleByRef(double &in)", asFUNCTION(TestDoubleByRef), asCALL_GENERIC);
	engine->RegisterGlobalFunction("void TestFloatByRef(float &in)", asFUNCTION(TestFloatByRef), asCALL_GENERIC);
	engine->RegisterGlobalFunction("void TestI64ByRef(int &in)", asFUNCTION(TestI64ByRef), asCALL_GENERIC);
	engine->RegisterGlobalFunction("void TestIntByRef(int &in)", asFUNCTION(TestIntByRef), asCALL_GENERIC);
	engine->RegisterGlobalFunction("void TestI16ByRef(int16 &in)", asFUNCTION(TestI16ByRef), asCALL_GENERIC);
	engine->RegisterGlobalFunction("void TestI8ByRef(int8 &in)", asFUNCTION(TestI8ByRef), asCALL_GENERIC);
	engine->RegisterGlobalFunction("void TestUI64ByRef(uint &in)", asFUNCTION(TestUI64ByRef), asCALL_GENERIC);
	engine->RegisterGlobalFunction("void TestUIntByRef(uint &in)", asFUNCTION(TestUIntByRef), asCALL_GENERIC);
	engine->RegisterGlobalFunction("void TestUI16ByRef(uint16 &in)", asFUNCTION(TestUI16ByRef), asCALL_GENERIC);
	engine->RegisterGlobalFunction("void TestUI8ByRef(uint8 &in)", asFUNCTION(TestUI8ByRef), asCALL_GENERIC);

	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
	d    = 12.3;  engine->ExecuteString(0, "d = double(d);");    if( d  !=   12.3  ) fail = true; 
	f    = 12.3f; engine->ExecuteString(0, "d = double(f);");    if( d  !=   12.3f ) fail = true; 
	ui   = 123;   engine->ExecuteString(0, "d = double(ui);");   if( d  !=  123.0  ) fail = true;
	ui8  = 123;   engine->ExecuteString(0, "d = double(ui8);");  if( d  !=  123.0  ) fail = true;
	ui16 = 123;   engine->ExecuteString(0, "d = double(ui16);"); if( d  !=  123.0  ) fail = true;
	ui64 = 123;   engine->ExecuteString(0, "d = double(ui64);"); if( d  !=  123.0  ) fail = true;
	i    = -123;  engine->ExecuteString(0, "d = double(i);");    if( d  != -123.0  ) fail = true;
	i8   = -123;  engine->ExecuteString(0, "d = double(i8);");   if( d  != -123.0  ) fail = true;
	i16  = -123;  engine->ExecuteString(0, "d = double(i16);");  if( d  != -123.0  ) fail = true;
	i64  = -123;  engine->ExecuteString(0, "d = double(i64);");  if( d  != -123.0  ) fail = true;

	ui64 = asQWORD(I64(-1000000000000000000)); 
	double d2 = 18446744073709551615.0 + double(asINT64(ui64));
	engine->ExecuteString(0, "d = double(ui64);"); if( d  !=  d2  ) fail = true;

	d    = 12.3;  engine->ExecuteString(0, "d = d;");    if( d  !=   12.3  ) fail = true; 
	f    = 12.3f; engine->ExecuteString(0, "d = f;");    if( d  !=   12.3f ) fail = true; 
	ui   = 123;   engine->ExecuteString(0, "d = ui;");   if( d  !=  123.0  ) fail = true;
	ui8  = 123;   engine->ExecuteString(0, "d = ui8;");  if( d  !=  123.0  ) fail = true;
	ui16 = 123;   engine->ExecuteString(0, "d = ui16;"); if( d  !=  123.0  ) fail = true;
	ui64 = 123;   engine->ExecuteString(0, "d = ui64;"); if( d  !=  123.0  ) fail = true;
	i    = -123;  engine->ExecuteString(0, "d = i;");    if( d  != -123.0  ) fail = true;
	i8   = -123;  engine->ExecuteString(0, "d = i8;");   if( d  != -123.0  ) fail = true;
	i16  = -123;  engine->ExecuteString(0, "d = i16;");  if( d  != -123.0  ) fail = true;
	i64  = -123;  engine->ExecuteString(0, "d = i64;");  if( d  != -123.0  ) fail = true;

	engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL);
	engine->ExecuteString(0, "d = 12.3; "); if( !CompareDouble(d,12.3) ) fail = true; 
	engine->ExecuteString(0, "d = 12.3f;"); if( !CompareDouble(d,12.3f) ) fail = true; 
	engine->ExecuteString(0, "d = 123;  "); if( !CompareDouble(d,123.0) ) fail = true;
	engine->ExecuteString(0, "d = -123; "); if( !CompareDouble(d,-123.0) ) fail = true;
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);

	d    = 12.3;  engine->ExecuteString(0, "f = float(d);");     if( f  !=   12.3f ) fail = true; 
	f    = 12.3f; engine->ExecuteString(0, "f = float(f);");     if( f  !=   12.3f ) fail = true; 
	ui   = 123;   engine->ExecuteString(0, "f = float(ui);");    if( f  !=  123.0f ) fail = true;
	ui8  = 123;   engine->ExecuteString(0, "f = float(ui8);");   if( f  !=  123.0f ) fail = true;
	ui16 = 123;   engine->ExecuteString(0, "f = float(ui16);");  if( f  !=  123.0f ) fail = true;
	ui64 = 123;   engine->ExecuteString(0, "f = float(ui64);");  if( f  !=  123.0f ) fail = true;
	i    = -123;  engine->ExecuteString(0, "f = float(i);");     if( f  != -123.0f ) fail = true;
	i8   = -123;  engine->ExecuteString(0, "f = float(i8);");    if( f  != -123.0f ) fail = true;
	i16  = -123;  engine->ExecuteString(0, "f = float(i16);");   if( f  != -123.0f ) fail = true;
	i64  = -123;  engine->ExecuteString(0, "f = float(i64);");   if( f  != -123.0f ) fail = true;

	d    = 12.3;  engine->ExecuteString(0, "f = d;");     if( f  !=   12.3f ) fail = true; 
	f    = 12.3f; engine->ExecuteString(0, "f = f;");     if( f  !=   12.3f ) fail = true; 
	ui   = 123;   engine->ExecuteString(0, "f = ui;");    if( f  !=  123.0f ) fail = true;
	ui8  = 123;   engine->ExecuteString(0, "f = ui8;");   if( f  !=  123.0f ) fail = true;
	ui16 = 123;   engine->ExecuteString(0, "f = ui16;");  if( f  !=  123.0f ) fail = true;
	ui64 = 123;   engine->ExecuteString(0, "f = ui64;");  if( f  !=  123.0f ) fail = true;
	i    = -123;  engine->ExecuteString(0, "f = i;");     if( f  != -123.0f ) fail = true;
	i8   = -123;  engine->ExecuteString(0, "f = i8;");    if( f  != -123.0f ) fail = true;
	i16  = -123;  engine->ExecuteString(0, "f = i16;");   if( f  != -123.0f ) fail = true;
	i64  = -123;  engine->ExecuteString(0, "f = i64;");   if( f  != -123.0f ) fail = true;

	engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL);
	engine->ExecuteString(0, "f = 12.3; "); if( f  !=   12.3f ) fail = true; 
	engine->ExecuteString(0, "f = 12.3f;"); if( f  !=   12.3f ) fail = true; 
	engine->ExecuteString(0, "f = 123;  "); if( f  !=  123.0f ) fail = true;
	engine->ExecuteString(0, "f = -123; "); if( f  != -123.0f ) fail = true;
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);

	d    = 12.3;   engine->ExecuteString(0, "i64 = int64(d);");      if( i64  !=   12 ) fail = true; 
	f    = -12.3f; engine->ExecuteString(0, "i64 = int64(f);");      if( i64  != - 12 ) fail = true;
	ui   = 123;    engine->ExecuteString(0, "i64 = int64(ui);");     if( i64  !=  123 ) fail = true;
	ui8  = 123;    engine->ExecuteString(0, "i64 = int64(ui8);");    if( i64  !=  123 ) fail = true;
	ui16 = 123;    engine->ExecuteString(0, "i64 = int64(ui16);");   if( i64  !=  123 ) fail = true;
	ui64 = 123;    engine->ExecuteString(0, "i64 = int64(ui64);");   if( i64  !=  123 ) fail = true;
	i    = -123;   engine->ExecuteString(0, "i64 = int64(i);");      if( i64  != -123 ) fail = true;
	i8   = -123;   engine->ExecuteString(0, "i64 = int64(i8);");     if( i64  != -123 ) fail = true;
	i16  = -123;   engine->ExecuteString(0, "i64 = int64(i16);");    if( i64  != -123 ) fail = true;
	i64  = -123;   engine->ExecuteString(0, "i64 = int64(i64);");    if( i64  != -123 ) fail = true;

	d    = 12.3;   engine->ExecuteString(0, "i64 = d;");      if( i64  !=   12 ) fail = true; 
	f    = -12.3f; engine->ExecuteString(0, "i64 = f;");      if( i64  != - 12 ) fail = true;
	ui   = 123;    engine->ExecuteString(0, "i64 = ui;");     if( i64  !=  123 ) fail = true;
	ui8  = 123;    engine->ExecuteString(0, "i64 = ui8;");    if( i64  !=  123 ) fail = true;
	ui16 = 123;    engine->ExecuteString(0, "i64 = ui16;");   if( i64  !=  123 ) fail = true;
	ui64 = 123;    engine->ExecuteString(0, "i64 = ui64;");   if( i64  !=  123 ) fail = true;
	i    = -123;   engine->ExecuteString(0, "i64 = i;");      if( i64  != -123 ) fail = true;
	i8   = -123;   engine->ExecuteString(0, "i64 = i8;");     if( i64  != -123 ) fail = true;
	i16  = -123;   engine->ExecuteString(0, "i64 = i16;");    if( i64  != -123 ) fail = true;
	i64  = -123;   engine->ExecuteString(0, "i64 = i64;");    if( i64  != -123 ) fail = true;

	engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL);
	engine->ExecuteString(0, "i64 = 12.3;  "); if( i64  !=   12 ) fail = true; 
	engine->ExecuteString(0, "i64 = -12.3f;"); if( i64  != - 12 ) fail = true;
	engine->ExecuteString(0, "i64 = 123;   "); if( i64  !=  123 ) fail = true;
	engine->ExecuteString(0, "i64 = -123;  "); if( i64  != -123 ) fail = true;
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);

	d    = 12.3;   engine->ExecuteString(0, "i = int(d);");      if( i  !=   12 ) fail = true; 
	f    = -12.3f; engine->ExecuteString(0, "i = int(f);");      if( i  != - 12 ) fail = true;
	ui   = 123;    engine->ExecuteString(0, "i = int(ui);");     if( i  !=  123 ) fail = true;
	ui8  = 123;    engine->ExecuteString(0, "i = int(ui8);");    if( i  !=  123 ) fail = true;
	ui16 = 123;    engine->ExecuteString(0, "i = int(ui16);");   if( i  !=  123 ) fail = true;
	ui64 = 123;    engine->ExecuteString(0, "i = int(ui64);");   if( i  !=  123 ) fail = true;
	i    = -123;   engine->ExecuteString(0, "i = int(i);");      if( i  != -123 ) fail = true;
	i8   = -123;   engine->ExecuteString(0, "i = int(i8);");     if( i  != -123 ) fail = true;
	i16  = -123;   engine->ExecuteString(0, "i = int(i16);");    if( i  != -123 ) fail = true;
	i64  = -123;   engine->ExecuteString(0, "i = int(i64);");    if( i  != -123 ) fail = true;

	d    = 12.3;   engine->ExecuteString(0, "i = d;");      if( i  !=   12 ) fail = true; 
	f    = -12.3f; engine->ExecuteString(0, "i = f;");      if( i  != - 12 ) fail = true;
	ui   = 123;    engine->ExecuteString(0, "i = ui;");     if( i  !=  123 ) fail = true;
	ui8  = 123;    engine->ExecuteString(0, "i = ui8;");    if( i  !=  123 ) fail = true;
	ui16 = 123;    engine->ExecuteString(0, "i = ui16;");   if( i  !=  123 ) fail = true;
	ui64 = 123;    engine->ExecuteString(0, "i = ui64;");   if( i  !=  123 ) fail = true;
	i    = -123;   engine->ExecuteString(0, "i = i;");      if( i  != -123 ) fail = true;
	i8   = -123;   engine->ExecuteString(0, "i = i8;");     if( i  != -123 ) fail = true;
	i16  = -123;   engine->ExecuteString(0, "i = i16;");    if( i  != -123 ) fail = true;
	i64  = -123;   engine->ExecuteString(0, "i = i64;");    if( i  != -123 ) fail = true;

	engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL);
	engine->ExecuteString(0, "i = 12.3;  "); if( i  !=   12 ) fail = true; 
	engine->ExecuteString(0, "i = -12.3f;"); if( i  != - 12 ) fail = true;
	engine->ExecuteString(0, "i = 123;   "); if( i  !=  123 ) fail = true;
	engine->ExecuteString(0, "i = -123;  "); if( i  != -123 ) fail = true;
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);

	d    = 12.3;   engine->ExecuteString(0, "i8 = int8(d);");     if( i8 !=   12 ) fail = true; 
	f    = -12.3f; engine->ExecuteString(0, "i8 = int8(f);");     if( i8 != - 12 ) fail = true;
	ui   = 123;    engine->ExecuteString(0, "i8 = int8(ui);");    if( i8 !=  123 ) fail = true;
	ui8  = 123;    engine->ExecuteString(0, "i8 = int8(ui8);");   if( i8 !=  123 ) fail = true;
	ui16 = 123;    engine->ExecuteString(0, "i8 = int8(ui16);");  if( i8 !=  123 ) fail = true;
	ui64 = 123;    engine->ExecuteString(0, "i8 = int8(ui64);");  if( i8 !=  123 ) fail = true;
	i    = -123;   engine->ExecuteString(0, "i8 = int8(i);");     if( i8 != -123 ) fail = true;
	i8   = -123;   engine->ExecuteString(0, "i8 = int8(i8);");    if( i8 != -123 ) fail = true;
	i16  = -123;   engine->ExecuteString(0, "i8 = int8(i16);");   if( i8 != -123 ) fail = true;
	i64  = -123;   engine->ExecuteString(0, "i8 = int8(i64);");   if( i8 != -123 ) fail = true;

	d    = 12.3;   engine->ExecuteString(0, "i8 = d;");     if( i8 !=   12 ) fail = true; 
	f    = -12.3f; engine->ExecuteString(0, "i8 = f;");     if( i8 != - 12 ) fail = true;
	ui   = 123;    engine->ExecuteString(0, "i8 = ui;");    if( i8 !=  123 ) fail = true;
	ui8  = 123;    engine->ExecuteString(0, "i8 = ui8;");   if( i8 !=  123 ) fail = true;
	ui16 = 123;    engine->ExecuteString(0, "i8 = ui16;");  if( i8 !=  123 ) fail = true;
	ui64 = 123;    engine->ExecuteString(0, "i8 = ui64;");  if( i8 !=  123 ) fail = true;
	i    = -123;   engine->ExecuteString(0, "i8 = i;");     if( i8 != -123 ) fail = true;
	i8   = -123;   engine->ExecuteString(0, "i8 = i8;");    if( i8 != -123 ) fail = true;
	i16  = -123;   engine->ExecuteString(0, "i8 = i16;");   if( i8 != -123 ) fail = true;
	i64  = -123;   engine->ExecuteString(0, "i8 = i64;");   if( i8 != -123 ) fail = true;

	engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL);
	engine->ExecuteString(0, "i8 = 12.3;  "); if( i8 !=   12 ) fail = true; 
	engine->ExecuteString(0, "i8 = -12.3f;"); if( i8 != - 12 ) fail = true;
	engine->ExecuteString(0, "i8 = 123;   "); if( i8 !=  123 ) fail = true;
	engine->ExecuteString(0, "i8 = -123;  "); if( i8 != -123 ) fail = true;
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);

	d    = 12.3;   engine->ExecuteString(0, "i16 = int16(d);");    if( i16 !=   12 ) fail = true; 
	f    = -12.3f; engine->ExecuteString(0, "i16 = int16(f);");    if( i16 != - 12 ) fail = true;
	ui   = 123;    engine->ExecuteString(0, "i16 = int16(ui);");   if( i16 !=  123 ) fail = true;
	ui8  = 123;    engine->ExecuteString(0, "i16 = int16(ui8);");  if( i16 !=  123 ) fail = true;
	ui16 = 123;    engine->ExecuteString(0, "i16 = int16(ui16);"); if( i16 !=  123 ) fail = true;
	ui64 = 123;    engine->ExecuteString(0, "i16 = int16(ui64);"); if( i16 !=  123 ) fail = true;
	i    = -123;   engine->ExecuteString(0, "i16 = int16(i);");    if( i16 != -123 ) fail = true;
	i8   = -123;   engine->ExecuteString(0, "i16 = int16(i8);");   if( i16 != -123 ) fail = true;
	i16  = -123;   engine->ExecuteString(0, "i16 = int16(i16);");  if( i16 != -123 ) fail = true;
	i64  = -123;   engine->ExecuteString(0, "i16 = int16(i64);");  if( i16 != -123 ) fail = true;

	d    = 12.3;   engine->ExecuteString(0, "i16 = d;");    if( i16 !=   12 ) fail = true; 
	f    = -12.3f; engine->ExecuteString(0, "i16 = f;");    if( i16 != - 12 ) fail = true;
	ui   = 123;    engine->ExecuteString(0, "i16 = ui;");   if( i16 !=  123 ) fail = true;
	ui8  = 123;    engine->ExecuteString(0, "i16 = ui8;");  if( i16 !=  123 ) fail = true;
	ui16 = 123;    engine->ExecuteString(0, "i16 = ui16;"); if( i16 !=  123 ) fail = true;
	ui64 = 123;    engine->ExecuteString(0, "i16 = ui64;"); if( i16 !=  123 ) fail = true;
	i    = -123;   engine->ExecuteString(0, "i16 = i;");    if( i16 != -123 ) fail = true;
	i8   = -123;   engine->ExecuteString(0, "i16 = i8;");   if( i16 != -123 ) fail = true;
	i16  = -123;   engine->ExecuteString(0, "i16 = i16;");  if( i16 != -123 ) fail = true;
	i64  = -123;   engine->ExecuteString(0, "i16 = i64;");  if( i16 != -123 ) fail = true;

	engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL);
	engine->ExecuteString(0, "i16 = 12.3;  "); if( i16 !=   12 ) fail = true; 
	engine->ExecuteString(0, "i16 = -12.3f;"); if( i16 != - 12 ) fail = true;
	engine->ExecuteString(0, "i16 = 123;   "); if( i16 !=  123 ) fail = true;
	engine->ExecuteString(0, "i16 = -123;  "); if( i16 != -123 ) fail = true;
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);

	d    = 12.3;   engine->ExecuteString(0, "ui64 = uint64(d);");      if( ui64  !=   12 ) fail = true; 
	f    = -12.3f; engine->ExecuteString(0, "ui64 = uint64(f);");      if( ui64  != - 12 ) fail = true;
	ui   = 123;    engine->ExecuteString(0, "ui64 = uint64(ui);");     if( ui64  !=  123 ) fail = true;
	ui8  = 123;    engine->ExecuteString(0, "ui64 = uint64(ui8);");    if( ui64  !=  123 ) fail = true;
	ui16 = 123;    engine->ExecuteString(0, "ui64 = uint64(ui16);");   if( ui64  !=  123 ) fail = true;
	ui64 = 123;    engine->ExecuteString(0, "ui64 = uint64(ui64);");   if( ui64  !=  123 ) fail = true;
	i    = -123;   engine->ExecuteString(0, "ui64 = uint64(i);");      if( ui64  != -123 ) fail = true;
	i8   = -123;   engine->ExecuteString(0, "ui64 = uint64(i8);");     if( ui64  != -123 ) fail = true;
	i16  = -123;   engine->ExecuteString(0, "ui64 = uint64(i16);");    if( ui64  != -123 ) fail = true;
	i64  = -123;   engine->ExecuteString(0, "ui64 = uint64(i64);");    if( ui64  != -123 ) fail = true;

	d    = 12.3;   engine->ExecuteString(0, "ui64 = d;");      if( ui64  !=   12 ) fail = true; 
	f    = -12.3f; engine->ExecuteString(0, "ui64 = f;");      if( ui64  != - 12 ) fail = true;
	ui   = 123;    engine->ExecuteString(0, "ui64 = ui;");     if( ui64  !=  123 ) fail = true;
	ui8  = 123;    engine->ExecuteString(0, "ui64 = ui8;");    if( ui64  !=  123 ) fail = true;
	ui16 = 123;    engine->ExecuteString(0, "ui64 = ui16;");   if( ui64  !=  123 ) fail = true;
	ui64 = 123;    engine->ExecuteString(0, "ui64 = ui64;");   if( ui64  !=  123 ) fail = true;
	i    = -123;   engine->ExecuteString(0, "ui64 = i;");      if( ui64  != -123 ) fail = true;
	i8   = -123;   engine->ExecuteString(0, "ui64 = i8;");     if( ui64  != -123 ) fail = true;
	i16  = -123;   engine->ExecuteString(0, "ui64 = i16;");    if( ui64  != -123 ) fail = true;
	i64  = -123;   engine->ExecuteString(0, "ui64 = i64;");    if( ui64  != -123 ) fail = true;

	engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL);
	engine->ExecuteString(0, "ui64 = 12.3;  "); if( ui64  !=   12 ) fail = true; 
	engine->ExecuteString(0, "ui64 = -12.3f;"); if( ui64  != - 12 ) fail = true;
	engine->ExecuteString(0, "ui64 = 123;   "); if( ui64  !=  123 ) fail = true;
	engine->ExecuteString(0, "ui64 = -123;  "); if( ui64  != -123 ) fail = true;
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);

	d    = 12.3;   engine->ExecuteString(0, "ui = uint(d);");    if( ui != 12           ) fail = true; 
	f    = -12.3f; engine->ExecuteString(0, "ui = uint(f);");    if( ui != asUINT(-12)  ) fail = true;
	ui   = 123;    engine->ExecuteString(0, "ui = uint(ui);");   if( ui !=  123         ) fail = true;
	ui8  = 123;    engine->ExecuteString(0, "ui = uint(ui8);");  if( ui !=  123         ) fail = true;
	ui16 = 123;    engine->ExecuteString(0, "ui = uint(ui16);"); if( ui !=  123         ) fail = true;
	ui64 = 123;    engine->ExecuteString(0, "ui = uint(ui64);"); if( ui !=  123         ) fail = true;
	i    = -123;   engine->ExecuteString(0, "ui = uint(i);");    if( ui != asUINT(-123) ) fail = true;
	i8   = -123;   engine->ExecuteString(0, "ui = uint(i8);");   if( ui != asUINT(-123) ) fail = true;
	i16  = -123;   engine->ExecuteString(0, "ui = uint(i16);");  if( ui != asUINT(-123) ) fail = true;
	i64  = -123;   engine->ExecuteString(0, "ui = uint(i64);");  if( ui != asUINT(-123) ) fail = true;

	d    = 12.3;   engine->ExecuteString(0, "ui = d;");    if( ui != 12           ) fail = true; 
	f    = -12.3f; engine->ExecuteString(0, "ui = f;");    if( ui != asUINT(-12)  ) fail = true;
	ui   = 123;    engine->ExecuteString(0, "ui = ui;");   if( ui !=  123         ) fail = true;
	ui8  = 123;    engine->ExecuteString(0, "ui = ui8;");  if( ui !=  123         ) fail = true;
	ui16 = 123;    engine->ExecuteString(0, "ui = ui16;"); if( ui !=  123         ) fail = true;
	ui64 = 123;    engine->ExecuteString(0, "ui = ui64;"); if( ui !=  123         ) fail = true;
	i    = -123;   engine->ExecuteString(0, "ui = i;");    if( ui != asUINT(-123) ) fail = true;
	i8   = -123;   engine->ExecuteString(0, "ui = i8;");   if( ui != asUINT(-123) ) fail = true;
	i16  = -123;   engine->ExecuteString(0, "ui = i16;");  if( ui != asUINT(-123) ) fail = true;
	i64  = -123;   engine->ExecuteString(0, "ui = i64;");  if( ui != asUINT(-123) ) fail = true;

	engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL);
	engine->ExecuteString(0, "ui = 12.3;  "); if( ui != 12           ) fail = true; 
	engine->ExecuteString(0, "ui = -12.3f;"); if( ui != asUINT(-12)  ) fail = true;
	engine->ExecuteString(0, "ui = 123;   "); if( ui !=  123         ) fail = true;
	engine->ExecuteString(0, "ui = -123;  "); if( ui != asUINT(-123) ) fail = true;
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);

	d    = 12.3;   engine->ExecuteString(0, "ui8 = uint8(d);");    if( ui8 != 12           ) fail = true; 
	f    = -12.3f; engine->ExecuteString(0, "ui8 = uint8(f);");    if( ui8 != asBYTE(-12)  ) fail = true;
	ui   = 123;    engine->ExecuteString(0, "ui8 = uint8(ui);");   if( ui8 !=  123         ) fail = true;
	ui8  = 123;    engine->ExecuteString(0, "ui8 = uint8(ui8);");  if( ui8 !=  123         ) fail = true;
	ui16 = 123;    engine->ExecuteString(0, "ui8 = uint8(ui16);"); if( ui8 !=  123         ) fail = true;
	ui64 = 123;    engine->ExecuteString(0, "ui8 = uint8(ui64);"); if( ui8 !=  123         ) fail = true;
	i    = -123;   engine->ExecuteString(0, "ui8 = uint8(i);");    if( ui8 != asBYTE(-123) ) fail = true;
	i8   = -123;   engine->ExecuteString(0, "ui8 = uint8(i8);");   if( ui8 != asBYTE(-123) ) fail = true;
	i16  = -123;   engine->ExecuteString(0, "ui8 = uint8(i16);");  if( ui8 != asBYTE(-123) ) fail = true;
	i64  = -123;   engine->ExecuteString(0, "ui8 = uint8(i64);");  if( ui8 != asBYTE(-123) ) fail = true;

	d    = 12.3;   engine->ExecuteString(0, "ui8 = d;");    if( ui8 != 12           ) fail = true; 
	f    = -12.3f; engine->ExecuteString(0, "ui8 = f;");    if( ui8 != asBYTE(-12)  ) fail = true;
	ui   = 123;    engine->ExecuteString(0, "ui8 = ui;");   if( ui8 !=  123         ) fail = true;
	ui8  = 123;    engine->ExecuteString(0, "ui8 = ui8;");  if( ui8 !=  123         ) fail = true;
	ui16 = 123;    engine->ExecuteString(0, "ui8 = ui16;"); if( ui8 !=  123         ) fail = true;
	ui64 = 123;    engine->ExecuteString(0, "ui8 = ui64;"); if( ui8 !=  123         ) fail = true;
	i    = -123;   engine->ExecuteString(0, "ui8 = i;");    if( ui8 != asBYTE(-123) ) fail = true;
	i8   = -123;   engine->ExecuteString(0, "ui8 = i8;");   if( ui8 != asBYTE(-123) ) fail = true;
	i16  = -123;   engine->ExecuteString(0, "ui8 = i16;");  if( ui8 != asBYTE(-123) ) fail = true;
	i64  = -123;   engine->ExecuteString(0, "ui8 = i64;");  if( ui8 != asBYTE(-123) ) fail = true;

	engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL);
	engine->ExecuteString(0, "ui8 = 12.3;  "); if( ui8 != 12           ) fail = true; 
	engine->ExecuteString(0, "ui8 = -12.3f;"); if( ui8 != asBYTE(-12)  ) fail = true; // asBYTE(-12.3f) doesn't seem to produce the same result on MSVC and GNUC
	engine->ExecuteString(0, "ui8 = 123;   "); if( ui8 !=  123         ) fail = true;
	engine->ExecuteString(0, "ui8 = -123;  "); if( ui8 != asBYTE(-123) ) fail = true;
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);

	d    = 12.3;   engine->ExecuteString(0, "ui16 = uint16(d);");    if( ui16 != 12           ) fail = true; 
	f    = -12.3f; engine->ExecuteString(0, "ui16 = uint16(f);");    if( ui16 != asWORD(-12)  ) fail = true;
	ui   = 123;    engine->ExecuteString(0, "ui16 = uint16(ui);");   if( ui16 !=  123         ) fail = true;
	ui8  = 123;    engine->ExecuteString(0, "ui16 = uint16(ui8);");  if( ui16 !=  123         ) fail = true;
	ui16 = 123;    engine->ExecuteString(0, "ui16 = uint16(ui16);"); if( ui16 !=  123         ) fail = true;
	ui64 = 123;    engine->ExecuteString(0, "ui16 = uint16(ui64);"); if( ui16 !=  123         ) fail = true;
	i    = -123;   engine->ExecuteString(0, "ui16 = uint16(i);");    if( ui16 != asWORD(-123) ) fail = true;
	i8   = -123;   engine->ExecuteString(0, "ui16 = uint16(i8);");   if( ui16 != asWORD(-123) ) fail = true;
	i16  = -123;   engine->ExecuteString(0, "ui16 = uint16(i16);");  if( ui16 != asWORD(-123) ) fail = true;
	i64  = -123;   engine->ExecuteString(0, "ui16 = uint16(i64);");  if( ui16 != asWORD(-123) ) fail = true;

	d    = 12.3;   engine->ExecuteString(0, "ui16 = d;");    if( ui16 != 12           ) fail = true; 
	f    = -12.3f; engine->ExecuteString(0, "ui16 = f;");    if( ui16 != asWORD(-12)  ) fail = true;
	ui   = 123;    engine->ExecuteString(0, "ui16 = ui;");   if( ui16 !=  123         ) fail = true;
	ui8  = 123;    engine->ExecuteString(0, "ui16 = ui8;");  if( ui16 !=  123         ) fail = true;
	ui16 = 123;    engine->ExecuteString(0, "ui16 = ui16;"); if( ui16 !=  123         ) fail = true;
	ui64 = 123;    engine->ExecuteString(0, "ui16 = ui64;"); if( ui16 !=  123         ) fail = true;
	i    = -123;   engine->ExecuteString(0, "ui16 = i;");    if( ui16 != asWORD(-123) ) fail = true;
	i8   = -123;   engine->ExecuteString(0, "ui16 = i8;");   if( ui16 != asWORD(-123) ) fail = true;
	i16  = -123;   engine->ExecuteString(0, "ui16 = i16;");  if( ui16 != asWORD(-123) ) fail = true;
	i64  = -123;   engine->ExecuteString(0, "ui16 = i64;");  if( ui16 != asWORD(-123) ) fail = true;

	engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL);
	engine->ExecuteString(0, "ui16 = 12.3;  "); if( ui16 != 12           ) fail = true; 
	engine->ExecuteString(0, "ui16 = -12.3f;"); if( ui16 != asWORD(-12)  ) fail = true; // asWORD(-12.3f) doesn't seem to produce the same result on MSVC and GNUC
	engine->ExecuteString(0, "ui16 = 123;   "); if( ui16 !=  123         ) fail = true;
	engine->ExecuteString(0, "ui16 = -123;  "); if( ui16 != asWORD(-123) ) fail = true;
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);

	engine->ExecuteString(0, "TestDouble(d); TestFloat(d); TestInt(d); TestI16(d); TestI8(d); TestUInt(d); TestUI16(d); TestUI8(d);");
	engine->ExecuteString(0, "TestDouble(f); TestFloat(f); TestInt(f); TestI16(f); TestI8(f); TestUInt(f); TestUI16(f); TestUI8(f);");
	engine->ExecuteString(0, "TestDouble(ui); TestFloat(ui); TestInt(ui); TestI16(ui); TestI8(ui); TestUInt(ui); TestUI16(ui); TestUI8(ui);");
	engine->ExecuteString(0, "TestDouble(ui8); TestFloat(ui8); TestInt(ui8); TestI16(ui8); TestI8(ui8); TestUInt(ui8); TestUI16(ui8); TestUI8(ui8);");
	engine->ExecuteString(0, "TestDouble(ui16); TestFloat(ui16); TestInt(ui16); TestI16(ui16); TestI8(ui16); TestUInt(ui16); TestUI16(ui16); TestUI8(ui16);");
	engine->ExecuteString(0, "TestDouble(ui64); TestFloat(ui64); TestInt(ui64); TestI16(ui64); TestI8(ui64); TestUInt(ui64); TestUI16(ui64); TestUI8(ui64);");
	engine->ExecuteString(0, "TestDouble(i); TestFloat(i); TestInt(i); TestI16(i); TestI8(i); TestUInt(i); TestUI16(i); TestUI8(i);");
	engine->ExecuteString(0, "TestDouble(i8); TestFloat(i8); TestInt(i8); TestI16(i8); TestI8(i8); TestUInt(i8); TestUI16(i8); TestUI8(i8);");
	engine->ExecuteString(0, "TestDouble(i16); TestFloat(i16); TestInt(i16); TestI16(i16); TestI8(i16); TestUInt(i16); TestUI16(i16); TestUI8(i16);");
	engine->ExecuteString(0, "TestDouble(i64); TestFloat(i64); TestInt(i64); TestI16(i64); TestI8(i64); TestUInt(i64); TestUI16(i64); TestUI8(i64);");

	d = 0; i8 = -22; engine->ExecuteString(0, "d = d + i8"); if( d != -22 ) fail = true;

	engine->ExecuteString(0, "int[] a(1); a[0] = 0; a[0] == 1");
	engine->ExecuteString(0, "ui + i");
	engine->ExecuteString(0, "int a = 0, ui = 0; (a+ui)&1;");

	// There is no bitwise conversion between uint to float anymore
	// f = 0; engine->ExecuteString(0, "f = float(0x3f800000)"); if( f != 1 ) fail = true;

	bout.buffer = "";
	engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL);
	engine->ExecuteString(0, "i == ui"); 
	if( bout.buffer != "ExecuteString (1, 3) : Warning : Signed/Unsigned mismatch\n" )
		fail = true;

	bout.buffer = "";

	int r;

	// TODO: PPC: We cannot allow this with PPC
	// Allow the conversion of a type to another even for reference parameters (C++ doesn't allow this)
	r = engine->ExecuteString(0, "TestDoubleByRef(d); TestFloatByRef(d); TestIntByRef(d); TestI16ByRef(d); TestI8ByRef(d); TestUIntByRef(d); TestUI16ByRef(d); TestUI8ByRef(d);"); if( r < 0 ) fail = true;
	r = engine->ExecuteString(0, "TestDoubleByRef(f); TestFloatByRef(f); TestIntByRef(f); TestI16ByRef(f); TestI8ByRef(f); TestUIntByRef(f); TestUI16ByRef(f); TestUI8ByRef(f);"); if( r < 0 ) fail = true;
	r = engine->ExecuteString(0, "TestDoubleByRef(ui); TestFloatByRef(ui); TestIntByRef(ui); TestI16ByRef(ui); TestI8ByRef(ui); TestUIntByRef(ui); TestUI16ByRef(ui); TestUI8ByRef(ui);"); if( r < 0 ) fail = true;
	r = engine->ExecuteString(0, "TestDoubleByRef(ui8); TestFloatByRef(ui8); TestIntByRef(ui8); TestI16ByRef(ui8); TestI8ByRef(ui8); TestUIntByRef(ui8); TestUI16ByRef(ui8); TestUI8ByRef(ui8);"); if( r < 0 ) fail = true;
	r = engine->ExecuteString(0, "TestDoubleByRef(ui16); TestFloatByRef(ui16); TestIntByRef(ui16); TestI16ByRef(ui16); TestI8ByRef(ui16); TestUIntByRef(ui16); TestUI16ByRef(ui16); TestUI8ByRef(ui16);"); if( r < 0 ) fail = true;
	r = engine->ExecuteString(0, "TestDoubleByRef(ui64); TestFloatByRef(ui64); TestIntByRef(ui64); TestI16ByRef(ui64); TestI8ByRef(ui64); TestUIntByRef(ui64); TestUI16ByRef(ui64); TestUI8ByRef(ui64);"); if( r < 0 ) fail = true;
	r = engine->ExecuteString(0, "TestDoubleByRef(i); TestFloatByRef(i); TestIntByRef(i); TestI16ByRef(i); TestI8ByRef(i); TestUIntByRef(i); TestUI16ByRef(i); TestUI8ByRef(i);"); if( r < 0 ) fail = true;
	r = engine->ExecuteString(0, "TestDoubleByRef(i8); TestFloatByRef(i8); TestIntByRef(i8); TestI16ByRef(i8); TestI8ByRef(i8); TestUIntByRef(i8); TestUI16ByRef(i8); TestUI8ByRef(i8);"); if( r < 0 ) fail = true;
	r = engine->ExecuteString(0, "TestDoubleByRef(i16); TestFloatByRef(i16); TestIntByRef(i16); TestI16ByRef(i16); TestI8ByRef(i16); TestUIntByRef(i16); TestUI16ByRef(i16); TestUI8ByRef(i16);"); if( r < 0 ) fail = true;
	r = engine->ExecuteString(0, "TestDoubleByRef(i64); TestFloatByRef(i64); TestIntByRef(i64); TestI16ByRef(i64); TestI8ByRef(i64); TestUIntByRef(i64); TestUI16ByRef(i64); TestUI8ByRef(i64);"); if( r < 0 ) fail = true;

	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
	asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection("script", script, strlen(script));
	mod->Build();

	// This test is to make sure that the float is in fact converted to a double
	engine->ExecuteString(0, "TestScript();");

	// Make sure uint and int can be converted to bits when using the ~ operator
	engine->ExecuteString(0, "uint x = 0x34; x = ~x;");
	engine->ExecuteString(0, "int x = 0x34; x = ~x;");

	engine->Release();

	if( fail )
		printf("%s: failed\n", TESTNAME);

	// Success
	return fail;
}
コード例 #24
0
bool Test()
{
	bool fail = false;
	asIScriptEngine *engine;
	int r;
	COutStream out;

	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);
		engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);

		const char *script =
			"int func() { return var; } \n"
			"int func2() { return var; } \n"
			"int var = 0; \n"
			"class cl { cl() {v = 0;} int v; } \n"
			"interface i {} \n"
			"enum e { e1 = 0 } \n"
			"funcdef void fd(); \n"
			// Namespaces allow same entities to be declared again
			"namespace a { \n"
			"  int func() { return var; } \n" // Should find the global var in the same namespace
			"  int func2() { return func(); } \n" // Should find the global function in the same namespace
			"  int var = 1; \n"
			"  class cl { cl() {v = 1;} int v; } \n"
			"  interface i {} \n"
			"  enum e { e1 = 1 } \n"
			"  funcdef void fd(); \n"
			// Nested namespaces are allowed
			"  namespace b { \n"
			"    int var = 2; \n"
			"  } \n"
			"} \n"
			// It's possible to specify exactly which one is wanted
			"cl gc; \n"
			"a::cl gca; \n"
			"void main() \n"
			"{ \n"
			"  assert(var == 0); \n"
			"  assert(::var == 0); \n"
			"  assert(a::var == 1); \n"
			"  assert(a::b::var == 2); \n"
			"  assert(func() == 0); \n"
			"  assert(a::func() == 1); \n"
			"  assert(func2() == 0); \n"
			"  assert(a::func2() == 1); \n"
			"  assert(e1 == 0); \n"
			"  assert(::e1 == 0); \n"
			"  assert(e::e1 == 0); \n"
			"  assert(::e::e1 == 0); \n"
			"  assert(a::e1 == 1); \n"
			"  assert(a::e::e1 == 1); \n"
			"  cl c; \n"
			"  a::cl ca; \n"
			"  assert(c.v == 0); \n"
			"  assert(ca.v == 1); \n"
			"  assert(gc.v == 0); \n"
			"  assert(gca.v == 1); \n"
			"} \n";

		asIScriptModule *mod = engine->GetModule("mod", asGM_ALWAYS_CREATE);
		mod->AddScriptSection("", script);
		r = mod->Build();
		if( r < 0 )
			TEST_FAILED;

		r = ExecuteString(engine, "main()", mod);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;

		// Test saving and loading 
		CBytecodeStream s("");
		mod->SaveByteCode(&s);

		asIScriptModule *mod2 = engine->GetModule("mod2", asGM_ALWAYS_CREATE);
		mod2->LoadByteCode(&s);

		r = ExecuteString(engine, "main()", mod2);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;

		engine->Release();
	}

	// TODO: It should be possible to inform the namespace when querying by declaration
	// TODO: It should be possible to choose whether to include namespace or not when getting declarations

	// Success
	return fail;
}
コード例 #25
0
bool Test2Modules()
{
	bool fail = false;
	int r;

	asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
	
	asIScriptModule *mod = engine->GetModule("a", asGM_ALWAYS_CREATE);
	mod->AddScriptSection("script", script, strlen(script), 0);
	if( mod->Build() < 0 )
	{
		printf("%s: failed to build module a\n", TESTNAME);
		TEST_FAILED;
	}

	mod = engine->GetModule("b", asGM_ALWAYS_CREATE);
	mod->AddScriptSection("script", script, strlen(script), 0);
	if( mod->Build() < 0 )
	{
		printf("%s: failed to build module b\n", TESTNAME);
		TEST_FAILED;
	}

	if( !fail )
	{
		asIScriptFunction *aFunc = engine->GetModule("a")->GetFunctionByName("Test");
		if( aFunc == 0 )
		{
			printf("%s: failed to retrieve func ID for module a\n", TESTNAME);
			TEST_FAILED;
		}

		asIScriptFunction *bFunc = engine->GetModule("b")->GetFunctionByName("Test");
		if( bFunc == 0 )
		{
			printf("%s: failed to retrieve func ID for module b\n", TESTNAME);
			TEST_FAILED;
		}
	}

	engine->Release();

	// Test using an object created in another module
	engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
	engine->RegisterInterface("ITest");
	engine->RegisterInterfaceMethod("ITest", "void test()");
	const char *scriptA = "ITest @obj;";
	const char *scriptB = 
	"class CTest : ITest        \n"
	"{                          \n"
	"  void test() {glob = 42;} \n"
	"}                          \n"
	"int glob = 0;              \n";

	mod = engine->GetModule("a", asGM_ALWAYS_CREATE);
	mod->AddScriptSection("scriptA", scriptA, strlen(scriptA));
	r = mod->Build();
	if( r < 0 ) TEST_FAILED;

	mod = engine->GetModule("b", asGM_ALWAYS_CREATE);
	mod->AddScriptSection("scriptB", scriptB, strlen(scriptB));
	mod->Build();
	if( r < 0 ) TEST_FAILED;

	asIScriptObject *obj = (asIScriptObject*)engine->CreateScriptObject(engine->GetModule("b")->GetObjectTypeByName("CTest"));
	*((asIScriptObject**)engine->GetModule("a")->GetAddressOfGlobalVar(0)) = obj;
	r = ExecuteString(engine, "obj.test()", engine->GetModule("a"));
	if( r != asEXECUTION_FINISHED ) TEST_FAILED;
	int val = *(int*)engine->GetModule("b")->GetAddressOfGlobalVar(engine->GetModule("b")->GetGlobalVarIndexByName("glob"));
	if( val != 42 ) TEST_FAILED;

	engine->Release();

	return fail;
}
コード例 #26
0
// This test was reported by Zeu5 on 2009-03-24
// It used to crash on the second call to Build(), and also on ExecuteString()
bool Test2()
{
	bool fail = false;
	int r;

	asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
	engine->BeginConfigGroup("MyGroup");
	engine->RegisterInterface("MyHostDefinedInterface");
	engine->RegisterInterfaceMethod("MyHostDefinedInterface", "void doSomething()");
	engine->EndConfigGroup();

	const char *script = "class MyScriptedClass : MyHostDefinedInterface\n"
						 "{\n"
						 "   void doSomething() { /* nothing */ }\n"
						 "} \n"
						 "void Test()  \n"
						 "{ \n"
						 "  MyScriptedClass @b = MyScriptedClass(); \n"
						 "} \n";

	asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection("script", script);
	r = mod->Build();
	if( r < 0 )
	{
		fail = true;
	}

	r = engine->ExecuteString(0, "Test()");
	if( r != asEXECUTION_FINISHED )
	{
		fail = true;
	}

	engine->DiscardModule(0);
	r = engine->RemoveConfigGroup("MyGroup");
	if( r < 0 )
	{
		fail = true;
	}

	// Now do everything again
	engine->BeginConfigGroup("MyGroup");
	engine->RegisterInterface("MyHostDefinedInterface");
	engine->RegisterInterfaceMethod("MyHostDefinedInterface", "void doSomething()");
	engine->EndConfigGroup();

	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection("script", script);
	r = mod->Build();
	if( r < 0 )
	{
		fail = true;
	}

	r = engine->ExecuteString(0, "Test()");
	if( r != asEXECUTION_FINISHED )
	{
		fail = true;
	}

	engine->Release();

	return fail;
}
コード例 #27
0
bool TestCDecl_ClassA()
{
	if( strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY") )
	{
		printf("%s: Skipped due to AS_MAX_PORTABILITY\n", TESTNAME);
		return false;
	}

	bool fail = false;

	asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);

	engine->RegisterObjectType("class1", sizeof(ClassA1), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS_A | asOBJ_APP_CLASS_ALLINTS);
	engine->RegisterObjectType("class2", sizeof(ClassA2), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS_A | asOBJ_APP_CLASS_ALLINTS);
	engine->RegisterObjectType("class3", sizeof(ClassA3), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS_A | asOBJ_APP_CLASS_ALLINTS);
	
	engine->RegisterGlobalProperty("class1 c1", &c1);
	engine->RegisterGlobalProperty("class2 c2", &c2);
	engine->RegisterGlobalProperty("class3 c3", &c3);

	engine->RegisterGlobalFunction("class1 _class1()", asFUNCTION(classA1), asCALL_CDECL);
	engine->RegisterGlobalFunction("class2 _class2()", asFUNCTION(classA2), asCALL_CDECL);
	engine->RegisterGlobalFunction("class3 _class3()", asFUNCTION(classA3), asCALL_CDECL);

	COutStream out;

	c1.a = 0;

	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
	int r = ExecuteString(engine, "c1 = _class1();");
	if( r < 0 )
	{
		printf("%s: ExecuteString() failed %d\n", TESTNAME, r);
		TEST_FAILED;
	}

	if( c1.a != 0xDEADC0DE )
	{
		printf("%s: Failed to assign object returned from function. c1.a = %X\n", TESTNAME, (unsigned int)c1.a);
		TEST_FAILED;
	}


	c2.a = 0;
	c2.b = 0;

	r = ExecuteString(engine, "c2 = _class2();");
	if( r < 0 )
	{
		printf("%s: ExecuteString() failed %d\n", TESTNAME, r);
		TEST_FAILED;
	}

	if( c2.a != 0xDEADC0DE )
	{
		printf("%s: Failed to assign object returned from function. c2.a = %X\n", TESTNAME, (unsigned int)c2.a);
		TEST_FAILED;
	}

	if( c2.b != 0x01234567 )
	{
		printf("%s: Failed to assign object returned from function. c2.b = %X\n", TESTNAME, (unsigned int)c2.b);
		TEST_FAILED;
	}

	c3.a = 0;
	c3.b = 0;
	c3.c = 0;

	r = ExecuteString(engine, "c3 = _class3();");
	if( r < 0 )
	{
		printf("%s: ExecuteString() failed %d\n", TESTNAME, r);
		TEST_FAILED;
	}

	if( c3.a != 0xDEADC0DE )
	{
		printf("%s: Failed to assign object returned from function. c3.a = %X\n", TESTNAME, (unsigned int)c3.a);
		TEST_FAILED;
	}

	if( c3.b != 0x01234567 )
	{
		printf("%s: Failed to assign object returned from function. c3.b = %X\n", TESTNAME, (unsigned int)c3.b);
		TEST_FAILED;
	}

	if( c3.c != 0x89ABCDEF )
	{
		printf("%s: Failed to assign object returned from function. c3.c = %X\n", TESTNAME, (unsigned int)c3.c);
		TEST_FAILED;
	}

	// Test passing the object types by value to a system function
	r = engine->RegisterGlobalFunction("void class1ByVal(class1)", asFUNCTION(class1ByVal), asCALL_CDECL); assert( r >= 0 );
	r = ExecuteString(engine, "class1 c = _class1(); class1ByVal(c)");
	if( r != asEXECUTION_FINISHED )
		TEST_FAILED;

	r = engine->RegisterGlobalFunction("void class2ByVal(class2)", asFUNCTION(class2ByVal), asCALL_CDECL); assert( r >= 0 );
	r = ExecuteString(engine, "class2 c = _class2(); class2ByVal(c)");
	if( r != asEXECUTION_FINISHED )
		TEST_FAILED;

	r = engine->RegisterGlobalFunction("void class3ByVal(class3)", asFUNCTION(class3ByVal), asCALL_CDECL); assert( r >= 0 );
	r = ExecuteString(engine, "class3 c = _class3(); class3ByVal(c)");
	if( r != asEXECUTION_FINISHED )
		TEST_FAILED;

	engine->Release();

	return fail;
}
コード例 #28
0
bool Test()
{
	bool fail = Test2();
	int r;

	//------------
	// Test global function
	asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);

	r = engine->BeginConfigGroup("group1"); assert( r >= 0 );
	r = engine->RegisterGlobalFunction("void MyFunc()", asFUNCTION(MyFunc), asCALL_GENERIC); assert( r >= 0 );
	r = engine->EndConfigGroup(); assert( r >= 0 );

	COutStream out;
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
	asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection(TESTNAME, script1, strlen(script1), 0);
	r = mod->Build();
	if( r < 0 )
	{
		fail = true;
	}

	r = engine->RemoveConfigGroup("group1"); assert( r == asCONFIG_GROUP_IS_IN_USE );

	engine->DiscardModule(0);

	r = engine->RemoveConfigGroup("group1"); assert( r >= 0 );

	CBufferedOutStream bout;
	engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL);
	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection(TESTNAME, script1, strlen(script1), 0);
	r = mod->Build();
	if( r >= 0 || bout.buffer != "TestDynamicConfig (1, 1) : Info    : Compiling void Test()\n"
                                 "TestDynamicConfig (3, 3) : Error   : No matching signatures to 'MyFunc()'\n" )
	{
		fail = true;
	}

	engine->Release();

	//----------------
	// Test global property
	engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);

	r = engine->BeginConfigGroup("group1"); assert( r >= 0 );
	r = engine->RegisterGlobalProperty("int global", 0); assert( r >= 0 );
	r = engine->EndConfigGroup(); assert( r >= 0 );

	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection(TESTNAME, script2, strlen(script2), 0);
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
	r = mod->Build();
	if( r < 0 )
	{
		fail = true;
	}

	r = engine->RemoveConfigGroup("group1"); assert( r == asCONFIG_GROUP_IS_IN_USE );

	engine->DiscardModule(0);

	r = engine->RemoveConfigGroup("group1"); assert( r >= 0 );

	bout.buffer = "";
	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection(TESTNAME, script2, strlen(script2), 0);
	engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL);
	r = mod->Build();
	if( r >= 0 || bout.buffer != "TestDynamicConfig (1, 1) : Info    : Compiling void Test()\n"
                                 "TestDynamicConfig (3, 3) : Error   : 'global' is not declared\n" )
	{
		fail = true;
	}

	// Try registering the property again
	r = engine->BeginConfigGroup("group1"); assert( r >= 0 );
	r = engine->RegisterGlobalProperty("int global", 0); assert( r >= 0 );
	r = engine->EndConfigGroup(); assert( r >= 0 );

	engine->Release();

	//-------------
	// Test object types
	engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);

	r = engine->BeginConfigGroup("group1"); assert( r >= 0 );
	r = engine->RegisterObjectType("mytype", sizeof(int), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_PRIMITIVE);
	r = engine->EndConfigGroup(); assert( r >= 0 );

	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection(TESTNAME, script3, strlen(script3), 0);
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
	r = mod->Build();
	if( r < 0 )
	{
		fail = true;
	}

	r = engine->RemoveConfigGroup("group1"); assert( r == asCONFIG_GROUP_IS_IN_USE );

	engine->DiscardModule(0);

	r = engine->RemoveConfigGroup("group1"); assert( r >= 0 );

	bout.buffer = "";
	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection(TESTNAME, script3, strlen(script3), 0);
	engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL);
	r = mod->Build();
	if( r >= 0 || bout.buffer != "TestDynamicConfig (1, 1) : Info    : Compiling void Test()\n"
                                 "TestDynamicConfig (3, 10) : Error   : Expected ';'\n" )
	{
		fail = true;
	}

	engine->Release();

	//------------------
	// Test global behaviours
	engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);

	RegisterScriptString_Generic(engine);

	r = engine->BeginConfigGroup("group1"); assert( r >= 0 );
	r = engine->RegisterObjectType("mytype", sizeof(int), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_PRIMITIVE);
	r = engine->RegisterObjectMethod("mytype", "string@ opAdd_r(const string &in)", asFUNCTION(MyFunc), asCALL_GENERIC); assert( r >= 0 );
	r = engine->EndConfigGroup(); assert( r >= 0 );

	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection(TESTNAME, script4, strlen(script4), 0);
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
	r = mod->Build();
	if( r < 0 )
	{
		fail = true;
	}

	r = engine->RemoveConfigGroup("group1"); assert( r == asCONFIG_GROUP_IS_IN_USE );

	engine->DiscardModule(0);

	r = engine->RemoveConfigGroup("group1"); assert( r >= 0 );

	// Register the type again, but without the operator overload
	r = engine->BeginConfigGroup("group1"); assert( r >= 0 );
	r = engine->RegisterObjectType("mytype", sizeof(int), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_PRIMITIVE);
	r = engine->EndConfigGroup(); assert( r >= 0 );

	bout.buffer = "";
	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection(TESTNAME, script4, strlen(script4), 0);
	engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL);
	r = mod->Build();
	if( r >= 0 || bout.buffer != "TestDynamicConfig (1, 1) : Info    : Compiling void Test()\n"
                                 "TestDynamicConfig (5, 9) : Error   : No matching operator that takes the types 'string&' and 'mytype&' found\n" )
	{
		fail = true;
	}

	engine->Release();

	//------------------
	// Test object types held by external variable, i.e. any

	// TODO: The application needs a way to tell the engine that the type is in use so that it won't be removed

/*	CScriptAny *any = 0;
	engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
	RegisterScriptAny(engine);

	engine->BeginConfigGroup("group1");
	r = engine->RegisterObjectType("mytype", sizeof(int), asOBJ_PRIMITIVE);
	r = engine->RegisterObjectBehaviour("mytype", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(Construct), asCALL_GENERIC);
	r = engine->RegisterObjectBehaviour("mytype", asBEHAVE_ADDREF, "void f()", asFUNCTION(AddRef), asCALL_GENERIC);
	r = engine->RegisterObjectBehaviour("mytype", asBEHAVE_RELEASE, "void f()", asFUNCTION(Release), asCALL_GENERIC);

	any = (CScriptAny*)engine->CreateScriptObject(engine->GetTypeIdByDecl(0, "any"));

	r = engine->RegisterGlobalProperty("any g_any", any);
	engine->EndConfigGroup();

	mod->AddScriptSection(0, TESTNAME, script5, strlen(script5), 0);
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
	r = mod->Build(0);
	if( r < 0 )
		fail = true;

	r = engine->ExecuteString(0, "Test()");
	if( r != asEXECUTION_FINISHED )
	{
		fail = true;
	}

	engine->Discard(0);
	engine->GarbageCollect();

	int *o = 0;
	any->Retrieve(&o, engine->GetTypeIdByDecl(0, "mytype@"));
	if( o == 0 )
		fail = true;
	if( --(*o) != 1 )
		fail = true;

	// The mytype variable is still stored in the any variable so we shouldn't be allowed to remove it's configuration group
	r = engine->RemoveConfigGroup("group1"); assert( r < 0 );

	any->Release();
	engine->GarbageCollect();

	// Now it should be possible to remove the group
	r = engine->RemoveConfigGroup("group1"); assert( r >= 0 );

	engine->Release();
*/
	//-------------
	// Test array types
	engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);

	r = engine->BeginConfigGroup("group1"); assert( r >= 0 );
	r = engine->RegisterObjectType("int[]", sizeof(int), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_PRIMITIVE);
	r = engine->EndConfigGroup(); assert( r >= 0 );

	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection(TESTNAME, script6, strlen(script6), 0);
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
	r = mod->Build();
	if( r < 0 )
	{
		fail = true;
	}

	r = engine->RemoveConfigGroup("group1"); assert( r == asCONFIG_GROUP_IS_IN_USE );

	engine->DiscardModule(0);

	r = engine->RemoveConfigGroup("group1"); assert( r >= 0 );

	engine->Release();

	//-------------
	// Test object types in struct members
	engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);

	r = engine->BeginConfigGroup("group1"); assert( r >= 0 );
	r = engine->RegisterObjectType("mytype", sizeof(int), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_PRIMITIVE);
	r = engine->EndConfigGroup(); assert( r >= 0 );

	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection(TESTNAME, script7, strlen(script7), 0);
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
	r = mod->Build();
	if( r < 0 )
	{
		fail = true;
	}

	r = engine->RemoveConfigGroup("group1"); assert( r == asCONFIG_GROUP_IS_IN_USE );

	engine->DiscardModule(0);

	r = engine->RemoveConfigGroup("group1"); assert( r >= 0 );

	bout.buffer = "";
	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection(TESTNAME, script7, strlen(script7), 0);
	engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL);
	r = mod->Build();
	if( r >= 0 || bout.buffer != "TestDynamicConfig (3, 3) : Error   : Identifier 'mytype' is not a data type\n" )
	{
		fail = true;
	}

	engine->Release();

	//-------------
	// Test object types in function declarations
	engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);

	r = engine->BeginConfigGroup("group1"); assert( r >= 0 );
	r = engine->RegisterObjectType("mytype", sizeof(int), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_PRIMITIVE);
	r = engine->EndConfigGroup(); assert( r >= 0 );

	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection(TESTNAME, script8, strlen(script8), 0);
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
	r = mod->Build();
	if( r < 0 )
	{
		fail = true;
	}

	r = engine->RemoveConfigGroup("group1"); assert( r == asCONFIG_GROUP_IS_IN_USE );

	engine->DiscardModule(0);

	r = engine->RemoveConfigGroup("group1"); assert( r >= 0 );

	bout.buffer = "";
	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection(TESTNAME, script8, strlen(script8), 0);
	engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL);
	r = mod->Build();
	if( r >= 0 || bout.buffer != "TestDynamicConfig (1, 11) : Error   : Identifier 'mytype' is not a data type\n"
								 "TestDynamicConfig (1, 1) : Info    : Compiling void Test(int&in)\n"
		                         "TestDynamicConfig (1, 11) : Error   : Identifier 'mytype' is not a data type\n" )
	{
		fail = true;
	}

	engine->Release();

	//-------------
	// Test object types in script arrays
	engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);

	r = engine->BeginConfigGroup("group1"); assert( r >= 0 );
	r = engine->RegisterObjectType("mytype", sizeof(int), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_PRIMITIVE);
	r = engine->EndConfigGroup(); assert( r >= 0 );

	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection(TESTNAME, script9, strlen(script9), 0);
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
	r = mod->Build();
	if( r < 0 )
	{
		fail = true;
	}

	r = engine->RemoveConfigGroup("group1"); assert( r == asCONFIG_GROUP_IS_IN_USE );

	engine->DiscardModule(0);

	r = engine->RemoveConfigGroup("group1"); assert( r >= 0 );

	bout.buffer = "";
	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection(TESTNAME, script9, strlen(script9), 0);
	engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL);
	r = mod->Build();
	if( r >= 0 || bout.buffer != "TestDynamicConfig (1, 1) : Info    : Compiling void Test()\n"
                                 "TestDynamicConfig (3, 11) : Error   : Expected expression value\n" )
	{
		fail = true;
	}

	engine->Release();


	//------------------
	// Test object types held by external variable, i.e. any
/*	engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
	RegisterScriptAny(engine);

	engine->BeginConfigGroup("group1");
	r = engine->RegisterObjectType("mytype", sizeof(int), asOBJ_PRIMITIVE);

	any = (CScriptAny*)engine->CreateScriptObject(engine->GetTypeIdByDecl(0, "any"));

	r = engine->RegisterGlobalProperty("any g_any", any);
	engine->EndConfigGroup();

	mod->AddScriptSection(0, TESTNAME, script10, strlen(script10), 0);
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
	r = mod->Build(0);
	if( r < 0 )
		fail = true;

	r = engine->ExecuteString(0, "Test()");
	if( r != asEXECUTION_FINISHED )
	{
		fail = true;
	}

	engine->Discard(0);
	engine->GarbageCollect();

	asIScriptArray *array = 0;
	any->Retrieve(&array, engine->GetTypeIdByDecl(0, "mytype[]@"));
	if( array == 0 )
		fail = true;
	else
		array->Release();

	engine->GarbageCollect();

	// The mytype variable is still stored in the any variable so we shouldn't be allowed to remove it's configuration group
	r = engine->RemoveConfigGroup("group1"); assert( r < 0 );

	any->Release();
	engine->GarbageCollect();

	// Now it should be possible to remove the group
	r = engine->RemoveConfigGroup("group1"); assert( r >= 0 );

	engine->Release();
*/
	//-------------------
	// Test references between config groups
	engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);

	engine->BeginConfigGroup("group1");
	r = engine->RegisterObjectType("mytype", sizeof(int), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_PRIMITIVE); assert( r >= 0 );
	engine->EndConfigGroup();

	engine->BeginConfigGroup("group2");
	r = engine->RegisterGlobalFunction("void func(mytype)", asFUNCTION(0), asCALL_GENERIC); assert( r >= 0 );
	engine->EndConfigGroup();

	r = engine->RemoveConfigGroup("group1"); assert( r == asCONFIG_GROUP_IS_IN_USE );

	r = engine->RemoveConfigGroup("group2"); assert( r <= 0 );

	r = engine->RemoveConfigGroup("group1"); assert( r <= 0 );

	engine->Release();

	//--------------------
	// Test situation where the default group references a dynamic group. It will then be impossible
	// to remove the dynamic group, but the application must still be able to release the engine.
	engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);

	engine->BeginConfigGroup("group1");
	r = engine->RegisterObjectType("mytype", sizeof(int), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_PRIMITIVE); assert( r >= 0 );
	engine->EndConfigGroup();

	r = engine->RegisterGlobalFunction("void func(mytype)", asFUNCTION(0), asCALL_GENERIC); assert( r >= 0 );

	r = engine->RemoveConfigGroup("group1"); assert( r == asCONFIG_GROUP_IS_IN_USE );

	engine->Release();

	//----------------------
	// Test that it is possible to repeat the registration of the config group
	engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);

	r = engine->BeginConfigGroup("g1"); assert( r >= 0 );
	RegisterScriptString_Generic(engine);
	r = engine->EndConfigGroup(); assert( r >= 0 );

	r = engine->ExecuteString(0, "string a = \"test\""); assert( r == asEXECUTION_FINISHED );

	r = engine->DiscardModule(0);  assert( r >= 0 );
	r = engine->GarbageCollect(); assert( r >= 0 );

	r = engine->RemoveConfigGroup("g1"); assert( r >= 0 );

	// again..
	r = engine->BeginConfigGroup("g1"); assert( r >= 0 );
	RegisterScriptString_Generic(engine);
	r = engine->EndConfigGroup(); assert( r >= 0 );

	r = engine->ExecuteString(0, "string a = \"test\""); assert( r == asEXECUTION_FINISHED );

	r = engine->DiscardModule(0);  assert( r >= 0 );
	r = engine->GarbageCollect(); assert( r >= 0 );

	r = engine->RemoveConfigGroup("g1"); assert( r >= 0 );

	engine->Release();


	//-----------------------------
	// Test that it isn't possible to register the sample property in two different groups
	engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);

	engine->BeginConfigGroup("a");

	r = engine->RegisterGlobalProperty("int a", 0); assert( r >= 0 );

	engine->EndConfigGroup();

	r = engine->RegisterGlobalProperty("int a", 0); assert( r < 0 );

	engine->Release();

	//------------------------------
	// Test that ExecuteString doesn't lock dynamic config groups
	engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);

	r = engine->BeginConfigGroup("g1"); assert( r >= 0 );
	RegisterScriptString_Generic(engine);
	r = engine->EndConfigGroup(); assert( r >= 0 );

	r = engine->ExecuteString(0, "string a = \"test\""); assert( r == asEXECUTION_FINISHED );

	// Garbage collect and remove config group before discarding module
	r = engine->GarbageCollect(); assert( r >= 0 );
	r = engine->RemoveConfigGroup("g1"); assert( r >= 0 );

	engine->Release();

	// Success
	return fail;
}
コード例 #29
0
bool Test()
{
	bool fail = false;

	//---
 	asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
	
	// Verify that the function doesn't crash when the stack is empty
	asIScriptContext *ctx = asGetActiveContext();
	assert( ctx == 0 );

	RegisterScriptString_Generic(engine);
	
	engine->RegisterGlobalFunction("void Suspend()", asFUNCTION(Suspend), asCALL_GENERIC);
	engine->RegisterGlobalProperty("int loopCount", &loopCount);

	COutStream out;
	engine->AddScriptSection(0, TESTNAME ":1", script1, strlen(script1), 0);

	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
	engine->Build(0);

	ctx = engine->CreateContext();
	ctx->SetLineCallback(asFUNCTION(LineCallback), 0, asCALL_STDCALL);
	if( ctx->Prepare(engine->GetFunctionIDByDecl(0, "void TestSuspend()")) >= 0 )
	{
		while( loopCount < 5 && !doSuspend )
			ctx->Execute();
	}
	else
		fail = true;

	// Release the engine first
	engine->Release();

	// Now release the context
	ctx->Release();
	//---
	// If the library was built with the flag BUILD_WITH_LINE_CUES the script
	// will return after each increment of the loopCount variable.
	engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
	engine->RegisterGlobalProperty("int loopCount", &loopCount);
	engine->AddScriptSection(0, TESTNAME ":2", script2, strlen(script2), 0);
	engine->Build(0);

	ctx = engine->CreateContext();
	ctx->SetLineCallback(asFUNCTION(LineCallback), 0, asCALL_STDCALL);
	ctx->Prepare(engine->GetFunctionIDByDecl(0, "void TestSuspend2()"));
	loopCount = 0;
	while( ctx->GetState() != asEXECUTION_FINISHED )
		ctx->Execute();
	if( loopCount != 3 )
	{
		printf("%s: failed\n", TESTNAME);
		fail = true;
	}

	ctx->Prepare(asPREPARE_PREVIOUS);
	loopCount = 0;
	while( ctx->GetState() != asEXECUTION_FINISHED )
		ctx->Execute();
	if( loopCount != 3 )
	{
		printf("%s: failed\n", TESTNAME);
		fail = true;
	}

	ctx->Release();
	engine->Release();

	// Success
	return fail;
}
コード例 #30
0
ファイル: test_arrayintf.cpp プロジェクト: Kaperstone/warsow
bool Test()
{
	bool fail = false;
	int r;
	COutStream out;

 	asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);

	RegisterScriptArray(engine, true);
	RegisterScriptString(engine);

	engine->RegisterGlobalProperty("float[] @floatArray", &floatArray);
	engine->RegisterGlobalProperty("string[] @stringArray", &stringArray);

	asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection(TESTNAME, script1, strlen(script1), 0);
	r = mod->Build();
	if( r < 0 ) TEST_FAILED;

	r = ExecuteString(engine, "Test()", mod);
	if( r != asEXECUTION_FINISHED ) 
	{
		TEST_FAILED;
	}
	else
	{
		if( (floatArray->GetArrayTypeId() & asTYPEID_MASK_OBJECT) != asTYPEID_TEMPLATE )
			TEST_FAILED;

		if( floatArray->GetArrayTypeId() != engine->GetTypeIdByDecl("float[]") )
			TEST_FAILED;

		if( floatArray->GetElementTypeId() != engine->GetTypeIdByDecl("float") )
			TEST_FAILED;

		if( floatArray->GetSize() != 2 )
			TEST_FAILED;

		if( *(float*)floatArray->At(0) != 1.1f )
			TEST_FAILED;

		if( *(float*)floatArray->At(1) != 1.2f )
			TEST_FAILED;

		if( stringArray->GetArrayTypeId() != engine->GetTypeIdByDecl("string[]") )
			TEST_FAILED;

		if( stringArray->GetElementTypeId() != engine->GetTypeIdByDecl("string") )
			TEST_FAILED;

		if( stringArray->GetSize() != 1 )
			TEST_FAILED;

		if( ((CScriptString*)stringArray->At(0))->buffer != "test" )
			TEST_FAILED;

		stringArray->Resize(2);
	}

	if( floatArray )
		floatArray->Release();
	if( stringArray )
		stringArray->Release();

	engine->Release();

	// Success
	return fail;
}