Unittests and demos update
-fixed bug in EntityManager -added better support for non-betterC unittests -added many new unittests -slightly improved JUnit xml output -fixed WASM compile script -added new textures -fixed model texture coordinaes in demos -some minor bug fixes in demo TODO: demos cpu usage in non-betterC mode
This commit is contained in:
parent
46530ff45b
commit
84e04191c8
13 changed files with 453 additions and 51 deletions
389
tests/basic.d
389
tests/basic.d
|
|
@ -1,7 +1,9 @@
|
|||
module tests.basic;
|
||||
|
||||
import ecs.manager;
|
||||
import ecs.core;
|
||||
import ecs.manager;
|
||||
import ecs.system;
|
||||
import ecs.attributes;
|
||||
|
||||
struct CInt
|
||||
{
|
||||
|
|
@ -57,15 +59,59 @@ struct CUnregistered
|
|||
short value = 12;
|
||||
}
|
||||
|
||||
struct LongAddSystem
|
||||
{
|
||||
mixin ECS.System;
|
||||
|
||||
struct EntitiesData
|
||||
{
|
||||
int length;
|
||||
|
||||
CLong[] long_;
|
||||
}
|
||||
|
||||
void onUpdate(EntitiesData data)
|
||||
{
|
||||
updates_count++;
|
||||
foreach(i;0..data.length)
|
||||
{
|
||||
data.long_[i] += 1;
|
||||
}
|
||||
}
|
||||
|
||||
int updates_count = 0;
|
||||
}
|
||||
|
||||
struct EmptySystem
|
||||
{
|
||||
mixin ECS.System!16;
|
||||
|
||||
struct EntitiesData
|
||||
{
|
||||
int thread_id;
|
||||
}
|
||||
|
||||
void onUpdate(EntitiesData data)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
}
|
||||
|
||||
void beforeEveryTest()
|
||||
{
|
||||
gEM.initialize(1);
|
||||
|
||||
gEM.beginRegister();
|
||||
|
||||
gEM.registerComponent!CInt;
|
||||
gEM.registerComponent!CFloat;
|
||||
gEM.registerComponent!CDouble;
|
||||
gEM.registerComponent!CLong;
|
||||
gEM.registerComponent!CShort;
|
||||
|
||||
gEM.endRegister();
|
||||
}
|
||||
|
||||
void afterEveryTest()
|
||||
|
|
@ -183,3 +229,344 @@ unittest
|
|||
gEM.freeTemplate(tmpl_6);
|
||||
gEM.freeTemplate(tmpl_7);
|
||||
}
|
||||
|
||||
@("UnsortedComponentIDs")
|
||||
unittest
|
||||
{
|
||||
//basic template allocation
|
||||
ushort[2] ids = [CFloat.component_id, CInt.component_id];
|
||||
ushort[2] ids2 = [CInt.component_id, CFloat.component_id];
|
||||
EntityTemplate* tmpl_ = gEM.allocateTemplate(ids);
|
||||
EntityTemplate* tmpl_2 = gEM.allocateTemplate(ids2);
|
||||
assert(tmpl_.info.components.length == 2);
|
||||
assert(tmpl_.getComponent!CInt);
|
||||
assert(tmpl_.getComponent!CFloat);
|
||||
assert(*tmpl_.getComponent!CInt == 1);
|
||||
assert(*tmpl_.getComponent!CFloat == 2.0);
|
||||
assert(tmpl_.info == tmpl_2.info);
|
||||
}
|
||||
|
||||
@("MultiRegister")
|
||||
unittest
|
||||
{
|
||||
gEM.beginRegister();
|
||||
|
||||
gEM.endRegister();
|
||||
|
||||
gEM.beginRegister();
|
||||
|
||||
gEM.registerComponent!CLong;
|
||||
gEM.registerComponent!CShort;
|
||||
|
||||
gEM.endRegister();
|
||||
}
|
||||
|
||||
@("EmptySystem")
|
||||
unittest
|
||||
{
|
||||
gEM.beginRegister();
|
||||
|
||||
gEM.registerSystem!EmptySystem(0);
|
||||
|
||||
gEM.endRegister();
|
||||
|
||||
EmptySystem* system = gEM.getSystem!EmptySystem;
|
||||
assert(system !is null);
|
||||
assert(system.count == 0);
|
||||
|
||||
System* ecs_system = gEM.getSystem(EmptySystem.system_id);
|
||||
assert(ecs_system !is null);
|
||||
assert(ecs_system.id == EmptySystem.system_id);
|
||||
assert(ecs_system.name == "EmptySystem");
|
||||
|
||||
gEM.begin();
|
||||
|
||||
gEM.update();
|
||||
|
||||
gEM.end();
|
||||
|
||||
assert(system.count == 1);
|
||||
}
|
||||
|
||||
@("SystemCallbacks")
|
||||
unittest
|
||||
{
|
||||
struct TestSystem
|
||||
{
|
||||
mixin ECS.System!16;
|
||||
|
||||
mixin ECS.ExcludedComponents!(CShort);
|
||||
|
||||
struct EntitiesData
|
||||
{
|
||||
int length;
|
||||
CLong[] long_;
|
||||
@optional CInt[] int_;
|
||||
}
|
||||
|
||||
void onCreate()
|
||||
{
|
||||
create++;
|
||||
}
|
||||
|
||||
void onDestroy()
|
||||
{
|
||||
(*destroy)++;
|
||||
}
|
||||
|
||||
void onEnable()
|
||||
{
|
||||
enable++;
|
||||
}
|
||||
|
||||
void onDisable()
|
||||
{
|
||||
disable++;
|
||||
}
|
||||
|
||||
bool onBegin()
|
||||
{
|
||||
begin++;
|
||||
update = 0;
|
||||
return pass;
|
||||
}
|
||||
|
||||
void onEnd()
|
||||
{
|
||||
end++;
|
||||
}
|
||||
|
||||
void onUpdate(EntitiesData data)
|
||||
{
|
||||
update++;
|
||||
}
|
||||
|
||||
int create = 0;
|
||||
int* destroy;
|
||||
int update = 0;
|
||||
int begin = 0;
|
||||
int end = 0;
|
||||
int enable = 0;
|
||||
int disable = 0;
|
||||
bool pass = true;
|
||||
}
|
||||
|
||||
gEM.beginRegister();
|
||||
|
||||
gEM.registerSystem!TestSystem(0);
|
||||
|
||||
gEM.endRegister();
|
||||
|
||||
TestSystem* system = gEM.getSystem!TestSystem;
|
||||
int destroy = 0;
|
||||
system.destroy = &destroy;
|
||||
|
||||
gEM.beginRegister();
|
||||
|
||||
gEM.registerSystem!TestSystem(0);
|
||||
|
||||
gEM.endRegister();
|
||||
|
||||
system = gEM.getSystem!TestSystem;
|
||||
system.destroy = &destroy;
|
||||
assert(system !is null);
|
||||
assert(system.create == 1);
|
||||
assert(system.begin == 0);
|
||||
assert(system.end == 0);
|
||||
assert(system.enable == 1);
|
||||
assert(system.disable == 0);
|
||||
//FIXME: currently destroy is only called with Manager.destory which is bug, but there is no workaround for this by now
|
||||
//assert(destroy == 1);
|
||||
|
||||
System* ecs_system = gEM.getSystem(system.system_id);
|
||||
|
||||
ecs_system.enable();
|
||||
assert(system.enable == 1);
|
||||
ecs_system.disable();
|
||||
ecs_system.disable();
|
||||
ecs_system.enable();
|
||||
assert(system.enable == 2);
|
||||
assert(system.disable == 1);
|
||||
|
||||
|
||||
ushort[2] ids = [CLong.component_id,CFloat.component_id];
|
||||
EntityTemplate* tmpl = gEM.allocateTemplate(ids);
|
||||
scope (exit) gEM.freeTemplate(tmpl);
|
||||
gEM.addEntity(tmpl);
|
||||
|
||||
gEM.begin();
|
||||
assert(system.begin == 1);
|
||||
|
||||
gEM.update();
|
||||
assert(system.update == 1);
|
||||
|
||||
gEM.end();
|
||||
assert(system.end == 1);
|
||||
|
||||
ushort[2] ids2 = [CLong.component_id, CInt.component_id];
|
||||
EntityTemplate* tmpl2 = gEM.allocateTemplate(ids2);
|
||||
scope (exit) gEM.freeTemplate(tmpl2);
|
||||
gEM.addEntity(tmpl2);
|
||||
gEM.addEntity(tmpl2);
|
||||
|
||||
gEM.begin();
|
||||
assert(system.begin == 2);
|
||||
|
||||
gEM.update();
|
||||
assert(system.update == 2);//system is updated number of entity blocks times
|
||||
|
||||
gEM.end();
|
||||
assert(system.end == 2);
|
||||
|
||||
ushort[2] ids3 = [CLong.component_id, CShort.component_id];
|
||||
EntityTemplate* tmpl3 = gEM.allocateTemplate(ids3);
|
||||
scope (exit) gEM.freeTemplate(tmpl3);
|
||||
gEM.addEntity(tmpl3);
|
||||
|
||||
//entity with excluded component shouldn't be updated
|
||||
gEM.begin();
|
||||
assert(system.begin == 3);
|
||||
|
||||
gEM.update();
|
||||
assert(system.update == 2);
|
||||
|
||||
gEM.end();
|
||||
assert(system.end == 3);
|
||||
|
||||
//system can be disable form update in onBegin() callback, onEnd() callback is called
|
||||
system.pass = false;
|
||||
gEM.begin();
|
||||
assert(system.begin == 4);
|
||||
|
||||
gEM.update();
|
||||
assert(system.update == 0);
|
||||
|
||||
gEM.end();
|
||||
assert(system.end == 4);
|
||||
system.pass = true;
|
||||
|
||||
//disabled system is't called
|
||||
ecs_system.disable();
|
||||
gEM.begin();
|
||||
assert(system.begin == 4);
|
||||
|
||||
gEM.update();
|
||||
assert(system.update == 0);
|
||||
|
||||
gEM.end();
|
||||
assert(system.end == 4);
|
||||
ecs_system.enable();
|
||||
}
|
||||
|
||||
@("CustomPass")
|
||||
unittest
|
||||
{
|
||||
gEM.beginRegister();
|
||||
|
||||
gEM.registerPass("custom");
|
||||
gEM.registerSystem!LongAddSystem(-1,"custom");
|
||||
|
||||
gEM.endRegister();
|
||||
|
||||
LongAddSystem* system = gEM.getSystem!LongAddSystem;
|
||||
assert(system !is null);
|
||||
assert(system.updates_count == 0);
|
||||
|
||||
System* ecs_system = gEM.getSystem(LongAddSystem.system_id);
|
||||
assert(ecs_system !is null);
|
||||
assert(ecs_system.id == LongAddSystem.system_id);
|
||||
assert(ecs_system.priority == -1);
|
||||
assert(ecs_system.name == "LongAddSystem");
|
||||
|
||||
ushort[1] ids = [CLong.component_id];
|
||||
EntityTemplate* tmpl = gEM.allocateTemplate(ids);
|
||||
scope (exit) gEM.freeTemplate(tmpl);
|
||||
gEM.addEntity(tmpl);
|
||||
|
||||
gEM.begin();
|
||||
|
||||
gEM.update();
|
||||
assert(system.updates_count == 0);
|
||||
gEM.update("custom");
|
||||
assert(system.updates_count == 1);
|
||||
|
||||
gEM.end();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@("SystemEntityCallbacks")
|
||||
unittest
|
||||
{
|
||||
struct TestSystem
|
||||
{
|
||||
mixin ECS.System!16;
|
||||
|
||||
mixin ECS.ExcludedComponents!(CShort);
|
||||
|
||||
struct EntitiesData
|
||||
{
|
||||
int length;
|
||||
CLong[] long_;
|
||||
@optional CInt[] int_;
|
||||
}
|
||||
|
||||
void onAddEntity(EntitiesData data)
|
||||
{
|
||||
add++;
|
||||
}
|
||||
|
||||
void onRemoveEntity(EntitiesData data)
|
||||
{
|
||||
remove++;
|
||||
}
|
||||
|
||||
void onChangeEntity(EntitiesData data)
|
||||
{
|
||||
change++;
|
||||
}
|
||||
|
||||
void onUpdate(EntitiesData data)
|
||||
{
|
||||
}
|
||||
|
||||
int add = 0;
|
||||
int remove = 0;
|
||||
int change = 0;
|
||||
}
|
||||
|
||||
gEM.beginRegister();
|
||||
|
||||
gEM.registerSystem!TestSystem(0);
|
||||
|
||||
gEM.endRegister();
|
||||
|
||||
TestSystem* system = gEM.getSystem!TestSystem;
|
||||
assert(system !is null);
|
||||
assert(system.add == 0);
|
||||
assert(system.remove == 0);
|
||||
assert(system.change == 0);
|
||||
|
||||
ushort[2] ids = [CLong.component_id,CFloat.component_id];
|
||||
EntityTemplate* tmpl = gEM.allocateTemplate(ids);
|
||||
scope (exit) gEM.freeTemplate(tmpl);
|
||||
EntityID id0 = gEM.addEntity(tmpl).id;
|
||||
gEM.commit();
|
||||
assert(system.add == 1);
|
||||
|
||||
ushort[2] ids2 = [CLong.component_id, CInt.component_id];
|
||||
EntityTemplate* tmpl2 = gEM.allocateTemplate(ids2);
|
||||
scope (exit) gEM.freeTemplate(tmpl2);
|
||||
EntityID id1 = gEM.addEntity(tmpl2).id;
|
||||
gEM.commit();
|
||||
assert(system.add == 2);
|
||||
|
||||
ushort[2] ids3 = [CLong.component_id, CShort.component_id];
|
||||
EntityTemplate* tmpl3 = gEM.allocateTemplate(ids3);
|
||||
scope (exit) gEM.freeTemplate(tmpl3);
|
||||
EntityID id2 = gEM.addEntity(tmpl3).id;
|
||||
gEM.commit();
|
||||
assert(system.add == 2);
|
||||
|
||||
gEM.commit();
|
||||
}
|
||||
|
|
@ -60,6 +60,11 @@ string copyString(const char* str)
|
|||
return cast(string) Mallocator.makeArray(arr);
|
||||
}
|
||||
|
||||
string copyString(string str)
|
||||
{
|
||||
return cast(string) Mallocator.makeArray((cast(char*)str)[0 .. str.length + 1]);
|
||||
}
|
||||
|
||||
struct TestRunner(Args...)
|
||||
{
|
||||
void generateJUnit()
|
||||
|
|
@ -90,10 +95,10 @@ struct TestRunner(Args...)
|
|||
write(test.name);
|
||||
write("\" classname=\"");
|
||||
write(suite.name);
|
||||
write("\">\n");
|
||||
write("\">");
|
||||
if (test.msg)
|
||||
{
|
||||
write("\t\t\t<failure type=\"Fail\" message=\"");
|
||||
write("\n\t\t\t<failure type=\"Fail\" message=\"");
|
||||
write(test.msg[0 .. $ - 1]);
|
||||
write("\">");
|
||||
write("Assert! File: ");
|
||||
|
|
@ -103,8 +108,10 @@ struct TestRunner(Args...)
|
|||
write(" Message: ");
|
||||
write(test.msg[0 .. $ - 1]);
|
||||
write("</failure>\n");
|
||||
write("\t\t</testcase>\n");
|
||||
}
|
||||
write("\t\t</testcase>\n");
|
||||
else write("</testcase>\n");
|
||||
|
||||
}
|
||||
|
||||
write("\t</testsuite>\n");
|
||||
|
|
@ -168,21 +175,39 @@ struct TestRunner(Args...)
|
|||
static if (__traits(hasMember, module_, "beforeEveryTest"))
|
||||
module_.beforeEveryTest();
|
||||
|
||||
// Save calling environment for longjmp
|
||||
int jmp_ret = setjmp(gEnvBuffer);
|
||||
|
||||
if (jmp_ret == ASSERTED)
|
||||
version(D_BetterC)
|
||||
{
|
||||
passed = false;
|
||||
test.passed = false;
|
||||
test.file = copyString(gAssertInfo.file);
|
||||
test.file_line = gAssertInfo.line;
|
||||
test.msg = copyString(gAssertInfo.msg);
|
||||
// Save calling environment for longjmp
|
||||
int jmp_ret = setjmp(gEnvBuffer);
|
||||
|
||||
if (jmp_ret == ASSERTED)
|
||||
{
|
||||
test.passed = false;
|
||||
test.file = copyString(gAssertInfo.file);
|
||||
test.file_line = gAssertInfo.line;
|
||||
test.msg = copyString(gAssertInfo.msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
unittest_();
|
||||
test.passed = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
unittest_();
|
||||
test.passed = true;
|
||||
import core.exception : AssertError;
|
||||
try
|
||||
{
|
||||
unittest_();
|
||||
test.passed = true;
|
||||
}
|
||||
catch(AssertError error)
|
||||
{
|
||||
test.passed = false;
|
||||
test.file = copyString(error.file);
|
||||
test.file_line = cast(int)error.line;
|
||||
test.msg = copyString(error.msg);
|
||||
}
|
||||
}
|
||||
|
||||
if (test.passed)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue