فهرست منبع

Logger and test system

Kajetan Johannes Hammerle 1 سال پیش
والد
کامیت
7474ed26fa
9فایلهای تغییر یافته به همراه345 افزوده شده و 31 حذف شده
  1. 1 1
      .clangd
  2. 10 10
      CMakeLists.txt
  3. 21 0
      include/core/utils/Check.h
  4. 61 0
      include/core/utils/Logger.h
  5. 28 11
      src/Logger.c
  6. 30 9
      test/Main.c
  7. 122 0
      test/Test.c
  8. 36 0
      test/Test.h
  9. 36 0
      test/Tests.h

+ 1 - 1
.clangd

@@ -1,3 +1,3 @@
 CompileFlags:
-  Add: [-ferror-limit=0, -std=c17, -DERROR_SIMULATOR=true]
+  Add: [-ferror-limit=0, -std=c2x, -DERROR_SIMULATOR=true]
   CompilationDatabase: ./build_debug/

+ 10 - 10
CMakeLists.txt

@@ -1,7 +1,7 @@
 cmake_minimum_required(VERSION 3.25)
 project(core)
 
-set(CMAKE_CXX_STANDARD 20)
+set(CMAKE_C_STANDARD 23)
 
 set(SRC
     "src/Logger.c"
@@ -29,7 +29,7 @@ set(SRC
 
 set(SRC_TESTS
     "test/Main.c"
-    #"test/Test.cpp"
+    "test/Test.c"
     #"test/modules/ArrayTests.cpp"
     #"test/modules/ArrayStringTests.cpp"
     #"test/modules/UtilityTests.cpp"
@@ -167,10 +167,10 @@ target_link_libraries(core
     PUBLIC -nodefaultlibs c m
     PRIVATE ${LINK_OPTIONS}
 )
-#target_sources(core PUBLIC 
-#    FILE_SET HEADERS
-#    BASE_DIRS include
-#    FILES 
+target_sources(core PUBLIC 
+    FILE_SET HEADERS
+    BASE_DIRS include
+    FILES 
 #        ./include/core/data/Stack.hpp
 #        ./include/core/data/HashMap.hpp
 #        ./include/core/data/Components.hpp
@@ -184,13 +184,13 @@ target_link_libraries(core
 #        ./include/core/thread/Thread.hpp
 #        ./include/core/utils/HashCode.hpp
 #        ./include/core/utils/New.hpp
-#        ./include/core/utils/Check.hpp
+        ./include/core/utils/Check.h
 #        ./include/core/utils/Buffer.hpp
 #        ./include/core/utils/Random.hpp
 #        ./include/core/utils/UniquePointer.hpp
 #        ./include/core/utils/Types.hpp
 #        ./include/core/utils/Color.hpp
-#        ./include/core/utils/Logger.hpp
+        ./include/core/utils/Logger.h
 #        ./include/core/utils/ArrayString.hpp
 #        ./include/core/utils/Utility.hpp
 #        ./include/core/utils/Meta.hpp
@@ -209,8 +209,8 @@ target_link_libraries(core
 #        ./include/core/math/Math.hpp
 #        ./include/core/io/File.hpp
 #        ./include/core/io/FileReader.hpp
-#)
-#install(TARGETS core FILE_SET HEADERS)
+)
+install(TARGETS core FILE_SET HEADERS)
 
 add_executable(test ${SRC_TESTS})
 target_link_libraries(test PRIVATE core)

+ 21 - 0
include/core/utils/Check.h

@@ -0,0 +1,21 @@
+#ifndef CORE_CHECK_HPP
+#define CORE_CHECK_HPP
+
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ > 202300L
+#define check_return [[nodiscard]]
+#elif defined(__GNUC__)
+#define check_return __attribute__((warn_unused_result))
+#else
+#error "please add a 'check_return' option"
+#endif
+
+#if defined(__GNUC__)
+#define check_format(format_index, arg_start_index)                            \
+    __attribute__((format(printf, format_index, arg_start_index)))
+#else
+#error "please add a 'check_format' option"
+#endif
+
+#define cbool check_return bool
+
+#endif

+ 61 - 0
include/core/utils/Logger.h

@@ -0,0 +1,61 @@
+#ifndef CORE_LOGGER_HPP
+#define CORE_LOGGER_HPP
+
+#include <stdio.h>
+
+#include "core/utils/Check.h"
+
+#define CORE_TERMINAL_RED "\33[1;31m"
+#define CORE_TERMINAL_YELLOW "\33[1;33m"
+#define CORE_TERMINAL_GRAY "\33[1;37m"
+#define CORE_TERMINAL_GREEN "\33[1;32m"
+#define CORE_TERMINAL_RESET "\33[0m"
+
+typedef enum {
+    LOG_LEVEL_ERROR,
+    LOG_LEVEL_WARNING,
+    LOG_LEVEL_INFO,
+    LOG_LEVEL_DEBUG
+} Logger_Level;
+
+extern Logger_Level logLevel;
+
+const char* Logger_getShortFileName(const char* s);
+
+check_format(6, 7) void Logger_log(Logger_Level l, const char* file, int line,
+                                   const char* prefix, const char* tag,
+                                   const char* format, ...);
+
+#if defined(CORE_LOG_LEVEL) && CORE_LOG_LEVEL >= 1
+#define CORE_LOG_ERROR(...)                                                    \
+    Logger_log(LOG_LEVEL_ERROR, __FILE__, __LINE__, CORE_TERMINAL_RED,         \
+               "[ERROR] ", __VA_ARGS__);
+#else
+#define CORE_LOG_ERROR(...)
+#endif
+
+#if defined(CORE_LOG_LEVEL) && CORE_LOG_LEVEL >= 2
+#define CORE_LOG_WARNING(...)                                                  \
+    Logger_log(LOG_LEVEL_WARNING, __FILE__, __LINE__, CORE_TERMINAL_YELLOW,    \
+               "[WARNING] ", __VA_ARGS__);
+#else
+#define CORE_LOG_WARNING(...)
+#endif
+
+#if defined(CORE_LOG_LEVEL) && CORE_LOG_LEVEL >= 3
+#define CORE_LOG_INFO(...)                                                     \
+    Logger_log(LOG_LEVEL_INFO, __FILE__, __LINE__, CORE_TERMINAL_GRAY,         \
+               "[INFO] ", __VA_ARGS__);
+#else
+#define CORE_LOG_INFO(...)
+#endif
+
+#if defined(CORE_LOG_LEVEL) && CORE_LOG_LEVEL >= 4
+#define CORE_LOG_DEBUG(...)                                                    \
+    Logger_log(LOG_LEVEL_DEBUG, __FILE__, __LINE__, CORE_TERMINAL_GREEN,       \
+               "[DEBUG] ", __VA_ARGS__);
+#else
+#define CORE_LOG_DEBUG(...)
+#endif
+
+#endif

+ 28 - 11
src/Logger.c

@@ -1,16 +1,33 @@
-/*#include "core/utils/Logger.hpp"
+#include "core/utils/Logger.h"
 
-Core::Logger::Level Core::Logger::level = Core::Logger::Level::DEBUG;
+#include <stdarg.h>
 
-const char* Core::Logger::getFileName(const char* path) {
-    int end = 0;
-    while(path[end] != '\0') {
-        end++;
+Logger_Level logLevel = LOG_LEVEL_DEBUG;
+
+const char* Logger_getShortFileName(const char* s) {
+    const char* r = s;
+    while(*s != '\0') {
+        if(*(s++) == '/') {
+            r = s;
+        }
     }
-    while(end > 0 && path[end - 1] != '/') {
-        end--;
+    return r;
+}
+
+void Logger_log(Logger_Level l, const char* file, int line, const char* prefix,
+                const char* tag, const char* format, ...) {
+    if(logLevel < l) {
+        return;
     }
-    return path + end;
-}*/
+    file = Logger_getShortFileName(file);
+    fputs(prefix, stdout);
+    fputs(tag, stdout);
+    printf("%s:%d | ", file, line);
+
+    va_list args;
+    va_start(args, format);
+    vprintf(format, args);
+    va_end(args);
 
-int wusi = 0;
+    puts(CORE_TERMINAL_RESET);
+}

+ 30 - 9
test/Main.c

@@ -1,9 +1,9 @@
 #include <locale.h>
-#include <stdbool.h>
 #include <string.h>
 // #include "../src/ErrorSimulator.hpp"
-// #include "Test.hpp"
-// #include "Tests.hpp"
+#include "Test.h"
+#include "Tests.h"
+#include "core/utils/Logger.h"
 // #include "core/utils/ArrayString.hpp"
 // #include "core/utils/Utility.hpp"
 
@@ -26,6 +26,27 @@ int main(int argAmount, const char** args) {
         }
     }
     (void)light;
+
+    CORE_TEST_INT(20, 30);
+    CORE_TEST_INT(20, 20);
+    CORE_TEST_INT(20, 40);
+    CORE_TEST_INT(20, 50);
+    CORE_TEST_BOOL(true, false);
+    CORE_TEST_TRUE(true);
+    CORE_TEST_FALSE(false);
+    CORE_TEST_TRUE(false);
+    CORE_TEST_NULL(nullptr);
+    CORE_TEST_NOT_NULL(nullptr);
+    CORE_TEST_FLOAT(0, 3, 1);
+    CORE_TEST_STRING("wusi", "GUSI");
+    CORE_TEST_STRING("wusi", "wusi");
+    Test_finalize();
+
+    CORE_LOG_DEBUG("This is a test %d", 6);
+    CORE_LOG_INFO("This is a test");
+    CORE_LOG_WARNING("This is a test");
+    CORE_LOG_ERROR("This is a test");
+
     /*
     Core::testArrayList(light);
     Core::testArrayString();
@@ -57,15 +78,15 @@ int main(int argAmount, const char** args) {
     Core::testUniquePointer();
     Core::testUtility();
     Core::testVector();
-    Core::testView();
+    Core::testView();*/
 
-    Core::Logger::level = Core::Logger::Level::WARNING;
+    logLevel = LOG_LEVEL_WARNING;
     CORE_LOG_DEBUG("You won't see this!");
-    Core::Logger::level = Core::Logger::Level::DEBUG;
+    logLevel = LOG_LEVEL_DEBUG;
 
-    unsigned int data = 123456789;
-    Core::setExitHandler(onExit, &data);
+    // unsigned int data = 123456789;
+    // Core::setExitHandler(onExit, &data);
 
-    CORE_EXIT(1);*/
+    // CORE_EXIT(1);
     return 0;
 }

+ 122 - 0
test/Test.c

@@ -0,0 +1,122 @@
+#include "Test.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "core/utils/Logger.h"
+
+typedef struct {
+    char* file;
+    int tests;
+    int successTests;
+} Result;
+
+static Result* results = nullptr;
+static size_t resultsIndex = 0;
+static size_t resultsCapacity = 0;
+
+static Result* getResult(const char* file) {
+    for(size_t i = 0; i < resultsIndex; i++) {
+        Result* r = results + i;
+        if(strcmp(r->file, file) == 0) {
+            return r;
+        }
+    }
+    while(resultsIndex >= resultsCapacity) {
+        size_t newCapacity = resultsCapacity == 0 ? 8 : resultsCapacity * 2;
+        results = realloc(results, newCapacity);
+        if(results == nullptr) {
+            printf("realloc failure in '%s' at '%d'\n", __FILE__, __LINE__);
+            exit(1);
+        }
+        resultsCapacity = newCapacity;
+    }
+    Result* r = results + (resultsIndex++);
+    r->file = strdup(file);
+    r->successTests = 0;
+    r->tests = 0;
+    return r;
+}
+
+void Test_finalize(void) {
+    for(size_t i = 0; i < resultsIndex; i++) {
+        Result* r = results + i;
+        bool c = r->successTests == r->tests;
+        fputs(c ? CORE_TERMINAL_GREEN : CORE_TERMINAL_RED, stdout);
+        printf("%s - %d / %d tests succeeded", r->file, r->successTests,
+               r->tests);
+        puts(CORE_TERMINAL_RESET);
+        free(r->file);
+    }
+    free(results);
+    results = nullptr;
+    resultsIndex = 0;
+    resultsCapacity = 0;
+}
+
+static bool addToResult(const char* file, bool comparison) {
+    Result* r = getResult(file);
+    r->tests++;
+    if(comparison) {
+        r->successTests++;
+        return true;
+    }
+    return false;
+}
+
+#define CORE_TEST_SUCCESS(result)                                              \
+    file = Logger_getShortFileName(file);                                      \
+    if(addToResult(file, result)) {                                            \
+        return true;                                                           \
+    }
+
+#define CORE_TEST_NAMED_COMPARE(name, type, format)                            \
+    bool Test_compare_##name(CORE_TEST_ARGS, type wanted, type actual) {       \
+        CORE_TEST_SUCCESS(wanted == actual)                                    \
+        fputs(CORE_TERMINAL_RED, stdout);                                      \
+        printf("%s:%d - expected '" format "' got '" format "'", file, line,   \
+               wanted, actual);                                                \
+        puts(CORE_TERMINAL_RESET);                                             \
+        return false;                                                          \
+    }
+
+CORE_TEST_NAMED_COMPARE(int, int, "%d")
+CORE_TEST_NAMED_COMPARE(bool, bool, "%d")
+
+bool Test_compare_string(CORE_TEST_ARGS, const char* wanted,
+                         const char* actual) {
+    CORE_TEST_SUCCESS(strcmp(wanted, actual) == 0);
+    fputs(CORE_TERMINAL_RED, stdout);
+    printf("%s:%d - expected '%s' got '%s'", file, line, wanted, actual);
+    puts(CORE_TERMINAL_RESET);
+    return false;
+}
+
+bool Test_compare_float(CORE_TEST_ARGS, float wanted, float actual,
+                        float error) {
+    float diff = wanted - actual;
+    diff = diff < 0.0f ? -diff : diff;
+    CORE_TEST_SUCCESS(diff <= error);
+    fputs(CORE_TERMINAL_RED, stdout);
+    printf("%s:%d - expected '%.3f' got '%.3f'", file, line, (double)wanted,
+           (double)actual);
+    puts(CORE_TERMINAL_RESET);
+    return false;
+}
+
+bool Test_isNull(CORE_TEST_ARGS, const void* actual) {
+    CORE_TEST_SUCCESS(actual == nullptr);
+    fputs(CORE_TERMINAL_RED, stdout);
+    printf("%s:%d - expected null", file, line);
+    puts(CORE_TERMINAL_RESET);
+    return false;
+}
+
+bool Test_isNotNull(CORE_TEST_ARGS, const void* actual) {
+    CORE_TEST_SUCCESS(actual != nullptr);
+    fputs(CORE_TERMINAL_RED, stdout);
+    printf("%s:%d - expected valid pointer", file, line);
+    puts(CORE_TERMINAL_RESET);
+    return false;
+}

+ 36 - 0
test/Test.h

@@ -0,0 +1,36 @@
+#ifndef CORE_TEST_HPP
+#define CORE_TEST_HPP
+
+void Test_finalize(void);
+
+#define CORE_TEST_ARGS const char *file, int line
+#define CORE_TEST_NAMED_FUNCTION(name, type)                                   \
+    bool Test_compare_##name(CORE_TEST_ARGS, type wanted, type actual)
+#define CORE_TEST_FUNCTION(type) CORE_TEST_NAMED_FUNCTION(type, type)
+
+CORE_TEST_FUNCTION(int);
+CORE_TEST_NAMED_FUNCTION(bool, bool);
+CORE_TEST_NAMED_FUNCTION(string, const char*);
+
+bool Test_compare_float(CORE_TEST_ARGS, float wanted, float actual,
+                        float error);
+
+bool Test_isNull(CORE_TEST_ARGS, const void* p);
+bool Test_isNotNull(CORE_TEST_ARGS, const void* p);
+
+#define CORE_TEST(wanted, actual, type)                                        \
+    Test_compare_##type(__FILE__, __LINE__, wanted, actual)
+
+#define CORE_TEST_FLOAT(wanted, actual, error)                                 \
+    Test_compare_float(__FILE__, __LINE__, wanted, actual, error)
+
+#define CORE_TEST_BOOL(wanted, actual) CORE_TEST(wanted, actual, bool)
+#define CORE_TEST_INT(wanted, actual) CORE_TEST(wanted, actual, int)
+#define CORE_TEST_STRING(wanted, actual) CORE_TEST(wanted, actual, string)
+
+#define CORE_TEST_FALSE(actual) CORE_TEST(false, actual, bool)
+#define CORE_TEST_TRUE(actual) CORE_TEST(true, actual, bool)
+#define CORE_TEST_NULL(actual) Test_isNull(__FILE__, __LINE__, actual)
+#define CORE_TEST_NOT_NULL(actual) Test_isNotNull(__FILE__, __LINE__, actual)
+
+#endif

+ 36 - 0
test/Tests.h

@@ -0,0 +1,36 @@
+#ifndef CORE_TESTS_HPP
+#define CORE_TESTS_HPP
+
+void testArrayList(bool light);
+void testArrayString(void);
+void testArray(void);
+void testBitArray(void);
+void testBox(void);
+void testBuffer(bool light);
+void testBufferedValue(void);
+void testClock(bool light);
+void testColor(void);
+void testComponents(void);
+void testError(void);
+void testFileReader(void);
+void testFrustum(void);
+void testHashedString(void);
+void testHashMap(bool light);
+void testLinkedList(bool light);
+void testList(bool light);
+void testMath(void);
+void testMatrixStack(bool light);
+void testMatrix(void);
+void testNew(void);
+void testPlane(void);
+void testQuaternion(void);
+void testRandom(bool light);
+void testRingBuffer(void);
+void testStack(bool light);
+void testThread(void);
+void testUniquePointer(void);
+void testUtility(void);
+void testVector(void);
+void testView(void);
+
+#endif