diff --git a/libs/rtemodel/src/RtePackage.cpp b/libs/rtemodel/src/RtePackage.cpp index 3afa5beaf..b7ee52c2e 100644 --- a/libs/rtemodel/src/RtePackage.cpp +++ b/libs/rtemodel/src/RtePackage.cpp @@ -6,7 +6,7 @@ */ /******************************************************************************/ /* - * Copyright (c) 2020-2021 Arm Limited. All rights reserved. + * Copyright (c) 2020-2026 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 */ @@ -1139,7 +1139,7 @@ bool RtePackageFilter::AreAllExcluded() const bool RtePackageFilter::IsUseAllPacks() const { - return m_bUseAllPacks && m_selectedPacks.empty() && m_latestPacks.empty(); + return m_bUseAllPacks; } bool RtePackageFilter::IsPackageSelected(const string& packId) const @@ -1170,10 +1170,10 @@ bool RtePackageFilter::IsPackageFiltered(RtePackage* pack) const bool RtePackageFilter::IsPackageFiltered(const string& packId) const { + if(IsPackageSelected(packId)) { // pack is explicitly selected => filtered + return true; + } if (!IsUseAllPacks()) { - if (IsPackageSelected(packId)) - return true; - string commonId = RtePackage::CommonIdFromId(packId); if (m_latestPacks.find(commonId) == m_latestPacks.end()) return false; @@ -1185,8 +1185,9 @@ bool RtePackageFilter::IsPackageFiltered(const string& packId) const } } } - if (m_latestInstalledPacks.find(packId) != m_latestInstalledPacks.end()) + if(m_latestInstalledPacks.find(packId) != m_latestInstalledPacks.end()) { return true; + } return false; } diff --git a/libs/rteutils/include/CollectionUtils.h b/libs/rteutils/include/CollectionUtils.h index 7639a8e0e..77ffb37a4 100644 --- a/libs/rteutils/include/CollectionUtils.h +++ b/libs/rteutils/include/CollectionUtils.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020-2024 Arm Limited. All rights reserved. + * Copyright (c) 2020-2026 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 */ @@ -13,6 +13,7 @@ #include #include #include +#include /** * @brief Returns value stored in a map for a given key or default value if no entry is found @@ -87,6 +88,37 @@ auto key_set(const M& m) { return ks; } +/** + * @brief Finds the first element in a container that satisfies a predicate. + * + * Searches the container in forward order and returns a reference to the + * first element for which the predicate returns true. + * + * @tparam Container A container type providing begin()/end() and value_type. + * @tparam Predicate A callable with signature bool(const value_type&). + * + * @param c Container to search. + * @param pred Predicate applied to each element. + * + * @return std::optional containing a reference to the matching element, + * or std::nullopt if no such element is found. + * + * @note The returned reference remains valid only as long as the container + * is not structurally modified (e.g. erase, reallocation). + * + * @complexity Linear in the size of the container. + */ +template +auto find_item(Container& c, Predicate pred) + -> std::optional> +{ + auto it = std::find_if(std::begin(c), std::end(c), pred); + if(it == std::end(c)) { + return std::nullopt; + } + return *it; // reference, not a copy +} + /** * @brief string pair */ diff --git a/libs/rteutils/test/src/RteUtilsTest.cpp b/libs/rteutils/test/src/RteUtilsTest.cpp index e03371b3f..af68e8ffc 100644 --- a/libs/rteutils/test/src/RteUtilsTest.cpp +++ b/libs/rteutils/test/src/RteUtilsTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020-2025 Arm Limited. All rights reserved. + * Copyright (c) 2020-2026 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 */ @@ -497,6 +497,15 @@ TEST(RteUtils, CollectionUtils) EXPECT_EQ(*get_or_default(strToPtr, "two", sDefault), '2'); EXPECT_EQ(*get_or_default(strToPtr, "four", sDefault), 'd'); + + auto notFound = find_item(intToInt, [](const auto& kv) {return kv.second < 5; }); + EXPECT_FALSE(!!notFound); + auto foundInt = find_item(intToInt, [](const auto& kv) {return kv.second > 5; }); + ASSERT_TRUE(!!foundInt); + auto& [key, val] = foundInt->get(); + EXPECT_EQ(key, 1); + EXPECT_EQ(val, 10); + } TEST(RteUtils, ExpandAccessSequences) { diff --git a/tools/projmgr/src/ProjMgrRpcServer.cpp b/tools/projmgr/src/ProjMgrRpcServer.cpp index 8bab3cf68..a000407d6 100644 --- a/tools/projmgr/src/ProjMgrRpcServer.cpp +++ b/tools/projmgr/src/ProjMgrRpcServer.cpp @@ -327,18 +327,17 @@ void RpcHandler::UpdateFilter(const string& context, RteTarget* rteTarget, bool StoreSelectedComponents(rteTarget, selectedComponents); RtePackageFilter packFilter; - if(!all) { - // construct and apply filter - // use resolved pack ID's from selected references - set packIds; - for(auto& ref : GetPackReferences(context)) { - if(ref.selected && ref.resolvedPack.has_value()) { - packIds.insert(ref.resolvedPack.value()); - } + // construct and apply filter + // use resolved pack ID's from selected references + set packIds; + for(auto& ref : GetPackReferences(context)) { + if(ref.selected && ref.resolvedPack.has_value()) { + packIds.insert(ref.resolvedPack.value()); } - packFilter.SetSelectedPackages(packIds); - packFilter.SetUseAllPacks(false); } + packFilter.SetSelectedPackages(packIds); + packFilter.SetUseAllPacks(all); + // only update filter if differs from current state if(!packFilter.IsEqual(rteTarget->GetPackageFilter())) { rteTarget->SetPackageFilter(packFilter); diff --git a/tools/projmgr/src/ProjMgrWorker.cpp b/tools/projmgr/src/ProjMgrWorker.cpp index 4e197b1ee..fae591045 100644 --- a/tools/projmgr/src/ProjMgrWorker.cpp +++ b/tools/projmgr/src/ProjMgrWorker.cpp @@ -567,11 +567,13 @@ bool ProjMgrWorker::LoadPacks(ContextItem& context) { set selectedPacks; const bool allOrLatest = (m_loadPacksPolicy == LoadPacksPolicy::ALL) || (m_loadPacksPolicy == LoadPacksPolicy::LATEST); for (const auto& pack : m_loadedPacks) { - if (allOrLatest || (context.pdscFiles.find(pack->GetPackageFileName()) != context.pdscFiles.end())) { + if (context.pdscFiles.find(pack->GetPackageFileName()) != context.pdscFiles.end()) { selectedPacks.insert(pack->GetPackageID()); } } RtePackageFilter filter; + // use all packs is enabled by default, by default policy it should be disabled if selectedPacks is not empty + filter.SetUseAllPacks(allOrLatest || selectedPacks.empty()); filter.SetSelectedPackages(selectedPacks); context.rteActiveTarget->SetPackageFilter(filter); context.rteActiveTarget->UpdateFilterModel(); diff --git a/tools/projmgr/test/data/TestSolution/test_pack_requirements.csolution.yml b/tools/projmgr/test/data/TestSolution/test_pack_requirements.csolution.yml index 1a29e1b30..68d8b7f7c 100644 --- a/tools/projmgr/test/data/TestSolution/test_pack_requirements.csolution.yml +++ b/tools/projmgr/test/data/TestSolution/test_pack_requirements.csolution.yml @@ -8,12 +8,16 @@ solution: build-types: - type: Debug compiler: AC6 + - type: DebugOldDfp + compiler: AC6 - type: Release compiler: GCC packs: - pack: ARM::RteTest for-context: .Debug + - pack: ARM::RteTest_DFP@0.1.1 + for-context: .DebugOldDfp - pack: ARM::RteTest_DFP@>=0.2.0 for-context: .Release - pack: ARM::RteTestRequired diff --git a/tools/projmgr/test/src/ProjMgrRpcTests.cpp b/tools/projmgr/test/src/ProjMgrRpcTests.cpp index bafb14dbf..72cdb1687 100644 --- a/tools/projmgr/test/src/ProjMgrRpcTests.cpp +++ b/tools/projmgr/test/src/ProjMgrRpcTests.cpp @@ -19,6 +19,10 @@ using namespace std; +auto find_item_by_id(json& items, const std::string& id) { + return find_item(items, [&](const auto& item) { return item["id"] == id; }); +} + class ProjMgrRpcTests : public ProjMgr, public ::testing::Test { protected: ProjMgrRpcTests() {} @@ -1012,6 +1016,7 @@ TEST_F(ProjMgrRpcTests, RpcGetPacksInfo) { auto packs = responses[2]["result"]["packs"]; EXPECT_EQ(packs[0]["pack"], "ARM::RteTest_DFP@>=0.2.0"); EXPECT_EQ(packs[0]["resolvedPack"], "ARM::RteTest_DFP@0.2.0"); + EXPECT_FALSE(packs[0].contains("upgrade")); EXPECT_TRUE(responses[3]["result"]["success"]); // get pack infos auto packInfos = responses[3]["result"]["packs"]; @@ -1025,6 +1030,54 @@ TEST_F(ProjMgrRpcTests, RpcGetPacksInfo) { EXPECT_FALSE(packInfos[7].contains("used")); } + +TEST_F(ProjMgrRpcTests, RpcGetPacksNotLatest) { + string context = "test1.DebugOldDfp+CM0"; + vector contextList = { + context + }; + + auto requests = CreateLoadRequests("/TestSolution/test_pack_requirements.csolution.yml", "", contextList); + requests += FormatRequest(3, "GetUsedItems", json({{ "context", context }})); + requests += FormatRequest(4, "GetPacksInfo", json({{ "context", context }, {"all", false}})); + requests += FormatRequest(5, "GetPacksInfo", json({{ "context", context }, {"all", true}})); + + const auto& responses = RunRpcMethods(requests); + + EXPECT_TRUE(responses[2]["result"]["success"]); + auto packs = responses[2]["result"]["packs"]; + EXPECT_EQ(packs[0]["pack"], "ARM::RteTest_DFP@0.1.1"); + EXPECT_EQ(packs[0]["resolvedPack"], "ARM::RteTest_DFP@0.1.1"); + + EXPECT_TRUE(responses[3]["result"]["success"]); // get pack infos + auto packInfos = responses[3]["result"]["packs"]; + EXPECT_EQ(packInfos.size(), 2); + auto p = find_item_by_id(packInfos, "ARM::RteTest_DFP@0.1.1"); + EXPECT_TRUE(!!p); + EXPECT_TRUE(p->get()["used"]); + EXPECT_TRUE(p->get().contains("references")); + p = find_item_by_id(packInfos, "ARM::RteTest_DFP@0.2.0"); + EXPECT_FALSE(!!p); + + auto packInfosAll = responses[4]["result"]["packs"]; + EXPECT_TRUE(packInfosAll.size() > packInfos.size()); + + p = find_item_by_id(packInfosAll, "SomeVendor::RteTest@0.0.1"); + EXPECT_TRUE(!!p); + EXPECT_FALSE(p->get().contains("used")); + + p = find_item_by_id(packInfosAll, "ARM::RteTest_DFP@0.1.1"); + EXPECT_TRUE(!!p); + EXPECT_TRUE(p->get()["used"]); + EXPECT_TRUE(p->get().contains("references")); + + p = find_item_by_id(packInfosAll, "ARM::RteTest_DFP@0.2.0"); + EXPECT_TRUE(!!p); + EXPECT_FALSE(p->get().contains("used")); + EXPECT_FALSE(p->get().contains("references")); +} + + TEST_F(ProjMgrRpcTests, RpcGetPacksInfoLayer) { string context = "packs.CompatibleLayers+RteTest_ARMCM3"; vector contextList = {