mirror of
https://github.com/HandmadeMath/HandmadeMath.git
synced 2025-09-07 10:48:17 +00:00
Add test coverage macros (#104)
* Add coverage features and add it, laboriously, to everything * Fix easy tests * Add tests for != operators * Clean up test framework a little * Add documentation of coverage macros * Fix tests for mat4 to quaternion * Slightly improve formatting of coverage output * Trailing whitespace must die
This commit is contained in:
9
.editorconfig
Normal file
9
.editorconfig
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
root = true
|
||||||
|
|
||||||
|
[*.{c,cpp,h}]
|
||||||
|
charset = utf-8
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
end_of_line = lf
|
||||||
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
@@ -5,4 +5,7 @@ compiler:
|
|||||||
install:
|
install:
|
||||||
- cd test
|
- cd test
|
||||||
script:
|
script:
|
||||||
- make all
|
- make c
|
||||||
|
- make c_no_sse
|
||||||
|
- make cpp
|
||||||
|
- make cpp_no_sse
|
||||||
|
1045
HandmadeMath.h
1045
HandmadeMath.h
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,7 @@
|
|||||||
|
#ifndef WITHOUT_COVERAGE
|
||||||
|
#include "HandmadeTest.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define HANDMADE_MATH_IMPLEMENTATION
|
#define HANDMADE_MATH_IMPLEMENTATION
|
||||||
#define HANDMADE_MATH_NO_INLINE
|
#define HANDMADE_MATH_NO_INLINE
|
||||||
#include "../HandmadeMath.h"
|
#include "../HandmadeMath.h"
|
||||||
|
@@ -4,19 +4,46 @@
|
|||||||
This is Handmade Math's test framework. It is fully compatible with both C
|
This is Handmade Math's test framework. It is fully compatible with both C
|
||||||
and C++, although it requires some compiler-specific features.
|
and C++, although it requires some compiler-specific features.
|
||||||
|
|
||||||
|
To use Handmade Test, you must #define HANDMADE_TEST_IMPLEMENTATION in
|
||||||
|
exactly one C or C++ file that includes the header, like this:
|
||||||
|
|
||||||
|
#define HANDMADE_TEST_IMPLEMENTATION
|
||||||
|
#include "HandmadeTest.h"
|
||||||
|
|
||||||
The basic way of creating a test is using the TEST macro, which registers a
|
The basic way of creating a test is using the TEST macro, which registers a
|
||||||
single test to be run:
|
single test to be run:
|
||||||
|
|
||||||
TEST(MyCategory, MyTestName) {
|
TEST(MyCategory, MyTestName) {
|
||||||
// test code, including asserts/expects
|
// test code, including asserts/expects
|
||||||
}
|
}
|
||||||
|
|
||||||
The main function of your test code should then call hmt_run_all_tests and
|
Handmade Test also provides macros you can use to check the coverage of
|
||||||
return the result:
|
important parts of your code. Define a coverage case by using the COVERAGE
|
||||||
|
macro outside the function you wish to test, providing both a name and the
|
||||||
|
number of asserts you expect to see covered over the course of your test.
|
||||||
|
Then use the ASSERT_COVERED macro in every part of the function you wish to
|
||||||
|
check coverage on. For example:
|
||||||
|
|
||||||
int main() {
|
COVERAGE(MyCoverageCase, 3)
|
||||||
return hmt_run_all_tests();
|
void MyFunction(int a, int b) {
|
||||||
}
|
if (a > b) {
|
||||||
|
ASSERT_COVERED(MyCoverageCase);
|
||||||
|
return 10;
|
||||||
|
} else if (a < b) {
|
||||||
|
ASSERT_COVERED(MyCoverageCase);
|
||||||
|
return -10;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT_COVERED(MyCoverageCase);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
The main function of your test code should then call hmt_run_all_tests (and
|
||||||
|
optionally hmt_check_all_coverage) and return the result:
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
return hmt_run_all_tests() || hmt_check_all_coverage();
|
||||||
|
}
|
||||||
|
|
||||||
=============================================================================
|
=============================================================================
|
||||||
|
|
||||||
@@ -40,7 +67,7 @@
|
|||||||
#define HMT_RED "\033[31m"
|
#define HMT_RED "\033[31m"
|
||||||
#define HMT_GREEN "\033[32m"
|
#define HMT_GREEN "\033[32m"
|
||||||
|
|
||||||
#define HMT_INITIAL_ARRAY_SIZE 1024
|
#define HMT_ARRAY_SIZE 1024
|
||||||
|
|
||||||
typedef struct hmt_testresult_struct {
|
typedef struct hmt_testresult_struct {
|
||||||
int count_cases;
|
int count_cases;
|
||||||
@@ -57,20 +84,137 @@ typedef struct hmt_test_struct {
|
|||||||
typedef struct hmt_category_struct {
|
typedef struct hmt_category_struct {
|
||||||
const char* name;
|
const char* name;
|
||||||
int num_tests;
|
int num_tests;
|
||||||
int tests_capacity;
|
|
||||||
hmt_test* tests;
|
hmt_test* tests;
|
||||||
} hmt_category;
|
} hmt_category;
|
||||||
|
|
||||||
int hmt_num_categories = 0;
|
typedef struct hmt_covercase_struct {
|
||||||
int hmt_category_capacity = HMT_INITIAL_ARRAY_SIZE;
|
const char* name;
|
||||||
hmt_category* categories = 0;
|
int expected_asserts;
|
||||||
|
int actual_asserts;
|
||||||
|
int* asserted_lines;
|
||||||
|
} hmt_covercase;
|
||||||
|
|
||||||
|
hmt_category _hmt_new_category(const char* name);
|
||||||
|
hmt_test _hmt_new_test(const char* name, hmt_test_func func);
|
||||||
|
hmt_covercase _hmt_new_covercase(const char* name, int expected);
|
||||||
|
void _hmt_register_test(const char* category, const char* name, hmt_test_func func);
|
||||||
|
void _hmt_register_covercase(const char* name, const char* expected_asserts);
|
||||||
|
void _hmt_count_cover(const char* name, int line);
|
||||||
|
|
||||||
|
#define _HMT_TEST_FUNCNAME(category, name) _hmt_test_ ## category ## _ ## name
|
||||||
|
#define _HMT_TEST_FUNCNAME_INIT(category, name) _hmt_test_ ## category ## _ ## name ## _init
|
||||||
|
#define _HMT_COVERCASE_FUNCNAME_INIT(name) _hmt_covercase_ ## name ## _init
|
||||||
|
|
||||||
|
#define HMT_TEST(category, name) \
|
||||||
|
void _HMT_TEST_FUNCNAME(category, name)(hmt_testresult* _result); \
|
||||||
|
INITIALIZER(_HMT_TEST_FUNCNAME_INIT(category, name)) { \
|
||||||
|
_hmt_register_test(#category, #name, _HMT_TEST_FUNCNAME(category, name)); \
|
||||||
|
} \
|
||||||
|
void _HMT_TEST_FUNCNAME(category, name)(hmt_testresult* _result)
|
||||||
|
|
||||||
|
#define _HMT_CASE_START() \
|
||||||
|
_result->count_cases++;
|
||||||
|
|
||||||
|
#define _HMT_CASE_FAIL() \
|
||||||
|
_result->count_failures++; \
|
||||||
|
printf("\n - " HMT_RED "[FAIL] (line %d) " HMT_RESET, __LINE__);
|
||||||
|
|
||||||
|
#define HMT_COVERAGE(name, num_asserts) \
|
||||||
|
INITIALIZER(_HMT_COVERCASE_FUNCNAME_INIT(name)) { \
|
||||||
|
_hmt_register_covercase(#name, #num_asserts); \
|
||||||
|
} \
|
||||||
|
|
||||||
|
#define HMT_ASSERT_COVERED(name) \
|
||||||
|
{ \
|
||||||
|
_hmt_count_cover(#name, __LINE__); \
|
||||||
|
} \
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Asserts and expects
|
||||||
|
*/
|
||||||
|
#define HMT_EXPECT_TRUE(_actual) { \
|
||||||
|
_HMT_CASE_START(); \
|
||||||
|
if (!(_actual)) { \
|
||||||
|
_HMT_CASE_FAIL(); \
|
||||||
|
printf("Expected true but got something false"); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
|
||||||
|
#define HMT_EXPECT_FALSE(_actual) { \
|
||||||
|
_HMT_CASE_START(); \
|
||||||
|
if (_actual) { \
|
||||||
|
_HMT_CASE_FAIL(); \
|
||||||
|
printf("Expected false but got something true"); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
|
||||||
|
#define HMT_EXPECT_FLOAT_EQ(_actual, _expected) { \
|
||||||
|
_HMT_CASE_START(); \
|
||||||
|
float actual = (_actual); \
|
||||||
|
float diff = actual - (_expected); \
|
||||||
|
if (diff < -FLT_EPSILON || FLT_EPSILON < diff) { \
|
||||||
|
_HMT_CASE_FAIL(); \
|
||||||
|
printf("Expected %f, got %f", (_expected), actual); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
|
||||||
|
#define HMT_EXPECT_NEAR(_actual, _expected, _epsilon) { \
|
||||||
|
_HMT_CASE_START(); \
|
||||||
|
float actual = (_actual); \
|
||||||
|
float diff = actual - (_expected); \
|
||||||
|
if (diff < -(_epsilon) || (_epsilon) < diff) { \
|
||||||
|
_HMT_CASE_FAIL(); \
|
||||||
|
printf("Expected %f, got %f", (_expected), actual); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
|
||||||
|
#define HMT_EXPECT_LT(_actual, _expected) { \
|
||||||
|
_HMT_CASE_START(); \
|
||||||
|
if ((_actual) >= (_expected)) { \
|
||||||
|
_HMT_CASE_FAIL(); \
|
||||||
|
printf("Expected %f to be less than %f", (_actual), (_expected)); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
|
||||||
|
#define HMT_EXPECT_GT(_actual, _expected) { \
|
||||||
|
_HMT_CASE_START(); \
|
||||||
|
if ((_actual) <= (_expected)) { \
|
||||||
|
_HMT_CASE_FAIL(); \
|
||||||
|
printf("Expected %f to be greater than %f", (_actual), (_expected)); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
|
||||||
|
#ifndef HMT_SAFE_MACROS
|
||||||
|
// Friendly defines
|
||||||
|
#define TEST(category, name) HMT_TEST(category, name)
|
||||||
|
#define COVERAGE(name, expected_asserts) HMT_COVERAGE(name, expected_asserts)
|
||||||
|
#define ASSERT_COVERED(name) HMT_ASSERT_COVERED(name)
|
||||||
|
#define EXPECT_TRUE(_actual) HMT_EXPECT_TRUE(_actual)
|
||||||
|
#define EXPECT_FALSE(_actual) HMT_EXPECT_FALSE(_actual)
|
||||||
|
#define EXPECT_FLOAT_EQ(_actual, _expected) HMT_EXPECT_FLOAT_EQ(_actual, _expected)
|
||||||
|
#define EXPECT_NEAR(_actual, _expected, _epsilon) HMT_EXPECT_NEAR(_actual, _expected, _epsilon)
|
||||||
|
#define EXPECT_LT(_actual, _expected) HMT_EXPECT_LT(_actual, _expected)
|
||||||
|
#define EXPECT_GT(_actual, _expected) HMT_EXPECT_GT(_actual, _expected)
|
||||||
|
#endif // HMT_SAFE_MACROS
|
||||||
|
|
||||||
|
#endif // HANDMADETEST_H
|
||||||
|
|
||||||
|
#ifdef HANDMADE_TEST_IMPLEMENTATION
|
||||||
|
|
||||||
|
#ifndef HANDMADE_TEST_IMPLEMENTATION_GUARD
|
||||||
|
#define HANDMADE_TEST_IMPLEMENTATION_GUARD
|
||||||
|
|
||||||
|
int _hmt_num_categories = 0;
|
||||||
|
hmt_category* _hmt_categories = 0;
|
||||||
|
|
||||||
|
int _hmt_num_covercases = 0;
|
||||||
|
hmt_covercase* _hmt_covercases = 0;
|
||||||
|
|
||||||
hmt_category _hmt_new_category(const char* name) {
|
hmt_category _hmt_new_category(const char* name) {
|
||||||
hmt_category cat = {
|
hmt_category cat = {
|
||||||
.name = name,
|
.name = name,
|
||||||
.num_tests = 0,
|
.num_tests = 0,
|
||||||
.tests_capacity = HMT_INITIAL_ARRAY_SIZE,
|
.tests = (hmt_test*) malloc(HMT_ARRAY_SIZE * sizeof(hmt_test))
|
||||||
.tests = (hmt_test*) malloc(HMT_INITIAL_ARRAY_SIZE * sizeof(hmt_test))
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return cat;
|
return cat;
|
||||||
@@ -85,53 +229,98 @@ hmt_test _hmt_new_test(const char* name, hmt_test_func func) {
|
|||||||
return test;
|
return test;
|
||||||
}
|
}
|
||||||
|
|
||||||
int hmt_register_test(const char* category, const char* name, hmt_test_func func) {
|
hmt_covercase _hmt_new_covercase(const char* name, int expected) {
|
||||||
|
hmt_covercase covercase = {
|
||||||
|
.name = name,
|
||||||
|
.expected_asserts = expected,
|
||||||
|
.actual_asserts = 0,
|
||||||
|
.asserted_lines = (int*) malloc(HMT_ARRAY_SIZE * sizeof(int)),
|
||||||
|
};
|
||||||
|
|
||||||
|
return covercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _hmt_register_test(const char* category, const char* name, hmt_test_func func) {
|
||||||
// initialize categories array if not initialized
|
// initialize categories array if not initialized
|
||||||
if (!categories) {
|
if (!_hmt_categories) {
|
||||||
categories = (hmt_category*) malloc(hmt_category_capacity * sizeof(hmt_category));
|
_hmt_categories = (hmt_category*) malloc(HMT_ARRAY_SIZE * sizeof(hmt_category));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the matching category, if possible
|
// Find the matching category, if possible
|
||||||
int cat_index;
|
int cat_index;
|
||||||
for (cat_index = 0; cat_index < hmt_num_categories; cat_index++) {
|
for (cat_index = 0; cat_index < _hmt_num_categories; cat_index++) {
|
||||||
if (strcmp(categories[cat_index].name, category) == 0) {
|
if (strcmp(_hmt_categories[cat_index].name, category) == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expand the array of categories if necessary
|
|
||||||
if (cat_index >= hmt_category_capacity) {
|
|
||||||
// TODO: If/when we ever split HandmadeTest off into its own package,
|
|
||||||
// we should start with a smaller initial capacity and dynamically expand.
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add a new category if necessary
|
// Add a new category if necessary
|
||||||
if (cat_index >= hmt_num_categories) {
|
if (cat_index >= _hmt_num_categories) {
|
||||||
categories[cat_index] = _hmt_new_category(category);
|
_hmt_categories[cat_index] = _hmt_new_category(category);
|
||||||
hmt_num_categories++;
|
_hmt_num_categories++;
|
||||||
}
|
}
|
||||||
|
|
||||||
hmt_category* cat = &categories[cat_index];
|
hmt_category* cat = &_hmt_categories[cat_index];
|
||||||
|
|
||||||
// Add the test to the category
|
// Add the test to the category
|
||||||
if (cat->num_tests >= cat->tests_capacity) {
|
|
||||||
// TODO: If/when we ever split HandmadeTest off into its own package,
|
|
||||||
// we should start with a smaller initial capacity and dynamically expand.
|
|
||||||
}
|
|
||||||
cat->tests[cat->num_tests] = _hmt_new_test(name, func);
|
cat->tests[cat->num_tests] = _hmt_new_test(name, func);
|
||||||
cat->num_tests++;
|
cat->num_tests++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _hmt_register_covercase(const char* name, const char* expected_asserts) {
|
||||||
|
// initialize cases array if not initialized
|
||||||
|
if (!_hmt_covercases) {
|
||||||
|
_hmt_covercases = (hmt_covercase*) malloc(HMT_ARRAY_SIZE * sizeof(hmt_covercase));
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for existing case with that name, because the macro can run multiple
|
||||||
|
// times in different translation units
|
||||||
|
for (int i = 0; i < _hmt_num_covercases; i++) {
|
||||||
|
if (strcmp(_hmt_covercases[i].name, name) == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_hmt_covercases[_hmt_num_covercases] = _hmt_new_covercase(name, atoi(expected_asserts));
|
||||||
|
_hmt_num_covercases++;
|
||||||
|
}
|
||||||
|
|
||||||
|
hmt_covercase* _hmt_find_covercase(const char* name) {
|
||||||
|
for (int i = 0; i < _hmt_num_covercases; i++) {
|
||||||
|
if (strcmp(_hmt_covercases[i].name, name) == 0) {
|
||||||
|
return &_hmt_covercases[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _hmt_count_cover(const char* name, int line) {
|
||||||
|
hmt_covercase* covercase = _hmt_find_covercase(name);
|
||||||
|
if (covercase == 0) {
|
||||||
|
printf(HMT_RED "ERROR (line %d): Could not find coverage case with name \"%s\".\n" HMT_RESET, line, name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// see if this line has already been covered
|
||||||
|
for (int i = 0; i < covercase->actual_asserts; i++) {
|
||||||
|
if (covercase->asserted_lines[i] == line) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
covercase->asserted_lines[covercase->actual_asserts] = line;
|
||||||
|
covercase->actual_asserts++;
|
||||||
|
}
|
||||||
|
|
||||||
int hmt_run_all_tests() {
|
int hmt_run_all_tests() {
|
||||||
int count_alltests = 0;
|
int count_alltests = 0;
|
||||||
int count_allfailedtests = 0; // failed test cases
|
int count_allfailedtests = 0; // failed test cases
|
||||||
int count_allfailures = 0; // failed asserts
|
int count_allfailures = 0; // failed asserts
|
||||||
|
|
||||||
for (int i = 0; i < hmt_num_categories; i++) {
|
for (int i = 0; i < _hmt_num_categories; i++) {
|
||||||
hmt_category cat = categories[i];
|
hmt_category cat = _hmt_categories[i];
|
||||||
int count_catfailedtests = 0;
|
int count_catfailedtests = 0;
|
||||||
int count_catfailures = 0;
|
int count_catfailures = 0;
|
||||||
|
|
||||||
printf("\n%s:\n", cat.name);
|
printf("\n%s:\n", cat.name);
|
||||||
@@ -177,87 +366,33 @@ int hmt_run_all_tests() {
|
|||||||
return (count_allfailedtests > 0);
|
return (count_allfailedtests > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define _HMT_TEST_FUNCNAME(category, name) category ## _ ## name
|
int hmt_check_all_coverage() {
|
||||||
#define _HMT_TEST_FUNCNAME_INIT(category, name) category ## _ ## name ## _init
|
printf("Coverage:\n");
|
||||||
|
|
||||||
#define HMT_TEST(category, name) \
|
int count_failures = 0;
|
||||||
void _HMT_TEST_FUNCNAME(category, name)(hmt_testresult* _result); \
|
|
||||||
INITIALIZER(_HMT_TEST_FUNCNAME_INIT(category, name)) { \
|
|
||||||
hmt_register_test(#category, #name, _HMT_TEST_FUNCNAME(category, name)); \
|
|
||||||
} \
|
|
||||||
void _HMT_TEST_FUNCNAME(category, name)(hmt_testresult* _result)
|
|
||||||
|
|
||||||
#define _HMT_CASE_START() \
|
for (int i = 0; i < _hmt_num_covercases; i++) {
|
||||||
_result->count_cases++;
|
hmt_covercase covercase = _hmt_covercases[i];
|
||||||
|
|
||||||
#define _HMT_CASE_FAIL() \
|
if (covercase.expected_asserts != covercase.actual_asserts) {
|
||||||
_result->count_failures++; \
|
count_failures++;
|
||||||
printf("\n - " HMT_RED "[FAIL] (%d) " HMT_RESET, __LINE__);
|
printf("%s: " HMT_RED "FAIL (expected %d asserts, got %d)\n" HMT_RESET, covercase.name, covercase.expected_asserts, covercase.actual_asserts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
if (count_failures > 0) {
|
||||||
* Asserts and expects
|
printf("\n");
|
||||||
*/
|
printf(HMT_RED);
|
||||||
#define HMT_EXPECT_TRUE(_actual) do { \
|
} else {
|
||||||
_HMT_CASE_START(); \
|
printf(HMT_GREEN);
|
||||||
if (!(_actual)) { \
|
}
|
||||||
_HMT_CASE_FAIL(); \
|
printf("%d coverage cases tested, %d failures\n", _hmt_num_covercases, count_failures);
|
||||||
printf("Expected true but got something false"); \
|
printf(HMT_RESET);
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define HMT_EXPECT_FALSE(_actual) do { \
|
printf("\n");
|
||||||
_HMT_CASE_START(); \
|
|
||||||
if (_actual) { \
|
|
||||||
_HMT_CASE_FAIL(); \
|
|
||||||
printf("Expected false but got something true"); \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define HMT_EXPECT_FLOAT_EQ(_actual, _expected) do { \
|
return (count_failures > 0);
|
||||||
_HMT_CASE_START(); \
|
}
|
||||||
float actual = (_actual); \
|
|
||||||
float diff = actual - (_expected); \
|
|
||||||
if (diff < -FLT_EPSILON || FLT_EPSILON < diff) { \
|
|
||||||
_HMT_CASE_FAIL(); \
|
|
||||||
printf("Expected %f, got %f", (_expected), actual); \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define HMT_EXPECT_NEAR(_actual, _expected, _epsilon) do { \
|
#endif // HANDMADE_TEST_IMPLEMENTATION_GUARD
|
||||||
_HMT_CASE_START(); \
|
#endif // HANDMADE_TEST_IMPLEMENTATION
|
||||||
float actual = (_actual); \
|
|
||||||
float diff = actual - (_expected); \
|
|
||||||
if (diff < -(_epsilon) || (_epsilon) < diff) { \
|
|
||||||
_HMT_CASE_FAIL(); \
|
|
||||||
printf("Expected %f, got %f", (_expected), actual); \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define HMT_EXPECT_LT(_actual, _expected) do { \
|
|
||||||
_HMT_CASE_START(); \
|
|
||||||
if ((_actual) >= (_expected)) { \
|
|
||||||
_HMT_CASE_FAIL(); \
|
|
||||||
printf("Expected %f to be less than %f", (_actual), (_expected)); \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define HMT_EXPECT_GT(_actual, _expected) do { \
|
|
||||||
_HMT_CASE_START(); \
|
|
||||||
if ((_actual) <= (_expected)) { \
|
|
||||||
_HMT_CASE_FAIL(); \
|
|
||||||
printf("Expected %f to be greater than %f", (_actual), (_expected)); \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#ifndef HMT_SAFE_MACROS
|
|
||||||
// Friendly defines
|
|
||||||
#define TEST(category, name) HMT_TEST(category, name)
|
|
||||||
#define EXPECT_TRUE(_actual) HMT_EXPECT_TRUE(_actual)
|
|
||||||
#define EXPECT_FALSE(_actual) HMT_EXPECT_FALSE(_actual)
|
|
||||||
#define EXPECT_FLOAT_EQ(_actual, _expected) HMT_EXPECT_FLOAT_EQ(_actual, _expected)
|
|
||||||
#define EXPECT_NEAR(_actual, _expected, _epsilon) HMT_EXPECT_NEAR(_actual, _expected, _epsilon)
|
|
||||||
#define EXPECT_LT(_actual, _expected) HMT_EXPECT_LT(_actual, _expected)
|
|
||||||
#define EXPECT_GT(_actual, _expected) HMT_EXPECT_GT(_actual, _expected)
|
|
||||||
#endif // HMT_SAFE_MACROS
|
|
||||||
|
|
||||||
#endif // HANDMADETEST_H
|
|
||||||
|
@@ -2,18 +2,17 @@ BUILD_DIR=./build
|
|||||||
|
|
||||||
CXXFLAGS+=-g -Wall -Wextra -pthread -Wno-missing-braces -Wno-missing-field-initializers
|
CXXFLAGS+=-g -Wall -Wextra -pthread -Wno-missing-braces -Wno-missing-field-initializers
|
||||||
|
|
||||||
all: build_all
|
all: c c_no_sse cpp cpp_no_sse build_c_without_coverage build_cpp_without_coverage
|
||||||
$(BUILD_DIR)/hmm_test_c
|
|
||||||
$(BUILD_DIR)/hmm_test_c_no_sse
|
|
||||||
$(BUILD_DIR)/hmm_test_cpp
|
|
||||||
$(BUILD_DIR)/hmm_test_cpp_no_sse
|
|
||||||
|
|
||||||
build_all: c c_no_sse cpp cpp_no_sse
|
build_all: build_c build_c_no_sse build_cpp build_cpp_no_sse
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf $(BUILD_DIR)
|
rm -rf $(BUILD_DIR)
|
||||||
|
|
||||||
c: HandmadeMath.c test_impl
|
c: build_c
|
||||||
|
$(BUILD_DIR)/hmm_test_c
|
||||||
|
|
||||||
|
build_c: HandmadeMath.c test_impl
|
||||||
@echo "\nCompiling in C mode"
|
@echo "\nCompiling in C mode"
|
||||||
mkdir -p $(BUILD_DIR)
|
mkdir -p $(BUILD_DIR)
|
||||||
cd $(BUILD_DIR)\
|
cd $(BUILD_DIR)\
|
||||||
@@ -22,7 +21,10 @@ c: HandmadeMath.c test_impl
|
|||||||
-lm \
|
-lm \
|
||||||
&& $(CC) -ohmm_test_c HandmadeMath.o hmm_test.o -lm
|
&& $(CC) -ohmm_test_c HandmadeMath.o hmm_test.o -lm
|
||||||
|
|
||||||
c_no_sse: HandmadeMath.c test_impl
|
c_no_sse: build_c_no_sse
|
||||||
|
$(BUILD_DIR)/hmm_test_c_no_sse
|
||||||
|
|
||||||
|
build_c_no_sse: HandmadeMath.c test_impl
|
||||||
@echo "\nCompiling in C mode (no SSE)"
|
@echo "\nCompiling in C mode (no SSE)"
|
||||||
mkdir -p $(BUILD_DIR)
|
mkdir -p $(BUILD_DIR)
|
||||||
cd $(BUILD_DIR) \
|
cd $(BUILD_DIR) \
|
||||||
@@ -32,7 +34,10 @@ c_no_sse: HandmadeMath.c test_impl
|
|||||||
-lm \
|
-lm \
|
||||||
&& $(CC) -ohmm_test_c_no_sse HandmadeMath.o hmm_test.o -lm
|
&& $(CC) -ohmm_test_c_no_sse HandmadeMath.o hmm_test.o -lm
|
||||||
|
|
||||||
cpp: HandmadeMath.cpp test_impl
|
cpp: build_cpp
|
||||||
|
$(BUILD_DIR)/hmm_test_cpp
|
||||||
|
|
||||||
|
build_cpp: HandmadeMath.cpp test_impl
|
||||||
@echo "\nCompiling in C++ mode"
|
@echo "\nCompiling in C++ mode"
|
||||||
mkdir -p $(BUILD_DIR)
|
mkdir -p $(BUILD_DIR)
|
||||||
cd $(BUILD_DIR) \
|
cd $(BUILD_DIR) \
|
||||||
@@ -40,7 +45,10 @@ cpp: HandmadeMath.cpp test_impl
|
|||||||
-DHANDMADE_MATH_CPP_MODE \
|
-DHANDMADE_MATH_CPP_MODE \
|
||||||
../HandmadeMath.cpp ../hmm_test.cpp
|
../HandmadeMath.cpp ../hmm_test.cpp
|
||||||
|
|
||||||
cpp_no_sse: HandmadeMath.cpp test_impl
|
cpp_no_sse: build_cpp_no_sse
|
||||||
|
$(BUILD_DIR)/hmm_test_cpp_no_sse
|
||||||
|
|
||||||
|
build_cpp_no_sse: HandmadeMath.cpp test_impl
|
||||||
@echo "\nCompiling in C++ mode (no SSE)"
|
@echo "\nCompiling in C++ mode (no SSE)"
|
||||||
mkdir -p $(BUILD_DIR)
|
mkdir -p $(BUILD_DIR)
|
||||||
cd $(BUILD_DIR) \
|
cd $(BUILD_DIR) \
|
||||||
@@ -49,3 +57,21 @@ cpp_no_sse: HandmadeMath.cpp test_impl
|
|||||||
../HandmadeMath.cpp ../hmm_test.cpp
|
../HandmadeMath.cpp ../hmm_test.cpp
|
||||||
|
|
||||||
test_impl: hmm_test.cpp hmm_test.c
|
test_impl: hmm_test.cpp hmm_test.c
|
||||||
|
|
||||||
|
build_c_without_coverage: HandmadeMath.c
|
||||||
|
@echo "\nCompiling in C mode"
|
||||||
|
mkdir -p $(BUILD_DIR)
|
||||||
|
cd $(BUILD_DIR)\
|
||||||
|
&& $(CC) $(CPPFLAGS) $(CXXFLAGS) -std=c99 \
|
||||||
|
-DWITHOUT_COVERAGE \
|
||||||
|
-c ../HandmadeMath.c ../hmm_test.c \
|
||||||
|
-lm \
|
||||||
|
&& $(CC) -ohmm_test_c HandmadeMath.o hmm_test.o -lm
|
||||||
|
|
||||||
|
build_cpp_without_coverage: HandmadeMath.cpp test_impl
|
||||||
|
@echo "\nCompiling in C++ mode (no SSE)"
|
||||||
|
mkdir -p $(BUILD_DIR)
|
||||||
|
cd $(BUILD_DIR) \
|
||||||
|
&& $(CXX) $(CPPFLAGS) $(CXXFLAGS) -ohmm_test_cpp_no_sse \
|
||||||
|
-DHANDMADE_MATH_CPP_MODE -DWITHOUT_COVERAGE \
|
||||||
|
../HandmadeMath.cpp ../hmm_test.cpp
|
||||||
|
@@ -4,8 +4,13 @@ You can compile and run the tests yourself by running:
|
|||||||
|
|
||||||
```
|
```
|
||||||
make
|
make
|
||||||
build/hmm_test_c
|
```
|
||||||
build/hmm_test_c_no_sse
|
|
||||||
build/hmm_test_cpp
|
To run a specific test configuration, run one of:
|
||||||
build/hmm_test_cpp_no_sse
|
|
||||||
|
```
|
||||||
|
make c
|
||||||
|
make c_no_sse
|
||||||
|
make cpp
|
||||||
|
make cpp_no_sse
|
||||||
```
|
```
|
||||||
|
@@ -37,7 +37,7 @@ TEST(Addition, Vec3)
|
|||||||
hmm_vec3 result = HMM_AddVec3(v3_1, v3_2);
|
hmm_vec3 result = HMM_AddVec3(v3_1, v3_2);
|
||||||
EXPECT_FLOAT_EQ(result.X, 5.0f);
|
EXPECT_FLOAT_EQ(result.X, 5.0f);
|
||||||
EXPECT_FLOAT_EQ(result.Y, 7.0f);
|
EXPECT_FLOAT_EQ(result.Y, 7.0f);
|
||||||
EXPECT_FLOAT_EQ(result.Z, 9.0f);
|
EXPECT_FLOAT_EQ(result.Z, 9.0f);
|
||||||
}
|
}
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
{
|
{
|
||||||
@@ -64,7 +64,7 @@ TEST(Addition, Vec4)
|
|||||||
{
|
{
|
||||||
hmm_vec4 v4_1 = HMM_Vec4(1.0f, 2.0f, 3.0f, 4.0f);
|
hmm_vec4 v4_1 = HMM_Vec4(1.0f, 2.0f, 3.0f, 4.0f);
|
||||||
hmm_vec4 v4_2 = HMM_Vec4(5.0f, 6.0f, 7.0f, 8.0f);
|
hmm_vec4 v4_2 = HMM_Vec4(5.0f, 6.0f, 7.0f, 8.0f);
|
||||||
|
|
||||||
{
|
{
|
||||||
hmm_vec4 result = HMM_AddVec4(v4_1, v4_2);
|
hmm_vec4 result = HMM_AddVec4(v4_1, v4_2);
|
||||||
EXPECT_FLOAT_EQ(result.X, 6.0f);
|
EXPECT_FLOAT_EQ(result.X, 6.0f);
|
||||||
|
@@ -15,6 +15,9 @@ TEST(Equality, Vec2)
|
|||||||
|
|
||||||
EXPECT_TRUE(a == b);
|
EXPECT_TRUE(a == b);
|
||||||
EXPECT_FALSE(a == c);
|
EXPECT_FALSE(a == c);
|
||||||
|
|
||||||
|
EXPECT_FALSE(a != b);
|
||||||
|
EXPECT_TRUE(a != c);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,6 +36,9 @@ TEST(Equality, Vec3)
|
|||||||
|
|
||||||
EXPECT_TRUE(a == b);
|
EXPECT_TRUE(a == b);
|
||||||
EXPECT_FALSE(a == c);
|
EXPECT_FALSE(a == c);
|
||||||
|
|
||||||
|
EXPECT_FALSE(a != b);
|
||||||
|
EXPECT_TRUE(a != c);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,5 +57,8 @@ TEST(Equality, Vec4)
|
|||||||
|
|
||||||
EXPECT_TRUE(a == b);
|
EXPECT_TRUE(a == b);
|
||||||
EXPECT_FALSE(a == c);
|
EXPECT_FALSE(a == c);
|
||||||
|
|
||||||
|
EXPECT_FALSE(a != b);
|
||||||
|
EXPECT_TRUE(a != c);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@@ -4,9 +4,9 @@ TEST(Initialization, Vectors)
|
|||||||
{
|
{
|
||||||
//
|
//
|
||||||
// Test vec2
|
// Test vec2
|
||||||
//
|
//
|
||||||
hmm_vec2 v2 = HMM_Vec2(1.0f, 2.0f);
|
hmm_vec2 v2 = HMM_Vec2(1.0f, 2.0f);
|
||||||
hmm_vec2 v2i = HMM_Vec2(1, 2);
|
hmm_vec2 v2i = HMM_Vec2i(1, 2);
|
||||||
|
|
||||||
EXPECT_FLOAT_EQ(v2.X, 1.0f);
|
EXPECT_FLOAT_EQ(v2.X, 1.0f);
|
||||||
EXPECT_FLOAT_EQ(v2.Y, 2.0f);
|
EXPECT_FLOAT_EQ(v2.Y, 2.0f);
|
||||||
|
@@ -151,16 +151,16 @@ TEST(QuaternionOps, Mat4ToQuat)
|
|||||||
EXPECT_NEAR(result.W, cosf, abs_error);
|
EXPECT_NEAR(result.W, cosf, abs_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rotate 135 degrees on the Y axis (this hits case 4)
|
// Rotate 45 degrees on the X axis (this hits case 4)
|
||||||
{
|
{
|
||||||
hmm_mat4 m = HMM_Rotate(135, HMM_Vec3(0, 1, 0));
|
hmm_mat4 m = HMM_Rotate(45, HMM_Vec3(1, 0, 0));
|
||||||
hmm_quaternion result = HMM_Mat4ToQuaternion(m);
|
hmm_quaternion result = HMM_Mat4ToQuaternion(m);
|
||||||
|
|
||||||
float cosf = 0.3826834324f; // cos(135/2 degrees)
|
float cosf = 0.9238795325f; // cos(90/2 degrees)
|
||||||
float sinf = 0.9238795325f; // sin(135/2 degrees)
|
float sinf = 0.3826834324f; // sin(90/2 degrees)
|
||||||
|
|
||||||
EXPECT_NEAR(result.X, 0.0f, abs_error);
|
EXPECT_NEAR(result.X, sinf, abs_error);
|
||||||
EXPECT_NEAR(result.Y, sinf, abs_error);
|
EXPECT_NEAR(result.Y, 0.0f, abs_error);
|
||||||
EXPECT_NEAR(result.Z, 0.0f, abs_error);
|
EXPECT_NEAR(result.Z, 0.0f, abs_error);
|
||||||
EXPECT_NEAR(result.W, cosf, abs_error);
|
EXPECT_NEAR(result.W, cosf, abs_error);
|
||||||
}
|
}
|
||||||
@@ -176,4 +176,4 @@ TEST(QuaternionOps, FromAxisAngle)
|
|||||||
EXPECT_FLOAT_EQ(result.Y, 0.0f);
|
EXPECT_FLOAT_EQ(result.Y, 0.0f);
|
||||||
EXPECT_FLOAT_EQ(result.Z, 0.0f);
|
EXPECT_FLOAT_EQ(result.Z, 0.0f);
|
||||||
EXPECT_NEAR(result.W, 0.707107f, FLT_EPSILON * 2);
|
EXPECT_NEAR(result.W, 0.707107f, FLT_EPSILON * 2);
|
||||||
}
|
}
|
||||||
|
@@ -7,33 +7,33 @@ TEST(SSE, LinearCombine)
|
|||||||
hmm_mat4 MatrixOne = HMM_Mat4d(2.0f);
|
hmm_mat4 MatrixOne = HMM_Mat4d(2.0f);
|
||||||
hmm_mat4 MatrixTwo = HMM_Mat4d(4.0f);
|
hmm_mat4 MatrixTwo = HMM_Mat4d(4.0f);
|
||||||
hmm_mat4 Result;
|
hmm_mat4 Result;
|
||||||
|
|
||||||
Result.Columns[0] = HMM_LinearCombineSSE(MatrixOne.Columns[0], MatrixTwo);
|
Result.Columns[0] = HMM_LinearCombineSSE(MatrixOne.Columns[0], MatrixTwo);
|
||||||
Result.Columns[1] = HMM_LinearCombineSSE(MatrixOne.Columns[1], MatrixTwo);
|
Result.Columns[1] = HMM_LinearCombineSSE(MatrixOne.Columns[1], MatrixTwo);
|
||||||
Result.Columns[2] = HMM_LinearCombineSSE(MatrixOne.Columns[2], MatrixTwo);
|
Result.Columns[2] = HMM_LinearCombineSSE(MatrixOne.Columns[2], MatrixTwo);
|
||||||
Result.Columns[3] = HMM_LinearCombineSSE(MatrixOne.Columns[3], MatrixTwo);
|
Result.Columns[3] = HMM_LinearCombineSSE(MatrixOne.Columns[3], MatrixTwo);
|
||||||
|
|
||||||
{
|
{
|
||||||
EXPECT_FLOAT_EQ(Result.Elements[0][0], 8.0f);
|
EXPECT_FLOAT_EQ(Result.Elements[0][0], 8.0f);
|
||||||
EXPECT_FLOAT_EQ(Result.Elements[0][1], 0.0f);
|
EXPECT_FLOAT_EQ(Result.Elements[0][1], 0.0f);
|
||||||
EXPECT_FLOAT_EQ(Result.Elements[0][2], 0.0f);
|
EXPECT_FLOAT_EQ(Result.Elements[0][2], 0.0f);
|
||||||
EXPECT_FLOAT_EQ(Result.Elements[0][3], 0.0f);
|
EXPECT_FLOAT_EQ(Result.Elements[0][3], 0.0f);
|
||||||
|
|
||||||
EXPECT_FLOAT_EQ(Result.Elements[1][0], 0.0f);
|
EXPECT_FLOAT_EQ(Result.Elements[1][0], 0.0f);
|
||||||
EXPECT_FLOAT_EQ(Result.Elements[1][1], 8.0f);
|
EXPECT_FLOAT_EQ(Result.Elements[1][1], 8.0f);
|
||||||
EXPECT_FLOAT_EQ(Result.Elements[1][2], 0.0f);
|
EXPECT_FLOAT_EQ(Result.Elements[1][2], 0.0f);
|
||||||
EXPECT_FLOAT_EQ(Result.Elements[1][3], 0.0f);
|
EXPECT_FLOAT_EQ(Result.Elements[1][3], 0.0f);
|
||||||
|
|
||||||
EXPECT_FLOAT_EQ(Result.Elements[2][0], 0.0f);
|
EXPECT_FLOAT_EQ(Result.Elements[2][0], 0.0f);
|
||||||
EXPECT_FLOAT_EQ(Result.Elements[2][1], 0.0f);
|
EXPECT_FLOAT_EQ(Result.Elements[2][1], 0.0f);
|
||||||
EXPECT_FLOAT_EQ(Result.Elements[2][2], 8.0f);
|
EXPECT_FLOAT_EQ(Result.Elements[2][2], 8.0f);
|
||||||
EXPECT_FLOAT_EQ(Result.Elements[2][3], 0.0f);
|
EXPECT_FLOAT_EQ(Result.Elements[2][3], 0.0f);
|
||||||
|
|
||||||
EXPECT_FLOAT_EQ(Result.Elements[3][0], 0.0f);
|
EXPECT_FLOAT_EQ(Result.Elements[3][0], 0.0f);
|
||||||
EXPECT_FLOAT_EQ(Result.Elements[3][1], 0.0f);
|
EXPECT_FLOAT_EQ(Result.Elements[3][1], 0.0f);
|
||||||
EXPECT_FLOAT_EQ(Result.Elements[3][2], 0.0f);
|
EXPECT_FLOAT_EQ(Result.Elements[3][2], 0.0f);
|
||||||
EXPECT_FLOAT_EQ(Result.Elements[3][3], 8.0f);
|
EXPECT_FLOAT_EQ(Result.Elements[3][3], 8.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -24,6 +24,14 @@ TEST(ScalarMath, Trigonometry)
|
|||||||
EXPECT_NEAR(HMM_TanF(HMM_PI32), 0.0f, trigAbsError);
|
EXPECT_NEAR(HMM_TanF(HMM_PI32), 0.0f, trigAbsError);
|
||||||
EXPECT_NEAR(HMM_TanF(-HMM_PI32 / 4), -1.0f, trigAbsError);
|
EXPECT_NEAR(HMM_TanF(-HMM_PI32 / 4), -1.0f, trigAbsError);
|
||||||
|
|
||||||
|
EXPECT_NEAR(HMM_ATanF(0.0f), 0.0f, trigAbsError);
|
||||||
|
EXPECT_NEAR(HMM_ATanF(HMM_PI32), 1.2626272557f, trigAbsError);
|
||||||
|
EXPECT_NEAR(HMM_ATanF(-HMM_PI32), -1.2626272557f, trigAbsError);
|
||||||
|
|
||||||
|
EXPECT_NEAR(HMM_ATan2F(0.0f, 1.0f), 0.0f, trigAbsError);
|
||||||
|
EXPECT_NEAR(HMM_ATan2F(1.0f, 1.0f), HMM_PI32 / 4.0f, trigAbsError);
|
||||||
|
EXPECT_NEAR(HMM_ATan2F(1.0f, 0.0f), HMM_PI32 / 2.0f, trigAbsError);
|
||||||
|
|
||||||
// This isn't the most rigorous because we're really just sanity-
|
// This isn't the most rigorous because we're really just sanity-
|
||||||
// checking that things work by default.
|
// checking that things work by default.
|
||||||
}
|
}
|
||||||
@@ -35,6 +43,18 @@ TEST(ScalarMath, ToRadians)
|
|||||||
EXPECT_FLOAT_EQ(HMM_ToRadians(-180.0f), -HMM_PI32);
|
EXPECT_FLOAT_EQ(HMM_ToRadians(-180.0f), -HMM_PI32);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(ScalarMath, ExpF)
|
||||||
|
{
|
||||||
|
EXPECT_NEAR(HMM_ExpF(0.0f), 1.0f, 0.0001f);
|
||||||
|
EXPECT_NEAR(HMM_ExpF(1.0f), 2.7182818285f, 0.0001f);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ScalarMath, LogF)
|
||||||
|
{
|
||||||
|
EXPECT_NEAR(HMM_LogF(1.0f), 0.0f, 0.0001f);
|
||||||
|
EXPECT_NEAR(HMM_LogF(2.7182818285f), 1.0f, 0.0001f);
|
||||||
|
}
|
||||||
|
|
||||||
TEST(ScalarMath, SquareRoot)
|
TEST(ScalarMath, SquareRoot)
|
||||||
{
|
{
|
||||||
EXPECT_FLOAT_EQ(HMM_SquareRootF(16.0f), 4.0f);
|
EXPECT_FLOAT_EQ(HMM_SquareRootF(16.0f), 4.0f);
|
||||||
@@ -48,7 +68,7 @@ TEST(ScalarMath, RSquareRootF)
|
|||||||
TEST(ScalarMath, Power)
|
TEST(ScalarMath, Power)
|
||||||
{
|
{
|
||||||
EXPECT_FLOAT_EQ(HMM_Power(2.0f, 0), 1.0f);
|
EXPECT_FLOAT_EQ(HMM_Power(2.0f, 0), 1.0f);
|
||||||
EXPECT_FLOAT_EQ(HMM_Power(2.0f, 4), 16.0f);
|
EXPECT_FLOAT_EQ(HMM_Power(2.0f, 4), 16.0f);
|
||||||
EXPECT_FLOAT_EQ(HMM_Power(2.0f, -2), 0.25f);
|
EXPECT_FLOAT_EQ(HMM_Power(2.0f, -2), 0.25f);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,14 +81,14 @@ TEST(ScalarMath, PowerF)
|
|||||||
|
|
||||||
TEST(ScalarMath, Lerp)
|
TEST(ScalarMath, Lerp)
|
||||||
{
|
{
|
||||||
EXPECT_FLOAT_EQ(HMM_Lerp(-2.0f, 0.0f, 2.0f), -2.0f);
|
EXPECT_FLOAT_EQ(HMM_Lerp(-2.0f, 0.0f, 2.0f), -2.0f);
|
||||||
EXPECT_FLOAT_EQ(HMM_Lerp(-2.0f, 0.5f, 2.0f), 0.0f);
|
EXPECT_FLOAT_EQ(HMM_Lerp(-2.0f, 0.5f, 2.0f), 0.0f);
|
||||||
EXPECT_FLOAT_EQ(HMM_Lerp(-2.0f, 1.0f, 2.0f), 2.0f);
|
EXPECT_FLOAT_EQ(HMM_Lerp(-2.0f, 1.0f, 2.0f), 2.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ScalarMath, Clamp)
|
TEST(ScalarMath, Clamp)
|
||||||
{
|
{
|
||||||
EXPECT_FLOAT_EQ(HMM_Clamp(-2.0f, 0.0f, 2.0f), 0.0f);
|
EXPECT_FLOAT_EQ(HMM_Clamp(-2.0f, 0.0f, 2.0f), 0.0f);
|
||||||
EXPECT_FLOAT_EQ(HMM_Clamp(-2.0f, -3.0f, 2.0f), -2.0f);
|
EXPECT_FLOAT_EQ(HMM_Clamp(-2.0f, -3.0f, 2.0f), -2.0f);
|
||||||
EXPECT_FLOAT_EQ(HMM_Clamp(-2.0f, 3.0f, 2.0f), 2.0f);
|
EXPECT_FLOAT_EQ(HMM_Clamp(-2.0f, 3.0f, 2.0f), 2.0f);
|
||||||
}
|
}
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
TEST(VectorOps, LengthSquared)
|
TEST(VectorOps, LengthSquared)
|
||||||
{
|
{
|
||||||
hmm_vec2 v2 = HMM_Vec2(1.0f, -2.0f);
|
hmm_vec2 v2 = HMM_Vec2(1.0f, -2.0f);
|
||||||
hmm_vec3 v3 = HMM_Vec3(1.0f, -2.0f, 3.0f);
|
hmm_vec3 v3 = HMM_Vec3(1.0f, -2.0f, 3.0f);
|
||||||
hmm_vec4 v4 = HMM_Vec4(1.0f, -2.0f, 3.0f, 1.0f);
|
hmm_vec4 v4 = HMM_Vec4(1.0f, -2.0f, 3.0f, 1.0f);
|
||||||
|
|
||||||
EXPECT_FLOAT_EQ(HMM_LengthSquaredVec2(v2), 5.0f);
|
EXPECT_FLOAT_EQ(HMM_LengthSquaredVec2(v2), 5.0f);
|
||||||
@@ -37,7 +37,7 @@ TEST(VectorOps, Length)
|
|||||||
TEST(VectorOps, Normalize)
|
TEST(VectorOps, Normalize)
|
||||||
{
|
{
|
||||||
hmm_vec2 v2 = HMM_Vec2(1.0f, -2.0f);
|
hmm_vec2 v2 = HMM_Vec2(1.0f, -2.0f);
|
||||||
hmm_vec3 v3 = HMM_Vec3(1.0f, -2.0f, 3.0f);
|
hmm_vec3 v3 = HMM_Vec3(1.0f, -2.0f, 3.0f);
|
||||||
hmm_vec4 v4 = HMM_Vec4(1.0f, -2.0f, 3.0f, -1.0f);
|
hmm_vec4 v4 = HMM_Vec4(1.0f, -2.0f, 3.0f, -1.0f);
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@@ -1,7 +1,9 @@
|
|||||||
#include "HandmadeTest.h"
|
|
||||||
#include "hmm_test.h"
|
#include "hmm_test.h"
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
return hmt_run_all_tests();
|
int tests_failed = hmt_run_all_tests();
|
||||||
|
int coverage_failed = hmt_check_all_coverage();
|
||||||
|
|
||||||
|
return tests_failed || coverage_failed;
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,8 @@
|
|||||||
#include <float.h>
|
#include <float.h>
|
||||||
|
|
||||||
|
#define HANDMADE_TEST_IMPLEMENTATION
|
||||||
#include "HandmadeTest.h"
|
#include "HandmadeTest.h"
|
||||||
|
|
||||||
#include "../HandmadeMath.h"
|
#include "../HandmadeMath.h"
|
||||||
|
|
||||||
#include "categories/ScalarMath.h"
|
#include "categories/ScalarMath.h"
|
||||||
|
Reference in New Issue
Block a user