mirror of
https://github.com/QuasarApp/pe-parse.git
synced 2025-04-26 12:24:32 +00:00
Add simple test and corkami test suite using Catch2 (#145)
* Add simple test and corkami test suite using Catch2 * Enable testing with CMake option '-DPEPARSE_ENABLE_TESTING=ON'. * The simple test is extremely basic just as an example of using Catch2. * Corkami test suite is a git submodule within assets and the tests can be run with or without cloning it. You are able to configure CMake without the submodule and it will warn you that the tests are not included, and then it will pick them up automatically on next cmake rebuild. There are a few Corkami files which pe-parse is unable to process. They have been added as exceptions for now (just to get this merged), but we can open new issues to track them. This will also catch any regressions that could prevent the successful parsing of files that have been parse-able in the past. * Raise C++ standard from 11 to 17 for easier filesystem handling in tests. Also included CMake script for handling how std::filesystem is found/linked. * Rename directory 'test' to 'tests'. * Update README with testing instructions. * Catch2 is downloaded and built unless otherwise specified (undocumented, aside from reading CMake).
This commit is contained in:
parent
d38c7daa7e
commit
e5ba0165ab
29
.github/workflows/ci.yml
vendored
29
.github/workflows/ci.yml
vendored
@ -11,7 +11,7 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
lint:
|
lint:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-18.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
@ -30,7 +30,7 @@ jobs:
|
|||||||
pe-parse:
|
pe-parse:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
platform: ["ubuntu-latest", "macos-latest"]
|
platform: ["ubuntu-18.04", "macos-latest"]
|
||||||
build-type: ["Debug", "Release"]
|
build-type: ["Debug", "Release"]
|
||||||
build-shared: ["0", "1"]
|
build-shared: ["0", "1"]
|
||||||
compiler:
|
compiler:
|
||||||
@ -42,6 +42,8 @@ jobs:
|
|||||||
runs-on: ${{ matrix.platform }}
|
runs-on: ${{ matrix.platform }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
submodules: 'true'
|
||||||
- name: build
|
- name: build
|
||||||
env:
|
env:
|
||||||
CC: ${{ matrix.compiler.CC }}
|
CC: ${{ matrix.compiler.CC }}
|
||||||
@ -52,16 +54,20 @@ jobs:
|
|||||||
cmake \
|
cmake \
|
||||||
-DCMAKE_BUILD_TYPE=${{ matrix.build-type }} \
|
-DCMAKE_BUILD_TYPE=${{ matrix.build-type }} \
|
||||||
-DBUILD_SHARED_LIBS=${{ matrix.build-shared }} \
|
-DBUILD_SHARED_LIBS=${{ matrix.build-shared }} \
|
||||||
|
-DPEPARSE_ENABLE_TESTING=ON \
|
||||||
..
|
..
|
||||||
cmake --build .
|
cmake --build .
|
||||||
- name: test
|
- name: test
|
||||||
|
env:
|
||||||
|
CTEST_OUTPUT_ON_FAILURE: 1
|
||||||
run: |
|
run: |
|
||||||
./build/dump-pe/dump-pe ./test/assets/example.exe
|
cd build && ctest -V
|
||||||
|
./dump-pe/dump-pe ../tests/assets/example.exe
|
||||||
|
|
||||||
pepy:
|
pepy:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
platform: ["ubuntu-latest", "macos-latest"]
|
platform: ["ubuntu-18.04", "macos-latest"]
|
||||||
python:
|
python:
|
||||||
- "3.6"
|
- "3.6"
|
||||||
- "3.7"
|
- "3.7"
|
||||||
@ -81,7 +87,7 @@ jobs:
|
|||||||
python3 -m pip install --user dist/*.tar.gz
|
python3 -m pip install --user dist/*.tar.gz
|
||||||
- name: test
|
- name: test
|
||||||
run: |
|
run: |
|
||||||
python3 test/test_pepy.py test/assets/example.exe
|
python3 tests/test_pepy.py tests/assets/example.exe
|
||||||
|
|
||||||
pe-parse-windows:
|
pe-parse-windows:
|
||||||
strategy:
|
strategy:
|
||||||
@ -92,6 +98,8 @@ jobs:
|
|||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
submodules: 'true'
|
||||||
- name: build
|
- name: build
|
||||||
run: |
|
run: |
|
||||||
mkdir build
|
mkdir build
|
||||||
@ -100,15 +108,20 @@ jobs:
|
|||||||
-G "Visual Studio 16 2019" `
|
-G "Visual Studio 16 2019" `
|
||||||
-A ${{ matrix.build-arch }} `
|
-A ${{ matrix.build-arch }} `
|
||||||
-DBUILD_SHARED_LIBS=${{ matrix.build-shared }} `
|
-DBUILD_SHARED_LIBS=${{ matrix.build-shared }} `
|
||||||
|
-DPEPARSE_ENABLE_TESTING=ON `
|
||||||
..
|
..
|
||||||
cmake --build . --config ${{ matrix.build-type }}
|
cmake --build . --config ${{ matrix.build-type }}
|
||||||
- name: install
|
- name: install
|
||||||
run: |
|
run: |
|
||||||
cd build
|
cd build
|
||||||
cmake --build . --target install
|
cmake --build . --config ${{ matrix.build-type }} --target install
|
||||||
- name: test
|
- name: test
|
||||||
|
env:
|
||||||
|
CTEST_OUTPUT_ON_FAILURE: 1
|
||||||
run: |
|
run: |
|
||||||
.\build\bin\dump-pe.exe .\test\assets\example.exe
|
cd build
|
||||||
|
ctest -V
|
||||||
|
.\bin\dump-pe.exe ..\tests\assets\example.exe
|
||||||
|
|
||||||
pepy-windows:
|
pepy-windows:
|
||||||
strategy:
|
strategy:
|
||||||
@ -131,4 +144,4 @@ jobs:
|
|||||||
python -m pip install --user .
|
python -m pip install --user .
|
||||||
- name: test
|
- name: test
|
||||||
run: |
|
run: |
|
||||||
python test/test_pepy.py test/assets/example.exe
|
python tests/test_pepy.py tests/assets/example.exe
|
||||||
|
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
[submodule "test/assets/corkami-poc-dataset"]
|
||||||
|
path = tests/assets/corkami-poc-dataset
|
||||||
|
url = https://github.com/corkami/pocs
|
@ -13,6 +13,9 @@ if (NOT CMAKE_BUILD_TYPE)
|
|||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
include(cmake/compilation_flags.cmake)
|
include(cmake/compilation_flags.cmake)
|
||||||
|
# Greater c++17 filesystem compatibility (like with experimental)
|
||||||
|
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules")
|
||||||
|
find_package(Filesystem COMPONENTS Experimental Final REQUIRED)
|
||||||
list(APPEND GLOBAL_CXXFLAGS ${DEFAULT_CXX_FLAGS})
|
list(APPEND GLOBAL_CXXFLAGS ${DEFAULT_CXX_FLAGS})
|
||||||
|
|
||||||
option(BUILD_SHARED_LIBS "Build Shared Libraries" ON)
|
option(BUILD_SHARED_LIBS "Build Shared Libraries" ON)
|
||||||
@ -45,6 +48,8 @@ file(
|
|||||||
dump-pe/*.cpp
|
dump-pe/*.cpp
|
||||||
examples/*.cpp
|
examples/*.cpp
|
||||||
examples/*.h
|
examples/*.h
|
||||||
|
tests/*.cpp
|
||||||
|
tests/*.h
|
||||||
)
|
)
|
||||||
add_custom_target(
|
add_custom_target(
|
||||||
peparse_format
|
peparse_format
|
||||||
@ -58,3 +63,9 @@ message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
|
|||||||
message(STATUS "Build Shared: ${BUILD_SHARED_LIBS} ${BUILD_SHARED_LIBS_MESSAGE}")
|
message(STATUS "Build Shared: ${BUILD_SHARED_LIBS} ${BUILD_SHARED_LIBS_MESSAGE}")
|
||||||
message(STATUS "Build Command Line Tools: ${BUILD_COMMAND_LINE_TOOLS}")
|
message(STATUS "Build Command Line Tools: ${BUILD_COMMAND_LINE_TOOLS}")
|
||||||
message(STATUS "Install prefix: ${CMAKE_INSTALL_PREFIX}")
|
message(STATUS "Install prefix: ${CMAKE_INSTALL_PREFIX}")
|
||||||
|
|
||||||
|
option(PEPARSE_ENABLE_TESTING "Enable building tests" OFF)
|
||||||
|
if (PEPARSE_ENABLE_TESTING)
|
||||||
|
enable_testing()
|
||||||
|
add_subdirectory(tests)
|
||||||
|
endif()
|
||||||
|
@ -10,7 +10,7 @@ automatically prompted to sign it during your first PR.
|
|||||||
|
|
||||||
## General contribution guidelines
|
## General contribution guidelines
|
||||||
|
|
||||||
* Your changes should be valid C++11
|
* Your changes should be valid C++17
|
||||||
* Your changes should work across all major compiler vendors (GCC, Clang, MSVC) and all
|
* Your changes should work across all major compiler vendors (GCC, Clang, MSVC) and all
|
||||||
major operating systems (Linux, macOS, Windows)
|
major operating systems (Linux, macOS, Windows)
|
||||||
* Your changes should be auto-formatted with `clang-format -style=file`
|
* Your changes should be auto-formatted with `clang-format -style=file`
|
||||||
|
@ -88,6 +88,12 @@ cmake -G "Visual Studio 16 2019" -A Win64 ..
|
|||||||
cmake --build . --config Release
|
cmake --build . --config Release
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
You can build the (catch2-based) tests by adding `-DPEPARSE_ENABLE_TESTING=ON` during CMake configuration. Build, and then run with `ctest` or `cmake --build . --target test`.
|
||||||
|
|
||||||
|
To run the full test suite with the [Corkami test suite](https://github.com/corkami/pocs/tree/master/PE), you must clone the submodule with `git submodule update --init`.
|
||||||
|
|
||||||
## Using the library
|
## Using the library
|
||||||
|
|
||||||
Once the library is installed, linking to it is easy! Add the following lines in your CMake project:
|
Once the library is installed, linking to it is easy! Add the following lines in your CMake project:
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
|
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
list(APPEND DEFAULT_CXX_FLAGS /W4 /analyze)
|
list(APPEND DEFAULT_CXX_FLAGS /W4 /analyze)
|
||||||
|
|
||||||
@ -10,10 +14,6 @@ if (MSVC)
|
|||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
else ()
|
else ()
|
||||||
set(CMAKE_CXX_STANDARD 11)
|
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
||||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
|
||||||
|
|
||||||
if (NOT MINGW)
|
if (NOT MINGW)
|
||||||
list(APPEND DEFAULT_CXX_FLAGS -fPIC)
|
list(APPEND DEFAULT_CXX_FLAGS -fPIC)
|
||||||
endif ()
|
endif ()
|
||||||
|
250
cmake/modules/FindFilesystem.cmake
Normal file
250
cmake/modules/FindFilesystem.cmake
Normal file
@ -0,0 +1,250 @@
|
|||||||
|
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||||
|
# file Copyright.txt or https://cmake.org/licensing for details.
|
||||||
|
|
||||||
|
# Copied from https://github.com/vector-of-bool/CMakeCM/tree/6cb8a6ada09eb40c271d2f83a032e03cd4005fa3/modules/FindFilesystem.cmake
|
||||||
|
# Latest commit as of March 10, 2021
|
||||||
|
|
||||||
|
#[=======================================================================[.rst:
|
||||||
|
|
||||||
|
FindFilesystem
|
||||||
|
##############
|
||||||
|
|
||||||
|
This module supports the C++17 standard library's filesystem utilities. Use the
|
||||||
|
:imp-target:`std::filesystem` imported target to
|
||||||
|
|
||||||
|
Options
|
||||||
|
*******
|
||||||
|
|
||||||
|
The ``COMPONENTS`` argument to this module supports the following values:
|
||||||
|
|
||||||
|
.. find-component:: Experimental
|
||||||
|
:name: fs.Experimental
|
||||||
|
|
||||||
|
Allows the module to find the "experimental" Filesystem TS version of the
|
||||||
|
Filesystem library. This is the library that should be used with the
|
||||||
|
``std::experimental::filesystem`` namespace.
|
||||||
|
|
||||||
|
.. find-component:: Final
|
||||||
|
:name: fs.Final
|
||||||
|
|
||||||
|
Finds the final C++17 standard version of the filesystem library.
|
||||||
|
|
||||||
|
If no components are provided, behaves as if the
|
||||||
|
:find-component:`fs.Final` component was specified.
|
||||||
|
|
||||||
|
If both :find-component:`fs.Experimental` and :find-component:`fs.Final` are
|
||||||
|
provided, first looks for ``Final``, and falls back to ``Experimental`` in case
|
||||||
|
of failure. If ``Final`` is found, :imp-target:`std::filesystem` and all
|
||||||
|
:ref:`variables <fs.variables>` will refer to the ``Final`` version.
|
||||||
|
|
||||||
|
|
||||||
|
Imported Targets
|
||||||
|
****************
|
||||||
|
|
||||||
|
.. imp-target:: std::filesystem
|
||||||
|
|
||||||
|
The ``std::filesystem`` imported target is defined when any requested
|
||||||
|
version of the C++ filesystem library has been found, whether it is
|
||||||
|
*Experimental* or *Final*.
|
||||||
|
|
||||||
|
If no version of the filesystem library is available, this target will not
|
||||||
|
be defined.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
This target has ``cxx_std_17`` as an ``INTERFACE``
|
||||||
|
:ref:`compile language standard feature <req-lang-standards>`. Linking
|
||||||
|
to this target will automatically enable C++17 if no later standard
|
||||||
|
version is already required on the linking target.
|
||||||
|
|
||||||
|
|
||||||
|
.. _fs.variables:
|
||||||
|
|
||||||
|
Variables
|
||||||
|
*********
|
||||||
|
|
||||||
|
.. variable:: CXX_FILESYSTEM_IS_EXPERIMENTAL
|
||||||
|
|
||||||
|
Set to ``TRUE`` when the :find-component:`fs.Experimental` version of C++
|
||||||
|
filesystem library was found, otherwise ``FALSE``.
|
||||||
|
|
||||||
|
.. variable:: CXX_FILESYSTEM_HAVE_FS
|
||||||
|
|
||||||
|
Set to ``TRUE`` when a filesystem header was found.
|
||||||
|
|
||||||
|
.. variable:: CXX_FILESYSTEM_HEADER
|
||||||
|
|
||||||
|
Set to either ``filesystem`` or ``experimental/filesystem`` depending on
|
||||||
|
whether :find-component:`fs.Final` or :find-component:`fs.Experimental` was
|
||||||
|
found.
|
||||||
|
|
||||||
|
.. variable:: CXX_FILESYSTEM_NAMESPACE
|
||||||
|
|
||||||
|
Set to either ``std::filesystem`` or ``std::experimental::filesystem``
|
||||||
|
depending on whether :find-component:`fs.Final` or
|
||||||
|
:find-component:`fs.Experimental` was found.
|
||||||
|
|
||||||
|
|
||||||
|
Examples
|
||||||
|
********
|
||||||
|
|
||||||
|
Using `find_package(Filesystem)` with no component arguments:
|
||||||
|
|
||||||
|
.. code-block:: cmake
|
||||||
|
|
||||||
|
find_package(Filesystem REQUIRED)
|
||||||
|
|
||||||
|
add_executable(my-program main.cpp)
|
||||||
|
target_link_libraries(my-program PRIVATE std::filesystem)
|
||||||
|
|
||||||
|
|
||||||
|
#]=======================================================================]
|
||||||
|
|
||||||
|
|
||||||
|
if(TARGET std::filesystem)
|
||||||
|
# This module has already been processed. Don't do it again.
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.10)
|
||||||
|
|
||||||
|
include(CMakePushCheckState)
|
||||||
|
include(CheckIncludeFileCXX)
|
||||||
|
|
||||||
|
# If we're not cross-compiling, try to run test executables.
|
||||||
|
# Otherwise, assume that compile + link is a sufficient check.
|
||||||
|
if(CMAKE_CROSSCOMPILING)
|
||||||
|
include(CheckCXXSourceCompiles)
|
||||||
|
macro(_cmcm_check_cxx_source code var)
|
||||||
|
check_cxx_source_compiles("${code}" ${var})
|
||||||
|
endmacro()
|
||||||
|
else()
|
||||||
|
include(CheckCXXSourceRuns)
|
||||||
|
macro(_cmcm_check_cxx_source code var)
|
||||||
|
check_cxx_source_runs("${code}" ${var})
|
||||||
|
endmacro()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
cmake_push_check_state()
|
||||||
|
|
||||||
|
set(CMAKE_REQUIRED_QUIET ${Filesystem_FIND_QUIETLY})
|
||||||
|
|
||||||
|
# All of our tests required C++17 or later
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
|
||||||
|
# Normalize and check the component list we were given
|
||||||
|
set(want_components ${Filesystem_FIND_COMPONENTS})
|
||||||
|
if(Filesystem_FIND_COMPONENTS STREQUAL "")
|
||||||
|
set(want_components Final)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Warn on any unrecognized components
|
||||||
|
set(extra_components ${want_components})
|
||||||
|
list(REMOVE_ITEM extra_components Final Experimental)
|
||||||
|
foreach(component IN LISTS extra_components)
|
||||||
|
message(WARNING "Extraneous find_package component for Filesystem: ${component}")
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
# Detect which of Experimental and Final we should look for
|
||||||
|
set(find_experimental TRUE)
|
||||||
|
set(find_final TRUE)
|
||||||
|
if(NOT "Final" IN_LIST want_components)
|
||||||
|
set(find_final FALSE)
|
||||||
|
endif()
|
||||||
|
if(NOT "Experimental" IN_LIST want_components)
|
||||||
|
set(find_experimental FALSE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(find_final)
|
||||||
|
check_include_file_cxx("filesystem" _CXX_FILESYSTEM_HAVE_HEADER)
|
||||||
|
mark_as_advanced(_CXX_FILESYSTEM_HAVE_HEADER)
|
||||||
|
if(_CXX_FILESYSTEM_HAVE_HEADER)
|
||||||
|
# We found the non-experimental header. Don't bother looking for the
|
||||||
|
# experimental one.
|
||||||
|
set(find_experimental FALSE)
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
set(_CXX_FILESYSTEM_HAVE_HEADER FALSE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(find_experimental)
|
||||||
|
check_include_file_cxx("experimental/filesystem" _CXX_FILESYSTEM_HAVE_EXPERIMENTAL_HEADER)
|
||||||
|
mark_as_advanced(_CXX_FILESYSTEM_HAVE_EXPERIMENTAL_HEADER)
|
||||||
|
else()
|
||||||
|
set(_CXX_FILESYSTEM_HAVE_EXPERIMENTAL_HEADER FALSE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(_CXX_FILESYSTEM_HAVE_HEADER)
|
||||||
|
set(_have_fs TRUE)
|
||||||
|
set(_fs_header filesystem)
|
||||||
|
set(_fs_namespace std::filesystem)
|
||||||
|
set(_is_experimental FALSE)
|
||||||
|
elseif(_CXX_FILESYSTEM_HAVE_EXPERIMENTAL_HEADER)
|
||||||
|
set(_have_fs TRUE)
|
||||||
|
set(_fs_header experimental/filesystem)
|
||||||
|
set(_fs_namespace std::experimental::filesystem)
|
||||||
|
set(_is_experimental TRUE)
|
||||||
|
else()
|
||||||
|
set(_have_fs FALSE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(CXX_FILESYSTEM_HAVE_FS ${_have_fs} CACHE BOOL "TRUE if we have the C++ filesystem headers")
|
||||||
|
set(CXX_FILESYSTEM_HEADER ${_fs_header} CACHE STRING "The header that should be included to obtain the filesystem APIs")
|
||||||
|
set(CXX_FILESYSTEM_NAMESPACE ${_fs_namespace} CACHE STRING "The C++ namespace that contains the filesystem APIs")
|
||||||
|
set(CXX_FILESYSTEM_IS_EXPERIMENTAL ${_is_experimental} CACHE BOOL "TRUE if the C++ filesystem library is the experimental version")
|
||||||
|
|
||||||
|
set(_found FALSE)
|
||||||
|
|
||||||
|
if(CXX_FILESYSTEM_HAVE_FS)
|
||||||
|
# We have some filesystem library available. Do link checks
|
||||||
|
string(CONFIGURE [[
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <@CXX_FILESYSTEM_HEADER@>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
auto cwd = @CXX_FILESYSTEM_NAMESPACE@::current_path();
|
||||||
|
printf("%s", cwd.c_str());
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
]] code @ONLY)
|
||||||
|
|
||||||
|
# Check a simple filesystem program without any linker flags
|
||||||
|
_cmcm_check_cxx_source("${code}" CXX_FILESYSTEM_NO_LINK_NEEDED)
|
||||||
|
|
||||||
|
set(can_link ${CXX_FILESYSTEM_NO_LINK_NEEDED})
|
||||||
|
|
||||||
|
if(NOT CXX_FILESYSTEM_NO_LINK_NEEDED)
|
||||||
|
set(prev_libraries ${CMAKE_REQUIRED_LIBRARIES})
|
||||||
|
# Add the libstdc++ flag
|
||||||
|
set(CMAKE_REQUIRED_LIBRARIES ${prev_libraries} -lstdc++fs)
|
||||||
|
_cmcm_check_cxx_source("${code}" CXX_FILESYSTEM_STDCPPFS_NEEDED)
|
||||||
|
set(can_link ${CXX_FILESYSTEM_STDCPPFS_NEEDED})
|
||||||
|
if(NOT CXX_FILESYSTEM_STDCPPFS_NEEDED)
|
||||||
|
# Try the libc++ flag
|
||||||
|
set(CMAKE_REQUIRED_LIBRARIES ${prev_libraries} -lc++fs)
|
||||||
|
_cmcm_check_cxx_source("${code}" CXX_FILESYSTEM_CPPFS_NEEDED)
|
||||||
|
set(can_link ${CXX_FILESYSTEM_CPPFS_NEEDED})
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(can_link)
|
||||||
|
add_library(std::filesystem INTERFACE IMPORTED)
|
||||||
|
set_property(TARGET std::filesystem APPEND PROPERTY INTERFACE_COMPILE_FEATURES cxx_std_17)
|
||||||
|
set(_found TRUE)
|
||||||
|
|
||||||
|
if(CXX_FILESYSTEM_NO_LINK_NEEDED)
|
||||||
|
# Nothing to add...
|
||||||
|
elseif(CXX_FILESYSTEM_STDCPPFS_NEEDED)
|
||||||
|
set_property(TARGET std::filesystem APPEND PROPERTY INTERFACE_LINK_LIBRARIES -lstdc++fs)
|
||||||
|
elseif(CXX_FILESYSTEM_CPPFS_NEEDED)
|
||||||
|
set_property(TARGET std::filesystem APPEND PROPERTY INTERFACE_LINK_LIBRARIES -lc++fs)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
cmake_pop_check_state()
|
||||||
|
|
||||||
|
set(Filesystem_FOUND ${_found} CACHE BOOL "TRUE if we can run a program using std::filesystem" FORCE)
|
||||||
|
|
||||||
|
if(Filesystem_FIND_REQUIRED AND NOT Filesystem_FOUND)
|
||||||
|
message(FATAL_ERROR "Cannot run simple program using std::filesystem")
|
||||||
|
endif()
|
47
tests/CMakeLists.txt
Normal file
47
tests/CMakeLists.txt
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
include(CTest)
|
||||||
|
|
||||||
|
# Path for corkami dataset
|
||||||
|
set(CORKAMI_SUBMODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/assets/corkami-poc-dataset")
|
||||||
|
set(CORKAMI_PE_PATH "${CORKAMI_SUBMODULE_PATH}/PE/bin")
|
||||||
|
|
||||||
|
if (NOT EXISTS "${CORKAMI_PE_PATH}")
|
||||||
|
message(WARNING "Could not find Corkami dataset for testing.\nUse 'git submodule update --init'")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# To reconfigure and rebuild when submodule status changes
|
||||||
|
# See https://gitlab.kitware.com/cmake/cmake/-/issues/18755 to read why using
|
||||||
|
# (potentially non-existant) CORKAMI_PE_PATH doesn't work
|
||||||
|
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${CORKAMI_SUBMODULE_PATH}")
|
||||||
|
|
||||||
|
if (NOT USE_EXTERNAL_CATCH2)
|
||||||
|
include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/catch.cmake.in")
|
||||||
|
else()
|
||||||
|
find_package(Catch2 REQUIRED)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_executable(tests
|
||||||
|
test_main.cpp
|
||||||
|
simple_test.cpp
|
||||||
|
corkami_test.cpp
|
||||||
|
|
||||||
|
filesystem_compat.h
|
||||||
|
)
|
||||||
|
target_compile_definitions(tests PRIVATE ASSETS_DIR="${CMAKE_CURRENT_SOURCE_DIR}/assets")
|
||||||
|
target_link_libraries(tests PRIVATE std::filesystem ${PROJECT_NAME} Catch2::Catch2)
|
||||||
|
target_include_directories(tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
|
||||||
|
if (EXISTS "${CORKAMI_PE_PATH}")
|
||||||
|
target_compile_definitions(tests PRIVATE CORKAMI_PE_PATH="${CORKAMI_PE_PATH}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (WIN32 AND BUILD_SHARED_LIBS)
|
||||||
|
# Workaround for shared lib loading in Windows.
|
||||||
|
# Need to copy all dependent DLLs to the same directory
|
||||||
|
add_custom_command (TARGET tests POST_BUILD
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||||
|
$<TARGET_FILE:${PROJECT_NAME}> $<TARGET_FILE_DIR:tests>
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
include(Catch)
|
||||||
|
catch_discover_tests(tests)
|
1
tests/assets/corkami-poc-dataset
Submodule
1
tests/assets/corkami-poc-dataset
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit befb3632214640a4af20be3b463f41e4b82f04f6
|
9
tests/cmake/catch.cmake.in
Normal file
9
tests/cmake/catch.cmake.in
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
Include(FetchContent)
|
||||||
|
|
||||||
|
FetchContent_Declare(
|
||||||
|
Catch2
|
||||||
|
GIT_REPOSITORY https://github.com/catchorg/Catch2.git
|
||||||
|
GIT_TAG v2.13.4)
|
||||||
|
|
||||||
|
FetchContent_MakeAvailable(Catch2)
|
||||||
|
list(APPEND CMAKE_MODULE_PATH ${catch2_SOURCE_DIR}/contrib)
|
74
tests/corkami_test.cpp
Normal file
74
tests/corkami_test.cpp
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
#include <pe-parse/parse.h>
|
||||||
|
|
||||||
|
#include <catch2/catch.hpp>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_set>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "filesystem_compat.h"
|
||||||
|
|
||||||
|
// Whether the corkami testset has been downloaded
|
||||||
|
// Path to corkami PEs
|
||||||
|
#if defined(CORKAMI_PE_PATH)
|
||||||
|
|
||||||
|
// Return a vector of all PE files immediately under `dir`
|
||||||
|
static std::vector<fs::path> PEFilesInDir(const fs::path &dir) {
|
||||||
|
std::vector<fs::path> all_entries;
|
||||||
|
if (!fs::exists(dir)) {
|
||||||
|
return all_entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto &entry : fs::directory_iterator(dir)) {
|
||||||
|
if ((entry.path().extension() == ".exe" ||
|
||||||
|
entry.path().extension() == ".dll" ||
|
||||||
|
entry.path().extension() == ".sys") &&
|
||||||
|
fs::is_regular_file(entry)) {
|
||||||
|
all_entries.emplace_back(entry.path());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return all_entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace peparse {
|
||||||
|
|
||||||
|
static const std::unordered_set<std::string> kKnownPEFailure{
|
||||||
|
"virtsectblXP.exe", "maxsec_lowaligW7.exe",
|
||||||
|
"maxsecXP.exe", "nullSOH-XP.exe",
|
||||||
|
"tinyXP.exe", "tinydllXP.dll",
|
||||||
|
"virtrelocXP.exe", "foldedhdrW7.exe",
|
||||||
|
"maxvals.exe", "d_nonnull.dll",
|
||||||
|
"reloccrypt.exe", "d_resource.dll",
|
||||||
|
"fakerelocs.exe", "lfanew_relocW7.exe",
|
||||||
|
"bigSoRD.exe", "tinyW7.exe",
|
||||||
|
"reloccryptW8.exe", "standard.exe",
|
||||||
|
"exe2pe.exe", "tinygui.exe",
|
||||||
|
"dllfwloop.dll", "tinydrivXP.sys",
|
||||||
|
"tiny.exe", "tinydll.dll",
|
||||||
|
"foldedhdr.exe", "dllmaxvals.dll",
|
||||||
|
"reloccryptXP.exe", "dosZMXP.exe",
|
||||||
|
"tinyW7_3264.exe", "dllfw.dll",
|
||||||
|
"hdrcode.exe", "ibrelocW7.exe",
|
||||||
|
"d_tiny.dll", "sc.exe"};
|
||||||
|
|
||||||
|
TEST_CASE("Corkami PEs smoketest", "[corkami]") {
|
||||||
|
for (fs::path path : PEFilesInDir(CORKAMI_PE_PATH)) {
|
||||||
|
std::string pe_name = path.filename().string();
|
||||||
|
SECTION(pe_name) {
|
||||||
|
parsed_pe *p = ParsePEFromFile(path.string().c_str());
|
||||||
|
|
||||||
|
if (kKnownPEFailure.count(pe_name)) {
|
||||||
|
CHECKED_ELSE(!p) {
|
||||||
|
FAIL("Previously failing test now passes! Remove from set");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
CHECKED_ELSE(p) {
|
||||||
|
FAIL(GetPEErrString() + " at " + GetPEErrLoc());
|
||||||
|
}
|
||||||
|
DestructParsedPE(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace peparse
|
||||||
|
#endif
|
12
tests/filesystem_compat.h
Normal file
12
tests/filesystem_compat.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// This header is for C++17 filesystem compatibility for different versions of
|
||||||
|
// compilers and c++ standard libraries header placement
|
||||||
|
|
||||||
|
#if __has_include(<filesystem>)
|
||||||
|
#include <filesystem>
|
||||||
|
namespace fs = std::filesystem;
|
||||||
|
#elif __has_include(<experimental/filesystem>)
|
||||||
|
#include <experimental/filesystem>
|
||||||
|
namespace fs = std::experimental::filesystem;
|
||||||
|
#else
|
||||||
|
#error "no filesystem support"
|
||||||
|
#endif
|
52
tests/simple_test.cpp
Normal file
52
tests/simple_test.cpp
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
#include <pe-parse/parse.h>
|
||||||
|
|
||||||
|
#include <catch2/catch.hpp>
|
||||||
|
|
||||||
|
#include "filesystem_compat.h"
|
||||||
|
|
||||||
|
namespace peparse {
|
||||||
|
|
||||||
|
TEST_CASE("Simple testing of PE", "[example]") {
|
||||||
|
fs::path path = fs::path(ASSETS_DIR) / "example.exe";
|
||||||
|
parsed_pe *p = ParsePEFromFile(path.string().c_str());
|
||||||
|
|
||||||
|
REQUIRE(p);
|
||||||
|
|
||||||
|
SECTION("dos header correctness") {
|
||||||
|
auto dos = p->peHeader.dos;
|
||||||
|
REQUIRE(dos.e_magic == 0x5a4d);
|
||||||
|
REQUIRE(dos.e_cp == 0x3);
|
||||||
|
REQUIRE(dos.e_crlc == 0x0);
|
||||||
|
REQUIRE(dos.e_cparhdr == 0x4);
|
||||||
|
REQUIRE(dos.e_minalloc == 0x0);
|
||||||
|
REQUIRE(dos.e_maxalloc == 0xffff);
|
||||||
|
REQUIRE(dos.e_ss == 0x0);
|
||||||
|
REQUIRE(dos.e_sp == 0xb8);
|
||||||
|
REQUIRE(dos.e_csum == 0x0);
|
||||||
|
REQUIRE(dos.e_ip == 0x0);
|
||||||
|
REQUIRE(dos.e_cs == 0x0);
|
||||||
|
REQUIRE(dos.e_lfarlc == 0x40);
|
||||||
|
REQUIRE(dos.e_ovno == 0x0);
|
||||||
|
REQUIRE(dos.e_res[0] == 0x0);
|
||||||
|
REQUIRE(dos.e_res[1] == 0x0);
|
||||||
|
REQUIRE(dos.e_res[2] == 0x0);
|
||||||
|
REQUIRE(dos.e_res[3] == 0x0);
|
||||||
|
REQUIRE(dos.e_oemid == 0x0);
|
||||||
|
REQUIRE(dos.e_oeminfo == 0x0);
|
||||||
|
REQUIRE(dos.e_res2[0] == 0x0);
|
||||||
|
REQUIRE(dos.e_res2[1] == 0x0);
|
||||||
|
REQUIRE(dos.e_res2[2] == 0x0);
|
||||||
|
REQUIRE(dos.e_res2[3] == 0x0);
|
||||||
|
REQUIRE(dos.e_res2[4] == 0x0);
|
||||||
|
REQUIRE(dos.e_res2[5] == 0x0);
|
||||||
|
REQUIRE(dos.e_res2[6] == 0x0);
|
||||||
|
REQUIRE(dos.e_res2[7] == 0x0);
|
||||||
|
REQUIRE(dos.e_res2[8] == 0x0);
|
||||||
|
REQUIRE(dos.e_res2[9] == 0x0);
|
||||||
|
REQUIRE(dos.e_lfanew == 0xf8);
|
||||||
|
}
|
||||||
|
|
||||||
|
DestructParsedPE(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace peparse
|
7
tests/test_main.cpp
Normal file
7
tests/test_main.cpp
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
// In a Catch project with multiple files, dedicate one file to compile the
|
||||||
|
// source code of Catch itself and reuse the resulting object file for linking.
|
||||||
|
|
||||||
|
// Let Catch provide main():
|
||||||
|
#define CATCH_CONFIG_MAIN
|
||||||
|
|
||||||
|
#include <catch2/catch.hpp>
|
Loading…
x
Reference in New Issue
Block a user