File indexing completed on 2024-05-19 05:42:02

0001 // ct_lvtclp_fileupdatemgr_physical.t.cpp                             -*-C++-*-
0002 
0003 /*
0004 // Copyright 2023 Codethink Ltd <codethink@codethink.co.uk>
0005 // SPDX-License-Identifier: Apache-2.0
0006 //
0007 // Licensed under the Apache License, Version 2.0 (the "License");
0008 // you may not use this file except in compliance with the License.
0009 // You may obtain a copy of the License at
0010 //
0011 //     http://www.apache.org/licenses/LICENSE-2.0
0012 //
0013 // Unless required by applicable law or agreed to in writing, software
0014 // distributed under the License is distributed on an "AS IS" BASIS,
0015 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0016 // See the License for the specific language governing permissions and
0017 // limitations under the License.
0018 */
0019 
0020 #include <ct_lvtmdb_fileobject.h>
0021 #include <ct_lvtmdb_objectstore.h>
0022 
0023 #include <ct_lvtclp_cpp_tool.h>
0024 #include <ct_lvtclp_testutil.h>
0025 
0026 #include <filesystem>
0027 #include <initializer_list>
0028 #include <vector>
0029 
0030 #include <catch2-local-includes.h>
0031 
0032 using namespace Codethink::lvtclp;
0033 using namespace Codethink::lvtmdb;
0034 
0035 const PyDefaultGilReleasedContext defaultGilContextForTesting;
0036 
0037 static void createTop(const std::filesystem::path& topLevel)
0038 {
0039     bool created = std::filesystem::create_directories(topLevel / "groups/one/onetop");
0040     REQUIRE(created);
0041 
0042     Test_Util::createFile(topLevel / "groups/one/onetop/onetop_top.h", R"(
0043 // onetop_top.h
0044 
0045 namespace onetop {
0046 
0047 class Top {
0048   public:
0049     int method();
0050 };
0051 
0052 })");
0053 
0054     Test_Util::createFile(topLevel / "groups/one/onetop/onetop_top.cpp", R"(
0055 // onetop_top.cpp
0056 
0057 #include <onetop_top.h>
0058 
0059 namespace onetop {
0060 
0061 int Top::method()
0062 {
0063     return 2;
0064 }
0065 
0066 })");
0067 }
0068 
0069 static void createDep(const std::filesystem::path& topLevel)
0070 {
0071     assert(std::filesystem::create_directories(topLevel / "groups/one/onedep"));
0072 
0073     Test_Util::createFile(topLevel / "groups/one/onedep/onedep_dep.h", R"(
0074 // onedep_dep.h
0075 
0076 #include <onetop_top.h>
0077 
0078 namespace onedep {
0079 
0080 class Dep {
0081     onetop::Top top;
0082 
0083     int method();
0084 };
0085 
0086 })");
0087     Test_Util::createFile(topLevel / "groups/one/onedep/onedep_dep.cpp", R"(
0088 // onedep_dep.cpp
0089 
0090 #include <onedep_dep.h>
0091 
0092 namespace onedep {
0093 
0094 int Dep::method()
0095 {
0096     return top.method();
0097 }
0098 
0099 })");
0100 }
0101 
0102 struct PhysicalFileUpdateManagerFixture {
0103     PhysicalFileUpdateManagerFixture():
0104         topLevel(std::filesystem::temp_directory_path() / "ct_lvtclp_fileupdatemgr_physical_test")
0105     {
0106         if (std::filesystem::exists(topLevel)) {
0107             REQUIRE(std::filesystem::remove_all(topLevel));
0108         }
0109 
0110         createTop(topLevel);
0111         createDep(topLevel);
0112     }
0113 
0114     ~PhysicalFileUpdateManagerFixture()
0115     {
0116         REQUIRE(std::filesystem::remove_all(topLevel));
0117     }
0118 
0119     std::filesystem::path topLevel;
0120 };
0121 
0122 void checkDatabaseOriginal(ObjectStore& session)
0123 // check the database before any files are removed
0124 {
0125     const std::initializer_list<ModelUtil::SourceFileModel> files = {{"groups/one/onedep/onedep_dep.cpp",
0126                                                                       false,
0127                                                                       "groups/one/onedep",
0128                                                                       "groups/one/onedep/onedep_dep",
0129                                                                       {"onedep"},
0130                                                                       {},
0131                                                                       {"groups/one/onedep/onedep_dep.h"}},
0132                                                                      {"groups/one/onedep/onedep_dep.h",
0133                                                                       true,
0134                                                                       "groups/one/onedep",
0135                                                                       "groups/one/onedep/onedep_dep",
0136                                                                       {"onedep"},
0137                                                                       {"onedep::Dep"},
0138                                                                       {"groups/one/onetop/onetop_top.h"}},
0139                                                                      {"groups/one/onetop/onetop_top.cpp",
0140                                                                       false,
0141                                                                       "groups/one/onetop",
0142                                                                       "groups/one/onetop/onetop_top",
0143                                                                       {"onetop"},
0144                                                                       {},
0145                                                                       {"groups/one/onetop/onetop_top.h"}},
0146                                                                      {"groups/one/onetop/onetop_top.h",
0147                                                                       true,
0148                                                                       "groups/one/onetop",
0149                                                                       "groups/one/onetop/onetop_top",
0150                                                                       {"onetop"},
0151                                                                       {"onetop::Top"},
0152                                                                       {}}};
0153 
0154     const std::initializer_list<ModelUtil::ComponentModel> comps = {
0155         {"groups/one/onedep/onedep_dep",
0156          "onedep_dep",
0157          {"groups/one/onedep/onedep_dep.h", "groups/one/onedep/onedep_dep.cpp"},
0158          {"groups/one/onetop/onetop_top"}},
0159         {"groups/one/onetop/onetop_top",
0160          "onetop_top",
0161          {"groups/one/onetop/onetop_top.h", "groups/one/onetop/onetop_top.cpp"},
0162          {}},
0163     };
0164 
0165     const std::initializer_list<ModelUtil::PackageModel> pkgs = {
0166         {"groups/one/onedep", "groups/one", {"onedep::Dep"}, {"groups/one/onedep/onedep_dep"}, {"groups/one/onetop"}},
0167         {"groups/one/onetop", "groups/one", {"onetop::Top"}, {"groups/one/onetop/onetop_top"}, {}}};
0168 
0169     const std::initializer_list<ModelUtil::UDTModel> udts = {
0170         {
0171             "onedep::Dep",
0172             "onedep",
0173             "groups/one/onedep",
0174             {"onetop::Top"},
0175             {},
0176             {},
0177             {"onedep::Dep::method"},
0178             {"onedep::Dep::top"},
0179         },
0180         {
0181             "onetop::Top",
0182             "onetop",
0183             "groups/one/onetop",
0184             {},
0185             {},
0186             {},
0187             {"onetop::Top::method"},
0188             {},
0189         },
0190     };
0191 
0192     ModelUtil::checkSourceFiles(session, files);
0193     ModelUtil::checkComponents(session, comps);
0194     ModelUtil::checkPackages(session, pkgs);
0195     ModelUtil::checkUDTs(session, udts);
0196 }
0197 
0198 void checkDatabaseDepDeleted(ObjectStore& session)
0199 // check the database after onedep_dep.h is deleted
0200 {
0201     const std::initializer_list<ModelUtil::SourceFileModel> files = {
0202         // onedep_dep.h deleted
0203         // onedep_dep.cpp deleted because it includes onedep_dep.h
0204         {"groups/one/onetop/onetop_top.cpp",
0205          false,
0206          "groups/one/onetop",
0207          "groups/one/onetop/onetop_top",
0208          {"onetop"},
0209          {},
0210          {"groups/one/onetop/onetop_top.h"}},
0211         {"groups/one/onetop/onetop_top.h",
0212          true,
0213          "groups/one/onetop",
0214          "groups/one/onetop/onetop_top",
0215          {"onetop"},
0216          {"onetop::Top"},
0217          {}}};
0218     const std::initializer_list<ModelUtil::ComponentModel> comps = {
0219         {"groups/one/onetop/onetop_top",
0220          "onetop_top",
0221          {"groups/one/onetop/onetop_top.h", "groups/one/onetop/onetop_top.cpp"},
0222          {}},
0223     };
0224     const std::initializer_list<ModelUtil::PackageModel> pkgs = {
0225         {"groups/one/onedep",
0226          "groups/one",
0227          {/*onedep::Dep deleted*/},
0228          {/*onedep_dep deleted*/},
0229          {/*depenency deleted*/}},
0230         {"groups/one/onetop", "groups/one", {"onetop::Top"}, {"groups/one/onetop/onetop_top"}, {}}};
0231     const std::initializer_list<ModelUtil::UDTModel> udts = {
0232         // onedep::Dep deleted
0233         {
0234             "onetop::Top",
0235             "onetop",
0236             "groups/one/onetop",
0237             {},
0238             {},
0239             {},
0240             {"onetop::Top::method"},
0241             {},
0242         },
0243     };
0244 
0245     ModelUtil::checkSourceFiles(session, files);
0246     ModelUtil::checkComponents(session, comps);
0247     ModelUtil::checkPackages(session, pkgs);
0248     ModelUtil::checkUDTs(session, udts);
0249 }
0250 
0251 void checkDatabaseTopDeleted(ObjectStore& session)
0252 // check the database after onetop_top.cpp is deleted
0253 {
0254     const std::initializer_list<ModelUtil::SourceFileModel> files = {{"groups/one/onedep/onedep_dep.cpp",
0255                                                                       false,
0256                                                                       "groups/one/onedep",
0257                                                                       "groups/one/onedep/onedep_dep",
0258                                                                       {"onedep"},
0259                                                                       {},
0260                                                                       {"groups/one/onedep/onedep_dep.h"}},
0261                                                                      {"groups/one/onedep/onedep_dep.h",
0262                                                                       true,
0263                                                                       "groups/one/onedep",
0264                                                                       "groups/one/onedep/onedep_dep",
0265                                                                       {"onedep"},
0266                                                                       {"onedep::Dep"},
0267                                                                       {"groups/one/onetop/onetop_top.h"}},
0268                                                                      //      onetop_top.cpp deleted
0269                                                                      {"groups/one/onetop/onetop_top.h",
0270                                                                       true,
0271                                                                       "groups/one/onetop",
0272                                                                       "groups/one/onetop/onetop_top",
0273                                                                       {"onetop"},
0274                                                                       {"onetop::Top"},
0275                                                                       {}}};
0276 
0277     const std::initializer_list<ModelUtil::ComponentModel> comps = {
0278         {"groups/one/onedep/onedep_dep",
0279          "onedep_dep",
0280          {"groups/one/onedep/onedep_dep.h", "groups/one/onedep/onedep_dep.cpp"},
0281          {"groups/one/onetop/onetop_top"}},
0282         {"groups/one/onetop/onetop_top", "onetop_top", {"groups/one/onetop/onetop_top.h"}, {}},
0283     };
0284 
0285     const std::initializer_list<ModelUtil::PackageModel> pkgs = {
0286         {"groups/one/onedep", "groups/one", {"onedep::Dep"}, {"groups/one/onedep/onedep_dep"}, {"groups/one/onetop"}},
0287         {"groups/one/onetop", "groups/one", {"onetop::Top"}, {"groups/one/onetop/onetop_top"}, {}}};
0288 
0289     const std::initializer_list<ModelUtil::UDTModel> udts = {
0290         {
0291             "onedep::Dep",
0292             "onedep",
0293             "groups/one/onedep",
0294             {"onetop::Top"},
0295             {},
0296             {},
0297             {"onedep::Dep::method"},
0298             {"onedep::Dep::top"},
0299         },
0300         {
0301             "onetop::Top",
0302             "onetop",
0303             "groups/one/onetop",
0304             {},
0305             {},
0306             {},
0307             {"onetop::Top::method"},
0308             {},
0309         },
0310     };
0311 
0312     ModelUtil::checkSourceFiles(session, files);
0313     ModelUtil::checkComponents(session, comps);
0314     ModelUtil::checkPackages(session, pkgs);
0315     ModelUtil::checkUDTs(session, udts);
0316 }
0317 
0318 TEST_CASE_METHOD(PhysicalFileUpdateManagerFixture, "File update manager physical")
0319 {
0320     StaticCompilationDatabase cmds({{"groups/one/onetop/onetop_top.cpp", "build/onetop_top.o"},
0321                                     {"groups/one/onedep/onedep_dep.cpp", "build/onedep_dep.o"}},
0322                                    "placeholder",
0323                                    {"-Igroups/one/onetop", "-Igroups/one/onedep"},
0324                                    topLevel);
0325 
0326     INFO("Using top level tmp path = '" << topLevel.string() << "'");
0327     CppTool tool(topLevel, cmds, ":memory:");
0328     REQUIRE(tool.runFull());
0329 
0330     ObjectStore& session = tool.getObjectStore();
0331 
0332     // remove onedep_dep.h from the database and check the right things change
0333     {
0334         FileObject *depH = nullptr;
0335         session.withROLock([&] {
0336             depH = session.getFile("groups/one/onedep/onedep_dep.h");
0337         });
0338         REQUIRE(depH);
0339         session.withRWLock([&] {
0340             auto removedFiles = std::set<intptr_t>{};
0341             session.removeFile(depH, removedFiles);
0342         });
0343         checkDatabaseDepDeleted(session);
0344     }
0345 
0346     // reparse the files removed by the fileUpdateMgr and check the database
0347     // is restored
0348     {
0349         session.withRWLock([&] {
0350             session.clear();
0351         });
0352         REQUIRE(tool.runFull());
0353         checkDatabaseOriginal(session);
0354     }
0355 
0356     // remove onedep_top.cpp from the database and check the right things change
0357     {
0358         FileObject *top = nullptr;
0359         session.withROLock([&] {
0360             top = session.getFile("groups/one/onetop/onetop_top.cpp");
0361         });
0362         REQUIRE(top);
0363         session.withRWLock([&] {
0364             auto removedFiles = std::set<intptr_t>{};
0365             session.removeFile(top, removedFiles);
0366         });
0367         checkDatabaseTopDeleted(session);
0368     }
0369 }