From 884d70a6ec64a0432852128f3fd31bf30461c647 Mon Sep 17 00:00:00 2001 From: grasci <86058054+grasci-arm@users.noreply.github.com> Date: Mon, 21 Aug 2023 15:45:27 +0100 Subject: [PATCH] [projmgr] Update `connections` validation rules --- .../0.2.0/Layers/board1.clayer.yml | 2 - .../0.2.0/Layers/board2.clayer.yml | 2 - .../0.2.0/Layers/board3.clayer.yml | 2 - .../0.2.0/Layers/incompatible.clayer.yml | 1 + .../0.2.0/Layers/testvariant.clayer.yml | 2 - tools/projmgr/include/ProjMgrWorker.h | 5 +- tools/projmgr/src/ProjMgrWorker.cpp | 74 ++++++++++++++++--- .../TestLayers/genericlayers.cproject.yml | 2 +- tools/projmgr/test/src/ProjMgrUnitTests.cpp | 24 +++++- .../test/src/ProjMgrWorkerUnitTests.cpp | 28 +++---- 10 files changed, 98 insertions(+), 44 deletions(-) diff --git a/test/packs/ARM/RteTest_DFP/0.2.0/Layers/board1.clayer.yml b/test/packs/ARM/RteTest_DFP/0.2.0/Layers/board1.clayer.yml index 75894226d..036d51410 100644 --- a/test/packs/ARM/RteTest_DFP/0.2.0/Layers/board1.clayer.yml +++ b/test/packs/ARM/RteTest_DFP/0.2.0/Layers/board1.clayer.yml @@ -9,8 +9,6 @@ layer: connections: - connect: Board1 Connections - provides: - - MultipleProvided # same connection is provided multiple times with identical values consumes: - ExactMatch: 42 # both key and value exact match - EmptyConsumedValue # key exact match, consumed value is empty diff --git a/test/packs/ARM/RteTest_DFP/0.2.0/Layers/board2.clayer.yml b/test/packs/ARM/RteTest_DFP/0.2.0/Layers/board2.clayer.yml index 1d045ca4c..6dd454a6b 100644 --- a/test/packs/ARM/RteTest_DFP/0.2.0/Layers/board2.clayer.yml +++ b/test/packs/ARM/RteTest_DFP/0.2.0/Layers/board2.clayer.yml @@ -9,8 +9,6 @@ layer: connections: - connect: Board2 Connections - provides: - - MultipleProvided # same connection is provided multiple times with identical values consumes: - ExactMatch: 42 # both key and value exact match - EmptyConsumedValue # key exact match, consumed value is empty diff --git a/test/packs/ARM/RteTest_DFP/0.2.0/Layers/board3.clayer.yml b/test/packs/ARM/RteTest_DFP/0.2.0/Layers/board3.clayer.yml index 5e09badea..8da90f292 100644 --- a/test/packs/ARM/RteTest_DFP/0.2.0/Layers/board3.clayer.yml +++ b/test/packs/ARM/RteTest_DFP/0.2.0/Layers/board3.clayer.yml @@ -9,8 +9,6 @@ layer: connections: - connect: Board3 Connections - provides: - - MultipleProvided # same connection is provided multiple times with identical values consumes: - ExactMatch: 42 # both key and value exact match - EmptyConsumedValue # key exact match, consumed value is empty diff --git a/test/packs/ARM/RteTest_DFP/0.2.0/Layers/incompatible.clayer.yml b/test/packs/ARM/RteTest_DFP/0.2.0/Layers/incompatible.clayer.yml index 94094f5de..f4da59d43 100644 --- a/test/packs/ARM/RteTest_DFP/0.2.0/Layers/incompatible.clayer.yml +++ b/test/packs/ARM/RteTest_DFP/0.2.0/Layers/incompatible.clayer.yml @@ -10,6 +10,7 @@ layer: connections: - connect: Incompatible Connections provides: + - MultipleProvided # same connection is provided multiple times with identical values - MultipleProvidedNonIdentical0: 111 # same connection is provided multiple times with non identical values - MultipleProvidedNonIdentical1: 222 # same connection is provided multiple times with non identical values consumes: diff --git a/test/packs/ARM/RteTest_DFP/0.2.0/Layers/testvariant.clayer.yml b/test/packs/ARM/RteTest_DFP/0.2.0/Layers/testvariant.clayer.yml index 8ee926c98..3010030d7 100644 --- a/test/packs/ARM/RteTest_DFP/0.2.0/Layers/testvariant.clayer.yml +++ b/test/packs/ARM/RteTest_DFP/0.2.0/Layers/testvariant.clayer.yml @@ -9,8 +9,6 @@ layer: connections: - connect: Test variant Connections - provides: - - MultipleProvided # same connection is provided multiple times with identical values consumes: - AddedValueLessThanProvided: +49 # added consumed values are less than provided - AddedValueEqualToProvided: +499 # added consumed values are equal to provided diff --git a/tools/projmgr/include/ProjMgrWorker.h b/tools/projmgr/include/ProjMgrWorker.h index 06bb09be7..c5570da36 100644 --- a/tools/projmgr/include/ProjMgrWorker.h +++ b/tools/projmgr/include/ProjMgrWorker.h @@ -17,6 +17,7 @@ * conflicted connections, * overflowed connections, * incompatible connections, + * missed provided combined connections, * provided connections */ struct ConnectionsValidationResult { @@ -24,6 +25,7 @@ struct ConnectionsValidationResult { StrVec conflicts; StrPairVec overflows; StrPairVec incompatibles; + std::vector missedCollections; StrPairPtrVec provides; }; @@ -648,7 +650,7 @@ class ProjMgrWorker { void CollectConnections(ContextItem& context, ConnectionsCollectionVec& connections); void GetConsumesProvides(const ConnectionsCollectionVec& collection, ConnectionsList& connections); ConnectionsCollectionMap ClassifyConnections(const ConnectionsCollectionVec& connections); - ConnectionsValidationResult ValidateConnections(ConnectionsList& connections); + ConnectionsValidationResult ValidateConnections(ConnectionsCollectionVec combination); void GetAllCombinations(const ConnectionsCollectionMap& src, const ConnectionsCollectionMap::iterator& it, std::vector& combinations, const ConnectionsCollectionVec& previous = ConnectionsCollectionVec()); void GetAllSelectCombinations(const ConnectPtrVec& src, const ConnectPtrVec::iterator& it, @@ -662,6 +664,7 @@ class ProjMgrWorker { bool IsConnectionSubset(const ConnectionsCollection& connectionSubset, const ConnectionsCollection& connectionSuperset); bool IsCollectionSubset(const ConnectionsCollectionVec& collectionSubset, const ConnectionsCollectionVec& collectionSuperset); void RemoveRedundantSubsets(std::vector& validConnections); + bool ProvidedConnectionsMatch(ConnectionsCollection collection, ConnectionsList connections); StrSet GetValidSets(ContextItem& context, const std::string& clayer); void SetDefaultLinkerScript(ContextItem& context); void CheckAndGenerateRegionsHeader(ContextItem& context); diff --git a/tools/projmgr/src/ProjMgrWorker.cpp b/tools/projmgr/src/ProjMgrWorker.cpp index 224e0c89f..b67c02984 100644 --- a/tools/projmgr/src/ProjMgrWorker.cpp +++ b/tools/projmgr/src/ProjMgrWorker.cpp @@ -677,15 +677,15 @@ bool ProjMgrWorker::DiscoverMatchingLayers(ContextItem& context, const string& c debugMsg += "\n"; } // validate connections - ConnectionsList connections; - GetConsumesProvides(combination, connections); - ConnectionsValidationResult result = ValidateConnections(connections); + ConnectionsValidationResult result = ValidateConnections(combination); + + // update list of compatible layers if (result.valid) { context.validConnections.push_back(combination); for (const auto& [type, _] : matchedTypeClayers) { - for (const auto& item : combination) { - if (item.type == type) { - ProjMgrUtils::PushBackUniquely(context.compatibleLayers[type], item.filename); + for (const auto& collection : combination) { + if (collection.type == type) { + ProjMgrUtils::PushBackUniquely(context.compatibleLayers[type], collection.filename); } } } @@ -775,7 +775,7 @@ bool ProjMgrWorker::DiscoverMatchingLayers(ContextItem& context, const string& c void ProjMgrWorker::PrintConnectionsValidation(ConnectionsValidationResult result, string& msg) { if (!result.valid) { if (!result.conflicts.empty()) { - msg += "connections provided with multiple different values:"; + msg += "connections provided multiple times:"; for (const auto& id : result.conflicts) { msg += "\n " + id; } @@ -795,6 +795,20 @@ void ProjMgrWorker::PrintConnectionsValidation(ConnectionsValidationResult resul } msg += "\n"; } + + if (!result.missedCollections.empty()) { + msg += "provided combined connections not consumed:"; + for (const auto& missedCollection : result.missedCollections) { + msg += "\n " + missedCollection.filename + (missedCollection.type.empty() ? "" : " (layer type: " + missedCollection.type + ")"); + for (const auto& connect : missedCollection.connections) { + for (const auto& provided : connect->provides) { + msg += "\n " + provided.first; + } + } + } + msg += "\n"; + } + } } @@ -870,8 +884,13 @@ ConnectionsCollectionMap ProjMgrWorker::ClassifyConnections(const ConnectionsCol void ProjMgrWorker::GetConsumesProvides(const ConnectionsCollectionVec& collection, ConnectionsList& connections) { // collect consumed and provided connections + ConnectPtrVec visitedConnect; for (const auto& item : collection) { for (const auto& connect : item.connections) { + if (find(visitedConnect.begin(), visitedConnect.end(), connect) != visitedConnect.end()) { + continue; + } + visitedConnect.push_back(connect); for (const auto& consumed : connect->consumes) { connections.consumes.push_back(&consumed); } @@ -882,15 +901,40 @@ void ProjMgrWorker::GetConsumesProvides(const ConnectionsCollectionVec& collecti } } -ConnectionsValidationResult ProjMgrWorker::ValidateConnections(ConnectionsList& connections) { +bool ProjMgrWorker::ProvidedConnectionsMatch(ConnectionsCollection collection, ConnectionsList connections) { + // for a given collection check if provided connections match at least a consumed one + if (collection.connections.size() == 0) { + return true; + } + for (const auto& connect : collection.connections) { + if (connect->provides.size() == 0) { + return true; + } + for (const auto& provided : connect->provides) { + for (const auto& consumed : connections.consumes) { + if (provided.first == (*consumed).first) { + return true; + } + } + } + } + return false; +} + +ConnectionsValidationResult ProjMgrWorker::ValidateConnections(ConnectionsCollectionVec combination) { + // get connections + ConnectionsList connections; + GetConsumesProvides(combination, connections); + // elaborate provided list StrMap providedValues; StrVec conflicts; + vector missedCollections; for (const auto& provided : connections.provides) { const auto& key = provided->first; const auto& value = provided->second; - if ((providedValues.find(key) != providedValues.end()) && (providedValues.at(key) != value)) { - // interface is provided with multiple different values + if ((providedValues.find(key) != providedValues.end())) { + // connection is provided multiple times ProjMgrUtils::PushBackUniquely(conflicts, key); continue; } @@ -930,10 +974,16 @@ ConnectionsValidationResult ProjMgrWorker::ValidateConnections(ConnectionsList& incompatibles.push_back({ consumedKey, consumed->second }); } } + // validate provided connections of each combination match at least one consumed + for (const auto& collection : combination) { + if (!ProvidedConnectionsMatch(collection, connections)) { + missedCollections.push_back(collection); + } + } // set results - bool result = !conflicts.empty() || !overflows.empty() || !incompatibles.empty() ? false : true; - return { result, conflicts, overflows, incompatibles, connections.provides }; + bool result = !conflicts.empty() || !overflows.empty() || !incompatibles.empty() || !missedCollections.empty() ? false : true; + return { result, conflicts, overflows, incompatibles, missedCollections, connections.provides }; } bool ProjMgrWorker::ProcessDevice(ContextItem& context) { diff --git a/tools/projmgr/test/data/TestLayers/genericlayers.cproject.yml b/tools/projmgr/test/data/TestLayers/genericlayers.cproject.yml index c8f0c56ee..c8e1a31d6 100644 --- a/tools/projmgr/test/data/TestLayers/genericlayers.cproject.yml +++ b/tools/projmgr/test/data/TestLayers/genericlayers.cproject.yml @@ -23,8 +23,8 @@ project: - EmptyValues # key exact match, both values empty - AddedValueLessThanProvided: 99 # added consumed values are less than provided - AddedValueEqualToProvided: 998 # added consumed values are equal to provided - - MultipleProvided # same connection is provided multiple times with identical values # incompatible connections + - MultipleProvided # same connection is provided multiple times with identical values - MultipleProvidedNonIdentical0: 222 # same connection is provided multiple times with non identical values - MultipleProvidedNonIdentical1 # same connection is provided multiple times with non identical values - ProvidedDontMatch: 0 # consumed connection doesn't match provided one diff --git a/tools/projmgr/test/src/ProjMgrUnitTests.cpp b/tools/projmgr/test/src/ProjMgrUnitTests.cpp index 96b5fe90f..08232d441 100644 --- a/tools/projmgr/test/src/ProjMgrUnitTests.cpp +++ b/tools/projmgr/test/src/ProjMgrUnitTests.cpp @@ -1020,7 +1020,8 @@ check combined connections:\n\ .*/ARM/RteTest_DFP/0.2.0/Layers/incompatible.clayer.yml \\(layer type: Incompatible\\)\n\ \\(Incompatible Connections\\)\n\ .*/ARM/RteTest_DFP/0.2.0/Layers/pdsc-type-mismatch.clayer.yml \\(layer type: DifferentFromDescriptionInPdsc\\)\n\ -connections provided with multiple different values:\n\ +connections provided multiple times:\n\ + MultipleProvided\n\ MultipleProvidedNonIdentical0\n\ MultipleProvidedNonIdentical1\n\ required connections not provided:\n\ @@ -1028,6 +1029,11 @@ required connections not provided:\n\ ProvidedEmpty: 123\n\ sum of required values exceed provided:\n\ AddedValueHigherThanProvided: 100 > 99\n\ +provided combined connections not consumed:\n\ + .*/ARM/RteTest_DFP/0.2.0/Layers/incompatible.clayer.yml \\(layer type: Incompatible\\)\n\ + MultipleProvided\n\ + MultipleProvidedNonIdentical0\n\ + MultipleProvidedNonIdentical1\n\ connections are invalid\n\ \n\ check combined connections:\n\ @@ -1038,7 +1044,8 @@ check combined connections:\n\ .*/ARM/RteTest_DFP/0.2.0/Layers/incompatible.clayer.yml \\(layer type: Incompatible\\)\n\ \\(Incompatible Connections\\)\n\ .*/ARM/RteTest_DFP/0.2.0/Layers/pdsc-type-mismatch.clayer.yml \\(layer type: DifferentFromDescriptionInPdsc\\)\n\ -connections provided with multiple different values:\n\ +connections provided multiple times:\n\ + MultipleProvided\n\ MultipleProvidedNonIdentical0\n\ MultipleProvidedNonIdentical1\n\ required connections not provided:\n\ @@ -1046,6 +1053,11 @@ required connections not provided:\n\ ProvidedEmpty: 123\n\ sum of required values exceed provided:\n\ AddedValueHigherThanProvided: 100 > 99\n\ +provided combined connections not consumed:\n\ + .*/ARM/RteTest_DFP/0.2.0/Layers/incompatible.clayer.yml \\(layer type: Incompatible\\)\n\ + MultipleProvided\n\ + MultipleProvidedNonIdentical0\n\ + MultipleProvidedNonIdentical1\n\ connections are invalid\n\ \n\ check combined connections:\n\ @@ -1056,7 +1068,8 @@ check combined connections:\n\ .*/ARM/RteTest_DFP/0.2.0/Layers/incompatible.clayer.yml \\(layer type: Incompatible\\)\n\ \\(Incompatible Connections\\)\n\ .*/ARM/RteTest_DFP/0.2.0/Layers/pdsc-type-mismatch.clayer.yml \\(layer type: DifferentFromDescriptionInPdsc\\)\n\ -connections provided with multiple different values:\n\ +connections provided multiple times:\n\ + MultipleProvided\n\ MultipleProvidedNonIdentical0\n\ MultipleProvidedNonIdentical1\n\ required connections not provided:\n\ @@ -1064,6 +1077,11 @@ required connections not provided:\n\ ProvidedEmpty: 123\n\ sum of required values exceed provided:\n\ AddedValueHigherThanProvided: 100 > 99\n\ +provided combined connections not consumed:\n\ + .*/ARM/RteTest_DFP/0.2.0/Layers/incompatible.clayer.yml \\(layer type: Incompatible\\)\n\ + MultipleProvided\n\ + MultipleProvidedNonIdentical0\n\ + MultipleProvidedNonIdentical1\n\ connections are invalid\n\ \n\ no valid combination of clayers was found\n\ diff --git a/tools/projmgr/test/src/ProjMgrWorkerUnitTests.cpp b/tools/projmgr/test/src/ProjMgrWorkerUnitTests.cpp index 4323c6f32..4fd144222 100644 --- a/tools/projmgr/test/src/ProjMgrWorkerUnitTests.cpp +++ b/tools/projmgr/test/src/ProjMgrWorkerUnitTests.cpp @@ -1026,7 +1026,6 @@ TEST_F(ProjMgrWorkerUnitTests, GetAllSelectCombinations) { TEST_F(ProjMgrWorkerUnitTests, ValidateConnections) { ConnectionsValidationResult result; - ConnectionsList connections; // valid connections StrPairVec consumedList = { @@ -1038,26 +1037,20 @@ TEST_F(ProjMgrWorkerUnitTests, ValidateConnections) { {"Lemon", "+150"}, {"Lemon", "+20"}, }; - for (const auto& item : consumedList) { - connections.consumes.push_back(&item); - } StrPairVec providedList = { {"Orange", "3"}, // both key and value exact match {"Grape Fruit", "999"}, // key exact match, consumed value is empty {"Peach", ""}, // key exact match, both values empty {"Lemon", "200"}, // added consumed values are less than provided {"Lime", "100"}, // added consumed values are equal to provided - {"Ananas", "2"}, {"Ananas", "2"}, // same interface is provided multiple times with identical values }; - for (const auto& item : providedList) { - connections.provides.push_back(&item); - } - result = ValidateConnections(connections); + + ConnectItem validConnectItem = { RteUtils::EMPTY_STRING, RteUtils::EMPTY_STRING, RteUtils::EMPTY_STRING, providedList, consumedList }; + ConnectionsCollection validCollection = { RteUtils::EMPTY_STRING, RteUtils::EMPTY_STRING, {&validConnectItem} }; + result = ValidateConnections({ validCollection }); EXPECT_TRUE(result.valid); // invalid connections - connections.consumes.clear(); - connections.provides.clear(); // same interface is provided multiple times with non identical values consumedList = { {"Lemon", "+150"}, @@ -1065,23 +1058,20 @@ TEST_F(ProjMgrWorkerUnitTests, ValidateConnections) { {"Ananas", "98"}, {"Grape Fruit", "1"}, }; - for (const auto& item : consumedList) { - connections.consumes.push_back(&item); - } providedList = { {"Ananas", "97"}, // consumed interface doesn't match provided one {"Grape Fruit", ""}, // consumed interface doesn't match empty provided one {"Lemon", "160"}, // sum of consumed added values is higher than provided value + {"Ananas", "2"}, {"Ananas", "2"}, // same interface is provided multiple times with identical values {"Orange", "3"}, {"Orange", "4"}, // same interface is provided multiple times with non identical values {"Banana", ""}, {"Banana", "0"}, // same interface is provided multiple times with non identical values }; - for (const auto& item : providedList) { - connections.provides.push_back(&item); - } - StrVec expectedConflicts = { "Orange", "Banana" }; + StrVec expectedConflicts = { "Ananas", "Orange", "Banana" }; StrPairVec expectedOverflow = {{"Lemon", "170 > 160"}}; StrPairVec expectedIncompatibles = {{"Ananas", "98"}, {"Grape Fruit", "1"}}; - result = ValidateConnections(connections); + ConnectItem invalidConnectItem = { RteUtils::EMPTY_STRING, RteUtils::EMPTY_STRING, RteUtils::EMPTY_STRING, providedList, consumedList }; + ConnectionsCollection invalidCollection = { RteUtils::EMPTY_STRING, RteUtils::EMPTY_STRING, {&invalidConnectItem} }; + result = ValidateConnections({ invalidCollection }); EXPECT_FALSE(result.valid); EXPECT_EQ(result.conflicts, expectedConflicts); EXPECT_EQ(result.overflows, expectedOverflow);