From d87acfc66fa54fff2c78decf162a0e0c47f22c26 Mon Sep 17 00:00:00 2001 From: Evgueni Driouk Date: Fri, 1 Sep 2023 11:54:53 +0200 Subject: [PATCH] Pack reqs (#679) * [csolution] package requirements info are not taken into account? #659 --------- Co-authored-by: Evgueni Driouk Co-authored-by: Daniel Brondani --- libs/rtemodel/include/RteCprjProject.h | 7 + libs/rtemodel/include/RteKernel.h | 23 +++ libs/rtemodel/include/RtePackage.h | 48 ++++- libs/rtemodel/include/RteProject.h | 7 + libs/rtemodel/src/RteCprjProject.cpp | 11 ++ libs/rtemodel/src/RteKernel.cpp | 85 ++++++++- libs/rtemodel/src/RtePackage.cpp | 27 +++ libs/rtemodel/src/RteProject.cpp | 22 ++- libs/rtemodel/test/src/RteChkTest.cpp | 8 +- libs/rtemodel/test/src/RteModelTest.cpp | 54 +++++- libs/rtemodel/test/src/RteModelTestConfig.cpp | 1 + libs/rtemodel/test/src/RteModelTestConfig.h | 1 + .../1.0.0/ARM.RteTestRequired.pdsc | 22 +++ .../1.0.0/ARM.RteTestRequiredRecursive.pdsc | 22 +++ .../RteTest_DFP/0.2.0/ARM.RteTest_DFP.pdsc | 1 - .../projects/RteTestM3/RteTestM3_PackReq.cprj | 76 ++++++++ tools/projmgr/include/ProjMgrKernel.h | 16 -- tools/projmgr/src/ProjMgrKernel.cpp | 81 -------- tools/projmgr/src/ProjMgrWorker.cpp | 36 +++- .../test_pack_requirements.csolution.yml | 22 +++ tools/projmgr/test/src/ProjMgrTestEnv.cpp | 40 ++++ tools/projmgr/test/src/ProjMgrTestEnv.h | 7 +- tools/projmgr/test/src/ProjMgrUnitTests.cpp | 177 ++++++++++-------- .../test/src/ProjMgrWorkerUnitTests.cpp | 2 +- 24 files changed, 595 insertions(+), 201 deletions(-) create mode 100644 test/packs/ARM/RteTestRequired/1.0.0/ARM.RteTestRequired.pdsc create mode 100644 test/packs/ARM/RteTestRequiredRecursive/1.0.0/ARM.RteTestRequiredRecursive.pdsc create mode 100644 test/projects/RteTestM3/RteTestM3_PackReq.cprj create mode 100644 tools/projmgr/test/data/TestSolution/test_pack_requirements.csolution.yml diff --git a/libs/rtemodel/include/RteCprjProject.h b/libs/rtemodel/include/RteCprjProject.h index f940a9cdd..d2db8484a 100644 --- a/libs/rtemodel/include/RteCprjProject.h +++ b/libs/rtemodel/include/RteCprjProject.h @@ -66,6 +66,13 @@ class RteCprjProject : public RteProject */ void Initialize() override; + /** + * @brief get all packs required in the specified target + * @param packs collection of package IDs mapped to RtePackage pointers to fill + * @param targetName target name + */ + void GetRequiredPacks(RtePackageMap& packs, const std::string& targetName) const override; + public: /** * @brief set toolchain for the project diff --git a/libs/rtemodel/include/RteKernel.h b/libs/rtemodel/include/RteKernel.h index 2200af8e1..18e5a34ee 100644 --- a/libs/rtemodel/include/RteKernel.h +++ b/libs/rtemodel/include/RteKernel.h @@ -173,6 +173,29 @@ class RteKernel */ static RteKernel* GetNullKernel() { return &NULL_RTE_KERNEL; } + /** + * @brief get installed packs + * @param pdscFiles list of installed packs + * @param bool latest get only latest versions (default true) + */ + bool GetInstalledPacks(std::list& pdscFiles, bool latest = true); + + /** + * @brief load and insert pack into global model + * @param packs list of loaded packages + * @param pdscFiles list of packs to be loaded + * @return true if executed successfully + */ + bool LoadAndInsertPacks(std::list& packs, std::list& pdscFiles); + + /** + * @brief get list of installed pdsc files + * @param files collection to fill with absolute pdsc filenames; + * @param bool latest get only latest versions (default true) + * @param rtePath pack path + */ + static void GetInstalledPdscFiles(std::list& files, const std::string& rtePath, bool latest = true); + /** * @brief getter for pdsc file determined by pack ID, pack path and pack attributes * @param attributes pack attributes diff --git a/libs/rtemodel/include/RtePackage.h b/libs/rtemodel/include/RtePackage.h index c9931bdb9..8e950838c 100644 --- a/libs/rtemodel/include/RtePackage.h +++ b/libs/rtemodel/include/RtePackage.h @@ -20,11 +20,16 @@ class RteTarget; class RtePackage; +class RtePackageComparator; class RteExample; class RteGeneratorContainer; class RteGeneratorProject; class RteBoard; + +typedef std::map RtePackageMap; +typedef std::map RteItemPackageMap; + /** * @brief class representing element in *.pdsc files */ @@ -150,6 +155,16 @@ class RtePackage : public RteRootItem */ static int ComparePackageIDs(const std::string& id1, const std::string& id2); + /** + * @brief helper static method to compare pack filenames. + * Alpha-numeric comparison for vendor and name. + * Semantic version comparison for pack version. + * @param pdsc1 first pdsc file path + * @param pdsc2 second pdsc file path + * @return 0 if both files are equal, less than 0 if pdsc1 < pdsc2, greater than 0 if pdsc1 > pdsc2 + */ + static int ComparePdscFileNames(const std::string& pdsc1, const std::string& pdsc2); + /** * @brief get pack display name * @return display string @@ -417,12 +432,28 @@ class RtePackage : public RteRootItem public: + /** + * @brief get collection of packs required by this one + * @param map of id to RtePackage pointers to fill + * @param model pointer to RteModel to resolve requirement + */ + void GetRequiredPacks(RtePackageMap& packs, RteModel* model) const; + /** * @brief get list of packs required by this one * @return list of pointers to RteItem objects with pack requirement information */ virtual const Collection& GetPackRequirements() const; + /** + * @brief resolve packs for specified requirements + * @param originatingItem RteItem* supplying requirements, can be NULL + * @param requirements collection of RteItem pointers representing requirements + * @param RtePackageMap to fill + * @param model pointer to RteModel to resolve requirement + */ + static void ResolveRequiredPacks(const RteItem* originatingItem, const Collection& requirements, RtePackageMap& packs, RteModel* model); + /** * @brief get list of language requirements imposed by this pack * @return list of pointers to RteItem objects with language requirement information @@ -651,9 +682,22 @@ class RtePackageComparator bool operator()(const std::string& a, const std::string& b) const { return RtePackage::ComparePackageIDs(a, b) < 0; } }; +/** + * @brief helper compare class for sorted pack maps + * compares common ID alpha-numerically in ascending order and version semantically in descending order +*/ +class RtePdscComparator +{ +public: + /** + * @brief compare two pdsc file names by their pack IDs + * @param a first absolute pdsc file name + * @param b second absolute pdsc file name + * @return true if first pack is 'less' than the second one + */ + bool operator()(const std::string& a, const std::string& b) const { return RtePackage::ComparePdscFileNames(a, b) < 0; } +}; -typedef std::map RtePackageMap; -typedef std::map RteItemPackageMap; /** * @brief class that replicates frequently used information of a pack object or a pack release. diff --git a/libs/rtemodel/include/RteProject.h b/libs/rtemodel/include/RteProject.h index ecfc4be8c..64f14066e 100644 --- a/libs/rtemodel/include/RteProject.h +++ b/libs/rtemodel/include/RteProject.h @@ -410,6 +410,13 @@ class RteProject : public RteRootItem */ void GetUsedPacks(RtePackageMap& packs, const std::string& targetName) const; + /** + * @brief get all packs required in the specified target + * @param packs collection of package IDs mapped to RtePackage pointers to fill + * @param targetName target name + */ + virtual void GetRequiredPacks(RtePackageMap& packs, const std::string& targetName) const; + /** * @brief get collection of RteGpdscInfo objects * @return collection of gpdsc files mapped to associated RteGpdscInfo pointers diff --git a/libs/rtemodel/src/RteCprjProject.cpp b/libs/rtemodel/src/RteCprjProject.cpp index 73d96036d..e07561edc 100644 --- a/libs/rtemodel/src/RteCprjProject.cpp +++ b/libs/rtemodel/src/RteCprjProject.cpp @@ -134,6 +134,17 @@ void RteCprjProject::Initialize() } } +void RteCprjProject::GetRequiredPacks(RtePackageMap& packs, const std::string& targetName) const +{ + RteTarget* t = GetTarget(targetName); + if (!t) + return; + CprjFile* cprjFile = GetCprjFile(); + + RtePackage::ResolveRequiredPacks(nullptr, cprjFile->GetPackRequirements(), packs, t->GetFilteredModel()); + RteProject::GetRequiredPacks(packs, targetName); +} + void RteCprjProject::FillToolchainAttributes(XmlItem &attributes) const{ if (m_toolchain == "AC5" || m_toolchain == "AC6") { diff --git a/libs/rtemodel/src/RteKernel.cpp b/libs/rtemodel/src/RteKernel.cpp index 735e38145..86db9d865 100644 --- a/libs/rtemodel/src/RteKernel.cpp +++ b/libs/rtemodel/src/RteKernel.cpp @@ -305,12 +305,6 @@ bool RteKernel::LoadRequiredPdscFiles(CprjFile* cprjFile) msg += packRequirement->GetPackageID(true); - const string& name = packRequirement->GetAttribute("name"); - const string& vendor = packRequirement->GetAttribute("vendor"); - const string& version = packRequirement->GetAttribute("version"); - msg += vendor + "." + name; - if (!version.empty()) - msg += "." + version; GetRteCallback()->Err("R821", msg, cprjFile->GetPackageFileName()); // TODO: install missing pack (not needed for web version) return false; @@ -332,7 +326,85 @@ bool RteKernel::LoadRequiredPdscFiles(CprjFile* cprjFile) return true; } +bool RteKernel::GetInstalledPacks(std::list& pdscFiles, bool latest) +{ + auto& cmsisPackRoot = GetCmsisPackRoot(); + if (cmsisPackRoot.empty()) { + return false; + } + RteKernel::GetInstalledPdscFiles(pdscFiles, GetCmsisPackRoot(), latest); + + // Find pdsc files from local repository + list localPdscUrls; + if (!GetLocalPacksUrls(GetCmsisPackRoot(), localPdscUrls)) { + return false; + } + for (const auto& localPdscUrl : localPdscUrls) { + list localPdscFiles; + RteFsUtils::GetPackageDescriptionFiles(localPdscFiles, localPdscUrl, 1); + // Insert local pdsc files first + pdscFiles.insert(pdscFiles.begin(), localPdscFiles.begin(), localPdscFiles.end()); + } + return true; +} + +bool RteKernel::LoadAndInsertPacks(std::list& packs, std::list& pdscFiles) { + RteGlobalModel* globalModel = GetGlobalModel(); + if (!globalModel) { + return false; + } + std::list newPacks; + pdscFiles.unique(); + for (const auto& pdscFile : pdscFiles) { + RtePackage* pack = LoadPack(pdscFile); + if (!pack) { + return false; + } + bool loaded = false; + for (const auto& loadedPack : packs) { + if (pack->GetPackageID() == loadedPack->GetPackageID()) { + loaded = true; + break; + } + } + if (!loaded) { + newPacks.push_back(pack); + } else { + delete pack; + } + } + + globalModel->InsertPacks(newPacks); + + // Track only packs that were actually inserted into the model + packs.clear(); + for (const auto& [_, pack] : globalModel->GetPackages()) { + packs.push_back(pack); + } + return true; +} + +void RteKernel::GetInstalledPdscFiles(list& files, const std::string& rtePath, bool latest) +{ + if (!latest) { + RteFsUtils::GetPackageDescriptionFiles(files, rtePath, 3); + files.sort(RtePdscComparator()); + } else { + list allFiles; + RteFsUtils::GetPackageDescriptionFiles(allFiles, rtePath, 3); + allFiles.sort(RtePdscComparator()); + string commonId; + for (auto& f : allFiles) { + string id = RtePackage::CommonIdFromId(RtePackage::PackIdFromPath(f)); + if (id == commonId) { + continue; // skip packs with the same common ID + } + commonId = id; + files.push_back(f); + } + } +} string RteKernel::GetInstalledPdscFile(const XmlItem& attributes, const string& rtePath, string& packId) { const string& name = attributes.GetAttribute("name"); @@ -347,7 +419,6 @@ string RteKernel::GetInstalledPdscFile(const XmlItem& attributes, const string& packId = RtePackage::ComposePackageID(vendor, name, installedVersion); return path + '/' + installedVersion + '/' + vendor + '.' + name + ".pdsc"; } - return RteUtils::EMPTY_STRING; } diff --git a/libs/rtemodel/src/RtePackage.cpp b/libs/rtemodel/src/RtePackage.cpp index 731b89001..a27045de7 100644 --- a/libs/rtemodel/src/RtePackage.cpp +++ b/libs/rtemodel/src/RtePackage.cpp @@ -282,6 +282,11 @@ int RtePackage::ComparePackageIDs(const string& a, const string& b) return VersionCmp::Compare(verB, verA); // reverse comparison! } +int RtePackage::ComparePdscFileNames(const std::string& pdsc1, const std::string& pdsc2) +{ + return ComparePackageIDs(PackIdFromPath(pdsc1), PackIdFromPath(pdsc2)); +} + RteItem* RtePackage::GetRelease(const string& version) const { if (m_releases == nullptr) { @@ -417,6 +422,28 @@ XMLTreeElement* RtePackage::CreatePackXmlTreeElement(XMLTreeElement* parent) con return package; } +void RtePackage::GetRequiredPacks(RtePackageMap& packs, RteModel* model) const +{ + RtePackage::ResolveRequiredPacks(this, GetPackRequirements(), packs, model); +} + +void RtePackage::ResolveRequiredPacks(const RteItem* originatingItem, + const Collection& requirements, RtePackageMap& packs, RteModel* model) +{ + for (auto item : requirements) { + string id = RtePackage::GetPackageIDfromAttributes(*item); + if (packs.find(id) != packs.end()) { + continue; // already in the map + } + RtePackage* pack = model ? model->GetPackage(*item) : nullptr; + packs[id] = pack; + if (pack && pack != originatingItem) { + pack->GetRequiredPacks(packs, model); + } + } +} + + const Collection& RtePackage::GetPackRequirements() const { return GetItemGrandChildren(m_requirements, "packages"); diff --git a/libs/rtemodel/src/RteProject.cpp b/libs/rtemodel/src/RteProject.cpp index a31aa47a4..4f046dfde 100644 --- a/libs/rtemodel/src/RteProject.cpp +++ b/libs/rtemodel/src/RteProject.cpp @@ -2493,19 +2493,33 @@ void RteProject::GetUsedPacks(RtePackageMap& packs, const string& targetName) co } } - - for (auto it = m_components.begin(); it != m_components.end(); it++) { - RteComponentInstance* ci = it->second; + for (auto [_, ci] : m_components) { if (!ci->IsUsedByTarget(targetName)) continue; RtePackage* pack = ci->GetEffectivePackage(targetName); if (pack) { const string& id = pack->GetID(); - packs[id] = pack; + if (packs.find(id) == packs.end()) { + packs[id] = pack; + } } } } +void RteProject::GetRequiredPacks(RtePackageMap& packs, const std::string& targetName) const +{ + RteTarget* t = GetTarget(targetName); + if (!t) + return; + RtePackageMap usedPacks; + GetUsedPacks(usedPacks, targetName); // get all used packs + // add required packs + RteModel* model = t->GetFilteredModel(); + for (auto [_, pack] : usedPacks) { + pack->GetRequiredPacks(packs, model); + } +} + bool RteProject::HasProjectGroup(const string& group) const { map::const_iterator it; diff --git a/libs/rtemodel/test/src/RteChkTest.cpp b/libs/rtemodel/test/src/RteChkTest.cpp index ac1bb34f5..c67206a08 100644 --- a/libs/rtemodel/test/src/RteChkTest.cpp +++ b/libs/rtemodel/test/src/RteChkTest.cpp @@ -15,7 +15,7 @@ using namespace std; TEST(RteChkTest, Summary) { -const string summary = "Collecting pdsc files 5 files found\n\ +const string summary = "Collecting pdsc files 7 files found\n\ Parsing XML passed\n\ \n\ Constructing Model passed\n\ @@ -25,8 +25,8 @@ Cleaning XML data\n\ Validating Model passed\n\ \n\ Summary:\n\ -Packs: 5\n\ -Generic: 1\n\ +Packs: 7\n\ +Generic: 3\n\ DFP: 3\n\ BSP: 1\n\ \n\ @@ -50,7 +50,7 @@ completed\n"; rteChk.AddFileDir(RteModelTestConfig::CMSIS_PACK_ROOT); int res = rteChk.RunCheckRte(); EXPECT_EQ(res, 0); - EXPECT_EQ(rteChk.GetPackCount(), 5); + EXPECT_EQ(rteChk.GetPackCount(), 7); EXPECT_EQ(rteChk.GetComponentCount(), 52); EXPECT_EQ(rteChk.GetDeviceCount(), 10); EXPECT_EQ(rteChk.GetBoardCount(), 13); diff --git a/libs/rtemodel/test/src/RteModelTest.cpp b/libs/rtemodel/test/src/RteModelTest.cpp index 71766a319..2d2ce9e0d 100644 --- a/libs/rtemodel/test/src/RteModelTest.cpp +++ b/libs/rtemodel/test/src/RteModelTest.cpp @@ -26,9 +26,17 @@ using namespace std; TEST(RteModelTest, LoadPacks) { RteKernelSlim rteKernel; // here just to instantiate XMLTree parser + list latestFiles; + EXPECT_FALSE(rteKernel.GetInstalledPacks(latestFiles, true)); + + rteKernel.SetCmsisPackRoot(RteModelTestConfig::CMSIS_PACK_ROOT); + + EXPECT_TRUE(rteKernel.GetInstalledPacks(latestFiles, true)); + EXPECT_EQ(latestFiles.size(), 6); + list files; - RteFsUtils::GetPackageDescriptionFiles(files, RteModelTestConfig::CMSIS_PACK_ROOT, 3); - EXPECT_TRUE(files.size() > 0); + rteKernel.GetInstalledPacks(files, false); + EXPECT_EQ(files.size(), 7); RteModel* rteModel = rteKernel.GetGlobalModel(); ASSERT_NE(rteModel, nullptr); @@ -41,6 +49,18 @@ TEST(RteModelTest, LoadPacks) { bool rteModelValidateResult = rteModel->Validate(); EXPECT_TRUE(rteModelValidateResult); + RtePackage* pack = rteModel->GetPackage("ARM::RteTest@0.1.0"); + ASSERT_TRUE(pack != nullptr); + RtePackageMap requiredPacks; + pack->GetRequiredPacks(requiredPacks, rteModel); + EXPECT_EQ(requiredPacks.size(), 1); + + // do not clean requiredPacks + pack = rteModel->GetPackage("ARM::RteTestRequired@1.0.0"); + ASSERT_TRUE(pack != nullptr); + pack->GetRequiredPacks(requiredPacks, rteModel); + EXPECT_EQ(requiredPacks.size(), 4); + RteDeviceItemAggregate* da = rteModel->GetDeviceAggregate("RteTest_ARMCM3", "ARM:82"); ASSERT_NE(da, nullptr); // test deprecated memory attributes: IROM and IRAM @@ -61,7 +81,7 @@ TEST(RteModelTest, LoadPacks) { Collection mems; EXPECT_EQ(board->GetMemories(mems).size(), 2); - RtePackage* pack = board->GetPackage(); + pack = board->GetPackage(); ASSERT_TRUE(pack != nullptr); RtePackageInfo pi(pack); EXPECT_TRUE(pi.HasAttribute("description")); @@ -361,6 +381,34 @@ TEST_F(RteModelPrjTest, LoadCprj) { ASSERT_NE(fi, nullptr); EXPECT_EQ(fi->GetInfoString(activeTarget->GetName()), "RTE/Device/RteTest_ARMCM3/system_ARMCM3.c@1.0.1 (update@1.2.2) from ARM::Device:Startup&RteTest Startup@2.0.3"); + + RtePackageMap usedPacks; + activeCprjProject->GetUsedPacks(usedPacks, activeTarget->GetName()); + EXPECT_EQ(usedPacks.size(), 2); + + RtePackageMap requiredPacks; + activeCprjProject->GetRequiredPacks(requiredPacks, activeTarget->GetName()); + // requirements overlap => more than used + EXPECT_EQ(requiredPacks.size(), 3); +} + +TEST_F(RteModelPrjTest, LoadCprjPacReq) { + + RteKernelSlim rteKernel; + rteKernel.SetCmsisPackRoot(RteModelTestConfig::CMSIS_PACK_ROOT); + RteCprjProject* loadedCprjProject = rteKernel.LoadCprj(RteTestM3PackReq_cprj); + ASSERT_NE(loadedCprjProject, nullptr); + RteTarget* activeTarget = loadedCprjProject->GetActiveTarget(); + ASSERT_NE(activeTarget, nullptr); + + RtePackageMap usedPacks; + loadedCprjProject->GetUsedPacks(usedPacks, activeTarget->GetName()); + EXPECT_EQ(usedPacks.size(), 2); + + RtePackageMap requiredPacks; + loadedCprjProject->GetRequiredPacks(requiredPacks, activeTarget->GetName()); + // requirements overlap and not all loaded => more than used + EXPECT_EQ(requiredPacks.size(), 6); } TEST_F(RteModelPrjTest, LoadCprj_NoRTEFileCreation) { diff --git a/libs/rtemodel/test/src/RteModelTestConfig.cpp b/libs/rtemodel/test/src/RteModelTestConfig.cpp index 0d5d25616..01c9c0246 100644 --- a/libs/rtemodel/test/src/RteModelTestConfig.cpp +++ b/libs/rtemodel/test/src/RteModelTestConfig.cpp @@ -22,6 +22,7 @@ const std::string RteModelTestConfig::prjsDir = "RteModelTestProjects"; const std::string RteModelTestConfig::localRepoDir = "RteModelLocalRepo"; const std::string RteModelTestConfig::RteTestM3 = "/RteTestM3"; const std::string RteModelTestConfig::RteTestM3_cprj = prjsDir + RteTestM3 + "/RteTestM3.cprj"; +const std::string RteModelTestConfig::RteTestM3PackReq_cprj = prjsDir + RteTestM3 + "/RteTestM3_PackReq.cprj"; const std::string RteModelTestConfig::RteTestM3_ConfigFolder_cprj = prjsDir + RteTestM3 + "/RteTestM3_ConfigFolder.cprj"; const std::string RteModelTestConfig::RteTestM3_PackPath_cprj = prjsDir + RteTestM3 + "/RteTestM3_PackPath.cprj"; const std::string RteModelTestConfig::RteTestM3_PackPath_MultiplePdscs_cprj = prjsDir + RteTestM3 + "/RteTestM3_PackPath_MultiplePdscs.cprj"; diff --git a/libs/rtemodel/test/src/RteModelTestConfig.h b/libs/rtemodel/test/src/RteModelTestConfig.h index 160e06c01..53203d789 100644 --- a/libs/rtemodel/test/src/RteModelTestConfig.h +++ b/libs/rtemodel/test/src/RteModelTestConfig.h @@ -40,6 +40,7 @@ class RteModelTestConfig : public ::testing::Test static const std::string localRepoDir; static const std::string RteTestM3; static const std::string RteTestM3_cprj; + static const std::string RteTestM3PackReq_cprj; static const std::string RteTestM3_ConfigFolder_cprj; static const std::string RteTestM3_PackPath_cprj; static const std::string RteTestM3_PackPath_MultiplePdscs_cprj; diff --git a/test/packs/ARM/RteTestRequired/1.0.0/ARM.RteTestRequired.pdsc b/test/packs/ARM/RteTestRequired/1.0.0/ARM.RteTestRequired.pdsc new file mode 100644 index 000000000..3dddde131 --- /dev/null +++ b/test/packs/ARM/RteTestRequired/1.0.0/ARM.RteTestRequired.pdsc @@ -0,0 +1,22 @@ + + + + RteTestRequired + Testing package dependencies + ARM + + + + Initial version + + + + + + + + + + + + diff --git a/test/packs/ARM/RteTestRequiredRecursive/1.0.0/ARM.RteTestRequiredRecursive.pdsc b/test/packs/ARM/RteTestRequiredRecursive/1.0.0/ARM.RteTestRequiredRecursive.pdsc new file mode 100644 index 000000000..90fd5c5c1 --- /dev/null +++ b/test/packs/ARM/RteTestRequiredRecursive/1.0.0/ARM.RteTestRequiredRecursive.pdsc @@ -0,0 +1,22 @@ + + + + RteTestRequiredRecursive + Testing package recursive dependencies + ARM + + + + Initial version + + + + + + + + + + + + diff --git a/test/packs/ARM/RteTest_DFP/0.2.0/ARM.RteTest_DFP.pdsc b/test/packs/ARM/RteTest_DFP/0.2.0/ARM.RteTest_DFP.pdsc index cb6d9a993..d06cef22b 100644 --- a/test/packs/ARM/RteTest_DFP/0.2.0/ARM.RteTest_DFP.pdsc +++ b/test/packs/ARM/RteTest_DFP/0.2.0/ARM.RteTest_DFP.pdsc @@ -18,7 +18,6 @@ Added a new device 'RteTest_ARMCM0_Dual' - Software components for testing of RTE Library Cortex Microcontroller Software Interface Components diff --git a/test/projects/RteTestM3/RteTestM3_PackReq.cprj b/test/projects/RteTestM3/RteTestM3_PackReq.cprj new file mode 100644 index 000000000..c140b048f --- /dev/null +++ b/test/projects/RteTestM3/RteTestM3_PackReq.cprj @@ -0,0 +1,76 @@ + + + + + + + RteTestM3 + https://arm-software.github.io/CMSIS_5/General/html/index.html + CI testing + Test project license + RteTestM3 description + + + + + https://arm-software.github.io/CMSIS_5/Pack/html/pack_Example.html + Layer One + LayerOne license + LayerOne Description + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tools/projmgr/include/ProjMgrKernel.h b/tools/projmgr/include/ProjMgrKernel.h index 5ab5c2fd5..d942e93d5 100644 --- a/tools/projmgr/include/ProjMgrKernel.h +++ b/tools/projmgr/include/ProjMgrKernel.h @@ -36,22 +36,6 @@ class ProjMgrKernel : public RteKernelSlim { */ static void Destroy(); - /** - * @brief get installed packs - * @param pdscFiles list of installed packs - * @param bool latest get only latest versions (default true) - * @return true if executed successfully - */ - bool GetInstalledPacks(std::list& pdscFiles, bool latest=true); - - /** - * @brief load and insert pack into global model - * @param packs list of loaded packages - * @param pdscFiles list of packs to be loaded - * @return true if executed successfully - */ - bool LoadAndInsertPacks(std::list& packs, std::list& pdscFiles); - /** * @brief get callback * @return pointer to callback diff --git a/tools/projmgr/src/ProjMgrKernel.cpp b/tools/projmgr/src/ProjMgrKernel.cpp index a3ba365a1..a2458341b 100644 --- a/tools/projmgr/src/ProjMgrKernel.cpp +++ b/tools/projmgr/src/ProjMgrKernel.cpp @@ -54,84 +54,3 @@ void ProjMgrKernel::Destroy() { theProjMgrKernel.reset(); } } - -bool ProjMgrKernel::GetInstalledPacks(std::list& pdscFiles, bool latest) { - // Find pdsc files from the CMSIS_PACK_ROOT - list installedPdscFiles; - RteFsUtils::GetPackageDescriptionFiles(installedPdscFiles, theProjMgrKernel->GetCmsisPackRoot(), 3); - - // Filter only latest versions according to CMSIS_PACK_ROOT file tree - if (latest) { - map>> installedPacks; - for (const auto& pdsc : installedPdscFiles) { - fs::path pdscPath = fs::path(pdsc); - const auto& versionPath = pdscPath.parent_path(); - const auto& namePath = versionPath.parent_path(); - const auto& vendorPath = namePath.parent_path(); - installedPacks[vendorPath.filename().generic_string()][namePath.filename().generic_string()][versionPath.filename().generic_string()] = pdsc; - } - for (const auto& [vendor, packs] : installedPacks) { - for (const auto& [pack, versions] : packs) { - string latestVersion; - for (const auto& [version, pdsc] : versions) { - if (VersionCmp::Compare(latestVersion, version) <= 0) { - latestVersion = version; - } - } - pdscFiles.push_back(versions.at(latestVersion)); - } - } - } else { - pdscFiles.splice(pdscFiles.end(), installedPdscFiles); - } - - // Find pdsc files from local repository - list localPdscUrls; - if (!GetLocalPacksUrls(theProjMgrKernel->GetCmsisPackRoot(), localPdscUrls)) { - return false; - } - for (const auto& localPdscUrl : localPdscUrls) { - list localPdscFiles; - RteFsUtils::GetPackageDescriptionFiles(localPdscFiles, localPdscUrl, 1); - // Insert local pdsc files first - pdscFiles.insert(pdscFiles.begin(), localPdscFiles.begin(), localPdscFiles.end()); - } - - return true; -} - -bool ProjMgrKernel::LoadAndInsertPacks(std::list& packs, std::list& pdscFiles) { - std::list newPacks; - pdscFiles.sort(); - pdscFiles.unique(); - for (const auto& pdscFile : pdscFiles) { - RtePackage* pack = theProjMgrKernel->LoadPack(pdscFile); - if (!pack) { - return false; - } - bool loaded = false; - for (const auto& loadedPack : packs) { - if (pack->GetPackageID() == loadedPack->GetPackageID()) { - loaded = true; - break; - } - } - if (!loaded) { - newPacks.push_back(pack); - } - } - - RteGlobalModel* globalModel = theProjMgrKernel->GetGlobalModel(); - if (!globalModel) { - return false; - } - - globalModel->InsertPacks(newPacks); - - // Track only packs that were actually inserted into the model - packs.clear(); - for (const auto& [_, pack] : globalModel->GetPackages()) { - packs.push_back(pack); - } - return true; -} diff --git a/tools/projmgr/src/ProjMgrWorker.cpp b/tools/projmgr/src/ProjMgrWorker.cpp index f91973c11..343fd62a2 100644 --- a/tools/projmgr/src/ProjMgrWorker.cpp +++ b/tools/projmgr/src/ProjMgrWorker.cpp @@ -396,6 +396,20 @@ bool ProjMgrWorker::LoadPacks(ContextItem& context) { context.rteActiveTarget->SetPackageFilter(filter); context.rteActiveTarget->UpdateFilterModel(); } + RtePackageMap allRequiredPacks; + // check if all pack requirements are fulfilled + for (auto pack : m_loadedPacks) { + pack->GetRequiredPacks(allRequiredPacks, m_model); + } + for (auto [id, pack] : allRequiredPacks) { + if (!pack) { + string msg("context '"); + msg += context.name; + msg += "': required pack '"; + msg += id + "' is not loaded"; + ProjMgrLogger::Warn(msg); + } + } return CheckRteErrors(); } @@ -864,7 +878,7 @@ void ProjMgrWorker::PrintConnectionsValidation(ConnectionsValidationResult resul } msg += "\n"; } - + if (!result.missedCollections.empty()) { msg += "provided combined connections not consumed:"; for (const auto& missedCollection : result.missedCollections) { @@ -877,7 +891,7 @@ void ProjMgrWorker::PrintConnectionsValidation(ConnectionsValidationResult resul } msg += "\n"; } - + } } @@ -2802,7 +2816,7 @@ set ProjMgrWorker::SplitArgs(const string& args, const string& delimiter } bool ProjMgrWorker::ListPacks(vector&packs, bool missingPacks, const string& filter) { - set packsSet; + map packsMap; list pdscFiles; std::set errMsgs; bool reqOk = true; @@ -2814,7 +2828,8 @@ bool ProjMgrWorker::ListPacks(vector&packs, bool missingPacks, const str GetRequiredPdscFiles(context, m_packRoot, errMsgs); // Get missing packs identifiers for (const auto& pack : context.missingPacks) { - packsSet.insert(RtePackage::ComposePackageID(pack.vendor, pack.name, pack.version)); + string packID = RtePackage::ComposePackageID(pack.vendor, pack.name, pack.version); + packsMap[packID] = RteUtils::EMPTY_STRING; } if (!missingPacks) { if (context.packRequirements.size() > 0) { @@ -2840,7 +2855,7 @@ bool ProjMgrWorker::ListPacks(vector&packs, bool missingPacks, const str // Load packs and get loaded packs identifiers m_kernel->LoadAndInsertPacks(m_loadedPacks, pdscFiles); for (const auto& pack : m_loadedPacks) { - packsSet.insert(pack->GetID() + " (" + pack->GetPackageFileName() + ")"); + packsMap[pack->GetID()] = pack->GetPackageFileName(); } } if (errMsgs.size() > 0) { @@ -2848,7 +2863,16 @@ bool ProjMgrWorker::ListPacks(vector&packs, bool missingPacks, const str reqOk = false; } } - vector packsVec(packsSet.begin(), packsSet.end()); + + vector packsVec; + packsVec.reserve(packsMap.size()); + for (auto [id, fileName] : packsMap) { + string s = id; + if (!fileName.empty()) { + s += " (" + fileName + ")"; + } + packsVec.push_back(s); + } if (!filter.empty()) { vector filteredPacks; ApplyFilter(packsVec, SplitArgs(filter), filteredPacks); diff --git a/tools/projmgr/test/data/TestSolution/test_pack_requirements.csolution.yml b/tools/projmgr/test/data/TestSolution/test_pack_requirements.csolution.yml new file mode 100644 index 000000000..1a29e1b30 --- /dev/null +++ b/tools/projmgr/test/data/TestSolution/test_pack_requirements.csolution.yml @@ -0,0 +1,22 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/Open-CMSIS-Pack/devtools/main/tools/projmgr/schemas/csolution.schema.json + +solution: + target-types: + - type: CM0 + device: RteTest_ARMCM0 + + build-types: + - type: Debug + compiler: AC6 + - type: Release + compiler: GCC + + packs: + - pack: ARM::RteTest + for-context: .Debug + - pack: ARM::RteTest_DFP@>=0.2.0 + for-context: .Release + - pack: ARM::RteTestRequired + + projects: + - project: ./TestProject1/test1.cproject.yml diff --git a/tools/projmgr/test/src/ProjMgrTestEnv.cpp b/tools/projmgr/test/src/ProjMgrTestEnv.cpp index fbef4ffd5..d88e575bc 100644 --- a/tools/projmgr/test/src/ProjMgrTestEnv.cpp +++ b/tools/projmgr/test/src/ProjMgrTestEnv.cpp @@ -5,10 +5,13 @@ */ #include "ProjMgrTestEnv.h" +#include "RteKernel.h" #include "RteFsUtils.h" + #include "CrossPlatformUtils.h" #include +#include using namespace std; @@ -155,7 +158,44 @@ void ProjMgrTestEnv::CompareFile(const string& file1, const string& file2) { f2.close(); } +const std::string& ProjMgrTestEnv::GetCmsisPackRoot() +{ + return testcmsispack_folder; +} + +std::list ProjMgrTestEnv::GetInstalledPdscFiles( bool bLatestsOnly) +{ + list files; + RteKernel::GetInstalledPdscFiles(files, GetCmsisPackRoot(), bLatestsOnly); + return files; +} + +std::string ProjMgrTestEnv::GetFilteredPacksString(const std::list& pdscFiles, const std::string& includeIds) +{ + stringstream ss; + for (auto& f : pdscFiles) { + string id = RtePackage::PackIdFromPath(f); + if(FilterId(id, includeIds)) { + ss << id << " (" << f << ")\n"; + } + } + return ss.str(); +} +bool ProjMgrTestEnv::FilterId(const std::string& id, const std::string& includeIds) +{ + if (!includeIds.empty()) { + list segments; + RteUtils::SplitString(segments, includeIds, ';'); + for (auto& s : segments) { + if (WildCards::Match(id, s)) { + return true; + } + } + return false; + } + return true; +} int main(int argc, char **argv) { try { diff --git a/tools/projmgr/test/src/ProjMgrTestEnv.h b/tools/projmgr/test/src/ProjMgrTestEnv.h index ec31c5412..a9e35a507 100644 --- a/tools/projmgr/test/src/ProjMgrTestEnv.h +++ b/tools/projmgr/test/src/ProjMgrTestEnv.h @@ -9,6 +9,8 @@ #include "gtest/gtest.h" +#include + extern std::string testoutput_folder; extern std::string testinput_folder; extern std::string testcmsispack_folder; @@ -42,7 +44,10 @@ class ProjMgrTestEnv : public ::testing::Environment { void SetUp() override; void TearDown() override; static void CompareFile(const std::string& file1, const std::string& file2); - + static const std::string& GetCmsisPackRoot(); + static std::list GetInstalledPdscFiles(bool bLatestsOnly = false); + static std::string GetFilteredPacksString(const std::list& pdscFiles, const std::string& includeIds); + static bool FilterId(const std::string& id, const std::string& includeIds); }; #endif // PROJMGRTESTENV_H diff --git a/tools/projmgr/test/src/ProjMgrUnitTests.cpp b/tools/projmgr/test/src/ProjMgrUnitTests.cpp index b59dafd66..7c838718c 100644 --- a/tools/projmgr/test/src/ProjMgrUnitTests.cpp +++ b/tools/projmgr/test/src/ProjMgrUnitTests.cpp @@ -31,37 +31,32 @@ class ProjMgrUnitTests : public ProjMgr, public ::testing::Test { virtual ~ProjMgrUnitTests() {} void SetUp() { m_context.clear(); }; - void GetFilesInTree(const string& dir, set& files); - void CompareFileTree(const string& dir1, const string& dir2); - - string UpdateTestSolutionFile(const string& projectFilePath); -}; - -string ProjMgrUnitTests::UpdateTestSolutionFile(const string& projectFilePath) { - string csolutionFile = testinput_folder + "/TestSolution/test_validate_project.csolution.yml"; - YAML::Node root = YAML::LoadFile(csolutionFile); - root["solution"]["projects"][0]["project"] = projectFilePath; - std::ofstream fout(csolutionFile); - fout << root; - fout.close(); - return csolutionFile; -} - -void ProjMgrUnitTests::GetFilesInTree(const string& dir, set& files) { - error_code ec; - if (RteFsUtils::Exists(dir)) { - for (auto& p : fs::recursive_directory_iterator(dir, ec)) { - files.insert(p.path().filename().generic_string()); + void GetFilesInTree(const string& dir, set& files) { + error_code ec; + if (RteFsUtils::Exists(dir)) { + for (auto& p : fs::recursive_directory_iterator(dir, ec)) { + files.insert(p.path().filename().generic_string()); + } } } -} -void ProjMgrUnitTests::CompareFileTree(const string& dir1, const string& dir2) { - set tree1, tree2; - GetFilesInTree(dir1, tree1); - GetFilesInTree(dir2, tree2); - EXPECT_EQ(tree1, tree2); -} + void CompareFileTree(const string& dir1, const string& dir2) { + set tree1, tree2; + GetFilesInTree(dir1, tree1); + GetFilesInTree(dir2, tree2); + EXPECT_EQ(tree1, tree2); + } + + string UpdateTestSolutionFile(const string& projectFilePath) { + string csolutionFile = testinput_folder + "/TestSolution/test_validate_project.csolution.yml"; + YAML::Node root = YAML::LoadFile(csolutionFile); + root["solution"]["projects"][0]["project"] = projectFilePath; + std::ofstream fout(csolutionFile); + fout << root; + fout.close(); + return csolutionFile; + } +}; TEST_F(ProjMgrUnitTests, RunProjMgr_EmptyOptions) { char* argv[1]; @@ -79,31 +74,62 @@ TEST_F(ProjMgrUnitTests, RunProjMgr_Version) { EXPECT_EQ(0, RunProjMgr(2, argv, 0)); } +TEST_F(ProjMgrUnitTests, RunProjMgr_Packs_Required_Warning) { + StdStreamRedirect streamRedirect; + const string csolution = testinput_folder + "/TestSolution/test_pack_requirements.csolution.yml"; + char* argv[9]; + argv[1] = (char*)"convert"; + argv[2] = (char*)"--solution"; + argv[3] = (char*)csolution.c_str(); + argv[4] = (char*)"-o"; + argv[5] = (char*)testoutput_folder.c_str(); + argv[6] = (char*)"-c"; + argv[7] = (char*)"test1.Debug+CM0"; + EXPECT_EQ(1, RunProjMgr(8, argv, 0)); //fails because DFP is not loaded + + auto errStr = streamRedirect.GetErrorString(); + + auto pos = errStr.find("required pack 'ARM::RteTestRequiredRecursive@1.0.0:2.0.0' is not loaded"); + EXPECT_TRUE(pos != string::npos); + pos = errStr.find("required pack 'ARM::RteTest_DFP@0.1.1:0.2.0' is not loaded"); + EXPECT_TRUE(pos != string::npos); + pos = errStr.find("required pack 'ARM::RteTest@0.1.0:0.2.0' is not loaded"); + EXPECT_FALSE(pos != string::npos); + + streamRedirect.ClearStringStreams(); + argv[7] = (char*)"test1.Release+CM0"; + EXPECT_EQ(0, RunProjMgr(8, argv, 0)); // succeeds regardless of warnings + + errStr = streamRedirect.GetErrorString(); + pos = errStr.find("required pack 'ARM::RteTest@0.1.0:0.2.0' is not loaded"); + EXPECT_TRUE(pos != string::npos); + pos = errStr.find("required pack 'ARM::RteTestRequiredRecursive@1.0.0:2.0.0' is not loaded"); + EXPECT_TRUE(pos != string::npos); + pos = errStr.find("required pack 'ARM::RteTest_DFP@0.1.1:0.2.0' is not loaded"); + EXPECT_FALSE(pos != string::npos); +} TEST_F(ProjMgrUnitTests, RunProjMgr_ListPacks) { - char* argv[7]; map, string> testInputs = { - {{"TestSolution/test.csolution.yml", "test1.Debug+CM0"}, - "ARM::RteTest_DFP@0.2.0 \\(.*\\)\n" }, + {{"TestSolution/test.csolution.yml", "test1.Debug+CM0"}, "ARM::RteTest_DFP@0.2.0" }, // packs are specified only with vendor - {{"TestSolution/test_filtered_pack_selection.csolution.yml", "test1.Debug+CM0"}, - "ARM::RteTest@0.1.0 \\(.*\\)\nARM::RteTestBoard@0.1.0 \\(.*\\)\nARM::RteTestGenerator@0.1.0 \\(.*\\)\nARM::RteTest_DFP@0.2.0 \\(.*\\)\n"}, + {{"TestSolution/test_filtered_pack_selection.csolution.yml", "test1.Debug+CM0"}, "*"}, // packs are specified with wildcards - {{"TestSolution/test_filtered_pack_selection.csolution.yml", "test1.Release+CM0"}, - "ARM::RteTest_DFP@0.2.0 \\(.*\\)\n"}, + {{"TestSolution/test_filtered_pack_selection.csolution.yml", "test1.Release+CM0"}, "ARM::RteTest_DFP@0.2.0"}, // packs are not specified - {{"TestSolution/test_no_packs.csolution.yml", "test1.Debug+CM0"}, - "ARM::RteTest@0.1.0 \\(.*\\)\nARM::RteTestBoard@0.1.0 \\(.*\\)\nARM::RteTestGenerator@0.1.0 \\(.*\\)\nARM::RteTest_DFP@0.2.0 \\(.*\\)\n"}, + {{"TestSolution/test_no_packs.csolution.yml", "test1.Debug+CM0"}, "*"}, // packs are fully specified - {{"TestSolution/test_pack_selection.csolution.yml", "test2.Debug+CM0"}, - "ARM::RteTest_DFP@0.2.0 \\(.*\\)\n"} + {{"TestSolution/test_pack_selection.csolution.yml", "test2.Debug+CM0"}, "ARM::RteTest_DFP@0.2.0"} }; + auto pdscFiles = ProjMgrTestEnv::GetInstalledPdscFiles(true); // positive tests + char* argv[7]; argv[1] = (char*)"list"; argv[2] = (char*)"packs"; argv[3] = (char*)"--solution"; - for (const auto& [input, expected] : testInputs) { + + for (const auto& [input, ids] : testInputs) { StdStreamRedirect streamRedirect; const string& csolution = testinput_folder + "/" + input.first; argv[4] = (char*)csolution.c_str(); @@ -112,7 +138,9 @@ TEST_F(ProjMgrUnitTests, RunProjMgr_ListPacks) { EXPECT_EQ(0, RunProjMgr(7, argv, 0)); auto outStr = streamRedirect.GetOutString(); - EXPECT_TRUE(regex_match(outStr, regex(expected.c_str()))) << "error listing pack for " << csolution << endl; + string expected = ProjMgrTestEnv::GetFilteredPacksString(pdscFiles, ids); + + EXPECT_TRUE(outStr == expected) << "error listing pack for " << csolution << endl; } map, string> testFalseInputs = { @@ -139,14 +167,15 @@ TEST_F(ProjMgrUnitTests, RunProjMgr_ListPacks) { TEST_F(ProjMgrUnitTests, RunProjMgr_ListPacks_1) { char* argv[3]; StdStreamRedirect streamRedirect; - const string& expected = "ARM::RteTest@0.1.0 \\(.*\\)\nARM::RteTestBoard@0.1.0 \\(.*\\)\nARM::RteTestGenerator@0.1.0 \\(.*\\)\nARM::RteTest_DFP@0.2.0 \\(.*\\)\n"; + auto pdscFiles = ProjMgrTestEnv::GetInstalledPdscFiles(true); + string expected = ProjMgrTestEnv::GetFilteredPacksString(pdscFiles, "*"); // list packs argv[1] = (char*)"list"; argv[2] = (char*)"packs"; EXPECT_EQ(0, RunProjMgr(3, argv, 0)); auto outStr = streamRedirect.GetOutString(); - EXPECT_TRUE(regex_match(outStr, regex(expected.c_str()))); + EXPECT_EQ(outStr, expected); } TEST_F(ProjMgrUnitTests, RunProjMgr_ListPacks_project) { @@ -187,39 +216,32 @@ TEST_F(ProjMgrUnitTests, RunProjMgr_ListPacks_MultiContext) { argv[6] = (char*)"test2.*"; EXPECT_EQ(0, RunProjMgr(7, argv, 0)); + auto pdscFiles = ProjMgrTestEnv::GetInstalledPdscFiles(true); + string expected = ProjMgrTestEnv::GetFilteredPacksString(pdscFiles, "ARM::RteTestGenerator@0.1.0;ARM::RteTest_DFP@0.2.0"); + auto outStr = streamRedirect.GetOutString(); - EXPECT_TRUE(regex_match(outStr.c_str(), regex("ARM::RteTestGenerator@0.1.0 \\(.*\\)\nARM::RteTest_DFP@0.2.0 \\(.*\\)\n"))); + EXPECT_EQ(outStr, expected); argv[7] = (char*)"-l"; argv[8] = (char*)"latest"; streamRedirect.ClearStringStreams(); EXPECT_EQ(0, RunProjMgr(9, argv, 0)); - const string& expectedLatest = "\ -ARM::RteTest@0.1.0 \\(.*\\)\n\ -ARM::RteTestBoard@0.1.0 \\(.*\\)\n\ -ARM::RteTestGenerator@0.1.0 \\(.*\\)\n\ -ARM::RteTest_DFP@0.2.0 \\(.*\\)\n\ -"; + string expectedLatest = ProjMgrTestEnv::GetFilteredPacksString(pdscFiles, "*"); outStr = streamRedirect.GetOutString(); - EXPECT_TRUE(regex_match(outStr, regex(expectedLatest))); + EXPECT_EQ(outStr, expectedLatest); argv[7] = (char*)"-l"; argv[8] = (char*)"all"; streamRedirect.ClearStringStreams(); EXPECT_EQ(0, RunProjMgr(9, argv, 0)); - const string& expectedAll = "\ -ARM::RteTest@0.1.0 \\(.*\\)\n\ -ARM::RteTestBoard@0.1.0 \\(.*\\)\n\ -ARM::RteTestGenerator@0.1.0 \\(.*\\)\n\ -ARM::RteTest_DFP@0.1.1 \\(.*\\)\n\ -ARM::RteTest_DFP@0.2.0 \\(.*\\)\n\ -"; + pdscFiles = ProjMgrTestEnv::GetInstalledPdscFiles(false); + string expectedAll = ProjMgrTestEnv::GetFilteredPacksString(pdscFiles, "*"); outStr = streamRedirect.GetOutString(); - EXPECT_TRUE(regex_match(outStr, regex(expectedAll))); + EXPECT_EQ(outStr, expectedAll); } TEST_F(ProjMgrUnitTests, RunProjMgr_ListPacksAll) { @@ -231,16 +253,11 @@ TEST_F(ProjMgrUnitTests, RunProjMgr_ListPacksAll) { argv[4] = (char*)"all"; EXPECT_EQ(0, RunProjMgr(5, argv, 0)); - const string& expectedAll = "\ -ARM::RteTest@0.1.0 \\(.*\\)\n\ -ARM::RteTestBoard@0.1.0 \\(.*\\)\n\ -ARM::RteTestGenerator@0.1.0 \\(.*\\)\n\ -ARM::RteTest_DFP@0.1.1 \\(.*\\)\n\ -ARM::RteTest_DFP@0.2.0 \\(.*\\)\n\ -"; + auto pdscFiles = ProjMgrTestEnv::GetInstalledPdscFiles(false); + string expectedAll = ProjMgrTestEnv::GetFilteredPacksString(pdscFiles, "*"); auto outStr = streamRedirect.GetOutString(); - EXPECT_TRUE(regex_match(outStr, regex(expectedAll))); + EXPECT_EQ(outStr, expectedAll); } TEST_F(ProjMgrUnitTests, RunProjMgr_ListPacksMissing) { @@ -265,7 +282,7 @@ TEST_F(ProjMgrUnitTests, ListPacks_ProjectAndLayer) { char* argv[5]; StdStreamRedirect streamRedirect; const string& csolution = testinput_folder + "/TestLayers/packs.csolution.yml"; - const string& expected = "ARM::RteTest@0.1.0 \\(.*\\)\nARM::RteTestBoard@0.1.0 \\(.*\\)\nARM::RteTest_DFP@0.2.0 \\(.*\\)\n"; + // list packs argv[1] = (char*)"list"; argv[2] = (char*)"packs"; @@ -273,8 +290,11 @@ TEST_F(ProjMgrUnitTests, ListPacks_ProjectAndLayer) { argv[4] = (char*)csolution.c_str(); EXPECT_EQ(0, RunProjMgr(5, argv, 0)); + auto pdscFiles = ProjMgrTestEnv::GetInstalledPdscFiles(false); + string expected = ProjMgrTestEnv::GetFilteredPacksString(pdscFiles, "ARM::RteTest@0.1.0;ARM::RteTestBoard@0.1.0;ARM::RteTest_DFP@0.2.0"); + auto outStr = streamRedirect.GetOutString(); - EXPECT_TRUE(regex_match(outStr, regex(expected.c_str()))); + EXPECT_EQ(outStr, expected); } TEST_F(ProjMgrUnitTests, RunProjMgr_ListBoards) { @@ -1474,10 +1494,14 @@ TEST_F(ProjMgrUnitTests, ListPacks) { EXPECT_TRUE(m_worker.ParseContextSelection({})); m_worker.SetLoadPacksPolicy(LoadPacksPolicy::ALL); EXPECT_TRUE(m_worker.ListPacks(packs, false, "RteTest")); - auto packIt = packs.begin(); - for (const auto& expected : expectedPacks) { - EXPECT_TRUE(regex_match(*packIt++, regex(expected))); + string allPacks; + for (auto& pack : packs) { + allPacks += pack + "\n"; } + + auto pdscFiles = ProjMgrTestEnv::GetInstalledPdscFiles(false); + string expected = ProjMgrTestEnv::GetFilteredPacksString(pdscFiles, "*"); + EXPECT_EQ(allPacks, expected); } TEST_F(ProjMgrUnitTests, ListPacksLatest) { @@ -1491,10 +1515,13 @@ TEST_F(ProjMgrUnitTests, ListPacksLatest) { EXPECT_TRUE(m_worker.ParseContextSelection({})); m_worker.SetLoadPacksPolicy(LoadPacksPolicy::LATEST); EXPECT_TRUE(m_worker.ListPacks(packs, false, "RteTest")); - auto packIt = packs.begin(); - for (const auto& expected : expectedPacks) { - EXPECT_TRUE(regex_match(*packIt++, regex(expected))); + string latestPacks; + for (auto& pack : packs) { + latestPacks += pack + "\n"; } + auto pdscFiles = ProjMgrTestEnv::GetInstalledPdscFiles(true); + string expected = ProjMgrTestEnv::GetFilteredPacksString(pdscFiles, "*"); + EXPECT_EQ(latestPacks, expected); } TEST_F(ProjMgrUnitTests, ListBoards) { diff --git a/tools/projmgr/test/src/ProjMgrWorkerUnitTests.cpp b/tools/projmgr/test/src/ProjMgrWorkerUnitTests.cpp index 4fd144222..acdecfa23 100644 --- a/tools/projmgr/test/src/ProjMgrWorkerUnitTests.cpp +++ b/tools/projmgr/test/src/ProjMgrWorkerUnitTests.cpp @@ -550,7 +550,7 @@ TEST_F(ProjMgrWorkerUnitTests, LoadPacksNoPackage) { ContextItem context; EXPECT_TRUE(LoadPacks(context)); // by default latest packs available should be loaded - EXPECT_EQ(4, m_loadedPacks.size()); + EXPECT_EQ(6, m_loadedPacks.size()); } TEST_F(ProjMgrWorkerUnitTests, LoadFilteredPack_1) {