Beispiel #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;
}
Beispiel #2
0
bool Test()
{
	bool fail = false;
	int r;

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

	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(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";

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

	if( TestModule(0, engine) )
	{
		fail = true;
	}

	// 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 )
		{
			fail = true;
		}

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

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

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

		if( TestModule("2", engine) )
		{
			fail = true;
		}

		engine->DiscardModule("2");
	}

	engine->Release();

	fail = Test2() || fail;

	// Success
	return fail;
}
Beispiel #3
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;
}