diff --git a/bootstrap/include/bootstrap/build_buildcc.h b/bootstrap/include/bootstrap/build_buildcc.h index 7dcb9aee..4f0d59e7 100644 --- a/bootstrap/include/bootstrap/build_buildcc.h +++ b/bootstrap/include/bootstrap/build_buildcc.h @@ -77,7 +77,7 @@ class BuildBuildCC { const BaseToolchain &toolchain_; TargetEnv env_; - PersistentStorage storage_; + ScopedStorage storage_; }; } // namespace buildcc diff --git a/buildcc/buildcc.h b/buildcc/buildcc.h index 0959cea4..227d9ce0 100644 --- a/buildcc/buildcc.h +++ b/buildcc/buildcc.h @@ -27,6 +27,7 @@ #include "env/host_compiler.h" #include "env/util.h" #include "env/command.h" +#include "env/storage.h" // Base #include "toolchain/toolchain.h" @@ -57,6 +58,5 @@ // BuildCC Modules #include "args/args.h" #include "args/register.h" -#include "args/persistent_storage.h" #endif diff --git a/buildcc/lib/args/CMakeLists.txt b/buildcc/lib/args/CMakeLists.txt index 5b5843fa..6535b1f3 100644 --- a/buildcc/lib/args/CMakeLists.txt +++ b/buildcc/lib/args/CMakeLists.txt @@ -41,20 +41,12 @@ target_link_libraries(test_register PRIVATE mock_args ) -add_executable(test_persistent_storage - test/test_persistent_storage.cpp -) -target_link_libraries(test_persistent_storage PRIVATE mock_args) - add_test(NAME test_args COMMAND test_args WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/test ) add_test(NAME test_register COMMAND test_register WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/test ) -add_test(NAME test_persistent_storage COMMAND test_persistent_storage - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/test -) endif() set(ARGS_SRCS @@ -64,7 +56,6 @@ set(ARGS_SRCS src/tasks.cpp include/args/args.h include/args/register.h - include/args/persistent_storage.h ) if(${BUILDCC_BUILD_AS_SINGLE_LIB}) diff --git a/buildcc/lib/args/test/test_persistent_storage.cpp b/buildcc/lib/args/test/test_persistent_storage.cpp deleted file mode 100644 index 56163d43..00000000 --- a/buildcc/lib/args/test/test_persistent_storage.cpp +++ /dev/null @@ -1,60 +0,0 @@ -#include "args/persistent_storage.h" - -#include "target/generator.h" -#include "target/target.h" - -// NOTE, Make sure all these includes are AFTER the system and header includes -#include "CppUTest/CommandLineTestRunner.h" -#include "CppUTest/MemoryLeakDetectorNewMacros.h" -#include "CppUTest/TestHarness.h" -#include "CppUTest/Utest.h" -#include "CppUTestExt/MockSupport.h" - -// clang-format off -TEST_GROUP(PersistentStorageTestGroup) -{ -}; -// clang-format on - -static buildcc::BaseToolchain gcc(buildcc::ToolchainId::Gcc, "gcc", "as", "gcc", - "g++", "ar", "ld"); - -TEST(PersistentStorageTestGroup, BasicUsage) { - buildcc::PersistentStorage persistent; - persistent.Add("target_identifier", "target_name", - buildcc::TargetType::Executable, gcc, ""); - persistent.Add("generator_identifier", - "generator_name", ""); - - // Usage - persistent.ConstRef("target_identifier").GetName(); - persistent.Ref("generator_identifier").GetTaskflow(); - - // Automatic cleanup here -} - -TEST(PersistentStorageTestGroup, IncorrectUsage) { - buildcc::PersistentStorage persistent; - persistent.Add("target_identifier", "target_name", - buildcc::TargetType::Executable, gcc, ""); - - // We try to cast to a different type! - CHECK_THROWS(std::exception, - persistent.Ref("target_identifier")); - - // We use a wrong identifier - CHECK_THROWS(std::exception, - persistent.Ref("generator_identifier")); -} - -std::string &toReference(std::string *pointer) { return *pointer; } - -TEST(PersistentStorageTestGroup, NullptrDelete) { - buildcc::PersistentStorage persistent; - persistent.Remove(nullptr); -} - -int main(int ac, char **av) { - buildcc::Project::Init(fs::current_path(), fs::current_path()); - return CommandLineTestRunner::RunAllTests(ac, av); -} diff --git a/buildcc/lib/env/CMakeLists.txt b/buildcc/lib/env/CMakeLists.txt index f76bcc34..f18d6b24 100644 --- a/buildcc/lib/env/CMakeLists.txt +++ b/buildcc/lib/env/CMakeLists.txt @@ -6,6 +6,7 @@ if (${TESTING}) src/env.cpp src/task_state.cpp + src/storage.cpp src/command.cpp mock/execute.cpp @@ -38,10 +39,14 @@ if (${TESTING}) add_executable(test_command test/test_command.cpp) target_link_libraries(test_command PRIVATE mock_env) + add_executable(test_storage test/test_storage.cpp) + target_link_libraries(test_storage PRIVATE mock_env) + add_test(NAME test_static_project COMMAND test_static_project) add_test(NAME test_env_util COMMAND test_env_util) add_test(NAME test_task_state COMMAND test_task_state) add_test(NAME test_command COMMAND test_command) + add_test(NAME test_storage COMMAND test_storage) endif() set(ENV_SRCS @@ -64,6 +69,9 @@ set(ENV_SRCS src/command.cpp src/execute.cpp include/env/command.h + + src/storage.cpp + include/env/storage.h ) if(${BUILDCC_BUILD_AS_SINGLE_LIB}) diff --git a/buildcc/lib/args/include/args/persistent_storage.h b/buildcc/lib/env/include/env/storage.h similarity index 70% rename from buildcc/lib/args/include/args/persistent_storage.h rename to buildcc/lib/env/include/env/storage.h index 573c0172..ccd1d1c9 100644 --- a/buildcc/lib/args/include/args/persistent_storage.h +++ b/buildcc/lib/env/include/env/storage.h @@ -14,10 +14,11 @@ * limitations under the License. */ -#ifndef ARGS_PERSISTENT_STORAGE_H_ -#define ARGS_PERSISTENT_STORAGE_H_ +#ifndef ENV_STORAGE_H_ +#define ENV_STORAGE_H_ #include +#include #include #include #include @@ -28,10 +29,10 @@ namespace buildcc { -class PersistentStorage { +class ScopedStorage { public: - PersistentStorage() {} - ~PersistentStorage() { + ScopedStorage() {} + ~ScopedStorage() { for (const auto &ptr_iter : ptrs_) { ptr_iter.second.destructor(); } @@ -39,6 +40,8 @@ class PersistentStorage { env::assert_fatal(ptrs_.empty(), "Memory not deallocated"); } + ScopedStorage(const ScopedStorage &) = delete; + template T &Add(const std::string &identifier, Params &&...params) { T *ptr = new T(std::forward(params)...); @@ -69,7 +72,7 @@ class PersistentStorage { // https://stackoverflow.com/questions/123758/how-do-i-remove-code-duplication-between-similar-const-and-non-const-member-func/123995 template T &Ref(const std::string &identifier) { return const_cast( - static_cast(*this).ConstRef(identifier)); + static_cast(*this).ConstRef(identifier)); } private: @@ -90,6 +93,34 @@ class PersistentStorage { std::unordered_map ptrs_; }; +class Storage { +public: + Storage() = delete; + Storage(const Storage &) = delete; + Storage(Storage &&) = delete; + + static void Init() { internal_ = std::make_unique(); } + static void Deinit() { internal_.reset(nullptr); } + + template + static T &Add(const std::string &identifier, Params &&...params) { + return internal_->Add(identifier, + std::forward(params)...); + } + + template + static const T &ConstRef(const std::string &identifier) { + return internal_->ConstRef(identifier); + } + + template static T &Ref(const std::string &identifier) { + return internal_->Ref(identifier); + } + +private: + static std::unique_ptr internal_; +}; + } // namespace buildcc #endif diff --git a/buildcc/lib/env/src/storage.cpp b/buildcc/lib/env/src/storage.cpp new file mode 100644 index 00000000..37bae38b --- /dev/null +++ b/buildcc/lib/env/src/storage.cpp @@ -0,0 +1,23 @@ +/* + * Copyright 2021-2022 Niket Naidu. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "env/storage.h" + +namespace buildcc { + +std::unique_ptr Storage::internal_; + +} diff --git a/buildcc/lib/env/test/test_storage.cpp b/buildcc/lib/env/test/test_storage.cpp new file mode 100644 index 00000000..ccd4be83 --- /dev/null +++ b/buildcc/lib/env/test/test_storage.cpp @@ -0,0 +1,91 @@ +#include "env/storage.h" + +// NOTE, Make sure all these includes are AFTER the system and header includes +#include "CppUTest/CommandLineTestRunner.h" +#include "CppUTest/MemoryLeakDetectorNewMacros.h" +#include "CppUTest/TestHarness.h" +#include "CppUTest/Utest.h" +#include "CppUTestExt/MockSupport.h" + +// clang-format off +TEST_GROUP(ScopedStorageTestGroup) +{ +}; + +TEST_GROUP(StorageTestGroup) +{ + void setup() { + buildcc::Storage::Init(); + } + void teardown() { + buildcc::Storage::Deinit(); + } +}; +// clang-format on + +class BigObj {}; + +class BigObjWithParameters { +public: + BigObjWithParameters(const std::string &name, int id, const BigObj &obj) + : name_(name) { + (void)id; + (void)obj; + } + + const std::string &GetName() const { return name_; } + +private: + std::string name_; +}; + +static BigObj obj; + +TEST(ScopedStorageTestGroup, BasicUsage) { + buildcc::ScopedStorage storage; + storage.Add("identifier", "name", 10, obj); + storage.Add("identifier2", "name2", 12, obj); + + // Usage + storage.ConstRef("identifier").GetName(); + storage.Ref("identifier2").GetName(); + + // Automatic cleanup here +} + +TEST(ScopedStorageTestGroup, IncorrectUsage) { + buildcc::ScopedStorage storage; + storage.Add("identifier", "name", 10, obj); + + // We try to cast to a different type! + CHECK_THROWS(std::exception, storage.Ref("identifier")); + + // We use a wrong identifier + CHECK_THROWS(std::exception, + storage.Ref("identifier2")); +} + +std::string &toReference(std::string *pointer) { return *pointer; } + +TEST(ScopedStorageTestGroup, NullptrDelete) { + buildcc::ScopedStorage storage; + storage.Remove(nullptr); +} + +TEST(StorageTestGroup, BasicUsage) { + buildcc::Storage::Add("identifier", "name", 10, obj); + buildcc::Storage::Add("identifier2", "name2", 12, obj); + + // Usage + const auto &bigobj = + buildcc::Storage::ConstRef("identifier").GetName(); + const auto &bigobj2 = + buildcc::Storage::Ref("identifier2").GetName(); + + STRCMP_EQUAL(bigobj.c_str(), "name"); + STRCMP_EQUAL(bigobj2.c_str(), "name2"); +} + +int main(int ac, char **av) { + return CommandLineTestRunner::RunAllTests(ac, av); +} diff --git a/buildexe/include/buildexe/build_env_setup.h b/buildexe/include/buildexe/build_env_setup.h index e36983d4..f76fd9fc 100644 --- a/buildexe/include/buildexe/build_env_setup.h +++ b/buildexe/include/buildexe/build_env_setup.h @@ -66,7 +66,7 @@ class BuildEnvSetup { const BuildExeArgs &buildexe_args_; ArgToolchainState state_; - PersistentStorage storage_; + ScopedStorage storage_; }; } // namespace buildcc