Skip to content

Commit

Permalink
Use comma over << operator for all unit test logging
Browse files Browse the repository at this point in the history
The comma operator should be preferred now according to doctest.

Moved macro aliases from `ClassDB` tests to `test_macros.h`, because those
are also used in `TextServer` tests.
  • Loading branch information
Xrayez committed Jan 8, 2021
1 parent b72ad9d commit faab6ff
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 55 deletions.
66 changes: 30 additions & 36 deletions tests/test_class_db.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/

#ifndef GODOT_TEST_CLASS_DB_H
#define GODOT_TEST_CLASS_DB_H
#ifndef TEST_CLASS_DB_H
#define TEST_CLASS_DB_H

#include "core/register_core_types.h"

Expand All @@ -42,11 +42,6 @@

#include "tests/test_macros.h"

#define TEST_COND(cond, msg) DOCTEST_CHECK_FALSE_MESSAGE(cond, String(msg))
#define TEST_FAIL(cond, msg) DOCTEST_FAIL(cond, String(msg))
#define TEST_FAIL_COND(cond, msg) DOCTEST_REQUIRE_FALSE_MESSAGE(cond, String(msg))
#define TEST_FAIL_COND_WARN(cond, msg) DOCTEST_WARN_FALSE_MESSAGE(cond, String(msg))

namespace TestClassDB {

struct TypeReference {
Expand Down Expand Up @@ -298,7 +293,7 @@ void validate_property(const Context &p_context, const ExposedClass &p_class, co
const ExposedClass *top = &p_class;
while (!setter && top->base != StringName()) {
top = p_context.find_exposed_class(top->base);
TEST_FAIL_COND(!top, "Class not found '" + top->base + "'. Inherited by '" + top->name + "'.");
TEST_FAIL_COND(!top, "Class not found '", top->base, "'. Inherited by '", top->name, "'.");
setter = top->find_method_by_name(p_prop.setter);
}

Expand All @@ -308,23 +303,23 @@ void validate_property(const Context &p_context, const ExposedClass &p_class, co
top = &p_class;
while (!getter && top->base != StringName()) {
top = p_context.find_exposed_class(top->base);
TEST_FAIL_COND(!top, "Class not found '" + top->base + "'. Inherited by '" + top->name + "'.");
TEST_FAIL_COND(!top, "Class not found '", top->base, "'. Inherited by '", top->name, "'.");
getter = top->find_method_by_name(p_prop.getter);
}

TEST_FAIL_COND((!setter && !getter),
"Couldn't find neither the setter nor the getter for property: '" + p_class.name + "." + String(p_prop.name) + "'.");
"Couldn't find neither the setter nor the getter for property: '", p_class.name, ".", String(p_prop.name), "'.");

if (setter) {
int setter_argc = p_prop.index != -1 ? 2 : 1;
TEST_FAIL_COND(setter->arguments.size() != setter_argc,
"Invalid property setter argument count: '" + p_class.name + "." + String(p_prop.name) + "'.");
"Invalid property setter argument count: '", p_class.name, ".", String(p_prop.name), "'.");
}

if (getter) {
int getter_argc = p_prop.index != -1 ? 1 : 0;
TEST_FAIL_COND(getter->arguments.size() != getter_argc,
"Invalid property setter argument count: '" + p_class.name + "." + String(p_prop.name) + "'.");
"Invalid property setter argument count: '", p_class.name, ".", String(p_prop.name), "'.");
}

if (getter && setter) {
Expand All @@ -335,7 +330,7 @@ void validate_property(const Context &p_context, const ExposedClass &p_class, co
setter_first_arg.type.name == p_context.names_cache.string_type;

TEST_FAIL_COND(!whitelisted,
"Return type from getter doesn't match first argument of setter, for property: '" + p_class.name + "." + String(p_prop.name) + "'.");
"Return type from getter doesn't match first argument of setter, for property: '", p_class.name, ".", String(p_prop.name), "'.");
}
}

