diff options
-rw-r--r-- | Source/CMakeLists.txt | 1 | ||||
-rw-r--r-- | Source/CTest/cmCTestHardwareAllocator.cxx | 86 | ||||
-rw-r--r-- | Source/CTest/cmCTestHardwareAllocator.h | 39 | ||||
-rw-r--r-- | Tests/CMakeLib/CMakeLists.txt | 1 | ||||
-rw-r--r-- | Tests/CMakeLib/testCTestHardwareAllocator.cxx | 426 |
5 files changed, 553 insertions, 0 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 8e38590..57229db 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -918,6 +918,7 @@ set(CTEST_SRCS cmCTest.cxx CTest/cmCTestEmptyBinaryDirectoryCommand.cxx CTest/cmCTestGenericHandler.cxx CTest/cmCTestHandlerCommand.cxx + CTest/cmCTestHardwareAllocator.cxx CTest/cmCTestHardwareSpec.cxx CTest/cmCTestLaunch.cxx CTest/cmCTestMemCheckCommand.cxx diff --git a/Source/CTest/cmCTestHardwareAllocator.cxx b/Source/CTest/cmCTestHardwareAllocator.cxx new file mode 100644 index 0000000..2d1833d --- /dev/null +++ b/Source/CTest/cmCTestHardwareAllocator.cxx @@ -0,0 +1,86 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ + +#include "cmCTestHardwareAllocator.h" + +#include <utility> +#include <vector> + +#include "cmCTestHardwareSpec.h" + +void cmCTestHardwareAllocator::InitializeFromHardwareSpec( + const cmCTestHardwareSpec& spec) +{ + this->Resources.clear(); + + for (auto const& it : spec.LocalSocket.Resources) { + auto& res = this->Resources[it.first]; + for (auto const& specRes : it.second) { + res[specRes.Id].Total = specRes.Capacity; + res[specRes.Id].Locked = 0; + } + } +} + +const std::map<std::string, + std::map<std::string, cmCTestHardwareAllocator::Resource>>& +cmCTestHardwareAllocator::GetResources() const +{ + return this->Resources; +} + +bool cmCTestHardwareAllocator::AllocateResource(const std::string& name, + const std::string& id, + unsigned int slots) +{ + auto it = this->Resources.find(name); + if (it == this->Resources.end()) { + return false; + } + + auto resIt = it->second.find(id); + if (resIt == it->second.end()) { + return false; + } + + if (resIt->second.Total < resIt->second.Locked + slots) { + return false; + } + + resIt->second.Locked += slots; + return true; +} + +bool cmCTestHardwareAllocator::DeallocateResource(const std::string& name, + const std::string& id, + unsigned int slots) +{ + auto it = this->Resources.find(name); + if (it == this->Resources.end()) { + return false; + } + + auto resIt = it->second.find(id); + if (resIt == it->second.end()) { + return false; + } + + if (resIt->second.Locked < slots) { + return false; + } + + resIt->second.Locked -= slots; + return true; +} + +bool cmCTestHardwareAllocator::Resource::operator==( + const Resource& other) const +{ + return this->Total == other.Total && this->Locked == other.Locked; +} + +bool cmCTestHardwareAllocator::Resource::operator!=( + const Resource& other) const +{ + return !(*this == other); +} diff --git a/Source/CTest/cmCTestHardwareAllocator.h b/Source/CTest/cmCTestHardwareAllocator.h new file mode 100644 index 0000000..441f84d --- /dev/null +++ b/Source/CTest/cmCTestHardwareAllocator.h @@ -0,0 +1,39 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmCTestHardwareAllocator_h +#define cmCTestHardwareAllocator_h + +#include <map> +#include <string> + +class cmCTestHardwareSpec; + +class cmCTestHardwareAllocator +{ +public: + struct Resource + { + unsigned int Total; + unsigned int Locked; + + unsigned int Free() const { return this->Total - this->Locked; } + + bool operator==(const Resource& other) const; + bool operator!=(const Resource& other) const; + }; + + void InitializeFromHardwareSpec(const cmCTestHardwareSpec& spec); + + const std::map<std::string, std::map<std::string, Resource>>& GetResources() + const; + + bool AllocateResource(const std::string& name, const std::string& id, + unsigned int slots); + bool DeallocateResource(const std::string& name, const std::string& id, + unsigned int slots); + +private: + std::map<std::string, std::map<std::string, Resource>> Resources; +}; + +#endif diff --git a/Tests/CMakeLib/CMakeLists.txt b/Tests/CMakeLib/CMakeLists.txt index 901f097..c24b64c 100644 --- a/Tests/CMakeLib/CMakeLists.txt +++ b/Tests/CMakeLib/CMakeLists.txt @@ -8,6 +8,7 @@ include_directories( set(CMakeLib_TESTS testArgumentParser.cxx testCTestProcesses.cxx + testCTestHardwareAllocator.cxx testCTestHardwareSpec.cxx testGeneratedFileStream.cxx testRST.cxx 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; +} |