Merge branch 'master' into cxx17
All checks were successful
Run UnitTests / build-and-run-unittests (push) Successful in 29s

This commit is contained in:
Stephen Seo 2024-07-15 13:34:15 +09:00
commit c016fcdbd9
9 changed files with 552 additions and 338 deletions

View file

@ -9,7 +9,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Install dependencies
run: sudo /usr/bin/env DEBIAN_FRONTEND=noninteractive apt-get install libgtest-dev cmake
run: sudo /usr/bin/env DEBIAN_FRONTEND=noninteractive apt-get install cmake
- name: Get sources
run: git clone --depth=1 --no-single-branch https://github.com/Stephen-Seo/EntityComponentMetaSystem.git ECMS && cd ECMS && git checkout $GITHUB_REF_NAME
- name: Build UnitTests

View file

@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2016-2019,2021-2022 Stephen Seo
Copyright (c) 2016-2019,2021-2022,2024 Stephen Seo
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

20
conanfile.py Normal file
View file

@ -0,0 +1,20 @@
from conan import ConanFile
from conan.tools.files import copy
class ECMSConan(ConanFile):
name = "ecms"
version = "1.0"
# No settings/options are necessary, this is header only
exports_sources = "src/EC/*"
no_copy_source = True
def package(self):
# This will also copy the "include" folder
copy(self, "*.hpp", self.source_folder, self.package_folder)
def package_info(self):
# For header-only packages, libdirs and bindirs are not used
# so it's recommended to set those as empty.
self.cpp_info.bindirs = []
self.cpp_info.libdirs = []

View file

