Example #1
0
bool Test()
{
	RET_ON_MAX_PORT

	bool fail = false;
	int r;

	asIScriptModule *mod = 0;
	COutStream out;
	CBufferedOutStream bout;
 	asIScriptEngine *engine = 0;

	// Value assignment on the base class where the operands are two different derived classes
	// Reported by Philip Bennefall
	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);

		RegisterStdString(engine);

		mod = engine->GetModule("Test", asGM_ALWAYS_CREATE);
		mod->AddScriptSection("test",
			"class Base {} \n"
			"class Derived1 : Base { string a; } \n"
			"class Derived2 : Base { double a; } \n"
			"void main() \n"
			"{ \n"
			"  Derived1 d1; \n"
			"  Derived2 d2; \n"
			"  Base@ b1 = d1, b2 = d2; \n"
			"  b1 = b2; \n" // must not crash application. should raise script exception
			"} \n");
		r = mod->Build();
		if( r < 0 )
			TEST_FAILED;

		asIScriptContext *ctx = engine->CreateContext();
		r = ExecuteString(engine, "main()", mod, ctx);
		if( r != asEXECUTION_EXCEPTION )
			TEST_FAILED;
		if( std::string(ctx->GetExceptionString()) != "Mismatching types in value assignment" )
			TEST_FAILED;
		ctx->Release();

		engine->Release();
	}

	// A derived class must not be allowed to implement a function with the same 
	// name and parameter list as parent class, but with a different return type.
	// Reported by Philip Bennefall
	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		bout.buffer = "";
		engine->SetMessageCallback(asMETHOD(CBufferedOutStream, Callback), &bout, asCALL_THISCALL);

		mod = engine->GetModule("Test", asGM_ALWAYS_CREATE);
		mod->AddScriptSection("test",
			"class P { \n"
			"  int MyFunc(float) { return 0; } \n"
			"} \n"
			"class D : P { \n"
			"  float MyFunc(float) { return 0; } \n"
			"} \n");
		r = mod->Build();
		if( r >= 0 )
			TEST_FAILED;

		if( bout.buffer != "test (4, 7) : Error   : The method in the derived class must have the same return type as in the base class: 'int P::MyFunc(float)'\n" )
		{
			PRINTF("%s", bout.buffer.c_str());
			TEST_FAILED;
		}

		engine->Release();
	}

	// Basic tests for inheritance
	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);
		RegisterStdString(engine);
		engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);
		engine->RegisterGlobalFunction("void print(const string &in)", asFUNCTION(print), asCALL_CDECL);

		const char *script =
			"bool baseDestructorCalled = false;               \n"
			"bool baseConstructorCalled = false;              \n"
			"bool baseFloatConstructorCalled = false;         \n"
			"class Base : Intf                                \n"
			"{                                                \n"
			"  int a;                                         \n"
			"  void f1() { a = 1; }                           \n"
			"  void f2() { a = 0; }                           \n"
			"  void f3() { a = 3; }                           \n"
			"  Base() { baseConstructorCalled = true; }       \n"
			"  Base(float) { baseFloatConstructorCalled = true; } \n"
			"  ~Base() { baseDestructorCalled = true; }       \n"
			"}                                                \n"
			"bool derivedDestructorCalled = false;            \n"
			"bool derivedConstructorCalled = false;           \n"
			"class Derived : Base                             \n"
			"{                                                \n"
			   // overload f2()
			"  void f2() { a = 2; }                           \n"
			   // overload f3()
			"  void f3() { a = 2; }                           \n"
			"  void func()                                    \n"
			"  {                                              \n"
				 // call Base::f1()
			"    f1();                                        \n"
			"    assert(a == 1);                              \n"
				 // call Derived::f2()
			"    f2();                                           \n"
			"    assert(a == 2);                                 \n"
				 // call Base::f3() 
			"    Base::f3();                                     \n"
			"    assert(a == 3);                                 \n"
			"  }                                                 \n"
			"  Derived() {} \n"
			"  Derived(int) { derivedConstructorCalled = true; } \n"
			"  ~Derived() { derivedDestructorCalled = true; }    \n"
			"}                                                \n"
			"void foo( Base &in a )                           \n"
			"{                                                \n"
			"  assert( cast<Derived>(a) is null );            \n"
			"}                                                \n"
			// Must be possible to call the default constructor, even if not declared
			"class DerivedGC : BaseGC { DerivedGC() { super(); } }  \n"
			"class BaseGC { BaseGC @b; }                      \n"
			"class DerivedS : Base                            \n"
			"{                                                \n"
			"  DerivedS(float)                                \n"
			"  {                                              \n"
	  			 // Call Base::Base(float)
			"    if( true )                                   \n"
			"      super(1.4f);                               \n"
			"    else                                         \n"
			"      super();                                   \n"
			"  }                                              \n"
			"}                                                \n"
			// Must handle inheritance where the classes have been declared out of order
			"void func()                                      \n"
			"{                                                \n"
			"   Intf@ a = C();                                \n"
			"}                                                \n"
			"class C : B {}                                   \n"
			"interface Intf {}                                \n"
			"class B : Intf {}                                \n"
			// Several levels of inheritance
			"class C0                                         \n"
			"{                                                \n"
			"  void Dummy() {}                                \n"
			"}                                                \n"
			"class C1 : C0                                    \n"
			"{                                                \n"
			"  void Fun() { print('C1:Fun'); }                \n"
			"}                                                \n"
			"class C2 : C1                                    \n"
			"{                                                \n"
			"  void Fun() { print('C2:Fun'); }                \n"
			"}                                                \n"
			"class C3 : C2                                    \n"
			"{                                                \n"
			"  void Call() { Fun(); }                         \n"
			"}                                                \n";


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

		// Make sure the bytecode for the ref cast is correct
		asIScriptFunction *func = mod->GetFunctionByName("foo");
		asBYTE expect[] = 
			{	
				asBC_SUSPEND,asBC_PSF,asBC_Cast,asBC_STOREOBJ,asBC_ClrVPtr,asBC_CmpPtr,asBC_TZ,asBC_CpyRtoV4,asBC_FREE,asBC_FREE,asBC_PshV4,asBC_CALLSYS,
				asBC_SUSPEND,asBC_RET
			};
		if( !ValidateByteCode(func, expect) )
			TEST_FAILED;

		if( TestModule(0, engine) )
		{
			TEST_FAILED;
		}

		// Must make sure that the inheritance path is stored/restored with the saved byte code
		{ 
			CBytecodeStream stream(__FILE__"1");
			r = mod->SaveByteCode(&stream);
			if( r < 0 )
			{
				TEST_FAILED;
			}

			asIScriptModule *mod2 = engine->GetModule("2", asGM_ALWAYS_CREATE);
			r = mod2->LoadByteCode(&stream);
			if( r < 0 )
			{
				TEST_FAILED;
			}

			// Both modules should have the same number of functions
			if( mod->GetFunctionCount() != mod2->GetFunctionCount() )
			{
				TEST_FAILED;

				asUINT n;
				PRINTF("First module's functions\n");
				for( n = 0; n < (asUINT)mod->GetFunctionCount(); n++ )
				{
					asIScriptFunction *f = mod->GetFunctionByIndex(n);
					PRINTF("%s\n", f->GetDeclaration());
				}
				PRINTF("\nSecond module's functions\n");
				for( n = 0; n < (asUINT)mod2->GetFunctionCount(); n++ )
				{
					asIScriptFunction *f = mod2->GetFunctionByIndex(n);
					PRINTF("%s\n", f->GetDeclaration());
				}
			}

			if( TestModule("2", engine) )
			{
				TEST_FAILED;
			}

			engine->DiscardModule("2");
		}

		engine->Release();
	}

	// Test final and override
	{
		CBufferedOutStream bout;
		asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(CBufferedOutStream, Callback), &bout, asCALL_THISCALL);

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

		mod->AddScriptSection("test", 
			"final class CFin1 {} \n" // Don't allow inheritance
			"shared final class CFin2 {} \n" // -"-
			"class CBase \n"
			"{ \n"
			"  void finalFunc() final {} \n" // don't allow override this func
			"  void overrideFunc() {} \n" 
			"} \n"
			"class CD1 : CFin1 {} \n" // Shouldn't work
			"class CD2 : CBase \n"
			"{ \n"
			"  void finalFunc() {} \n" // shouldn't work
			"  void overrideFunc(int) override {} \n" // must override
			"} \n");

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

		if( bout.buffer != "test (8, 13) : Error   : Can't inherit from class 'CFin1' marked as final\n"
						   "test (9, 7) : Error   : Method 'void CBase::finalFunc()' declared as final and cannot be overridden\n"
						   "test (9, 7) : Error   : Method 'void CD2::overrideFunc(int)' marked as override but does not replace any base class or interface method\n" )
		{
			PRINTF("%s", bout.buffer.c_str());
			TEST_FAILED;
		}

		engine->Release();
	}

	fail = Test2() || fail;

	// Success
	return fail;
}
Example #2
0
int main( int argc, char *argv[] )
{
	char	*height_name;
	char	*edge_name;

	tga_t	*heightmap;
	tga_t	*edgemap;

	int		i, j;
	int		num;


	FILE	*h;

	printf( "===== envpot - build and optimize a environment data =====\n" );
	SetCmdArgs( argc, argv );


	height_name = GetCmdOpt2( "-h" );
	edge_name = GetCmdOpt2( "-e" );

	if ( !height_name )
		Error( "no heightmap.\n" );
	if ( !edge_name )
		Error( "no edgemap.\n" );

	h = fopen( height_name, "r" );
	if ( !h )
		Error( "can't open heightmap.\n" );
	heightmap = TGA_Read( h );
	fclose( h );

	h = fopen( edge_name, "r" );
	if ( !h )
		Error( "can't open edgemap.\n" );
	edgemap = TGA_Read( h );
	fclose( h );

	InitEdgeMap( edgemap );
//	InitHeightMap( heightmap );
//	SetupCells();

#if 0	
	num = 0;
	for ( i = 0; i < 10; i++ )
	{
		for ( j = 0; j < 10; j++ )
		{
//			Vec3dInit( vertices[num++], (random()%1000)/1000.0, 0.0, (random()%1000)/1000.0 );
			Vec3dInit( vertices[num++], j/10.0, 0.0, i/10.0 );
		}
	}

	for ( i = 0; i < 5; i++ )
	{
		for ( j = 0; j < 5; j++ )
		{
//			Vec3dInit( vertices[num++], (random()%1000)/1000.0, 0.0, (random()%1000)/1000.0 );
			Vec3dInit( vertices[num++], 0.05+j/10.0, 0.0, 0.05+i/10.0 );
		}
	}

	vertexnum = num;
#endif

//	Vec2dInit( vertices[0].v, 0.0, 0.0 );
//	Vec2dInit( vertices[1].v, 0.0, 1.0 );
//	Vec2dInit( vertices[2].v, -1.0, 0.5 );
//	Vec2dInit( vertices[3].v, 1.0, 0.5 );
//	Vec2dInit( vertices[4].v, 2.0, 0.5 );
//	vertexnum = 5;


	Init2();
	handle = fopen( "env_tris", "w" );
	Test2();
	fprintf( handle, "end" );
	fclose( handle );

	handle = fopen( "env_vertices", "w" );
	WriteVertices();
	fclose( handle );

}
Example #3
0
bool Test()
{
	bool fail = Test2();
	int r;
	asIScriptEngine *engine;

	CBufferedOutStream bout;
	COutStream out;

	// Two forms of casts: value cast and ref cast
	// A value cast actually constructs a new object
	// A ref cast will only reinterpret a handle, without actually constructing any object

	// Should be possible to tell AngelScript if it may use the behaviour implicitly or not
	// Since care must be taken with implicit casts, it is not allowed by default,
	// i.e. asBEHAVE_VALUE_CAST and asBEHAVE_VALUE_CAST_IMPLICIT or
	//      asBEHAVE_REF_CAST and asBEHAVE_REF_CAST_IMPLICIT

	//----------------------------------------------------------------------------
	// VALUE_CAST

	// TODO: (Test) Cast from primitive to object is an object constructor/factory
	// TODO: (Test) Cast from object to object can be either object behaviour or object constructor/factory, 
	// depending on which object registers the cast

	// TODO: (Implement) It shall be possible to register cast operators as explicit casts. The constructor/factory 
	// is by default an explicit cast, but shall be possible to register as implicit cast.

	// TODO: (Implement) Type constructors should be made explicit cast only, or perhaps not permit casts at all

	// TODO: (Test) When compiling operators with non-primitives, the compiler should first look for 
	// compatible registered operator behaviours. If not found, the compiler should see if 
	// there is any cast behaviour that allow conversion of the type to a primitive type.

	// Test 1
	// A class can be implicitly cast to a primitive, if registered the VALUE_CAST behaviour
 	engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);

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

	r = engine->RegisterObjectType("type", sizeof(int), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_PRIMITIVE); assert( r >= 0 );
	r = engine->RegisterObjectBehaviour("type", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(Type_construct0), asCALL_GENERIC); assert( r >= 0 );
	r = engine->RegisterObjectBehaviour("type", asBEHAVE_CONSTRUCT, "void f(int)", asFUNCTION(Type_construct1), asCALL_GENERIC); assert( r >= 0 );
	r = engine->RegisterObjectBehaviour("type", asBEHAVE_IMPLICIT_VALUE_CAST, "int f()", asFUNCTION(Type_castInt), asCALL_GENERIC); assert( r >= 0 );

	asIScriptContext *ctx = 0;
	r = engine->ExecuteString(0, "type t(5); \n"
		                         "int a = t; \n"             // conversion to primitive in assignment
								 "assert( a == 5 ); \n"
								 "assert( a + t == 10 ); \n" // conversion to primitive with math operation
								 "a -= t; \n"                // conversion to primitive with math operation
								 "assert( a == 0 ); \n"
								 "assert( t == int(5) ); \n" // conversion to primitive with comparison 
								 "type b(t); \n"             // conversion to primitive with parameter
								 "assert( 32 == (1 << t) ); \n"   // conversion to primitive with bitwise operation 
	                             "assert( (int(5) & t) == 5 ); \n" // conversion to primitive with bitwise operation
								 , &ctx);
	if( r != 0 )
	{
		if( r == 3 )
			PrintException(ctx);
		fail = true;
	}
	if( ctx ) ctx->Release();

	// Test 2
	// A class won't be converted to primitive if there is no obvious target type
	// ex: t << 1 - It is not known what type t should be converted to
	// ex: t + t - It is not known what type t should be converted to
	// ex: t < t - It is not known what type t should be converted to
	bout.buffer = "";
	engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL);
	r = engine->ExecuteString(0, "type t(5); t << 1; ");
	if( r >= 0 ) fail = true;
	if( bout.buffer != "ExecuteString (1, 14) : Error   : Illegal operation on 'type&'\n" )
	{
		printf(bout.buffer.c_str());
		fail = true;
	}

	bout.buffer = "";
	r = engine->ExecuteString(0, "type t(5); t + t; ");
	if( r >= 0 ) fail = true;
	if( bout.buffer != "ExecuteString (1, 14) : Error   : No matching operator that takes the types 'type&' and 'type&' found\n" )
	{
		printf(bout.buffer.c_str());
		fail = true;
	}

	bout.buffer = "";
	r = engine->ExecuteString(0, "type t(5); t < t; ");
	if( r >= 0 ) fail = true;
	if( bout.buffer != "ExecuteString (1, 14) : Error   : No matching operator that takes the types 'type&' and 'type&' found\n" )
	{
		printf(bout.buffer.c_str());
		fail = true;
	}

	// Test3
	// If an object has a cast to more than one matching primitive type, the cast to the 
	// closest matching type will be used, i.e. Obj has cast to int and to float. A type of 
	// int8 is requested, so the cast to int is used
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
	r = engine->ExecuteString(0, "type t(2); assert( (1.0 / t) == (1.0 / 2.0) );");
	if( r != asEXECUTION_FINISHED ) fail = true;

	engine->Release();

	// Test4
	// It shall not be possible to register a cast behaviour from an object to a boolean type
 	engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);

	r = engine->RegisterObjectType("type", sizeof(int), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_PRIMITIVE); assert( r >= 0 );
	r = engine->RegisterObjectBehaviour("type", asBEHAVE_IMPLICIT_VALUE_CAST, "bool f()", asFUNCTION(Type_castInt), asCALL_GENERIC); 
	if( r != asNOT_SUPPORTED )
	{
		fail = true;
	}

	engine->Release();

	// Test5
	// Exclicit value cast
	// TODO: This should work for MAX_PORTABILITY as well
	if( !strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY") )
	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);

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

		r = engine->RegisterObjectType("type", sizeof(int), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_PRIMITIVE); assert( r >= 0 );
		r = engine->RegisterObjectBehaviour("type", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(Type_construct0), asCALL_GENERIC); assert( r >= 0 );
		r = engine->RegisterObjectBehaviour("type", asBEHAVE_CONSTRUCT, "void f(int)", asFUNCTION(Type_construct1), asCALL_GENERIC); assert( r >= 0 );
		r = engine->RegisterObjectBehaviour("type", asBEHAVE_VALUE_CAST, "int f()", asFUNCTION(Type_castInt), asCALL_GENERIC); assert( r >= 0 );
		r = engine->RegisterGlobalBehaviour(asBEHAVE_EQUAL, "bool f(const type &in, const type &in)", asFUNCTION(Type_equal), asCALL_CDECL); assert( r >= 0 );
		r = engine->RegisterObjectProperty("type", "int v", 0);

		// explicit cast to int is allowed
		r = engine->ExecuteString(0, "type t; t.v = 5; int a = int(t); assert(a == 5);"); 
		if( r < 0 )
			fail = true;

		// as cast to int is allowed, AngelScript also allows cast to float (using cast to int then implicit cast to int)
		r = engine->ExecuteString(0, "type t; t.v = 5; float a = float(t); assert(a == 5.0f);");
		if( r < 0 )
			fail = true;

		// implicit cast to int is not allowed
		bout.buffer = "";
		engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL);
		r = engine->ExecuteString(0, "type t; int a = t;");
		if( r >= 0 )
			fail = true;
		if( bout.buffer != "ExecuteString (1, 17) : Error   : Can't implicitly convert from 'type&' to 'int'.\n" )
		{
			printf(bout.buffer.c_str());
			fail = true;
		}
/*
		// Having an implicit constructor with an int param makes it possible to compare the type with int
		engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
		r = engine->ExecuteString(0, "type t(5); assert( t == 5 );");
		if( r < 0 )
			fail = true;
*/
		engine->Release();
	}

	//-----------------------------------------------------------------
	// REFERENCE_CAST

	// TODO: This should work for MAX_PORTABILITY as well
	if( !strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY") )
	{

		// It must be possible to cast an object handle to another object handle, without 
		// losing the reference to the original object. This is what will allow applications
		// to register inheritance for registered types. This should be a special 
		// behaviour, i.e. REF_CAST. 
		
		// How to provide a cast from a base class to a derived class?
		// The base class may not know about the derived class, so it must
		// be the derived class that registers the behaviour. 
		
		// How to provide interface functionalities to registered types? I.e. a class implements 
		// various interfaces, and a handle to one of the interfaces may be converted to a handle
		// of another interface that is implemented by the class.

		// TODO: Can't register casts from primitive to primitive

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

		// Class A is the base class
		engine->RegisterObjectType("A", 0, asOBJ_REF);
		engine->RegisterObjectBehaviour("A", asBEHAVE_FACTORY, "A@f()", asFUNCTION(A::factory), asCALL_CDECL); 
		engine->RegisterObjectBehaviour("A", asBEHAVE_RELEASE, "void f()", asMETHOD(A, release), asCALL_THISCALL);
		engine->RegisterObjectBehaviour("A", asBEHAVE_ADDREF, "void f()", asMETHOD(A, addref), asCALL_THISCALL);
		engine->RegisterObjectBehaviour("A", asBEHAVE_ASSIGNMENT, "A& f(const A &in)", asMETHOD(A, assign), asCALL_THISCALL);
		engine->RegisterObjectMethod("A", "int test()", asMETHOD(A, test), asCALL_THISCALL);

		// Class B inherits from class A
		engine->RegisterObjectType("B", 0, asOBJ_REF);
		engine->RegisterObjectBehaviour("B", asBEHAVE_FACTORY, "B@f()", asFUNCTION(B::factory), asCALL_CDECL); 
		engine->RegisterObjectBehaviour("B", asBEHAVE_RELEASE, "void f()", asMETHOD(B, release), asCALL_THISCALL);
		engine->RegisterObjectBehaviour("B", asBEHAVE_ADDREF, "void f()", asMETHOD(B, addref), asCALL_THISCALL);
		engine->RegisterObjectMethod("B", "int test()", asMETHOD(B, test), asCALL_THISCALL);
		
		// Test the classes to make sure they work
		r = engine->ExecuteString(0, "A a; assert(a.test() == 1); B b; assert(b.test() == 2);");
		if( r != asEXECUTION_FINISHED )
			fail = true;

		// It should be possible to register a REF_CAST to allow implicit cast
		// Test IMPLICIT_REF_CAST from subclass to baseclass
		r = engine->RegisterGlobalBehaviour(asBEHAVE_IMPLICIT_REF_CAST, "A@ f(B@)", asFUNCTION(B::castToA), asCALL_CDECL); assert( r >= 0 );
		r = engine->ExecuteString(0, "B b; A@ a = b; assert(a.test() == 2);");
		if( r != asEXECUTION_FINISHED )
			fail = true;

		// Test explicit cast with registered IMPLICIT_REF_CAST
		r = engine->ExecuteString(0, "B b; A@ a = cast<A>(b); assert(a.test() == 2);");
		if( r != asEXECUTION_FINISHED )
			fail = true;

		// It should be possible to assign a value of type B 
		// to and variable of type A due to the implicit ref cast
		r = engine->ExecuteString(0, "A a; B b; a = b;");
		if( r != asEXECUTION_FINISHED )
			fail = true;

		// Test REF_CAST from baseclass to subclass
		r = engine->RegisterGlobalBehaviour(asBEHAVE_REF_CAST, "B@ f(A@)", asFUNCTION(B::AcastToB), asCALL_CDECL); assert( r >= 0 );
		r = engine->ExecuteString(0, "B b; A@ a = cast<A>(b); B@ _b = cast<B>(a); assert(_b.test() == 2);");
		if( r != asEXECUTION_FINISHED )
			fail = true;

		// Test REF_CAST from baseclass to subclass, where the cast is invalid
		r = engine->ExecuteString(0, "A a; B@ b = cast<B>(a); assert(@b == null);");
		if( r != asEXECUTION_FINISHED )
			fail = true;

		// TODO: This requires implicit value cast
		// Test passing a value of B to a function expecting its base class
		// the compiler will automatically create a copy
/*		const char *script = 
			"void func(A a) {assert(a.test() == 1);}\n";
		r = mod->AddScriptSection(0, "script", script, strlen(script));
		r = mod->Build(0);
		if( r < 0 )
			fail = true;
		r = engine->ExecuteString(0, "B b; func(b)");
		if( r < 0 )
			fail = true;
*/
		// TODO: A handle to A can not be implicitly cast to a handle to B since it was registered as explicit REF_CAST
		// TODO: It shouldn't be possible to cast away constness

		engine->Release();
	}

	// Success
 	return fail;
}
Example #4
0
bool Test()
{
	bool fail = Test2();
	int r;
	COutStream out;
	asIScriptContext *ctx;

	// Test to make sure opIndex properly catches null pointer access
	// http://www.gamedev.net/topic/676729-crash-instead-of-null-pointer-exception-on-opindex/
	{
		asIScriptEngine *engine = asCreateScriptEngine();

		RegisterScriptArray(engine, true);

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

		ctx = engine->CreateContext();
		r = ExecuteString(engine, "array<array<int>@> a = {null}; a[0][0] = 1;", 0, ctx);
		if (r != asEXECUTION_EXCEPTION)
			TEST_FAILED;
		else if( GetExceptionInfo(ctx) != "func: void ExecuteString()\n"
										  "modl: \n"
										  "sect: ExecuteString\n"
										  "line: 1\n"
										  "desc: Null pointer access\n" )
		{
			PRINTF("%s", GetExceptionInfo(ctx).c_str());
			TEST_FAILED;
		}
		ctx->Release();
		engine->ShutDownAndRelease();
	}

	// Test GetTypeDeclaration with arrays
	// http://www.gamedev.net/topic/663428-simplest-way-to-get-variable-type/
	{
		asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);

		RegisterScriptArray(engine, true);

		int typeId = engine->GetTypeIdByDecl("array<array<int>@>");
		if( typeId < 0 )
			TEST_FAILED;

		std::string typeDecl = engine->GetTypeDeclaration(typeId, true);
		if( typeDecl != "int[]@[]" )
		{
			PRINTF("%s\n", typeDecl.c_str());
			TEST_FAILED;
		}

		engine->SetDefaultNamespace("foo");
		engine->RegisterEnum("MyEnum");
		engine->SetDefaultNamespace("");

		typeId = engine->GetTypeIdByDecl("array<foo::MyEnum>");
		if( typeId < 0 )
			TEST_FAILED;

		typeDecl = engine->GetTypeDeclaration(typeId, true);
		if( typeDecl != "foo::MyEnum[]" )
		{
			PRINTF("%s\n", typeDecl.c_str());
			TEST_FAILED;
		}

		engine->ShutDownAndRelease();
	}

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

	RegisterScriptString_Generic(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 )
	{
		TEST_FAILED;
		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 )
			PRINTF("%s", GetExceptionInfo(ctx).c_str());

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

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

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

	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection(TESTNAME, script3, strlen(script3), 0);
	r = mod->Build();
	if( r < 0 )
	{
		TEST_FAILED;
		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);
		TEST_FAILED;
	}
	if( r == asEXECUTION_EXCEPTION )
	{
		PRINTF("%s", GetExceptionInfo(ctx).c_str());
	}
	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 )
	{
		TEST_FAILED;
		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);
		TEST_FAILED;
	}
	if( r == asEXECUTION_EXCEPTION )
	{
		PRINTF("%s", GetExceptionInfo(ctx).c_str());
	}

	if( ctx ) ctx->Release();

	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection(TESTNAME, script5, strlen(script5), 0);
	r = mod->Build();
	if( r < 0 ) TEST_FAILED;
	ctx = engine->CreateContext();
	r = ExecuteString(engine, "TestArrayInitList()", mod, ctx);
	if( r != asEXECUTION_FINISHED ) TEST_FAILED;
	if( r == asEXECUTION_EXCEPTION )
		PRINTF("%s", GetExceptionInfo(ctx).c_str());

	if( ctx ) ctx->Release();

	CBufferedOutStream bout;
	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 ) TEST_FAILED;
	if( bout.buffer != "TestArray (1, 1) : Info    : Compiling void Test()\n"
	                   "TestArray (4, 16) : Error   : Initialization lists cannot be used with 'int'\n" )
	{
		PRINTF("%s", bout.buffer.c_str());
		TEST_FAILED;
	}

	// 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 ) 
		TEST_FAILED;
	r = ExecuteString(engine, "Test()", mod);
	if( r != asEXECUTION_FINISHED )
		TEST_FAILED;
		
	// Test bool[] on Mac OS X with PPC CPU
	// Submitted by Edward Rudd
	const char *script8 =
	"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);
	if( r != asEXECUTION_FINISHED )
		TEST_FAILED;

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

	engine->Release();

	// Test circular reference between types
	{
		// Create the script engine
		asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		RegisterScriptArray(engine, true);

		// Compile
		asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
		mod->AddScriptSection("script", 
			"class Hoge"
			"{"
			"    Hoge(){}"
			"    Hoge(HogeManager&){}"
			"};"
			"class HogeManager"
			"{"
			"    Hoge[] hoges;"
			"};"
			, 0);
		mod->Build();

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

	// Test multidimensional array initialization
	{
		// Create the script engine
		asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);
		RegisterScriptArray(engine, true);

		r = ExecuteString(engine, "int[][] a(2, int[](2)); assert(a[1].length() == 2);\n");
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;

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

	// Test array of void
	{
		asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		CBufferedOutStream bout;
		engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL);
		RegisterScriptArray(engine, false);
		r = ExecuteString(engine, "array<void> a;");
		if( r != -1 )
			TEST_FAILED;
		if( bout.buffer != "ExecuteString (1, 7) : Error   : Attempting to instantiate invalid template type 'array<void>'\n" )
		{
			PRINTF("%s", bout.buffer.c_str());
			TEST_FAILED;
		}

		engine->Release();
	}

	// Success
	return fail;
}
Example #5
0
bool Test()
{
	if( strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY") )
	{
		printf("Skipped due to AS_MAX_PORTABILITY\n");
		return false;
	}

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

	engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
	engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL);
	RegisterScriptArray(engine, true);
	RegisterScriptString(engine);
	engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);

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

	// The getter can return a handle while the setter takes a reference
	{
		const char *script = 
			"class Test \n"
			"{ \n"
			"  string @get_s() { return 'test'; } \n"
			"  void set_s(const string &in) {} \n"
			"} \n"
			"void func() \n"
			"{ \n"
			"  Test t; \n"
			"  string s = t.s; \n" 
			"  t.s = s; \n"
			"} \n";

		mod->AddScriptSection("script", script);
		bout.buffer = "";
		r = mod->Build();
		if( r < 0 )
		{
			TEST_FAILED;
			printf("Failed to compile the script\n");
		}

		r = ExecuteString(engine, "Test t; @t.s = 'test';", mod);
		if( r >= 0 )
		{
			TEST_FAILED;
			printf("Shouldn't be allowed\n");
		}
		if( bout.buffer != "ExecuteString (1, 14) : Error   : It is not allowed to perform a handle assignment on a non-handle property\n" )
		{
			printf("%s", bout.buffer.c_str());
			TEST_FAILED;
		}
	}

	// main1 and main2 should produce the same bytecode
	const char *script1 = 
		"class Test                            \n"
		"{                                     \n"
		"  int get_prop() { return _prop; }    \n"
		"  void set_prop(int v) { _prop = v; } \n"
        "  int _prop;                          \n"
		"}                                     \n"
		"void main1()                          \n"
		"{                                     \n"
		"  Test t;                             \n"
		"  t.set_prop(42);                     \n"
		"  assert( t.get_prop() == 42 );       \n"
		"}                                     \n"
		"void main2()                          \n"
		"{                                     \n"
		"  Test t;                             \n"
		"  t.prop = 42;                        \n"
		"  assert( t.prop == 42 );             \n"
		"}                                     \n";
		
	mod->AddScriptSection("script", script1);
	bout.buffer = "";
	r = mod->Build();
	if( r < 0 )
	{
		TEST_FAILED;
		printf("Failed to compile the script\n");
	}
	if( bout.buffer != "" )
	{
		printf("%s", bout.buffer.c_str());
		TEST_FAILED;
	}

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

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

	// Test compound assignment with accessors (not allowed)
	const char *script2 = 
		"class Test                            \n"
		"{                                     \n"
		"  void set_prop(int v) { _prop = v; } \n"
        "  int _prop;                          \n"
		"}                                     \n"
		"void main1()                          \n"
		"{                                     \n"
		"  Test t;                             \n"
		"  t.prop += 42;                       \n"
		"}                                     \n";

	mod->AddScriptSection("script", script2);
	bout.buffer = "";
	r = mod->Build();
	if( r >= 0 )
	{
		TEST_FAILED;
	}
	if( bout.buffer != "script (6, 1) : Info    : Compiling void main1()\n"
	                   "script (9, 10) : Error   : Compound assignments with property accessors are not allowed\n" )
	{
		printf("%s", bout.buffer.c_str());
		TEST_FAILED;
	}

	// Test get accessor with boolean operators
	const char *script3 = 
		"class Test                              \n"
		"{                                       \n"
		"  bool get_boolProp() { return true; }  \n"
		"}                                       \n"
		"void main1()                            \n"
		"{                                       \n"
		"  Test t;                               \n"
		"  if( t.boolProp ) {}                   \n"
		"  if( t.boolProp && true ) {}           \n"
		"  if( false || t.boolProp ) {}          \n"
		"  if( t.boolProp ^^ t.boolProp ) {}     \n"
		"  if( !t.boolProp ) {}                  \n"
		"  t.boolProp ? t.boolProp : t.boolProp; \n"
		"}                                       \n";

	mod->AddScriptSection("script", script3);
	bout.buffer = "";
	r = mod->Build();
	if( r < 0 )
	{
		TEST_FAILED;
		printf("Failed to compile the script\n");
	}
	if( bout.buffer != "" )
	{
		printf("%s", bout.buffer.c_str());
		TEST_FAILED;
	}

	// Test get accessor with math operators
	const char *script4 = 
		"class Test                              \n"
		"{                                       \n"
		"  float get_prop() { return 1.0f; }     \n"
		"}                                       \n"
		"void main1()                            \n"
		"{                                       \n"
		"  Test t;                               \n"
		"  float f = t.prop * 1;                 \n"
		"  f = (t.prop) + 1;                     \n"
		"  10 / t.prop;                          \n"
		"  -t.prop;                              \n"
		"}                                       \n";

	mod->AddScriptSection("script", script4);
	bout.buffer = "";
	r = mod->Build();
	if( r < 0 )
	{
		TEST_FAILED;
		printf("Failed to compile the script\n");
	}
	if( bout.buffer != "" )
	{
		printf("%s", bout.buffer.c_str());
		TEST_FAILED;
	}

	// Test get accessor with bitwise operators
	const char *script5 = 
		"class Test                              \n"
		"{                                       \n"
		"  uint get_prop() { return 1; }         \n"
		"}                                       \n"
		"void main1()                            \n"
		"{                                       \n"
		"  Test t;                               \n"
		"  t.prop << t.prop;                     \n"
		"  t.prop & t.prop;                      \n"
		"  ~t.prop;                              \n"
		"}                                       \n";

	mod->AddScriptSection("script", script5);
	bout.buffer = "";
	r = mod->Build();
	if( r < 0 )
	{
		TEST_FAILED;
		printf("Failed to compile the script\n");
	}
	if( bout.buffer != "" )
	{
		printf("%s", bout.buffer.c_str());
		TEST_FAILED;
	}

	// Test multiple get accessors for same property. Should give error
	// Test multiple set accessors for same property. Should give error
	const char *script6 = 
		"class Test                  \n"
		"{                           \n"
		"  uint get_p() {return 0;}  \n"
		"  float get_p() {return 0;} \n"
		"  void set_s(float) {}      \n"
		"  void set_s(uint) {}       \n"
		"}                           \n"
		"void main()                 \n"
		"{                           \n"
		"  Test t;                   \n"
		"  t.p;                      \n"
		"  t.s = 0;                  \n"
		"}                           \n";
	mod->AddScriptSection("script", script6);
	bout.buffer = "";
	r = mod->Build();
	if( r >= 0 )
	{
		TEST_FAILED;
		printf("Failed to compile the script\n");
	}
	if( bout.buffer != "script (8, 1) : Info    : Compiling void main()\n"
	                   "script (11, 4) : Error   : Found multiple get accessors for property 'p'\n"
	                   "script (11, 4) : Info    : uint Test::get_p()\n"
	                   "script (11, 4) : Info    : float Test::get_p()\n"
	                   "script (12, 4) : Error   : Found multiple set accessors for property 's'\n"
	                   "script (12, 4) : Info    : void Test::set_s(float)\n"
	                   "script (12, 4) : Info    : void Test::set_s(uint)\n" )
	{
		printf("%s", bout.buffer.c_str());
		TEST_FAILED;
	}

	// Test mismatching type between get accessor and set accessor. Should give error
	const char *script7 = 
		"class Test                  \n"
		"{                           \n"
		"  uint get_p() {return 0;}  \n"
		"  void set_p(float) {}      \n"
		"}                           \n"
		"void main()                 \n"
		"{                           \n"
		"  Test t;                   \n"
		"  t.p;                      \n"
		"}                           \n";
	mod->AddScriptSection("script", script7);
	bout.buffer = "";
	r = mod->Build();
	if( r >= 0 )
	{
		TEST_FAILED;
		printf("Failed to compile the script\n");
	}
	if( bout.buffer != "script (6, 1) : Info    : Compiling void main()\n"
                       "script (9, 4) : Error   : The property 'p' has mismatching types for the get and set accessors\n"
                       "script (9, 4) : Info    : uint Test::get_p()\n"
                       "script (9, 4) : Info    : void Test::set_p(float)\n" )
	{
		printf("%s", bout.buffer.c_str());
		TEST_FAILED;
	}

	// Test only set accessor for read expression
	// Test only get accessor for write expression
	const char *script8 = 
		"class Test                  \n"
		"{                           \n"
		"  uint get_g() {return 0;}  \n"
		"  void set_s(float) {}      \n"
		"}                           \n"
		"void main()                 \n"
		"{                           \n"
		"  Test t;                   \n"
		"  t.g = 0;                  \n"
        "  t.s + 1;                  \n"
		"}                           \n";
	mod->AddScriptSection("script", script8);
	bout.buffer = "";
	r = mod->Build();
	if( r >= 0 )
	{
		TEST_FAILED;
		printf("Failed to compile the script\n");
	}
	if( bout.buffer != "script (6, 1) : Info    : Compiling void main()\n"
					   "script (9, 7) : Error   : The property has no set accessor\n"
					   "script (10, 7) : Error   : The property has no get accessor\n" )
	{
		printf("%s", bout.buffer.c_str());
		TEST_FAILED;
	}

	// Test pre and post ++. Should fail, since the expression is not a variable
	const char *script9 = 
		"class Test                  \n"
		"{                           \n"
		"  uint get_p() {return 0;}  \n"
		"  void set_p(uint) {}       \n"
		"}                           \n"
		"void main()                 \n"
		"{                           \n"
		"  Test t;                   \n"
		"  t.p++;                    \n"
        "  --t.p;                    \n"
		"}                           \n";
	mod->AddScriptSection("script", script9);
	bout.buffer = "";
	r = mod->Build();
	if( r >= 0 )
	{
		TEST_FAILED;
		printf("Didn't fail to compile the script\n");
	}
	if( bout.buffer != "script (6, 1) : Info    : Compiling void main()\n"
					   "script (9, 6) : Error   : Invalid reference. Property accessors cannot be used in combined read/write operations\n"
				 	   "script (10, 3) : Error   : Invalid reference. Property accessors cannot be used in combined read/write operations\n" )
	{
		printf("%s", bout.buffer.c_str());
		TEST_FAILED;
	}

	// Test using property accessors from within class methods without 'this'
	// Test accessor where the object is a handle
	const char *script10 = 
		"class Test                 \n"
		"{                          \n"
		"  uint get_p() {return 0;} \n"
		"  void set_p(uint) {}      \n"
		"  void test()              \n"
		"  {                        \n"
		"    p = 0;                 \n"
		"    int a = p;             \n"
		"  }                        \n"
		"}                          \n"
		"void func()                \n"
		"{                          \n"
		"  Test @a = Test();        \n"
		"  a.p = 1;                 \n"
		"  int b = a.p;             \n"
		"}                          \n";
	mod->AddScriptSection("script", script10);
	bout.buffer = "";
	r = mod->Build();
	if( r < 0 )
	{
		TEST_FAILED;
		printf("Failed to compile the script\n");
	}
	if( bout.buffer != "" )
	{
		printf("%s", bout.buffer.c_str());
		TEST_FAILED;
	}
	r = ExecuteString(engine, "func()", mod);
	if( r != asEXECUTION_FINISHED )
	{
		TEST_FAILED;
	}

	// Test accessors with function arguments (by value, in ref, out ref)
	const char *script11 = 
		"class Test                 \n"
		"{                          \n"
		"  uint get_p() {return 0;} \n"
		"  void set_p(uint) {}      \n"
		"}                          \n"
		"void func()                \n"
		"{                          \n"
		"  Test a();                \n"
		"  byVal(a.p);              \n"
		"  inArg(a.p);              \n"
		"  outArg(a.p);             \n"
		"}                          \n"
		"void byVal(int v) {}       \n"
		"void inArg(int &in v) {}   \n"
		"void outArg(int &out v) {} \n";
	mod->AddScriptSection("script", script11);
	bout.buffer = "";
	r = mod->Build();
	if( r < 0 )
	{
		TEST_FAILED;
		printf("Failed to compile the script\n");
	}
	if( bout.buffer != "" )
	{
		printf("%s", bout.buffer.c_str());
		TEST_FAILED;
	}
	r = ExecuteString(engine, "func()", mod);
	if( r != asEXECUTION_FINISHED )
	{
		TEST_FAILED;
	}

	// When the property is an object type, then the set accessor should be 
	// used instead of the overloaded assignment operator to set the value. 
	// Properties of object properties, must allow having different 
	// types for get and set. IsEqualExceptConstAndRef should be used.
	const char *script12 = 
		"class Test                                   \n"
		"{                                            \n"
		"  string get_s() {return _s;}                \n"
		"  void set_s(const string &in n) {_s = n;}   \n"
		"  string _s;                                 \n"
		"}                                            \n"
		"void func()                \n"
		"{                          \n"
		"  Test t;                  \n"
		"  t.s = 'hello';           \n"
		"  assert(t.s == 'hello');  \n"
		"}                          \n";
	mod->AddScriptSection("script", script12);
	bout.buffer = "";
	r = mod->Build();
	if( r < 0 )
	{
		TEST_FAILED;
		printf("Failed to compile the script\n");
	}
	if( bout.buffer != "" )
	{
		printf("%s", bout.buffer.c_str());
		TEST_FAILED;
	}
	r = ExecuteString(engine, "func()", mod);
	if( r != asEXECUTION_FINISHED )
	{
		TEST_FAILED;
	}

	// Compound assignments for object properties will not be allowed
	r = ExecuteString(engine, "Test t; t.s += 'hello';", mod);
	if( r >= 0 )
	{
		TEST_FAILED;
	}
	if( bout.buffer != "ExecuteString (1, 13) : Error   : Compound assignments with property accessors are not allowed\n" )
	{
		printf("%s", bout.buffer.c_str());
		TEST_FAILED;
	}
	
	// Test @t.prop = @obj; Property is a handle, and the property is assigned a new handle. Should work
	const char *script13 = 
		"class Test                                   \n"
		"{                                            \n"
		"  string@ get_s() {return _s;}               \n"
		"  void set_s(string @n) {@_s = @n;}          \n"
		"  string@ _s;                                \n"
		"}                          \n"
		"void func()                \n"
		"{                          \n"
		"  Test t;                  \n"
		"  string s = 'hello';      \n"
		"  @t.s = @s;               \n" // handle assignment
		"  assert(t.s is s);        \n"
		"  t.s = 'other';           \n" // value assignment
		"  assert(s == 'other');    \n"
		"}                          \n";
	mod->AddScriptSection("script", script13);
	bout.buffer = "";
	r = mod->Build();
	if( r < 0 )
	{
		TEST_FAILED;
		printf("Failed to compile the script\n");
	}
	if( bout.buffer != "" )
	{
		printf("%s", bout.buffer.c_str());
		TEST_FAILED;
	}
	r = ExecuteString(engine, "func()", mod);
	if( r != asEXECUTION_FINISHED )
	{
		TEST_FAILED;
	}

	// Test accessing members of an object property
	const char *script14 = 
		"class Test                                   \n"
		"{                                            \n"
		"  string get_s() {return _s;}                \n"
		"  void set_s(string n) {_s = n;}             \n"
		"  string _s;                                 \n"
		"}                            \n"
		"void func()                  \n"
		"{                            \n"
		"  Test t;                    \n"
		"  t.s = 'hello';             \n" // value assignment
		"  assert(t.s == 'hello');    \n"
		"  assert(t.s.length() == 5); \n" // this should work as length is const
		"}                            \n";
	mod->AddScriptSection("script", script14);
	bout.buffer = "";
	r = mod->Build();
	if( r < 0 )
	{
		TEST_FAILED;
		printf("Failed to compile the script\n");
	}
	if( bout.buffer != "" )
	{
		printf("%s", bout.buffer.c_str());
		TEST_FAILED;
	}
	r = ExecuteString(engine, "func()", mod);
	if( r != asEXECUTION_FINISHED )
	{
		TEST_FAILED;
	}

	// Test accessing a non-const method on an object through a get accessor
	// Should at least warn since the object is just a temporary one
	bout.buffer.c_str();
	r = ExecuteString(engine, "Test t; t.s.resize(4);", mod);
	if( r < 0 )
		TEST_FAILED;
	if( (sizeof(void*) == 4 &&
		 bout.buffer != "ExecuteString (1, 13) : Warning : A non-const method is called on temporary object. Changes to the object may be lost.\n"
		                "ExecuteString (1, 13) : Info    : void string::resize(uint)\n") ||
		(sizeof(void*) == 8 &&
		 bout.buffer != "ExecuteString (1, 13) : Warning : A non-const method is called on temporary object. Changes to the object may be lost.\n"
		                "ExecuteString (1, 13) : Info    : void string::resize(uint64)\n") )
	{
		printf("%s", bout.buffer.c_str());
		TEST_FAILED;
	}

	// Test opNeg for object through get accessor
	const char *script15 = 
		"class Val { int opNeg() const { return -1; } } \n"
		"class Test                          \n"
		"{                                   \n"
		"  Val get_s() const {return Val();} \n"
		"}                                   \n"
		"void func()                  \n"
		"{                            \n"
		"  Test t;                    \n"
		"  assert( -t.s == -1 );      \n"
		"}                            \n";
	mod->AddScriptSection("script", script15);
	bout.buffer = "";
	r = mod->Build();
	if( r < 0 )
	{
		TEST_FAILED;
		printf("Failed to compile the script\n");
	}
	if( bout.buffer != "" )
	{
		printf("%s", bout.buffer.c_str());
		TEST_FAILED;
	}
	r = ExecuteString(engine, "func()", mod);
	if( r != asEXECUTION_FINISHED )
	{
		TEST_FAILED;
	}	

	// Test index operator for object through get accessor
	const char *script16 = 
		"class Test                          \n"
		"{                                   \n"
		"  int[] get_s() const { int[] a(1); a[0] = 42; return a; } \n"
		"}                                   \n"
		"void func()                  \n"
		"{                            \n"
		"  Test t;                    \n"
		"  assert( t.s[0] == 42 );    \n"
		"}                            \n";
	mod->AddScriptSection("script", script16);
	bout.buffer = "";
	r = mod->Build();
	if( r < 0 )
	{
		TEST_FAILED;
		printf("Failed to compile the script\n");
	}
	if( bout.buffer != "script (5, 1) : Info    : Compiling void func()\n"
	                   "script (8, 14) : Warning : A non-const method is called on temporary object. Changes to the object may be lost.\n"
					   "script (8, 14) : Info    : int& array::opIndex(uint)\n" )
	{
		printf("%s", bout.buffer.c_str());
		TEST_FAILED;
	}
	r = ExecuteString(engine, "func()", mod);
	if( r != asEXECUTION_FINISHED )
	{
		TEST_FAILED;
	}	

	// Test accessing normal properties for object through get accessor
	const char *script17 = 
		"class Val { int val; } \n"
		"class Test                          \n"
		"{                                   \n"
		"  Val get_s() const { Val v; v.val = 42; return v;} \n"
		"}                                   \n"
		"void func()                  \n"
		"{                            \n"
		"  Test t;                    \n"
		"  assert( t.s.val == 42 );   \n"
		"}                            \n";
	mod->AddScriptSection("script", script17);
	bout.buffer = "";
	r = mod->Build();
	if( r < 0 )
	{
		TEST_FAILED;
		printf("Failed to compile the script\n");
	}
	if( bout.buffer != "" )
	{
		printf("%s", bout.buffer.c_str());
		TEST_FAILED;
	}
	r = ExecuteString(engine, "func()", mod);
	if( r != asEXECUTION_FINISHED )
	{
		TEST_FAILED;
	}	

	// Test const/non-const get and set accessors
	const char *script18 = 
		"class Test                          \n"
		"{                                   \n"
		"  int get_p() { return 42; }        \n"
		"  int get_c() const { return 42; }  \n"
		"  void set_s(int) {}                \n"
		"}                                   \n"
		"void func()                  \n"
		"{                            \n"
		"  const Test @t = @Test();   \n"
		"  assert( t.p == 42 );       \n" // Fail
		"  assert( t.c == 42 );       \n" // Success
		"  t.s = 42;                  \n" // Fail
		"}                            \n";
	mod->AddScriptSection("script", script18);
	bout.buffer = "";
	r = mod->Build();
	if( r >= 0 )
		TEST_FAILED;
	if( bout.buffer != "script (7, 1) : Info    : Compiling void func()\n"
	                   "script (10, 15) : Error   : Non-const method call on read-only object reference\n"
	                   "script (10, 15) : Info    : int Test::get_p()\n"
					   "script (12, 7) : Error   : Non-const method call on read-only object reference\n"
	                   "script (12, 7) : Info    : void Test::set_s(int)\n" )
	{
		printf("%s", bout.buffer.c_str());
		TEST_FAILED;
	}

	// Test accessor with property of the same name
	const char *script19 = 
		"int direction; \n"
		"void set_direction(int val) { direction = val; } \n"
		"void test_set() \n"
		"{ \n"
		"  direction = 9; \n" // calls the set_direction property accessor
		"} \n"
		"void test_get() \n"
		"{ \n"
		"  assert( direction == 9 ); \n" // fails, since there is no get accessor
		"} \n";
	mod->AddScriptSection("script", script19);
	bout.buffer = "";
	r = mod->Build();
	if( r >= 0 )
		TEST_FAILED;
	if( bout.buffer != "script (7, 1) : Info    : Compiling void test_get()\n"
	                   "script (9, 21) : Error   : The property has no get accessor\n" )
	{
		printf("%s", bout.buffer.c_str());
		TEST_FAILED;
	}

	const char *script20 = 
		"class Test { \n"
		"  int direction; \n"
		"  void set_direction(int val) { direction = val; } \n"
		"} \n";
	mod->AddScriptSection("script", script20);
	bout.buffer = "";
	r = mod->Build();
	if( r < 0 )
		TEST_FAILED;
	if( bout.buffer != "" )
	{
		printf("%s", bout.buffer.c_str());
		TEST_FAILED;
	}
	r = ExecuteString(engine, "Test t; t.set_direction(3);", mod);
	if( r != asEXECUTION_FINISHED )
		TEST_FAILED;
	
	// TODO: Test non-const get accessor for object type with const overloaded dual operator
	
	// TODO: Test get accessor that returns a reference (only from application func to start with)
		
	// TODO: Test property accessor with inout references. Shouldn't be allowed as the value is not a valid reference

	// TODO: Test set accessor with parameter declared as out ref (shouldn't be found)

	// TODO: What should be done with expressions like t.prop; Should the get accessor be called even though 
	//       the value is never used?

	// TODO: Accessing a class member from within the property accessor with the same name as the property 
	//       shouldn't call the accessor again. Instead it should access the real member. FindPropertyAccessor() 
	//       shouldn't find any if the function being compiler is the property accessor itself

	engine->Release();

	// Test property accessor on temporary object handle
	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);
		RegisterStdString(engine);

		const char *script = "class Obj { void set_opacity(float v) {} }\n"
			                 "Obj @GetObject() { return @Obj(); } \n";

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

		r = ExecuteString(engine, "GetObject().opacity = 1.0f;", mod);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;

		engine->Release();
	}

	// Test bug reported by Scarabus2
	// The bug was an incorrect reusage of temporary variable by the  
	// property get accessor when compiling a binary operator
	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);
		engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);

		const char *script = 
			"class Object { \n"
			"  Object() {rot = 0;} \n"
			"  void set_rotation(float r) {rot = r;} \n"
			"  float get_rotation() const {return rot;} \n"
			"  float rot; } \n";

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

		r = ExecuteString(engine, "Object obj; \n"
								  "float elapsed = 1.0f; \n"
								  "float temp = obj.rotation + elapsed * 1.0f; \n"
								  "obj.rotation = obj.rotation + elapsed * 1.0f; \n"
								  "assert( obj.rot == 1 ); \n", mod);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;

		engine->Release();
	}

	// Test global property accessor
	{
		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 _s = 0;  \n"
			"int get_s() { return _s; } \n"
			"void set_s(int v) { _s = v; } \n";

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

		r = ExecuteString(engine, "s = 10; assert( s == 10 );", mod);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;

		engine->Release();

		// The global property accessors are available to initialize global 
		// variables, but can possibly throw an exception if used inappropriately.
		// This test also verifies that circular references between global 
		// properties and functions is properly resolved by the GC.
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(CBufferedOutStream, Callback), &bout, asCALL_THISCALL);
		RegisterStdString(engine);

		bout.buffer = "";

		script =
			"string _s = s; \n"
			"string get_s() { return _s; } \n";

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

		if( bout.buffer != "script (1, 13) : Error   : Failed to initialize global variable '_s'\n"
		                   "script (2, 0) : Info    : Exception 'Null pointer access' in 'string get_s()'\n" )
		{
			printf("%s", bout.buffer.c_str());
			TEST_FAILED;
		}

		engine->Release();
	}

	// Test property accessor for object in array
	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);
		RegisterScriptArray(engine, true);
		engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);

		const char *script = 
			"class MyObj { bool get_Active() { return true; } } \n";
			
		asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
		mod->AddScriptSection("script", script);
		r = mod->Build();
		if( r < 0 )
			TEST_FAILED;

		r = ExecuteString(engine, "MyObj[] a(1); if( a[0].Active == true ) { } if( a[0].get_Active() == true ) { }", mod);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;

		engine->Release();
	}

	// Test property accessor from within class method
	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);

		const char *script = 
			"class Vector3 \n"
			"{ \n"
			"  float x; \n"
			"  float y; \n"
			"  float z; \n"
			"}; \n"
			"class Hoge \n"
			"{ \n"
			"    const Vector3 get_pos() { return mPos; } \n"
			"    const Vector3 foo() { return pos;  } \n"
			"    const Vector3 zoo() { return get_pos(); } \n"
			"    Vector3 mPos; \n"
			"}; \n"
			"void main() \n"
			"{ \n"
			"    Hoge h; \n"
			"    Vector3 vec; \n"
			"    vec = h.zoo(); \n" // ok
			"    vec = h.foo(); \n" // runtime exception
			"} \n";
			
		asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
		mod->AddScriptSection("script", script);
		r = mod->Build();
		if( r < 0 )
			TEST_FAILED;

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

		engine->Release();
	}

	// Test property accessor in type conversion 
	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);
		RegisterScriptArray(engine, true);

		const char *script = 
			"class sound \n"
			"{ \n"
			"  int get_pitch() { return 1; } \n"
			"  void set_pitch(int p) {} \n"
			"} \n"
			"void main() \n"
			"{ \n"
			"  sound[] sounds(1) ; \n"
			"  sounds[0].pitch = int(sounds[0].pitch)/2; \n"
			"} \n";


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

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

		engine->Release();
	}

	// Test property accessor in type conversion (2)
	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);

		const char *script = 
			"class sound \n"
			"{ \n"
			"  const int &get_id() const { return i; } \n"
			"  int i; \n"
			"} \n"
			"void main() \n"
			"{ \n"
			"  sound s; \n"
			"  if( s.id == 1 ) \n"
			"    return; \n"
			"} \n";


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

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

		engine->Release();
	}

	// Test property accessors for opIndex
	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);
		RegisterScriptArray(engine, false);
		RegisterScriptString(engine);
		engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);

		const char *script = 
			"class CTest \n"
			"{ \n"
			"  CTest() { arr.resize(5); } \n"
			"  int get_opIndex(int i) const { return arr[i]; } \n"
			"  void set_opIndex(int i, int v) { arr[i] = v; } \n"
			"  array<int> arr; \n"
			"} \n"
			"void main() \n"
			"{ \n"
			"  CTest s; \n"
			"  s[0] = 42; \n"
			"  assert( s[0] == 42 ); \n"
			"  s[1] = 24; \n"
			"  assert( s[1] == 24 ); \n"
			"} \n";

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

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

		engine->Release();
	}

	// Test global property accessors with index argument
	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);
		RegisterScriptArray(engine, false);
		RegisterScriptString(engine);
		engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);

		const char *script = 
			"  int get_arr(int i) { arr.resize(5); return arr[i]; } \n"
			"  void set_arr(int i, int v) { arr.resize(5); arr[i] = v; } \n"
			"  array<int> arr; \n"
			"void main() \n"
			"{ \n"
			"  arr[0] = 42; \n"
			"  assert( arr[0] == 42 ); \n"
			"  arr[1] = 24; \n"
			"  assert( arr[1] == 24 ); \n"
			"} \n";

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

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

		engine->Release();
	}

	// Test member property accessors with index argument
	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);
		RegisterScriptArray(engine, false);
		RegisterScriptString(engine);
		engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);

		const char *script = 
			"class CTest \n"
			"{ \n"
			"  CTest() { arr.resize(5); } \n"
			"  int get_arr(int i) { return arr[i]; } \n"
			"  void set_arr(int i, int v) { arr[i] = v; } \n"
			"  private array<int> arr; \n"
			"  void test() \n"
			"  { \n"
			"    arr[0] = 42; \n"
			"    assert( arr[0] == 42 ); \n"
			"    arr[1] = 24; \n"
			"    assert( arr[1] == 24 ); \n"
			"  } \n"
			"} \n"
			"void main() \n"
			"{ \n"
			"  CTest s; \n"
			"  s.arr[0] = 42; \n"
			"  assert( s.arr[0] == 42 ); \n"
			"  s.arr[1] = 24; \n"
			"  assert( s.arr[1] == 24 ); \n"
			"  s.test(); \n"
			"} \n";

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

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

		engine->Release();
	}

	// Test member property accessors with ++ where the set accessor takes a reference
	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(CBufferedOutStream, Callback), &bout, asCALL_THISCALL);

		bout.buffer = "";
		const char *script = 
			"class CTest \n"
			"{ \n"
			"  double _vol; \n"
			"  double get_vol() const { return _vol; } \n"
			"  void set_vol(double &in v) { _vol = v; } \n"
			"} \n"
			"CTest t; \n"
			"void main() \n"
			"{ \n"
			"  for( t.vol = 0; t.vol < 10; t.vol++ ); \n"
			"} \n";

		asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
		mod->AddScriptSection("script", script);
		r = mod->Build();
		if( r >= 0 )
			TEST_FAILED;
		if( bout.buffer != "script (8, 1) : Info    : Compiling void main()\n"
		                   "script (10, 36) : Error   : Invalid reference. Property accessors cannot be used in combined read/write operations\n" )
		{
			printf("%s", bout.buffer.c_str());
			TEST_FAILED;
		}

		engine->Release();
	}

	fail = Test2() || fail;

	// Success
	return fail;
}
Example #6
0
bool Test()
{
	bool fail = false;
	fail = Test2() || fail;
	int r;
	COutStream out;
	CBufferedOutStream bout;
	asIScriptContext *ctx;
	asIScriptEngine *engine;
	
	// Compile array with default value in list
	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
		RegisterScriptString(engine); // ref type
		RegisterScriptArray(engine, false);
		engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);

		r = ExecuteString(engine, "array<string> a = {'a', , 'c', , 'e'}; assert( a[1] == '' );");
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;

		engine->Release();
	}

	// Compile array with default value in list
	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
		RegisterStdString(engine); // value type
		RegisterScriptArray(engine, false);
		engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);

		r = ExecuteString(engine, "array<string> a = {'a', , 'c', , 'e'}; assert( a[1] == '' );");
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;

		engine->Release();
	}

	// Compile nested array init list
	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
		RegisterScriptArray(engine, false);

		r = ExecuteString(engine, "array<array<int>> a = {{1,2},{3,4}};");
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;

		engine->Release();
	}

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

		RegisterScriptString(engine);
		RegisterScriptArray(engine, false);

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

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

		// Test sorting on array of handles
		mod->AddScriptSection(TESTNAME, 
			"class Test { \n"
			"  Test(int v) {val = v;} \n"
			"  int opCmp(const Test & o) const { return val - o.val; } \n"
			"  int val; \n"
			"} \n");
		r = mod->Build();
		if( r < 0 )
			TEST_FAILED;
		ctx = engine->CreateContext();
		r = ExecuteString(engine, 
			"array<Test @> a = { Test(1), Test(4), Test(2), null, Test(3) }; \n"
			"a.sortAsc(); \n"
			"Assert( a[0] is null ); \n"
			"Assert( a[1].val == 1 ); \n"
			"Assert( a[2].val == 2 ); \n"
			"Assert( a[3].val == 3 ); \n"
			"Assert( a[4].val == 4 ); \n", mod);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;
		if( r == asEXECUTION_EXCEPTION )
			PrintException(ctx);
		ctx->Release();	

		// Test different signatures on opCmp and opEquals
		mod->AddScriptSection(TESTNAME,
			"class C \n"
			"{ \n"
			"    C(int i) {i_ = i;} \n"
	//		"    bool opEquals (const C &in other) const\n"
	//		"    { \n"
	//		"        return i_ == other.i_; \n"
	//		"    } \n"
	//		"    int opCmp (const C &in other) const\n"
	//		"    { \n"
	//		"        return i_ - other.i_; \n"
	//		"    } \n"
			"    bool opEquals (const C @ other) const\n"
			"    { \n"
			"        return i_ == other.i_; \n"
			"    } \n"
			"    int opCmp (const C @ other) const\n"
			"    { \n"
			"        return i_ - other.i_; \n"
			"    } \n"
			"    int i_; \n"
			"} \n"
			"void main (void) \n"
			"{ \n"
			"    array<const C @> a2; \n"
			"    a2.insertLast(@C(2)); \n"
			"    a2.insertLast(@C(1)); \n"
			"    a2.sortAsc(); \n"
			"    Assert( a2[0].i_ == 1 ); \n"
			"    Assert( a2[1].i_ == 2 ); \n"
			"    C f(2); \n"
			"    Assert( a2.find(f) == 1 ); \n"
			"} \n");
		r = mod->Build();
		if( r < 0 )
			TEST_FAILED;
		ctx = engine->CreateContext();
		r = ExecuteString(engine, "main()", mod, ctx);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;
		if( r == asEXECUTION_EXCEPTION )
			PrintException(ctx);
		ctx->Release();

		// Multiple tests in one
		mod->AddScriptSection(TESTNAME, script1, strlen(script1), 0);
		r = mod->Build();
		if( r < 0 )
		{
			TEST_FAILED;
			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);
			TEST_FAILED;
		}
		if( ctx ) ctx->Release();

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

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

		// 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 )
		{
			TEST_FAILED;
			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);
			TEST_FAILED;
		}
		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 )
		{
			TEST_FAILED;
			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);
			TEST_FAILED;
		}
		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 ) TEST_FAILED;
		ctx = engine->CreateContext();
		r = ExecuteString(engine, "TestArrayInitList()", mod, ctx);
		if( r != asEXECUTION_FINISHED ) TEST_FAILED;
		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 ) TEST_FAILED;
		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("%s", bout.buffer.c_str());
			TEST_FAILED;
		}

		// 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 ) 
			TEST_FAILED;
		r = ExecuteString(engine, "Test()", mod);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;
		
		// 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 )
			TEST_FAILED;

		// Test reserve()
		{
			const char *script = 
				"array<int> f; \n"
				"f.reserve(10); \n"
				"for( uint n = 0; n < 10; n++ ) \n"
				"  f.insertAt(n, n); \n"
				"Assert( f.length() == 10 ); \n";
			r = ExecuteString(engine, script, mod);
			if( r != asEXECUTION_FINISHED )
				TEST_FAILED;
		}

		// 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 )
			TEST_FAILED;

		// 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 )
			TEST_FAILED;

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

		// 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 )
			TEST_FAILED;
		if( bout.buffer != "ExecuteString (1, 7) : Error   : Can't instanciate template 'array' with subtype 'single'\n" )
		{
			printf("%s", bout.buffer.c_str());
			TEST_FAILED;
		}

		engine->Release();
	}

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

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

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

		r = ExecuteString(engine, "array<int> list;\n"
								  "list.resize(3);\n"
								  "list.reserve(-1);\n", 0, ctx);
		if( r != asEXECUTION_EXCEPTION )
			TEST_FAILED;
		else if( strcmp(ctx->GetExceptionString(), "Too large array size") != 0 )
			TEST_FAILED;

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

	// Test garbage collect with script class that holds array member
	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		RegisterScriptArray(engine, false);

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

		const char *script = 
			"class MyTest \n"
			"{ \n"
			"	array<int> myList; \n"
			"} \n";

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

		asIScriptObject *obj = (asIScriptObject*)engine->CreateScriptObject(mod->GetObjectTypeByName("MyTest"));
		obj->Release();

		engine->Release();
	}

	// Test the default value constructor
	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);
		RegisterScriptArray(engine, false);
		engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);

		asIScriptModule *mod = engine->GetModule("module", asGM_ALWAYS_CREATE);
		engine->SetEngineProperty(asEP_OPTIMIZE_BYTECODE, false);

		const char *script = 
			"void main() \n"
			"{ \n"
			"	array<int> arr(2, 42); \n"
			"   assert(arr[0] == 42); \n"
			"   assert(arr[1] == 42); \n"
			"   array<array<int>> arr2(2, array<int>(2)); \n"
			"   assert(arr2[0].length() == 2); \n"
			"	assert(arr2[1].length() == 2); \n"
			"   array<array<int>@> arr3(2, arr); \n"
			"   assert(arr3[0] is arr); \n"
			"   assert(arr3[1] is arr); \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;

		engine->Release();
	}

	// Test potential memory leak situation with circular reference between types
	{
		// Create the script engine
		asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
	 
		// Register array class
		RegisterScriptArray(engine, false);
	 
		// Compile
		asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
		mod->AddScriptSection("script", 
			"class Hoge"
			"{"
			"    HogeManager@ hogeManager;"
			"};"
			"class HogeManager"
			"{"
			"    array< Hoge >@ hoges;"
			"};"
			, 0);
		mod->Build();
	 
		// Release engine
		engine->Release();
	}

	// Test creating script array from application
	{
		if( strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY") )
		{
			printf("Subtest: Skipped due to AS_MAX_PORTABILITY\n");
		}
		else
		{
			asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
			RegisterScriptArray(engine, false);
			RegisterScriptString(engine);
		
			r = engine->RegisterGlobalFunction("array<string@>@ CreateArrayOfStrings()", asFUNCTION(CreateArrayOfStrings), asCALL_CDECL); assert( r >= 0 );

			r = ExecuteString(engine, "array<string@>@ arr = CreateArrayOfStrings()");
			if( r != asEXECUTION_FINISHED )
				TEST_FAILED;
		 
			// Release engine
			engine->Release();
		}		
	}

	// Test insertAt, removeAt
	{
		asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		RegisterScriptArray(engine, false);
		RegisterScriptString(engine);
		engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);

		r = ExecuteString(engine, "array<string> arr = {'1','2','3'}; \n"
			                      "arr.insertAt(1, 'test'); \n"
								  "assert( arr[1] == 'test' );\n"
								  "arr.insertAt(4, '4'); \n"
								  "assert( arr[4] == '4' );\n"
								  "arr.removeAt(0); \n"
								  "assert( arr[0] == 'test' );\n"
								  "assert( arr[3] == '4' );\n");
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;

		engine->Release();
	}

	// This test was failing on XBOX 360
	{
		asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);

		RegisterScriptArray(engine, true);
		
		const char *script = 
			"class ArrayOf  \n"
			"{  \n"
			"  uint8[] _boolList;  \n"
			"  int _numOfStockedObject;  \n"
			"  ArrayOf(int arraySizeMax)  \n"
			"  {  \n"
			"    _boolList.resize(arraySizeMax);  \n"
			"    _numOfStockedObject = 0;  \n"
			"    for(int i = 0; i < arraySizeMax; ++i)  \n"
			"    {  \n"
			"       _boolList[i] = 0; \n"
			"    } \n"
			"  } \n"
			"} \n";

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

		engine->Release();
	}

	// Array should call subtypes' opAssign when it exists
	{
		asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);
		RegisterScriptArray(engine, true);
		engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);

		const char *script = 
			"int calls = 0; \n"
			"class Value  \n"
			"{  \n"
			"  int val;  \n"
			"  Value(int v) {val = v;} \n"
			"  Value() {} \n"
			"  Value &opAssign(const Value &in o) { calls++; return this; } \n"
			"} \n";

		asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
		mod->AddScriptSection("script", script);
		r = mod->Build();
		if( r < 0 ) TEST_FAILED;
		r = ExecuteString(engine, "array<Value> arr = {Value(2), Value(3), Value(0)}; \n"
								  "assert( calls == 0 ); \n"
								  "array<Value> arr2; \n"
								  "arr2 = arr; \n"
								  "assert( calls == 3 ); \n", mod);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;

		engine->Release();
	}

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

		const char *script = 
			"class Value  \n"
			"{  \n"
			"  int val;  \n"
			"  Value(int v) {val = v;} \n"
			"  Value() {} \n"
			"  int opCmp(const Value &in o) {return val - o.val;} \n"
			"} \n";

		asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
		mod->AddScriptSection("script", script);
		r = mod->Build();
		if( r < 0 ) TEST_FAILED;
		r = ExecuteString(engine, "Value[] arr = {Value(2), Value(3), Value(0)}; \n"
			                      "arr.sortAsc(); \n"
								  "assert(arr[0].val == 0); \n"
								  "assert(arr[1].val == 2); \n"
								  "assert(arr[2].val == 3);", mod);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;

		engine->Release();
	}

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

		const char *script = 
			"bool TestSort() \n"
			"{ \n"
			"	array<int> A = {1, 5, 2, 4, 3}; \n"
			"	array<int> B = {1, 5, 2, 4, 3}; \n"
			"	A.sortAsc(); \n"
			"	B.sortDesc(); \n"
			"	return \n"
			"		A[0] == 1 && A[1] == 2 && A[2] == 3 && A[3] == 4 && A[4] == 5 && \n"
			"		B[0] == 5 && B[1] == 4 && B[2] == 3 && B[3] == 2 && B[4] == 1; \n"
			"} \n"
			"bool TestReverse() \n"
			"{ \n"
			"	array<int> A = {5, 4, 3, 2, 1}; \n"
			"	A.reverse(); \n"
			"	return A[0] == 1 && A[1] == 2 && A[2] == 3 && A[3] == 4 && A[4] == 5; \n"
			"} \n"
			"class cOpCmp \n"
			"{ \n"
			"	cOpCmp() \n"
			"	{ \n"
			"		a = 0; \n"
			"		b = 0.0; \n"
			"	}	 \n"
			"	cOpCmp(int _a, float _b) \n"
			"	{ \n"
			"		a = _a; \n"
			"		b = _b;	 \n"
			"	} \n"
			"	void set(int _a, float _b) \n"
			"	{ \n"
			"		a = _a; \n"
			"		b = _b; \n"
			"	} \n"
			"	int opCmp(cOpCmp &in other) \n"
			"	{ \n"
			"		return a - other.a; \n"
			"	} \n"
			"	int a; \n"
			"	float b; \n"
			"} \n"
			"class cOpEquals \n"
			"{ \n"
			"	cOpEquals() \n"
			"	{ \n"
			"		a = 0; \n"
			"		b = 0.0; \n"
			"	}	 \n"
			"	cOpEquals(int _a, float _b) \n"
			"	{ \n"
			"		a = _a; \n"
			"		b = _b;	 \n"
			"	} \n"
			"	void set(int _a, float _b) \n"
			"	{ \n"
			"		a = _a; \n"
			"		b = _b; \n"
			"	} \n"
			"	bool opEquals(cOpEquals &in other) \n"
			"	{ \n"
			"		return a == other.a; \n"
			"	} \n"
			"	int a; \n"
			"	float b; \n"
			"} \n"
			"bool TestFind() \n"
			"{ \n"
			"	array<int> A = {5, 8, 3, 2, 0, 0, 2, 1}; \n"
			"	if (A.find(10) != -1) \n"
			"		return false; \n"
			"	if (A.find(0) != 4) \n"
			"		return false; \n"
			"	if (A.find(1, 8) != 1) \n"
			"		return false; \n"
			"	if (A.find(2, 8) != -1) \n"
			"		return false; \n"
			"	array<cOpCmp> CMP(5); \n"
			"	CMP[0].set(0, 0.0); \n"
			"	CMP[1].set(1, 0.0); \n"
			"	CMP[2].set(2, 0.0); \n"
			"	CMP[3].set(3, 0.0); \n"
			"	CMP[4].set(4, 0.0);	\n"
			"	if (CMP.find(cOpCmp(5, 0.0)) != -1) \n"
			"		return false; \n"
			"	if (CMP.find(2, cOpCmp(2, 1.0)) != 2) \n"
			"		return false; \n"
			"	if (CMP.find(3, cOpCmp(2, 1.0)) != -1) \n"
			"		return false; \n"
			"	array<cOpEquals> EQ(5); \n"
			"	EQ[0].set(0, 0.0); \n"
			"	EQ[1].set(1, 0.0); \n"
			"	EQ[2].set(2, 0.0); \n"
			"	EQ[3].set(3, 0.0); \n"
			"	EQ[4].set(4, 0.0); \n"
			"	if (EQ.find(cOpEquals(5, 0.0)) != -1) \n"
			"		return false; \n"
			"	if (EQ.find(2, cOpEquals(2, 1.0)) != 2) \n"
			"		return false; \n"
			"	if (EQ.find(3, cOpEquals(2, 1.0)) != -1) \n"
			"		return false; \n"
			"	return true; \n"
			"} \n"
			"int main() \n"
			"{ \n"
			"	assert( TestSort() ); \n"
			"	assert( TestReverse() ); \n"
			"	assert( TestFind() ); \n"
			"	return 789; \n"
			"} \n";

		asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
		mod->AddScriptSection("script", script);
		r = mod->Build();
		if( r < 0 ) TEST_FAILED;
		r = ExecuteString(engine, "assert( main() == 789 ); \n", mod);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;

		engine->Release();
	}

	// Test array, with objects that don't have default constructor/factory
	{
		asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(CBufferedOutStream, Callback), &bout, asCALL_THISCALL);
		RegisterScriptArray(engine, true);
		engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);

		const char *script = 
			"class CTest \n"
			"{ \n"
			"  CTest(int v) {} \n" // With an explicit non-default constructor the compiler won't create the default constructor
			"} \n"
			"array<CTest> arr; \n";

		asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
		mod->AddScriptSection("script", script);
		bout.buffer = "";
		r = mod->Build();
		if( r > 0 ) 
			TEST_FAILED;
		if( bout.buffer != "script (5, 7) : Error   : Can't instanciate template 'array' with subtype 'CTest'\n" )
		{
			printf("%s", bout.buffer.c_str());
			TEST_FAILED;
		}

		engine->Release();
	}	

	{
		asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(CBufferedOutStream, Callback), &bout, asCALL_THISCALL);
		RegisterScriptArray(engine, true);

		const char *script = 
			"class T { }; \n"
			"array<T> arr; \n";

		asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
		mod->AddScriptSection("script", 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, "array<T> arr(1); \n", mod);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;
		
		engine->Release();
	}

	// Test problem with arrays of enums reported by Philip Bennefall
	{
		const char *script = 
			"enum fruit \n"
			"{ \n"
			"  APPLE, ORANGE, BANANA \n"
			"} \n"
			"void main() \n"
			"{ \n"
			"  fruit[] basket; \n"
			"  basket.insertLast(APPLE); \n"
			"  basket.insertLast(ORANGE); \n"
			"  basket.sortDesc(); \n"
			"  int index = basket.find(APPLE); \n"
			"  assert( index == 1 ); \n"
			"} \n";

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

		asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
		mod->AddScriptSection("script", 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, "main()", mod);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;
		
		engine->Release();
	}

	// Test problem with arrays and opEquals reported by Philip Bennefall
	{
		const char *script = 
			"class fish \n"
			"{ \n"
			"  bool opEquals(fish@ other) \n" // handles should be supported too
			"  { \n"
			"    return false; \n"
			"  } \n"
			"} \n"
			"void main() \n"
			"{ \n"
			"  fish[] ocean(100); \n"
			"  fish nemo; \n"
			"  int index = ocean.find(nemo); \n"
			"} \n";

		asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(CBufferedOutStream, Callback), &bout, asCALL_THISCALL);
		RegisterScriptArray(engine, true);

		asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
		mod->AddScriptSection("script", 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, "main()", mod);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;
		
		engine->Release();
	}

	// Test problem with arrays and opEquals reported by Philip Bennefall
	{
		const char *script = 
			"class fish \n"
			"{ \n"
			"  bool opEquals(fish@ other) \n"
			"  { \n"
			"    return false; \n"
			"  } \n"
			"} \n"
			"void main() \n"
			"{ \n"
			"  fish@[] ocean(100); \n"
			"  for(uint i=0; i<ocean.length(); i++) \n"
			"  { \n"
			"    fish fred; \n"
			"    @(ocean[i]) = fred; \n"
			"  } \n"
			"  fish nemo; \n"
			"  int index = ocean.find(nemo); \n"
			"} \n";

		asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(CBufferedOutStream, Callback), &bout, asCALL_THISCALL);
		RegisterScriptArray(engine, true);

		asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
		mod->AddScriptSection("script", 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, "main()", mod);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;
		
		engine->Release();
	}

	// Test problem with arrays and opAssign reported by Philip Bennefall
	{
		const char *script = 
			"array<uint> a, b = {0,1,2,3}; \n"
			"a.reserve(10); \n"
			"a = b; \n"
			"assert( a.length() == b.length() ); \n"
			"assert( a.length() == 4 ); \n"
			"for( uint n = 0; n < a.length(); n++ ) \n"
			"  assert( a[n] == n ); \n";

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

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

	// Test findByRef
	{
		const char *script =
			"class Obj {} \n"
			"array<int> ia = {1,2,3}; \n"
			"array<Obj> oa = {Obj(), Obj()}; \n"
			"array<Obj@> ha = {Obj(), Obj()}; \n";

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

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

		r = ExecuteString(engine, "assert( ia.findByRef(ia[1]) == -1 ); \n"
								  "Obj @obj = oa[1]; assert( oa.findByRef(obj) == 1 ); \n"
								  "@obj = ha[1]; assert( ha.findByRef(obj) == 1 ); \n"
								  "ha.insertLast(null); assert( ha.findByRef(null) == 2 ); \n", mod);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;
		
		engine->Release();
	}

	// Success
	return fail;
}
int TestMain () {
    Test1(); // requires malloc initialization so should be first
    Test2();
    TestKeyDtor();
    return Harness::Done;
}
Example #8
0
bool Test()
{
	bool fail = false;

	if( !fail ) fail = Test2();

	int r;

 	asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);

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

	RegisterScriptString_Generic(engine);

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

	// Register an interface from the application
	r = engine->RegisterInterface("appintf"); assert( r >= 0 );
	r = engine->RegisterInterfaceMethod("appintf", "void test()"); assert( r >= 0 );

	// Test working example
	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;

	// Test calling the interface method from the application
	asIObjectType *type = engine->GetModule(0)->GetObjectTypeByName("myclass");
	asIScriptObject *obj = (asIScriptObject*)engine->CreateScriptObject(type);

	int intfTypeId = engine->GetModule(0)->GetTypeIdByDecl("myintf");
	type = engine->GetObjectTypeById(intfTypeId);
	asIScriptFunction *func = type->GetMethodByDecl("void test()");
	asIScriptContext *ctx = engine->CreateContext();
	r = ctx->Prepare(func);
	if( r < 0 ) TEST_FAILED;
	ctx->SetObject(obj);
	ctx->Execute();
	if( r != asEXECUTION_FINISHED )
		TEST_FAILED;

	intfTypeId = engine->GetTypeIdByDecl("appintf");
	type = engine->GetObjectTypeById(intfTypeId);
	func = type->GetMethodByDecl("void test()");

	r = ctx->Prepare(func);
	if( r < 0 ) TEST_FAILED;
	ctx->SetObject(obj);
	ctx->Execute();
	if( r != asEXECUTION_FINISHED )
		TEST_FAILED;

	if( ctx ) ctx->Release();
	if( obj ) obj->Release();

	// Test class that don't implement all functions of the interface.
	// Test instanciating an interface. Shouldn't work.
	// Test that classes don't implement the same interface twice
	// Try copying an interface variable to another. Shouldn't work.
	// Test implicit conversion from class to interface that is not being implemented. Should give compiler error
	// Test implicit conversion from interface to class. Should give compiler error.
	engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL);
	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection(TESTNAME, script2, strlen(script2), 0);
	r = mod->Build();
	if( r >= 0 ) TEST_FAILED;
	if( bout.buffer != "TestInterface (5, 7) : Error   : Missing implementation of 'void intf::test()'\n"
					   "TestInterface (9, 1) : Info    : Compiling void test(intf&inout)\n"
					   "TestInterface (11, 9) : Error   : Interface 'intf' cannot be instantiated\n"
					   "TestInterface (13, 6) : Error   : No appropriate opAssign method found in 'intf' for value assignment\n"
					   "TestInterface (15, 16) : Error   : Can't implicitly convert from 'myclass&' to 'nointf@&'.\n"
					   "TestInterface (16, 16) : Error   : Can't implicitly convert from 'intf@&' to 'myclass@&'.\n" )
	{
		PRINTF("%s", bout.buffer.c_str());
		TEST_FAILED;
	}

	engine->Release();

	// Test cast for both temporary handle and non-temporary handle
	{
		const char *script = 
			"interface ScriptLogic {} \n"
			"class PlayerLogic : ScriptLogic {} \n"
			"ScriptLogic @getScriptObject() { return PlayerLogic(); } \n";

		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
		RegisterStdString(engine);
		mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
		mod->AddScriptSection(TESTNAME, script);
		r = mod->Build();
		if( r < 0 ) TEST_FAILED;

		// Non-temporary handle
		r = ExecuteString(engine, "ScriptLogic @c = getScriptObject(); cast<PlayerLogic>(c);", mod);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;

		// Temporary handle
		r = ExecuteString(engine, "cast<PlayerLogic>(getScriptObject());", mod);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;

		engine->Release();			
	}

	// It should be possible to inherit the implementation of an interface method
	{
		const char *script = 
			"interface I { void method(); } \n"
			"class B { void method() {} } \n"
			"class D : B, I {} \n"
			"D d; \n";

		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
		mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
		mod->AddScriptSection(TESTNAME, script);
		r = mod->Build();
		if( r < 0 ) TEST_FAILED;

		engine->Release();			
	}

	// Allow script declared interfaces to inherit from other interfaces
	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL);
		mod = engine->GetModule(0, asGM_ALWAYS_CREATE);

		const char *script = 
			"interface A { void a(); } \n"
			"interface B : A { void b(); } \n"
			"class C : B {} \n"; // Must implement both a() and b()

		bout.buffer = "";
		mod->AddScriptSection(TESTNAME, script);
		r = mod->Build();
		if( r >= 0 ) TEST_FAILED;
		if( bout.buffer != "TestInterface (3, 7) : Error   : Missing implementation of 'void B::b()'\n"
		                   "TestInterface (3, 7) : Error   : Missing implementation of 'void A::a()'\n" )
		{
			PRINTF("%s", bout.buffer.c_str());
			TEST_FAILED;
		}

		// Don't allow shared interface to implement non-shared interface
		script = 
			"interface A {} \n"
			"shared interface B : A {} \n";

		bout.buffer = "";
		mod->AddScriptSection(TESTNAME, script);
		r = mod->Build();
		if( r >= 0 ) TEST_FAILED;
		if( bout.buffer != "TestInterface (2, 22) : Error   : Shared type cannot implement non-shared interface 'A'\n" )
		{
			PRINTF("%s", bout.buffer.c_str());
			TEST_FAILED;
		}

		// Implicit casts to an inherited interface should work
		script = 
			"interface A {} \n"
			"interface B : A {} \n"
			"void func() \n"
			"{ \n"
			"  A@ a; B@ b; \n"
			"  @a = b; \n"
			"} \n";

		bout.buffer = "";
		mod->AddScriptSection(TESTNAME, script);
		r = mod->Build();
		if( r < 0 ) TEST_FAILED;
		if( bout.buffer != "" )
		{
			PRINTF("%s", bout.buffer.c_str());
			TEST_FAILED;
		}

		// Don't allow circular inheritance
		script = 
			"interface A : C {} \n"
			"interface B : A {} \n"
			"interface C : B {} \n";
		bout.buffer = "";
		mod->AddScriptSection(TESTNAME, script);
		r = mod->Build();
		if( r >= 0 ) TEST_FAILED;
		if( bout.buffer != "TestInterface (3, 15) : Error   : Can't implement itself, or another interface that implements this interface\n" )
		{
			PRINTF("%s", bout.buffer.c_str());
			TEST_FAILED;
		}

		engine->Release();
	}

	// http://www.gamedev.net/topic/638959-interface-inheritance-issue/
	{
		engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL);

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

		mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
		mod->AddScriptSection("test", 
			"shared interface ielement \n"
			"{ \n"
			"    int func1(); \n"
			"} \n"
			"shared interface iscreen : ielement \n"
			"{ \n"
			"    int func2(); \n"
			"} \n"
			"mixin class celementbase \n"
			"{ \n"
			"    int func1() { return 1; } \n"
			"} \n"
			"class cscreen : celementbase, iscreen \n"
			"{ \n"
			"    int func2() { return 2; } \n"
			"} \n"
			"void stuff( iscreen@ scr ) \n"
			"{ \n"
			"    assert( scr.func1() == 1 ); \n"
			"    assert( scr.func2() == 2 ); \n"
			"} \n");

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

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

		r = ExecuteString(engine, "cscreen s; stuff(s);", mod);
		if( r != asEXECUTION_FINISHED )
			TEST_FAILED;

		engine->Release();
	}

	// Success
	return fail;
}
Example #9
0
bool Test()
{
	bool fail = Test2();
	int r;
	COutStream out;

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

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

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

	r = ExecuteString(engine, "uint8 newmask = 0xFF, mask = 0x15; Assert( (newmask & ~mask) == 0xEA );");
	if( r != asEXECUTION_FINISHED ) TEST_FAILED;

	r = ExecuteString(engine, "uint8 newmask = 0xFF; newmask = newmask & (~mask2) & (~mask3) & (~mask5); Assert( newmask == 0xD3 );", mod);
	if( r != asEXECUTION_FINISHED ) TEST_FAILED;

	r = ExecuteString(engine, "uint8 newmask = 0XFE; Assert( (newmask & mask0) == 0 );", mod);
	if( r != asEXECUTION_FINISHED ) TEST_FAILED;

	r = ExecuteString(engine, "uint8 b = 0xFF; b &= ~mask4; BitsTest(b);", mod);
	if( r != asEXECUTION_FINISHED ) TEST_FAILED;


	engine->RegisterGlobalFunction("uint8 ReturnByte(uint8)", asFUNCTION(ReturnByte), asCALL_GENERIC);
	engine->RegisterGlobalFunction("uint16 ReturnWord(uint16)", asFUNCTION(ReturnWord), asCALL_GENERIC);
	mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
	mod->AddScriptSection("script", script2, strlen(script2));
	engine->SetEngineProperty(asEP_OPTIMIZE_BYTECODE, false);
	r = mod->Build();
	if( r < 0 ) 
		TEST_FAILED;
	r = ExecuteString(engine, "Test()", mod);
	if( r != asEXECUTION_FINISHED )
		TEST_FAILED;

	// bitwise operators should maintain signed/unsigned type of left hand operand
	CBufferedOutStream bout;
	engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL);
	r = ExecuteString(engine, "int a = 0, b = 0; bool c = (a < (b>>1));");
	if( r < 0 )
		TEST_FAILED;
	r = ExecuteString(engine, "uint a = 0, b = 0; bool c = (a < (b>>1));");
	if( r < 0 )
		TEST_FAILED;
	if( bout.buffer != "" )
	{
		printf("%s", bout.buffer.c_str());
		TEST_FAILED;
	}
	
	engine->Release();

	// Success
	return fail;
}
Example #10
0
/*----------------------------------------------------------------------
|   main
+---------------------------------------------------------------------*/
int
main(int argc, char** argv)
{
    NPT_COMPILER_UNUSED(argc);

    NPT_HttpRequestHandler *handler, *custom_handler;
    NPT_Reference<NPT_DataBuffer> buffer;
    NPT_Size size;
    bool result;
    PLT_RingBufferStreamReference ringbuffer_stream(new PLT_RingBufferStream());

    /* parse command line */
    ParseCommandLine(argv);

    /* create http server */
    PLT_HttpServer http_server(Options.port?Options.port:80);
    NPT_String url = "http://127.0.0.1:" + NPT_String::FromInteger(http_server.GetPort());
    NPT_String custom_url = url;

    if (!Options.path.IsEmpty()) {
        /* extract folder path */
        int index1 = Options.path.ReverseFind('\\');
        int index2 = Options.path.ReverseFind('/');
        if (index1 <= 0 && index2 <=0) {
            fprintf(stderr, "ERROR: invalid path\n");
            exit(1);
        }

        NPT_FileInfo info;
        NPT_CHECK_SEVERE(NPT_File::GetInfo(Options.path, &info));

        /* add file request handler */
        handler = new NPT_HttpFileRequestHandler(
            Options.path.Left(index1>index2?index1:index2), 
            "/");
        http_server.AddRequestHandler(handler, "/", true);

        /* build url*/
        url += "/" + Options.path.SubString((index1>index2?index1:index2)+1);
    } else {
        /* create random data */
        buffer = new NPT_DataBuffer(32768);
        buffer->SetDataSize(32768);

        /* add static handler */
        handler = new NPT_HttpStaticRequestHandler(buffer->GetData(),
            buffer->GetDataSize(),
            "text/xml");
        http_server.AddRequestHandler(handler, "/test");

        /* build url*/
        url += "/test";
    }

    /* add custom handler */
    NPT_InputStreamReference stream(ringbuffer_stream);
    custom_handler = new PLT_HttpCustomRequestHandler(stream,
        "text/xml");
    http_server.AddRequestHandler(custom_handler, "/custom");
    custom_url += "/custom";

    /* start server */
    NPT_CHECK_SEVERE(http_server.Start());

    /* a task manager for the tests downloader */
    PLT_TaskManager task_manager;

    /* small delay to let the server start */
    NPT_System::Sleep(NPT_TimeInterval(1, 0));
    
    /* execute tests */
    result = Test1(&task_manager, url.GetChars(), size);
    if (!result) return -1;

    result = Test2(&task_manager, url.GetChars(), size);
    if (!result) return -1;

    result = Test3(&task_manager, custom_url.GetChars(), ringbuffer_stream, size);
    if (!result) return -1;

    NPT_System::Sleep(NPT_TimeInterval(1, 0));

    http_server.Stop();
    delete handler;
    delete custom_handler;
    return 0;
}
Example #11
0
bool TestSdp()
{
	if( Test( 
		"v=0\r\n"
		"o=jdoe 2890844526 2890842807 IN IP4 10.47.16.5\r\n"
		"s=SDP Seminar\r\n"
		"i=A Seminar on the session description protocol\r\n"
		"u=http://www.example.com/seminars/sdp.pdf\r\n"
		"[email protected] (Jane Doe)\r\n"
		"c=IN IP4 224.2.17.12/127\r\n"
		"t=2873397496 2873404696\r\n"
		"a=recvonly\r\n"
		"m=audio 49170 RTP/AVP 0\r\n"
		"m=video 51372 RTP/AVP 99\r\n"
		"a=rtpmap:99 h263-1998/90000\r\n",
		"v=0\r\n"
		"o=jdoe 2890844526 2890842807 IN IP4 10.47.16.5\r\n"
		"s=SDP Seminar\r\n"
		"i=A Seminar on the session description protocol\r\n"
		"u=http://www.example.com/seminars/sdp.pdf\r\n"
		"[email protected] (Jane Doe)\r\n"
		"c=IN IP4 224.2.17.12/127\r\n"
		"t=2873397496 2873404696\r\n"
		"a=recvonly\r\n"
		"m=audio 49170 RTP/AVP 0\r\n"
		"m=video 51372 RTP/AVP 99\r\n"
		"a=rtpmap:99 h263-1998/90000\r\n" ) == false ) return false;

	if( Test( 
		"v=0\r\n"
		"o=jdoe 2890844526 2890842807 IN IP4 10.47.16.5\r\n"
		"s=SDP Seminar\r\n"
		"i=A Seminar on the session description protocol\r\n"
		"u=http://www.example.com/seminars/sdp.pdf\r\n"
		"[email protected] (Jane Doe)\r\n"
		"c=IN IP4 224.2.17.12/127\r\n"
		"b=X-YZ:128\r\n",
		"v=0\r\n"
		"o=jdoe 2890844526 2890842807 IN IP4 10.47.16.5\r\n"
		"s=SDP Seminar\r\n"
		"i=A Seminar on the session description protocol\r\n"
		"u=http://www.example.com/seminars/sdp.pdf\r\n"
		"[email protected] (Jane Doe)\r\n"
		"c=IN IP4 224.2.17.12/127\r\n"
		"b=X-YZ:128\r\n" ) == false ) return false;

	if( Test( 
		"v=0\r\n"
		"o=CiscoSystemsSIP-GW-UserAgent 7393 3874 IN IP4 192.10.228.41\r\n"
		"s=SIP Call\r\n"
		"c=IN IP4 192.10.228.41\r\n"
		"t=0 0\r\n"
		"m=audio 24864 RTP/AVP 0 101\r\n"
		"c=IN IP4 192.10.228.41\r\n"
		"a=rtpmap:0 PCMU/8000\r\n"
		"a=rtpmap:101 telephone-event/8000\r\n"
		"a=fmtp:101 0-16\r\n"
		"a=ptime:20\r\n"
		"\r\n"
		"--uniqueBoundary\r\n"
		"Content-Type: application/gtd\r\n"
		"Content-Disposition: signal;handling=optional\r\n"
		"\r\n"
		"IAM,\r\n"
		"PRN,isdn*,,NET5*,\r\n"
		"USI,rate,c,s,c,1\r\n"
		"USI,lay1,alaw\r\n"
		"TMR,00\r\n"
		"CPN,00,,1,2936\r\n"
		"CGN,04,,1,y,4,01075066103\r\n"
		"CPC,09\r\n"
		"FCI,,,,,,,y,\r\n"
		"GCI,5c2f3c7d861811e789221005ca2bd880\r\n"
		"--uniqueBoundary\r\n",
		"v=0\r\n"
		"o=CiscoSystemsSIP-GW-UserAgent 7393 3874 IN IP4 192.10.228.41\r\n"
		"s=SIP Call\r\n"
		"c=IN IP4 192.10.228.41\r\n"
		"t=0 0\r\n"
		"m=audio 24864 RTP/AVP 0 101\r\n"
		"c=IN IP4 192.10.228.41\r\n"
		"a=rtpmap:0 PCMU/8000\r\n"
		"a=rtpmap:101 telephone-event/8000\r\n"
		"a=fmtp:101 0-16\r\n"
		"a=ptime:20\r\n" ) == false ) return false;		

	Test2( "v=0\r\n"
					"o=- 3593775777 3593775777 IN IP4 192.168.184.129\r\n"
					"s=media\r\n"
					"c=IN IP4 192.168.184.129\r\n"
					"t=0 0\r\n"
					"a=X-nat:0\r\n"
					"m=audio 11263 RTP/AVP 103 102 104 117 3 0 8 9 101\r\n"
					"a=rtcp:11264 IN IP4 192.168.184.129\r\n"
					"a=rtpmap:103 speex/16000\r\n"
					"a=rtpmap:102 speex/8000\r\n"
					"a=rtpmap:104 speex/32000\r\n"
					"a=rtpmap:117 iLBC/8000\r\n"
					"a=fmtp:117 mode=30\r\n"
					"a=rtpmap:3 GSM/8000\r\n"
					"a=rtpmap:0 PCMU/8000\r\n"
					"a=rtpmap:8 PCMA/8000\r\n"
					"a=rtpmap:9 G722/8000\r\n"
					"a=sendrecv\r\n"
					"a=rtpmap:101 telephone-event/8000\r\n"
					"a=fmtp:101 0-15\r\n" );

	Test3( "v=0\r\n"
					"o=- 3593775777 3593775777 IN IP4 192.168.184.129\r\n"
					"s=media\r\n"
					"c=IN IP4 192.168.184.129\r\n"
					"t=0 0\r\n"
					"a=X-nat:0\r\n"
					"m=video 11263 RTP/AVP 97\r\n"
					"a=rtpmap:97 H264/90000\r\n"
					"a=fmtp:97 profile-level-id=428016;max-br=5000;max-mbps=490000;max-fs=9000;max-smbps=490000;max-fps=6000;max-rcmd-nalu-size=3456000\r\n" );

	CSdpAttributeCrypto clsCrypto;
	const char * pszCrypto = "1 AES_CM_128_HMAC_SHA1_80 inline:7s65riA38OlE4U5OepU5zgaoMvzOL19nSQqeursI";

	if( clsCrypto.Parse( pszCrypto, (int)strlen(pszCrypto) ) == -1 )
	{
		printf( "crypto[%s] parser error\n", pszCrypto );
		return false;
	}

	if( strcmp( clsCrypto.m_strTag.c_str(), "1" ) || 
			strcmp( clsCrypto.m_strCryptoSuite.c_str(), "AES_CM_128_HMAC_SHA1_80" ) ||
			strcmp( clsCrypto.m_strKey.c_str(), "7s65riA38OlE4U5OepU5zgaoMvzOL19nSQqeursI" ) )
	{
		printf( "crypto[%s] parser result error\n", pszCrypto );
		return false;
	}

	if( TestAudioMedia( "v=0\r\n"
		"o=jdoe 2890844526 2890842807 IN IP4 10.47.16.5\r\n"
		"s=SDP Seminar\r\n"
		"i=A Seminar on the session description protocol\r\n"
		"u=http://www.example.com/seminars/sdp.pdf\r\n"
		"[email protected] (Jane Doe)\r\n"
		"c=IN IP4 224.2.17.12/127\r\n"
		"t=2873397496 2873404696\r\n"
		"a=recvonly\r\n"
		"m=audio 49170 RTP/AVP 0\r\n"
		"m=video 51372 RTP/AVP 99\r\n"
		"a=rtpmap:99 h263-1998/90000\r\n" ) == false ) return false;

	if( Test4( "v=0\r\n"
					"o=- 3593775777 3593775777 IN IP4 192.168.184.129\r\n"
					"s=media\r\n"
					"c=IN IP4 192.168.184.129\r\n"
					"t=0 0\r\n"
					"a=X-nat:0\r\n"
					"m=audio 11263 RTP/AVP 103 102 104 117 3 0 8 9 101\r\n"
					"a=rtcp:11264 IN IP4 192.168.184.129\r\n"
					"a=rtpmap:103 speex/16000\r\n"
					"a=rtpmap:102 speex/8000\r\n"
					"a=rtpmap:104 speex/32000\r\n"
					"a=rtpmap:117 iLBC/8000\r\n"
					"a=fmtp:117 mode=30\r\n"
					"a=rtpmap:3 GSM/8000\r\n"
					"a=rtpmap:0 PCMU/8000\r\n"
					"a=rtpmap:8 PCMA/8000\r\n"
					"a=rtpmap:9 G722/8000\r\n"
					"a=sendrecv\r\n"
					"a=rtpmap:101 telephone-event/8000\r\n"
					"a=fmtp:101 0-15\r\n"
				, "v=0\r\n"
					"o=- 3593775777 3593775777 IN IP4 192.168.184.129\r\n"
					"s=media\r\n"
					"c=IN IP4 192.168.184.129\r\n"
					"t=0 0\r\n"
					"a=X-nat:0\r\n"
					"m=audio 11263 RTP/AVP 8 101\r\n"
					"a=rtcp:11264 IN IP4 192.168.184.129\r\n"
					"a=rtpmap:8 PCMA/8000\r\n"
					"a=sendrecv\r\n"
					"a=rtpmap:101 telephone-event/8000\r\n"
					"a=fmtp:101 0-15\r\n") == false ) return false;

	if( TestTopCodec( "v=0\r\n"
					"o=- 3593775777 3593775777 IN IP4 192.168.184.129\r\n"
					"s=media\r\n"
					"c=IN IP4 192.168.184.129\r\n"
					"t=0 0\r\n"
					"a=X-nat:0\r\n"
					"m=audio 11263 RTP/AVP 103 102 104 117 3 0 8 9 101\r\n"
					"a=rtcp:11264 IN IP4 192.168.184.129\r\n"
					"a=rtpmap:103 speex/16000\r\n"
					"a=rtpmap:102 speex/8000\r\n"
					"a=rtpmap:104 speex/32000\r\n"
					"a=rtpmap:117 iLBC/8000\r\n"
					"a=fmtp:117 mode=30\r\n"
					"a=rtpmap:3 GSM/8000\r\n"
					"a=rtpmap:0 PCMU/8000\r\n"
					"a=rtpmap:8 PCMA/8000\r\n"
					"a=rtpmap:9 G722/8000\r\n"
					"a=sendrecv\r\n"
					"a=rtpmap:101 telephone-event/8000\r\n"
					"a=fmtp:101 0-15\r\n"
				, "v=0\r\n"
					"o=- 3593775777 3593775777 IN IP4 192.168.184.129\r\n"
					"s=media\r\n"
					"c=IN IP4 192.168.184.129\r\n"
					"t=0 0\r\n"
					"a=X-nat:0\r\n"
					"m=audio 11263 RTP/AVP 8 103 102 104 117 3 0 9 101\r\n"
					"a=rtcp:11264 IN IP4 192.168.184.129\r\n"
					"a=rtpmap:8 PCMA/8000\r\n"
					"a=rtpmap:103 speex/16000\r\n"
					"a=rtpmap:102 speex/8000\r\n"
					"a=rtpmap:104 speex/32000\r\n"
					"a=rtpmap:117 iLBC/8000\r\n"
					"a=fmtp:117 mode=30\r\n"
					"a=rtpmap:3 GSM/8000\r\n"
					"a=rtpmap:0 PCMU/8000\r\n"
					"a=rtpmap:9 G722/8000\r\n"
					"a=sendrecv\r\n"
					"a=rtpmap:101 telephone-event/8000\r\n"
					"a=fmtp:101 0-15\r\n", 8 ) == false ) return false;

	if( TestTopCodec( "v=0\r\n"
					"o=- 3593775777 3593775777 IN IP4 192.168.184.129\r\n"
					"s=media\r\n"
					"c=IN IP4 192.168.184.129\r\n"
					"t=0 0\r\n"
					"a=X-nat:0\r\n"
					"m=audio 11263 RTP/AVP 103 102 104 117 3 0 8 9 101\r\n"
					"a=rtcp:11264 IN IP4 192.168.184.129\r\n"
					"a=rtpmap:103 speex/16000\r\n"
					"a=rtpmap:102 speex/8000\r\n"
					"a=rtpmap:104 speex/32000\r\n"
					"a=rtpmap:117 iLBC/8000\r\n"
					"a=fmtp:117 mode=30\r\n"
					"a=rtpmap:3 GSM/8000\r\n"
					"a=rtpmap:0 PCMU/8000\r\n"
					"a=rtpmap:8 PCMA/8000\r\n"
					"a=rtpmap:9 G722/8000\r\n"
					"a=sendrecv\r\n"
					"a=rtpmap:101 telephone-event/8000\r\n"
					"a=fmtp:101 0-15\r\n"
				, "v=0\r\n"
					"o=- 3593775777 3593775777 IN IP4 192.168.184.129\r\n"
					"s=media\r\n"
					"c=IN IP4 192.168.184.129\r\n"
					"t=0 0\r\n"
					"a=X-nat:0\r\n"
					"m=audio 11263 RTP/AVP 117 103 102 104 3 0 8 9 101\r\n"
					"a=rtcp:11264 IN IP4 192.168.184.129\r\n"
					"a=rtpmap:117 iLBC/8000\r\n"
					"a=fmtp:117 mode=30\r\n"
					"a=rtpmap:103 speex/16000\r\n"
					"a=rtpmap:102 speex/8000\r\n"
					"a=rtpmap:104 speex/32000\r\n"
					"a=rtpmap:3 GSM/8000\r\n"
					"a=rtpmap:0 PCMU/8000\r\n"
					"a=rtpmap:8 PCMA/8000\r\n"
					"a=rtpmap:9 G722/8000\r\n"
					"a=sendrecv\r\n"
					"a=rtpmap:101 telephone-event/8000\r\n"
					"a=fmtp:101 0-15\r\n", 117 ) == false ) return false;

	if( TestTopCodec( "v=0\r\n"
					"o=- 3593775777 3593775777 IN IP4 192.168.184.129\r\n"
					"s=media\r\n"
					"c=IN IP4 192.168.184.129\r\n"
					"t=0 0\r\n"
					"a=X-nat:0\r\n"
					"m=audio 11263 RTP/AVP 8 101\r\n"
					"a=rtpmap:8 PCMA/8000\r\n"
					"a=sendrecv\r\n"
					"a=rtpmap:101 telephone-event/8000\r\n"
					"a=fmtp:101 0-15\r\n"
				, "v=0\r\n"
					"o=- 3593775777 3593775777 IN IP4 192.168.184.129\r\n"
					"s=media\r\n"
					"c=IN IP4 192.168.184.129\r\n"
					"t=0 0\r\n"
					"a=X-nat:0\r\n"
					"m=audio 11263 RTP/AVP 8 101\r\n"
					"a=rtpmap:8 PCMA/8000\r\n"
					"a=sendrecv\r\n"
					"a=rtpmap:101 telephone-event/8000\r\n"
					"a=fmtp:101 0-15\r\n", 8 ) == false ) return false;

	if( TestTopCodec( "v=0\r\n"
					"o=- 3593775777 3593775777 IN IP4 192.168.184.129\r\n"
					"s=media\r\n"
					"c=IN IP4 192.168.184.129\r\n"
					"t=0 0\r\n"
					"a=X-nat:0\r\n"
					"m=audio 11263 RTP/AVP 103 102 104 117 3 0 8 9 101\r\n"
					"a=rtcp:11264 IN IP4 192.168.184.129\r\n"
					"a=rtpmap:103 speex/16000\r\n"
					"a=rtpmap:102 speex/8000\r\n"
					"a=rtpmap:104 speex/32000\r\n"
					"a=rtpmap:117 iLBC/8000\r\n"
					"a=fmtp:117 mode=30\r\n"
					"a=rtpmap:3 GSM/8000\r\n"
					"a=rtpmap:0 PCMU/8000\r\n"
					"a=rtpmap:8 PCMA/8000\r\n"
					"a=rtpmap:9 G722/8000\r\n"
					"a=sendrecv\r\n"
					"a=rtpmap:101 telephone-event/8000\r\n"
					"a=fmtp:101 0-15\r\n"
				, "v=0\r\n"
					"o=- 3593775777 3593775777 IN IP4 192.168.184.129\r\n"
					"s=media\r\n"
					"c=IN IP4 192.168.184.129\r\n"
					"t=0 0\r\n"
					"a=X-nat:0\r\n"
					"m=audio 11263 RTP/AVP 103 102 104 117 3 0 8 9 101\r\n"
					"a=rtcp:11264 IN IP4 192.168.184.129\r\n"
					"a=rtpmap:103 speex/16000\r\n"
					"a=rtpmap:102 speex/8000\r\n"
					"a=rtpmap:104 speex/32000\r\n"
					"a=rtpmap:117 iLBC/8000\r\n"
					"a=fmtp:117 mode=30\r\n"
					"a=rtpmap:3 GSM/8000\r\n"
					"a=rtpmap:0 PCMU/8000\r\n"
					"a=rtpmap:8 PCMA/8000\r\n"
					"a=rtpmap:9 G722/8000\r\n"
					"a=sendrecv\r\n"
					"a=rtpmap:101 telephone-event/8000\r\n"
					"a=fmtp:101 0-15\r\n", 300 ) == false ) return false;

	return true;
}
Example #12
0
  // CHECK: @_ZN9BaseClass2t1E = constant {{.*}} { i32 3, i8 1, i8 1, i8 1, double 4.000000e+00, i8 1, i32 5 }, align 8
  extern constexpr Test1 t1 = Test1();

  struct DN : D, N {};
  struct DND : DN, X<D,0> {};
  struct DNN : DN, X<N,0> {};
  // CHECK: @_ZN9BaseClass3dndE = constant {{.*}} { double 4.000000e+00, i32 3, double 4.000000e+00 }
  extern constexpr DND dnd = DND();
  // Note, N subobject is laid out in DN subobject's tail padding.
  // CHECK: @_ZN9BaseClass3dnnE = constant {{.*}} { double 4.000000e+00, i32 3, i32 3 }
  extern constexpr DNN dnn = DNN();

  struct E {};
  struct Test2 : X<E,0>, X<E,1>, X<E,2>, X<E,3> {};
  // CHECK: @_ZN9BaseClass2t2E = constant {{.*}} undef
  extern constexpr Test2 t2 = Test2();

  struct __attribute((packed)) PackedD { double y = 2; };
  struct Test3 : C, PackedD { constexpr Test3() {} };
  // CHECK: @_ZN9BaseClass2t3E = constant <{ i8, double }> <{ i8 1, double 2.000000e+00 }>
  extern constexpr Test3 t3 = Test3();
}