Expand All @@ -344,10 +339,10 @@ void validate_property(const Context &p_context, const ExposedClass &p_class, co
const ExposedClass *prop_class = p_context.find_exposed_class(prop_type_ref);
if (prop_class) {
TEST_COND(prop_class->is_singleton,
"Property type is a singleton: '" + p_class.name + "." + String(p_prop.name) + "'.");
"Property type is a singleton: '", p_class.name, ".", String(p_prop.name), "'.");
} else {
TEST_FAIL_COND(!p_context.has_type(prop_type_ref),
"Property type '" + prop_type_ref.name + "' not found: '" + p_class.name + "." + String(p_prop.name) + "'.");
"Property type '", prop_type_ref.name, "' not found: '", p_class.name, ".", String(p_prop.name), "'.");
}

if (getter) {
Expand All @@ -356,7 +351,7 @@ void validate_property(const Context &p_context, const ExposedClass &p_class, co
if (idx_arg.type.name != p_context.names_cache.int_type) {
// If not an int, it can be an enum
TEST_COND(p_context.enum_types.find(idx_arg.type.name) < 0,
"Invalid type '" + idx_arg.type.name + "' for index argument of property getter: '" + p_class.name + "." + String(p_prop.name) + "'.");
"Invalid type '", idx_arg.type.name, "' for index argument of property getter: '", p_class.name, ".", String(p_prop.name), "'.");
}
}
}
Expand All @@ -368,7 +363,7 @@ void validate_property(const Context &p_context, const ExposedClass &p_class, co
// Assume the index parameter is an enum
// If not an int, it can be an enum
TEST_COND(p_context.enum_types.find(idx_arg.type.name) < 0,
"Invalid type '" + idx_arg.type.name + "' for index argument of property setter: '" + p_class.name + "." + String(p_prop.name) + "'.");
"Invalid type '", idx_arg.type.name, "' for index argument of property setter: '", p_class.name, ".", String(p_prop.name), "'.");
}
}
}
Expand All @@ -378,7 +373,7 @@ void validate_method(const Context &p_context, const ExposedClass &p_class, cons
const ExposedClass *return_class = p_context.find_exposed_class(p_method.return_type);
if (return_class) {
TEST_COND(return_class->is_singleton,
"Method return type is a singleton: '" + p_class.name + "." + p_method.name + "'.");
"Method return type is a singleton: '", p_class.name, ".", p_method.name, "'.");
}

for (const List<ArgumentData>::Element *F = p_method.arguments.front(); F; F = F->next()) {
Expand All @@ -387,10 +382,10 @@ void validate_method(const Context &p_context, const ExposedClass &p_class, cons
const ExposedClass *arg_class = p_context.find_exposed_class(arg.type);
if (arg_class) {
TEST_COND(arg_class->is_singleton,
"Argument type is a singleton: '" + arg.name + "' of method '" + p_class.name + "." + p_method.name + "'.");
"Argument type is a singleton: '", arg.name, "' of method '", p_class.name, ".", p_method.name, "'.");
} else {
TEST_FAIL_COND(!p_context.has_type(arg.type),
"Argument type '" + arg.type.name + "' not found: '" + arg.name + "' of method" + p_class.name + "." + p_method.name + "'.");
"Argument type '", arg.type.name, "' not found: '", arg.name, "' of method", p_class.name, ".", p_method.name, "'.");
}

if (arg.has_defval) {
Expand All @@ -412,10 +407,10 @@ void validate_signal(const Context &p_context, const ExposedClass &p_class, cons
const ExposedClass *arg_class = p_context.find_exposed_class(arg.type);
if (arg_class) {
TEST_COND(arg_class->is_singleton,
"Argument class is a singleton: '" + arg.name + "' of signal" + p_class.name + "." + p_signal.name + "'.");
"Argument class is a singleton: '", arg.name, "' of signal", p_class.name, ".", p_signal.name, "'.");
} else {
TEST_FAIL_COND(!p_context.has_type(arg.type),
"Argument type '" + arg.type.name + "' not found: '" + arg.name + "' of signal" + p_class.name + "." + p_signal.name + "'.");
"Argument type '", arg.type.name, "' not found: '", arg.name, "' of signal", p_class.name, ".", p_signal.name, "'.");
}
}
}
Expand All @@ -426,7 +421,7 @@ void validate_class(const Context &p_context, const ExposedClass &p_exposed_clas
if (!is_derived_type) {
// Asserts about the base Object class
TEST_FAIL_COND(p_exposed_class.name != p_context.names_cache.object_class,
"Class '" + p_exposed_class.name + "' has no base class.");
"Class '", p_exposed_class.name, "' has no base class.");
TEST_FAIL_COND(!p_exposed_class.is_instantiable,
"Object class is not instantiable.");
TEST_FAIL_COND(p_exposed_class.api_type != ClassDB::API_CORE,
Expand All @@ -436,10 +431,10 @@ void validate_class(const Context &p_context, const ExposedClass &p_exposed_clas
}

TEST_FAIL_COND((p_exposed_class.is_singleton && p_exposed_class.base != p_context.names_cache.object_class),
"Singleton base class '" + String(p_exposed_class.base) + "' is not Object, for class '" + p_exposed_class.name + "'.");
"Singleton base class '", String(p_exposed_class.base), "' is not Object, for class '", p_exposed_class.name, "'.");

TEST_FAIL_COND((is_derived_type && !p_context.exposed_classes.has(p_exposed_class.base)),
"Base type '" + p_exposed_class.base.operator String() + "' does not exist, for class '" + p_exposed_class.name + "'.");
"Base type '", p_exposed_class.base.operator String(), "' does not exist, for class '", p_exposed_class.name, "'.");

