save-state-1
This commit is contained in:
3
.vscode/c_cpp_properties.json
vendored
3
.vscode/c_cpp_properties.json
vendored
@@ -5,7 +5,8 @@
|
|||||||
"includePath": [
|
"includePath": [
|
||||||
"${workspaceFolder}/**",
|
"${workspaceFolder}/**",
|
||||||
"/opt/homebrew/include",
|
"/opt/homebrew/include",
|
||||||
"/opt/homebrew/opt/ncurses/include"
|
"/opt/homebrew/opt/ncurses/include",
|
||||||
|
"/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Kernel.framework/Versions/A/Headers"
|
||||||
],
|
],
|
||||||
"defines": [],
|
"defines": [],
|
||||||
"macFrameworkPath": [
|
"macFrameworkPath": [
|
||||||
|
|||||||
88
.vscode/settings.json
vendored
88
.vscode/settings.json
vendored
@@ -1,3 +1,89 @@
|
|||||||
{
|
{
|
||||||
"files.encoding": "cp437"
|
"files.encoding": "cp437",
|
||||||
|
"files.associations": {
|
||||||
|
"*.monster": "json",
|
||||||
|
"*.ipp": "cpp",
|
||||||
|
"stack": "cpp",
|
||||||
|
"iosfwd": "cpp",
|
||||||
|
"ostream": "cpp",
|
||||||
|
"tuple": "cpp",
|
||||||
|
"vector": "cpp",
|
||||||
|
"cstdint": "cpp",
|
||||||
|
"__bit_reference": "cpp",
|
||||||
|
"__bits": "cpp",
|
||||||
|
"__config": "cpp",
|
||||||
|
"__debug": "cpp",
|
||||||
|
"__errc": "cpp",
|
||||||
|
"__hash_table": "cpp",
|
||||||
|
"__locale": "cpp",
|
||||||
|
"__mutex_base": "cpp",
|
||||||
|
"__node_handle": "cpp",
|
||||||
|
"__nullptr": "cpp",
|
||||||
|
"__split_buffer": "cpp",
|
||||||
|
"__std_stream": "cpp",
|
||||||
|
"__string": "cpp",
|
||||||
|
"__threading_support": "cpp",
|
||||||
|
"__tree": "cpp",
|
||||||
|
"__tuple": "cpp",
|
||||||
|
"array": "cpp",
|
||||||
|
"atomic": "cpp",
|
||||||
|
"bit": "cpp",
|
||||||
|
"bitset": "cpp",
|
||||||
|
"cctype": "cpp",
|
||||||
|
"cfenv": "cpp",
|
||||||
|
"chrono": "cpp",
|
||||||
|
"clocale": "cpp",
|
||||||
|
"cmath": "cpp",
|
||||||
|
"compare": "cpp",
|
||||||
|
"complex": "cpp",
|
||||||
|
"concepts": "cpp",
|
||||||
|
"csignal": "cpp",
|
||||||
|
"cstdarg": "cpp",
|
||||||
|
"cstddef": "cpp",
|
||||||
|
"cstdio": "cpp",
|
||||||
|
"cstdlib": "cpp",
|
||||||
|
"cstring": "cpp",
|
||||||
|
"ctime": "cpp",
|
||||||
|
"cwchar": "cpp",
|
||||||
|
"cwctype": "cpp",
|
||||||
|
"deque": "cpp",
|
||||||
|
"exception": "cpp",
|
||||||
|
"fstream": "cpp",
|
||||||
|
"initializer_list": "cpp",
|
||||||
|
"iomanip": "cpp",
|
||||||
|
"ios": "cpp",
|
||||||
|
"iostream": "cpp",
|
||||||
|
"istream": "cpp",
|
||||||
|
"limits": "cpp",
|
||||||
|
"list": "cpp",
|
||||||
|
"locale": "cpp",
|
||||||
|
"map": "cpp",
|
||||||
|
"memory": "cpp",
|
||||||
|
"mutex": "cpp",
|
||||||
|
"new": "cpp",
|
||||||
|
"numeric": "cpp",
|
||||||
|
"optional": "cpp",
|
||||||
|
"random": "cpp",
|
||||||
|
"ranges": "cpp",
|
||||||
|
"ratio": "cpp",
|
||||||
|
"set": "cpp",
|
||||||
|
"span": "cpp",
|
||||||
|
"sstream": "cpp",
|
||||||
|
"stdexcept": "cpp",
|
||||||
|
"streambuf": "cpp",
|
||||||
|
"string": "cpp",
|
||||||
|
"string_view": "cpp",
|
||||||
|
"strstream": "cpp",
|
||||||
|
"system_error": "cpp",
|
||||||
|
"type_traits": "cpp",
|
||||||
|
"typeindex": "cpp",
|
||||||
|
"typeinfo": "cpp",
|
||||||
|
"unordered_map": "cpp",
|
||||||
|
"valarray": "cpp",
|
||||||
|
"variant": "cpp",
|
||||||
|
"algorithm": "cpp",
|
||||||
|
"__verbose_abort": "cpp",
|
||||||
|
"thread": "cpp",
|
||||||
|
"iterator": "cpp"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
26
Makefile
26
Makefile
@@ -128,15 +128,17 @@ $(TEST_MAIN_CPP): $(TEST_OBJECTS)
|
|||||||
@echo "#include <iostream>" >> $(TEST_MAIN_CPP)
|
@echo "#include <iostream>" >> $(TEST_MAIN_CPP)
|
||||||
@echo "#include <tuple>" >> $(TEST_MAIN_CPP)
|
@echo "#include <tuple>" >> $(TEST_MAIN_CPP)
|
||||||
@echo "using namespace Test;" >> $(TEST_MAIN_CPP)
|
@echo "using namespace Test;" >> $(TEST_MAIN_CPP)
|
||||||
@echo "using std::wcout;\nusing std::endl;\nusing std::tuple;\nusing std::get;" >> $(TEST_MAIN_CPP)
|
@echo "using std::cout;\nusing std::endl;\nusing std::tuple;\nusing std::get;" >> $(TEST_MAIN_CPP)
|
||||||
@echo "$(patsubst %, extern test_method_result main_test_%(int argc, char** argv);\n, $(MODULES))" >> $(TEST_MAIN_CPP)
|
@echo "$(patsubst %, extern TestResults main_test_%(int argc, char** argv);\n, $(MODULES))" >> $(TEST_MAIN_CPP)
|
||||||
@echo "int main(int argc, char** argv) {\n setlocale(LC_ALL, \"\");\n test_method_result results;\n" >> $(TEST_MAIN_CPP)
|
@echo "int main(int argc, char** argv) {\n setlocale(LC_ALL, \"\");\n TestResults results;\n" >> $(TEST_MAIN_CPP)
|
||||||
@echo "$(patsubst %, results = results + main_test_%(argc, argv);\n, $(MODULES))" >> $(TEST_MAIN_CPP)
|
@echo "$(patsubst %, results += main_test_%(argc, argv);\n, $(MODULES))" >> $(TEST_MAIN_CPP)
|
||||||
@echo " wcout << \"Total tests ran: \" << get<0>(results) << endl;\n" >> $(TEST_MAIN_CPP)
|
@echo " cout << \"Total tests: \" << results.total() << endl;" >> $(TEST_MAIN_CPP)
|
||||||
@echo " wcout << \"Total failures: \" << get<1>(results) << endl;\n" >> $(TEST_MAIN_CPP)
|
@echo " cout << \"Passed: \" << results.passed() << endl;" >> $(TEST_MAIN_CPP)
|
||||||
|
@echo " cout << \"Failed: \" << results.failed() << endl;" >> $(TEST_MAIN_CPP)
|
||||||
|
@echo " cout << \"Skipped: \" << results.skipped() << endl;" >> $(TEST_MAIN_CPP)
|
||||||
@echo "\n return 0;\n}" >> $(TEST_MAIN_CPP)
|
@echo "\n return 0;\n}" >> $(TEST_MAIN_CPP)
|
||||||
|
|
||||||
# We make our own fat libs cause homebrew sucks
|
# We make our own fat libs cause homebrew sucks. # We may have to do something similar for macports, but that's not supported yet.
|
||||||
$(LIB_DIR)/lib%.a: $(BREW_PREFIX)/opt/$$*/lib/lib$$*.a $(BREW86_PREFIX)/opt/$$*/lib/lib$$*.a $(MANDATORY_TARGETS)
|
$(LIB_DIR)/lib%.a: $(BREW_PREFIX)/opt/$$*/lib/lib$$*.a $(BREW86_PREFIX)/opt/$$*/lib/lib$$*.a $(MANDATORY_TARGETS)
|
||||||
lipo -create -output $@ $(word 1, $^) $(word 2, $^)
|
lipo -create -output $@ $(word 1, $^) $(word 2, $^)
|
||||||
|
|
||||||
@@ -158,12 +160,12 @@ $(TEST_HARNESS_CPP): $(MANDATORY_TARGETS)
|
|||||||
@echo "#include <iostream>" >> $(TEST_HARNESS_CPP)
|
@echo "#include <iostream>" >> $(TEST_HARNESS_CPP)
|
||||||
@echo "#include <tuple>" >> $(TEST_HARNESS_CPP)
|
@echo "#include <tuple>" >> $(TEST_HARNESS_CPP)
|
||||||
@echo "using namespace Test;" >> $(TEST_HARNESS_CPP)
|
@echo "using namespace Test;" >> $(TEST_HARNESS_CPP)
|
||||||
@echo "using std::wcout;\nusing std::endl;\nusing std::tuple;\nusing std::get;" >> $(TEST_HARNESS_CPP)
|
@echo "using std::cout;\nusing std::endl;\nusing std::tuple;\nusing std::get;" >> $(TEST_HARNESS_CPP)
|
||||||
@echo "extern test_method_result main_test_$(MODULE)(int argc, char** argv);" >> $(TEST_HARNESS_CPP)
|
@echo "extern TestResults main_test_$(MODULE)(int argc, char** argv);" >> $(TEST_HARNESS_CPP)
|
||||||
@echo "int main(int argc, char** argv) {\n setlocale(LC_ALL, \"\");\n test_method_result results;\n" >> $(TEST_HARNESS_CPP)
|
@echo "int main(int argc, char** argv) {\n setlocale(LC_ALL, \"\");\n TestResults results;\n" >> $(TEST_HARNESS_CPP)
|
||||||
@echo " results = results + main_test_$(MODULE)(argc, argv);\n" >> $(TEST_HARNESS_CPP)
|
@echo " results = results + main_test_$(MODULE)(argc, argv);\n" >> $(TEST_HARNESS_CPP)
|
||||||
@echo " wcout << \"Total tests ran: \" << get<0>(results) << endl;" >> $(TEST_HARNESS_CPP)
|
@echo " cout << \"Total tests ran: \" << get<0>(results) << endl;" >> $(TEST_HARNESS_CPP)
|
||||||
@echo " wcout << \"Total failures: \" << get<1>(results) << endl;" >> $(TEST_HARNESS_CPP)
|
@echo " cout << \"Total failures: \" << get<1>(results) << endl;" >> $(TEST_HARNESS_CPP)
|
||||||
@echo "\n return 0;\n}" >> $(TEST_HARNESS_CPP)
|
@echo "\n return 0;\n}" >> $(TEST_HARNESS_CPP)
|
||||||
|
|
||||||
$(TEST_HARNESS_OBJ): $(TEST_HARNESS_CPP) $(SRC_DIR)/*.h $(TEST_CPP) $(MANDATORY_TARGETS)
|
$(TEST_HARNESS_OBJ): $(TEST_HARNESS_CPP) $(SRC_DIR)/*.h $(TEST_CPP) $(MANDATORY_TARGETS)
|
||||||
|
|||||||
13
log.txt
Normal file
13
log.txt
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
Makefile:111: warning: overriding commands for target `build/_test'
|
||||||
|
Makefile:86: warning: ignoring old commands for target `build/_test'
|
||||||
|
clang++ -std=c++17 -finput-charset=UTF-8 -Isbf-cpp -I/opt/homebrew/opt/ncurses/include -arch arm64 -arch x86_64 -fdiagnostics-show-template-tree -fno-elide-type -c -o build/Abilities_test.o sbf-cpp/Abilities_test.cpp
|
||||||
|
clang++ -std=c++17 -finput-charset=UTF-8 -Isbf-cpp -I/opt/homebrew/opt/ncurses/include -arch arm64 -arch x86_64 -fdiagnostics-show-template-tree -fno-elide-type -c -o build/test_main.o build/test_main.cpp
|
||||||
|
clang++ -Lbuild/lib -lncurses -arch arm64 -arch x86_64 -O2 -o build/test build/test_main.o build/Abilities.o build/Archetypes.o build/Attributes.o build/Backgrounds.o build/Character.o build/Clans.o build/Colors.o build/Derangements.o build/Disciplines.o build/Genders.o build/Ranks.o build/Utils.o build/Virtues.o build/Abilities_test.o build/Archetypes_test.o build/Attributes_test.o build/Backgrounds_test.o build/Character_test.o build/Clans_test.o build/Colors_test.o build/Derangements_test.o build/Disciplines_test.o build/Genders_test.o build/Ranks_test.o build/Utils_test.o build/Virtues_test.o build/test.o
|
||||||
|
cp sbf-cpp/Info.plist build/Contents/Info.plist
|
||||||
|
plutil -replace CFBundleExecutable -string "SBF" build/Contents/Info.plist
|
||||||
|
plutil -replace CFBundleIdentifier -string "com.majinnaibu.SBF" build/Contents/Info.plist
|
||||||
|
plutil -replace CFBundleName -string "SBF" build/Contents/Info.plist
|
||||||
|
plutil -replace CFBundleSignature -string SBF_ build/Contents/Info.plist
|
||||||
|
cp build/Contents/Info.plist build/SBF.app/Contents/
|
||||||
|
cp build/sbf build/SBF.app/Contents/MacOS/SBF
|
||||||
|
cp -r Resources/* build/SBF.app/Contents/Resources/
|
||||||
@@ -1,10 +1,26 @@
|
|||||||
#include "Abilities.h"
|
#include "Abilities.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
namespace SBF {
|
namespace SBF {
|
||||||
using std::wstring;
|
using std::wstring;
|
||||||
|
|
||||||
const wstring& GetAbilityLabel(int abilityGroupId, int abilityId) {
|
|
||||||
|
// template<typename T>
|
||||||
|
// T r(int a, int b) {
|
||||||
|
// auto s = [](int a, int b){return (T)nullptr;}
|
||||||
|
// auto t = wstring(L"asdf");
|
||||||
|
// return s(a,b);
|
||||||
|
// }
|
||||||
|
|
||||||
|
void testMe() {
|
||||||
|
auto l = [](int a, int b){return;};
|
||||||
|
l(1,2);
|
||||||
|
// std::cout << "l: " << l(1,2) << std::endl;
|
||||||
|
// auto q = r<void>(1, 2);
|
||||||
|
// std::cout << "q: " << q(1,2) << std::endl;
|
||||||
|
}
|
||||||
|
const wstring GetAbilityLabel(int abilityGroupId, int abilityId) {
|
||||||
switch (abilityGroupId) {
|
switch (abilityGroupId) {
|
||||||
case kAbilityTalentsId:
|
case kAbilityTalentsId:
|
||||||
return kTalents[abilityId];
|
return kTalents[abilityId];
|
||||||
@@ -12,7 +28,7 @@ namespace SBF {
|
|||||||
return kSkills[abilityId];
|
return kSkills[abilityId];
|
||||||
case kAbilityKnowledgesId:
|
case kAbilityKnowledgesId:
|
||||||
return kKnowledges[abilityId];
|
return kKnowledges[abilityId];
|
||||||
}
|
};
|
||||||
return L"";
|
return wstring() + L"";
|
||||||
}
|
}
|
||||||
} // End namespace SBF
|
} // End namespace SBF
|
||||||
|
|||||||
@@ -132,12 +132,12 @@ namespace SBF {
|
|||||||
};
|
};
|
||||||
|
|
||||||
int GetNumItemsForAbilityGroup(int abilityGroupId);
|
int GetNumItemsForAbilityGroup(int abilityGroupId);
|
||||||
const AbilityType& GetAbility(int abilityId);
|
const AbilityType GetAbility(int abilityId);
|
||||||
void FillAbilities(std::vector<AbilityType> abilities);
|
void FillAbilities(std::vector<AbilityType> abilities);
|
||||||
const std::wstring& GetTalentLabel(int talentId);
|
const std::wstring GetTalentLabel(int talentId);
|
||||||
const std::wstring& GetSkillLabel(int talentId);
|
const std::wstring GetSkillLabel(int talentId);
|
||||||
const std::wstring& GetKnowledgeLabel(int talentId);
|
const std::wstring GetKnowledgeLabel(int talentId);
|
||||||
const std::wstring& GetAbilityLabel(int abilityGroupId, int abilityId);
|
const std::wstring GetAbilityLabel(int abilityGroupId, int abilityId);
|
||||||
void FillTalentLabels(std::vector<std::wstring> talentLabels);
|
void FillTalentLabels(std::vector<std::wstring> talentLabels);
|
||||||
void FillSkillLabels(std::vector<std::wstring> skillLabels);
|
void FillSkillLabels(std::vector<std::wstring> skillLabels);
|
||||||
void FillKnowledgeLabels(std::vector<std::wstring> knowledgeLabels);
|
void FillKnowledgeLabels(std::vector<std::wstring> knowledgeLabels);
|
||||||
|
|||||||
@@ -1,23 +1,107 @@
|
|||||||
#include "Abilities.h"
|
#include "Abilities.h"
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
#include <iostream>
|
||||||
using namespace SBF;
|
using namespace SBF;
|
||||||
using namespace Test;
|
using namespace Test;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
// void test_GetNumItemsForAbilityGroup()
|
namespace Test::Abilities {
|
||||||
|
TestResults test_GetNumItemsForAbilityGroup();
|
||||||
|
TestResults test_GetAbility();
|
||||||
|
TestResults test_FillAbilities();
|
||||||
|
TestResults test_GetTalentLabel();
|
||||||
|
TestResults test_GetSkillLabel();
|
||||||
|
TestResults test_GetKnowledgeLabel();
|
||||||
|
TestResults test_GetAbilityLabel();
|
||||||
|
TestResults test_FillTalentLabels();
|
||||||
|
TestResults test_FillSkillLabels();
|
||||||
|
TestResults test_FkilKnowledgeLabels();
|
||||||
|
|
||||||
// int GetNumItemsForAbilityGroup(int abilityGroupId);
|
} // End namespace Test::Abilities
|
||||||
// const AbilityType& GetAbility(int abilityId);
|
using namespace Test::Abilities;
|
||||||
// void FillAbilities(std::vector<AbilityType> abilities);
|
|
||||||
// const std::wstring& GetTalentLabel(int talentId);
|
|
||||||
// const std::wstring& GetSkillLabel(int talentId);
|
|
||||||
// const std::wstring& GetKnowledgeLabel(int talentId);
|
|
||||||
// const std::wstring& GetAbilityLabel(int abilityGroupId, int abilityId);
|
|
||||||
// void FillTalentLabels(std::vector<std::wstring> talentLabels);
|
|
||||||
// void FillSkillLabels(std::vector<std::wstring> skillLabels);
|
|
||||||
// void FillKnowledgeLabels(std::vector<std::wstring> knowledgeLabels);
|
|
||||||
|
|
||||||
test_method_result main_test_Abilities(int argc, char** argv) {
|
namespace Test {
|
||||||
test_method_result results = std::make_tuple(1, 0);
|
extern TestResults do_the_other_thing();
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Find a way to put this in Test::Abilities or at least Test.
|
||||||
|
TestResults main_test_Abilities(int argc, char** argv) {
|
||||||
|
TestResults results;
|
||||||
|
|
||||||
|
// results = results + test_GetNumItemsForAbilityGroup();
|
||||||
|
// results = results + test_GetAbility();
|
||||||
|
// results = results + test_FillAbilities();
|
||||||
|
// results = results + test_GetTalentLabel();
|
||||||
|
// results = results + test_GetSkillLabel();
|
||||||
|
// results = results + test_GetKnowledgeLabel();
|
||||||
|
// results = results + test_GetAbilityLabel();
|
||||||
|
// results = results + test_FillTalentLabels();
|
||||||
|
// results = results + test_FillSkillLabels();
|
||||||
|
// results = results + test_FkilKnowledgeLabels();
|
||||||
|
|
||||||
|
results = do_the_other_thing();
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace Test::Abilities {
|
||||||
|
TestResults test_GetNumItemsForAbilityGroup() {
|
||||||
|
// return test_fn(
|
||||||
|
// L"/SBF/Abilities/GetNumItemsForAbilityGroup",
|
||||||
|
// GetNumItemsForAbilityGroup,
|
||||||
|
// vector({
|
||||||
|
// pair(kTalentsCount, make_tuple(kAbilityTalentsId)),
|
||||||
|
// pair(kSkillsCount, make_tuple(kAbilitySkillsId)),
|
||||||
|
// pair(kKnowledgesCount, make_tuple(kAbilityKnowledgesId)),
|
||||||
|
// pair(0, make_tuple(0)),
|
||||||
|
// pair(0, make_tuple(99)),
|
||||||
|
// }));
|
||||||
|
return TestResults();
|
||||||
|
}
|
||||||
|
|
||||||
|
TestResults test_GetAbility() {
|
||||||
|
// return test_fn(
|
||||||
|
// L"/SBF/Abilities/GetAbility",
|
||||||
|
// GetAbility,
|
||||||
|
// vector({
|
||||||
|
// pair(kAbilityKnowledges, make_tuple(kAbilityKnowledgesId)),
|
||||||
|
// }));
|
||||||
|
return TestResults();
|
||||||
|
}
|
||||||
|
TestResults test_FillAbilities() {
|
||||||
|
return TestResults();
|
||||||
|
}
|
||||||
|
TestResults test_GetTalentLabel() {
|
||||||
|
return TestResults();
|
||||||
|
}
|
||||||
|
TestResults test_GetSkillLabel() {
|
||||||
|
return TestResults();
|
||||||
|
}
|
||||||
|
TestResults test_GetKnowledgeLabel() {
|
||||||
|
return TestResults();
|
||||||
|
}
|
||||||
|
TestResults test_GetAbilityLabel() {
|
||||||
|
return TestResults();
|
||||||
|
}
|
||||||
|
TestResults test_FillTalentLabels() {
|
||||||
|
return TestResults();
|
||||||
|
}
|
||||||
|
TestResults test_FillSkillLabels() {
|
||||||
|
return TestResults();
|
||||||
|
}
|
||||||
|
TestResults test_FkilKnowledgeLabels() {
|
||||||
|
return TestResults();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// TestResults test_GetNumItemsForAbilityGroup() {
|
||||||
|
// return std::make_tuple(1, 0);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// results = results + test_fn(L"get_substring", get_substring, vector({
|
||||||
|
// pair(L"234", make_tuple(L"1234567890", 1, 3)),
|
||||||
|
// pair(L"Paris", make_tuple(L"Where is Paris?", 10-1, 5)),
|
||||||
|
// }));
|
||||||
|
|
||||||
|
|
||||||
|
} // End namespace Test::Abilities
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
using namespace SBF;
|
using namespace SBF;
|
||||||
using namespace Test;
|
using namespace Test;
|
||||||
|
|
||||||
test_method_result main_test_Archetypes(int argc, char** argv) {
|
TestResults main_test_Archetypes(int argc, char** argv) {
|
||||||
test_method_result results = std::make_tuple(1, 0);
|
TestResults results;
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
using namespace SBF;
|
using namespace SBF;
|
||||||
using namespace Test;
|
using namespace Test;
|
||||||
|
|
||||||
test_method_result main_test_Attributes(int argc, char** argv) {
|
TestResults main_test_Attributes(int argc, char** argv) {
|
||||||
test_method_result results = std::make_tuple(1, 0);
|
TestResults results = TestResults().pass();
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
using namespace SBF;
|
using namespace SBF;
|
||||||
using namespace Test;
|
using namespace Test;
|
||||||
|
|
||||||
test_method_result main_test_Backgrounds(int argc, char** argv) {
|
TestResults main_test_Backgrounds(int argc, char** argv) {
|
||||||
test_method_result results = std::make_tuple(1, 0);
|
TestResults results = TestResults().pass();
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
using namespace SBF;
|
using namespace SBF;
|
||||||
using namespace Test;
|
using namespace Test;
|
||||||
|
|
||||||
test_method_result main_test_Character(int argc, char** argv) {
|
TestResults main_test_Character(int argc, char** argv) {
|
||||||
test_method_result results = std::make_tuple(1, 0);
|
TestResults results = TestResults().pass();
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
using namespace SBF;
|
using namespace SBF;
|
||||||
using namespace Test;
|
using namespace Test;
|
||||||
|
|
||||||
test_method_result main_test_Clans(int argc, char** argv) {
|
TestResults main_test_Clans(int argc, char** argv) {
|
||||||
test_method_result results = std::make_tuple(1, 0);
|
TestResults results = TestResults();
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
using namespace SBF;
|
using namespace SBF;
|
||||||
using namespace Test;
|
using namespace Test;
|
||||||
|
|
||||||
test_method_result main_test_Colors(int argc, char** argv) {
|
TestResults main_test_Colors(int argc, char** argv) {
|
||||||
test_method_result results = std::make_tuple(1, 0);
|
TestResults results;
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
using namespace SBF;
|
using namespace SBF;
|
||||||
using namespace Test;
|
using namespace Test;
|
||||||
|
|
||||||
test_method_result main_test_Derangements(int argc, char** argv) {
|
TestResults main_test_Derangements(int argc, char** argv) {
|
||||||
test_method_result results = std::make_tuple(1, 0);
|
TestResults results;
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
using namespace SBF;
|
using namespace SBF;
|
||||||
using namespace Test;
|
using namespace Test;
|
||||||
|
|
||||||
test_method_result main_test_Disciplines(int argc, char** argv) {
|
TestResults main_test_Disciplines(int argc, char** argv) {
|
||||||
test_method_result results = std::make_tuple(1, 0);
|
TestResults results;
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
using namespace SBF;
|
using namespace SBF;
|
||||||
using namespace Test;
|
using namespace Test;
|
||||||
|
|
||||||
test_method_result main_test_Genders(int argc, char** argv) {
|
TestResults main_test_Genders(int argc, char** argv) {
|
||||||
test_method_result results = std::make_tuple(1, 0);
|
TestResults results;
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|||||||
18
sbf-cpp/Questions.md
Normal file
18
sbf-cpp/Questions.md
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
## Why do I have to cast std::nullopt to a specific optional type when calling a templated function i.e.
|
||||||
|
|
||||||
|
```c++
|
||||||
|
template<typename T>
|
||||||
|
void DoSomething(std::optional<T> = std::nullopt, bool report_errors = false);
|
||||||
|
```
|
||||||
|
|
||||||
|
```text
|
||||||
|
DoSomething() works fine.
|
||||||
|
DoSomething(std::nullopt, true) no matching function for call to 'DoSomething' Do_Something<std::optional<string>, bool>(
|
||||||
|
```
|
||||||
|
|
||||||
|
## Which is uglier
|
||||||
|
```c++
|
||||||
|
(*after_each)()
|
||||||
|
after_each->operator()()
|
||||||
|
after_each.value()();
|
||||||
|
```
|
||||||
@@ -3,8 +3,8 @@
|
|||||||
using namespace SBF;
|
using namespace SBF;
|
||||||
using namespace Test;
|
using namespace Test;
|
||||||
|
|
||||||
test_method_result main_test_Ranks(int argc, char** argv) {
|
TestResults main_test_Ranks(int argc, char** argv) {
|
||||||
test_method_result results = std::make_tuple(1, 0);
|
TestResults results;
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|||||||
276
sbf-cpp/Template Problems.md
Normal file
276
sbf-cpp/Template Problems.md
Normal file
@@ -0,0 +1,276 @@
|
|||||||
|
## test_fn implicit template values
|
||||||
|
### Error Message
|
||||||
|
test.cpp(350, 16): argument types are: (const wchar_t [18], lambda [](int id)->std::wstring, std::__1::vector<std::__1::tuple<const wchar_t *, const wchar_t *, std::__1::tuple<int>, lambda [](std::__1::wstring left, std::__1::wstring right)->bool, lambda [](int id)->void, lambda [](int id)->void, bool>, std::__1::allocator<std::__1::tuple<const wchar_t *, const wchar_t *, std::__1::tuple<int>, lambda [](std::__1::wstring left, std::__1::wstring right)->bool, lambda [](int id)->void, lambda [](int id)->void, bool>>>, lambda [](std::__1::wstring left, std::__1::wstring right)->bool, lambda [](int id)->void, lambda [](int id)->void, bool)
|
||||||
|
test_fn
|
||||||
|
+2 overloads
|
||||||
|
|
||||||
|
### Declaration
|
||||||
|
template<typename TResult, typename FnToTest, typename... TInputParams>
|
||||||
|
test_method_result test_fn(
|
||||||
|
wstring suiteName, /* suiteName - This is the name of the test suite. It will be used in logs. */
|
||||||
|
FnToTest testFn, /* testFn - This is the function to be tested. It will be called with std::apply and the inputParams from each test in tests below. */
|
||||||
|
vector<
|
||||||
|
tuple<
|
||||||
|
wstring /* testName */,
|
||||||
|
TResult /* expectedOutput */,
|
||||||
|
tuple<TInputParams...> /* inputParams - The input parameters for this test. These will be used when calling std::apply with testFn to execute the test. */,
|
||||||
|
bool(*)(const TResult expected, const TResult actual) /* testCompareFn - If this is not nullprt then this function will be called instead of suiteCompareFn to determine if the test passes. Use this to check for side effects of the test. Return true if the test passes and false otherwise. */,
|
||||||
|
void(*)(TInputParams...) /* testSetupFn - If this is not nullptr this function is called before each test to setup the environment. It is called with std::apply and inputParams so you can use them to mock records with specific IDs or calculate an expected result. */,
|
||||||
|
void(*)(TInputParams...) /* testTeardownFn - If this is not nullptr this function is called after each test to cleanup any allocated/shared resources. */,
|
||||||
|
bool /* testIsEnabled - If this is false the test, setup, and teardown functions are not run. */
|
||||||
|
> /* <no name> - This is the data and config functions for a specific test run. */
|
||||||
|
> tests, /* tests - Each tuple in the vector is a test run with a name, enabledStatus, input, expected output, and optional compare, setup, and teardown functions. */
|
||||||
|
bool(*suiteCompareFn)(TResult a, TResult b) /* suiteCompareFn used to compare*/,
|
||||||
|
void(*suiteSetupFn)() /* suiteSetupFn called before running the test suite */,
|
||||||
|
void(*suiteTeardownFn)() /* suiteTeardownFn called after all tests have run */,
|
||||||
|
bool /* suiteIsEnabled - If this is false the entire test suite is skipped. The skipped tests will be reported as skipped/disabled. */
|
||||||
|
);
|
||||||
|
|
||||||
|
### For SO post
|
||||||
|
(
|
||||||
|
const wchar_t [18],
|
||||||
|
lambda [](int id)->std::wstring,
|
||||||
|
std::vector<
|
||||||
|
std::tuple<
|
||||||
|
const wchar_t *,
|
||||||
|
const wchar_t *,
|
||||||
|
std::tuple<int>,
|
||||||
|
lambda [](std::wstring left, std::wstring right)->bool,
|
||||||
|
lambda [](int id)->void,
|
||||||
|
lambda [](int id)->void,
|
||||||
|
bool
|
||||||
|
>,
|
||||||
|
std::allocator<
|
||||||
|
std::tuple<
|
||||||
|
const wchar_t *,
|
||||||
|
const wchar_t *,
|
||||||
|
std::tuple<int>,
|
||||||
|
lambda [](std::wstring left, std::wstring right)->bool,
|
||||||
|
lambda [](int id)->void,
|
||||||
|
lambda [](int id)->void,
|
||||||
|
bool
|
||||||
|
>
|
||||||
|
>
|
||||||
|
>,
|
||||||
|
lambda [](std::wstring left, std::wstring right)->bool,
|
||||||
|
lambda [](int id)->void,
|
||||||
|
lambda [](int id)->void,
|
||||||
|
bool
|
||||||
|
)
|
||||||
|
|
||||||
|
template<typename TResult, typename FnToTest, typename... TInputParams>
|
||||||
|
test_method_result test_fn(
|
||||||
|
wstring suiteName,
|
||||||
|
FnToTest testFn,
|
||||||
|
vector<
|
||||||
|
tuple<
|
||||||
|
wstring,
|
||||||
|
TResult,
|
||||||
|
tuple<TInputParams...>,
|
||||||
|
bool(*)(const TResult expected, const TResult actual),
|
||||||
|
void(*)(TInputParams...),
|
||||||
|
void(*)(TInputParams...),
|
||||||
|
bool
|
||||||
|
>
|
||||||
|
> tests,
|
||||||
|
bool(*suiteCompareFn)(TResult a, TResult b),
|
||||||
|
void(*suiteSetupFn)(),
|
||||||
|
void(*suiteTeardownFn)(),
|
||||||
|
bool
|
||||||
|
);
|
||||||
|
|
||||||
|
### For SO Post v2
|
||||||
|
(
|
||||||
|
const wchar_t [18], // const wchar_t* suiteName // Literal wstring
|
||||||
|
lambda [](int id)->std::wstring, // wstring(*)(int id) testFn //
|
||||||
|
std::vector< // Begin vector<...> tests //
|
||||||
|
std::tuple< // Begin tuple<...> a test //
|
||||||
|
const wchar_t *, // const wchar_t* testName // Literal const wchar_t*
|
||||||
|
const wchar_t *, // const wchar_t* expected // Literal const wchar_t*
|
||||||
|
std::tuple<int>, // tuple<int> inputParams // int id
|
||||||
|
lambda [](std::wstring left, std::wstring right)->bool, // bool(*)(const wstring expected, const wstring actual) compareFn // dummy equals fn
|
||||||
|
lambda [](int id)->void, // void(*)(int id) testSetupFn // dummy fn
|
||||||
|
lambda [](int id)->void, // void(*)(int id) testTeardownFn // dummy fn
|
||||||
|
bool // bool testIsEnabled // true
|
||||||
|
>, // End tuple<...> test //
|
||||||
|
std::allocator< // Begin skipping allocator //
|
||||||
|
std::tuple<
|
||||||
|
const wchar_t *,
|
||||||
|
const wchar_t *,
|
||||||
|
std::tuple<int>,
|
||||||
|
lambda [](std::wstring left, std::wstring right)->bool,
|
||||||
|
lambda [](int id)->void,
|
||||||
|
lambda [](int id)->void,
|
||||||
|
bool
|
||||||
|
>
|
||||||
|
> // End skipping allocator //
|
||||||
|
>, // End vector<...> tests
|
||||||
|
lambda [](std::wstring left, std::wstring right)->bool, // bool(*)() // dummy equals fn
|
||||||
|
lambda [](int id)->void, // void(*)(int id) // dummy fn
|
||||||
|
lambda [](int id)->void, // void(*)(int di) // dummy fn
|
||||||
|
bool // bool suiteIsEnabled // true
|
||||||
|
)
|
||||||
|
|
||||||
|
template<typename TResult, typename FnToTest, typename... TInputParams>
|
||||||
|
test_method_result test_fn(
|
||||||
|
wstring suiteName, // wstring suiteName
|
||||||
|
FnToTest testFn, // FnToTest testName
|
||||||
|
vector< // Begin vector<...> tests
|
||||||
|
tuple< // Begin tuple<...> a test
|
||||||
|
wstring, // wstring testName
|
||||||
|
TResult, // TResult expectedResult
|
||||||
|
tuple<TInputParams...>, // tuple<TInputParams...> inputParams
|
||||||
|
bool(*)(const TResult expected, const TResult actual), // bool(*)(const TResult expected, const TResult actual) testCompareFn
|
||||||
|
void(*)(TInputParams...), // void(*)(TInputParams...) testSetupFn
|
||||||
|
void(*)(TInputParams...), // void(*)(TInputParams...) testTeardownFn
|
||||||
|
bool // bool isTestEnabled
|
||||||
|
> // End tuple<...> a test
|
||||||
|
> tests, // End vector<...> tests
|
||||||
|
bool(*suiteCompareFn)(TResult a, TResult b), // bool(*)(TResult a, TResult b) suiteCompareFn
|
||||||
|
void(*suiteSetupFn)(), // void(*)() suiteSetupFn
|
||||||
|
void(*suiteTeardownFn)(), // void(*)() suiteTeardownFn
|
||||||
|
bool // bool isSuiteEnabled
|
||||||
|
);
|
||||||
|
|
||||||
|
### For SO Post v3
|
||||||
|
### Scratch
|
||||||
|
(
|
||||||
|
const wchar_t [18], // const wchar_t* suiteName // Literal wstring
|
||||||
|
lambda [](int id)->std::wstring, // wstring(*)(int id) testFn // (wstring)(*)(int id) testFn
|
||||||
|
std::vector< // Begin vector<...> tests //
|
||||||
|
std::tuple< // Begin tuple<...> a test //
|
||||||
|
const wchar_t *, // const wchar_t* testName // Literal const wchar_t*
|
||||||
|
const wchar_t *, // const wchar_t* expected // Literal const wchar_t*
|
||||||
|
std::tuple<int>, // tuple<int> inputParams // int id
|
||||||
|
lambda [](std::wstring left, std::wstring right)->bool, // bool(*)(const wstring expected, const wstring actual) compareFn // dummy equals fn
|
||||||
|
lambda [](int id)->void, // void(*)(int id) testSetupFn // dummy fn
|
||||||
|
lambda [](int id)->void, // void(*)(int id) testTeardownFn // dummy fn
|
||||||
|
bool // bool testIsEnabled // true
|
||||||
|
>, // End tuple<...> test //
|
||||||
|
std::allocator<...> // Skipping allocator //
|
||||||
|
>, // End vector<...> tests
|
||||||
|
lambda [](std::wstring left, std::wstring right)->bool, // bool(*)() // dummy equals fn
|
||||||
|
lambda [](int id)->void, // void(*)(int id) // dummy fn
|
||||||
|
lambda [](int id)->void, // void(*)(int di) // dummy fn
|
||||||
|
bool // bool suiteIsEnabled // true
|
||||||
|
)
|
||||||
|
|
||||||
|
template<typename TResult, typename FnToTest, typename... TInputParams>
|
||||||
|
test_method_result test_fn(
|
||||||
|
wstring suiteName, // wstring suiteName
|
||||||
|
FnToTest testFn, // FnToTest testName
|
||||||
|
vector< // Begin vector<...> tests
|
||||||
|
tuple< // Begin tuple<...> a test
|
||||||
|
wstring, // wstring testName
|
||||||
|
TResult, // TResult expectedResult
|
||||||
|
tuple<TInputParams...>, // tuple<TInputParams...> inputParams
|
||||||
|
bool(*)(const TResult expected, const TResult actual), // bool(*)(const TResult expected, const TResult actual) testCompareFn
|
||||||
|
void(*)(TInputParams...), // void(*)(TInputParams...) testSetupFn
|
||||||
|
void(*)(TInputParams...), // void(*)(TInputParams...) testTeardownFn
|
||||||
|
bool // bool isTestEnabled
|
||||||
|
> // End tuple<...> a test
|
||||||
|
> tests, // End vector<...> tests
|
||||||
|
bool(*suiteCompareFn)(TResult a, TResult b), // bool(*)(TResult a, TResult b) suiteCompareFn
|
||||||
|
void(*suiteSetupFn)(), // void(*)() suiteSetupFn
|
||||||
|
void(*suiteTeardownFn)(), // void(*)() suiteTeardownFn
|
||||||
|
bool // bool isSuiteEnabled
|
||||||
|
);
|
||||||
|
|
||||||
|
### For SO Post v4
|
||||||
|
### Scratch
|
||||||
|
(
|
||||||
|
(wstring)const wchar_t [18], // wstring suiteName // Literal wstring
|
||||||
|
lambda [](int id)->std::wstring, // wstring(*)(int id) testFn // (wstring)(*)(int id) testFn
|
||||||
|
std::vector< // Begin vector<...> tests //
|
||||||
|
std::tuple< // Begin tuple<...> a test //
|
||||||
|
const wchar_t *, // const wchar_t* testName // Literal const wchar_t*
|
||||||
|
const wchar_t *, // const wchar_t* expected // Literal const wchar_t*
|
||||||
|
std::tuple<int>, // tuple<int> inputParams // int id
|
||||||
|
lambda [](std::wstring left, std::wstring right)->bool, // bool(*)(const wstring expected, const wstring actual) compareFn // dummy equals fn
|
||||||
|
lambda [](int id)->void, // void(*)(int id) testSetupFn // dummy fn
|
||||||
|
lambda [](int id)->void, // void(*)(int id) testTeardownFn // dummy fn
|
||||||
|
bool // bool testIsEnabled // true
|
||||||
|
>, // End tuple<...> test //
|
||||||
|
std::allocator<...> // Skipping allocator //
|
||||||
|
>, // End vector<...> tests
|
||||||
|
lambda [](std::wstring left, std::wstring right)->bool, // bool(*)() // dummy equals fn
|
||||||
|
lambda [](int id)->void, // void(*)(int id) // dummy fn
|
||||||
|
lambda [](int id)->void, // void(*)(int di) // dummy fn
|
||||||
|
bool // bool suiteIsEnabled // true
|
||||||
|
)
|
||||||
|
|
||||||
|
template<typename TResult, typename FnToTest, typename... TInputParams>
|
||||||
|
test_method_result test_fn(
|
||||||
|
wstring suiteName, // wstring suiteName
|
||||||
|
FnToTest testFn, // FnToTest testName
|
||||||
|
vector< // Begin vector<...> tests
|
||||||
|
tuple< // Begin tuple<...> a test
|
||||||
|
wstring, // wstring testName
|
||||||
|
TResult, // TResult expectedResult
|
||||||
|
tuple<TInputParams...>, // tuple<TInputParams...> inputParams
|
||||||
|
bool(*)(const TResult expected, const TResult actual), // bool(*)(const TResult expected, const TResult actual) testCompareFn
|
||||||
|
void(*)(TInputParams...), // void(*)(TInputParams...) testSetupFn
|
||||||
|
void(*)(TInputParams...), // void(*)(TInputParams...) testTeardownFn
|
||||||
|
bool // bool isTestEnabled
|
||||||
|
> // End tuple<...> a test
|
||||||
|
> tests, // End vector<...> tests
|
||||||
|
bool(*suiteCompareFn)(TResult a, TResult b), // bool(*)(TResult a, TResult b) suiteCompareFn
|
||||||
|
void(*suiteSetupFn)(), // void(*)() suiteSetupFn
|
||||||
|
void(*suiteTeardownFn)(), // void(*)() suiteTeardownFn
|
||||||
|
bool // bool isSuiteEnabled
|
||||||
|
);
|
||||||
|
|
||||||
|
```c++
|
||||||
|
typedef FnTotest wstring(*)(int id);
|
||||||
|
typedef TResult wstring;
|
||||||
|
typedef TInputParams int;
|
||||||
|
(
|
||||||
|
wstring, // wstring suiteName // wstring suiteName // (wstring)L"MyClass::MyMethod"
|
||||||
|
lambda [](int id)->wstring, // wstring(*)(int id) testFn // FnToTest testFn // [](int id){return (wstring)(id==0?L"IS_ZERO":L"IS_NOT_ZERO");}
|
||||||
|
vector< // Begin vector<...> tests // vector< // vector({
|
||||||
|
tuple< // Begin tuple<...> a test // tuple< // make_tuple(
|
||||||
|
basic_string<wchar_t...>, // basic_string<...> testName // wstring testName // (wstring)L"ShouldReturn_IS_ZERO_for_id_0"
|
||||||
|
basic_string<wchar_t...>, // basic_string<...> expectedResult // TResult expectedResult // (wstring)L"IS_ZERO"
|
||||||
|
tuple<int>, // tuple<int> inputParams // tuple<TInputParams...> // make_tuple(0)
|
||||||
|
lambda [](wstring left, wstring right)->bool, // bool(*)(wstring left, wstring right) testCompareFn // bool(*)(const TResult expected, TResult actual) // [](wstring left, wstring right){return left==right;}
|
||||||
|
lambda [](int id)->void, // void(*)(int id) testSetupFn // void(*)(int id) testSetupFn // []()(int id)[] dummy function
|
||||||
|
lambda [](int id)->void, // void(*)(int id) testSetupFn // void(*)(int id) testTeardownFn // []()(int id)[] dummy function
|
||||||
|
bool // bool isTestEnabled // bool isTestEnabled // true
|
||||||
|
>, // End tuple<...> a test // > a test // )
|
||||||
|
allocator<> // Skipping allocator //
|
||||||
|
>, // End vector<...> tests // > tests // })
|
||||||
|
lambda [](wstring left, wstring right)->bool, // bool(*)(wstring left, wstring right) suiteCompareFn // bool(*)(TResult a, TResult b) suiteCompareFn // [](wstring left, wstring right){return left==right;}
|
||||||
|
lambda [](int id)->void, // void(*)(int id) suiteSetupFn // void(*)(int id) suiteSetupFn // [](int id){} dummy function
|
||||||
|
lambda [](int id)->void, // void(*)(int id) suiteTeardownFn // void(*)(int id) suiteTeardownFn // [](int id){} dummy function
|
||||||
|
bool // bool isSuiteEnabled // bool isSuiteEnabled // true
|
||||||
|
)
|
||||||
|
```
|
||||||
|
TResult basic_string<...>, wstring /* const TResult */, wstring
|
||||||
|
|
||||||
|
|
||||||
|
test.cpp(350, 16): argument types are: (wstring, lambda [](int id)->wstring, vector<tuple<basic_string<wchar_t, char_traits<wchar_t>, allocator<wchar_t>>, basic_string<wchar_t, char_traits<wchar_t>, allocator<wchar_t>>, tuple<int>, lambda [](wstring left, wstring right)->bool, lambda [](int id)->void, lambda [](int id)->void, bool>, allocator<tuple<basic_string<wchar_t, char_traits<wchar_t>, allocator<wchar_t>>, basic_string<wchar_t, char_traits<wchar_t>, allocator<wchar_t>>, tuple<int>, lambda [](wstring left, wstring right)->bool, lambda [](int id)->void, lambda [](int id)->void, bool>>>, lambda [](wstring left, wstring right)->bool, lambda [](int id)->void, lambda [](int id)->void, bool)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
instance of constructor "
|
||||||
|
std::__1::vector<_Tp, _Allocator>::vector
|
||||||
|
[with
|
||||||
|
_Tp=std::__1::tuple<
|
||||||
|
std::__1::wstring,
|
||||||
|
std::__1::wstring,
|
||||||
|
std::__1::tuple<
|
||||||
|
const std::__1::wstring &, int
|
||||||
|
>
|
||||||
|
>,
|
||||||
|
_Allocator=std::__1::function<bool (const std::__1::wstring &, const std::__1::wstring &)>
|
||||||
|
]" matches the argument listC/C++(289)
|
||||||
|
test.cpp(667, 13): argument types are: ({...})
|
||||||
|
class std::__1::vector<
|
||||||
|
std::__1::tuple<
|
||||||
|
std::__1::wstring,
|
||||||
|
std::__1::wstring,
|
||||||
|
std::__1::tuple<const std::__1::wstring &, int>
|
||||||
|
>,
|
||||||
|
std::__1::function<bool (const std::__1::wstring &, const std::__1::wstring &)>
|
||||||
|
>
|
||||||
@@ -3,8 +3,8 @@
|
|||||||
using namespace SBF;
|
using namespace SBF;
|
||||||
using namespace Test;
|
using namespace Test;
|
||||||
|
|
||||||
test_method_result main_test_Utils(int argc, char** argv) {
|
TestResults main_test_Utils(int argc, char** argv) {
|
||||||
test_method_result results = std::make_tuple(1, 0);
|
TestResults results;
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
using namespace SBF;
|
using namespace SBF;
|
||||||
using namespace Test;
|
using namespace Test;
|
||||||
|
|
||||||
test_method_result main_test_Virtues(int argc, char** argv) {
|
TestResults main_test_Virtues(int argc, char** argv) {
|
||||||
test_method_result results = std::make_tuple(1, 0);
|
TestResults results;
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|||||||
749
sbf-cpp/test.cpp
749
sbf-cpp/test.cpp
@@ -1,4 +1,4 @@
|
|||||||
#define _XOPEN_SOURCE_EXTENDED
|
#define _XOPEN_SOURCE_EXTENDED
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -7,27 +7,28 @@
|
|||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
|
||||||
// using namespace std;
|
// using namespace std;
|
||||||
using std::wcout;
|
using std::cout;
|
||||||
using std::tuple;
|
using std::tuple;
|
||||||
using std::wcerr;
|
using std::wcerr;
|
||||||
using std::wstring;
|
using std::string;
|
||||||
using std::endl;
|
using std::endl;
|
||||||
using std::pair;
|
using std::pair;
|
||||||
using std::get;
|
using std::get;
|
||||||
using std::make_tuple;
|
using std::make_tuple;
|
||||||
using std::vector;
|
using std::vector;
|
||||||
using Test::test_method_result;
|
using Test::TestResults;
|
||||||
using Test::test_fn;
|
using std::optional;
|
||||||
using Test::operator+;
|
using std::function;
|
||||||
|
using std::for_each;
|
||||||
|
|
||||||
// using namespace Test;
|
// using namespace Test;
|
||||||
|
|
||||||
// size_t get_index_of(const wstring& text, const wstring& search, size_t start);
|
// size_t get_index_of(const string& text, const string& search, size_t start);
|
||||||
// wstring word_wrap(const wstring& text, int maxWidth);
|
// string word_wrap(const string& text, int maxWidth);
|
||||||
// wstring get_substring(const wstring& text, int32_t var1, int32_t var2);
|
// string get_substring(const string& text, int32_t var1, int32_t var2);
|
||||||
// wstring make_fit_l(const wstring& text, size_t length, wchar_t paddCh);
|
// string make_fit_l(const string& text, size_t length, char paddCh);
|
||||||
// wstring left(const wstring& text, size_t length);
|
// string left(const string& text, size_t length);
|
||||||
// wstring string_dollar(size_t length, wchar_t ch);
|
// string string_dollar(size_t length, char ch);
|
||||||
|
|
||||||
// int main(int argc, char* argv[]) {
|
// int main(int argc, char* argv[]) {
|
||||||
// // TODO: Come up with a good way to enable/disable tests.
|
// // TODO: Come up with a good way to enable/disable tests.
|
||||||
@@ -36,56 +37,56 @@ using Test::operator+;
|
|||||||
|
|
||||||
// setlocale(LC_ALL, "");
|
// setlocale(LC_ALL, "");
|
||||||
|
|
||||||
// test_method_result results;
|
// TestResults results;
|
||||||
|
|
||||||
// wstring longText = L"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.";
|
// string longText = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.";
|
||||||
// results = results + Test::test_fn(L"get_index_of", get_index_of,
|
// results = results + Test::test_fn("get_index_of", get_index_of,
|
||||||
// vector<pair<size_t, tuple<wstring, wstring, size_t>>>({
|
// vector<pair<size_t, tuple<string, string, size_t>>>({
|
||||||
// pair(22, make_tuple(longText, L"dummy", 0)),
|
// pair(22, make_tuple(longText, "dummy", 0)),
|
||||||
// pair(-1, make_tuple(longText, L"acid", 0)),
|
// pair(-1, make_tuple(longText, "acid", 0)),
|
||||||
// pair(120, make_tuple(longText, L"dummy", 100)),
|
// pair(120, make_tuple(longText, "dummy", 100)),
|
||||||
// pair(-1, make_tuple(longText, L"dummy", longText.size())),
|
// pair(-1, make_tuple(longText, "dummy", longText.size())),
|
||||||
// pair(6, make_tuple(L"these are words", L"are", 0)),
|
// pair(6, make_tuple("these are words", "are", 0)),
|
||||||
// pair(4, make_tuple(L"one two one two", L"two", 0)),
|
// pair(4, make_tuple("one two one two", "two", 0)),
|
||||||
// pair(12, make_tuple(L"one two one two", L"two", 5)),
|
// pair(12, make_tuple("one two one two", "two", 5)),
|
||||||
// }));
|
// }));
|
||||||
|
|
||||||
// results = results + test_fn(L"get_substring", get_substring, vector({
|
// results = results + test_fn("get_substring", get_substring, vector({
|
||||||
// pair(L"234", make_tuple(L"1234567890", 1, 3)),
|
// pair("234", make_tuple("1234567890", 1, 3)),
|
||||||
// pair(L"Paris", make_tuple(L"Where is Paris?", 10-1, 5)),
|
// pair("Paris", make_tuple("Where is Paris?", 10-1, 5)),
|
||||||
// }));
|
// }));
|
||||||
|
|
||||||
// results = results + test_fn(L"left", left, vector({
|
// results = results + test_fn("left", left, vector({
|
||||||
// pair(L"Micro", make_tuple(L"Microsoft QBasic", 5)),
|
// pair("Micro", make_tuple("Microsoft QBasic", 5)),
|
||||||
// }));
|
// }));
|
||||||
|
|
||||||
// results = results + test_fn(L"make_fit_l", make_fit_l, vector({
|
// results = results + test_fn("make_fit_l", make_fit_l, vector({
|
||||||
// pair(L"12___", make_tuple(L"12", 5, L'_')),
|
// pair("12___", make_tuple("12", 5, L'_')),
|
||||||
// }));
|
// }));
|
||||||
|
|
||||||
// results = results + test_fn(L"string_dollar", string_dollar, vector({
|
// results = results + test_fn("string_dollar", string_dollar, vector({
|
||||||
// pair(L"AAAAA", make_tuple(5, L'A')),
|
// pair("AAAAA", make_tuple(5, L'A')),
|
||||||
// }));
|
// }));
|
||||||
|
|
||||||
// results = results + test_fn(L"word_wrap", word_wrap, vector({
|
// results = results + test_fn("word_wrap", word_wrap, vector({
|
||||||
// pair(L"0123_", make_tuple(L"0123", 5)),
|
// pair("0123_", make_tuple("0123", 5)),
|
||||||
// pair(L"01234", make_tuple(L"01234", 5)),
|
// pair("01234", make_tuple("01234", 5)),
|
||||||
// pair(L"01234\n5____", make_tuple(L"012345", 5)),
|
// pair("01234\n5____", make_tuple("012345", 5)),
|
||||||
// pair(L"01234\n56789\n0____", make_tuple(L"01234567890", 5)),
|
// pair("01234\n56789\n0____", make_tuple("01234567890", 5)),
|
||||||
// pair(L"01 23\n45 67\n89 01", make_tuple(L"01 23 45 67 89 01", 5)),
|
// pair("01 23\n45 67\n89 01", make_tuple("01 23 45 67 89 01", 5)),
|
||||||
// pair(L"01 34\n67 90\n23 56\n89___", make_tuple(L"01 34 67 90 23 56 89 ", 5)),
|
// pair("01 34\n67 90\n23 56\n89___", make_tuple("01 34 67 90 23 56 89 ", 5)),
|
||||||
// }));
|
// }));
|
||||||
|
|
||||||
// wcout << "Total tests ran: " << get<0>(results) << endl;
|
// cout << "Total tests ran: " << get<0>(results) << endl;
|
||||||
// wcout << "Total failures: " << get<1>(results) << endl;
|
// cout << "Total failures: " << get<1>(results) << endl;
|
||||||
|
|
||||||
// return 0;
|
// return 0;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// wstring word_wrap(const wstring& text, int maxWidth) {
|
// string word_wrap(const string& text, int maxWidth) {
|
||||||
// wstring output = L"";
|
// string output = "";
|
||||||
// wstring thisLine = L"";
|
// string thisLine = "";
|
||||||
// wstring nextChunk = L"";
|
// string nextChunk = "";
|
||||||
// int32_t thisLineStartPosition = 0;
|
// int32_t thisLineStartPosition = 0;
|
||||||
// int32_t thisLineCurrentPosition = 0;
|
// int32_t thisLineCurrentPosition = 0;
|
||||||
// int32_t nextSpace = -1;
|
// int32_t nextSpace = -1;
|
||||||
@@ -95,7 +96,7 @@ using Test::operator+;
|
|||||||
// bool done = false;
|
// bool done = false;
|
||||||
|
|
||||||
// while (!done) {
|
// while (!done) {
|
||||||
// nextSpace = get_index_of(text, L" ", thisLineCurrentPosition);
|
// nextSpace = get_index_of(text, " ", thisLineCurrentPosition);
|
||||||
// if (nextSpace < 0) {
|
// if (nextSpace < 0) {
|
||||||
// nextSpace = textLength;
|
// nextSpace = textLength;
|
||||||
// }
|
// }
|
||||||
@@ -104,7 +105,7 @@ using Test::operator+;
|
|||||||
// if (nextChunkLength > 0) {
|
// if (nextChunkLength > 0) {
|
||||||
// auto needsSpace = thisLine.size() > 0;
|
// auto needsSpace = thisLine.size() > 0;
|
||||||
// if (needsSpace) {
|
// if (needsSpace) {
|
||||||
// thisLine = thisLine + L" ";
|
// thisLine = thisLine + " ";
|
||||||
// }
|
// }
|
||||||
// thisLineLength = thisLine.size();
|
// thisLineLength = thisLine.size();
|
||||||
// if (nextChunkLength > maxWidth) {
|
// if (nextChunkLength > maxWidth) {
|
||||||
@@ -127,8 +128,8 @@ using Test::operator+;
|
|||||||
// done = true;
|
// done = true;
|
||||||
// }
|
// }
|
||||||
// thisLine = make_fit_l(thisLine, maxWidth, L'_');
|
// thisLine = make_fit_l(thisLine, maxWidth, L'_');
|
||||||
// output += thisLine + (done ? L"" : L"\n");
|
// output += thisLine + (done ? "" : "\n");
|
||||||
// thisLine = L"";
|
// thisLine = "";
|
||||||
// thisLineLength = thisLine.size();
|
// thisLineLength = thisLine.size();
|
||||||
// thisLineStartPosition = thisLineCurrentPosition;
|
// thisLineStartPosition = thisLineCurrentPosition;
|
||||||
// }
|
// }
|
||||||
@@ -137,65 +138,649 @@ using Test::operator+;
|
|||||||
// return output;
|
// return output;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// wstring string_dollar(size_t length, wchar_t ch) {
|
// string string_dollar(size_t length, char ch) {
|
||||||
// wstring str = L"";
|
// string str = "";
|
||||||
// for (size_t i = 0; i<length; i++) {
|
// for (size_t i = 0; i<length; i++) {
|
||||||
// str += ch;
|
// str += ch;
|
||||||
// }
|
// }
|
||||||
// return str;
|
// return str;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// wstring left(const wstring& text, size_t length) {
|
// string left(const string& text, size_t length) {
|
||||||
// return text.substr(0, length);
|
// return text.substr(0, length);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// wstring make_fit_l(const wstring& text, size_t length, wchar_t paddCh) {
|
// string make_fit_l(const string& text, size_t length, char paddCh) {
|
||||||
// return left(text + string_dollar(length, paddCh), length);
|
// return left(text + string_dollar(length, paddCh), length);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// wstring get_substring(const wstring& text, const int32_t var1, const int32_t var2) {
|
// string get_substring(const string& text, const int32_t var1, const int32_t var2) {
|
||||||
// return text.substr(std::min<int32_t>(var1, text.length()-1), std::max(var2, 0));
|
// return text.substr(std::min<int32_t>(var1, text.length()-1), std::max(var2, 0));
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// size_t get_index_of(const wstring& text, const wstring& search, size_t start) {
|
// size_t get_index_of(const string& text, const string& search, size_t start) {
|
||||||
// return text.find(search, start);
|
// return text.find(search, start);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
namespace Test {
|
namespace Test {
|
||||||
uint32_t do_pass_fail(bool passed) {
|
const string fn1(const string& s, int l) {
|
||||||
if (passed) {
|
return s.substr(0, l);
|
||||||
wcout << "Result: PASS" << endl;
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
wcout << "Result: FAILURE" << endl;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// _Step_1
|
||||||
|
// template<typename _T1, typename F, typename... T2>
|
||||||
|
// TestResults test_fn(string test_name, F f, vector<pair<_T1, tuple<T2...>>> tests);
|
||||||
|
// TestResults dummyTest(){
|
||||||
|
// return test_fn("/Dummy", [](int id){return id==0?"":"Unknown";}, vector({
|
||||||
|
// pair("", make_tuple(0)),
|
||||||
|
// }));
|
||||||
|
// }
|
||||||
|
|
||||||
// Call like this `auto results = test_fn(L"left", left, vector({pair(L"Micro", make_tuple(L"Microsoft QBasic", 5))}));`
|
// _Step_2
|
||||||
template<typename _T1, typename F, typename... T2>
|
// template<typename _T1, typename F, typename... T2>
|
||||||
test_method_result test_fn(wstring testName, F f, vector<pair<_T1, tuple<T2...>>> tests) {
|
// TestResults test_fn(string test_name, F f, vector<tuple<_T1, tuple<T2...>>> tests);
|
||||||
size_t testsRun = 0;
|
// TestResults dummyTest(){
|
||||||
uint32_t failures = 0;
|
// return test_fn("/Dummy", [](int id){return id==0?"":"Unknown";}, vector({
|
||||||
wcout << L"Testing function " << testName << endl;
|
// make_tuple("", make_tuple(0)),
|
||||||
|
// }));
|
||||||
|
// }
|
||||||
|
|
||||||
for_each(tests.begin(), tests.end(), [&testsRun, &failures, testName, &f](pair<_T1, tuple<T2...>> data) {
|
// _Step_3
|
||||||
const auto& expected = data.first;
|
// template<typename TResult, typename FnToTest, typename... TInputParams>
|
||||||
const auto& actual = std::apply(f, data.second);
|
// TestResults test_fn(string suite_label, FnToTest testFn, vector<tuple<TResult, tuple<TInputParams...>>> tests);
|
||||||
testsRun++;
|
// TestResults dummyTest() {
|
||||||
wcout << "Expected: " << expected << endl;
|
// return test_fn("/Dummy", [](int id){return id==0?"":"Unknown";}, vector({
|
||||||
wcout << "Actual: " << actual << endl;
|
// make_tuple("", make_tuple(0)),
|
||||||
failures += do_pass_fail(expected == actual);
|
// }));
|
||||||
if (expected!=actual) {
|
// }
|
||||||
wcerr << testName << L" failed for " << get<0>(data.second) << endl;
|
|
||||||
|
// _Step_4
|
||||||
|
// template<typename TResult, typename FnToTest, typename... TInputParams>
|
||||||
|
// TestResults test_fn(string suite_label, FnToTest testFn, vector<tuple<string, TResult, tuple<TInputParams...>>> tests);
|
||||||
|
// TestResults dummyTest() {
|
||||||
|
// return test_fn("/Dummy", [](int id){return id==0?"":"Unknown";}, vector({
|
||||||
|
// make_tuple((string)"", "", make_tuple(0)),
|
||||||
|
// }));
|
||||||
|
// }
|
||||||
|
|
||||||
|
// _Step_5
|
||||||
|
// auto testFunction = [](int id){return id==0?"":"";};
|
||||||
|
// template<typename TResult, typename FnToTest, typename... TInputParams>
|
||||||
|
// TestResults test_fn(string suite_label, FnToTest testFn, vector<tuple<string, TResult, tuple<TInputParams...>>> tests);
|
||||||
|
// TestResults dummyTest() {
|
||||||
|
// return test_fn("/Dummy", testFunction, vector({
|
||||||
|
// make_tuple((string)"", "", make_tuple(0)),
|
||||||
|
// }));
|
||||||
|
// }
|
||||||
|
|
||||||
|
// _Step_6
|
||||||
|
// auto testFunction = [](int id){return id==0?"":"";};
|
||||||
|
// auto compareFunction = [](string a, string b){return a==b;};
|
||||||
|
// template<typename TResult, typename FnToTest, typename... TInputParams>
|
||||||
|
// TestResults test_fn(
|
||||||
|
// string suite_label,
|
||||||
|
// FnToTest testFn,
|
||||||
|
// bool(*compare_function)(TResult a, TResult b),
|
||||||
|
// vector<tuple<string, TResult, tuple<TInputParams...>>> tests);
|
||||||
|
// TestResults dummyTest() {
|
||||||
|
// return test_fn<string>(
|
||||||
|
// "/Dummy",
|
||||||
|
// testFunction,
|
||||||
|
// compareFunction,
|
||||||
|
// vector({
|
||||||
|
// make_tuple((string)"", (string)"", make_tuple(0)),
|
||||||
|
// }));
|
||||||
|
// }
|
||||||
|
|
||||||
|
// _Step_7
|
||||||
|
// auto testFunction = [](int id){return id==0?"":"";};
|
||||||
|
// auto compareFunction = [](const string a, const string b){return a==b;};
|
||||||
|
// template<typename TResult, typename FnToTest, typename... TInputParams>
|
||||||
|
// TestResults test_fn(
|
||||||
|
// string suite_label,
|
||||||
|
// FnToTest testFn,
|
||||||
|
// bool(*compare_function)(TResult a, TResult b),
|
||||||
|
// vector<tuple<string, bool, TResult, tuple<TInputParams...>>> tests);
|
||||||
|
// TestResults dummyTest() {
|
||||||
|
// // Parse argc/argv and return {0,0} if test is disabled.
|
||||||
|
// return test_fn<string>(
|
||||||
|
// // Suite Name
|
||||||
|
// "/Dummy",
|
||||||
|
// testFunction,
|
||||||
|
// compareFunction,
|
||||||
|
// vector({
|
||||||
|
// // Test Name, Expect Output, Inputs
|
||||||
|
// make_tuple((string)"", true, (string)"", make_tuple(0)),
|
||||||
|
// }));
|
||||||
|
// }
|
||||||
|
|
||||||
|
// _Step_8 - Make compareFunction optional
|
||||||
|
// Test lifecycle
|
||||||
|
// suiteSetupFn(); - This is called to allocate any suite level resources. This is called once when the suite begins.
|
||||||
|
// These functions may be called in parallel but execution will not proceed past this block until they have all finished.
|
||||||
|
// testSetupFn(); - This is called once for every test in tests. You may use it to allocate resources or setup mocks, stubs, and spies.
|
||||||
|
// testFn(...); - This is called once for every test to execute the test.
|
||||||
|
// Only one of these test functions will actually be run for each test in tests. They should return true if the test passed, return false if the test failed or there was an error, and be nullptr if they should be skipped. The executed function will be called with expectedOutput and the result of testFn(...). They can be used to test functions with side effects, especially void functions.
|
||||||
|
// maybe_compare_function; - This is the highest priority compare function. If it is not nullptr then it will be called.
|
||||||
|
// suite_compare_function; - This is the second highest priority compare function. If maybe_compare_function is nullptr and this is not nullptr then it will be called.
|
||||||
|
// [](TResult expected, TResult actual) { return expected, actual; } - This is the lowest priority compare function. If all other compare functions are nullptr then this will be called to evaluate the test.
|
||||||
|
// testTeardownFn(); - This is called once for every test in tests. You must free/release any resources allocated by testSetupFn.
|
||||||
|
// This ends the parallel test functions section all tests will have completed before execution proceeds.
|
||||||
|
// Collect reports - Ths step is not visible to the user at this point, but data returned by all of the test functions is collected here. This is where you will eventually be able to format/log data for reports.
|
||||||
|
// suiteTeardownFn(); - This is called after all test calls have completed, all testTeardownFn calls have completed, and all test reports/logs have been written. You should free any resources allocated in suiteSetupFn.
|
||||||
|
|
||||||
|
// TODO: Add TShared(*)(string /*test_name*/, UUID /*testRunId*/) allocateSharedData to the test tuple to make some shared data that can be used in a thread safe way by setup, teardown, and evaluate steps of the test.
|
||||||
|
// TODO: Add TShared to be returned by the setup functions, and consumed by the evaluate and teardown functions.
|
||||||
|
// Suite setup/teardown functions should allocate/free.
|
||||||
|
// Test setup/teardown functions should consume the data allocated by Suite setup.
|
||||||
|
// Test setup functions may allocate additional resources. If they do then the allocated resources they should be freed by test teardown function.
|
||||||
|
// Suite and/or Test compare functions may consume this shared data, but it will not be shared with the execution of testFn.
|
||||||
|
|
||||||
|
// This function is called to execute a test suite. You provide it with some configuration info, optional utility callback functions, and test data (input parameters for each call to testFn and the expected result). It returns a TestResults that should be treated as an opaque data type.
|
||||||
|
// Not all parameters are named in code, but they are named and explained in the comments and will be described by those names below.
|
||||||
|
// string suite_label - This is the name of this test suite. It is used for reporting messages.
|
||||||
|
// FnToTest testFn - This is the function to test. This may be replaced if necessary by function. It may not currently support class methods, but that is planned.
|
||||||
|
// vector<tuple<...>> tests - This is the test run data. Each tuple in the vector is a single test run. It's members are explained below.
|
||||||
|
// string test_name - This is the name of this test. It is used for reporting messages.
|
||||||
|
// TResult expectedOutput - This is the expected result of executing this test.
|
||||||
|
// bool(*)(const TResult expected, const TResult actual) maybe_compare_function - This is optional. If unset or set to nullptr it is skipped. If set to a function it is called to evaluate the test results. It takes the expected and actual results as parameters and should return true if the test passed and false otherwise. This may be changed to return a TestResults at some point.
|
||||||
|
// void(*)(TInputParams...) testSetupFn - This is optional. If unset or set to nullptr it is skipped. If set to a function it is called before each test to setup the environment for the test. You may use it to allocate resources and setup mocks, stubs, and spies.
|
||||||
|
// void(*)(TInputParams...) testTeardownFn - This is optiona. If unset or set to nullptr it is skipped. If set to a function it is called after each test to cleanup the environment after the test. You should free resources allocated by testSetupFn.
|
||||||
|
// bool isEnabled - This is optional. If unset or set to true the test is run. If set to false this test is skipped. If skipped it will be reported as a skipped/disabled test.
|
||||||
|
// bool(*)(const TResult expected, const TResult actual) suite_compare_function - This is optional. If unset or set to nullptr it is skipped. If set to a function and maybe_compare_function is not called for a test run then this function is called to evaluate the test results. It takes the expected and actual results as parameters and should return true if the test passed and false otherwise. This may be changed to return a TestResults at some point.
|
||||||
|
// void(*)() suiteSetupFn - This is optional. If unset or set to nullptr it is skipped. If set to a function it is called before starting this test suite to setup the environment. You may use it to allocate resources and setup mocks, stubs, and spies.
|
||||||
|
// void(*)() suiteTeardownFn - This is optional. If unset or set to nullptr it is skipped. If set to a function it is called after all tests in this suite have finished and all reporting has finished. You should free resources allocated by suiteSetupFn.
|
||||||
|
// This method should be called like so. This is the minimal call and omits all of the optional params. This is the most common usage. You should put one tuple of inputs and expected output for each test case.
|
||||||
|
// results = collect_and_report_TestResultstest_fn(
|
||||||
|
// "Test: functionUnderTest",
|
||||||
|
// functionUnderTest,
|
||||||
|
// vector({
|
||||||
|
// make_tuple(
|
||||||
|
// "ShouldReturnAppleForGroupId_1_and_ItemId_2",
|
||||||
|
// string("Apple"),
|
||||||
|
// make_tuple(1,2),
|
||||||
|
// ),
|
||||||
|
// }),
|
||||||
|
// );
|
||||||
|
// The suites can be run from one file as such. From a file called ThingDoer_test.cpp to test the class/methods ThingDoer declared in ThingDoer.cpp. This isn't mandatory but is a best practice.
|
||||||
|
// You can use testFn without calling collect_and_report_TestResults() and also could call it from a normal int main(int argc, char** argv) or other function.
|
||||||
|
// TestResults test_main_ThingDoer(int argc, char** argv) {
|
||||||
|
// TestResults results;
|
||||||
|
// results = collect_and_report_TestResults(results, testFn("doThing1", ...), argc, argv);
|
||||||
|
// results = collect_and_report_TestResults(results, testFn("doThing2", ...), argc, argv);
|
||||||
|
// return results;
|
||||||
|
// }
|
||||||
|
// Then some test harness either generated or explicit can call test_main_ThingDoer(...) and optionally reported there. Reporting granularity is controlled by how frequently you call collect_and_report_TestResults(...).
|
||||||
|
// You can combine test results with results = results + testFn(..); and then collect_and_report_TestResults on the aggregate TestResults value.
|
||||||
|
// template<typename TResult, typename FnToTest, typename... TInputParams>
|
||||||
|
// TestResults test_fn(
|
||||||
|
// string suite_label, /* suite_label - This is the name of the test suite. It will be used in logs. */
|
||||||
|
// FnToTest testFn, /* testFn - This is the function to be tested. It will be called with std::apply and the inputParams from each test in tests below. */
|
||||||
|
// vector<
|
||||||
|
// tuple<
|
||||||
|
// string /* test_name */,
|
||||||
|
// TResult /* expectedOutput */,
|
||||||
|
// tuple<TInputParams...> /* inputParams - The input parameters for this test. These will be used when calling std::apply with testFn to execute the test. */,
|
||||||
|
// bool(*)(const TResult expected, const TResult actual) /* maybe_compare_function - If this is not nullprt then this function will be called instead of suite_compare_function to determine if the test passes. Use this to check for side effects of the test. Return true if the test passes and false otherwise. */,
|
||||||
|
// void(*)(TInputParams...) /* testSetupFn - If this is not nullptr this function is called before each test to setup the environment. It is called with std::apply and inputParams so you can use them to mock records with specific IDs or calculate an expected result. */,
|
||||||
|
// void(*)(TInputParams...) /* testTeardownFn - If this is not nullptr this function is called after each test to cleanup any allocated/shared resources. */,
|
||||||
|
// bool /* testIsEnabled - If this is false the test, setup, and teardown functions are not run. */
|
||||||
|
// > /* <no name> - This is the data and config functions for a specific test run. */
|
||||||
|
// > tests, /* tests - Each tuple in the vector is a test run with a name, enabledStatus, input, expected output, and optional compare, setup, and teardown functions. */
|
||||||
|
// bool(*suite_compare_function)(const TResult expected, const TResult actual) /* suite_compare_function used to compare*/,
|
||||||
|
// void(*suiteSetupFn)() /* suiteSetupFn called before running the test suite */,
|
||||||
|
// void(*suiteTeardownFn)() /* suiteTeardownFn called after all tests have run */,
|
||||||
|
// bool /* suiteIsEnabled - If this is false the entire test suite is skipped. The skipped tests will be reported as skipped/disabled. */
|
||||||
|
// ) {
|
||||||
|
// return {0,0};
|
||||||
|
// };
|
||||||
|
// auto testFunction = [](int id){return (string)(id==0?"IS_ZERO":"IS_NOT_ZERO");};
|
||||||
|
// auto compareFunction = [](const string a, const string b){return a==b;};
|
||||||
|
// auto evaluateFunction = [](const string expected, const string actual){return expected==actual;};
|
||||||
|
// auto suiteSetupFunction = [](){};
|
||||||
|
// auto suiteTeardownFunction = [](){};
|
||||||
|
// auto testSetupFunction = [](){};
|
||||||
|
// auto testTeardownFunction = [](){};
|
||||||
|
// TestResults doTestSuite() {
|
||||||
|
// return test_fn<string, string(*)(int), int>(
|
||||||
|
// (string)string("MyClass::MyMethod"),
|
||||||
|
// [](int id){return (string)string(id==0?"IS_ZERO":"IS_NOT_ZERO");},
|
||||||
|
// vector({
|
||||||
|
// make_tuple(
|
||||||
|
// (string)string("ShouldReturn_IS_ZERO_for_id_0"),
|
||||||
|
// (string)string("IS_ZERO"),
|
||||||
|
// make_tuple(0),
|
||||||
|
// [](const string left, const string right){return (bool)(left==right);},
|
||||||
|
// [](int id){},
|
||||||
|
// [](int id){},
|
||||||
|
// true
|
||||||
|
// )
|
||||||
|
// }),
|
||||||
|
// [](const string left, const string right){return left==right;},
|
||||||
|
// [](int id){},
|
||||||
|
// [](int id){},
|
||||||
|
// true
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
||||||
|
// template<typename TResult, typename TFunctionToTest, typename... TInputParams>
|
||||||
|
// TestResults test_fn(
|
||||||
|
// string suite_name,
|
||||||
|
// TFunctionToTest test_function,
|
||||||
|
// vector<
|
||||||
|
// TestTuple<TResult, TInputParams...> /* <no name> - This is the data and config functions for a specific test run. */
|
||||||
|
// > tests,
|
||||||
|
// MaybeTestCompareFunction<TResult> suite_compare_function,
|
||||||
|
// MaybeTestConfigureFunction suite_before_each,
|
||||||
|
// MaybeTestConfigureFunction suite_after_each,
|
||||||
|
// bool is_enabled
|
||||||
|
// );
|
||||||
|
|
||||||
|
template <typename TResult, typename... TInputParams>
|
||||||
|
TestResults execute_suite(
|
||||||
|
string suite_label,
|
||||||
|
function<TResult(TInputParams...)> function_to_test,
|
||||||
|
vector<TestTuple<TResult, TInputParams...>> tests,
|
||||||
|
MaybeTestCompareFunction<TResult> maybe_suite_compare_function,
|
||||||
|
MaybeTestConfigureFunction maybe_suite_before_each_function,
|
||||||
|
MaybeTestConfigureFunction maybe_suite_after_each_function,
|
||||||
|
bool is_enabled) {
|
||||||
|
TestResults results;
|
||||||
|
cout << "🚀 Beginning Suite: " << suite_label << endl;
|
||||||
|
|
||||||
|
// Step 1: Suite Setup
|
||||||
|
|
||||||
|
if (maybe_suite_before_each_function.has_value()) {
|
||||||
|
(*maybe_suite_before_each_function)();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 2: Execute Tests
|
||||||
|
for_each(tests.begin(), tests.end(), [&suite_label, &function_to_test, &results, &maybe_suite_compare_function](
|
||||||
|
TestTuple<TResult, TInputParams...> test_data
|
||||||
|
) {
|
||||||
|
// Step 2a: Extract our variables from the TestTuple.
|
||||||
|
const std::string& test_name = get<0>(test_data);
|
||||||
|
const std::string qualified_test_name = suite_label + "::" + test_name;
|
||||||
|
const TResult& expected_output = get<1>(test_data);
|
||||||
|
std::tuple<TInputParams...> input_params = get<2>(test_data);
|
||||||
|
MaybeTestCompareFunction<TResult> maybe_compare_function = get<3>(test_data);
|
||||||
|
TestCompareFunction<TResult> compare_function = maybe_compare_function.has_value()
|
||||||
|
? *maybe_compare_function
|
||||||
|
: maybe_suite_compare_function.has_value()
|
||||||
|
? *maybe_suite_compare_function
|
||||||
|
: [](const TResult& l, const TResult& r){return l==r;};
|
||||||
|
MaybeTestConfigureFunction before_each = get<4>(test_data);
|
||||||
|
MaybeTestConfigureFunction after_each = get<5>(test_data);
|
||||||
|
|
||||||
|
// Step 2b: Test Setup
|
||||||
|
cout << " Beginning Test: " << qualified_test_name << endl;
|
||||||
|
if(before_each.has_value()) {
|
||||||
|
(*before_each)();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TResult actual;
|
||||||
|
try {
|
||||||
|
// Step 2c: Execute the test method.
|
||||||
|
actual = std::apply(function_to_test, input_params);
|
||||||
|
} catch(const std::exception& ex) {
|
||||||
|
cout << " ERROR: Caught exception \"" << ex.what() << "\"" << endl;
|
||||||
|
} catch(const std::string& message) {
|
||||||
|
cout << " ERROR: Caught string \"" << message << "\"" << endl;
|
||||||
|
} catch(...) {
|
||||||
|
cout << " ERROR: Caught something that is neither an std::exception nor a std::string." << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 2d: Pass or fail.
|
||||||
|
TestResults result;
|
||||||
|
if (compare_function(expected_output, actual)) {
|
||||||
|
result = TestResults().pass();
|
||||||
|
cout << " PASSED" << endl;
|
||||||
|
} else {
|
||||||
|
result = TestResults().fail();
|
||||||
|
cout << " FAILED: expected: " << expected_output << ", actual: " << actual << endl;
|
||||||
|
}
|
||||||
|
results += result;
|
||||||
|
|
||||||
|
// Step 2e: Test Teardown
|
||||||
|
if (after_each.has_value()) {
|
||||||
|
(*after_each)();
|
||||||
|
}
|
||||||
|
cout << " Ending Test: " << test_name << endl;
|
||||||
});
|
});
|
||||||
|
|
||||||
wcout << failures << L" failures" << endl;
|
// Step 3: Suite Teardown
|
||||||
return make_tuple(testsRun, failures);
|
if (maybe_suite_after_each_function.has_value()) {
|
||||||
|
(*maybe_suite_after_each_function)();
|
||||||
|
}
|
||||||
|
cout << "Ending Suite: " << suite_label << endl;
|
||||||
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
test_method_result operator+(const test_method_result& first, const test_method_result second) {
|
|
||||||
return make_tuple(get<0>(first) + get<0>(second), get<1>(first) + get<1>(second));
|
|
||||||
|
// auto test_data9 = vector<tuple<
|
||||||
|
// string, string, tuple<const string&, int>,
|
||||||
|
// function<bool(const string&, const string&)>,
|
||||||
|
// function<void(const string&, int)>,
|
||||||
|
// function<void(const string&, int)>,
|
||||||
|
// bool
|
||||||
|
// >>({
|
||||||
|
|
||||||
|
// });
|
||||||
|
// test_fn_9<string, const string&, int>(
|
||||||
|
// "",
|
||||||
|
// (function<string(const string&, int)>)fn1,
|
||||||
|
// test_data9
|
||||||
|
// );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// string /* test_name */,
|
||||||
|
// TResult /* expectedOutput */,
|
||||||
|
// tuple<TInputParams...> /* inputParams - The input parameters for this test. These will be used when calling std::apply with testFn to execute the test. */,
|
||||||
|
// bool(*)(const TResult expected, const TResult actual) /* maybe_compare_function - If this is not nullprt then this function will be called instead of suite_compare_function to determine if the test passes. Use this to check for side effects of the test. Return true if the test passes and false otherwise. */,
|
||||||
|
// void(*)(TInputParams...) /* testSetupFn - If this is not nullptr this function is called before each test to setup the environment. It is called with std::apply and inputParams so you can use them to mock records with specific IDs or calculate an expected result. */,
|
||||||
|
// void(*)(TInputParams...) /* testTeardownFn - If this is not nullptr this function is called after each test to cleanup any allocated/shared resources. */,
|
||||||
|
// bool /* testIsEnabled - If this is false the test, setup, and teardown functions are not run. */
|
||||||
|
|
||||||
|
//char pc3(function<bool(TInputParams...)> compare_function, TInputParams... input_params) {
|
||||||
|
|
||||||
|
// template<typename T>
|
||||||
|
// typedef function<bool(const T&, const T&)> compare_function2;
|
||||||
|
|
||||||
|
TestResults do_the_other_thing(){
|
||||||
|
auto p1 = "Microsoft QBasic";
|
||||||
|
auto p2 = 5;
|
||||||
|
// auto exp = "Micro";
|
||||||
|
string s = fn1("Microsoft QBasic", 5);
|
||||||
|
TestResults tr;
|
||||||
|
|
||||||
|
// tr = tr + execute_suite<string, const string&, int>(
|
||||||
|
// "Test 8 Function",
|
||||||
|
// (function<string(const string&, int)>)fn1,
|
||||||
|
// vector<TestTuple<string, const string&, int>>({
|
||||||
|
// // vector<tuple<string, string, tuple<const string&, int>, MaybeTestCompareFunction<string>>>({
|
||||||
|
// make_tuple(
|
||||||
|
// string("should do something"), // test_name
|
||||||
|
// string("Micro"), // expectedOutput
|
||||||
|
// make_tuple((string)p1, p2),// inputParams,
|
||||||
|
// std::nullopt, // compare_function
|
||||||
|
// std::nullopt, // before_each
|
||||||
|
// std::nullopt, // after_each
|
||||||
|
// true
|
||||||
|
// ),
|
||||||
|
// make_test<string, string, int>(
|
||||||
|
// "should do something else",
|
||||||
|
// "Micro",
|
||||||
|
// make_tuple((string)p1, p2)
|
||||||
|
// )
|
||||||
|
// }));
|
||||||
|
|
||||||
|
auto test_data8 = vector<TestTuple<string, const string&, int>>({
|
||||||
|
make_test<string, string, int>(
|
||||||
|
"Test 8 equals", "Micro", make_tuple((string)p1, p2),
|
||||||
|
[](const string& l, const string& r){ return l==r;}),
|
||||||
|
make_test<string, string, int>(
|
||||||
|
"Test 8 not equals", "Micro", make_tuple((string)p1, p2),
|
||||||
|
[](const string& l, const string& r){ return l!=r;}
|
||||||
|
),
|
||||||
|
make_test<string, string, int>("Test 8 default compare", "Micro", make_tuple((string)p1, p2)),
|
||||||
|
make_test<string, string, int>("Test 8 default compare", "Micro", make_tuple((string)p1, p2)),
|
||||||
|
make_test<string, string, int>("Test 8 default compare", "Micro", make_tuple((string)p1, p2))
|
||||||
|
});
|
||||||
|
tr = tr + execute_suite<string, const string&, int>(
|
||||||
|
"Test 8 Function with extra data",
|
||||||
|
(function<string(const string&, int)>)fn1,
|
||||||
|
test_data8
|
||||||
|
);
|
||||||
|
|
||||||
|
return tr;
|
||||||
|
}
|
||||||
|
// void(*)(TInputParams...) /* testSetupFn - If this is not nullptr this function is called before each test to setup the environment. It is called with std::apply and inputParams so you can use them to mock records with specific IDs or calculate an expected result. */,
|
||||||
|
// void(*)(TInputParams...) /* testTeardownFn - If this is not nullptr this function is called after each test to cleanup any allocated/shared resources. */,
|
||||||
|
// bool /* testIsEnabled - If this is false the test, setup, and teardown functions are not run. */
|
||||||
|
|
||||||
|
// bool(*suite_compare_function)(const TResult expected, const TResult actual) /* suite_compare_function used to compare*/,
|
||||||
|
// void(*suiteSetupFn)() /* suiteSetupFn called before running the test suite */,
|
||||||
|
// void(*suiteTeardownFn)() /* suiteTeardownFn called after all tests have run */,
|
||||||
|
// bool /* suiteIsEnabled - If this is false the entire test suite is skipped. The skipped tests will be reported as skipped/disabled. */
|
||||||
|
|
||||||
|
|
||||||
|
// template<typename TResult, typename... TInputParams>
|
||||||
|
// TestResults test_fn(
|
||||||
|
// string suite_label, /* suite_label - This is the name of the test suite. It will be used in logs. */
|
||||||
|
// function<TResult(TInputParams...)> testFn, /* testFn - This is the function to be tested. It will be called with std::apply and the inputParams from each test in tests below. */
|
||||||
|
// vector<
|
||||||
|
// tuple<
|
||||||
|
// string /* test_name */,
|
||||||
|
// TResult /* expectedOutput */,
|
||||||
|
// tuple<TInputParams...> /* inputParams - The input parameters for this test. These will be used when calling std::apply with testFn to execute the test. */,
|
||||||
|
// bool(*)(const TResult expected, const TResult actual) /* maybe_compare_function - If this is not nullprt then this function will be called instead of suite_compare_function to determine if the test passes. Use this to check for side effects of the test. Return true if the test passes and false otherwise. */,
|
||||||
|
// void(*)(TInputParams...) /* testSetupFn - If this is not nullptr this function is called before each test to setup the environment. It is called with std::apply and inputParams so you can use them to mock records with specific IDs or calculate an expected result. */,
|
||||||
|
// void(*)(TInputParams...) /* testTeardownFn - If this is not nullptr this function is called after each test to cleanup any allocated/shared resources. */,
|
||||||
|
// bool /* testIsEnabled - If this is false the test, setup, and teardown functions are not run. */
|
||||||
|
// > /* <no name> - This is the data and config functions for a specific test run. */
|
||||||
|
// > tests, /* tests - Each tuple in the vector is a test run with a name, enabledStatus, input, expected output, and optional compare, setup, and teardown functions. */
|
||||||
|
// bool(*suite_compare_function)(const TResult expected, const TResult actual) /* suite_compare_function used to compare*/,
|
||||||
|
// void(*suiteSetupFn)() /* suiteSetupFn called before running the test suite */,
|
||||||
|
// void(*suiteTeardownFn)() /* suiteTeardownFn called after all tests have run */,
|
||||||
|
// bool /* suiteIsEnabled - If this is false the entire test suite is skipped. The skipped tests will be reported as skipped/disabled. */
|
||||||
|
// ) {
|
||||||
|
// return {0,0};
|
||||||
|
// };
|
||||||
|
// auto testFunction = [](int id){return (string)(id==0?"IS_ZERO":"IS_NOT_ZERO");};
|
||||||
|
// auto compareFunction = [](const string a, const string b){return a==b;};
|
||||||
|
// auto evaluateFunction = [](const string expected, const string actual){return expected==actual;};
|
||||||
|
// auto suiteSetupFunction = [](){};
|
||||||
|
// auto suiteTeardownFunction = [](){};
|
||||||
|
// auto testSetupFunction = [](){};
|
||||||
|
// auto testTeardownFunction = [](){};
|
||||||
|
// TestResults doTestSuite() {
|
||||||
|
// return test_fn<string, string(*)(int), int>(
|
||||||
|
// (string)string("MyClass::MyMethod"),
|
||||||
|
// [](int id){return (string)string(id==0?"IS_ZERO":"IS_NOT_ZERO");},
|
||||||
|
// vector({
|
||||||
|
// make_tuple(
|
||||||
|
// (string)string("ShouldReturn_IS_ZERO_for_id_0"),
|
||||||
|
// (string)string("IS_ZERO"),
|
||||||
|
// make_tuple(0),
|
||||||
|
// [](const string left, const string right){return (bool)(left==right);},
|
||||||
|
// [](int id){},
|
||||||
|
// [](int id){},
|
||||||
|
// true
|
||||||
|
// )
|
||||||
|
// }),
|
||||||
|
// [](const string left, const string right){return left==right;},
|
||||||
|
// [](int id){},
|
||||||
|
// [](int id){},
|
||||||
|
// true
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// TestResults dummyTest() {
|
||||||
|
// // Parse argc/argv and return {0,0} if test is disabled.
|
||||||
|
// return test_fn<string>(
|
||||||
|
// // Suite Name
|
||||||
|
// "/Dummy",
|
||||||
|
// testFunction,
|
||||||
|
// vector({
|
||||||
|
// // Test Name, Expect Output, Inputs
|
||||||
|
// make_tuple((string)"", (string)"", make_tuple(0)),
|
||||||
|
// }),
|
||||||
|
// compareFunction
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
||||||
|
// test_fn(
|
||||||
|
// "Suite Name",
|
||||||
|
// [](){}, // test fn
|
||||||
|
// vector({
|
||||||
|
// make_tuple(
|
||||||
|
// "Test Name",
|
||||||
|
// "Expected Result", // TODO: find a way for this to work with void fn tests
|
||||||
|
// [](string expected, string actual){return true;} // Evaluate fn nullptr allowed and default
|
||||||
|
// [](){}, // Suite setup fn nullptr allowed and default
|
||||||
|
// [](){}, // Suite teardown fn nullptr allowed and default
|
||||||
|
// make_tuple(), // Input params
|
||||||
|
// ),
|
||||||
|
// }),
|
||||||
|
// [](string a, string b) {return a==b;},// compare fn nullptr allowed and default
|
||||||
|
// [](){}, // Suite setup fn nullprt allowed and default
|
||||||
|
// [](){}, // Suite teardown fn nullptr allowed and default
|
||||||
|
// )
|
||||||
|
|
||||||
|
// _Step_9 - if T2 is a single value then make_tuple<T2>(T2) and call longer version
|
||||||
|
// auto testFunction = [](int id){return id==0?"":"";};
|
||||||
|
// auto compareFunction = [](const string a, const string b){return a==b;};
|
||||||
|
// template<typename TResult, typename FnToTest, typename... TInputParams>
|
||||||
|
// TestResults test_fn(
|
||||||
|
// string suite_label,
|
||||||
|
// FnToTest testFn,
|
||||||
|
// vector<tuple<string, bool, TResult, tuple<TInputParams...>>> tests,
|
||||||
|
// bool(*compare_function)(TResult a, TResult b));
|
||||||
|
// TestResults dummyTest() {
|
||||||
|
// // Parse argc/argv and return {0,0} if test is disabled.
|
||||||
|
// return test_fn<string>(
|
||||||
|
// // Suite Name
|
||||||
|
// "/Dummy",
|
||||||
|
// testFunction,
|
||||||
|
// vector({
|
||||||
|
// // Test Name, Expect Output, Inputs
|
||||||
|
// make_tuple((string)"", true, (string)"", make_tuple(0)),
|
||||||
|
// }),
|
||||||
|
// compareFunction
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
||||||
|
// _Step_10 -
|
||||||
|
|
||||||
|
// test_fn(string, _FnToTest, vector<tuple<string, _T1, _CompareFn, <tuple<_T2...>>>)
|
||||||
|
// Default to (string, _FnToTest, vector<tuple<"", _T1, [](a,b){return a==b;}, make_tuple())
|
||||||
|
// Also allow make_tuple(T2) if the last param is not a tuple.
|
||||||
|
//bool(*compare_function)(_TResult, _TResult)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// return test_fn(
|
||||||
|
// "/Dummy",
|
||||||
|
// [](int id){ if (id==0) {return "";} return "Unknown";},
|
||||||
|
// [](string a, string b){ return a == b; },
|
||||||
|
// vector({
|
||||||
|
// make_tuple("ShouldReturnEmptyStringForIdZero", "", make_tuple(0))
|
||||||
|
// })
|
||||||
|
// );
|
||||||
|
// return test_fn(
|
||||||
|
// "/Dummy",
|
||||||
|
// [](int id){ if (id==0) {return "";} return "Unknown";},
|
||||||
|
// [](string a, string b){ return a == b; },
|
||||||
|
// vector({
|
||||||
|
// make_tuple("ShouldReturnEmptyStringForIdZero", "", make_tuple(0))
|
||||||
|
// })
|
||||||
|
// );
|
||||||
|
// return test_fn(
|
||||||
|
// "/Dummy",
|
||||||
|
// [](){},
|
||||||
|
// [](string a, string b){ return a == b; },
|
||||||
|
// vector({
|
||||||
|
// make_tuple("ShouldReturnEmptyStringForIdZero", "", make_tuple(0))
|
||||||
|
// })
|
||||||
|
// );
|
||||||
|
|
||||||
|
|
||||||
|
// Call like this `auto results = test_fn("left", left, vector({pair("Micro", make_tuple("Microsoft QBasic", 5))}));`
|
||||||
|
// template<typename _T1, typename F, typename... T2>
|
||||||
|
// TestResults test_fn(string test_name, F f, vector<pair<_T1, tuple<T2...>>> tests) {
|
||||||
|
// size_t testsRun = 0;
|
||||||
|
// uint32_t failures = 0;
|
||||||
|
// cout << "Testing function " << test_name << endl;
|
||||||
|
|
||||||
|
// for_each(tests.begin(), tests.end(), [&testsRun, &failures, test_name, &f](pair<_T1, tuple<T2...>> data) {
|
||||||
|
// const auto& expected = data.first;
|
||||||
|
// const auto& actual = std::apply(f, data.second);
|
||||||
|
// testsRun++;
|
||||||
|
// cout << "Expected: " << expected << endl;
|
||||||
|
// cout << "Actual: " << actual << endl;
|
||||||
|
// failures += do_pass_fail(expected == actual);
|
||||||
|
// if (expected!=actual) {
|
||||||
|
// wcerr << test_name << " failed for " << get<0>(data.second) << endl;
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
|
// cout << failures << " failures" << endl;
|
||||||
|
// return make_tuple(testsRun, failures);
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
TestResults::TestResults()
|
||||||
|
: failed_(0)
|
||||||
|
, passed_(0)
|
||||||
|
, skipped_(0)
|
||||||
|
, total_(0) {}
|
||||||
|
|
||||||
|
TestResults::TestResults(const TestResults& other)
|
||||||
|
: failed_(other.failed_)
|
||||||
|
, passed_(other.passed_)
|
||||||
|
, skipped_(other.skipped_)
|
||||||
|
, total_(other.total_) {}
|
||||||
|
|
||||||
|
TestResults::TestResults(uint32_t failed, uint32_t passed, uint32_t skipped, uint32_t total)
|
||||||
|
: failed_(failed)
|
||||||
|
, passed_(passed)
|
||||||
|
, skipped_(skipped)
|
||||||
|
, total_(total) {}
|
||||||
|
|
||||||
|
TestResults& TestResults::fail() {
|
||||||
|
total_++;
|
||||||
|
failed_++;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
TestResults& TestResults::pass() {
|
||||||
|
total_++;
|
||||||
|
passed_++;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
TestResults& TestResults::skip() {
|
||||||
|
total_++;
|
||||||
|
skipped_++;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t TestResults::failed() {
|
||||||
|
return failed_;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t TestResults::passed() {
|
||||||
|
return passed_;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t TestResults::skipped() {
|
||||||
|
return skipped_;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t TestResults::total() {
|
||||||
|
return total_;
|
||||||
|
}
|
||||||
|
|
||||||
|
TestResults TestResults::operator+(const TestResults& other) const {
|
||||||
|
return TestResults(
|
||||||
|
failed_ + other.failed_,
|
||||||
|
passed_ + other.passed_,
|
||||||
|
skipped_ + other.skipped_,
|
||||||
|
total_ + other.total_);
|
||||||
|
}
|
||||||
|
|
||||||
|
TestResults& TestResults::operator+=(const TestResults& other) {
|
||||||
|
failed_ += other.failed_;
|
||||||
|
passed_ += other.passed_;
|
||||||
|
skipped_ += other.skipped_;
|
||||||
|
total_ += other.total_;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
} // End namespace Test
|
} // End namespace Test
|
||||||
|
|||||||
267
sbf-cpp/test.h
267
sbf-cpp/test.h
@@ -5,20 +5,269 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
// Test lifecycle
|
||||||
|
// suite_setup_function(); - This is called to allocate any suite level resources. This is called once when the suite begins.
|
||||||
|
// These functions may be called in parallel but execution will not proceed past this block until they have all finished.
|
||||||
|
// test_setup_function(); - This is called once for every test in tests. You may use it to allocate resources or setup mocks, stubs, and spies.
|
||||||
|
// function_to_test(...); - This is called once for every test to execute the test.
|
||||||
|
// Only one of these test functions will actually be run for each test in tests. They should return true if the test passed, return false if the test failed or there was an error, and be nullptr if they should be skipped. The executed function will be called with expected_output and the result of function_to_test(...). They can be used to test functions with side effects, especially void functions.
|
||||||
|
// test_compare_function; - This is the highest priority compare function. If it is not nullptr then it will be called.
|
||||||
|
// suite_compare_function; - This is the second highest priority compare function. If test_compare_function is nullptr and this is not nullptr then it will be called.
|
||||||
|
// [](TResult expected, TResult actual) { return expected, actual; } - This is the lowest priority compare function. If all other compare functions are nullptr then this will be called to evaluate the test.
|
||||||
|
// test_teardown_function(); - This is called once for every test in tests. You must free/release any resources allocated by test_setup_function.
|
||||||
|
// This ends the parallel test functions section all tests will have completed before execution proceeds.
|
||||||
|
// Collect reports - Ths step is not visible to the user at this point, but data returned by all of the test functions is collected here. This is where you will eventually be able to format/log data for reports.
|
||||||
|
// suite_teardown_function(); - This is called after all test calls have completed, all test_teardown_function calls have completed, and all test reports/logs have been written. You should free any resources allocated in suite_setup_function.
|
||||||
|
|
||||||
namespace Test {
|
namespace Test {
|
||||||
using std::tuple;
|
using std::tuple;
|
||||||
using std::pair;
|
using std::pair;
|
||||||
using std::vector;
|
using std::vector;
|
||||||
using std::wstring;
|
using std::string;
|
||||||
|
|
||||||
typedef tuple<size_t, uint32_t> test_method_result;
|
/// @brief
|
||||||
|
class TestResults {
|
||||||
|
public:
|
||||||
|
/// @brief Creates an empty TestResults instance representing no tests run.
|
||||||
|
TestResults();
|
||||||
|
|
||||||
void do_pass_fail(bool passed, uint32_t& failureCount);
|
/// @brief Creates a new TestResults instance that is a copy of other.
|
||||||
uint32_t do_pass_fail(bool passed);
|
/// @param other
|
||||||
template<typename _T1, typename F, typename... T2>
|
TestResults(const TestResults& other);
|
||||||
test_method_result test_fn(wstring testName, F f, vector<pair<_T1, tuple<T2...>>> tests);
|
|
||||||
test_method_result operator+(const test_method_result& first, const test_method_result second);
|
/// @brief Creates a new TestResults instance with specific counts.
|
||||||
// TODO: define operator<< for std::tuple
|
/// @param failed The number of failed tests.
|
||||||
// TODO: Define operator+= for test_method_result
|
/// @param passed The number of passed tests.
|
||||||
|
/// @param skipped The number of skipped tests.
|
||||||
|
/// @param total The total number of tests run. This should equal the sum of failed, passed, and skipped tests.
|
||||||
|
TestResults(uint32_t failed, uint32_t passed, uint32_t skipped, uint32_t total);
|
||||||
|
|
||||||
|
/// @brief Adds a failed test. This increments total and failed.
|
||||||
|
/// @return A reference to this instance. Used for chaining.
|
||||||
|
TestResults& fail();
|
||||||
|
|
||||||
|
/// @brief Adds a passed test. This increments total and passed.
|
||||||
|
/// @return A reference to this instance. Used for chaining.
|
||||||
|
TestResults& pass();
|
||||||
|
|
||||||
|
/// @brief Adds a skipped test. This increments total and skipped.
|
||||||
|
/// @return A reference to this instance. Used for chaining.
|
||||||
|
TestResults& skip();
|
||||||
|
|
||||||
|
/// @brief Getter for the count of failed tests.
|
||||||
|
/// @return The count of failed tests.
|
||||||
|
uint32_t failed();
|
||||||
|
|
||||||
|
/// @brief Getter for the count of passed tests.
|
||||||
|
/// @return The count of passed tests.
|
||||||
|
uint32_t passed();
|
||||||
|
|
||||||
|
/// @brief Getter for the count of skipped tests.
|
||||||
|
/// @return The count of skipped tests.
|
||||||
|
uint32_t skipped();
|
||||||
|
|
||||||
|
/// @brief Getter for the count of total tests.
|
||||||
|
/// @return The count of total tests run.
|
||||||
|
uint32_t total();
|
||||||
|
|
||||||
|
/// @brief Returns the combination of this and another TestResults instance.
|
||||||
|
/// @param other The other TestResults instance to add to this one.
|
||||||
|
/// @return The combination of the two TestResults instances.
|
||||||
|
TestResults operator+(const TestResults& other) const;
|
||||||
|
|
||||||
|
/// @brief Adds another TestResults to this one and returns a reference to this instance.
|
||||||
|
/// @param other The other TestResults instance to add to this one.
|
||||||
|
/// @return A reference to this instance.
|
||||||
|
TestResults& operator+=(const TestResults& other);
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint32_t failed_;
|
||||||
|
uint32_t passed_;
|
||||||
|
uint32_t skipped_;
|
||||||
|
uint32_t total_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// This function is called to execute a test suite. You provide it with some configuration info, optional utility callback functions, and test data (input parameters for each call to function_to_test and the expected result). It returns a TestResults that should be treated as an opaque data type.
|
||||||
|
// Not all parameters are named in code, but they are named and explained in the comments and will be described by those names below.
|
||||||
|
// string suite_name - This is the name of this test suite. It is used for reporting messages.
|
||||||
|
// TFunctionToTest function_to_test - This is the function to test. This may be replaced if necessary by std::function. It may not currently support class methods, but that is planned.
|
||||||
|
// vector<tuple<...>> tests - This is the test run data. Each tuple in the vector is a single test run. It's members are explained below.
|
||||||
|
// string test_name - This is the name of this test. It is used for reporting messages.
|
||||||
|
// TResult expected_output - This is the expected result of executing this test.
|
||||||
|
// bool(*)(const TResult expected, const TResult actual) test_compare_function - This is optional. If unset or set to nullptr it is skipped. If set to a function it is called to evaluate the test results. It takes the expected and actual results as parameters and should return true if the test passed and false otherwise. This may be changed to return a TestResults at some point.
|
||||||
|
// void(*)(TInputParams...) test_setup_function - This is optional. If unset or set to nullptr it is skipped. If set to a function it is called before each test to setup the environment for the test. You may use it to allocate resources and setup mocks, stubs, and spies.
|
||||||
|
// void(*)(TInputParams...) test_teardown_function - This is optiona. If unset or set to nullptr it is skipped. If set to a function it is called after each test to cleanup the environment after the test. You should free resources allocated by test_setup_function.
|
||||||
|
// bool is_enabled - This is optional. If unset or set to true the test is run. If set to false this test is skipped. If skipped it will be reported as a skipped/disabled test.
|
||||||
|
// bool(*)(const TResult expected, const TResult actual) suite_compare_function - This is optional. If unset or set to nullptr it is skipped. If set to a function and test_compare_function is not called for a test run then this function is called to evaluate the test results. It takes the expected and actual results as parameters and should return true if the test passed and false otherwise. This may be changed to return a TestResults at some point.
|
||||||
|
// void(*)() suite_setup_function - This is optional. If unset or set to nullptr it is skipped. If set to a function it is called before starting this test suite to setup the environment. You may use it to allocate resources and setup mocks, stubs, and spies.
|
||||||
|
// void(*)() suite_teardown_function - This is optional. If unset or set to nullptr it is skipped. If set to a function it is called after all tests in this suite have finished and all reporting has finished. You should free resources allocated by suite_setup_function.
|
||||||
|
// This method should be called like so. This is the minimal call and omits all of the optional params. This is the most common usage. You should put one tuple of inputs and expected output for each test case.
|
||||||
|
// results = collect_and_report_test_resultstest_fn(
|
||||||
|
// "Test: function_under_test",
|
||||||
|
// function_under_test,
|
||||||
|
// vector({
|
||||||
|
// make_tuple(
|
||||||
|
// "ShouldReturnAppleForGroupId_1_and_ItemId_2",
|
||||||
|
// string("Apple"),
|
||||||
|
// make_tuple(1,2),
|
||||||
|
// ),
|
||||||
|
// }),
|
||||||
|
// );
|
||||||
|
// The suites can be run from one file as such. From a file called ThingDoer_test.cpp to test the class/methods ThingDoer declared in ThingDoer.cpp. This isn't mandatory but is a best practice.
|
||||||
|
// You can use function_to_test without calling collect_and_report_test_results() and also could call it from a normal int main(int argc, char** argv) or other function.
|
||||||
|
// TestResults test_main_ThingDoer(int argc, char** argv) {
|
||||||
|
// TestResults results;
|
||||||
|
// results = collect_and_report_test_results(results, function_to_test("do_thing1", ...), argc, argv);
|
||||||
|
// results = collect_and_report_test_results(results, function_to_test("do_thing2", ...), argc, argv);
|
||||||
|
// return results;
|
||||||
|
// }
|
||||||
|
// Then some test harness either generated or explicit can call test_main_ThingDoer(...) and optionally reported there. Reporting granularity is controlled by how frequently you call collect_and_report_test_results(...).
|
||||||
|
// You can combine test results with results = results + function_to_test(..); and then collect_and_report_test_results on the aggregate TestResults value.
|
||||||
|
|
||||||
|
/// @brief
|
||||||
|
/// @tparam TResult
|
||||||
|
template<typename TResult>
|
||||||
|
using TestCompareFunction = std::function<bool(const TResult& expected, const TResult& actual)>;
|
||||||
|
|
||||||
|
/// @brief
|
||||||
|
/// @tparam TResult
|
||||||
|
template<typename TResult>
|
||||||
|
using MaybeTestCompareFunction = std::optional<TestCompareFunction<TResult>>;
|
||||||
|
|
||||||
|
using TestConfigureFunction = std::function<void()>;
|
||||||
|
using MaybeTestConfigureFunction = std::optional<TestConfigureFunction>;
|
||||||
|
|
||||||
|
/// @brief
|
||||||
|
/// @tparam TResult
|
||||||
|
/// @tparam ...TInputParams
|
||||||
|
template<typename TResult, typename... TInputParams>
|
||||||
|
using TestTuple = std::tuple<
|
||||||
|
const std::string& /* test_name */,
|
||||||
|
const TResult& /* expected_output */,
|
||||||
|
std::tuple<TInputParams...> /* input_params - The input parameters for this test. These will be used when calling std::apply with function_to_test to execute the test. */,
|
||||||
|
MaybeTestCompareFunction<TResult> /* test_compare_function - If this is not nullprt then this function will be called instead of suite_compare_function to determine if the test passes. Use this to check for side effects of the test. Return true if the test passes and false otherwise. */,
|
||||||
|
MaybeTestConfigureFunction /* test_setup_function - If this is not nullptr this function is called before each test to setup the environment. It is called with std::apply and input_params so you can use them to mock records with specific IDs or calculate an expected result. */,
|
||||||
|
MaybeTestConfigureFunction /* test_teardown_function If this is not nullptr this function is called after each test to cleanup any allocated/shared resources. */,
|
||||||
|
bool /* is_enabled If this is false the test, setup, and teardown functions are not run. */>;
|
||||||
|
|
||||||
|
/// @brief
|
||||||
|
/// @tparam TResult
|
||||||
|
/// @tparam TFunctionToTest
|
||||||
|
/// @tparam ...TInputParams
|
||||||
|
template<typename TResult, typename... TInputParams>
|
||||||
|
using TestSuite = std::tuple<
|
||||||
|
std::string,
|
||||||
|
std::function<TResult(TInputParams...)>,
|
||||||
|
std::vector<TestTuple<TResult, TInputParams...>>,
|
||||||
|
MaybeTestCompareFunction<TResult>,
|
||||||
|
MaybeTestConfigureFunction,
|
||||||
|
MaybeTestConfigureFunction,
|
||||||
|
bool
|
||||||
|
>;
|
||||||
|
|
||||||
|
/// @brief
|
||||||
|
/// @tparam TResult The result type of the test.
|
||||||
|
/// @tparam TInputParams... The types of parameters sent to the test function.
|
||||||
|
/// @param suite_label The label for this test suite. For example a class name such as "MortgageCalculator".
|
||||||
|
/// @param function_to_test The function to be tested. It will be called with std::apply and a std::tuple<TInputParams...> made from each item in tests.
|
||||||
|
/// @param tests A std::vector of test runs.
|
||||||
|
/// @param suite_compare_function A function used to compare the expected and actual test results. This can be overridden per test by setting test_compare_function.
|
||||||
|
/// @param after_all This is called before each suite is started to setup the environment. This is where you should build mocks, setup spies, and test fixtures.
|
||||||
|
/// @param before_all This is called after each suite has completed to cleanup anything allocated in suite_before_each.
|
||||||
|
/// @param is_enabled If false none of these tests are run and they are all reported as skipped.
|
||||||
|
template <typename TResult, typename... TInputParams>
|
||||||
|
TestResults execute_suite(
|
||||||
|
std::string suite_label,
|
||||||
|
std::function<TResult(TInputParams...)> function_to_test,
|
||||||
|
vector<TestTuple<TResult, TInputParams...>> tests,
|
||||||
|
MaybeTestCompareFunction<TResult> suite_compare = std::nullopt,
|
||||||
|
MaybeTestConfigureFunction before_all = std::nullopt,
|
||||||
|
MaybeTestConfigureFunction after_all = std::nullopt,
|
||||||
|
bool is_enabled = true
|
||||||
|
);
|
||||||
|
|
||||||
|
/// @brief
|
||||||
|
/// @tparam TResult The result type of the test.
|
||||||
|
/// @tparam ...TInputParams The types of parameters sent to the test function.
|
||||||
|
/// @param test_name The label for this test. For example "should calculate the interest".
|
||||||
|
/// @param expected The expected output of calling the test function with these input parameters.
|
||||||
|
/// @param input_params The input parameters to use when calling the test function.
|
||||||
|
/// @param test_compare_fn An optional function that can be used to compare the expected and actual return values. This is good for when you only care about certain fields being equal.
|
||||||
|
/// @param before_each This is called to setup the environment before running the test. This is where you should build mocks, setup spies, and set any other values you need before calling the test function.
|
||||||
|
/// @param after_each This is called after each test run to cleanup anything allocated in before_each.
|
||||||
|
/// @param is_enabled If false this test run is not executed and considered skipped for reporting purposes.
|
||||||
|
/// @return A TestTuple suitable for use as a test run when calling test_fn.
|
||||||
|
template<typename TResult, typename... TInputParams>
|
||||||
|
TestTuple<TResult, TInputParams...> make_test(
|
||||||
|
const string& test_name,
|
||||||
|
const TResult& expected,
|
||||||
|
tuple<TInputParams...> input_params,
|
||||||
|
MaybeTestCompareFunction<TResult> test_compare_fn = std::nullopt,
|
||||||
|
MaybeTestConfigureFunction before_each = std::nullopt,
|
||||||
|
MaybeTestConfigureFunction after_each = std::nullopt,
|
||||||
|
bool is_enabled = true) {
|
||||||
|
return make_tuple(test_name, expected, input_params, test_compare_fn, before_each, after_each, is_enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief
|
||||||
|
/// @tparam TResult
|
||||||
|
/// @tparam TFunctionToTest
|
||||||
|
/// @tparam ...TInputParams
|
||||||
|
/// @param suite_name
|
||||||
|
/// @param function_to_test
|
||||||
|
/// @param test_data
|
||||||
|
/// @param compare
|
||||||
|
/// @param before_each
|
||||||
|
/// @param after_each
|
||||||
|
/// @param is_enabled
|
||||||
|
/// @return
|
||||||
|
template<typename TResult, typename TFunctionToTest, typename... TInputParams>
|
||||||
|
TestSuite<TResult, TInputParams...> make_test_suite(
|
||||||
|
const string& suite_name,
|
||||||
|
TFunctionToTest function_to_test,
|
||||||
|
vector<TestTuple<TResult, TInputParams...>> test_data,
|
||||||
|
MaybeTestCompareFunction<TResult> compare = std::nullopt,
|
||||||
|
MaybeTestConfigureFunction before_each = std::nullopt,
|
||||||
|
MaybeTestConfigureFunction after_each = std::nullopt,
|
||||||
|
bool is_enabled = true) {
|
||||||
|
return make_tuple(suite_name, function_to_test, test_data, compare, before_each, after_each, is_enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TResult, typename... TInputParams>
|
||||||
|
TestResults execute_suite(const TestSuite<TResult, TInputParams...>& test_suite) {
|
||||||
|
return std::apply(execute_suite<TResult, TInputParams...>, test_suite);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief
|
||||||
|
/// @tparam ...TInputParams
|
||||||
|
/// @param first
|
||||||
|
/// @param second
|
||||||
|
/// @return
|
||||||
|
template<typename... TInputParams>
|
||||||
|
MaybeTestConfigureFunction coalesce(
|
||||||
|
MaybeTestConfigureFunction first,
|
||||||
|
MaybeTestConfigureFunction second) {
|
||||||
|
if (first.has_value()) {
|
||||||
|
if (second.has_value()) {
|
||||||
|
// This is the only place we actually need to combine them.
|
||||||
|
return [&first, &second](TInputParams... input_params) {
|
||||||
|
*first(input_params...);
|
||||||
|
*second(input_params...);
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return first;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return second;
|
||||||
|
}
|
||||||
|
}
|
||||||
} // End namespace Test
|
} // End namespace Test
|
||||||
|
|
||||||
|
// TODO: define operator<< for std::tuple.
|
||||||
|
// TODO: Add TShared(*)(string /*test_name*/, UUID /*test_run_id*/) allocate_shared_data to the test tuple to make some shared data that can be used in a thread safe way by setup, teardown, and evaluate steps of the test.
|
||||||
|
// TODO: Add TShared to be returned by the setup functions, and consumed by the evaluate and teardown functions.
|
||||||
|
// Suite setup/teardown functions should allocate/free.
|
||||||
|
// Test setup/teardown functions should consume the data allocated by suite setup.
|
||||||
|
// Test setup functions may allocate additional resources. If they do then the allocated resources they should be freed by test teardown function.
|
||||||
|
// Suite and/or test compare functions may consume this shared data, but it will not be shared with the execution of function_to_test.
|
||||||
#endif // End !defined TEST_H__
|
#endif // End !defined TEST_H__
|
||||||
|
|||||||
Reference in New Issue
Block a user