namespace Array {
  // CHECK: @_ZN5Array3arrE = constant [2 x i32] [i32 4, i32 0]
  extern constexpr int arr[2] = { 4 };

  // CHECK: @_ZN5Array1cE = constant [6 x [4 x i8]] [{{.*}} c"foo\00", [4 x i8] c"a\00\00\00", [4 x i8] c"bar\00", [4 x i8] c"xyz\00", [4 x i8] c"b\00\00\00", [4 x i8] c"123\00"]
  extern constexpr char c[6][4] = { "foo", "a", { "bar" }, { 'x', 'y', 'z' }, { "b" }, '1', '2', '3' };

  // CHECK: @_ZN5Array2ucE = constant [4 x i8] c"foo\00"
Example #13
0
bool Test()
{
	if( strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY") )
	{
		printf("%s: Skipped due to AS_MAX_PORTABILITY\n", "TestInheritance");
		return false;
	}

	bool fail = false;
	int r;

	asIScriptModule *mod = 0;
	COutStream out;
 	asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
	engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL);
	RegisterStdString(engine);
	engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);
	engine->RegisterGlobalFunction("void print(const string &in)", asFUNCTION(print), asCALL_CDECL);

	const char *script =
		"bool baseDestructorCalled = false;               \n"
		"bool baseConstructorCalled = false;              \n"
		"bool baseFloatConstructorCalled = false;         \n"
		"class Base : Intf                                \n"
		"{                                                \n"
		"  int a;                                         \n"
		"  void f1() { a = 1; }                           \n"
		"  void f2() { a = 0; }                           \n"
		"  void f3() { a = 3; }                           \n"
		"  Base() { baseConstructorCalled = true; }       \n"
		"  Base(float) { baseFloatConstructorCalled = true; } \n"
		"  ~Base() { baseDestructorCalled = true; }       \n"
		"}                                                \n"
		"bool derivedDestructorCalled = false;            \n"
		"bool derivedConstructorCalled = false;           \n"
		"class Derived : Base                             \n"
		"{                                                \n"
		   // overload f2()
		"  void f2() { a = 2; }                           \n"
		   // overload f3()
		"  void f3() { a = 2; }                           \n"
		"  void func()                                    \n"
		"  {                                              \n"
		     // call Base::f1()
		"    f1();                                        \n"
		"    assert(a == 1);                              \n"
		     // call Derived::f2()
		"    f2();                                           \n"
		"    assert(a == 2);                                 \n"
		     // call Base::f3() 
		"    Base::f3();                                     \n"
		"    assert(a == 3);                                 \n"
		"  }                                                 \n"
		"  Derived() {} \n"
		"  Derived(int) { derivedConstructorCalled = true; } \n"
		"  ~Derived() { derivedDestructorCalled = true; }    \n"
		"}                                                \n"
		"void foo( Base &in a )                           \n"
		"{                                                \n"
		"  assert( cast<Derived>(a) is null );            \n"
		"}                                                \n"
		// Must be possible to call the default constructor, even if not declared
		"class DerivedGC : BaseGC { DerivedGC() { super(); } }  \n"
		"class BaseGC { BaseGC @b; }                      \n"
		"class DerivedS : Base                            \n"
		"{                                                \n"
		"  DerivedS(float)                                \n"
		"  {                                              \n"
	  	     // Call Base::Base(float)
		"    if( true )                                   \n"
		"      super(1.4f);                               \n"
		"    else                                         \n"
		"      super();                                   \n"
		"  }                                              \n"
		"}                                                \n"
		// Must handle inheritance where the classes have been declared out of order
		"void func()                                      \n"
		"{                                                \n"
		"   Intf@ a = C();                                \n"
		"}                                                \n"
		"class C : B {}                                   \n"
		"interface Intf {}                                \n"
		"class B : Intf {}                                \n"
		// Several levels of inheritance
		"class C0                                         \n"
		"{                                                \n"
		"  void Dummy() {}                                \n"
		"}                                                \n"
		"class C1 : C0                                    \n"
		"{                                                \n"
		"  void Fun() { print('C1:Fun'); }                \n"
		"}                                                \n"
		"class C2 : C1                                    \n"
		"{                                                \n"
		"  void Fun() { print('C2:Fun'); }                \n"
		"}                                                \n"
		"class C3 : C2                                    \n"
		"{                                                \n"
		"  void Call() { Fun(); }                         \n"
		"}                                                \n";


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

