diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 006fb39..f9cc485 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -3,6 +3,7 @@ add_executable(mach_detours_tests test_dylib_function.cpp test_local_function.cpp + test_transaction.cpp ) # The target function must be in a shared library because otherwise it might be in the same code page as the test.cpp functions. diff --git a/tests/test_dylib_function.cpp b/tests/test_dylib_function.cpp index 1cf7cf0..c32679a 100644 --- a/tests/test_dylib_function.cpp +++ b/tests/test_dylib_function.cpp @@ -5,10 +5,10 @@ #include #include "lib_function.h" -int (*realLibFunction)() = libFunction; +static int (*realLibFunction)() = libFunction; static int libFunctionDetourCounter = 0; -int libFunctionDetour() +static int libFunctionDetour() { libFunctionDetourCounter++; return 94; @@ -75,34 +75,4 @@ TEST_CASE( "Overriding custom function in dylib", "[dylib]" ) CHECK( libFunctionCounter == 1 ); CHECK( libFunctionDetourCounter == 0 ); } - - SECTION( "aborting transaction means no detour" ) - { - REQUIRE( detour_transaction_begin() == err_none ); - REQUIRE( detour_attach(reinterpret_cast(&realLibFunction), reinterpret_cast(libFunctionDetour)) == err_none ); - CHECK( detour_transaction_abort() == err_none ); - - CHECK( realLibFunction == libFunction ); - CHECK( libFunctionCounter == 0 ); - CHECK( libFunctionDetourCounter == 0 ); - CHECK( libFunction() == 42 ); - CHECK( libFunctionCounter == 1 ); - CHECK( libFunctionDetourCounter == 0 ); - } - - SECTION( "an error in a transaction means no detour" ) - { - REQUIRE( detour_transaction_begin() == err_none ); - REQUIRE( detour_attach(reinterpret_cast(&realLibFunction), reinterpret_cast(libFunctionDetour)) == err_none ); - // cannot detach because trampoline is not yet in place - CHECK( detour_detach(reinterpret_cast(&realLibFunction), reinterpret_cast(libFunctionDetour)) == KERN_FAILURE ); - CHECK( detour_transaction_commit() == KERN_FAILURE ); - - CHECK( realLibFunction == libFunction ); - CHECK( libFunctionCounter == 0 ); - CHECK( libFunctionDetourCounter == 0 ); - CHECK( libFunction() == 42 ); - CHECK( libFunctionCounter == 1 ); - CHECK( libFunctionDetourCounter == 0 ); - } } diff --git a/tests/test_transaction.cpp b/tests/test_transaction.cpp new file mode 100644 index 0000000..9885b00 --- /dev/null +++ b/tests/test_transaction.cpp @@ -0,0 +1,84 @@ +// Copyright (c) Lysann Tranvouez. All rights reserved. + +#include + +#include + +#include "lib_function.h" +static int (*realLibFunction)() = libFunction; + +static int libFunctionDetourCounter = 0; +static int libFunctionDetour() +{ + libFunctionDetourCounter++; + return 94; +} + +TEST_CASE( "Must start a transaction to attach", "[transaction]" ) +{ + libFunctionCounter = 0; + libFunctionDetourCounter = 0; + + CHECK( detour_attach(reinterpret_cast(&realLibFunction), reinterpret_cast(libFunctionDetour)) == detour_err_wrong_thread ); + CHECK( libFunction() == 42 ); + CHECK( libFunctionCounter == 1 ); + CHECK( libFunctionDetourCounter == 0 ); +} + +TEST_CASE( "Must start a transaction to detach", "[transaction]" ) +{ + libFunctionCounter = 0; + libFunctionDetourCounter = 0; + + REQUIRE( detour_transaction_begin() == err_none ); + REQUIRE( detour_attach_and_commit(reinterpret_cast(&realLibFunction), reinterpret_cast(libFunctionDetour)) == err_none ); + + CHECK( detour_detach_and_commit(reinterpret_cast(&realLibFunction), reinterpret_cast(libFunctionDetour)) == detour_err_wrong_thread ); + + CHECK( libFunction() == 94 ); + CHECK( libFunctionCounter == 0 ); + CHECK( libFunctionDetourCounter == 1 ); + + CHECK( detour_transaction_begin() == err_none ); + CHECK( detour_detach_and_commit(reinterpret_cast(&realLibFunction), reinterpret_cast(libFunctionDetour)) == err_none ); + + CHECK( libFunction() == 42 ); + CHECK( libFunctionCounter == 1 ); + CHECK( libFunctionDetourCounter == 1 ); +} + +TEST_CASE( "aborting transaction means no detour", "[transaction]" ) +{ + libFunctionCounter = 0; + libFunctionDetourCounter = 0; + + REQUIRE( detour_transaction_begin() == err_none ); + REQUIRE( detour_attach(reinterpret_cast(&realLibFunction), reinterpret_cast(libFunctionDetour)) == err_none ); + CHECK( detour_transaction_abort() == err_none ); + + CHECK( realLibFunction == libFunction ); + CHECK( libFunctionCounter == 0 ); + CHECK( libFunctionDetourCounter == 0 ); + CHECK( libFunction() == 42 ); + CHECK( libFunctionCounter == 1 ); + CHECK( libFunctionDetourCounter == 0 ); +} + +TEST_CASE( "an error in a transaction means no detour", "[transaction]" ) +{ + libFunctionCounter = 0; + libFunctionDetourCounter = 0; + + REQUIRE( detour_transaction_begin() == err_none ); + REQUIRE( detour_attach(reinterpret_cast(&realLibFunction), reinterpret_cast(libFunctionDetour)) == err_none ); + // cannot detach because trampoline is not yet in place + CHECK( detour_detach(reinterpret_cast(&realLibFunction), reinterpret_cast(libFunctionDetour)) == KERN_FAILURE ); + CHECK( detour_transaction_commit() == KERN_FAILURE ); + + CHECK( realLibFunction == libFunction ); + CHECK( libFunctionCounter == 0 ); + CHECK( libFunctionDetourCounter == 0 ); + CHECK( libFunction() == 42 ); + CHECK( libFunctionCounter == 1 ); + CHECK( libFunctionDetourCounter == 0 ); +}