@ -47,8 +47,6 @@ endif()
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/EC DESTINATION include)
find_package(GTest)
if(GTEST_FOUND)
set(UnitTests_SOURCES
test/MetaTest.cpp
test/ECTest.cpp
@ -57,13 +55,12 @@ if(GTEST_FOUND)
)
add_executable(UnitTests ${UnitTests_SOURCES})
target_link_libraries(UnitTests EntityComponentSystem ${GTEST_LIBRARIES})
target_include_directories(UnitTests PUBLIC ${GTEST_INCLUDE_DIR})
target_link_libraries(UnitTests EntityComponentSystem)
target_compile_features(UnitTests PUBLIC cxx_std_17)
target_compile_options(UnitTests PRIVATE "-Wno-sign-compare")
enable_testing()
add_test(NAME UnitTests COMMAND UnitTests)
endif()
add_executable(WillFailCompile ${WillFailCompile_SOURCES})
set_target_properties(WillFailCompile PROPERTIES

File diff suppressed because it is too large Load diff

View file

@ -1,8 +1,44 @@
#include "test_helpers.h"
#include <gtest/gtest.h>
int checks_checked = 0;
int checks_passed = 0;
int main(int argc, char** argv)
{
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
int main() {
TEST_EC_Bitset();
TEST_EC_Manager();
TEST_EC_MoveComponentWithUniquePtr();
TEST_EC_DeletedEntities();
TEST_EC_FunctionStorage();
TEST_EC_DeletedEntityID();
TEST_EC_MultiThreaded();
TEST_EC_ForMatchingSignatures();
TEST_EC_forMatchingPtrs();
TEST_EC_context();
TEST_EC_FunctionStorageOrder();
TEST_EC_forMatchingSimple();
TEST_EC_forMatchingIterableFn();
TEST_EC_MultiThreadedForMatching();
TEST_EC_ManagerWithLowThreadCount();
TEST_EC_ManagerDeferredDeletions();
TEST_EC_NestedThreadPoolTasks();
TEST_Meta_Contains();
TEST_Meta_ContainsAll();
TEST_Meta_IndexOf();
TEST_Meta_Bitset();
TEST_Meta_Combine();
TEST_Meta_Morph();
TEST_Meta_TypeListGet();
TEST_Meta_ForEach();
TEST_Meta_Matching();
TEST_ECThreadPool_OneThread();
TEST_ECThreadPool_Simple();
TEST_ECThreadPool_QueryCount();
TEST_ECThreadPool_easyStartAndWait();
std::cout << "checks_checked: " << checks_checked << '\n'
<< "checks_passed: " << checks_passed << std::endl;
return checks_checked == checks_passed ? 0 : 1;
}

View file

@ -1,5 +1,4 @@
#include <gtest/gtest.h>
#include "test_helpers.h"
#include <tuple>
#include <EC/Meta/Meta.hpp>
@ -28,179 +27,179 @@ struct Storage
using type = std::tuple<std::vector<STypes>... >;
};
TEST(Meta, Contains)
void TEST_Meta_Contains()
{
int size = ListComponentsAll::size;
EXPECT_EQ(size, 4);
CHECK_EQ(size, 4);
bool result = EC::Meta::Contains<C0, ListComponentsAll>::value;
EXPECT_TRUE(result);
CHECK_TRUE(result);
result = EC::Meta::Contains<C1, ListComponentsAll>::value;
EXPECT_TRUE(result);
CHECK_TRUE(result);
result = EC::Meta::Contains<C2, ListComponentsAll>::value;
EXPECT_TRUE(result);
CHECK_TRUE(result);
result = EC::Meta::Contains<C3, ListComponentsAll>::value;
EXPECT_TRUE(result);
CHECK_TRUE(result);
size = ListComponentsSome::size;
EXPECT_EQ(size, 2);
CHECK_EQ(size, 2);
result = EC::Meta::Contains<C0, ListComponentsSome>::value;
EXPECT_FALSE(result);
CHECK_FALSE(result);
result = EC::Meta::Contains<C1, ListComponentsSome>::value;
EXPECT_TRUE(result);
CHECK_TRUE(result);
result = EC::Meta::Contains<C2, ListComponentsSome>::value;
EXPECT_FALSE(result);
CHECK_FALSE(result);
result = EC::Meta::Contains<C3, ListComponentsSome>::value;
EXPECT_TRUE(result);
CHECK_TRUE(result);
}
TEST(Meta, ContainsAll)
void TEST_Meta_ContainsAll()
{
bool contains = EC::Meta::ContainsAll<ListComponentsSome, ListComponentsAll>::value;
EXPECT_TRUE(contains);
CHECK_TRUE(contains);
contains = EC::Meta::ContainsAll<ListComponentsAll, ListComponentsSome>::value;
EXPECT_FALSE(contains);
CHECK_FALSE(contains);
contains = EC::Meta::ContainsAll<ListComponentsAll, ListComponentsAll>::value;
EXPECT_TRUE(contains);
CHECK_TRUE(contains);
}
TEST(Meta, IndexOf)
void TEST_Meta_IndexOf()
{
int index = EC::Meta::IndexOf<C0, ListComponentsAll>::value;
EXPECT_EQ(index, 0);
CHECK_EQ(index, 0);
index = EC::Meta::IndexOf<C1, ListComponentsAll>::value;
EXPECT_EQ(index, 1);
CHECK_EQ(index, 1);
index = EC::Meta::IndexOf<C2, ListComponentsAll>::value;
EXPECT_EQ(index, 2);
CHECK_EQ(index, 2);
index = EC::Meta::IndexOf<C3, ListComponentsAll>::value;
EXPECT_EQ(index, 3);
CHECK_EQ(index, 3);
index = EC::Meta::IndexOf<T0, ListComponentsAll>::value;
EXPECT_EQ(index, 4);
CHECK_EQ(index, 4);
index = EC::Meta::IndexOf<C1, ListComponentsSome>::value;
EXPECT_EQ(index, 0);
CHECK_EQ(index, 0);
index = EC::Meta::IndexOf<C3, ListComponentsSome>::value;
EXPECT_EQ(index, 1);
CHECK_EQ(index, 1);
index = EC::Meta::IndexOf<C2, ListComponentsSome>::value;
EXPECT_EQ(index, 2);
CHECK_EQ(index, 2);
}
TEST(Meta, Bitset)
void TEST_Meta_Bitset()
{
EC::Bitset<ListComponentsAll, ListTagsAll> bitset;
EXPECT_EQ(bitset.size(), ListComponentsAll::size + ListTagsAll::size + 1);
CHECK_EQ(bitset.size(), ListComponentsAll::size + ListTagsAll::size + 1);
bitset[EC::Meta::IndexOf<C1, ListComponentsAll>::value] = true;
EXPECT_TRUE(bitset.getComponentBit<C1>());
CHECK_TRUE(bitset.getComponentBit<C1>());
bitset.flip();
EXPECT_FALSE(bitset.getComponentBit<C1>());
CHECK_FALSE(bitset.getComponentBit<C1>());
bitset.reset();
bitset[ListComponentsAll::size + EC::Meta::IndexOf<T0, ListTagsAll>::value] = true;
EXPECT_TRUE(bitset.getTagBit<T0>());
CHECK_TRUE(bitset.getTagBit<T0>());
bitset.flip();
EXPECT_FALSE(bitset.getTagBit<T0>());
CHECK_FALSE(bitset.getTagBit<T0>());
}
TEST(Meta, Combine)
void TEST_Meta_Combine()
{
using CombinedAll = EC::Meta::Combine<ListComponentsAll, ListTagsAll>;
int listAllTemp = ListAll::size;
int combinedAllTemp = CombinedAll::size;
EXPECT_EQ(combinedAllTemp, listAllTemp);
CHECK_EQ(combinedAllTemp, listAllTemp);
listAllTemp = EC::Meta::IndexOf<C0, ListAll>::value;
combinedAllTemp = EC::Meta::IndexOf<C0, CombinedAll>::value;
EXPECT_EQ(combinedAllTemp, listAllTemp);
CHECK_EQ(combinedAllTemp, listAllTemp);
listAllTemp = EC::Meta::IndexOf<C1, ListAll>::value;
combinedAllTemp = EC::Meta::IndexOf<C1, CombinedAll>::value;
EXPECT_EQ(combinedAllTemp, listAllTemp);
CHECK_EQ(combinedAllTemp, listAllTemp);
listAllTemp = EC::Meta::IndexOf<C2, ListAll>::value;
combinedAllTemp = EC::Meta::IndexOf<C2, CombinedAll>::value;
EXPECT_EQ(combinedAllTemp, listAllTemp);
CHECK_EQ(combinedAllTemp, listAllTemp);
listAllTemp = EC::Meta::IndexOf<C3, ListAll>::value;
combinedAllTemp = EC::Meta::IndexOf<C3, CombinedAll>::value;
EXPECT_EQ(combinedAllTemp, listAllTemp);
CHECK_EQ(combinedAllTemp, listAllTemp);
listAllTemp = EC::Meta::IndexOf<T0, ListAll>::value;
combinedAllTemp = EC::Meta::IndexOf<T0, CombinedAll>::value;
EXPECT_EQ(combinedAllTemp, listAllTemp);
CHECK_EQ(combinedAllTemp, listAllTemp);
listAllTemp = EC::Meta::IndexOf<T1, ListAll>::value;
combinedAllTemp = EC::Meta::IndexOf<T1, CombinedAll>::value;
EXPECT_EQ(combinedAllTemp, listAllTemp);
CHECK_EQ(combinedAllTemp, listAllTemp);
bool same = std::is_same<CombinedAll, ListAll>::value;
EXPECT_TRUE(same);
CHECK_TRUE(same);
}
TEST(Meta, Morph)
void TEST_Meta_Morph()
{
using TupleAll = std::tuple<C0, C1, C2, C3>;
using MorphedTuple = EC::Meta::Morph<TupleAll, EC::Meta::TypeList<> >;
int morphedTupleTemp = MorphedTuple::size;
int componentsTemp = ListComponentsAll::size;
EXPECT_EQ(morphedTupleTemp, componentsTemp);
CHECK_EQ(morphedTupleTemp, componentsTemp);
morphedTupleTemp = EC::Meta::IndexOf<C0, MorphedTuple>::value;
componentsTemp = EC::Meta::IndexOf<C0, ListComponentsAll>::value;
EXPECT_EQ(morphedTupleTemp, componentsTemp);
CHECK_EQ(morphedTupleTemp, componentsTemp);
morphedTupleTemp = EC::Meta::IndexOf<C1, MorphedTuple>::value;
componentsTemp = EC::Meta::IndexOf<C1, ListComponentsAll>::value;
EXPECT_EQ(morphedTupleTemp, componentsTemp);
CHECK_EQ(morphedTupleTemp, componentsTemp);
morphedTupleTemp = EC::Meta::IndexOf<C2, MorphedTuple>::value;
componentsTemp = EC::Meta::IndexOf<C2, ListComponentsAll>::value;
EXPECT_EQ(morphedTupleTemp, componentsTemp);
CHECK_EQ(morphedTupleTemp, componentsTemp);
morphedTupleTemp = EC::Meta::IndexOf<C3, MorphedTuple>::value;
componentsTemp = EC::Meta::IndexOf<C3, ListComponentsAll>::value;
EXPECT_EQ(morphedTupleTemp, componentsTemp);
CHECK_EQ(morphedTupleTemp, componentsTemp);
using MorphedComponents = EC::Meta::Morph<ListComponentsAll, std::tuple<> >;
bool isSame = std::is_same<MorphedComponents, TupleAll>::value;
EXPECT_TRUE(isSame);
CHECK_TRUE(isSame);
using ComponentsStorage = EC::Meta::Morph<ListComponentsAll, Storage<> >;
isSame = std::is_same<ComponentsStorage::type,
std::tuple<std::vector<C0>, std::vector<C1>, std::vector<C2>, std::vector<C3> > >::value;
EXPECT_TRUE(isSame);
CHECK_TRUE(isSame);
}
TEST(Meta, TypeListGet)
void TEST_Meta_TypeListGet()
{
bool isSame = std::is_same<C0, EC::Meta::TypeListGet<ListAll, 0> >::value;
EXPECT_TRUE(isSame);
CHECK_TRUE(isSame);
isSame = std::is_same<C1, EC::Meta::TypeListGet<ListAll, 1> >::value;
EXPECT_TRUE(isSame);
CHECK_TRUE(isSame);
isSame = std::is_same<C2, EC::Meta::TypeListGet<ListAll, 2> >::value;
EXPECT_TRUE(isSame);
CHECK_TRUE(isSame);
isSame = std::is_same<C3, EC::Meta::TypeListGet<ListAll, 3> >::value;
EXPECT_TRUE(isSame);
CHECK_TRUE(isSame);
const unsigned int temp = 4;
isSame = std::is_same<T0, EC::Meta::TypeListGet<ListAll, temp> >::value;
EXPECT_TRUE(isSame);
CHECK_TRUE(isSame);
isSame = std::is_same<T1, EC::Meta::TypeListGet<ListAll, 5> >::value;
EXPECT_TRUE(isSame);
CHECK_TRUE(isSame);
}
TEST(Meta, ForEach)
void TEST_Meta_ForEach()
{
EC::Bitset<ListComponentsAll, ListTagsAll> bitset;
@ -210,32 +209,32 @@ TEST(Meta, ForEach)
EC::Meta::forEach<ListComponentsSome>(setBits);
EXPECT_FALSE(bitset[0]);
EXPECT_TRUE(bitset[1]);
EXPECT_FALSE(bitset[2]);
EXPECT_TRUE(bitset[3]);
EXPECT_FALSE(bitset[4]);
EXPECT_FALSE(bitset[5]);
CHECK_FALSE(bitset[0]);
CHECK_TRUE(bitset[1]);
CHECK_FALSE(bitset[2]);
CHECK_TRUE(bitset[3]);
CHECK_FALSE(bitset[4]);
CHECK_FALSE(bitset[5]);
}
TEST(Meta, Matching)
void TEST_Meta_Matching()
{
{
using Matched = EC::Meta::Matching<ListComponentsSome, ListComponentsAll>::type;
bool isSame = std::is_same<ListComponentsSome, Matched>::value;
EXPECT_TRUE(isSame);
CHECK_TRUE(isSame);
}
{
using Matched = EC::Meta::Matching<ListSome, ListAll>::type;
bool isSame = std::is_same<ListSome, Matched>::value;
EXPECT_TRUE(isSame);
CHECK_TRUE(isSame);
}
{
using Matched = EC::Meta::Matching<ListTagsAll, ListComponentsAll>::type;
bool isSame = std::is_same<EC::Meta::TypeList<>, Matched>::value;
EXPECT_TRUE(isSame);
CHECK_TRUE(isSame);
}
}

View file

@ -1,11 +1,11 @@
#include <gtest/gtest.h>
#include "test_helpers.h"
#include <EC/ThreadPool.hpp>
using OneThreadPool = EC::ThreadPool<1>;
using ThreeThreadPool = EC::ThreadPool<3>;
TEST(ECThreadPool, OneThread) {
void TEST_ECThreadPool_OneThread() {
OneThreadPool p;
std::atomic_int data;
data.store(0);
@ -36,7 +36,7 @@ TEST(ECThreadPool, OneThread) {
ASSERT_EQ(data.load(), 11);
}
TEST(ECThreadPool, Simple) {
void TEST_ECThreadPool_Simple() {
ThreeThreadPool p;
std::atomic_int data;
data.store(0);
@ -67,7 +67,7 @@ TEST(ECThreadPool, Simple) {
ASSERT_EQ(data.load(), 11);
}
TEST(ECThreadPool, QueryCount) {
void TEST_ECThreadPool_QueryCount() {
{
OneThreadPool oneP;
ASSERT_EQ(1, oneP.getMaxThreadCount());
@ -78,7 +78,7 @@ TEST(ECThreadPool, QueryCount) {
}
}
TEST(ECThreadPool, easyStartAndWait) {
void TEST_ECThreadPool_easyStartAndWait() {
std::atomic_int data;
data.store(0);
{
@ -90,7 +90,7 @@ TEST(ECThreadPool, easyStartAndWait) {
}, &data);
}
oneP.easyStartAndWait();
EXPECT_EQ(20, data.load());
CHECK_EQ(20, data.load());
}
{
ThreeThreadPool threeP;
@ -101,6 +101,6 @@ TEST(ECThreadPool, easyStartAndWait) {
}, &data);
}
threeP.easyStartAndWait();
EXPECT_EQ(40, data.load());
CHECK_EQ(40, data.load());
}
}

163
src/test/test_helpers.h Normal file
View file

@ -0,0 +1,163 @@
#ifndef SEODISPARATE_COM_ENTITY_COMPONENT_META_SYSTEM_TEST_HELPERS_H_
#define SEODISPARATE_COM_ENTITY_COMPONENT_META_SYSTEM_TEST_HELPERS_H_
#include <cstring>
#include <iostream>
extern int checks_checked;
extern int checks_passed;
// Macros for unit testing.
#define CHECK_TRUE(x) \
do { \
++checks_checked; \
if (!(x)) { \
std::cout << "CHECK_TRUE at line " << __LINE__ << " failed: " << #x \
<< '\n'; \
} else { \
++checks_passed; \
} \
} while (false);
#define ASSERT_TRUE(x) \
do { \
++checks_checked; \
if (!(x)) { \
std::cout << "CHECK_TRUE at line " << __LINE__ << " failed: " << #x \
<< '\n'; \
return; \
} else { \
++checks_passed; \
} \
} while (false);
#define CHECK_FALSE(x) \
do { \
++checks_checked; \
if (x) { \
std::cout << "CHECK_FALSE at line " << __LINE__ << " failed: " << #x \
<< '\n'; \
} else { \
++checks_passed; \
} \
} while (false);
#define ASSERT_FALSE(x) \
do { \
++checks_checked; \
if (x) { \
std::cout << "CHECK_FALSE at line " << __LINE__ << " failed: " << #x \
<< '\n'; \
return; \
} else { \
++checks_passed; \
} \
} while (false);
#define CHECK_FLOAT(var, value) \
do { \
++checks_checked; \
if ((var) > (value) - 0.0001F && (var) < (value) + 0.0001F) { \
++checks_passed; \
} else { \
std::cout << "CHECK_FLOAT at line " << __LINE__ << " failed: " << #var \
<< " != " << #value << '\n'; \
} \
} while (false);
#define CHECK_EQ(var, value) \
do { \
++checks_checked; \
if ((var) == (value)) { \
++checks_passed; \
} else { \
std::cout << "CHECK_EQ at line " << __LINE__ << " failed: " << #var \
<< " != " << #value << '\n'; \
} \
} while (false);
#define ASSERT_EQ(var, value) \
do { \
++checks_checked; \
if ((var) == (value)) { \
++checks_passed; \
} else { \
std::cout << "ASSERT_EQ at line " << __LINE__ << " failed: " << #var \
<< " != " << #value << '\n'; \
return; \
} \
} while (false);
#define CHECK_NE(var, value) \
do { \
++checks_checked; \
if ((var) != (value)) { \
++checks_passed; \
} else { \
std::cout << "CHECK_NE at line " << __LINE__ << " failed: " << #var \
<< " == " << #value << '\n'; \
} \
} while (false);
#define CHECK_GE(var, value) \
do { \
++checks_checked; \
if ((var) >= (value)) { \
++checks_passed; \
} else { \
std::cout << "CHECK_GE at line " << __LINE__ << " failed: " << #var \
<< " < " << #value << '\n'; \
} \
} while (false);
#define CHECK_LE(var, value) \
do { \
++checks_checked; \
if ((var) <= (value)) { \
++checks_passed; \
} else { \
std::cout << "CHECK_LE at line " << __LINE__ << " failed: " << #var \
<< " > " << #value << '\n'; \
} \
} while (false);
#define CHECK_STREQ(str_a, str_b) \
do { \
++checks_checked; \
if (std::strcmp((str_a), (str_b)) == 0) { \
++checks_passed; \
} else { \
std::cout << "CHECK_STREQ at line " << __LINE__ << "failed: " << #str_a \
<< " != " << #str_b << '\n'; \
} \
} while (false);
// Tests.
void TEST_EC_Bitset();
void TEST_EC_Manager();
void TEST_EC_MoveComponentWithUniquePtr();
void TEST_EC_DeletedEntities();
void TEST_EC_FunctionStorage();
void TEST_EC_DeletedEntityID();
void TEST_EC_MultiThreaded();
void TEST_EC_ForMatchingSignatures();
void TEST_EC_forMatchingPtrs();
void TEST_EC_context();
void TEST_EC_FunctionStorageOrder();
void TEST_EC_forMatchingSimple();
void TEST_EC_forMatchingIterableFn();
void TEST_EC_MultiThreadedForMatching();
void TEST_EC_ManagerWithLowThreadCount();
void TEST_EC_ManagerDeferredDeletions();
void TEST_EC_NestedThreadPoolTasks();
void TEST_Meta_Contains();
void TEST_Meta_ContainsAll();
void TEST_Meta_IndexOf();
void TEST_Meta_Bitset();
void TEST_Meta_Combine();
void TEST_Meta_Morph();
void TEST_Meta_TypeListGet();
void TEST_Meta_ForEach();
void TEST_Meta_Matching();
void TEST_ECThreadPool_OneThread();
void TEST_ECThreadPool_Simple();
void TEST_ECThreadPool_QueryCount();
void TEST_ECThreadPool_easyStartAndWait();
#endif