	if( TestModule(0, engine) )
	{
		TEST_FAILED;
	}

	// Must make sure that the inheritance path is stored/restored with the saved byte code
	{ 
		CBytecodeStream stream(__FILE__"1");
		r = mod->SaveByteCode(&stream);
		if( r < 0 )
		{
			TEST_FAILED;
		}

		asIScriptModule *mod2 = engine->GetModule("2", asGM_ALWAYS_CREATE);
		r = mod2->LoadByteCode(&stream);
		if( r < 0 )
		{
			TEST_FAILED;
		}

		// Both modules should have the same number of functions
		if( mod->GetFunctionCount() != mod2->GetFunctionCount() )
		{
			TEST_FAILED;

			asUINT n;
			printf("First module's functions\n");
			for( n = 0; n < (asUINT)mod->GetFunctionCount(); n++ )
			{
				asIScriptFunction *f = mod->GetFunctionByIndex(n);
				printf("%s\n", f->GetDeclaration());
			}
			printf("\nSecond module's functions\n");
			for( n = 0; n < (asUINT)mod2->GetFunctionCount(); n++ )
			{
				asIScriptFunction *f = mod2->GetFunctionByIndex(n);
				printf("%s\n", f->GetDeclaration());
			}
		}

		if( TestModule("2", engine) )
		{
			TEST_FAILED;
		}

		engine->DiscardModule("2");
	}

	engine->Release();

	// Test final and override
	{
		CBufferedOutStream bout;
		asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
		engine->SetMessageCallback(asMETHOD(CBufferedOutStream, Callback), &bout, asCALL_THISCALL);

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

		mod->AddScriptSection("test", 
			"final class CFin1 {} \n" // Don't allow inheritance
			"shared final class CFin2 {} \n" // -"-
			"class CBase \n"
			"{ \n"
			"  void finalFunc() final {} \n" // don't allow override this func
			"  void overrideFunc() {} \n" 
			"} \n"
			"class CD1 : CFin1 {} \n" // Shouldn't work
			"class CD2 : CBase \n"
			"{ \n"
			"  void finalFunc() {} \n" // shouldn't work
			"  void overrideFunc(int) override {} \n" // must override
			"} \n");

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

		if( bout.buffer != "test (8, 13) : Error   : Can't inherit from class 'CFin1' marked as final\n"
						   "test (9, 7) : Error   : Method 'void CBase::finalFunc()' declared as final and cannot be overridden\n"
						   "test (9, 7) : Error   : Method 'void CD2::overrideFunc(int)' marked as override but does not replace any base class or interface method\n" )
		{
			printf("%s", bout.buffer.c_str());
			TEST_FAILED;
		}

		engine->Release();
	}

	fail = Test2() || fail;

	// Success
	return fail;
}