diff options
author | Brad King <brad.king@kitware.com> | 2019-10-03 18:07:37 (GMT) |
---|---|---|
committer | Kitware Robot <kwrobot@kitware.com> | 2019-10-03 18:07:52 (GMT) |
commit | 3247506662684003e19d9552ab5ce70643808f4d (patch) | |
tree | 95f9c2d0892c36249448a37d0e77ff5c4821101b /Tests | |
parent | d918b4a545fefd1593753189d83ec8590f430579 (diff) | |
parent | e9500271a3acdc0d1ee448cae5912f768491f429 (diff) | |
download | CMake-3247506662684003e19d9552ab5ce70643808f4d.zip CMake-3247506662684003e19d9552ab5ce70643808f4d.tar.gz CMake-3247506662684003e19d9552ab5ce70643808f4d.tar.bz2 |
Merge topic 'ctest-hardware-allocation'
e9500271a3 Help: Add documentation for CTest hardware allocation
d1f100a415 CTest: Add Json output for PROCESSES property
b741ee820d Tests: Add test for CTest hardware allocation feature
3c8a5aad46 Tests: Write tests for cthwalloc helper tool
2d74e54661 Tests: Write cthwalloc helper tool
e34de0691b CTest: Allocate hardware to tests
aee0964851 CTest: Add bin-packing algorithm
c494b2973a CTest: Add cmCTestHardwareAllocator class
...
Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !3858
Diffstat (limited to 'Tests')
92 files changed, 2050 insertions, 5 deletions
diff --git a/Tests/CMakeLib/CMakeLists.txt b/Tests/CMakeLib/CMakeLists.txt index 204810e..bc2079f 100644 --- a/Tests/CMakeLib/CMakeLists.txt +++ b/Tests/CMakeLib/CMakeLists.txt @@ -2,10 +2,15 @@ include_directories( ${CMAKE_CURRENT_BINARY_DIR} ${CMake_BINARY_DIR}/Source ${CMake_SOURCE_DIR}/Source + ${CMake_SOURCE_DIR}/Source/CTest ) set(CMakeLib_TESTS testArgumentParser.cxx + testCTestBinPacker.cxx + testCTestProcesses.cxx + testCTestHardwareAllocator.cxx + testCTestHardwareSpec.cxx testGeneratedFileStream.cxx testRST.cxx testRange.cxx @@ -27,6 +32,7 @@ add_executable(testUVProcessChainHelper testUVProcessChainHelper.cxx) set(testRST_ARGS ${CMAKE_CURRENT_SOURCE_DIR}) set(testUVProcessChain_ARGS $<TARGET_FILE:testUVProcessChainHelper>) set(testUVStreambuf_ARGS $<TARGET_FILE:cmake>) +set(testCTestHardwareSpec_ARGS ${CMAKE_CURRENT_SOURCE_DIR}) if(WIN32) list(APPEND CMakeLib_TESTS @@ -41,7 +47,7 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/testXMLParser.h.in create_test_sourcelist(CMakeLib_TEST_SRCS CMakeLibTests.cxx ${CMakeLib_TESTS}) add_executable(CMakeLibTests ${CMakeLib_TEST_SRCS}) -target_link_libraries(CMakeLibTests CMakeLib) +target_link_libraries(CMakeLibTests CMakeLib CTestLib) set_property(TARGET CMakeLibTests PROPERTY C_CLANG_TIDY "") set_property(TARGET CMakeLibTests PROPERTY CXX_CLANG_TIDY "") diff --git a/Tests/CMakeLib/testCTestBinPacker.cxx b/Tests/CMakeLib/testCTestBinPacker.cxx new file mode 100644 index 0000000..62ea55b --- /dev/null +++ b/Tests/CMakeLib/testCTestBinPacker.cxx @@ -0,0 +1,300 @@ +#include <cstddef> +#include <iostream> +#include <map> +#include <string> +#include <vector> + +#include "cmCTestBinPacker.h" +#include "cmCTestHardwareAllocator.h" + +struct ExpectedPackResult +{ + std::vector<int> SlotsNeeded; + std::map<std::string, cmCTestHardwareAllocator::Resource> Hardware; + bool ExpectedReturnValue; + std::vector<cmCTestBinPackerAllocation> ExpectedRoundRobinAllocations; + std::vector<cmCTestBinPackerAllocation> ExpectedBlockAllocations; +}; + +static const std::vector<ExpectedPackResult> expectedResults +{ + /* clang-format off */ + { + { 2, 2, 2, 2 }, + { { "0", { 4, 0 } }, { "1", { 4, 0 } }, { "2", { 4, 0 } }, + { "3", { 4, 0 } } }, + true, + { + { 0, 2, "0" }, + { 1, 2, "1" }, + { 2, 2, "2" }, + { 3, 2, "3" }, + }, + { + { 0, 2, "0" }, + { 1, 2, "0" }, + { 2, 2, "1" }, + { 3, 2, "1" }, + }, + }, + { + { 2, 3, 2 }, + { { "0", { 5, 0 } }, { "1", { 2, 0 } } }, + true, + { + { 0, 2, "0" }, + { 1, 3, "0" }, + { 2, 2, "1" }, + }, + { + { 0, 2, "0" }, + { 1, 3, "0" }, + { 2, 2, "1" }, + }, + }, + { + { 1, 2, 3 }, + { { "0", { 1, 0 } }, { "1", { 2, 0 } }, { "2", { 2, 0 } } }, + false, + { }, + { }, + }, + { + { 48, 21, 31, 10, 40 }, + { { "0", { 81, 0 } }, { "1", { 68, 0 } }, { "2", { 20, 0 } }, + { "3", { 13, 0 } } }, + true, + { + { 0, 48, "0" }, + { 1, 21, "1" }, + { 2, 31, "0" }, + { 3, 10, "2" }, + { 4, 40, "1" }, + }, + { + { 0, 48, "0" }, + { 1, 21, "1" }, + { 2, 31, "0" }, + { 3, 10, "2" }, + { 4, 40, "1" }, + }, + }, + { + { 30, 31, 39, 67 }, + { { "0", { 16, 0 } }, { "1", { 81, 0 } }, { "2", { 97, 0 } } }, + true, + { + { 0, 30, "2" }, + { 1, 31, "1" }, + { 2, 39, "1" }, + { 3, 67, "2" }, + }, + { + { 0, 30, "2" }, + { 1, 31, "1" }, + { 2, 39, "1" }, + { 3, 67, "2" }, + }, + }, + { + { 63, 47, 1, 9 }, + { { "0", { 18, 0 } }, { "1", { 29, 0 } }, { "2", { 9, 0 } }, + { "3", { 52, 0 } } }, + false, + { }, + { }, + }, + { + { 22, 29, 46, 85 }, + { { "0", { 65, 0 } }, { "1", { 85, 0 } }, { "2", { 65, 0 } }, + { "3", { 78, 0 } } }, + true, + { + { 0, 22, "2" }, + { 1, 29, "0" }, + { 2, 46, "3" }, + { 3, 85, "1" }, + }, + { + { 0, 22, "0" }, + { 1, 29, "3" }, + { 2, 46, "3" }, + { 3, 85, "1" }, + }, + }, + { + { 66, 11, 34, 21 }, + { { "0", { 24, 0 } }, { "1", { 57, 0 } }, { "2", { 61, 0 } }, + { "3", { 51, 0 } } }, + false, + { }, + { }, + }, + { + { 72, 65, 67, 45 }, + { { "0", { 29, 0 } }, { "1", { 77, 0 } }, { "2", { 98, 0 } }, + { "3", { 58, 0 } } }, + false, + { }, + { }, + }, + /* + * The following is a contrived attack on the bin-packing algorithm that + * causes it to execute with n! complexity, where n is the number of + * resources. This case is very unrepresentative of real-world usage, and + * has been documented but disabled. The bin-packing problem is NP-hard, and + * we may not be able to fix this case at all. + */ +#if 0 + { + { 1000, 999, 998, 997, 996, 995, 994, 993, 992, 991, 19 }, + { { "0", { 1000, 0 } }, { "1", { 1001, 0 } }, { "2", { 1002, 0 } }, + { "3", { 1003, 0 } }, { "4", { 1004, 0 } }, { "5", { 1005, 0 } }, + { "6", { 1006, 0 } }, { "7", { 1007, 0 } }, { "8", { 1008, 0 } }, + { "9", { 1009, 0 } } }, + false, + { }, + { }, + }, +#endif + /* + * These cases are more representative of real-world usage (the resource + * sizes are all the same.) + */ + { + { 1000, 999, 998, 997, 996, 995, 994, 993, 992, 991, 10 }, + { { "0", { 1000, 0 } }, { "1", { 1000, 0 } }, { "2", { 1000, 0 } }, + { "3", { 1000, 0 } }, { "4", { 1000, 0 } }, { "5", { 1000, 0 } }, + { "6", { 1000, 0 } }, { "7", { 1000, 0 } }, { "8", { 1000, 0 } }, + { "9", { 1000, 0 } } }, + false, + { }, + { }, + }, + { + { 1000, 999, 998, 997, 996, 995, 994, 993, 992, 991, 9 }, + { { "0", { 1000, 0 } }, { "1", { 1000, 0 } }, { "2", { 1000, 0 } }, + { "3", { 1000, 0 } }, { "4", { 1000, 0 } }, { "5", { 1000, 0 } }, + { "6", { 1000, 0 } }, { "7", { 1000, 0 } }, { "8", { 1000, 0 } }, + { "9", { 1000, 0 } } }, + true, + { + { 0, 1000, "0" }, + { 1, 999, "1" }, + { 2, 998, "2" }, + { 3, 997, "3" }, + { 4, 996, "4" }, + { 5, 995, "5" }, + { 6, 994, "6" }, + { 7, 993, "7" }, + { 8, 992, "8" }, + { 9, 991, "9" }, + { 10, 9, "9" }, + }, + { + { 0, 1000, "0" }, + { 1, 999, "1" }, + { 2, 998, "2" }, + { 3, 997, "3" }, + { 4, 996, "4" }, + { 5, 995, "5" }, + { 6, 994, "6" }, + { 7, 993, "7" }, + { 8, 992, "8" }, + { 9, 991, "9" }, + { 10, 9, "9" }, + }, + }, + /* clang-format on */ +}; + +struct AllocationComparison +{ + cmCTestBinPackerAllocation First; + cmCTestBinPackerAllocation Second; + bool Equal; +}; + +static const std::vector<AllocationComparison> comparisons{ + /* clang-format off */ + { { 0, 1, "0" }, { 0, 1, "0" }, true }, + { { 0, 1, "0" }, { 1, 1, "0" }, false }, + { { 0, 1, "0" }, { 0, 2, "0" }, false }, + { { 0, 1, "0" }, { 0, 1, "1" }, false }, + /* clang-format on */ +}; + +bool TestExpectedPackResult(const ExpectedPackResult& expected) +{ + std::vector<cmCTestBinPackerAllocation> roundRobinAllocations; + roundRobinAllocations.reserve(expected.SlotsNeeded.size()); + std::size_t index = 0; + for (auto const& n : expected.SlotsNeeded) { + roundRobinAllocations.push_back({ index++, n, "" }); + } + + bool roundRobinResult = cmAllocateCTestHardwareRoundRobin( + expected.Hardware, roundRobinAllocations); + if (roundRobinResult != expected.ExpectedReturnValue) { + std::cout + << "cmAllocateCTestHardwareRoundRobin did not return expected value" + << std::endl; + return false; + } + + if (roundRobinResult && + roundRobinAllocations != expected.ExpectedRoundRobinAllocations) { + std::cout << "cmAllocateCTestHardwareRoundRobin did not return expected " + "allocations" + << std::endl; + return false; + } + + std::vector<cmCTestBinPackerAllocation> blockAllocations; + blockAllocations.reserve(expected.SlotsNeeded.size()); + index = 0; + for (auto const& n : expected.SlotsNeeded) { + blockAllocations.push_back({ index++, n, "" }); + } + + bool blockResult = + cmAllocateCTestHardwareBlock(expected.Hardware, blockAllocations); + if (blockResult != expected.ExpectedReturnValue) { + std::cout << "cmAllocateCTestHardwareBlock did not return expected value" + << std::endl; + return false; + } + + if (blockResult && blockAllocations != expected.ExpectedBlockAllocations) { + std::cout << "cmAllocateCTestHardwareBlock did not return expected" + " allocations" + << std::endl; + return false; + } + + return true; +} + +int testCTestBinPacker(int /*unused*/, char* /*unused*/ []) +{ + int retval = 0; + + for (auto const& comparison : comparisons) { + if ((comparison.First == comparison.Second) != comparison.Equal) { + std::cout << "Comparison did not match expected" << std::endl; + retval = 1; + } + if ((comparison.First != comparison.Second) == comparison.Equal) { + std::cout << "Comparison did not match expected" << std::endl; + retval = 1; + } + } + + for (auto const& expected : expectedResults) { + if (!TestExpectedPackResult(expected)) { + retval = 1; + } + } + + return retval; +} diff --git a/Tests/CMakeLib/testCTestHardwareAllocator.cxx b/Tests/CMakeLib/testCTestHardwareAllocator.cxx new file mode 100644 index 0000000..6f05d03 --- /dev/null +++ b/Tests/CMakeLib/testCTestHardwareAllocator.cxx @@ -0,0 +1,426 @@ +#include <iostream> +#include <map> +#include <string> +#include <vector> + +#include "cmCTestHardwareAllocator.h" +#include "cmCTestHardwareSpec.h" + +static const cmCTestHardwareSpec spec{ { { + /* clang-format off */ + { "gpus", { { "0", 4 }, { "1", 8 }, { "2", 0 }, { "3", 8 } } }, + /* clang-format on */ +} } }; + +bool testInitializeFromHardwareSpec() +{ + bool retval = true; + + cmCTestHardwareAllocator allocator; + allocator.InitializeFromHardwareSpec(spec); + + static const std::map< + std::string, std::map<std::string, cmCTestHardwareAllocator::Resource>> + expected{ + /* clang-format off */ + { "gpus", { + { "0", { 4, 0 } }, + { "1", { 8, 0 } }, + { "2", { 0, 0 } }, + { "3", { 8, 0 } }, + } }, + /* clang-format on */ + }; + if (allocator.GetResources() != expected) { + std::cout << "GetResources() did not return expected value\n"; + retval = false; + } + + return retval; +} + +bool testAllocateResource() +{ + bool retval = true; + + cmCTestHardwareAllocator allocator; + allocator.InitializeFromHardwareSpec(spec); + + static const std::map< + std::string, std::map<std::string, cmCTestHardwareAllocator::Resource>> + expected1{ + /* clang-format off */ + { "gpus", { + { "0", { 4, 2 } }, + { "1", { 8, 0 } }, + { "2", { 0, 0 } }, + { "3", { 8, 0 } }, + } }, + /* clang-format on */ + }; + if (!allocator.AllocateResource("gpus", "0", 2)) { + std::cout + << "AllocateResource(\"gpus\", \"0\", 2) returned false, should be " + "true\n"; + retval = false; + } + if (allocator.GetResources() != expected1) { + std::cout << "GetResources() did not return expected value\n"; + retval = false; + } + + static const std::map< + std::string, std::map<std::string, cmCTestHardwareAllocator::Resource>> + expected2{ + /* clang-format off */ + { "gpus", { + { "0", { 4, 4 } }, + { "1", { 8, 0 } }, + { "2", { 0, 0 } }, + { "3", { 8, 0 } }, + } }, + /* clang-format on */ + }; + if (!allocator.AllocateResource("gpus", "0", 2)) { + std::cout + << "AllocateResource(\"gpus\", \"0\", 2) returned false, should be " + "true\n"; + retval = false; + } + if (allocator.GetResources() != expected2) { + std::cout << "GetResources() did not return expected value\n"; + retval = false; + } + + static const std::map< + std::string, std::map<std::string, cmCTestHardwareAllocator::Resource>> + expected3{ + /* clang-format off */ + { "gpus", { + { "0", { 4, 4 } }, + { "1", { 8, 0 } }, + { "2", { 0, 0 } }, + { "3", { 8, 0 } }, + } }, + /* clang-format on */ + }; + if (allocator.AllocateResource("gpus", "0", 1)) { + std::cout + << "AllocateResource(\"gpus\", \"0\", 1) returned true, should be " + "false\n"; + retval = false; + } + if (allocator.GetResources() != expected3) { + std::cout << "GetResources() did not return expected value\n"; + retval = false; + } + + static const std::map< + std::string, std::map<std::string, cmCTestHardwareAllocator::Resource>> + expected4{ + /* clang-format off */ + { "gpus", { + { "0", { 4, 4 } }, + { "1", { 8, 7 } }, + { "2", { 0, 0 } }, + { "3", { 8, 0 } }, + } }, + /* clang-format on */ + }; + if (!allocator.AllocateResource("gpus", "1", 7)) { + std::cout + << "AllocateResource(\"gpus\", \"1\", 7) returned false, should be " + "true\n"; + retval = false; + } + if (allocator.AllocateResource("gpus", "1", 2)) { + std::cout + << "AllocateResource(\"gpus\", \"1\", 2) returned true, should be " + "false\n"; + retval = false; + } + if (allocator.GetResources() != expected4) { + std::cout << "GetResources() did not return expected value\n"; + retval = false; + } + + static const std::map< + std::string, std::map<std::string, cmCTestHardwareAllocator::Resource>> + expected5{ + /* clang-format off */ + { "gpus", { + { "0", { 4, 4 } }, + { "1", { 8, 7 } }, + { "2", { 0, 0 } }, + { "3", { 8, 0 } }, + } }, + /* clang-format on */ + }; + if (allocator.AllocateResource("gpus", "2", 1)) { + std::cout + << "AllocateResource(\"gpus\", \"2\", 1) returned true, should be " + "false\n"; + retval = false; + } + if (allocator.GetResources() != expected5) { + std::cout << "GetResources() did not return expected value\n"; + retval = false; + } + + static const std::map< + std::string, std::map<std::string, cmCTestHardwareAllocator::Resource>> + expected6{ + /* clang-format off */ + { "gpus", { + { "0", { 4, 4 } }, + { "1", { 8, 7 } }, + { "2", { 0, 0 } }, + { "3", { 8, 0 } }, + } }, + /* clang-format on */ + }; + if (allocator.AllocateResource("gpus", "4", 1)) { + std::cout + << "AllocateResource(\"gpus\", \"4\", 1) returned true, should be " + "false\n"; + retval = false; + } + if (allocator.GetResources() != expected6) { + std::cout << "GetResources() did not return expected value\n"; + retval = false; + } + + static const std::map< + std::string, std::map<std::string, cmCTestHardwareAllocator::Resource>> + expected7{ + /* clang-format off */ + { "gpus", { + { "0", { 4, 4 } }, + { "1", { 8, 7 } }, + { "2", { 0, 0 } }, + { "3", { 8, 0 } }, + } }, + /* clang-format on */ + }; + if (allocator.AllocateResource("threads", "0", 1)) { + std::cout + << "AllocateResource(\"threads\", \"0\", 1) returned true, should be" + " false\n"; + retval = false; + } + if (allocator.GetResources() != expected7) { + std::cout << "GetResources() did not return expected value\n"; + retval = false; + } + + return retval; +} + +bool testDeallocateResource() +{ + bool retval = true; + + cmCTestHardwareAllocator allocator; + allocator.InitializeFromHardwareSpec(spec); + + static const std::map< + std::string, std::map<std::string, cmCTestHardwareAllocator::Resource>> + expected1{ + /* clang-format off */ + { "gpus", { + { "0", { 4, 1 } }, + { "1", { 8, 0 } }, + { "2", { 0, 0 } }, + { "3", { 8, 0 } }, + } }, + /* clang-format on */ + }; + if (!allocator.AllocateResource("gpus", "0", 2)) { + std::cout + << "AllocateResource(\"gpus\", \"0\", 2) returned false, should be " + "true\n"; + retval = false; + } + if (!allocator.DeallocateResource("gpus", "0", 1)) { + std::cout + << "DeallocateResource(\"gpus\", \"0\", 1) returned false, should be" + " true\n"; + retval = false; + } + if (allocator.GetResources() != expected1) { + std::cout << "GetResources() did not return expected value\n"; + retval = false; + } + + static const std::map< + std::string, std::map<std::string, cmCTestHardwareAllocator::Resource>> + expected2{ + /* clang-format off */ + { "gpus", { + { "0", { 4, 1 } }, + { "1", { 8, 0 } }, + { "2", { 0, 0 } }, + { "3", { 8, 0 } }, + } }, + /* clang-format on */ + }; + if (allocator.DeallocateResource("gpus", "0", 2)) { + std::cout + << "DeallocateResource(\"gpus\", \"0\", 2) returned true, should be" + " false\n"; + retval = false; + } + if (allocator.GetResources() != expected2) { + std::cout << "GetResources() did not return expected value\n"; + retval = false; + } + + static const std::map< + std::string, std::map<std::string, cmCTestHardwareAllocator::Resource>> + expected3{ + /* clang-format off */ + { "gpus", { + { "0", { 4, 0 } }, + { "1", { 8, 0 } }, + { "2", { 0, 0 } }, + { "3", { 8, 0 } }, + } }, + /* clang-format on */ + }; + if (!allocator.DeallocateResource("gpus", "0", 1)) { + std::cout + << "DeallocateResource(\"gpus\", \"0\", 1) returned false, should be" + " true\n"; + retval = false; + } + if (allocator.GetResources() != expected3) { + std::cout << "GetResources() did not return expected value\n"; + retval = false; + } + + static const std::map< + std::string, std::map<std::string, cmCTestHardwareAllocator::Resource>> + expected4{ + /* clang-format off */ + { "gpus", { + { "0", { 4, 0 } }, + { "1", { 8, 0 } }, + { "2", { 0, 0 } }, + { "3", { 8, 0 } }, + } }, + /* clang-format on */ + }; + if (allocator.DeallocateResource("gpus", "0", 1)) { + std::cout + << "DeallocateResource(\"gpus\", \"0\", 1) returned true, should be" + " false\n"; + retval = false; + } + if (allocator.GetResources() != expected4) { + std::cout << "GetResources() did not return expected value\n"; + retval = false; + } + + static const std::map< + std::string, std::map<std::string, cmCTestHardwareAllocator::Resource>> + expected5{ + /* clang-format off */ + { "gpus", { + { "0", { 4, 0 } }, + { "1", { 8, 0 } }, + { "2", { 0, 0 } }, + { "3", { 8, 0 } }, + } }, + /* clang-format on */ + }; + if (allocator.DeallocateResource("gpus", "4", 1)) { + std::cout + << "DeallocateResource(\"gpus\", \"4\", 1) returned true, should be" + " false\n"; + retval = false; + } + if (allocator.GetResources() != expected5) { + std::cout << "GetResources() did not return expected value\n"; + retval = false; + } + + static const std::map< + std::string, std::map<std::string, cmCTestHardwareAllocator::Resource>> + expected6{ + /* clang-format off */ + { "gpus", { + { "0", { 4, 0 } }, + { "1", { 8, 0 } }, + { "2", { 0, 0 } }, + { "3", { 8, 0 } }, + } }, + /* clang-format on */ + }; + if (allocator.DeallocateResource("threads", "0", 1)) { + std::cout + << "DeallocateResource(\"threads\", \"0\", 1) returned true, should be" + " false\n"; + retval = false; + } + if (allocator.GetResources() != expected6) { + std::cout << "GetResources() did not return expected value\n"; + retval = false; + } + + return retval; +} + +bool testResourceFree() +{ + bool retval = true; + + const cmCTestHardwareAllocator::Resource r1{ 5, 0 }; + if (r1.Free() != 5) { + std::cout << "cmCTestHardwareAllocator::Resource::Free() did not return " + "expected value for { 5, 0 }\n"; + retval = false; + } + + const cmCTestHardwareAllocator::Resource r2{ 3, 2 }; + if (r2.Free() != 1) { + std::cout << "cmCTestHardwareAllocator::Resource::Free() did not return " + "expected value for { 3, 2 }\n"; + retval = false; + } + + const cmCTestHardwareAllocator::Resource r3{ 4, 4 }; + if (r3.Free() != 0) { + std::cout << "cmCTestHardwareAllocator::Resource::Free() did not return " + "expected value for { 4, 4 }\n"; + retval = false; + } + + return retval; +} + +int testCTestHardwareAllocator(int, char** const) +{ + int retval = 0; + + if (!testInitializeFromHardwareSpec()) { + std::cout << "in testInitializeFromHardwareSpec()\n"; + retval = -1; + } + + if (!testAllocateResource()) { + std::cout << "in testAllocateResource()\n"; + retval = -1; + } + + if (!testDeallocateResource()) { + std::cout << "in testDeallocateResource()\n"; + retval = -1; + } + + if (!testResourceFree()) { + std::cout << "in testResourceFree()\n"; + retval = -1; + } + + return retval; +} diff --git a/Tests/CMakeLib/testCTestHardwareSpec.cxx b/Tests/CMakeLib/testCTestHardwareSpec.cxx new file mode 100644 index 0000000..3e3eccc --- /dev/null +++ b/Tests/CMakeLib/testCTestHardwareSpec.cxx @@ -0,0 +1,84 @@ +#include <iostream> +#include <string> +#include <vector> + +#include "cmCTestHardwareSpec.h" + +struct ExpectedSpec +{ + std::string Path; + bool ParseResult; + cmCTestHardwareSpec Expected; +}; + +static const std::vector<ExpectedSpec> expectedHardwareSpecs = { + /* clang-format off */ + {"spec1.json", true, {{{ + {"gpus", { + {"2", 4}, + {"e", 1}, + }}, + {"threads", { + }}, + }}}}, + {"spec2.json", true, {{{ + }}}}, + {"spec3.json", false, {{{}}}}, + {"spec4.json", false, {{{}}}}, + {"spec5.json", false, {{{}}}}, + {"spec6.json", false, {{{}}}}, + {"spec7.json", false, {{{}}}}, + {"spec8.json", false, {{{}}}}, + {"spec9.json", false, {{{}}}}, + {"spec10.json", false, {{{}}}}, + {"spec11.json", false, {{{}}}}, + {"spec12.json", false, {{{}}}}, + {"spec13.json", false, {{{}}}}, + {"spec14.json", true, {{{}}}}, + {"spec15.json", true, {{{}}}}, + {"spec16.json", true, {{{}}}}, + {"spec17.json", false, {{{}}}}, + {"spec18.json", false, {{{}}}}, + {"noexist.json", false, {{{}}}}, + /* clang-format on */ +}; + +static bool testSpec(const std::string& path, bool expectedResult, + const cmCTestHardwareSpec& expected) +{ + cmCTestHardwareSpec actual; + bool result = actual.ReadFromJSONFile(path); + if (result != expectedResult) { + std::cout << "ReadFromJSONFile(\"" << path << "\") returned " << result + << ", should be " << expectedResult << std::endl; + return false; + } + + if (result && actual != expected) { + std::cout << "ReadFromJSONFile(\"" << path + << "\") did not give expected spec" << std::endl; + return false; + } + + return true; +} + +int testCTestHardwareSpec(int argc, char** const argv) +{ + if (argc < 2) { + std::cout << "Invalid arguments.\n"; + return -1; + } + + int retval = 0; + for (auto const& spec : expectedHardwareSpecs) { + std::string path = argv[1]; + path += "/testCTestHardwareSpec_data/"; + path += spec.Path; + if (!testSpec(path, spec.ParseResult, spec.Expected)) { + retval = -1; + } + } + + return retval; +} diff --git a/Tests/CMakeLib/testCTestHardwareSpec_data/spec1.json b/Tests/CMakeLib/testCTestHardwareSpec_data/spec1.json new file mode 100644 index 0000000..ee3d0ce --- /dev/null +++ b/Tests/CMakeLib/testCTestHardwareSpec_data/spec1.json @@ -0,0 +1,23 @@ +{ + "local": [ + { + "gpus": [ + { + "id": "2", + "slots": 4 + }, + { + "id": "e" + } + ], + ".reserved": [ + { + "id": "a", + "slots": 3 + } + ], + "threads": [ + ] + } + ] +} diff --git a/Tests/CMakeLib/testCTestHardwareSpec_data/spec10.json b/Tests/CMakeLib/testCTestHardwareSpec_data/spec10.json new file mode 100644 index 0000000..22105d7 --- /dev/null +++ b/Tests/CMakeLib/testCTestHardwareSpec_data/spec10.json @@ -0,0 +1,11 @@ +{ + "local": [ + { + "gpus": [ + { + "id": 4 + } + ] + } + ] +} diff --git a/Tests/CMakeLib/testCTestHardwareSpec_data/spec11.json b/Tests/CMakeLib/testCTestHardwareSpec_data/spec11.json new file mode 100644 index 0000000..1e37ef5 --- /dev/null +++ b/Tests/CMakeLib/testCTestHardwareSpec_data/spec11.json @@ -0,0 +1,12 @@ +{ + "local": [ + { + "gpus": [ + { + "id": "4", + "slots": "giraffe" + } + ] + } + ] +} diff --git a/Tests/CMakeLib/testCTestHardwareSpec_data/spec12.json b/Tests/CMakeLib/testCTestHardwareSpec_data/spec12.json new file mode 100644 index 0000000..fe51488 --- /dev/null +++ b/Tests/CMakeLib/testCTestHardwareSpec_data/spec12.json @@ -0,0 +1 @@ +[] diff --git a/Tests/CMakeLib/testCTestHardwareSpec_data/spec13.json b/Tests/CMakeLib/testCTestHardwareSpec_data/spec13.json new file mode 100644 index 0000000..6b7a9f4 --- /dev/null +++ b/Tests/CMakeLib/testCTestHardwareSpec_data/spec13.json @@ -0,0 +1 @@ +not json diff --git a/Tests/CMakeLib/testCTestHardwareSpec_data/spec14.json b/Tests/CMakeLib/testCTestHardwareSpec_data/spec14.json new file mode 100644 index 0000000..ce708c7 --- /dev/null +++ b/Tests/CMakeLib/testCTestHardwareSpec_data/spec14.json @@ -0,0 +1,8 @@ +{ + "local": [ + { + "0": [ + ] + } + ] +} diff --git a/Tests/CMakeLib/testCTestHardwareSpec_data/spec15.json b/Tests/CMakeLib/testCTestHardwareSpec_data/spec15.json new file mode 100644 index 0000000..78b6990 --- /dev/null +++ b/Tests/CMakeLib/testCTestHardwareSpec_data/spec15.json @@ -0,0 +1,8 @@ +{ + "local": [ + { + "-": [ + ] + } + ] +} diff --git a/Tests/CMakeLib/testCTestHardwareSpec_data/spec16.json b/Tests/CMakeLib/testCTestHardwareSpec_data/spec16.json new file mode 100644 index 0000000..95c7d26 --- /dev/null +++ b/Tests/CMakeLib/testCTestHardwareSpec_data/spec16.json @@ -0,0 +1,8 @@ +{ + "local": [ + { + "A": [ + ] + } + ] +} diff --git a/Tests/CMakeLib/testCTestHardwareSpec_data/spec17.json b/Tests/CMakeLib/testCTestHardwareSpec_data/spec17.json new file mode 100644 index 0000000..1b6ab4b --- /dev/null +++ b/Tests/CMakeLib/testCTestHardwareSpec_data/spec17.json @@ -0,0 +1,11 @@ +{ + "local": [ + { + "gpus": [ + { + "id": "A" + } + ] + } + ] +} diff --git a/Tests/CMakeLib/testCTestHardwareSpec_data/spec18.json b/Tests/CMakeLib/testCTestHardwareSpec_data/spec18.json new file mode 100644 index 0000000..1a17df7 --- /dev/null +++ b/Tests/CMakeLib/testCTestHardwareSpec_data/spec18.json @@ -0,0 +1,11 @@ +{ + "local": [ + { + "gpus": [ + { + "id": "-" + } + ] + } + ] +} diff --git a/Tests/CMakeLib/testCTestHardwareSpec_data/spec2.json b/Tests/CMakeLib/testCTestHardwareSpec_data/spec2.json new file mode 100644 index 0000000..6175b1a --- /dev/null +++ b/Tests/CMakeLib/testCTestHardwareSpec_data/spec2.json @@ -0,0 +1,4 @@ +{ + "local": [ + ] +} diff --git a/Tests/CMakeLib/testCTestHardwareSpec_data/spec3.json b/Tests/CMakeLib/testCTestHardwareSpec_data/spec3.json new file mode 100644 index 0000000..82453ec --- /dev/null +++ b/Tests/CMakeLib/testCTestHardwareSpec_data/spec3.json @@ -0,0 +1,8 @@ +{ + "local": [ + { + }, + { + } + ] +} diff --git a/Tests/CMakeLib/testCTestHardwareSpec_data/spec4.json b/Tests/CMakeLib/testCTestHardwareSpec_data/spec4.json new file mode 100644 index 0000000..05e73d7 --- /dev/null +++ b/Tests/CMakeLib/testCTestHardwareSpec_data/spec4.json @@ -0,0 +1,4 @@ +{ + "local": { + } +} diff --git a/Tests/CMakeLib/testCTestHardwareSpec_data/spec5.json b/Tests/CMakeLib/testCTestHardwareSpec_data/spec5.json new file mode 100644 index 0000000..2c63c08 --- /dev/null +++ b/Tests/CMakeLib/testCTestHardwareSpec_data/spec5.json @@ -0,0 +1,2 @@ +{ +} diff --git a/Tests/CMakeLib/testCTestHardwareSpec_data/spec6.json b/Tests/CMakeLib/testCTestHardwareSpec_data/spec6.json new file mode 100644 index 0000000..93c790d --- /dev/null +++ b/Tests/CMakeLib/testCTestHardwareSpec_data/spec6.json @@ -0,0 +1,5 @@ +{ + "local": [ + [] + ] +} diff --git a/Tests/CMakeLib/testCTestHardwareSpec_data/spec7.json b/Tests/CMakeLib/testCTestHardwareSpec_data/spec7.json new file mode 100644 index 0000000..28b6a4f --- /dev/null +++ b/Tests/CMakeLib/testCTestHardwareSpec_data/spec7.json @@ -0,0 +1,8 @@ +{ + "local": [ + { + "gpus": { + } + } + ] +} diff --git a/Tests/CMakeLib/testCTestHardwareSpec_data/spec8.json b/Tests/CMakeLib/testCTestHardwareSpec_data/spec8.json new file mode 100644 index 0000000..79bd224 --- /dev/null +++ b/Tests/CMakeLib/testCTestHardwareSpec_data/spec8.json @@ -0,0 +1,9 @@ +{ + "local": [ + { + "gpus": [ + [] + ] + } + ] +} diff --git a/Tests/CMakeLib/testCTestHardwareSpec_data/spec9.json b/Tests/CMakeLib/testCTestHardwareSpec_data/spec9.json new file mode 100644 index 0000000..6bb1def --- /dev/null +++ b/Tests/CMakeLib/testCTestHardwareSpec_data/spec9.json @@ -0,0 +1,10 @@ +{ + "local": [ + { + "gpus": [ + { + } + ] + } + ] +} diff --git a/Tests/CMakeLib/testCTestProcesses.cxx b/Tests/CMakeLib/testCTestProcesses.cxx new file mode 100644 index 0000000..acf4f67 --- /dev/null +++ b/Tests/CMakeLib/testCTestProcesses.cxx @@ -0,0 +1,137 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ + +#include <iostream> +#include <string> +#include <vector> + +#include "cmCTestTestHandler.h" + +struct ExpectedParseResult +{ + std::string String; + bool ExpectedReturnValue; + std::vector<std::vector<cmCTestTestHandler::cmCTestTestResourceRequirement>> + ExpectedValue; +}; + +static const std::vector<ExpectedParseResult> expectedResults{ + /* clang-format off */ + { "threads:2", true, { + { { "threads", 2, 1 } }, + } }, + { "3,threads:2", true, { + { { "threads", 2, 1 } }, + { { "threads", 2, 1 } }, + { { "threads", 2, 1 } }, + } }, + { "3,threads:2,gpus:4", true, { + { { "threads", 2, 1 }, { "gpus", 4, 1 } }, + { { "threads", 2, 1 }, { "gpus", 4, 1 } }, + { { "threads", 2, 1 }, { "gpus", 4, 1 } }, + } }, + { "2,threads:2;gpus:4", true, { + { { "threads", 2, 1 } }, + { { "threads", 2, 1 } }, + { { "gpus", 4, 1 } }, + } }, + { "threads:2;2,gpus:4", true, { + { { "threads", 2, 1 } }, + { { "gpus", 4, 1 } }, + { { "gpus", 4, 1 } }, + } }, + { "threads:2;gpus:4", true, { + { { "threads", 2, 1 } }, + { { "gpus", 4, 1 } }, + } }, + { "1,threads:2;0,gpus:4", true, { + { { "threads", 2, 1 } }, + } }, + { "1,_:1", true, { + { { "_", 1, 1 } }, + } }, + { "1,a:1", true, { + { { "a", 1, 1 } }, + } }, + { "2", true, { + {}, + {}, + } }, + { "1;2,threads:1", true, { + {}, + { { "threads", 1, 1 } }, + { { "threads", 1, 1 } }, + } }, + { "1,,threads:1", true, { + { { "threads", 1, 1 } }, + } }, + { ";1,threads:1", true, { + { { "threads", 1, 1 } }, + } }, + { "1,threads:1;", true, { + { { "threads", 1, 1 } }, + } }, + { "1,threads:1,", true, { + { { "threads", 1, 1 } }, + } }, + { "threads:1;;threads:2", true, { + { { "threads", 1, 1 } }, + { { "threads", 2, 1 } }, + } }, + { "1,", true, { + {}, + } }, + { ";", true, {} }, + { "", true, {} }, + { ",", false, {} }, + { "1,0:1", false, {} }, + { "1,A:1", false, {} }, + { "1,a-b:1", false, {} }, + { "invalid", false, {} }, + { ",1,invalid:1", false, {} }, + { "1,1", false, {} }, + { "-1,invalid:1", false, {} }, + { "1,invalid:*", false, {} }, + { "1,invalid:-1", false, {} }, + { "1,invalid:-", false, {} }, + { "1,invalid:ab2", false, {} }, + { "1,invalid :2", false, {} }, + { "1, invalid:2", false, {} }, + { "1,invalid:ab", false, {} }, + /* clang-format on */ +}; + +bool TestExpectedParseResult(const ExpectedParseResult& expected) +{ + std::vector<std::vector<cmCTestTestHandler::cmCTestTestResourceRequirement>> + result; + bool retval; + if ((retval = cmCTestTestHandler::ParseProcessesProperty( + expected.String, result)) != expected.ExpectedReturnValue) { + std::cout << "ParseProcessesProperty(\"" << expected.String + << "\") returned " << retval << ", should be " + << expected.ExpectedReturnValue << std::endl; + return false; + } + + if (result != expected.ExpectedValue) { + std::cout << "ParseProcessesProperty(\"" << expected.String + << "\") did not yield expected set of processes" << std::endl; + return false; + } + + return true; +} + +int testCTestProcesses(int /*unused*/, char* /*unused*/ []) +{ + int retval = 0; + + for (auto const& expected : expectedResults) { + if (!TestExpectedParseResult(expected)) { + retval = 1; + } + } + + return retval; +} diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index bd068fd..0925c0e 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -335,6 +335,44 @@ add_RunCMake_test(no_install_prefix) add_RunCMake_test(configure_file) add_RunCMake_test(CTestTimeoutAfterMatch) +# cthwalloc links against CMakeLib and CTestLib, which means it can't be built +# if CMake_TEST_EXTERNAL_CMAKE is activated (the compiler might be different.) +# So, it has to be provided in the original build tree. +if(CMake_TEST_EXTERNAL_CMAKE) + set(no_package_root_path) + if(NOT CMAKE_VERSION VERSION_LESS 3.12) + set(no_package_root_path NO_PACKAGE_ROOT_PATH) + endif() + find_program(cthwalloc cthwalloc PATHS ${CMake_TEST_EXTERNAL_CMAKE} + NO_DEFAULT_PATH + ${no_package_root_path} + NO_CMAKE_PATH + NO_CMAKE_ENVIRONMENT_PATH + NO_SYSTEM_ENVIRONMENT_PATH + NO_CMAKE_SYSTEM_PATH + NO_CMAKE_FIND_ROOT_PATH + ) + if(cthwalloc) + add_executable(cthwalloc IMPORTED) + set_property(TARGET cthwalloc PROPERTY IMPORTED_LOCATION ${cthwalloc}) + endif() +else() + add_executable(cthwalloc CTestHardwareAllocation/cthwalloc.cxx) + target_link_libraries(cthwalloc CTestLib) + target_include_directories(cthwalloc PRIVATE + ${CMake_BINARY_DIR}/Source + ${CMake_SOURCE_DIR}/Source + ${CMake_SOURCE_DIR}/Source/CTest + ) + set_property(TARGET cthwalloc PROPERTY RUNTIME_OUTPUT_DIRECTORY ${CMake_BIN_DIR}) +endif() + +if(TARGET cthwalloc) + add_RunCMake_test(CTestHardwareAllocation -DCTHWALLOC_COMMAND=$<TARGET_FILE:cthwalloc>) +else() + message(WARNING "Could not find or build cthwalloc") +endif() + find_package(Qt4 QUIET) find_package(Qt5Core QUIET) if (QT4_FOUND AND Qt5Core_FOUND AND NOT Qt5Core_VERSION VERSION_LESS 5.1.0) diff --git a/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake index ca2975a..fd2c97f 100644 --- a/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake +++ b/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake @@ -258,6 +258,7 @@ function(run_ShowOnly) add_test(ShowOnly \"${CMAKE_COMMAND}\" -E echo) set_tests_properties(ShowOnly PROPERTIES WILL_FAIL true + PROCESSES \"2,threads:2,gpus:4;gpus:2,threads:4\" REQUIRED_FILES RequiredFileDoesNotExist _BACKTRACE_TRIPLES \"file1;1;add_test;file0;;\" ) diff --git a/Tests/RunCMake/CTestCommandLine/show-only_json-v1_check.py b/Tests/RunCMake/CTestCommandLine/show-only_json-v1_check.py index 3ad5768..6eb8624 100644 --- a/Tests/RunCMake/CTestCommandLine/show-only_json-v1_check.py +++ b/Tests/RunCMake/CTestCommandLine/show-only_json-v1_check.py @@ -80,6 +80,62 @@ def check_willfail_property(p): assert p["name"] == "WILL_FAIL" assert p["value"] == True +def check_processes_property(p): + assert is_dict(p) + assert sorted(p.keys()) == ["name", "value"] + assert is_string(p["name"]) + assert is_list(p["value"]) + assert p["name"] == "PROCESSES" + assert len(p["value"]) == 3 + + assert is_dict(p["value"][0]) + assert sorted(p["value"][0].keys()) == ["requirements"] + assert is_list(p["value"][0]["requirements"]) + assert len(p["value"][0]["requirements"]) == 2 + assert is_dict(p["value"][0]["requirements"][0]) + assert sorted(p["value"][0]["requirements"][0].keys()) == \ + [".type", "slots"] + assert is_string(p["value"][0]["requirements"][0][".type"]) + assert p["value"][0]["requirements"][0][".type"] == "threads" + assert is_int(p["value"][0]["requirements"][0]["slots"]) + assert p["value"][0]["requirements"][0]["slots"] == 2 + assert is_string(p["value"][0]["requirements"][1][".type"]) + assert p["value"][0]["requirements"][1][".type"] == "gpus" + assert is_int(p["value"][0]["requirements"][1]["slots"]) + assert p["value"][0]["requirements"][1]["slots"] == 4 + + assert is_dict(p["value"][1]) + assert sorted(p["value"][1].keys()) == ["requirements"] + assert is_list(p["value"][1]["requirements"]) + assert len(p["value"][1]["requirements"]) == 2 + assert is_dict(p["value"][1]["requirements"][0]) + assert sorted(p["value"][1]["requirements"][0].keys()) == \ + [".type", "slots"] + assert is_string(p["value"][1]["requirements"][0][".type"]) + assert p["value"][1]["requirements"][0][".type"] == "threads" + assert is_int(p["value"][1]["requirements"][0]["slots"]) + assert p["value"][1]["requirements"][0]["slots"] == 2 + assert is_string(p["value"][1]["requirements"][1][".type"]) + assert p["value"][1]["requirements"][1][".type"] == "gpus" + assert is_int(p["value"][1]["requirements"][1]["slots"]) + assert p["value"][1]["requirements"][1]["slots"] == 4 + + assert is_dict(p["value"][2]) + assert sorted(p["value"][2].keys()) == ["requirements"] + assert is_list(p["value"][2]["requirements"]) + assert len(p["value"][2]["requirements"]) == 2 + assert is_dict(p["value"][2]["requirements"][0]) + assert sorted(p["value"][2]["requirements"][0].keys()) == \ + [".type", "slots"] + assert is_string(p["value"][2]["requirements"][0][".type"]) + assert p["value"][2]["requirements"][0][".type"] == "gpus" + assert is_int(p["value"][2]["requirements"][0]["slots"]) + assert p["value"][2]["requirements"][0]["slots"] == 2 + assert is_string(p["value"][2]["requirements"][1][".type"]) + assert p["value"][2]["requirements"][1][".type"] == "threads" + assert is_int(p["value"][2]["requirements"][1]["slots"]) + assert p["value"][2]["requirements"][1]["slots"] == 4 + def check_workingdir_property(p): assert is_dict(p) assert sorted(p.keys()) == ["name", "value"] @@ -90,10 +146,11 @@ def check_workingdir_property(p): def check_properties(p): assert is_list(p) - assert len(p) == 3 - check_reqfiles_property(p[0]) - check_willfail_property(p[1]) - check_workingdir_property(p[2]) + assert len(p) == 4 + check_processes_property(p[0]) + check_reqfiles_property(p[1]) + check_willfail_property(p[2]) + check_workingdir_property(p[3]) def check_tests(t): assert is_list(t) diff --git a/Tests/RunCMake/CTestHardwareAllocation/CMakeLists.txt.in b/Tests/RunCMake/CTestHardwareAllocation/CMakeLists.txt.in new file mode 100644 index 0000000..d6cff63 --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/CMakeLists.txt.in @@ -0,0 +1,9 @@ +cmake_minimum_required(VERSION 3.15) +set(CASE_NAME "@CASE_NAME@") +if(CASE_NAME MATCHES "^(.*)-ctest-s") + set(projname "${CMAKE_MATCH_1}") + project(${projname} NONE) + include(CTest) + include("@RunCMake_SOURCE_DIR@/HardwareCommon.cmake") + include("@RunCMake_SOURCE_DIR@/${projname}.cmake") +endif() diff --git a/Tests/RunCMake/CTestHardwareAllocation/HardwareCommon.cmake b/Tests/RunCMake/CTestHardwareAllocation/HardwareCommon.cmake new file mode 100644 index 0000000..3893d40 --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/HardwareCommon.cmake @@ -0,0 +1,23 @@ +function(setup_hardware_tests) + if(CTEST_HARDWARE_ALLOC_ENABLED) + add_test(NAME HardwareSetup COMMAND "${CMAKE_COMMAND}" -E remove -f "${CMAKE_BINARY_DIR}/cthwalloc.log") + endif() +endfunction() + +function(add_hardware_test name sleep_time proc) + if(CTEST_HARDWARE_ALLOC_ENABLED) + add_test(NAME "${name}" COMMAND "${CTHWALLOC_COMMAND}" write "${CMAKE_BINARY_DIR}/cthwalloc.log" "${name}" "${sleep_time}" "${proc}") + set_property(TEST "${name}" PROPERTY DEPENDS HardwareSetup) + else() + add_test(NAME "${name}" COMMAND "${CTHWALLOC_COMMAND}" write "${CMAKE_BINARY_DIR}/cthwalloc.log" "${name}" "${sleep_time}") + endif() + set_property(TEST "${name}" PROPERTY PROCESSES "${proc}") + list(APPEND HARDWARE_TESTS "${name}") + set(HARDWARE_TESTS "${HARDWARE_TESTS}" PARENT_SCOPE) +endfunction() + +function(cleanup_hardware_tests) + if(CTEST_HARDWARE_ALLOC_ENABLED) + file(WRITE "${CMAKE_BINARY_DIR}/hwtests.txt" "${HARDWARE_TESTS}") + endif() +endfunction() diff --git a/Tests/RunCMake/CTestHardwareAllocation/RunCMakeTest.cmake b/Tests/RunCMake/CTestHardwareAllocation/RunCMakeTest.cmake new file mode 100644 index 0000000..d666922 --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/RunCMakeTest.cmake @@ -0,0 +1,167 @@ +include(RunCMake) +include(RunCTest) + +############################################################################### +# Test cthwalloc itself - we want to make sure it's not just rubber-stamping +# the test results +############################################################################### + +function(cthwalloc_verify_log expected_contents) + if(NOT EXISTS "${RunCMake_TEST_BINARY_DIR}/cthwalloc.log") + string(APPEND RunCMake_TEST_FAILED "Log file was not written\n") + set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE) + return() + endif() + file(READ "${RunCMake_TEST_BINARY_DIR}/cthwalloc.log" actual_contents) + if(NOT actual_contents STREQUAL expected_contents) + string(APPEND RunCMake_TEST_FAILED "Actual log did not match expected log\n") + set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE) + endif() +endfunction() + +function(run_cthwalloc_write_proc name proc) + file(REMOVE "${RunCMake_BINARY_DIR}/${name}-build/cthwalloc.log") + run_cthwalloc_write_proc_nodel("${name}" "${proc}" "${ARGN}") +endfunction() + +function(run_cthwalloc_write_proc_nodel name proc) + string(REPLACE ";" "\\;" proc "${proc}") + run_cmake_command(${name} "${CMAKE_COMMAND}" -E env "${ARGN}" "${CTHWALLOC_COMMAND}" write "${RunCMake_BINARY_DIR}/${name}-build/cthwalloc.log" "${name}" 0 "${proc}") +endfunction() + +function(run_cthwalloc_write_noproc name) + run_cmake_command(${name} "${CMAKE_COMMAND}" -E env "${ARGN}" "${CTHWALLOC_COMMAND}" write "${RunCMake_BINARY_DIR}/${name}-build/cthwalloc.log" "${name}" 0) +endfunction() + +function(run_cthwalloc_verify name tests) + string(REPLACE ";" "\\;" tests "${tests}") + run_cmake_command(${name} "${CTHWALLOC_COMMAND}" verify "${RunCMake_SOURCE_DIR}/${name}.log" "${CMAKE_CURRENT_LIST_DIR}/hwspec.json" "${tests}") +endfunction() + +unset(ENV{CTEST_PROCESS_COUNT}) +set(RunCMake_TEST_NO_CLEAN 1) +file(REMOVE_RECURSE "${RunCMake_BINARY_DIR}/cthwalloc-write-proc-good1-build") +file(MAKE_DIRECTORY "${RunCMake_BINARY_DIR}/cthwalloc-write-proc-good1-build") +file(WRITE "${RunCMake_BINARY_DIR}/cthwalloc-write-proc-good1-build/cthwalloc.log" +[[begin test1 +alloc widgets 0 1 +dealloc widgets 0 1 +end test1 +]]) +run_cthwalloc_write_proc_nodel(cthwalloc-write-proc-good1 "1,widgets:2,transmogrifiers:1;2,widgets:1,widgets:2" + CTEST_PROCESS_COUNT=3 + CTEST_PROCESS_0=widgets,transmogrifiers + CTEST_PROCESS_0_WIDGETS=id:0,slots:2 + CTEST_PROCESS_0_TRANSMOGRIFIERS=id:calvin,slots:1 + CTEST_PROCESS_1=widgets + "CTEST_PROCESS_1_WIDGETS=id:0,slots:1\\;id:2,slots:2" + CTEST_PROCESS_2=widgets + "CTEST_PROCESS_2_WIDGETS=id:0,slots:1\\;id:2,slots:2" + ) +set(RunCMake_TEST_NO_CLEAN 0) +run_cthwalloc_write_proc(cthwalloc-write-proc-good2 "widgets:8" + CTEST_PROCESS_COUNT=1 + CTEST_PROCESS_0=widgets + CTEST_PROCESS_0_WIDGETS=id:3,slots:8 + ) +run_cthwalloc_write_proc(cthwalloc-write-proc-nocount "widgets:8") +run_cthwalloc_write_proc(cthwalloc-write-proc-badcount "widgets:8" + CTEST_PROCESS_COUNT=2 + ) +run_cthwalloc_write_proc(cthwalloc-write-proc-nores "widgets:8" + CTEST_PROCESS_COUNT=1 + ) +run_cthwalloc_write_proc(cthwalloc-write-proc-badres "widgets:8" + CTEST_PROCESS_COUNT=1 + CTEST_PROCESS_0=widgets,transmogrifiers + ) +run_cthwalloc_write_proc(cthwalloc-write-proc-nowidgets "widgets:8" + CTEST_PROCESS_COUNT=1 + CTEST_PROCESS_0=widgets + ) +run_cthwalloc_write_proc(cthwalloc-write-proc-badwidgets1 "widgets:8" + CTEST_PROCESS_COUNT=1 + CTEST_PROCESS_0=widgets + CTEST_PROCESS_0_WIDGETS= + ) +run_cthwalloc_write_proc(cthwalloc-write-proc-badwidgets2 "widgets:8" + CTEST_PROCESS_COUNT=1 + CTEST_PROCESS_0=widgets + "CTEST_PROCESS_0_WIDGETS=id:3,slots:8\\;id:0,slots:1" + ) +run_cthwalloc_write_proc(cthwalloc-write-proc-badwidgets3 "widgets:8" + CTEST_PROCESS_COUNT=1 + CTEST_PROCESS_0=widgets + CTEST_PROCESS_0_WIDGETS=id:3,slots:7 + ) +run_cthwalloc_write_proc(cthwalloc-write-proc-badwidgets4 "widgets:8" + CTEST_PROCESS_COUNT=1 + CTEST_PROCESS_0=widgets + CTEST_PROCESS_0_WIDGETS=invalid + ) +run_cthwalloc_write_proc(cthwalloc-write-proc-badwidgets5 "widgets:2,widgets:2" + CTEST_PROCESS_COUNT=1 + CTEST_PROCESS_0=widgets + "CTEST_PROCESS_0_WIDGETS=id:0,slots:2\\;id:0,slots:1" + ) +run_cthwalloc_write_proc(cthwalloc-write-proc-badwidgets6 "widgets:2" + CTEST_PROCESS_COUNT=1 + CTEST_PROCESS_0=widgets + "CTEST_PROCESS_0_WIDGETS=id:0,slots:2\\;id:0,slots:1" + ) +run_cthwalloc_write_proc(cthwalloc-write-proc-badwidgets7 "widgets:2,widgets:2" + CTEST_PROCESS_COUNT=1 + CTEST_PROCESS_0=widgets + CTEST_PROCESS_0_WIDGETS=id:0,slots:2 + ) + +run_cthwalloc_write_noproc(cthwalloc-write-noproc-good1) +run_cthwalloc_write_noproc(cthwalloc-write-noproc-count + CTEST_PROCESS_COUNT=1 + ) + +run_cthwalloc_verify(cthwalloc-verify-good1 "test1;test2") +run_cthwalloc_verify(cthwalloc-verify-good2 "") +run_cthwalloc_verify(cthwalloc-verify-nolog "") +run_cthwalloc_verify(cthwalloc-verify-nores "") +run_cthwalloc_verify(cthwalloc-verify-noid "") +run_cthwalloc_verify(cthwalloc-verify-notenough "") +run_cthwalloc_verify(cthwalloc-verify-baddealloc "") +run_cthwalloc_verify(cthwalloc-verify-leak "") +run_cthwalloc_verify(cthwalloc-verify-badtest1 "") +run_cthwalloc_verify(cthwalloc-verify-badtest2 "test1") +run_cthwalloc_verify(cthwalloc-verify-badtest3 "test1") +run_cthwalloc_verify(cthwalloc-verify-badtest4 "test1") +run_cthwalloc_verify(cthwalloc-verify-badtest5 "test1") +run_cthwalloc_verify(cthwalloc-verify-nobegin "test1") +run_cthwalloc_verify(cthwalloc-verify-noend "test1") + +############################################################################### +# Now test the hardware allocation feature of CTest +############################################################################### + +function(run_ctest_hardware name parallel random) + run_ctest("${name}-ctest-s-hw" "-DCTEST_HARDWARE_ALLOC_ENABLED=1" "-DCTHWALLOC_COMMAND=${CTHWALLOC_COMMAND}" "-DCTEST_PARALLEL=${parallel}" "-DCTEST_RANDOM=${random}") + run_ctest("${name}-ctest-s-nohw" "-DCTEST_HARDWARE_ALLOC_ENABLED=0" "-DCTHWALLOC_COMMAND=${CTHWALLOC_COMMAND}" "-DCTEST_PARALLEL=${parallel}" "-DCTEST_RANDOM=${random}") +endfunction() + +function(verify_ctest_hardware) + file(READ "${RunCMake_TEST_BINARY_DIR}/hwtests.txt" hwtests) + execute_process(COMMAND "${CTHWALLOC_COMMAND}" verify "${RunCMake_TEST_BINARY_DIR}/cthwalloc.log" "${CMAKE_CURRENT_LIST_DIR}/hwspec.json" "${hwtests}" + OUTPUT_VARIABLE output ERROR_QUIET RESULT_VARIABLE result) + if(result) + string(APPEND RunCMake_TEST_FAILED "${output}") + set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE) + endif() +endfunction() + +run_ctest_hardware(lotsoftests 10 1) +run_ctest_hardware(checkfree1 2 0) +run_ctest_hardware(checkfree2 1 0) +run_ctest_hardware(notenough1 1 0) +run_ctest_hardware(notenough2 1 0) +run_ctest_hardware(ensure_parallel 2 0) + +set(ENV{CTEST_PROCESS_COUNT} 2) +run_ctest_hardware(process_count 1 0) +unset(ENV{CTEST_PROCESS_COUNT}) diff --git a/Tests/RunCMake/CTestHardwareAllocation/checkfree1-ctest-s-hw-check.cmake b/Tests/RunCMake/CTestHardwareAllocation/checkfree1-ctest-s-hw-check.cmake new file mode 100644 index 0000000..94b1fa7 --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/checkfree1-ctest-s-hw-check.cmake @@ -0,0 +1 @@ +verify_ctest_hardware() diff --git a/Tests/RunCMake/CTestHardwareAllocation/checkfree1.cmake b/Tests/RunCMake/CTestHardwareAllocation/checkfree1.cmake new file mode 100644 index 0000000..0e997b5 --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/checkfree1.cmake @@ -0,0 +1,7 @@ +setup_hardware_tests() + +add_hardware_test(Test1 1 "widgets:8") +add_hardware_test(Test2 1 "fluxcapacitors:50;fluxcapacitors:50,widgets:8") +add_hardware_test(Test3 1 "fluxcapacitors:121") + +cleanup_hardware_tests() diff --git a/Tests/RunCMake/CTestHardwareAllocation/checkfree2-ctest-s-hw-check.cmake b/Tests/RunCMake/CTestHardwareAllocation/checkfree2-ctest-s-hw-check.cmake new file mode 100644 index 0000000..94b1fa7 --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/checkfree2-ctest-s-hw-check.cmake @@ -0,0 +1 @@ +verify_ctest_hardware() diff --git a/Tests/RunCMake/CTestHardwareAllocation/checkfree2.cmake b/Tests/RunCMake/CTestHardwareAllocation/checkfree2.cmake new file mode 100644 index 0000000..3c2b666 --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/checkfree2.cmake @@ -0,0 +1,8 @@ +setup_hardware_tests() + +# This test is an attack on the hardware scheduling algorithm. It has been +# carefully crafted to fool the algorithm into thinking there isn't sufficient +# hardware for it. +add_hardware_test(Test1 1 "widgets:2;4,widgets:4") + +cleanup_hardware_tests() diff --git a/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-baddealloc-result.txt b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-baddealloc-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-baddealloc-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-baddealloc.log b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-baddealloc.log new file mode 100644 index 0000000..abd6bad --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-baddealloc.log @@ -0,0 +1,2 @@ +alloc widgets 0 1 +dealloc widgets 0 2 diff --git a/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-badtest1-result.txt b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-badtest1-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-badtest1-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-badtest1.log b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-badtest1.log new file mode 100644 index 0000000..605104b --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-badtest1.log @@ -0,0 +1 @@ +begin test1 diff --git a/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-badtest2-result.txt b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-badtest2-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-badtest2-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-badtest2.log b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-badtest2.log new file mode 100644 index 0000000..1ff1b0d --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-badtest2.log @@ -0,0 +1,2 @@ +begin test1 +begin test1 diff --git a/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-badtest3-result.txt b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-badtest3-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-badtest3-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-badtest3.log b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-badtest3.log new file mode 100644 index 0000000..1925e6a --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-badtest3.log @@ -0,0 +1,3 @@ +begin test1 +end test1 +begin test1 diff --git a/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-badtest4-result.txt b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-badtest4-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-badtest4-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-badtest4.log b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-badtest4.log new file mode 100644 index 0000000..3fe7da1 --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-badtest4.log @@ -0,0 +1,3 @@ +begin test1 +end test1 +end test1 diff --git a/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-badtest5-result.txt b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-badtest5-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-badtest5-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-badtest5.log b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-badtest5.log new file mode 100644 index 0000000..3a2e7e3 --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-badtest5.log @@ -0,0 +1 @@ +end test1 diff --git a/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-good1.log b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-good1.log new file mode 100644 index 0000000..2cca0c3 --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-good1.log @@ -0,0 +1,14 @@ +begin test1 +alloc widgets 3 4 +alloc widgets 4 1 +alloc transmogrifiers calvin 2 +alloc fluxcapacitors outatime 121 +begin test2 +alloc widgets 3 4 +dealloc widgets 3 4 +dealloc widgets 4 1 +dealloc transmogrifiers calvin 2 +dealloc fluxcapacitors outatime 121 +end test1 +dealloc widgets 3 4 +end test2 diff --git a/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-good2.log b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-good2.log new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-good2.log diff --git a/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-leak-result.txt b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-leak-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-leak-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-leak.log b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-leak.log new file mode 100644 index 0000000..b900d86 --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-leak.log @@ -0,0 +1 @@ +alloc widgets 0 1 diff --git a/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-nobegin-result.txt b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-nobegin-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-nobegin-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-nobegin.log b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-nobegin.log new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-nobegin.log diff --git a/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-noend-result.txt b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-noend-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-noend-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-noend.log b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-noend.log new file mode 100644 index 0000000..605104b --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-noend.log @@ -0,0 +1 @@ +begin test1 diff --git a/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-noid-result.txt b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-noid-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-noid-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-noid.log b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-noid.log new file mode 100644 index 0000000..c718975 --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-noid.log @@ -0,0 +1,2 @@ +alloc fluxcapacitors train 1 +dealloc fluxcapacitors train 1 diff --git a/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-nolog-result.txt b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-nolog-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-nolog-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-nores-result.txt b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-nores-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-nores-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-nores.log b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-nores.log new file mode 100644 index 0000000..a18202b --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-nores.log @@ -0,0 +1,2 @@ +alloc gpus 0 1 +dealloc gpus 0 1 diff --git a/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-notenough-result.txt b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-notenough-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-notenough-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-notenough.log b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-notenough.log new file mode 100644 index 0000000..ac78d5a --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-verify-notenough.log @@ -0,0 +1,2 @@ +alloc widgets 0 8 +dealloc widgets 0 8 diff --git a/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-write-noproc-count-result.txt b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-write-noproc-count-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-write-noproc-count-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-write-proc-badcount-result.txt b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-write-proc-badcount-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-write-proc-badcount-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-write-proc-badres-result.txt b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-write-proc-badres-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-write-proc-badres-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-write-proc-badwidgets1-result.txt b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-write-proc-badwidgets1-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-write-proc-badwidgets1-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-write-proc-badwidgets2-result.txt b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-write-proc-badwidgets2-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-write-proc-badwidgets2-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-write-proc-badwidgets3-result.txt b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-write-proc-badwidgets3-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-write-proc-badwidgets3-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-write-proc-badwidgets4-result.txt b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-write-proc-badwidgets4-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-write-proc-badwidgets4-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-write-proc-badwidgets5-result.txt b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-write-proc-badwidgets5-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-write-proc-badwidgets5-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-write-proc-badwidgets6-result.txt b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-write-proc-badwidgets6-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-write-proc-badwidgets6-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-write-proc-badwidgets7-result.txt b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-write-proc-badwidgets7-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-write-proc-badwidgets7-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-write-proc-good1-check.cmake b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-write-proc-good1-check.cmake new file mode 100644 index 0000000..949d2d7 --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-write-proc-good1-check.cmake @@ -0,0 +1,20 @@ +cthwalloc_verify_log( +[[begin test1 +alloc widgets 0 1 +dealloc widgets 0 1 +end test1 +begin cthwalloc-write-proc-good1 +alloc transmogrifiers calvin 1 +alloc widgets 0 2 +alloc widgets 0 1 +alloc widgets 2 2 +alloc widgets 0 1 +alloc widgets 2 2 +dealloc transmogrifiers calvin 1 +dealloc widgets 0 2 +dealloc widgets 0 1 +dealloc widgets 2 2 +dealloc widgets 0 1 +dealloc widgets 2 2 +end cthwalloc-write-proc-good1 +]]) diff --git a/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-write-proc-good2-check.cmake b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-write-proc-good2-check.cmake new file mode 100644 index 0000000..ca0c6b8 --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-write-proc-good2-check.cmake @@ -0,0 +1,6 @@ +cthwalloc_verify_log( +[[begin cthwalloc-write-proc-good2 +alloc widgets 3 8 +dealloc widgets 3 8 +end cthwalloc-write-proc-good2 +]]) diff --git a/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-write-proc-nocount-result.txt b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-write-proc-nocount-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-write-proc-nocount-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-write-proc-nores-result.txt b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-write-proc-nores-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-write-proc-nores-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-write-proc-nowidgets-result.txt b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-write-proc-nowidgets-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc-write-proc-nowidgets-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CTestHardwareAllocation/cthwalloc.cxx b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc.cxx new file mode 100644 index 0000000..eee2c7f --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/cthwalloc.cxx @@ -0,0 +1,396 @@ +#include <cassert> +#include <chrono> +#include <cstddef> +#include <cstdlib> +#include <iostream> +#include <map> +#include <set> +#include <string> +#include <thread> +#include <utility> +#include <vector> + +#include "cmsys/Encoding.hxx" +#include "cmsys/FStream.hxx" + +#include "cmCTestHardwareAllocator.h" +#include "cmCTestHardwareSpec.h" +#include "cmCTestMultiProcessHandler.h" +#include "cmCTestTestHandler.h" +#include "cmFileLock.h" +#include "cmFileLockResult.h" +#include "cmStringAlgorithms.h" +#include "cmSystemTools.h" + +/* + * This helper program is used to verify that the CTest hardware allocation + * feature is working correctly. It consists of two stages: + * + * 1) write - This stage receives the PROCESSES property of the test and + * compares it with the values passed in the CTEST_PROCESS_* environment + * variables. If it received all of the resources it expected, then it + * writes this information to a log file, which will be read in the verify + * stage. + * 2) verify - This stage compares the log file with the hardware spec file to + * make sure that no resources were over-subscribed, deallocated without + * being allocated, or allocated without being deallocated. + */ + +static int usage(const char* argv0) +{ + std::cout << "Usage: " << argv0 << " (write|verify) <args...>" << std::endl; + return 1; +} + +static int usageWrite(const char* argv0) +{ + std::cout << "Usage: " << argv0 + << " write <log-file> <test-name> <sleep-time-secs>" + " [<processes-property>]" + << std::endl; + return 1; +} + +static int usageVerify(const char* argv0) +{ + std::cout << "Usage: " << argv0 + << " verify <log-file> <hardware-spec-file> [<test-names>]" + << std::endl; + return 1; +} + +static int doWrite(int argc, char const* const* argv) +{ + if (argc < 5 || argc > 6) { + return usageWrite(argv[0]); + } + std::string logFile = argv[2]; + std::string testName = argv[3]; + unsigned int sleepTime = std::atoi(argv[4]); + std::vector<std::map< + std::string, std::vector<cmCTestMultiProcessHandler::HardwareAllocation>>> + hardware; + if (argc == 6) { + // Parse processes property + std::string processesProperty = argv[5]; + std::vector< + std::vector<cmCTestTestHandler::cmCTestTestResourceRequirement>> + processes; + bool result = + cmCTestTestHandler::ParseProcessesProperty(processesProperty, processes); + (void)result; + assert(result); + + // Verify process count + const char* processCountEnv = cmSystemTools::GetEnv("CTEST_PROCESS_COUNT"); + if (!processCountEnv) { + std::cout << "CTEST_PROCESS_COUNT should be defined" << std::endl; + return 1; + } + int processCount = std::atoi(processCountEnv); + if (processes.size() != std::size_t(processCount)) { + std::cout << "CTEST_PROCESS_COUNT does not match expected processes" + << std::endl + << "Expected: " << processes.size() << std::endl + << "Actual: " << processCount << std::endl; + return 1; + } + + if (!cmSystemTools::Touch(logFile + ".lock", true)) { + std::cout << "Could not create lock file" << std::endl; + return 1; + } + cmFileLock lock; + auto lockResult = + lock.Lock(logFile + ".lock", static_cast<unsigned long>(-1)); + if (!lockResult.IsOk()) { + std::cout << "Could not lock file" << std::endl; + return 1; + } + std::size_t i = 0; + cmsys::ofstream fout(logFile.c_str(), std::ios::app); + fout << "begin " << testName << std::endl; + for (auto& process : processes) { + try { + // Build and verify set of expected resources + std::set<std::string> expectedResources; + for (auto const& it : process) { + expectedResources.insert(it.ResourceType); + } + + std::string prefix = "CTEST_PROCESS_"; + prefix += std::to_string(i); + const char* actualResourcesCStr = cmSystemTools::GetEnv(prefix); + if (!actualResourcesCStr) { + std::cout << prefix << " should be defined" << std::endl; + return 1; + } + + auto actualResourcesVec = + cmSystemTools::SplitString(actualResourcesCStr, ','); + std::set<std::string> actualResources; + for (auto const& r : actualResourcesVec) { + if (!r.empty()) { + actualResources.insert(r); + } + } + + if (actualResources != expectedResources) { + std::cout << prefix << " did not list expected resources" + << std::endl; + return 1; + } + + // Verify that we got what we asked for and write it to the log + prefix += '_'; + std::map<std::string, + std::vector<cmCTestMultiProcessHandler::HardwareAllocation>> + hwEntry; + for (auto const& type : actualResources) { + auto it = process.begin(); + + std::string varName = prefix; + varName += cmSystemTools::UpperCase(type); + const char* varVal = cmSystemTools::GetEnv(varName); + if (!varVal) { + std::cout << varName << " should be defined" << std::endl; + return 1; + } + + auto received = cmSystemTools::SplitString(varVal, ';'); + for (auto const& r : received) { + while (it->ResourceType != type || it->UnitsNeeded == 0) { + ++it; + if (it == process.end()) { + std::cout << varName << " did not list expected resources" + << std::endl; + return 1; + } + } + auto split = cmSystemTools::SplitString(r, ','); + if (split.size() != 2) { + std::cout << varName << " was ill-formed" << std::endl; + return 1; + } + if (!cmHasLiteralPrefix(split[0], "id:")) { + std::cout << varName << " was ill-formed" << std::endl; + return 1; + } + auto id = split[0].substr(3); + if (!cmHasLiteralPrefix(split[1], "slots:")) { + std::cout << varName << " was ill-formed" << std::endl; + return 1; + } + auto slots = split[1].substr(6); + unsigned int amount = std::atoi(slots.c_str()); + if (amount != static_cast<unsigned int>(it->SlotsNeeded)) { + std::cout << varName << " did not list expected resources" + << std::endl; + return 1; + } + --it->UnitsNeeded; + + fout << "alloc " << type << " " << id << " " << amount + << std::endl; + hwEntry[type].push_back({ id, amount }); + } + + bool ended = false; + while (it->ResourceType != type || it->UnitsNeeded == 0) { + ++it; + if (it == process.end()) { + ended = true; + break; + } + } + + if (!ended) { + std::cout << varName << " did not list expected resources" + << std::endl; + return 1; + } + } + hardware.push_back(hwEntry); + + ++i; + } catch (...) { + std::cout << "Unknown error while processing resources" << std::endl; + return 1; + } + } + + auto unlockResult = lock.Release(); + if (!unlockResult.IsOk()) { + std::cout << "Could not unlock file" << std::endl; + return 1; + } + } else { + if (cmSystemTools::GetEnv("CTEST_PROCESS_COUNT")) { + std::cout << "CTEST_PROCESS_COUNT should not be defined" << std::endl; + return 1; + } + } + + std::this_thread::sleep_for(std::chrono::seconds(sleepTime)); + + if (argc == 6) { + if (!cmSystemTools::Touch(logFile + ".lock", true)) { + std::cout << "Could not create lock file" << std::endl; + return 1; + } + cmFileLock lock; + auto lockResult = + lock.Lock(logFile + ".lock", static_cast<unsigned long>(-1)); + if (!lockResult.IsOk()) { + std::cout << "Could not lock file" << std::endl; + return 1; + } + cmsys::ofstream fout(logFile.c_str(), std::ios::app); + for (auto const& process : hardware) { + for (auto const& it : process) { + for (auto const& it2 : it.second) { + fout << "dealloc " << it.first << " " << it2.Id << " " << it2.Slots + << std::endl; + } + } + } + + fout << "end " << testName << std::endl; + + auto unlockResult = lock.Release(); + if (!unlockResult.IsOk()) { + std::cout << "Could not unlock file" << std::endl; + return 1; + } + } + + return 0; +} + +static int doVerify(int argc, char const* const* argv) +{ + if (argc < 4 || argc > 5) { + return usageVerify(argv[0]); + } + std::string logFile = argv[2]; + std::string hwFile = argv[3]; + std::string testNames; + if (argc == 5) { + testNames = argv[4]; + } + auto testNameList = cmExpandedList(testNames, false); + std::set<std::string> testNameSet(testNameList.begin(), testNameList.end()); + + cmCTestHardwareSpec spec; + if (!spec.ReadFromJSONFile(hwFile)) { + std::cout << "Could not read hardware spec " << hwFile << std::endl; + return 1; + } + + cmCTestHardwareAllocator allocator; + allocator.InitializeFromHardwareSpec(spec); + + cmsys::ifstream fin(logFile.c_str(), std::ios::in); + if (!fin) { + std::cout << "Could not open log file " << logFile << std::endl; + return 1; + } + + std::string command; + std::string resourceName; + std::string resourceId; + std::string testName; + unsigned int amount; + std::set<std::string> inProgressTests; + std::set<std::string> completedTests; + try { + while (fin >> command) { + if (command == "begin") { + if (!(fin >> testName)) { + std::cout << "Could not read begin line" << std::endl; + return 1; + } + if (!testNameSet.count(testName) || inProgressTests.count(testName) || + completedTests.count(testName)) { + std::cout << "Could not begin test" << std::endl; + return 1; + } + inProgressTests.insert(testName); + } else if (command == "alloc") { + if (!(fin >> resourceName) || !(fin >> resourceId) || + !(fin >> amount)) { + std::cout << "Could not read alloc line" << std::endl; + return 1; + } + if (!allocator.AllocateResource(resourceName, resourceId, amount)) { + std::cout << "Could not allocate resources" << std::endl; + return 1; + } + } else if (command == "dealloc") { + if (!(fin >> resourceName) || !(fin >> resourceId) || + !(fin >> amount)) { + std::cout << "Could not read dealloc line" << std::endl; + return 1; + } + if (!allocator.DeallocateResource(resourceName, resourceId, amount)) { + std::cout << "Could not deallocate resources" << std::endl; + return 1; + } + } else if (command == "end") { + if (!(fin >> testName)) { + std::cout << "Could not read end line" << std::endl; + return 1; + } + if (!inProgressTests.erase(testName)) { + std::cout << "Could not end test" << std::endl; + return 1; + } + if (!completedTests.insert(testName).second) { + std::cout << "Could not end test" << std::endl; + return 1; + } + } + } + } catch (...) { + std::cout << "Unknown error while reading log file" << std::endl; + return 1; + } + + auto const& avail = allocator.GetResources(); + for (auto const& it : avail) { + for (auto const& it2 : it.second) { + if (it2.second.Locked != 0) { + std::cout << "Resource was not unlocked" << std::endl; + return 1; + } + } + } + + if (completedTests != testNameSet) { + std::cout << "Tests were not ended" << std::endl; + return 1; + } + + return 0; +} + +int main(int argc, char const* const* argv) +{ + cmsys::Encoding::CommandLineArguments args = + cmsys::Encoding::CommandLineArguments::Main(argc, argv); + argc = args.argc(); + argv = args.argv(); + + if (argc < 2) { + return usage(argv[0]); + } + + std::string argv1 = argv[1]; + if (argv1 == "write") { + return doWrite(argc, argv); + } + if (argv1 == "verify") { + return doVerify(argc, argv); + } + return usage(argv[0]); +} diff --git a/Tests/RunCMake/CTestHardwareAllocation/ensure_parallel-ctest-s-hw-check.cmake b/Tests/RunCMake/CTestHardwareAllocation/ensure_parallel-ctest-s-hw-check.cmake new file mode 100644 index 0000000..e5f6828 --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/ensure_parallel-ctest-s-hw-check.cmake @@ -0,0 +1,16 @@ +verify_ctest_hardware() + +set(expected_contents [[ +begin Test1 +alloc transmogrifiers calvin 2 +begin Test2 +alloc transmogrifiers hobbes 2 +dealloc transmogrifiers calvin 2 +end Test1 +dealloc transmogrifiers hobbes 2 +end Test2 +]]) +file(READ "${RunCMake_TEST_BINARY_DIR}/cthwalloc.log" actual_contents) +if(NOT actual_contents STREQUAL expected_contents) + string(APPEND RunCMake_TEST_FAILED "cthwalloc.log contents did not match expected\n") +endif() diff --git a/Tests/RunCMake/CTestHardwareAllocation/ensure_parallel.cmake b/Tests/RunCMake/CTestHardwareAllocation/ensure_parallel.cmake new file mode 100644 index 0000000..1dafb8f --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/ensure_parallel.cmake @@ -0,0 +1,11 @@ +setup_hardware_tests() + +add_hardware_test(Test1 4 "transmogrifiers:2") + +# Mitigate possible race conditions to ensure that the events are logged in the +# exact order we want +add_test(NAME Test2Sleep COMMAND "${CMAKE_COMMAND}" -E sleep 2) +add_hardware_test(Test2 4 "transmogrifiers:2") +set_property(TEST Test2 APPEND PROPERTY DEPENDS Test2Sleep) + +cleanup_hardware_tests() diff --git a/Tests/RunCMake/CTestHardwareAllocation/hwspec.json b/Tests/RunCMake/CTestHardwareAllocation/hwspec.json new file mode 100644 index 0000000..c67fcca --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/hwspec.json @@ -0,0 +1,55 @@ +{ + "local": [ + { + "widgets": [ + { + "id": "0", + "slots": 4 + }, + { + "id": "1", + "slots": 2 + }, + { + "id": "2", + "slots": 4 + }, + { + "id": "3", + "slots": 8 + }, + { + "id": "4", + "slots": 1 + }, + { + "id": "5", + "slots": 1 + }, + { + "id": "6", + "slots": 1 + }, + { + "id": "7" + } + ], + "transmogrifiers": [ + { + "id": "calvin", + "slots": 2 + }, + { + "id": "hobbes", + "slots": 2 + } + ], + "fluxcapacitors": [ + { + "id": "outatime", + "slots": 121 + } + ] + } + ] +} diff --git a/Tests/RunCMake/CTestHardwareAllocation/lotsoftests-ctest-s-hw-check.cmake b/Tests/RunCMake/CTestHardwareAllocation/lotsoftests-ctest-s-hw-check.cmake new file mode 100644 index 0000000..94b1fa7 --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/lotsoftests-ctest-s-hw-check.cmake @@ -0,0 +1 @@ +verify_ctest_hardware() diff --git a/Tests/RunCMake/CTestHardwareAllocation/lotsoftests.cmake b/Tests/RunCMake/CTestHardwareAllocation/lotsoftests.cmake new file mode 100644 index 0000000..c684434 --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/lotsoftests.cmake @@ -0,0 +1,16 @@ +setup_hardware_tests() + +add_hardware_test(Test1 2 "widgets:8;2,widgets:2") +add_hardware_test(Test2 5 "fluxcapacitors:40") +add_hardware_test(Test3 1 "10,widgets:1,fluxcapacitors:2") +add_hardware_test(Test4 4 "fluxcapacitors:121") + +foreach(i RANGE 5 50) + add_hardware_test(Test${i} 1 "2,widgets:1") +endforeach() + +foreach(i RANGE 51 100) + add_hardware_test(Test${i} 1 "2,transmogrifiers:2") +endforeach() + +cleanup_hardware_tests() diff --git a/Tests/RunCMake/CTestHardwareAllocation/notenough1-ctest-s-hw-check.cmake b/Tests/RunCMake/CTestHardwareAllocation/notenough1-ctest-s-hw-check.cmake new file mode 100644 index 0000000..9c730be --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/notenough1-ctest-s-hw-check.cmake @@ -0,0 +1,3 @@ +if(EXISTS "${RunCMake_TEST_BINARY_DIR}/cthwalloc.log") + set(RunCMake_TEST_FAILED "cthwalloc.log should not exist") +endif() diff --git a/Tests/RunCMake/CTestHardwareAllocation/notenough1-ctest-s-hw-result.txt b/Tests/RunCMake/CTestHardwareAllocation/notenough1-ctest-s-hw-result.txt new file mode 100644 index 0000000..b57e2de --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/notenough1-ctest-s-hw-result.txt @@ -0,0 +1 @@ +(-1|255) diff --git a/Tests/RunCMake/CTestHardwareAllocation/notenough1-ctest-s-hw-stderr.txt b/Tests/RunCMake/CTestHardwareAllocation/notenough1-ctest-s-hw-stderr.txt new file mode 100644 index 0000000..d465cd3 --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/notenough1-ctest-s-hw-stderr.txt @@ -0,0 +1,4 @@ +^Insufficient hardware +CMake Error at [^ +]*/Tests/RunCMake/CTestHardwareAllocation/notenough1-ctest-s-hw/test\.cmake:[0-9]+ \(message\): + Tests did not pass$ diff --git a/Tests/RunCMake/CTestHardwareAllocation/notenough1.cmake b/Tests/RunCMake/CTestHardwareAllocation/notenough1.cmake new file mode 100644 index 0000000..3e1f620 --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/notenough1.cmake @@ -0,0 +1,5 @@ +setup_hardware_tests() + +add_hardware_test(Test1 1 "fluxcapacitors:200") + +cleanup_hardware_tests() diff --git a/Tests/RunCMake/CTestHardwareAllocation/notenough2-ctest-s-hw-check.cmake b/Tests/RunCMake/CTestHardwareAllocation/notenough2-ctest-s-hw-check.cmake new file mode 100644 index 0000000..9c730be --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/notenough2-ctest-s-hw-check.cmake @@ -0,0 +1,3 @@ +if(EXISTS "${RunCMake_TEST_BINARY_DIR}/cthwalloc.log") + set(RunCMake_TEST_FAILED "cthwalloc.log should not exist") +endif() diff --git a/Tests/RunCMake/CTestHardwareAllocation/notenough2-ctest-s-hw-result.txt b/Tests/RunCMake/CTestHardwareAllocation/notenough2-ctest-s-hw-result.txt new file mode 100644 index 0000000..b57e2de --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/notenough2-ctest-s-hw-result.txt @@ -0,0 +1 @@ +(-1|255) diff --git a/Tests/RunCMake/CTestHardwareAllocation/notenough2-ctest-s-hw-stderr.txt b/Tests/RunCMake/CTestHardwareAllocation/notenough2-ctest-s-hw-stderr.txt new file mode 100644 index 0000000..912f0fb --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/notenough2-ctest-s-hw-stderr.txt @@ -0,0 +1,4 @@ +^Insufficient hardware +CMake Error at [^ +]*/Tests/RunCMake/CTestHardwareAllocation/notenough2-ctest-s-hw/test\.cmake:[0-9]+ \(message\): + Tests did not pass$ diff --git a/Tests/RunCMake/CTestHardwareAllocation/notenough2.cmake b/Tests/RunCMake/CTestHardwareAllocation/notenough2.cmake new file mode 100644 index 0000000..8205c95 --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/notenough2.cmake @@ -0,0 +1,5 @@ +setup_hardware_tests() + +add_hardware_test(Test1 1 "terminators:2") + +cleanup_hardware_tests() diff --git a/Tests/RunCMake/CTestHardwareAllocation/process_count-ctest-s-hw-check.cmake b/Tests/RunCMake/CTestHardwareAllocation/process_count-ctest-s-hw-check.cmake new file mode 100644 index 0000000..94b1fa7 --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/process_count-ctest-s-hw-check.cmake @@ -0,0 +1 @@ +verify_ctest_hardware() diff --git a/Tests/RunCMake/CTestHardwareAllocation/process_count.cmake b/Tests/RunCMake/CTestHardwareAllocation/process_count.cmake new file mode 100644 index 0000000..c969648 --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/process_count.cmake @@ -0,0 +1,5 @@ +setup_hardware_tests() + +add_hardware_test(Test1 1 "widgets:1") + +cleanup_hardware_tests() diff --git a/Tests/RunCMake/CTestHardwareAllocation/test.cmake.in b/Tests/RunCMake/CTestHardwareAllocation/test.cmake.in new file mode 100644 index 0000000..5ba3587 --- /dev/null +++ b/Tests/RunCMake/CTestHardwareAllocation/test.cmake.in @@ -0,0 +1,23 @@ +set(CTEST_SITE "test-site") +set(CTEST_BUILD_NAME "test-build-name") +set(CTEST_SOURCE_DIRECTORY "@RunCMake_BINARY_DIR@/@CASE_NAME@") +set(CTEST_BINARY_DIRECTORY "@RunCMake_BINARY_DIR@/@CASE_NAME@-build") +set(CTEST_CMAKE_GENERATOR "@RunCMake_GENERATOR@") +set(CTEST_CMAKE_GENERATOR_PLATFORM "@RunCMake_GENERATOR_PLATFORM@") +set(CTEST_CMAKE_GENERATOR_TOOLSET "@RunCMake_GENERATOR_TOOLSET@") +set(CTEST_BUILD_CONFIGURATION "$ENV{CMAKE_CONFIG_TYPE}") +set(CTEST_NIGHTLY_START_TIME "01:00:00 UTC") + +ctest_start(Experimental QUIET) +ctest_configure(OPTIONS + "-DCTEST_HARDWARE_ALLOC_ENABLED=${CTEST_HARDWARE_ALLOC_ENABLED};-DCTHWALLOC_COMMAND=${CTHWALLOC_COMMAND}" + ) +ctest_build() + +if(CTEST_HARDWARE_ALLOC_ENABLED) + set(hwspec HARDWARE_SPEC_FILE "@RunCMake_SOURCE_DIR@/hwspec.json") +endif() +ctest_test(${hwspec} RETURN_VALUE retval PARALLEL_LEVEL ${CTEST_PARALLEL} SCHEDULE_RANDOM ${CTEST_RANDOM}) +if(retval) + message(FATAL_ERROR "Tests did not pass") +endif() |