for (const List<PropertyData>::Element *F = p_exposed_class.properties.front(); F; F = F->next()) {
validate_property(p_context, p_exposed_class, F->get());
Expand Down Expand Up @@ -519,7 +514,7 @@ void add_exposed_classes(Context &r_context) {

bool valid = false;
prop.index = ClassDB::get_property_index(class_name, prop.name, &valid);
TEST_FAIL_COND(!valid, "Invalid property: '" + exposed_class.name + "." + String(prop.name) + "'.");
TEST_FAIL_COND(!valid, "Invalid property: '", exposed_class.name, ".", String(prop.name), "'.");

exposed_class.properties.push_back(prop);
}
Expand Down Expand Up @@ -557,7 +552,7 @@ void add_exposed_classes(Context &r_context) {

if (!m && !method.is_virtual) {
TEST_FAIL_COND(!virtual_method_list.find(method_info),
"Missing MethodBind for non-virtual method: '" + exposed_class.name + "." + method.name + "'.");
"Missing MethodBind for non-virtual method: '", exposed_class.name, ".", method.name, "'.");

// A virtual method without the virtual flag. This is a special case.

Expand All @@ -584,9 +579,8 @@ void add_exposed_classes(Context &r_context) {

bool bad_reference_hint = !method.is_virtual && return_info.hint != PROPERTY_HINT_RESOURCE_TYPE &&
ClassDB::is_parent_class(return_info.class_name, r_context.names_cache.reference_class);
TEST_COND(bad_reference_hint, String() + "Return type is reference but hint is not '" _STR(PROPERTY_HINT_RESOURCE_TYPE) "'." +
" Are you returning a reference type by pointer? Method: '" +
exposed_class.name + "." + method.name + "'.");
TEST_COND(bad_reference_hint, "Return type is reference but hint is not '" _STR(PROPERTY_HINT_RESOURCE_TYPE) "'.", " Are you returning a reference type by pointer? Method: '",
exposed_class.name, ".", method.name, "'.");
} else if (return_info.hint == PROPERTY_HINT_RESOURCE_TYPE) {
method.return_type.name = return_info.hint_string;
} else if (return_info.type == Variant::NIL && return_info.usage & PROPERTY_USAGE_NIL_IS_VARIANT) {
Expand Down Expand Up @@ -636,7 +630,7 @@ void add_exposed_classes(Context &r_context) {
}

TEST_COND(exposed_class.find_property_by_name(method.name),
"Method name conflicts with property: '" + String(class_name) + "." + String(method.name) + "'.");
"Method name conflicts with property: '", String(class_name), ".", String(method.name), "'.");

// Classes starting with an underscore are ignored unless they're used as a property setter or getter
if (!method.is_virtual && String(method.name)[0] == '_') {
Expand Down Expand Up @@ -724,8 +718,8 @@ void add_exposed_classes(Context &r_context) {
for (const List<StringName>::Element *E = enum_constants.front(); E; E = E->next()) {
const StringName &constant_name = E->get();
int *value = class_info->constant_map.getptr(constant_name);
TEST_FAIL_COND(!value, "Missing enum constant value: '" +
String(class_name) + "." + String(enum_.name) + "." + String(constant_name) + "'.");
TEST_FAIL_COND(!value, "Missing enum constant value: '",
String(class_name), ".", String(enum_.name), ".", String(constant_name), "'.");
constants.erase(constant_name);

ConstantData constant;
Expand All @@ -743,7 +737,7 @@ void add_exposed_classes(Context &r_context) {
for (const List<String>::Element *E = constants.front(); E; E = E->next()) {
const String &constant_name = E->get();
int *value = class_info->constant_map.getptr(StringName(E->get()));
TEST_FAIL_COND(!value, "Missing enum constant value: '" + String(class_name) + "." + String(constant_name) + "'.");
TEST_FAIL_COND(!value, "Missing enum constant value: '", String(class_name), ".", String(constant_name), "'.");

ConstantData constant;
constant.name = constant_name;
Expand Down Expand Up @@ -822,7 +816,7 @@ TEST_SUITE("[ClassDB]") {
const ExposedClass *object_class = context.find_exposed_class(context.names_cache.object_class);
TEST_FAIL_COND(!object_class, "Object class not found.");
TEST_FAIL_COND(object_class->base != StringName(),
"Object class derives from another class: '" + object_class->base + "'.");
"Object class derives from another class: '", object_class->base, "'.");

for (ExposedClasses::Element E = context.exposed_classes.front(); E; E = E.next()) {
validate_class(context, E.value());
Expand All @@ -832,4 +826,4 @@ TEST_SUITE("[ClassDB]") {
}
} // namespace TestClassDB

#endif //GODOT_TEST_CLASS_DB_H
#endif // TEST_CLASS_DB_H
6 changes: 6 additions & 0 deletions tests/test_macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@
// The test case is marked as failed, but does not fail the entire test run.
#define TEST_CASE_MAY_FAIL(name) TEST_CASE(name *doctest::may_fail())

// Provide aliases to conform with Godot naming conventions (see error macros).
#define TEST_COND(cond, ...) DOCTEST_CHECK_FALSE_MESSAGE(cond, __VA_ARGS__)
#define TEST_FAIL(cond, ...) DOCTEST_FAIL(cond, __VA_ARGS__)
#define TEST_FAIL_COND(cond, ...) DOCTEST_REQUIRE_FALSE_MESSAGE(cond, __VA_ARGS__)
#define TEST_FAIL_COND_WARN(cond, ...) DOCTEST_WARN_FALSE_MESSAGE(cond, __VA_ARGS__)

// Temporarily disable error prints to test failure paths.
// This allows to avoid polluting the test summary with error messages.
// The `_print_error_enabled` boolean is defined in `core/print_string.cpp` and
Expand Down
28 changes: 14 additions & 14 deletions tests/test_random_number_generator.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ TEST_CASE_MAY_FAIL("[RandomNumberGenerator] Integer 32 bit") {
break;
}
}
INFO("Current seed: " << rng->get_seed());
INFO("Current iteration: " << i);
INFO("Current seed: ", rng->get_seed());
INFO("Current iteration: ", i);
CHECK_MESSAGE(higher, "Given current seed, this should give an integer higher than 0x0fff'ffff at least once.");
}

Expand Down Expand Up @@ -185,21 +185,21 @@ TEST_CASE("[RandomNumberGenerator] Zero for first number immediately after seedi
rng->set_seed(0);
uint32_t n1 = rng->randi();
uint32_t n2 = rng->randi();
INFO("Initial random values: " << n1 << " " << n2);
INFO("Initial random values: ", n1, " ", n2);
CHECK(n1 != 0);

rng->set_seed(1);
uint32_t n3 = rng->randi();
uint32_t n4 = rng->randi();
INFO("Values after changing the seed: " << n3 << " " << n4);
INFO("Values after changing the seed: ", n3, " ", n4);
CHECK(n3 != 0);
}

TEST_CASE("[RandomNumberGenerator] Restore state") {
Ref<RandomNumberGenerator> rng = memnew(RandomNumberGenerator);
rng->randomize();
uint64_t last_seed = rng->get_seed();
INFO("Current seed: " << last_seed);
INFO("Current seed: ", last_seed);

rng->randi();
rng->randi();
Expand All @@ -208,18 +208,18 @@ TEST_CASE("[RandomNumberGenerator] Restore state") {
"The seed should remain the same after generating some numbers");

uint64_t saved_state = rng->get_state();
INFO("Current state: " << saved_state);
INFO("Current state: ", saved_state);

real_t f1_before = rng->randf();
real_t f2_before = rng->randf();
INFO("This seed produces: " << f1_before << " " << f2_before);
INFO("This seed produces: ", f1_before, " ", f2_before);

// Restore now.
rng->set_state(saved_state);

real_t f1_after = rng->randf();
real_t f2_after = rng->randf();
INFO("Resetting the state produces: " << f1_after << " " << f2_after);
INFO("Resetting the state produces: ", f1_after, " ", f2_after);

String msg = "Should restore the sequence of numbers after resetting the state";
CHECK_MESSAGE(f1_before == f1_after, msg);
Expand All @@ -229,22 +229,22 @@ TEST_CASE("[RandomNumberGenerator] Restore state") {
TEST_CASE("[RandomNumberGenerator] Restore from seed") {
Ref<RandomNumberGenerator> rng = memnew(RandomNumberGenerator);
rng->set_seed(0);
INFO("Current seed: " << rng->get_seed());
INFO("Current seed: ", rng->get_seed());
uint32_t s0_1_before = rng->randi();
uint32_t s0_2_before = rng->randi();
INFO("This seed produces: " << s0_1_before << " " << s0_2_before);
INFO("This seed produces: ", s0_1_before, " ", s0_2_before);

rng->set_seed(9000);
INFO("Current seed: " << rng->get_seed());
INFO("Current seed: ", rng->get_seed());
uint32_t s9000_1 = rng->randi();
uint32_t s9000_2 = rng->randi();
INFO("This seed produces: " << s9000_1 << " " << s9000_2);
INFO("This seed produces: ", s9000_1, " ", s9000_2);

rng->set_seed(0);
INFO("Current seed: " << rng->get_seed());
INFO("Current seed: ", rng->get_seed());
uint32_t s0_1_after = rng->randi();
uint32_t s0_2_after = rng->randi();
INFO("This seed produces: " << s0_1_after << " " << s0_2_after);
INFO("This seed produces: ", s0_1_after, " ", s0_2_after);

String msg = "Should restore the sequence of numbers after resetting the seed";
CHECK_MESSAGE(s0_1_before == s0_1_after, msg);
Expand Down
2 changes: 1 addition & 1 deletion tests/test_text_server.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ TEST_SUITE("[[TextServer]") {
SUBCASE("[TextServer] Init") {
for (int i = 0; i < TextServerManager::get_interface_count(); i++) {
TextServer *ts = TextServerManager::initialize(i, err);
TEST_FAIL_COND((err != OK || ts == nullptr), "Text server " + TextServerManager::get_interface_name(i) + " init failed.");
TEST_FAIL_COND((err != OK || ts == nullptr), "Text server ", TextServerManager::get_interface_name(i), " init failed.");
}
}

Expand Down
6 changes: 2 additions & 4 deletions tests/test_validate_testing.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,10 +179,8 @@ TEST_SUITE("Validate tests") {
color_arr.push_back(Color(2, 2, 2));
INFO(color_arr);

INFO("doctest insertion operator << "
<< var << " " << vec2 << " " << rect2 << " " << color);

CHECK(true); // So all above prints.
// doctest string concatenation.
CHECK_MESSAGE(true, var, " ", vec2, " ", rect2, " ", color);
}
}

Expand Down

0 comments on commit faab6ff

Please sign in to comment.