diff --git a/.gitmodules b/.gitmodules index 646e0a7..025e4c8 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,8 +1,4 @@ [submodule "rules"] path = yara/official_rules url = https://github.com/Yara-Rules/rules - branch = master -[submodule "tests/lib/pl"] - path = tests/lib/pl - url = https://github.com/WerWolv/PatternLanguage - branch = master + branch = master \ No newline at end of file diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 7e88faa..bc328e1 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -4,8 +4,19 @@ project(tests) set(CMAKE_CXX_STANDARD 20) -add_subdirectory(lib/pl) +include(FetchContent) + +FetchContent_Declare( + pattern_language + GIT_REPOSITORY https://github.com/WerWolv/PatternLanguage + GIT_TAG master +) + +FetchContent_MakeAvailable(pattern_language) enable_testing() -add_subdirectory(patterns) \ No newline at end of file +add_subdirectory(patterns) +add_subdirectory(includes) + +add_custom_target(test_all DEPENDS patterns_tests includes_test) \ No newline at end of file diff --git a/tests/includes/CMakeLists.txt b/tests/includes/CMakeLists.txt new file mode 100644 index 0000000..c62f9c4 --- /dev/null +++ b/tests/includes/CMakeLists.txt @@ -0,0 +1,29 @@ +cmake_minimum_required(VERSION 3.16) + +project(includes_test) + +set(TOP_LEVEL "${CMAKE_CURRENT_SOURCE_DIR}/../..") + +file(GLOB INCLUDES + "${TOP_LEVEL}/includes/*/*.pat" +) + +set(PATTERN_INCLUDES "${TOP_LEVEL}/includes") + +add_executable(includes_test + source/main.cpp +) + +target_include_directories(includes_test PRIVATE include) +target_link_libraries(includes_test libpl) + +set_target_properties(includes_test PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) + +foreach (include IN LISTS INCLUDES) + file(RELATIVE_PATH INCLUDE_NAME ${PATTERN_INCLUDES} ${include}) + + set(TEST_NAME "Includes/${INCLUDE_NAME}") + + add_test(NAME ${TEST_NAME} COMMAND includes_test "${INCLUDE_NAME}" "${include}" "${PATTERN_INCLUDES}" WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) + set_tests_properties(${TEST_NAME} PROPERTIES SKIP_RETURN_CODE 77) +endforeach () \ No newline at end of file diff --git a/tests/includes/source/main.cpp b/tests/includes/source/main.cpp new file mode 100644 index 0000000..61bf539 --- /dev/null +++ b/tests/includes/source/main.cpp @@ -0,0 +1,67 @@ +#include +#include + +#include +#include + +#define EXIT_SKIP 77 + +int main(int argc, char **argv) { + // Any number of arguments other than 4 are invalid + if (argc != 4) + return EXIT_FAILURE; + + // Extract command line arguments + const std::string includeName = argv[1]; + const std::fs::path includeFilePath = argv[2]; + const std::fs::path includePath = argv[3]; + + fmt::print("Running test {} on test file {}\n", includeName, includeFilePath.filename().string()); + + // Open pattern file + pl::fs::File patternFile(includeFilePath, pl::fs::File::Mode::Read); + if (!patternFile.isValid()) + return EXIT_FAILURE; + + // Setup Pattern Language Runtime + pl::PatternLanguage runtime; + { + constexpr auto DummyPragmaHandler = [](const auto&, const auto&){ pl::LogConsole::abortEvaluation("Include files should never use this pragma!"); return true; }; + + runtime.setDataSource([&](pl::u64 address, pl::u8 *data, size_t size) { + pl::LogConsole::abortEvaluation("Include files should never read from memory directly!"); + }, 0x00, 0x100000); + runtime.setDangerousFunctionCallHandler([]{ return true; }); + runtime.setIncludePaths({ includePath }); + + runtime.addPragma("endian", DummyPragmaHandler); + runtime.addPragma("MIME", DummyPragmaHandler); + runtime.addPragma("base_address", DummyPragmaHandler); + runtime.addPragma("eval_depth", DummyPragmaHandler); + runtime.addPragma("array_limit", DummyPragmaHandler); + runtime.addPragma("pattern_limit", DummyPragmaHandler); + } + + // Execute pattern + if (!runtime.executeString(patternFile.readString())) { + fmt::print("Error during execution!\n"); + + if (const auto &hardError = runtime.getError(); hardError.has_value()) + fmt::print("Hard error: {}\n\n", hardError.value().what()); + + for (const auto &[level, message] : runtime.getConsoleLog()) { + switch (level) { + case pl::LogConsole::Level::Debug: fmt::print(" [DEBUG] "); break; + case pl::LogConsole::Level::Info: fmt::print(" [INFO] "); break; + case pl::LogConsole::Level::Warning: fmt::print(" [WARN] "); break; + case pl::LogConsole::Level::Error: fmt::print(" [ERROR] "); break; + } + + fmt::print("{}\n", message); + } + + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/tests/lib/pl b/tests/lib/pl deleted file mode 160000 index d399836..0000000 --- a/tests/lib/pl +++ /dev/null @@ -1 +0,0 @@ -Subproject commit d399836b693feaab3b323acd4374c1371164c0eb diff --git a/tests/patterns/CMakeLists.txt b/tests/patterns/CMakeLists.txt index 0db7c6b..b54f05b 100644 --- a/tests/patterns/CMakeLists.txt +++ b/tests/patterns/CMakeLists.txt @@ -8,7 +8,7 @@ file(GLOB PATTERNS "${TOP_LEVEL}/patterns/*.hexpat" ) -set(PATTERN_INCLUDES "${TOP_LEVEL}/includes/std") +set(PATTERN_INCLUDES "${TOP_LEVEL}/includes") add_executable(patterns_tests source/main.cpp @@ -24,7 +24,6 @@ foreach (pattern IN LISTS PATTERNS) file(GLOB TEST_FILES "${CMAKE_CURRENT_SOURCE_DIR}/test_data/${PATTERN_NAME}.*") - message(STATUS ${CMAKE_CURRENT_SOURCE_DIR}/test_data/${PATTERN_NAME}.*) if (TEST_FILES) list(GET TEST_FILES 0 TEST_FILE) else ()