diff --git a/.github/workflows/meson_ci.yml b/.github/workflows/meson_ci.yml index 2bd197aa..5d7a255c 100644 --- a/.github/workflows/meson_ci.yml +++ b/.github/workflows/meson_ci.yml @@ -5,6 +5,9 @@ on: paths: - "**.c" - "**.h" + - "**.cpp" + - "**.hpp" + - "**.rs" - "**.py" - "**.build" - "**.options" @@ -12,6 +15,9 @@ on: paths: - "**.c" - "**.h" + - "**.cpp" + - "**.hpp" + - "**.rs" - "**.py" - "**.build" - "**.options" diff --git a/code/logic/fossil/test/benchmark.h b/code/logic/fossil/test/benchmark.h index 5ac8b8a9..5cd5efc5 100644 --- a/code/logic/fossil/test/benchmark.h +++ b/code/logic/fossil/test/benchmark.h @@ -137,9 +137,6 @@ uint64_t fossil_test_stop_benchmark(void); #endif #ifdef __cplusplus -#include -#include - namespace fossil { } diff --git a/code/logic/fossil/test/mockup.h b/code/logic/fossil/test/mockup.h index ddb884d7..6242250c 100644 --- a/code/logic/fossil/test/mockup.h +++ b/code/logic/fossil/test/mockup.h @@ -159,9 +159,6 @@ void fossil_mock_print(MockCallList *list); #endif #ifdef __cplusplus -#include -#include - namespace fossil { } diff --git a/code/logic/fossil/test/unittest.h b/code/logic/fossil/test/unittest.h index ce6faea8..c3462853 100644 --- a/code/logic/fossil/test/unittest.h +++ b/code/logic/fossil/test/unittest.h @@ -212,7 +212,27 @@ void fossil_test_print_stack_trace(stack_frame_t *stack_trace); #define _FOSSIL_TEST_ASSUME(condition, message) \ fossil_test_assert_internal((condition), (message), __FILE__, __LINE__, __func__) +// Macro for defining test data structures +#define _FOSSIL_TEST_DATA(name) \ + typedef struct name + // Macro for defining a test case +#ifdef __cplusplus +#define _FOSSIL_TEST_CASE(test_name) \ + void test_name##_test_func(void); \ + test_case_t test_name##_test_case = { \ + #test_name, \ + test_name##_test_func, \ + nullptr, \ + nullptr, \ + TEST_STATUS_PASS, \ + nullptr, \ + nullptr, \ + 0.0, \ + nullptr \ + }; \ + void test_name##_test_func(void) +#else #define _FOSSIL_TEST_CASE(test_name) \ void test_name##_test_func(void); \ test_case_t test_name##_test_case = { \ @@ -222,36 +242,47 @@ void fossil_test_print_stack_trace(stack_frame_t *stack_trace); .teardown_func = NULL, \ .status = TEST_STATUS_PASS, \ .failure_message = NULL, \ - .execution_time = 0.0, \ .stack_trace = NULL, \ + .execution_time = 0.0, \ .next = NULL \ }; \ void test_name##_test_func(void) - -// Macro for defining test data structures -#define _FOSSIL_TEST_DATA(name) \ - typedef struct name - -// Macro for setting up a test case -#define _FOSSIL_TEST_SETUP(name) \ - void name##_setup_func(void) - -// Macro for tearing down a test case -#define _FOSSIL_TEST_TEARDOWN(name) \ - void name##_teardown_func(void) +#endif // Macro to create a test suite with setup and teardown hooks +#ifdef __cplusplus +#define _FOSSIL_TEST_SUITE(suite_name) \ + void suite_name##_setup_func(void); \ + void suite_name##_teardown_func(void); \ + test_suite_t suite_name = { \ + #suite_name, \ + suite_name##_setup_func, \ + suite_name##_teardown_func, \ + 0.0, \ + nullptr, \ + nullptr \ + } +#else #define _FOSSIL_TEST_SUITE(suite_name) \ void suite_name##_setup_func(void); \ void suite_name##_teardown_func(void); \ test_suite_t suite_name = { \ .name = #suite_name, \ - .tests = NULL, \ - .total_execution_time = 0.0, \ .suite_setup_func = suite_name##_setup_func, \ .suite_teardown_func = suite_name##_teardown_func, \ + .total_execution_time = 0.0, \ + .tests = NULL, \ .next = NULL \ } +#endif + +// Macro for setting up a test case +#define _FOSSIL_TEST_SETUP(name) \ + void name##_setup_func(void) + +// Macro for tearing down a test case +#define _FOSSIL_TEST_TEARDOWN(name) \ + void name##_teardown_func(void) // Macro to register a suite with the test environment #define _FOSSIL_TEST_REGISTER(suite) \ @@ -315,12 +346,9 @@ void fossil_test_print_stack_trace(stack_frame_t *stack_trace); #endif #ifdef __cplusplus -#include -#include - namespace fossil { -} +} // namespace fossil #endif #endif diff --git a/code/tests/test_bdd.c b/code/tests/cases/test_bdd.c similarity index 85% rename from code/tests/test_bdd.c rename to code/tests/cases/test_bdd.c index ddb0a7c0..31ff1970 100644 --- a/code/tests/test_bdd.c +++ b/code/tests/cases/test_bdd.c @@ -137,14 +137,36 @@ FOSSIL_TEST_CASE(xbdd_valid_login) { } } // end of case +FOSSIL_TEST_CASE(xbdd_invalid_login) { + GIVEN("a registered user with valid credentials") { + // Set up the context + const char* validUsername = "user123"; + const char* validPassword = "pass456"; + + WHEN("the user provides incorrect username") { + // Perform the action of user login + const char* inputUsername = "wronguser"; + const char* inputPassword = "pass456"; + + THEN("the login should fail with an error message") { + // Check the expected outcome + // Simulate login validation + FOSSIL_TEST_ASSUME(strcmp(inputUsername, validUsername) != 0, "Username should not match"); + FOSSIL_TEST_ASSUME(strcmp(inputPassword, validPassword) == 0, "Password should match"); + } + } + } +} // end of case + // * * * * * * * * * * * * * * * * * * * * * * * * // * Fossil Logic Test Pool // * * * * * * * * * * * * * * * * * * * * * * * * -FOSSIL_TEST_GROUP(bdd_test_group) { +FOSSIL_TEST_GROUP(c_bdd_test_cases) { FOSSIL_TEST_ADD(bdd_suite, xbdd_logic_test); FOSSIL_TEST_ADD(bdd_suite, xbdd_user_account); FOSSIL_TEST_ADD(bdd_suite, xbdd_empty_cart); FOSSIL_TEST_ADD(bdd_suite, xbdd_valid_login); + FOSSIL_TEST_ADD(bdd_suite, xbdd_invalid_login); FOSSIL_TEST_REGISTER(bdd_suite); } // end of group diff --git a/code/tests/cases/test_bdd.cpp b/code/tests/cases/test_bdd.cpp new file mode 100644 index 00000000..0c365317 --- /dev/null +++ b/code/tests/cases/test_bdd.cpp @@ -0,0 +1,172 @@ +/* + * ----------------------------------------------------------------------------- + * Project: Fossil Logic + * + * This file is part of the Fossil Logic project, which aims to develop high- + * performance, cross-platform applications and libraries. The code contained + * herein is subject to the terms and conditions defined in the project license. + * + * Author: Michael Gene Brockus (Dreamer) + * Date: 07/01/2024 + * + * Copyright (C) 2024 Fossil Logic. All rights reserved. + * ----------------------------------------------------------------------------- + */ +#include + +// * * * * * * * * * * * * * * * * * * * * * * * * +// * Fossil Logic Test Utilites +// * * * * * * * * * * * * * * * * * * * * * * * * +// Setup steps for things like test fixtures and +// mock objects are set here. +// * * * * * * * * * * * * * * * * * * * * * * * * + +// Define the test suite and add test cases +FOSSIL_TEST_SUITE(cpp_bdd_suite); + +// Setup function for the test suite +FOSSIL_SETUP(cpp_bdd_suite) { + // Setup code here +} + +// Teardown function for the test suite +FOSSIL_TEARDOWN(cpp_bdd_suite) { + // Teardown code here +} + +// * * * * * * * * * * * * * * * * * * * * * * * * +// * Fossil Logic Test Cases +// * * * * * * * * * * * * * * * * * * * * * * * * +// The test cases below are provided as samples, inspired +// by the Meson build system's approach of using test cases +// as samples for library usage. +// * * * * * * * * * * * * * * * * * * * * * * * * + +FOSSIL_TEST_CASE(cpp_xbdd_logic_test) { + GIVEN("a valid statement is passed") { + // Set up the context + bool givenExecuted = true; + + WHEN("a statement is true") { + // Perform the login action + bool whenExecuted = true; + + THEN("we validate everything was worked") { + // Check the expected outcome + bool thenExecuted = true; + + FOSSIL_TEST_ASSUME(givenExecuted, "Given statement should have executed"); + FOSSIL_TEST_ASSUME(whenExecuted, "When statement should have executed"); + FOSSIL_TEST_ASSUME(thenExecuted, "Then statement should have executed"); + } + } + } +} // end of case + +FOSSIL_TEST_CASE(cpp_xbdd_user_account) { + GIVEN("a user's account with sufficient balance") { + // Set up the context + float accountBalance = 500.0; + float withdrawalAmount = 200.0; + + WHEN("the user requests a withdrawal of $200") { + // Perform the withdrawal action + if (accountBalance >= withdrawalAmount) { + accountBalance -= withdrawalAmount; + } // end if + THEN("the withdrawal amount should be deducted from the account balance") { + // Check the expected outcome + + // Simulate the scenario + float compareBalance = 500.0; + FOSSIL_TEST_ASSUME(accountBalance == (compareBalance - withdrawalAmount), "Account balance should have been deducted by $200"); + } + } + } +} // end of case + +FOSSIL_TEST_CASE(cpp_xbdd_empty_cart) { + GIVEN("a user with an empty shopping cart") { + // Set up the context + int cartItemCount = 0; + + WHEN("the user adds a product to the cart") { + // Perform the action of adding a product + + THEN("the cart item count should increase by 1") { + // Check the expected outcome + cartItemCount++; + + FOSSIL_TEST_ASSUME(cartItemCount == 1, "Cart item count should have increased by 1"); + } + } + } +} // end of case + +FOSSIL_TEST_CASE(cpp_xbdd_valid_login) { + GIVEN("a registered user with valid credentials") { + // Set up the context + const char* validUsername = "user123"; + const char* validPassword = "pass456"; + + WHEN("the user provides correct username and password") { + // Perform the action of user login + const char* inputUsername = "user123"; + const char* inputPassword = "pass456"; + + THEN("the login should be successful") { + // Check the expected outcome + // Simulate login validation + FOSSIL_TEST_ASSUME(strcmp(inputUsername, validUsername) == 0, "Username should match"); + FOSSIL_TEST_ASSUME(strcmp(inputPassword, validPassword) == 0, "Password should match"); + } + } + + WHEN("the user provides incorrect password") { + // Perform the action of user login + const char* inputUsername = "user123"; + const char* inputPassword = "wrongpass"; + + THEN("the login should fail with an error message") { + // Check the expected outcome + // Simulate login validation + FOSSIL_TEST_ASSUME(strcmp(inputUsername, validUsername) == 0, "Username should match"); + FOSSIL_TEST_ASSUME(strcmp(inputPassword, validPassword) != 0, "Password should not match"); + } + } + } +} // end of case + +FOSSIL_TEST_CASE(cpp_xbdd_invalid_login) { + GIVEN("a registered user with valid credentials") { + // Set up the context + const char* validUsername = "user123"; + const char* validPassword = "pass456"; + + WHEN("the user provides incorrect username") { + // Perform the action of user login + const char* inputUsername = "wronguser"; + const char* inputPassword = "pass456"; + + THEN("the login should fail with an error message") { + // Check the expected outcome + // Simulate login validation + FOSSIL_TEST_ASSUME(strcmp(inputUsername, validUsername) != 0, "Username should not match"); + FOSSIL_TEST_ASSUME(strcmp(inputPassword, validPassword) == 0, "Password should match"); + } + } + } +} // end of case + +// * * * * * * * * * * * * * * * * * * * * * * * * +// * Fossil Logic Test Pool +// * * * * * * * * * * * * * * * * * * * * * * * * +FOSSIL_TEST_GROUP(cpp_bdd_test_cases) { + FOSSIL_TEST_ADD(cpp_bdd_suite, cpp_xbdd_logic_test); + FOSSIL_TEST_ADD(cpp_bdd_suite, cpp_xbdd_user_account); + FOSSIL_TEST_ADD(cpp_bdd_suite, cpp_xbdd_empty_cart); + FOSSIL_TEST_ADD(cpp_bdd_suite, cpp_xbdd_valid_login); + FOSSIL_TEST_ADD(cpp_bdd_suite, cpp_xbdd_invalid_login); + + FOSSIL_TEST_REGISTER(cpp_bdd_suite); +} // end of group diff --git a/code/tests/test_sample.c b/code/tests/cases/test_sample.c similarity index 62% rename from code/tests/test_sample.c rename to code/tests/cases/test_sample.c index 34983dc2..eed168d4 100644 --- a/code/tests/test_sample.c +++ b/code/tests/cases/test_sample.c @@ -16,10 +16,10 @@ #include "fossil/test/framework.h" // Test data structure for a sample test -FOSSIL_TEST_DATA(SampleTestData) { +FOSSIL_TEST_DATA(CSampleTestData) { int input; int expected_output; -} SampleTestData; +} CSampleTestData; // Setup function for the test suite FOSSIL_SETUP(sample_suite) { @@ -36,7 +36,7 @@ FOSSIL_TEST_SUITE(sample_suite); // A simple test case to check if input + 1 equals expected_output FOSSIL_TEST_CASE(test_input_increment) { - SampleTestData data = { .input = 5, .expected_output = 6 }; + CSampleTestData data = { .input = 5, .expected_output = 6 }; int actual_output = data.input + 1; @@ -45,16 +45,36 @@ FOSSIL_TEST_CASE(test_input_increment) { // A simple test case to check if input - 1 equals expected_output FOSSIL_TEST_CASE(test_input_decrement) { - SampleTestData data = { .input = 5, .expected_output = 4 }; + CSampleTestData data = { .input = 5, .expected_output = 4 }; int actual_output = data.input - 1; FOSSIL_TEST_ASSUME(actual_output == data.expected_output, "Decrement test failed"); } -FOSSIL_TEST_GROUP(sample_test_group) { +// A simple test case to check if input * 2 equals expected_output +FOSSIL_TEST_CASE(test_input_double) { + CSampleTestData data = { .input = 5, .expected_output = 10 }; + + int actual_output = data.input * 2; + + FOSSIL_TEST_ASSUME(actual_output == data.expected_output, "Double test failed"); +} + +// A simple test case to check if input / 2 equals expected_output +FOSSIL_TEST_CASE(test_input_half) { + CSampleTestData data = { .input = 10, .expected_output = 5 }; + + int actual_output = data.input / 2; + + FOSSIL_TEST_ASSUME(actual_output == data.expected_output, "Half test failed"); +} + +FOSSIL_TEST_GROUP(c_sample_test_cases) { FOSSIL_TEST_ADD(sample_suite, test_input_increment); FOSSIL_TEST_ADD(sample_suite, test_input_decrement); + FOSSIL_TEST_ADD(sample_suite, test_input_double); + FOSSIL_TEST_ADD(sample_suite, test_input_half); FOSSIL_TEST_REGISTER(sample_suite); } diff --git a/code/tests/cases/test_sample.cpp b/code/tests/cases/test_sample.cpp new file mode 100644 index 00000000..e8b33f3f --- /dev/null +++ b/code/tests/cases/test_sample.cpp @@ -0,0 +1,80 @@ +/* + * ----------------------------------------------------------------------------- + * Project: Fossil Logic + * + * This file is part of the Fossil Logic project, which aims to develop high- + * performance, cross-platform applications and libraries. The code contained + * herein is subject to the terms and conditions defined in the project license. + * + * Author: Michael Gene Brockus (Dreamer) + * Date: 07/01/2024 + * + * Copyright (C) 2024 Fossil Logic. All rights reserved. + * ----------------------------------------------------------------------------- + */ + +#include "fossil/test/framework.h" + +// Test data structure for a sample test +struct CppSampleTestData { + int input; + int expected_output; +}; + +// Setup function for the test suite +FOSSIL_SETUP(cpp_sample_suite) { + // Setup code here +} + +// Teardown function for the test suite +FOSSIL_TEARDOWN(cpp_sample_suite) { + // Teardown code here +} + +// Define the test suite and add test cases +FOSSIL_TEST_SUITE(cpp_sample_suite); + +// A simple test case to check if input + 1 equals expected_output +FOSSIL_TEST_CASE(cpp_test_input_increment) { + CppSampleTestData data = {5, 6}; // Simplified initialization + + int actual_output = data.input + 1; + + FOSSIL_TEST_ASSUME(actual_output == data.expected_output, "Increment test failed"); +} + +// A simple test case to check if input - 1 equals expected_output +FOSSIL_TEST_CASE(cpp_test_input_decrement) { + CppSampleTestData data = {5, 4}; // Simplified initialization + + int actual_output = data.input - 1; + + FOSSIL_TEST_ASSUME(actual_output == data.expected_output, "Decrement test failed"); +} + +// A simple test case to check if input * 2 equals expected_output +FOSSIL_TEST_CASE(cpp_test_input_double) { + CppSampleTestData data = {5, 10}; // Simplified initialization + + int actual_output = data.input * 2; + + FOSSIL_TEST_ASSUME(actual_output == data.expected_output, "Double test failed"); +} + +// A simple test case to check if input / 2 equals expected_output +FOSSIL_TEST_CASE(cpp_test_input_half) { + CppSampleTestData data = {10, 5}; // Simplified initialization + + int actual_output = data.input / 2; + + FOSSIL_TEST_ASSUME(actual_output == data.expected_output, "Half test failed"); +} + +FOSSIL_TEST_GROUP(cpp_sample_test_cases) { + FOSSIL_TEST_ADD(cpp_sample_suite, cpp_test_input_increment); + FOSSIL_TEST_ADD(cpp_sample_suite, cpp_test_input_decrement); + FOSSIL_TEST_ADD(cpp_sample_suite, cpp_test_input_double); + FOSSIL_TEST_ADD(cpp_sample_suite, cpp_test_input_half); + + FOSSIL_TEST_REGISTER(cpp_sample_suite); +} diff --git a/code/tests/test_tdd.c b/code/tests/cases/test_tdd.c similarity index 99% rename from code/tests/test_tdd.c rename to code/tests/cases/test_tdd.c index dc19182f..3525ef77 100644 --- a/code/tests/test_tdd.c +++ b/code/tests/cases/test_tdd.c @@ -153,7 +153,7 @@ FOSSIL_TEST_CASE(xassume_run_of_int64_shortcut) { // * * * * * * * * * * * * * * * * * * * * * * * * // * Fossil Logic Test Pool // * * * * * * * * * * * * * * * * * * * * * * * * -FOSSIL_TEST_GROUP(tdd_test_group) { +FOSSIL_TEST_GROUP(c_tdd_test_cases) { FOSSIL_TEST_ADD(tdd_suite, xassume_run_of_int); FOSSIL_TEST_ADD(tdd_suite, xassume_run_of_int8); FOSSIL_TEST_ADD(tdd_suite, xassume_run_of_int16); diff --git a/code/tests/cases/test_tdd.cpp b/code/tests/cases/test_tdd.cpp new file mode 100644 index 00000000..6f1e065a --- /dev/null +++ b/code/tests/cases/test_tdd.cpp @@ -0,0 +1,168 @@ +/* + * ----------------------------------------------------------------------------- + * Project: Fossil Logic + * + * This file is part of the Fossil Logic project, which aims to develop high- + * performance, cross-platform applications and libraries. The code contained + * herein is subject to the terms and conditions defined in the project license. + * + * Author: Michael Gene Brockus (Dreamer) + * Date: 07/01/2024 + * + * Copyright (C) 2024 Fossil Logic. All rights reserved. + * ----------------------------------------------------------------------------- + */ +#include + +// * * * * * * * * * * * * * * * * * * * * * * * * +// * Fossil Logic Test Utilites +// * * * * * * * * * * * * * * * * * * * * * * * * +// Setup steps for things like test fixtures and +// mock objects are set here. +// * * * * * * * * * * * * * * * * * * * * * * * * + +// Define the test suite and add test cases +FOSSIL_TEST_SUITE(cpp_tdd_suite); + +// Setup function for the test suite +FOSSIL_SETUP(cpp_tdd_suite) { + // Setup code here +} + +// Teardown function for the test suite +FOSSIL_TEARDOWN(cpp_tdd_suite) { + // Teardown code here +} + +// * * * * * * * * * * * * * * * * * * * * * * * * +// * Fossil Logic Test Cases +// * * * * * * * * * * * * * * * * * * * * * * * * +// The test cases below are provided as samples, inspired +// by the Meson build system's approach of using test cases +// as samples for library usage. +// * * * * * * * * * * * * * * * * * * * * * * * * + +FOSSIL_TEST_CASE(cpp_xassume_run_of_int) { + int x = 42; + int y = 20; + + // Test cases + FOSSIL_TEST_ASSUME(x == 42, "Should have passed the test case"); + FOSSIL_TEST_ASSUME(y == 20, "Should have passed the test case"); + FOSSIL_TEST_ASSUME(x != y, "Should have passed the test case"); + FOSSIL_TEST_ASSUME(y < x, "Should have passed the test case"); + FOSSIL_TEST_ASSUME(y <= x, "Should have passed the test case"); +} // end case + +FOSSIL_TEST_CASE(cpp_xassume_run_of_int8) { + int8_t x = 42; + int8_t y = 20; + + // Test cases + FOSSIL_TEST_ASSUME((int8_t)x == 42, "Should have passed the test case"); + FOSSIL_TEST_ASSUME((int8_t)y == 20, "Should have passed the test case"); + FOSSIL_TEST_ASSUME((int8_t)x != (int8_t)y, "Should have passed the test case"); + FOSSIL_TEST_ASSUME((int8_t)y < (int8_t)x, "Should have passed the test case"); + FOSSIL_TEST_ASSUME((int8_t)y <= (int8_t)x, "Should have passed the test case"); +} // end case + +FOSSIL_TEST_CASE(cpp_xassume_run_of_int16) { + int16_t x = 42; + int16_t y = 20; + + // Test cases + FOSSIL_TEST_ASSUME((int16_t)x == 42, "Should have passed the test case"); + FOSSIL_TEST_ASSUME((int16_t)y == 20, "Should have passed the test case"); + FOSSIL_TEST_ASSUME((int16_t)x != (int16_t)y, "Should have passed the test case"); + FOSSIL_TEST_ASSUME((int16_t)y < (int16_t)x, "Should have passed the test case"); + FOSSIL_TEST_ASSUME((int16_t)y <= (int16_t)x, "Should have passed the test case"); +} // end case + +FOSSIL_TEST_CASE(cpp_xassume_run_of_int32) { + int32_t x = 42; + int32_t y = 20; + + // Test cases + FOSSIL_TEST_ASSUME((int32_t)x == 42, "Should have passed the test case"); + FOSSIL_TEST_ASSUME((int32_t)y == 20, "Should have passed the test case"); + FOSSIL_TEST_ASSUME((int32_t)x != (int32_t)y, "Should have passed the test case"); + FOSSIL_TEST_ASSUME((int32_t)y < (int32_t)x, "Should have passed the test case"); + FOSSIL_TEST_ASSUME((int32_t)y <= (int32_t)x, "Should have passed the test case"); +} // end case + +FOSSIL_TEST_CASE(cpp_xassume_run_of_int64) { + int64_t x = 42; + int64_t y = 20; + + // Test cases + FOSSIL_TEST_ASSUME((int64_t)x == 42, "Should have passed the test case"); + FOSSIL_TEST_ASSUME((int64_t)y == 20, "Should have passed the test case"); + FOSSIL_TEST_ASSUME((int64_t)x != (int64_t)y, "Should have passed the test case"); + FOSSIL_TEST_ASSUME((int64_t)y < (int64_t)x, "Should have passed the test case"); + FOSSIL_TEST_ASSUME((int64_t)y <= (int64_t)x, "Should have passed the test case"); +} // end case + +FOSSIL_TEST_CASE(cpp_xassume_run_of_int8_shortcut) { + int8_t x = 42; + int8_t y = 20; + + // Test cases + ASSUME_ITS_EQUAL_I8((int8_t)x, 42); + ASSUME_ITS_EQUAL_I8((int8_t)y, 20); + ASSUME_NOT_EQUAL_I8((int8_t)x, (int8_t)y); + ASSUME_ITS_LESS_THAN_I8((int8_t)y, (int8_t)x); + ASSUME_ITS_LESS_OR_EQUAL_I8((int8_t)y, (int8_t)x); +} // end case + +FOSSIL_TEST_CASE(cpp_xassume_run_of_int16_shortcut) { + int16_t x = 42; + int16_t y = 20; + + // Test cases + ASSUME_ITS_EQUAL_I16((int16_t)x, 42); + ASSUME_ITS_EQUAL_I16((int16_t)y, 20); + ASSUME_NOT_EQUAL_I16((int16_t)x, (int16_t)y); + ASSUME_ITS_LESS_THAN_I16((int16_t)y, (int16_t)x); + ASSUME_ITS_LESS_OR_EQUAL_I16((int16_t)y, (int16_t)x); +} // end case + +FOSSIL_TEST_CASE(cpp_xassume_run_of_int32_shortcut) { + int32_t x = 42; + int32_t y = 20; + + // Test cases + ASSUME_ITS_EQUAL_I32((int32_t)x, 42); + ASSUME_ITS_EQUAL_I32((int32_t)y, 20); + ASSUME_NOT_EQUAL_I32((int32_t)x, (int32_t)y); + ASSUME_ITS_LESS_THAN_I32((int32_t)y, (int32_t)x); + ASSUME_ITS_LESS_OR_EQUAL_I32((int32_t)y, (int32_t)x); +} // end case + +FOSSIL_TEST_CASE(cpp_xassume_run_of_int64_shortcut) { + int64_t x = 42; + int64_t y = 20; + + // Test cases + ASSUME_ITS_EQUAL_I64((int64_t)x, 42); + ASSUME_ITS_EQUAL_I64((int64_t)y, 20); + ASSUME_NOT_EQUAL_I64((int64_t)x, (int64_t)y); + ASSUME_ITS_LESS_THAN_I64((int64_t)y, (int64_t)x); + ASSUME_ITS_LESS_OR_EQUAL_I64((int64_t)y, (int64_t)x); +} // end case + +// * * * * * * * * * * * * * * * * * * * * * * * * +// * Fossil Logic Test Pool +// * * * * * * * * * * * * * * * * * * * * * * * * +FOSSIL_TEST_GROUP(cpp_tdd_test_cases) { + FOSSIL_TEST_ADD(cpp_tdd_suite, cpp_xassume_run_of_int); + FOSSIL_TEST_ADD(cpp_tdd_suite, cpp_xassume_run_of_int8); + FOSSIL_TEST_ADD(cpp_tdd_suite, cpp_xassume_run_of_int16); + FOSSIL_TEST_ADD(cpp_tdd_suite, cpp_xassume_run_of_int32); + FOSSIL_TEST_ADD(cpp_tdd_suite, cpp_xassume_run_of_int64); + FOSSIL_TEST_ADD(cpp_tdd_suite, cpp_xassume_run_of_int8_shortcut); + FOSSIL_TEST_ADD(cpp_tdd_suite, cpp_xassume_run_of_int16_shortcut); + FOSSIL_TEST_ADD(cpp_tdd_suite, cpp_xassume_run_of_int32_shortcut); + FOSSIL_TEST_ADD(cpp_tdd_suite, cpp_xassume_run_of_int64_shortcut); + + FOSSIL_TEST_REGISTER(cpp_tdd_suite); +} // end of group diff --git a/code/tests/meson.build b/code/tests/meson.build index b69d25fb..24b31a86 100644 --- a/code/tests/meson.build +++ b/code/tests/meson.build @@ -1,15 +1,20 @@ if get_option('with_test').enabled() run_command(['python3', 'tools' / 'generate-runner.py'], check: true) - test_src = ['unit_runner.c'] - test_cubes = [ + test_c = ['unit_runner.c'] + test_cpp = ['unit_runner.cpp'] + test_cases = [ 'sample', 'bdd', 'tdd', ] - foreach cube : test_cubes - test_src += ['test_' + cube + '.c'] + foreach cases : test_cases + test_c += ['cases' / 'test_' + cases + '.c'] + test_cpp += ['cases' / 'test_' + cases + '.cpp'] endforeach - pizza = executable('xcli', test_src, include_directories: dir, dependencies: [fossil_test_dep]) - test('fossil_tests', pizza) # Renamed the test target for clarity + pizza_c = executable('testbed-c', test_c, include_directories: dir, dependencies: [fossil_test_dep]) + pizza_cpp = executable('testbed-cpp', test_cpp, include_directories: dir, dependencies: [fossil_test_dep]) + + test('fossil testing C ', pizza_c ) + test('fossil testing Cpp', pizza_cpp) endif diff --git a/code/tests/tools/generate-runner.py b/code/tests/tools/generate-runner.py index afa54ff7..cda8be52 100644 --- a/code/tests/tools/generate-runner.py +++ b/code/tests/tools/generate-runner.py @@ -4,72 +4,127 @@ class TestRunnerGenerator: def __init__(self): - self.directory = os.getcwd() + # Set the directory to a subdirectory named 'cases' within the current working directory + self.directory = os.path.join(os.getcwd(), "cases") def find_test_groups(self): - test_groups = set() + c_test_groups = set() + cpp_test_groups = set() pattern = r"FOSSIL_TEST_GROUP\((\w+)\)" + # Walk through files in the specified directory, 'cases' for root, _, files in os.walk(self.directory): for file in files: + # Search for C files if file.startswith("test_") and file.endswith(".c"): with open(os.path.join(root, file), "r") as f: content = f.read() matches = re.findall(pattern, content) - test_groups.update(matches) + c_test_groups.update(matches) + # Search for C++ files + elif file.startswith("test_") and file.endswith(".cpp"): + with open(os.path.join(root, file), "r") as f: + content = f.read() + matches = re.findall(pattern, content) + cpp_test_groups.update(matches) - return list(test_groups) + return list(c_test_groups), list(cpp_test_groups) - def generate_test_runner(self, test_groups): + def generate_c_runner(self, c_test_groups): + # Prepare header content for C test runner header = """ -// Generated Fossil Logic Test -""" - - header += """ +// Generated Fossil Logic Test (C) #include + +// * * * * * * * * * * * * * * * * * * * * * * * * +// * Fossil Logic Test List (C) +// * * * * * * * * * * * * * * * * * * * * * * * * """ - header += """ + # Declare C test group externs within extern "C" + extern_c_pools = "\n".join( + [f"FOSSIL_TEST_EXPORT({group});" for group in c_test_groups] + ) + # Prepare runner content for C + runner = """\n // * * * * * * * * * * * * * * * * * * * * * * * * -// * Fossil Logic Test List -// * * * * * * * * * * * * * * * * * * * * * * * *\n""" +// * Fossil Logic Test Runner (C) +// * * * * * * * * * * * * * * * * * * * * * * * * +int main(int argc, char **argv) { + FOSSIL_TEST_START(argc, argv);\n""" - extern_pools = "\n".join( - [f"FOSSIL_TEST_EXPORT({group});" for group in test_groups] + # Import C test groups in the main function + import_c_pools = "\n".join( + [f" FOSSIL_TEST_IMPORT({group});" for group in c_test_groups] ) - runner = """ + # Complete with footer + footer = """\n + FOSSIL_TEST_RUN(); + FOSSIL_TEST_SUMMARY(); + FOSSIL_TEST_END(); +} // end of func +""" + + # Write the generated C test runner to 'unit_runner_c.cpp' + with open("unit_runner.c", "w") as file: + file.write(header) + file.write(extern_c_pools) + file.write(runner) + file.write(import_c_pools) + file.write(footer) + + def generate_cpp_runner(self, cpp_test_groups): + # Prepare header content for C++ test runner + header = """ +// Generated Fossil Logic Test (C++) +#include // * * * * * * * * * * * * * * * * * * * * * * * * -// * Fossil Logic Test Runner -// * * * * * * * * * * * * * * * * * * * * * * * *""" +// * Fossil Logic Test List (C++) +// * * * * * * * * * * * * * * * * * * * * * * * * +""" + + # Declare C++ test group externs + extern_cpp_pools = "\n".join( + [f"FOSSIL_TEST_EXPORT({group});" for group in cpp_test_groups] + ) - runner += """ + # Prepare runner content for C++ + runner = """\n +// * * * * * * * * * * * * * * * * * * * * * * * * +// * Fossil Logic Test Runner (C++) +// * * * * * * * * * * * * * * * * * * * * * * * * int main(int argc, char **argv) { FOSSIL_TEST_START(argc, argv);\n""" - import_pools = "\n".join( - [f" FOSSIL_TEST_IMPORT({group});" for group in test_groups] + # Import C++ test groups in the main function + import_cpp_pools = "\n".join( + [f" FOSSIL_TEST_IMPORT({group});" for group in cpp_test_groups] ) - footer = """ + # Complete with footer + footer = """\n FOSSIL_TEST_RUN(); FOSSIL_TEST_SUMMARY(); FOSSIL_TEST_END(); } // end of func """ - with open("unit_runner.c", "w") as file: + # Write the generated C++ test runner to 'unit_runner_cpp.cpp' + with open("unit_runner.cpp", "w") as file: file.write(header) - file.write("\n") - file.write(extern_pools) + file.write(extern_cpp_pools) file.write(runner) - file.write(import_pools) - file.write("\n") + file.write(import_cpp_pools) file.write(footer) +# Instantiate the generator, find test groups, and generate the test runners generator = TestRunnerGenerator() -test_groups = generator.find_test_groups() -generator.generate_test_runner(test_groups) +c_test_groups, cpp_test_groups = generator.find_test_groups() + +# Generate separate runners for C and C++ +generator.generate_c_runner(c_test_groups) +generator.generate_cpp_runner(cpp_test_groups) diff --git a/code/tests/unit_runner.cpp b/code/tests/unit_runner.cpp new file mode 100644 index 00000000..314d4cfe --- /dev/null +++ b/code/tests/unit_runner.cpp @@ -0,0 +1,28 @@ + +// Generated Fossil Logic Test +#include + +// * * * * * * * * * * * * * * * * * * * * * * * * +// * Fossil Logic Test List +// * * * * * * * * * * * * * * * * * * * * * * * * +FOSSIL_TEST_EXPORT(cpp_bdd_test_cases); +FOSSIL_TEST_EXPORT(cpp_sample_test_cases); +FOSSIL_TEST_EXPORT(cpp_tdd_test_cases); +FOSSIL_TEST_EXPORT(c_tdd_test_cases); +FOSSIL_TEST_EXPORT(c_sample_test_cases); +FOSSIL_TEST_EXPORT(c_bdd_test_cases); +// * * * * * * * * * * * * * * * * * * * * * * * * +// * Fossil Logic Test Runner +// * * * * * * * * * * * * * * * * * * * * * * * * +int main(int argc, char **argv) { + FOSSIL_TEST_START(argc, argv); + FOSSIL_TEST_IMPORT(cpp_bdd_test_cases); + FOSSIL_TEST_IMPORT(cpp_sample_test_cases); + FOSSIL_TEST_IMPORT(cpp_tdd_test_cases); + FOSSIL_TEST_IMPORT(c_tdd_test_cases); + FOSSIL_TEST_IMPORT(c_sample_test_cases); + FOSSIL_TEST_IMPORT(c_bdd_test_cases); + FOSSIL_TEST_RUN(); + FOSSIL_TEST_SUMMARY(); + FOSSIL_TEST_END(); +} // end of func