From 6ff0a8e539621abd6a00db3e7c4f4a8f5d284363 Mon Sep 17 00:00:00 2001 From: Jeremy Retailleau Date: Mon, 4 Sep 2023 10:23:57 -0700 Subject: [PATCH] Use GTest to structure unit tests. Organize tests into separate test functions and test cases. This will make it easier to understand and maintain the test suite. --- .github/workflows/linux.yml | 2 +- .github/workflows/macos.yml | 2 +- .github/workflows/windows.yml | 6 +- CMakeLists.txt | 3 + doc/sphinx/glossary.rst | 7 +- doc/sphinx/installing.rst | 5 +- test/CMakeLists.txt | 147 +---------- test/testArchAbi.cpp | 67 ----- test/testArchPRead.cpp | 58 ----- test/testDemangle.cpp | 128 ---------- test/testFileSystem.cpp | 147 ----------- test/testFunction.cpp | 74 ------ test/testMath.cpp | 53 ---- test/unit/CMakeLists.txt | 162 ++++++++++++ test/unit/testArchAbi.cpp | 75 ++++++ test/{ => unit}/testAttributes.cpp | 29 ++- test/unit/testDemangle.cpp | 241 ++++++++++++++++++ test/{ => unit}/testErrno.cpp | 12 +- test/{ => unit}/testError.cpp | 5 +- test/unit/testFileSystem.cpp | 132 ++++++++++ test/unit/testFunction.cpp | 86 +++++++ test/unit/testMath.cpp | 68 +++++ test/{ => unit}/testStackTrace.cpp | 40 ++- test/{ => unit}/testSymbols.cpp | 26 +- test/{ => unit}/testSystemInfo.cpp | 9 +- test/{ => unit}/testThreads.cpp | 10 +- test/{ => unit}/testTiming.cpp | 22 +- test/{ => unit}/testVsnprintf.cpp | 20 +- test/utility/CMakeLists.txt | 15 ++ .../{testArchAbi.h => utility/archTest/abi.h} | 6 +- .../archTest/util.cpp} | 3 +- .../archTest/util.h} | 6 +- test/utility/plugins/CMakeLists.txt | 7 + .../plugins/main.cpp} | 7 +- 34 files changed, 899 insertions(+), 781 deletions(-) delete mode 100644 test/testArchAbi.cpp delete mode 100644 test/testArchPRead.cpp delete mode 100644 test/testDemangle.cpp delete mode 100644 test/testFileSystem.cpp delete mode 100644 test/testFunction.cpp delete mode 100644 test/testMath.cpp create mode 100644 test/unit/CMakeLists.txt create mode 100644 test/unit/testArchAbi.cpp rename test/{ => unit}/testAttributes.cpp (82%) create mode 100644 test/unit/testDemangle.cpp rename test/{ => unit}/testErrno.cpp (53%) rename test/{ => unit}/testError.cpp (86%) create mode 100644 test/unit/testFileSystem.cpp create mode 100644 test/unit/testFunction.cpp create mode 100644 test/unit/testMath.cpp rename test/{ => unit}/testStackTrace.cpp (69%) rename test/{ => unit}/testSymbols.cpp (67%) rename test/{ => unit}/testSystemInfo.cpp (53%) rename test/{ => unit}/testThreads.cpp (70%) rename test/{ => unit}/testTiming.cpp (70%) rename test/{ => unit}/testVsnprintf.cpp (61%) create mode 100644 test/utility/CMakeLists.txt rename test/{testArchAbi.h => utility/archTest/abi.h} (84%) rename test/{testArchUtil.cpp => utility/archTest/util.cpp} (99%) rename test/{testArchUtil.h => utility/archTest/util.h} (85%) create mode 100644 test/utility/plugins/CMakeLists.txt rename test/{testArchAbiPlugin.cpp => utility/plugins/main.cpp} (69%) diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index aa3ef37..bf8c1b8 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -26,7 +26,7 @@ jobs: - name: Create Build Environment run: | sudo apt update - sudo apt install -y ninja-build + sudo apt install -y libgtest-dev ninja-build cmake -E make_directory ${{github.workspace}}/build - name: Configure diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 458384f..680662d 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -25,7 +25,7 @@ jobs: - name: Create Build Environment run: | - brew install ninja + brew install ninja googletest cmake -E make_directory ${{github.workspace}}/build - name: Configure diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index e1a06dc..cf9b1d7 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -15,7 +15,9 @@ env: CMAKE_BUILD_TYPE: Release CMAKE_GENERATOR: Visual Studio 17 2022 CMAKE_GENERATOR_PLATFORM: x64 + CMAKE_TOOLCHAIN_FILE: C:/vcpkg/scripts/buildsystems/vcpkg.cmake CTEST_OUTPUT_ON_FAILURE: True + VCPKG_DEFAULT_TRIPLET: x64-windows # Avoid the just-in-time debugger where possible when running tests. ARCH_AVOID_JIT: True @@ -28,7 +30,9 @@ jobs: - uses: actions/checkout@v4 - name: Create Build Environment - run: cmake -E make_directory ${{github.workspace}}/build + run: | + vcpkg install gtest + cmake -E make_directory ${{github.workspace}}/build - name: Configure working-directory: ${{github.workspace}}/build diff --git a/CMakeLists.txt b/CMakeLists.txt index e88e597..0f82089 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,6 +55,9 @@ add_subdirectory(src) # Build and setup tests if required. if (BUILD_TESTS) + find_package(GTest REQUIRED) + include(GoogleTest) + enable_testing() add_subdirectory(test) endif() diff --git a/doc/sphinx/glossary.rst b/doc/sphinx/glossary.rst index ad55efc..713ddb7 100644 --- a/doc/sphinx/glossary.rst +++ b/doc/sphinx/glossary.rst @@ -22,6 +22,11 @@ Glossary .. seealso:: https://doxygen.nl/ + GTest + Google Test is a testing and mocking framework for C++. + + .. seealso:: http://google.github.io/googletest/ + reStructuredText Lightweight markup language. @@ -31,4 +36,4 @@ Glossary Python documentation generator which converts :term:`reStructuredText` files into HTML and other formats. - .. seealso:: https://www.sphinx-doc.org/ \ No newline at end of file + .. seealso:: https://www.sphinx-doc.org/ diff --git a/doc/sphinx/installing.rst b/doc/sphinx/installing.rst index 3076de9..e5f908b 100644 --- a/doc/sphinx/installing.rst +++ b/doc/sphinx/installing.rst @@ -92,6 +92,8 @@ Then build the documentation as follows:: Running tests ============= +Ensure that :term:`GTest` is installed. + Once the library and all tests are built, you can run the tests using :term:`Ctest` within the build folder as follows:: @@ -100,7 +102,8 @@ Once the library and all tests are built, you can run the tests using You can increase the verbosity and filter in one or several tests as follows:: ctest -VV - ctest -R testArchDemangle -VV + ctest -R DemangleTest.Bool -VV + ctest -R DemangleTest.* -VV .. note:: diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 4acfcf8..f683a64 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,145 +1,2 @@ -add_library(archTest - testArchAbi.cpp - testArchUtil.cpp -) - -target_include_directories(archTest - PUBLIC - $ -) - -target_link_libraries(archTest - PUBLIC - arch -) - -if (WIN32) - # Expand 'add_test' to copy dependent DLLs in the same folder after - # building target to ensure that tests can run properly on Windows. - macro(add_test NAME) - add_custom_command( - TARGET ${NAME} POST_BUILD - COMMAND ${CMAKE_COMMAND} - -E copy_if_different - $ - $ - COMMAND_EXPAND_LISTS - ) - _add_test(${NAME} ${ARGV}) - endmacro() -endif() - -add_library(testArchAbiPlugin testArchAbiPlugin.cpp) - -target_link_libraries(testArchAbiPlugin - PUBLIC - arch - archTest -) - -add_executable(testArchAbi testArchAbi.cpp) -target_link_libraries(testArchAbi - PRIVATE - arch - testArchAbiPlugin -) -add_test(testArchAbi testArchAbi) - -add_executable(testArchPRead testArchPRead.cpp) -target_link_libraries(testArchPRead - PRIVATE - arch -) - -add_executable(testArchAttributes testAttributes.cpp) -target_link_libraries(testArchAttributes - PRIVATE - arch -) -add_test(testArchAttributes testArchAttributes) - -add_executable(testArchDemangle testDemangle.cpp) -target_link_libraries(testArchDemangle - PRIVATE - arch -) -add_test(testArchDemangle testArchDemangle) - -add_executable(testArchErrno testErrno.cpp) -target_link_libraries(testArchErrno - PRIVATE - arch -) -add_test(testArchErrno testArchErrno) - -add_executable(testArchError testError.cpp) -target_link_libraries(testArchError - PRIVATE - arch - archTest -) -add_test(testArchError testArchError) - -add_executable(testArchFileSystem testFileSystem.cpp) -target_link_libraries(testArchFileSystem - PRIVATE - arch -) -add_test(testArchFileSystem testArchFileSystem) - -add_executable(testArchFunction testFunction.cpp) -target_link_libraries(testArchFunction - PRIVATE - arch -) -add_test(testArchFunction testArchFunction) - -add_executable(testArchMath testMath.cpp) -target_link_libraries(testArchMath - PRIVATE - arch -) -add_test(testArchMath testArchMath) - -add_executable(testArchStackTrace testStackTrace.cpp) -target_link_libraries(testArchStackTrace - PRIVATE - arch - archTest -) -add_test(testArchStackTrace testArchStackTrace) - -add_executable(testArchSymbols testSymbols.cpp) -target_link_libraries(testArchSymbols - PRIVATE - arch -) -add_test(testArchSymbols testArchSymbols) - -add_executable(testArchSystemInfo testSystemInfo.cpp) -target_link_libraries(testArchSystemInfo - PRIVATE - arch -) -add_test(testArchSystemInfo testArchSystemInfo) - -add_executable(testArchThreads testThreads.cpp) -target_link_libraries(testArchThreads - PRIVATE - arch -) -add_test(testArchThreads testArchThreads) - -add_executable(testArchTiming testTiming.cpp) -target_link_libraries(testArchTiming - PRIVATE - arch -) -add_test(testArchTiming testArchTiming) - -add_executable(testArchVsnprintf testVsnprintf.cpp) -target_link_libraries(testArchVsnprintf - PRIVATE - arch -) -add_test(testArchVsnprintf testArchVsnprintf) +add_subdirectory(utility) +add_subdirectory(unit) diff --git a/test/testArchAbi.cpp b/test/testArchAbi.cpp deleted file mode 100644 index 83b4585..0000000 --- a/test/testArchAbi.cpp +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2016 Pixar -// -// Licensed under the terms set forth in the LICENSE.txt file available at -// https://openusd.org/license. -// -// Modified by Jeremy Retailleau. - -#include "./testArchAbi.h" -#include -#include -#include -#include - -#include -#include - -using namespace pxr; - -typedef ArchAbiBase2* (*NewDerived)(); - -int -main(int /*argc*/, char** /*argv*/) -{ - // Compute the plugin directory. - std::string path = ArchGetExecutablePath(); - // Get directories. - path = path.substr(0, path.find_last_of("/\\")); - - // Load the plugin and get the factory function. -#if defined(ARCH_OS_WINDOWS) - path += "\\testArchAbiPlugin.dll"; -#elif defined(ARCH_OS_DARWIN) - path += "/libtestArchAbiPlugin.dylib"; -#else - path += "/libtestArchAbiPlugin.so"; -#endif - auto plugin = ArchLibraryOpen(path, ARCH_LIBRARY_LAZY); - if (!plugin) { - std::string error = ArchLibraryError(); - std::cerr << "Failed to load plugin: " << error << std::endl; - ARCH_AXIOM(plugin); - } - - NewDerived newPluginDerived = (NewDerived)ArchLibraryGetSymbolAddress( - plugin, "newDerived"); - if (!newPluginDerived) { - std::cerr << "Failed to find factory symbol" << std::endl; - ARCH_AXIOM(newPluginDerived); - } - - // Create a derived object in this executable and in the plugin. - ArchAbiBase2* mainDerived = new ArchAbiDerived; - ArchAbiBase2* pluginDerived = newPluginDerived(); - - // Compare. The types should be equal and the dynamic cast should not - // change the pointer. - std::cout - << "Derived types are equal: " - << ((typeid(*mainDerived) == typeid(*pluginDerived)) ? "yes" : "no") - << ", cast: " << pluginDerived - << "->" << dynamic_cast*>(pluginDerived) - << std::endl; - ARCH_AXIOM(typeid(*mainDerived) == typeid(*pluginDerived)); - ARCH_AXIOM(pluginDerived == dynamic_cast*>(pluginDerived)); - - return 0; -} diff --git a/test/testArchPRead.cpp b/test/testArchPRead.cpp deleted file mode 100644 index bc2f3f9..0000000 --- a/test/testArchPRead.cpp +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2021 Pixar -// -// Licensed under the terms set forth in the LICENSE.txt file available at -// https://openusd.org/license. -// -// Modified by Jeremy Retailleau. - -#include - -#include -#include - -using namespace pxr; - -int main(int argc, char** argv) -{ - if (argc < 3) { - printf("usage: %s \n", argv[0]); - printf("- Uses ArchPRead to read file and print the last N bytes.\n"); - return 1; - } - - const std::string filename(argv[1]); - size_t bytesFromEnd = 0; - - try { - bytesFromEnd = std::strtoul(argv[2], NULL, 10); - } - catch (const std::exception& e) { - printf("ERROR: Invalid number of bytes specified\n"); - return 1; - } - - - auto close_file = [](FILE* f) { fclose(f); }; - std::unique_ptr f( - fopen(filename.c_str(), "r"), close_file); - if (!f) { - printf("ERROR: Unable to open %s\n", filename.c_str()); - return 1; - } - - const int64_t fileSize = ArchGetFileLength(f.get()); - printf("Reading %s (%zu bytes)...\n", filename.c_str(), fileSize); - - std::unique_ptr fileContents(new char[fileSize]); - const int64_t numRead = ArchPRead(f.get(), fileContents.get(), fileSize, 0); - if (numRead != fileSize) { - printf("ERROR: Read %zu bytes, expected %zu\n", numRead, fileSize); - return 1; - } - - const std::string lastNBytes( - fileContents.get() + fileSize - bytesFromEnd, bytesFromEnd); - printf("%s", lastNBytes.c_str()); - - return 0; -} diff --git a/test/testDemangle.cpp b/test/testDemangle.cpp deleted file mode 100644 index 410d95f..0000000 --- a/test/testDemangle.cpp +++ /dev/null @@ -1,128 +0,0 @@ -// Copyright 2016 Pixar -// -// Licensed under the terms set forth in the LICENSE.txt file available at -// https://openusd.org/license. -// -// Modified by Jeremy Retailleau. - -#include -#include - -namespace pxr { - -class DummyClassInNamespace {}; -class OtherDummyClassInNamespace { - public: class SubClass { }; -}; - -template -class TemplatedDummyClassInNamespace { }; - -} // namespace pxr - - -using namespace pxr; - -template -class TemplatedDummyClass { }; - -struct Mangled {}; - -struct FooSsSsSsBar {}; - -template -class MangledAlso {}; - -typedef Mangled Remangled; - -enum MangleEnum { ONE, TWO, THREE }; - -static std::string -GetAlternativeTemplateTypename(std::string typeName) -{ - // Since C++11, the parser specification has been improved to be - // able to interpret successive right angle brackets in nested template - // declarations. The implementation of the C++ ABI has been updated - // accordingly on some systems, e.g. starting with Clang 14 on macOS 13.3. - // We accept a demangled result without additional white space between - // successive right angle brackets. - - const std::string oldStyle = "> >"; - const std::string newStyle = ">>"; - - std::string::size_type pos = 0; - while ((pos = typeName.find(oldStyle, pos)) != std::string::npos) { - typeName.replace(pos, oldStyle.size(), newStyle); - pos += newStyle.size() - 1; - } - - printf("\texpected alternative: '%s'\n", typeName.c_str()); - - return typeName; -} - -static bool -TypeNamesMatch(const std::string& demangledName, const std::string& expected) -{ - return (demangledName == expected) || - (demangledName == GetAlternativeTemplateTypename(expected)); -} - -template -static bool -TestDemangle(const std::string& typeName) -{ - const std::type_info& typeInfo = typeid(T); - std::string mangledName = typeInfo.name(); - std::string toBeDemangledName = typeInfo.name(); - - ARCH_AXIOM(ArchDemangle(&toBeDemangledName)); - - printf("ArchDemangle('%s') => '%s', expected '%s'\n", - mangledName.c_str(), toBeDemangledName.c_str(), typeName.c_str()); - - ARCH_AXIOM(TypeNamesMatch(toBeDemangledName, typeName)); - ARCH_AXIOM(TypeNamesMatch(ArchGetDemangled(mangledName), typeName)); - ARCH_AXIOM(TypeNamesMatch(ArchGetDemangled(typeInfo), typeName)); - ARCH_AXIOM(TypeNamesMatch(ArchGetDemangled(), typeName)); - - return true; -} - -int main() -{ - TestDemangle("bool"); - TestDemangle("Mangled"); - TestDemangle("Mangled"); - TestDemangle("MangleEnum"); - // We have special case code for std::string. - TestDemangle("string"); - TestDemangle>( - "TemplatedDummyClass"); - // This one is a regression test for a demangle bug on Linux. - TestDemangle("FooSsSsSsBar"); - - TestDemangle("pxr::DummyClassInNamespace"); - TestDemangle("pxr::OtherDummyClassInNamespace::SubClass"); - TestDemangle>( - "pxr::TemplatedDummyClassInNamespace"); - TestDemangle>( - "pxr::TemplatedDummyClassInNamespace"); - - TestDemangle("unsigned long"); - TestDemangle >("MangledAlso"); - - TestDemangle > >( - "MangledAlso >"); - TestDemangle > > >( - "MangledAlso > >"); - - const char* const badType = "type_that_doesnt_exist"; -#if defined(ARCH_OS_WINDOWS) - ARCH_AXIOM(ArchGetDemangled(badType) == badType); -#else - ARCH_AXIOM(ArchGetDemangled(badType) == ""); -#endif - - return 0; -} diff --git a/test/testFileSystem.cpp b/test/testFileSystem.cpp deleted file mode 100644 index 10e2e04..0000000 --- a/test/testFileSystem.cpp +++ /dev/null @@ -1,147 +0,0 @@ -// Copyright 2016 Pixar -// -// Licensed under the terms set forth in the LICENSE.txt file available at -// https://openusd.org/license. -// -// Modified by Jeremy Retailleau. - -#include -#include -#include - -#include -#include -#include -#include -#include - -using namespace pxr; - -ARCH_PRAGMA_DEPRECATED_POSIX_NAME - -static bool -TestArchNormPath() -{ - ARCH_AXIOM(ArchNormPath("") == "."); - ARCH_AXIOM(ArchNormPath(".") == "."); - ARCH_AXIOM(ArchNormPath("..") == ".."); - ARCH_AXIOM(ArchNormPath("foobar/../barbaz") == "barbaz"); - ARCH_AXIOM(ArchNormPath("/") == "/"); - ARCH_AXIOM(ArchNormPath("//") == "//"); - ARCH_AXIOM(ArchNormPath("///") == "/"); - ARCH_AXIOM(ArchNormPath("///foo/.//bar//") == "/foo/bar"); - ARCH_AXIOM(ArchNormPath("///foo/.//bar//.//..//.//baz") == "/foo/baz"); - ARCH_AXIOM(ArchNormPath("///..//./foo/.//bar") == "/foo/bar"); - ARCH_AXIOM(ArchNormPath( - "foo/bar/../../../../../../baz") == "../../../../baz"); - -#if defined(ARCH_OS_WINDOWS) - ARCH_AXIOM(ArchNormPath("C:\\foo\\bar") == "C:/foo/bar"); - ARCH_AXIOM(ArchNormPath("C:foo\\bar") == "C:foo/bar"); - ARCH_AXIOM(ArchNormPath("c:\\foo\\bar") == "c:/foo/bar"); - ARCH_AXIOM(ArchNormPath("c:foo\\bar") == "c:foo/bar"); - ARCH_AXIOM(ArchNormPath( - "C:\\foo\\bar", /* stripDriveSpecifier = */ true) == "/foo/bar"); - ARCH_AXIOM(ArchNormPath( - "C:foo\\bar", /* stripDriveSpecifier = */ true) == "foo/bar"); -#endif - - return true; -} - -namespace { -std::string -_AbsPathFilter(const std::string& path) -{ -#if defined(ARCH_OS_WINDOWS) - // Strip drive specifier and convert backslashes to forward slashes. - std::string result = path.substr(2); - std::replace(result.begin(), result.end(), '\\', '/'); - return result; -#else - // Return path as-is. - return path; -#endif -} -} - -static bool -TestArchAbsPath() -{ - ARCH_AXIOM(ArchAbsPath("") == ""); - ARCH_AXIOM(ArchAbsPath("foo") != "foo"); - ARCH_AXIOM(_AbsPathFilter(ArchAbsPath("/foo/bar")) == "/foo/bar"); - ARCH_AXIOM(_AbsPathFilter(ArchAbsPath("/foo/bar/../baz")) == "/foo/baz"); - - return true; -} - -int main() -{ - std::string firstName = ArchMakeTmpFileName("archFS"); - FILE *firstFile; - - char const * const testContent = "text in a file"; - - // Open a file, check that its length is 0, write to it, close it, and then - // check that its length is now the number of characters written. - ARCH_AXIOM((firstFile = ArchOpenFile(firstName.c_str(), "wb")) != NULL); - fflush(firstFile); - ARCH_AXIOM(ArchGetFileLength(firstName.c_str()) == 0); - fputs(testContent, firstFile); - fclose(firstFile); - ARCH_AXIOM(ArchGetFileLength(firstName.c_str()) == strlen(testContent)); - - // Open a file, check that the file path from FILE* handle is matched. - ARCH_AXIOM((firstFile = ArchOpenFile(firstName.c_str(), "rb")) != NULL); - std::string filePath = ArchGetFileName(firstFile); - ARCH_AXIOM(std::filesystem::equivalent(filePath, firstName)); - fclose(firstFile); - - // Map the file and assert the bytes are what we expect they are. - ARCH_AXIOM((firstFile = ArchOpenFile(firstName.c_str(), "rb")) != NULL); - ArchConstFileMapping cfm = ArchMapFileReadOnly(firstFile); - fclose(firstFile); - ARCH_AXIOM(cfm); - ARCH_AXIOM(memcmp(testContent, cfm.get(), strlen(testContent)) == 0); - cfm.reset(); - - // Try again with a mutable mapping. - ARCH_AXIOM((firstFile = ArchOpenFile(firstName.c_str(), "rb")) != NULL); - ArchMutableFileMapping mfm = ArchMapFileReadWrite(firstFile); - fclose(firstFile); - ARCH_AXIOM(mfm); - ARCH_AXIOM(memcmp(testContent, mfm.get(), strlen(testContent)) == 0); - // Check that we can successfully mutate. - mfm.get()[0] = 'T'; mfm.get()[2] = 's'; - ARCH_AXIOM(memcmp("Test", mfm.get(), strlen("Test")) == 0); - mfm.reset(); - ArchUnlinkFile(firstName.c_str()); - - // Test ArchPWrite and ArchPRead. - int64_t len = strlen(testContent); - ARCH_AXIOM((firstFile = ArchOpenFile(firstName.c_str(), "w+b")) != NULL); - ARCH_AXIOM(ArchPWrite(firstFile, testContent, len, 0) == len); - std::unique_ptr buf(new char[len]); - ARCH_AXIOM(ArchPRead(firstFile, buf.get(), len, 0) == len); - ARCH_AXIOM(memcmp(testContent, buf.get(), len) == 0); - char const * const newText = "overwritten in a file"; - ARCH_AXIOM(ArchPWrite(firstFile, newText, strlen(newText), - 5/*index of 'in a file'*/) == strlen(newText)); - std::unique_ptr buf2(new char[strlen("written in a")]); - ARCH_AXIOM(ArchPRead(firstFile, buf2.get(), strlen("written in a"), - 9/*index of 'written in a'*/) == strlen("written in a")); - ARCH_AXIOM(memcmp("written in a", buf2.get(), strlen("written in a")) == 0); - - // create and remove a tmp subdir - std::string retpath; - retpath = ArchMakeTmpSubdir(ArchGetTmpDir(), "myprefix"); - ARCH_AXIOM (retpath != ""); - ArchRmDir(retpath.c_str()); - - // Test other utilities - TestArchNormPath(); - TestArchAbsPath(); - - return 0; -} diff --git a/test/testFunction.cpp b/test/testFunction.cpp deleted file mode 100644 index 75ab477..0000000 --- a/test/testFunction.cpp +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2016 Pixar -// -// Licensed under the terms set forth in the LICENSE.txt file available at -// https://openusd.org/license. -// -// Modified by Jeremy Retailleau. - -#include -#include - -using namespace pxr; - -int main() -{ - // Non-member - ARCH_AXIOM(ArchGetPrettierFunctionName("Bar", "int Bar(float)") - == "Bar"); - - // Template non-member function - ARCH_AXIOM(ArchGetPrettierFunctionName("Bar", "int Bar(C) [with C = int]") - == "Bar"); - ARCH_AXIOM(ArchGetPrettierFunctionName("Bar", "int Bar(C)") - == "Bar"); - - // Non-template class non-template member function - ARCH_AXIOM(ArchGetPrettierFunctionName("Bar", "int Foo::Bar(float)") - == "Foo::Bar"); - - // Template class member function - ARCH_AXIOM(ArchGetPrettierFunctionName("Bar", - "int Foo::Bar(float) [with A = int]") - == "Foo::Bar [with A = int]"); - - // Multi-parameter template class - ARCH_AXIOM(ArchGetPrettierFunctionName("Bar", - "int Foo::Bar(float) [with A = int, B = int]") - == "Foo::Bar [with A = int, B = int]"); - - // Template function - ARCH_AXIOM(ArchGetPrettierFunctionName("Bar", - "A Foo::Bar(C) [with C = double; B = float; A = int]") - == "Foo::Bar [with A = int, B = float]"); - - // Linux-style nested templates - ARCH_AXIOM(ArchGetPrettierFunctionName("foo", - "int X::Y::foo(A, B, C) [with C = bool; B = float; A = int]") - == "X::Y::foo [with A = int, B = float]"); - - // Linux-style nested templates with templates for template arguments - ARCH_AXIOM(ArchGetPrettierFunctionName("foo", - "int X::Y::foo(A, B, C) [with C = bool; B = Z::W; A = Z]") - == "X::Y::foo [with A = Z, B = Z::W]"); - - // Windows-style nested templates - ARCH_AXIOM(ArchGetPrettierFunctionName("foo", - "int __cdecl X::Y::foo(int,float,bool)") - == "X::Y::foo"); - - // Windows-style nested templates with templates for template arguments - ARCH_AXIOM(ArchGetPrettierFunctionName("foo", - "int __cdecl X >::Y::W >::foo(Z,Z::W,bool)") - == "X >::Y::W >::foo"); - - // Edge cases. - ARCH_AXIOM(ArchGetPrettierFunctionName("operator<", "bool operator<(X, Y)") - == "operator<"); - ARCH_AXIOM(ArchGetPrettierFunctionName("operator<", "bool Z::operator<(Y) const [with W = int]") - == "Z::operator< [with W = int]"); - ARCH_AXIOM(ArchGetPrettierFunctionName("operator<<", "int operator<<(X, int)") - == "operator<<"); - - return 0; -} - diff --git a/test/testMath.cpp b/test/testMath.cpp deleted file mode 100644 index 2fcec4b..0000000 --- a/test/testMath.cpp +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2019 Pixar -// -// Licensed under the terms set forth in the LICENSE.txt file available at -// https://openusd.org/license. -// -// Modified by Jeremy Retailleau. - -#include -#include - -using namespace pxr; - -#define AXIOM(cond) \ - if (!(cond)) { ARCH_ERROR("failed: " #cond); } - -int main() -{ - /* - * Verify that the exponent and significand of float and double are - * IEEE-754 compliant. - */ - if (ArchFloatToBitPattern(5.6904566e-28f) != 0x12345678 || - ArchBitPatternToFloat(0x12345678) != 5.6904566e-28f) { - ARCH_ERROR("float is not IEEE-754 compliant"); - } - if (ArchDoubleToBitPattern( - 5.6263470058989390e-221) != 0x1234567811223344ULL || - ArchBitPatternToDouble( - 0x1234567811223344ULL) != 5.6263470058989390e-221) { - ARCH_ERROR("double is not IEEE-754 compliant"); - } - - AXIOM(ArchSign(-123) == -1); - AXIOM(ArchSign(123) == 1); - AXIOM(ArchSign(0) == 0); - - AXIOM(ArchCountTrailingZeros(1) == 0); - AXIOM(ArchCountTrailingZeros(2) == 1); - AXIOM(ArchCountTrailingZeros(3) == 0); - AXIOM(ArchCountTrailingZeros(4) == 2); - AXIOM(ArchCountTrailingZeros(5) == 0); - AXIOM(ArchCountTrailingZeros(6) == 1); - AXIOM(ArchCountTrailingZeros(7) == 0); - AXIOM(ArchCountTrailingZeros(8) == 3); - - AXIOM(ArchCountTrailingZeros(65535) == 0); - AXIOM(ArchCountTrailingZeros(65536) == 16); - - AXIOM(ArchCountTrailingZeros(~((1ull << 32ull)-1ull)) == 32); - AXIOM(ArchCountTrailingZeros(1ull << 63ull) == 63); - - return 0; -} diff --git a/test/unit/CMakeLists.txt b/test/unit/CMakeLists.txt new file mode 100644 index 0000000..59f7207 --- /dev/null +++ b/test/unit/CMakeLists.txt @@ -0,0 +1,162 @@ +if (WIN32) + # Patch Gtest discovery command to extend the DLL search path on Windows. + + macro(gtest_discover_tests NAME) + gtest_add_tests(TARGET ${NAME} TEST_LIST tests) + + # Sanitize and extend environment. + cmake_parse_arguments("" "" "" "PROPERTIES" ${ARGN}) + cmake_parse_arguments("" "" "" "ENVIRONMENT" ${_PROPERTIES}) + + # Apply environment to newly added tests. + set(DLL_DIRS $) + + set_tests_properties(${tests} + PROPERTIES ENVIRONMENT + "${_ENVIRONMENT};PATH=$,\\;>") + endmacro() + + # Patch CMake's 'add_test' to extend the DLL search path on Windows based + # on the command associated with the test, which is also a CMake target in + # this case. + + macro(add_test) + _add_test(${ARGV}) + + cmake_parse_arguments("" "" "NAME;COMMAND" "" ${ARGV}) + set(DLL_DIRS $) + set_tests_properties(${_NAME} + PROPERTIES ENVIRONMENT + "PATH=$,\\;>") + endmacro() +endif() + +add_executable(testArchAbi testArchAbi.cpp) +target_link_libraries(testArchAbi + PRIVATE + arch + archTest + GTest::gtest + GTest::gtest_main +) +gtest_discover_tests( + testArchAbi + PROPERTIES + ENVIRONMENT "EXE_PATH=$>" + ENVIRONMENT "PLUGIN_PATH=$" +) + +add_executable(testArchAttributes testAttributes.cpp) +target_link_libraries(testArchAttributes + PRIVATE + arch + GTest::gtest +) +add_test(NAME AttributeTest.OperationOrder COMMAND testArchAttributes) + +add_executable(testArchDemangle testDemangle.cpp) +target_link_libraries(testArchDemangle + PRIVATE + arch + GTest::gtest + GTest::gtest_main +) +gtest_discover_tests(testArchDemangle) + +add_executable(testArchError testError.cpp) +target_link_libraries(testArchError + PRIVATE + arch + archTest +) +add_test(NAME ErrorTest.TestCrash COMMAND testArchError) + +add_executable(testArchErrno testErrno.cpp) +target_link_libraries(testArchErrno + PRIVATE + arch + GTest::gtest + GTest::gtest_main +) +gtest_discover_tests(testArchErrno) + +add_executable(testArchFileSystem testFileSystem.cpp) +target_link_libraries(testArchFileSystem + PRIVATE + arch + GTest::gtest + GTest::gtest_main +) +gtest_discover_tests(testArchFileSystem) + +add_executable(testArchFunction testFunction.cpp) +target_link_libraries(testArchFunction + PRIVATE + arch + GTest::gtest + GTest::gtest_main +) +gtest_discover_tests(testArchFunction) + +add_executable(testArchMath testMath.cpp) +target_link_libraries(testArchMath + PRIVATE + arch + GTest::gtest + GTest::gtest_main +) +gtest_discover_tests(testArchMath) + +add_executable(testArchStackTrace testStackTrace.cpp) +target_link_libraries(testArchStackTrace + PRIVATE + arch + archTest + GTest::gtest +) +gtest_discover_tests(testArchStackTrace) + +add_executable(testArchSymbols testSymbols.cpp) +target_link_libraries(testArchSymbols + PRIVATE + arch + GTest::gtest + GTest::gtest_main +) +gtest_discover_tests(testArchSymbols) + +add_executable(testArchSystemInfo testSystemInfo.cpp) +target_link_libraries(testArchSystemInfo + PRIVATE + arch + GTest::gtest + GTest::gtest_main +) +gtest_discover_tests(testArchSystemInfo) + +add_executable(testArchThreads testThreads.cpp) +target_link_libraries(testArchThreads + PRIVATE + arch + GTest::gtest + GTest::gtest_main +) +gtest_discover_tests(testArchThreads) + +add_executable(testArchTiming testTiming.cpp) +target_link_libraries(testArchTiming + PRIVATE + arch + GTest::gtest + GTest::gtest_main +) +gtest_discover_tests(testArchTiming) + +add_executable(testArchVsnprintf testVsnprintf.cpp) +target_link_libraries(testArchVsnprintf + PRIVATE + arch + GTest::gtest + GTest::gtest_main +) +gtest_discover_tests(testArchVsnprintf) diff --git a/test/unit/testArchAbi.cpp b/test/unit/testArchAbi.cpp new file mode 100644 index 0000000..cb99572 --- /dev/null +++ b/test/unit/testArchAbi.cpp @@ -0,0 +1,75 @@ +// Copyright 2016 Pixar +// +// Licensed under the terms set forth in the LICENSE.txt file available at +// https://openusd.org/license. +// +// Modified by Jeremy Retailleau. + +#include +#include +#include +#include + +#include +#include + +using namespace pxr; + +TEST(ArchABITest, GetExecutablePath) +{ + std::string path = ArchGetExecutablePath(); + std::string root = std::getenv("EXE_PATH"); +#if defined(ARCH_OS_WINDOWS) + std::string expected = root + "\\testArchAbi.exe"; +#else + std::string expected = root + "/testArchAbi"; +#endif + ASSERT_EQ(path, expected); +} + +TEST(ArchABITest, Library) +{ + std::string path = std::getenv("PLUGIN_PATH"); +#if defined(ARCH_OS_WINDOWS) + path += "\\archTestPlugin.dll"; +#elif defined(ARCH_OS_DARWIN) + path += "/libarchTestPlugin.dylib"; +#else + path += "/libarchTestPlugin.so"; +#endif + auto plugin = ArchLibraryOpen(path, ARCH_LIBRARY_LAZY); + ASSERT_NE(plugin, nullptr); + ASSERT_EQ(ArchLibraryError(), ""); + + // Get symbol from library. + using NewDerived = ArchAbiBase2* (*)(); + auto newPluginDerived = + (NewDerived)ArchLibraryGetSymbolAddress(plugin, "newDerived"); + ASSERT_NE(newPluginDerived, nullptr); + + // Fail to get symbol from library. + auto symbol = + (NewDerived)ArchLibraryGetSymbolAddress(plugin, "incorrect"); + ASSERT_EQ(symbol, nullptr); + + // Create a derived object in this executable and in the plugin. + ArchAbiBase2* mainDerived = new ArchAbiDerived; + ArchAbiBase2* pluginDerived = newPluginDerived(); + + // The types should be equal and the dynamic cast should not + // change the pointer. + ASSERT_EQ(typeid(*mainDerived), typeid(*pluginDerived)); + ASSERT_EQ( + pluginDerived, dynamic_cast*>(pluginDerived)); + + auto status = ArchLibraryClose(plugin); + ASSERT_EQ(status, 0); +} + +TEST(ArchABITest, LibraryOpenError) +{ + std::string path = "/incorrect"; + auto plugin = ArchLibraryOpen(path, ARCH_LIBRARY_LAZY); + ASSERT_EQ(plugin, nullptr); + ASSERT_NE(ArchLibraryError(), ""); +} diff --git a/test/testAttributes.cpp b/test/unit/testAttributes.cpp similarity index 82% rename from test/testAttributes.cpp rename to test/unit/testAttributes.cpp index 1e9b79f..9278d81 100644 --- a/test/testAttributes.cpp +++ b/test/unit/testAttributes.cpp @@ -6,9 +6,8 @@ // Modified by Jeremy Retailleau. #include -#include +#include -#include #include using namespace pxr; @@ -52,7 +51,7 @@ static const Bits dependencies[NumOperations] = { /* Dtor20Op */ BIT(Dtor30Op) }; -static void TestAndSet(Operation operation) +static testing::AssertionResult IsOrderCorrect(Operation operation) { static const char binary[][5] = { "0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", @@ -62,18 +61,20 @@ static void TestAndSet(Operation operation) // Check dependencies. const Bits deps = dependencies[operation]; if ((done & deps) != deps) { - fprintf(stderr, "Failed on operation %d: %s%s%s%s expected %s%s%s%s\n", - operation, - binary[(done >> 12) & 15], - binary[(done >> 8) & 15], - binary[(done >> 4) & 15], - binary[(done ) & 15], - binary[(deps >> 12) & 15], - binary[(deps >> 8) & 15], - binary[(deps >> 4) & 15], - binary[(deps ) & 15]); + return testing::AssertionFailure() + << "Failed on operation " << operation << ": " + << binary[(done >> 12) & 15] << binary[(done >> 8) & 15] + << binary[(done >> 4) & 15] << binary[(done)&15] << " expected " + << binary[(deps >> 12) & 15] << binary[(deps >> 8) & 15] + << binary[(deps >> 4) & 15] << binary[(deps)&15]; } - ARCH_AXIOM((done & deps) == deps); + + return testing::AssertionSuccess() << "Order correct."; +} + +static void TestAndSet(Operation operation) +{ + ASSERT_TRUE(IsOrderCorrect(operation)); done |= BIT(operation); } diff --git a/test/unit/testDemangle.cpp b/test/unit/testDemangle.cpp new file mode 100644 index 0000000..ad03c87 --- /dev/null +++ b/test/unit/testDemangle.cpp @@ -0,0 +1,241 @@ +// Copyright 2016 Pixar +// +// Licensed under the terms set forth in the LICENSE.txt file available at +// https://openusd.org/license. +// +// Modified by Jeremy Retailleau. + +#include +#include + +#include + +using namespace pxr; + +struct MangledStruct { +}; +typedef MangledStruct MangledStructAlias; + +enum MangledEnum { ONE, TWO, THREE }; + +template +class MangledTemplatedClass { +}; + +// Ad std::string is mangled as 'Ss' on Linux, check that the following +// struct is properly demangled. +struct FooSsSsSsBar { +}; + +class MangledClass1 { +}; + +class MangledClass2 { + public: + class SubClass { + }; +}; + +TEST(DemangleTest, Bool) +{ + const std::type_info& typeInfo = typeid(bool); + std::string mangledName = typeInfo.name(); + std::string toBeDemangledName = typeInfo.name(); + + ASSERT_TRUE(ArchDemangle(&toBeDemangledName)); + + ASSERT_EQ(toBeDemangledName, "bool"); + ASSERT_EQ(ArchGetDemangled(mangledName), "bool"); + ASSERT_EQ(ArchGetDemangled(typeInfo), "bool"); + ASSERT_EQ(ArchGetDemangled(), "bool"); +} + +TEST(DemangleTest, Struct) +{ + const std::type_info& typeInfo = typeid(MangledStruct); + std::string mangledName = typeInfo.name(); + std::string toBeDemangledName = typeInfo.name(); + + ASSERT_TRUE(ArchDemangle(&toBeDemangledName)); + + ASSERT_EQ(toBeDemangledName, "MangledStruct"); + ASSERT_EQ(ArchGetDemangled(mangledName), "MangledStruct"); + ASSERT_EQ(ArchGetDemangled(typeInfo), "MangledStruct"); + ASSERT_EQ(ArchGetDemangled(), "MangledStruct"); +} + +TEST(DemangleTest, StructAlias) +{ + const std::type_info& typeInfo = typeid(MangledStructAlias); + std::string mangledName = typeInfo.name(); + std::string toBeDemangledName = typeInfo.name(); + + ASSERT_TRUE(ArchDemangle(&toBeDemangledName)); + + ASSERT_EQ(toBeDemangledName, "MangledStruct"); + ASSERT_EQ(ArchGetDemangled(mangledName), "MangledStruct"); + ASSERT_EQ(ArchGetDemangled(typeInfo), "MangledStruct"); + ASSERT_EQ(ArchGetDemangled(), "MangledStruct"); +} + +TEST(DemangleTest, Enum) +{ + const std::type_info& typeInfo = typeid(MangledEnum); + std::string mangledName = typeInfo.name(); + std::string toBeDemangledName = typeInfo.name(); + + ASSERT_TRUE(ArchDemangle(&toBeDemangledName)); + + ASSERT_EQ(toBeDemangledName, "MangledEnum"); + ASSERT_EQ(ArchGetDemangled(mangledName), "MangledEnum"); + ASSERT_EQ(ArchGetDemangled(typeInfo), "MangledEnum"); + ASSERT_EQ(ArchGetDemangled(), "MangledEnum"); +} + +TEST(DemangleTest, String) +{ + const std::type_info& typeInfo = typeid(std::string); + std::string mangledName = typeInfo.name(); + std::string toBeDemangledName = typeInfo.name(); + + ASSERT_TRUE(ArchDemangle(&toBeDemangledName)); + + ASSERT_EQ(toBeDemangledName, "string"); + ASSERT_EQ(ArchGetDemangled(mangledName), "string"); + ASSERT_EQ(ArchGetDemangled(typeInfo), "string"); + ASSERT_EQ(ArchGetDemangled(), "string"); +} + +TEST(DemangleTest, TemplatedClassString) +{ + const std::type_info& typeInfo = typeid(MangledTemplatedClass); + std::string mangledName = typeInfo.name(); + std::string toBeDemangledName = typeInfo.name(); + + ASSERT_TRUE(ArchDemangle(&toBeDemangledName)); + + ASSERT_EQ(toBeDemangledName, "MangledTemplatedClass"); + ASSERT_EQ(ArchGetDemangled(mangledName), "MangledTemplatedClass"); + ASSERT_EQ(ArchGetDemangled(typeInfo), "MangledTemplatedClass"); + ASSERT_EQ( + ArchGetDemangled>(), + "MangledTemplatedClass"); +} + +TEST(DemangleTest, StringConfusingMatch) +{ + const std::type_info& typeInfo = typeid(FooSsSsSsBar); + std::string mangledName = typeInfo.name(); + std::string toBeDemangledName = typeInfo.name(); + + ASSERT_TRUE(ArchDemangle(&toBeDemangledName)); + + ASSERT_EQ(toBeDemangledName, "FooSsSsSsBar"); + ASSERT_EQ(ArchGetDemangled(mangledName), "FooSsSsSsBar"); + ASSERT_EQ(ArchGetDemangled(typeInfo), "FooSsSsSsBar"); + ASSERT_EQ(ArchGetDemangled(), "FooSsSsSsBar"); +} + +TEST(DemangleTest, Class) +{ + const std::type_info& typeInfo = typeid(MangledClass1); + std::string mangledName = typeInfo.name(); + std::string toBeDemangledName = typeInfo.name(); + + ASSERT_TRUE(ArchDemangle(&toBeDemangledName)); + + ASSERT_EQ(toBeDemangledName, "MangledClass1"); + ASSERT_EQ(ArchGetDemangled(mangledName), "MangledClass1"); + ASSERT_EQ(ArchGetDemangled(typeInfo), "MangledClass1"); + ASSERT_EQ( + ArchGetDemangled(), + "MangledClass1"); +} + +TEST(DemangleTest, SubClass) +{ + const std::type_info& typeInfo = typeid(MangledClass2::SubClass); + std::string mangledName = typeInfo.name(); + std::string toBeDemangledName = typeInfo.name(); + + ASSERT_TRUE(ArchDemangle(&toBeDemangledName)); + + ASSERT_EQ(toBeDemangledName, "MangledClass2::SubClass"); + ASSERT_EQ( + ArchGetDemangled(mangledName), "MangledClass2::SubClass"); + ASSERT_EQ( + ArchGetDemangled(typeInfo), "MangledClass2::SubClass"); + ASSERT_EQ( + ArchGetDemangled(), + "MangledClass2::SubClass"); +} + +TEST(DemangleTest, Long) +{ + const std::type_info& typeInfo = typeid(unsigned long); + std::string mangledName = typeInfo.name(); + std::string toBeDemangledName = typeInfo.name(); + + ASSERT_TRUE(ArchDemangle(&toBeDemangledName)); + + ASSERT_EQ(toBeDemangledName, "unsigned long"); + ASSERT_EQ(ArchGetDemangled(mangledName), "unsigned long"); + ASSERT_EQ(ArchGetDemangled(typeInfo), "unsigned long"); + ASSERT_EQ(ArchGetDemangled(), "unsigned long"); +} + +TEST(DemangleTest, TemplatedClassInt) +{ + const std::type_info& typeInfo = typeid(MangledTemplatedClass); + std::string mangledName = typeInfo.name(); + std::string toBeDemangledName = typeInfo.name(); + + ASSERT_TRUE(ArchDemangle(&toBeDemangledName)); + + ASSERT_EQ(toBeDemangledName, "MangledTemplatedClass"); + ASSERT_EQ(ArchGetDemangled(mangledName), "MangledTemplatedClass"); + ASSERT_EQ(ArchGetDemangled(typeInfo), "MangledTemplatedClass"); + ASSERT_EQ( + ArchGetDemangled>(), + "MangledTemplatedClass"); +} + +TEST(DemangleTest, TemplatedClassRecursiveInt) +{ + const std::type_info& typeInfo = + typeid(MangledTemplatedClass>); + std::string mangledName = typeInfo.name(); + std::string toBeDemangledName = typeInfo.name(); + + ASSERT_TRUE(ArchDemangle(&toBeDemangledName)); + + // Since C++11, the parser specification has been improved to be + // able to interpret successive right angle brackets in nested template + // declarations. The implementation of the C++ ABI has been updated + // accordingly on some systems, e.g. starting with Clang 14 on macOS 13.3. + // We accept a demangled result without additional white space between + // successive right angle brackets. + + const char* const oldStyle = "MangledTemplatedClass >"; + const char* const newStyle = "MangledTemplatedClass>"; + + const auto isDemangledCorrectly = [&](const std::string& demangledName) { + return demangledName == oldStyle || demangledName == newStyle; + }; + + ASSERT_TRUE(isDemangledCorrectly(toBeDemangledName)); + ASSERT_TRUE(isDemangledCorrectly(ArchGetDemangled(mangledName))); + ASSERT_TRUE(isDemangledCorrectly(ArchGetDemangled(typeInfo))); + ASSERT_TRUE(isDemangledCorrectly( + ArchGetDemangled>>())); +} + +TEST(DemangleTest, IncorrectType) +{ + const char* const badType = "type_that_doesnt_exist"; +#if defined(ARCH_OS_WINDOWS) + ASSERT_EQ(ArchGetDemangled(badType), badType); +#else + ASSERT_EQ(ArchGetDemangled(badType), ""); +#endif +} diff --git a/test/testErrno.cpp b/test/unit/testErrno.cpp similarity index 53% rename from test/testErrno.cpp rename to test/unit/testErrno.cpp index 172aca5..eefa692 100644 --- a/test/testErrno.cpp +++ b/test/unit/testErrno.cpp @@ -6,19 +6,13 @@ // Modified by Jeremy Retailleau. #include -#include - -#include +#include using namespace pxr; -int main(int /*argc*/, char** /*argv*/) +TEST(ErrnoTest, ErrorMessages) { for (int i = -1; i < 10; i++) { - const std::string msg = ArchStrerror(i); - ARCH_AXIOM(!msg.empty()); - printf("%d -> '%s'\n", i, msg.c_str()); + ASSERT_NE(ArchStrerror(i), ""); } - - return 0; } diff --git a/test/testError.cpp b/test/unit/testError.cpp similarity index 86% rename from test/testError.cpp rename to test/unit/testError.cpp index 48cc5f1..6948166 100644 --- a/test/testError.cpp +++ b/test/unit/testError.cpp @@ -7,8 +7,7 @@ // // Modified by Jeremy Retailleau. -#include -#include "./testArchUtil.h" +#include using namespace pxr; @@ -16,4 +15,6 @@ int main(int argc, char** argv) { ArchTestCrashArgParse(argc, argv); ArchTestCrash(ArchTestCrashMode::Error); + + return 0; } diff --git a/test/unit/testFileSystem.cpp b/test/unit/testFileSystem.cpp new file mode 100644 index 0000000..eeacc41 --- /dev/null +++ b/test/unit/testFileSystem.cpp @@ -0,0 +1,132 @@ +// Copyright 2016 Pixar +// +// Licensed under the terms set forth in the LICENSE.txt file available at +// https://openusd.org/license. +// +// Modified by Jeremy Retailleau. + +#include +#include + +#include +#include +#include + +using namespace pxr; + +TEST(FileSystemTest, FileOperations) +{ + std::string firstName = ArchMakeTmpFileName("archFS"); + FILE *firstFile; + + char const * const testContent = "text in a file"; + + // Open a file, check that its length is 0, write to it, close it, and then + // check that its length is now the number of characters written. + ASSERT_NE((firstFile = ArchOpenFile(firstName.c_str(), "wb")), nullptr); + fflush(firstFile); + ASSERT_EQ(ArchGetFileLength(firstName.c_str()), 0); + fputs(testContent, firstFile); + fclose(firstFile); + ASSERT_EQ(ArchGetFileLength(firstName.c_str()), strlen(testContent)); + + // Open a file, check that the file path from FILE* handle is matched. + ASSERT_NE((firstFile = ArchOpenFile(firstName.c_str(), "rb")), nullptr); + std::string filePath = ArchGetFileName(firstFile); + ASSERT_TRUE(std::filesystem::equivalent(filePath, firstName)); + fclose(firstFile); + + // Map the file and assert the bytes are what we expect they are. + ASSERT_NE((firstFile = ArchOpenFile(firstName.c_str(), "rb")), nullptr); + ArchConstFileMapping cfm = ArchMapFileReadOnly(firstFile); + fclose(firstFile); + ASSERT_TRUE(cfm); + ASSERT_EQ(memcmp(testContent, cfm.get(), strlen(testContent)), 0); + cfm.reset(); + + // Try again with a mutable mapping. + ASSERT_NE((firstFile = ArchOpenFile(firstName.c_str(), "rb")), nullptr); + ArchMutableFileMapping mfm = ArchMapFileReadWrite(firstFile); + fclose(firstFile); + ASSERT_TRUE(mfm); + ASSERT_EQ(memcmp(testContent, mfm.get(), strlen(testContent)), 0); + // Check that we can successfully mutate. + mfm.get()[0] = 'T'; + mfm.get()[2] = 's'; + ASSERT_EQ(memcmp("Test", mfm.get(), strlen("Test")), 0); + mfm.reset(); + ArchUnlinkFile(firstName.c_str()); + + // Test PWrite and PRead. + auto len = (int64_t)strlen(testContent); + ASSERT_NE((firstFile = ArchOpenFile(firstName.c_str(), "w+b")), nullptr); + ASSERT_EQ(ArchPWrite(firstFile, testContent, len, 0), len); + std::unique_ptr buf(new char[len]); + ASSERT_EQ(ArchPRead(firstFile, buf.get(), len, 0), len); + ASSERT_EQ(memcmp(testContent, buf.get(), len), 0); + char const * const newText = "overwritten in a file"; + ASSERT_EQ(ArchPWrite(firstFile, newText, strlen(newText), + 5/*index of 'in a file'*/), strlen(newText)); + std::unique_ptr buf2(new char[strlen("written in a")]); + ASSERT_EQ(ArchPRead(firstFile, buf2.get(), strlen("written in a"), + 9/*index of 'written in a'*/), strlen("written in a")); + ASSERT_EQ(memcmp("written in a", buf2.get(), strlen("written in a")), 0); + + // create and remove a tmp subdir + std::string retpath; + retpath = ArchMakeTmpSubdir(ArchGetTmpDir(), "myprefix"); + ASSERT_NE(retpath, ""); + ArchRmDir(retpath.c_str()); +} + +TEST(FileSystemTest, NormPath) +{ + ASSERT_EQ(ArchNormPath(""), "."); + ASSERT_EQ(ArchNormPath("."), "."); + ASSERT_EQ(ArchNormPath(".."), ".."); + ASSERT_EQ(ArchNormPath("foobar/../barbaz"), "barbaz"); + ASSERT_EQ(ArchNormPath("/"), "/"); + ASSERT_EQ(ArchNormPath("//"), "//"); + ASSERT_EQ(ArchNormPath("///"), "/"); + ASSERT_EQ(ArchNormPath("///foo/.//bar//"), "/foo/bar"); + ASSERT_EQ(ArchNormPath("///foo/.//bar//.//..//.//baz"), "/foo/baz"); + ASSERT_EQ(ArchNormPath("///..//./foo/.//bar"), "/foo/bar"); + ASSERT_EQ( + ArchNormPath("foo/bar/../../../../../../baz"), "../../../../baz"); + +#if defined(ARCH_OS_WINDOWS) + ASSERT_EQ(ArchNormPath("C:\\foo\\bar"), "C:/foo/bar"); + ASSERT_EQ(ArchNormPath("C:foo\\bar"), "C:foo/bar"); + ASSERT_EQ(ArchNormPath("c:\\foo\\bar"), "c:/foo/bar"); + ASSERT_EQ(ArchNormPath("c:foo\\bar"), "c:foo/bar"); + ASSERT_EQ( + ArchNormPath("C:\\foo\\bar", /* stripDriveSpecifier = */ true), + "/foo/bar"); + ASSERT_EQ( + ArchNormPath("C:foo\\bar", /* stripDriveSpecifier = */ true), + "foo/bar"); +#endif +} + +TEST(FileSystemTest, AbsPath) +{ + ASSERT_EQ(ArchAbsPath(""), ""); + ASSERT_NE(ArchAbsPath("foo"), "foo"); + + auto path1 = ArchAbsPath("/foo/bar"); + auto path2 = ArchAbsPath("/foo/bar/../baz"); + +#if defined(ARCH_OS_WINDOWS) + // Strip drive specifier and convert backslashes to forward slashes. + std::string _path1 = path1.substr(2); + std::replace(_path1.begin(), _path1.end(), '\\', '/'); + ASSERT_EQ(_path1, "/foo/bar"); + + std::string _path2 = path2.substr(2); + std::replace(_path2.begin(), _path2.end(), '\\', '/'); + ASSERT_EQ(_path2, "/foo/baz"); +#else + ASSERT_EQ(path1, "/foo/bar"); + ASSERT_EQ(path2, "/foo/baz"); +#endif +} diff --git a/test/unit/testFunction.cpp b/test/unit/testFunction.cpp new file mode 100644 index 0000000..0ce4d91 --- /dev/null +++ b/test/unit/testFunction.cpp @@ -0,0 +1,86 @@ +// Copyright 2016 Pixar +// +// Licensed under the terms set forth in the LICENSE.txt file available at +// https://openusd.org/license. +// +// Modified by Jeremy Retailleau. + +#include +#include + +using namespace pxr; + +TEST(FunctionTest, GetPrettierFunctionName) +{ + // Non-member + ASSERT_EQ(ArchGetPrettierFunctionName("Bar", "int Bar(float)"), "Bar"); + + // Template non-member function + ASSERT_EQ(ArchGetPrettierFunctionName("Bar", "int Bar(C) [with C = int]"), + "Bar"); + ASSERT_EQ(ArchGetPrettierFunctionName("Bar", "int Bar(C)"), "Bar"); + + // Non-template class non-template member function + ASSERT_EQ(ArchGetPrettierFunctionName("Bar", "int Foo::Bar(float)"), + "Foo::Bar"); + + // Template class member function + ASSERT_EQ( + ArchGetPrettierFunctionName( + "Bar", "int Foo::Bar(float) [with A = int]"), + "Foo::Bar [with A = int]"); + + // Multi-parameter template class + ASSERT_EQ( + ArchGetPrettierFunctionName( + "Bar", "int Foo::Bar(float) [with A = int, B = int]"), + "Foo::Bar [with A = int, B = int]"); + + // Template function + ASSERT_EQ( + ArchGetPrettierFunctionName( + "Bar", "A Foo::Bar(C) [with C = double; B = float; A = int]"), + "Foo::Bar [with A = int, B = float]"); + + // Linux-style nested templates + ASSERT_EQ( + ArchGetPrettierFunctionName( + "foo", + "int X::Y::foo(A, B, C) [with C = bool; B = float; A = int]"), + "X::Y::foo [with A = int, B = float]"); + + // Linux-style nested templates with templates for template arguments + ASSERT_EQ( + ArchGetPrettierFunctionName( + "foo", + "int X::Y::foo(A, B, C) [with C = bool; B = " + "Z::W; A = Z]"), + "X::Y::foo [with A = Z, B = " + "Z::W]"); + + // Windows-style nested templates + ASSERT_EQ( + ArchGetPrettierFunctionName( + "foo", "int __cdecl X::Y::foo(int,float,bool)"), + "X::Y::foo"); + + // Windows-style nested templates with templates for template arguments + ASSERT_EQ( + ArchGetPrettierFunctionName( + "foo", + "int __cdecl X >::Y::W >" + "::foo(Z,Z::W,bool)"), + "X >::Y::W >::foo"); + + // Edge cases. + ASSERT_EQ( + ArchGetPrettierFunctionName("operator<", "bool operator<(X, Y)"), + "operator<"); + ASSERT_EQ( + ArchGetPrettierFunctionName( + "operator<", "bool Z::operator<(Y) const [with W = int]"), + "Z::operator< [with W = int]"); + ASSERT_EQ( + ArchGetPrettierFunctionName("operator<<", "int operator<<(X, int)"), + "operator<<"); +} diff --git a/test/unit/testMath.cpp b/test/unit/testMath.cpp new file mode 100644 index 0000000..30e158c --- /dev/null +++ b/test/unit/testMath.cpp @@ -0,0 +1,68 @@ +// Copyright 2019 Pixar +// +// Licensed under the terms set forth in the LICENSE.txt file available at +// https://openusd.org/license. +// +// Modified by Jeremy Retailleau. + +#include +#include + +#include + +using namespace pxr; + +static testing::AssertionResult IsCompliant(bool cond, const char* type) +{ + if (!cond) { + return testing::AssertionFailure() + << "failed: " << type << " is not IEEE-754 compliant"; + } + + return testing::AssertionSuccess() << type << " is IEEE-754 compliant."; +} + +TEST(MathTest, FloatIEEE754Compliance) +{ + auto a = 5.6904566e-28f; + auto b = 0x12345678; + auto cond = + (ArchFloatToBitPattern(a) == b && ArchBitPatternToFloat(b) == a); + + ASSERT_TRUE(IsCompliant(cond, "float")); +} + +TEST(MathTest, DoubleIEEE754Compliance) +{ + auto a = 5.6263470058989390e-221; + auto b = 0x1234567811223344ULL; + auto cond = + (ArchDoubleToBitPattern(a) == b && ArchBitPatternToDouble(b) == a); + + ASSERT_TRUE(IsCompliant(cond, "double")); +} + +TEST(MathTest, Sign) +{ + ASSERT_EQ(ArchSign(-123), -1); + ASSERT_EQ(ArchSign(123), 1); + ASSERT_EQ(ArchSign(0), 0); +} + +TEST(MathTest, CountTrailingZeros) +{ + ASSERT_EQ(ArchCountTrailingZeros(1), 0); + ASSERT_EQ(ArchCountTrailingZeros(2), 1); + ASSERT_EQ(ArchCountTrailingZeros(3), 0); + ASSERT_EQ(ArchCountTrailingZeros(4), 2); + ASSERT_EQ(ArchCountTrailingZeros(5), 0); + ASSERT_EQ(ArchCountTrailingZeros(6), 1); + ASSERT_EQ(ArchCountTrailingZeros(7), 0); + ASSERT_EQ(ArchCountTrailingZeros(8), 3); + + ASSERT_EQ(ArchCountTrailingZeros(65535), 0); + ASSERT_EQ(ArchCountTrailingZeros(65536), 16); + + ASSERT_EQ(ArchCountTrailingZeros(~((1ull << 32ull) - 1ull)), 32); + ASSERT_EQ(ArchCountTrailingZeros(1ull << 63ull), 63); +} diff --git a/test/testStackTrace.cpp b/test/unit/testStackTrace.cpp similarity index 69% rename from test/testStackTrace.cpp rename to test/unit/testStackTrace.cpp index 860ffad..deb90a0 100644 --- a/test/testStackTrace.cpp +++ b/test/unit/testStackTrace.cpp @@ -5,32 +5,24 @@ // // Modified by Jeremy Retailleau. -#include -#include -#include #include -#include "./testArchUtil.h" +#include +#include +#include +#include #include -#include using namespace pxr; -int main(int argc, char** argv) +TEST(StackTraceTest, TestCrash) { - // Verify the "is crashing" flag is initialized properly, and doesn't - // get modified until we call the fatal process state handler below. - ARCH_AXIOM(!ArchIsAppCrashing()); - - ArchSetProgramNameForErrors( "testArch ArchError" ); - ArchTestCrashArgParse(argc, argv); - - ARCH_AXIOM(!ArchIsAppCrashing()); + ASSERT_FALSE(ArchIsAppCrashing()); std::string log = ArchMakeTmpFileName("statusLogTester"); FILE *logFile; - ARCH_AXIOM((logFile = ArchOpenFile(log.c_str(), "w")) != NULL); + ASSERT_NE((logFile = ArchOpenFile(log.c_str(), "w")), nullptr); fputs("fake log\n", logFile); fputs("let's throw in a weird printf %1024$s specifier\n", logFile); fclose(logFile); @@ -38,14 +30,14 @@ int main(int argc, char** argv) ArchLogStackTrace("Crashing", true, log.c_str()); ArchUnlinkFile(log.c_str()); - ARCH_AXIOM(!ArchIsAppCrashing()); + ASSERT_FALSE(ArchIsAppCrashing()); ArchLogCurrentProcessState("Test Non-Fatal"); - ARCH_AXIOM(!ArchIsAppCrashing()); + ASSERT_FALSE(ArchIsAppCrashing()); ArchLogFatalProcessState("Test Fatal"); // Now we should be marked as crashing - ARCH_AXIOM(ArchIsAppCrashing()); + ASSERT_TRUE(ArchIsAppCrashing()); // test crashing with and without spawning ArchTestCrash(ArchTestCrashMode::ReadInvalidAddresses); @@ -61,8 +53,14 @@ int main(int argc, char** argv) // Release builds on windows can't get symbolic names. found |= !stackTrace.empty(); #endif - ARCH_AXIOM(found); - - return 0; + ASSERT_TRUE(found); } +int main(int argc, char** argv) +{ + ArchSetProgramNameForErrors("testArch ArchError"); + ArchTestCrashArgParse(argc, argv); + + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/test/testSymbols.cpp b/test/unit/testSymbols.cpp similarity index 67% rename from test/testSymbols.cpp rename to test/unit/testSymbols.cpp index 25ee4fc..2974fdf 100644 --- a/test/testSymbols.cpp +++ b/test/unit/testSymbols.cpp @@ -6,7 +6,7 @@ // Modified by Jeremy Retailleau. #include -#include +#include #include @@ -41,31 +41,29 @@ static std::string GetBasename(const std::string& path) return path; } -int main() +TEST(SymbolsTest, GetAddressInfo) { std::string path; // Invalid pointer. - ARCH_AXIOM(!_GetLibraryPath(0, &path)); + ASSERT_FALSE(_GetLibraryPath(0, &path)); // Pointer to a local non-function. - ARCH_AXIOM(!_GetLibraryPath(&path, &path)); + ASSERT_FALSE(_GetLibraryPath(&path, &path)); // Pointer into the DATA section. - ARCH_AXIOM(_GetLibraryPath(&data, &path)); - ARCH_AXIOM(GetBasename(path) == "testArchSymbols"); + ASSERT_TRUE(_GetLibraryPath(&data, &path)); + ASSERT_EQ(GetBasename(path), "testArchSymbols"); // Pointer into the BSS section. - ARCH_AXIOM(_GetLibraryPath(&bss, &path)); - ARCH_AXIOM(GetBasename(path) == "testArchSymbols"); + ASSERT_TRUE(_GetLibraryPath(&bss, &path)); + ASSERT_EQ(GetBasename(path), "testArchSymbols"); // Find this library. - ARCH_AXIOM(_GetLibraryPath((void*)&Code, &path)); - ARCH_AXIOM(GetBasename(path) == "testArchSymbols"); + ASSERT_TRUE(_GetLibraryPath((void*)&Code, &path)); + ASSERT_EQ(GetBasename(path), "testArchSymbols"); // Find another library. - ARCH_AXIOM(_GetLibraryPath((void*)&exit, &path)); - ARCH_AXIOM(GetBasename(path) != "testArchSymbols"); - - return 0; + ASSERT_TRUE(_GetLibraryPath((void*)&exit, &path)); + ASSERT_NE(GetBasename(path), "testArchSymbols"); } diff --git a/test/testSystemInfo.cpp b/test/unit/testSystemInfo.cpp similarity index 53% rename from test/testSystemInfo.cpp rename to test/unit/testSystemInfo.cpp index 31992a4..446095f 100644 --- a/test/testSystemInfo.cpp +++ b/test/unit/testSystemInfo.cpp @@ -6,16 +6,13 @@ // Modified by Jeremy Retailleau. #include -#include +#include using namespace pxr; using std::string; -//most of these tests are just for code coverage -int main(int /*argc*/, char const** /*argv*/) +TEST(SystemInfoTest, GetExecutablePath) { - ARCH_AXIOM(ArchGetExecutablePath().find("testArch", 0) != string::npos); - return 0; + ASSERT_NE(ArchGetExecutablePath().find("testArch", 0), string::npos); } - diff --git a/test/testThreads.cpp b/test/unit/testThreads.cpp similarity index 70% rename from test/testThreads.cpp rename to test/unit/testThreads.cpp index d489954..b388544 100644 --- a/test/testThreads.cpp +++ b/test/unit/testThreads.cpp @@ -6,14 +6,10 @@ // Modified by Jeremy Retailleau. #include -#include +#include using namespace pxr; -int main() -{ - ARCH_AXIOM(ArchIsMainThread()); - - return 0; +TEST(ThreadTest, IsMainThread) { + ASSERT_TRUE(ArchIsMainThread()); } - diff --git a/test/testTiming.cpp b/test/unit/testTiming.cpp similarity index 70% rename from test/testTiming.cpp rename to test/unit/testTiming.cpp index ac0d2b7..92f58e8 100644 --- a/test/testTiming.cpp +++ b/test/unit/testTiming.cpp @@ -6,28 +6,32 @@ // Modified by Jeremy Retailleau. #include -#include +#include + #include #include using namespace pxr; -int main() +TEST(TimingTest, Conversion) { - ARCH_AXIOM(ArchGetNanosecondsPerTick() > 0.0); + ASSERT_TRUE(ArchGetNanosecondsPerTick() > 0.0); // If you're not even doing 1 tick a second, it's probably a bogus value - ARCH_AXIOM(ArchGetNanosecondsPerTick() < 1e9); + ASSERT_TRUE(ArchGetNanosecondsPerTick() < 1e9); // Verify conversions for many tick counts. for (size_t ticks = 0ul; ticks != 1ul << 24u; ++ticks) { - ARCH_AXIOM( (uint64_t) ArchTicksToNanoseconds(ticks) == + ASSERT_EQ( (uint64_t) ArchTicksToNanoseconds(ticks), uint64_t(static_cast(ticks)*ArchGetNanosecondsPerTick() + .5)); double nanos = double(ArchTicksToNanoseconds(ticks)) / 1e9; double secs = ArchTicksToSeconds(ticks); double epsilon = 0.0001; - ARCH_AXIOM( (nanos - epsilon <= secs) && (nanos + epsilon >= secs) ); + ASSERT_TRUE( (nanos - epsilon <= secs) && (nanos + epsilon >= secs) ); } +} +TEST(TimingTest, Delta) +{ // Compute some time delta. const auto t1 = ArchGetTickTime(); std::this_thread::sleep_for(std::chrono::milliseconds(1500)); @@ -36,8 +40,6 @@ int main() // Verify the delta is reasonable. We allow a lot of leeway on the top // end in case of heavy machine load. - ARCH_AXIOM(ArchTicksToSeconds(delta) > 1.4); - ARCH_AXIOM(ArchTicksToSeconds(delta) < 5.0); - - return 0; + ASSERT_TRUE(ArchTicksToSeconds(delta) > 1.4); + ASSERT_TRUE(ArchTicksToSeconds(delta) < 5.0); } diff --git a/test/testVsnprintf.cpp b/test/unit/testVsnprintf.cpp similarity index 61% rename from test/testVsnprintf.cpp rename to test/unit/testVsnprintf.cpp index 913b63c..d86c470 100644 --- a/test/testVsnprintf.cpp +++ b/test/unit/testVsnprintf.cpp @@ -6,17 +6,15 @@ // Modified by Jeremy Retailleau. #include -#include +#include #include -#include -#include +#include using namespace pxr; -using std::string; - -static int ArchSnprintf(char *str, size_t size, const char* fmt, ...) { +static int Snprintf(char* str, size_t size, const char* fmt, ...) +{ int n; va_list ap; va_start(ap, fmt); @@ -27,12 +25,12 @@ static int ArchSnprintf(char *str, size_t size, const char* fmt, ...) { return n; } -int main() +TEST(VsnprintfTest, Print) { char str[1] = ""; - // ArchSnprintf should report 3 characters not written - ARCH_AXIOM(ArchSnprintf(str, strlen(str), " ") == 3); + // Snprintf should report 3 characters not written + ASSERT_EQ(Snprintf(str, strlen(str), " "), 3); // ensure that a string longer than 4096 works // create a long format string @@ -42,7 +40,5 @@ int main() } long_fmt[8191] = '\0'; - ARCH_AXIOM(ArchStringPrintf("%s", long_fmt).size() == 8191); - - return 0; + ASSERT_EQ(ArchStringPrintf("%s", long_fmt).size(), 8191); } diff --git a/test/utility/CMakeLists.txt b/test/utility/CMakeLists.txt new file mode 100644 index 0000000..a902253 --- /dev/null +++ b/test/utility/CMakeLists.txt @@ -0,0 +1,15 @@ +add_library(archTest + archTest/util.cpp +) + +target_include_directories(archTest + PUBLIC + $ +) + +target_link_libraries(archTest + PUBLIC + arch +) + +add_subdirectory(plugins) diff --git a/test/testArchAbi.h b/test/utility/archTest/abi.h similarity index 84% rename from test/testArchAbi.h rename to test/utility/archTest/abi.h index a3a5d53..d7e77e0 100644 --- a/test/testArchAbi.h +++ b/test/utility/archTest/abi.h @@ -5,8 +5,8 @@ // // Modified by Jeremy Retailleau. -#ifndef PXR_ARCH_TEST_ARCH_ABI_H -#define PXR_ARCH_TEST_ARCH_ABI_H +#ifndef PXR_ARCH_TEST_ABI_H +#define PXR_ARCH_TEST_ABI_H #include @@ -29,4 +29,4 @@ struct ArchAbiDerived : public ArchAbiBase1, public ArchAbiBase2 { } // namespace pxr -#endif // PXR_ARCH_TEST_ARCH_ABI_H +#endif // PXR_ARCH_TEST_ABI_H diff --git a/test/testArchUtil.cpp b/test/utility/archTest/util.cpp similarity index 99% rename from test/testArchUtil.cpp rename to test/utility/archTest/util.cpp index 6fd9a95..20c72b4 100644 --- a/test/testArchUtil.cpp +++ b/test/utility/archTest/util.cpp @@ -7,7 +7,8 @@ #define _CRT_SECURE_NO_WARNINGS -#include "./testArchUtil.h" +#include "./util.h" + #include #include #include diff --git a/test/testArchUtil.h b/test/utility/archTest/util.h similarity index 85% rename from test/testArchUtil.h rename to test/utility/archTest/util.h index 69fde24..be72b16 100644 --- a/test/testArchUtil.h +++ b/test/utility/archTest/util.h @@ -5,8 +5,8 @@ // // Modified by Jeremy Retailleau. -#ifndef PXR_ARCH_TEST_ARCH_UTIL_H -#define PXR_ARCH_TEST_ARCH_UTIL_H +#ifndef PXR_ARCH_TEST_UTIL_H +#define PXR_ARCH_TEST_UTIL_H #include @@ -28,4 +28,4 @@ ARCH_API void ArchTestCrashArgParse(int argc, char** argv); } // namespace pxr -#endif // PXR_ARCH_TEST_ARCH_UTIL_H +#endif // PXR_ARCH_TEST_UTIL_H diff --git a/test/utility/plugins/CMakeLists.txt b/test/utility/plugins/CMakeLists.txt new file mode 100644 index 0000000..ff32cdb --- /dev/null +++ b/test/utility/plugins/CMakeLists.txt @@ -0,0 +1,7 @@ +add_library(archTestPlugin SHARED main.cpp) + +target_link_libraries(archTestPlugin + PUBLIC + arch + archTest +) diff --git a/test/testArchAbiPlugin.cpp b/test/utility/plugins/main.cpp similarity index 69% rename from test/testArchAbiPlugin.cpp rename to test/utility/plugins/main.cpp index 8916675..686a859 100644 --- a/test/testArchAbiPlugin.cpp +++ b/test/utility/plugins/main.cpp @@ -6,13 +6,16 @@ // Modified by Jeremy Retailleau. #include -#include "./testArchAbi.h" +#include using namespace pxr; extern "C" { -ARCH_EXPORT ArchAbiBase2* newDerived() { return new ArchAbiDerived; } +ARCH_EXPORT ArchAbiBase2* newDerived() +{ + return new ArchAbiDerived; +} }