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 }