INSTINCT Code Coverage Report


Directory: src/
File: Nodes/Utility/Merger.cpp
Date: 2025-02-07 16:54:41
Exec Total Coverage
Lines: 57 92 62.0%
Functions: 9 10 90.0%
Branches: 58 204 28.4%

Line Branch Exec Source
1 // This file is part of INSTINCT, the INS Toolkit for Integrated
2 // Navigation Concepts and Training by the Institute of Navigation of
3 // the University of Stuttgart, Germany.
4 //
5 // This Source Code Form is subject to the terms of the Mozilla Public
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
7 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
8
9 #include "Merger.hpp"
10
11 #include "internal/NodeManager.hpp"
12 namespace nm = NAV::NodeManager;
13 #include "internal/FlowManager.hpp"
14
15 #include "NodeRegistry.hpp"
16
17 #include "NodeData/NodeData.hpp"
18
19 114 NAV::Merger::Merger()
20
2/4
✓ Branch 1 taken 114 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 114 times.
✗ Branch 5 not taken.
114 : Node(typeStatic())
21 {
22 LOG_TRACE("{}: called", name);
23
24 114 _hasConfig = false;
25 114 kind = Kind::Simple;
26
27
4/8
✓ Branch 1 taken 114 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 114 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 114 times.
✓ Branch 9 taken 114 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
342 nm::CreateInputPin(this, "", Pin::Type::Flow, { NodeData::type() }, &Merger::receiveData);
28
4/8
✓ Branch 1 taken 114 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 114 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 114 times.
✓ Branch 9 taken 114 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
342 nm::CreateInputPin(this, "", Pin::Type::Flow, { NodeData::type() }, &Merger::receiveData);
29
4/8
✓ Branch 2 taken 114 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 114 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 114 times.
✓ Branch 10 taken 114 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
456 nm::CreateOutputPin(this, "", Pin::Type::Flow, { NodeData::type() });
30 456 }
31
32 232 NAV::Merger::~Merger()
33 {
34 LOG_TRACE("{}: called", nameId());
35 232 }
36
37 226 std::string NAV::Merger::typeStatic()
38 {
39
1/2
✓ Branch 1 taken 226 times.
✗ Branch 2 not taken.
452 return "Merger";
40 }
41
42 std::string NAV::Merger::type() const
43 {
44 return typeStatic();
45 }
46
47 112 std::string NAV::Merger::category()
48 {
49
1/2
✓ Branch 1 taken 112 times.
✗ Branch 2 not taken.
224 return "Utility";
50 }
51
52 2 void NAV::Merger::setPinIdentifiers(size_t connectedPinIndex, size_t otherPinIndex, const std::vector<std::string>& dataIdentifiers)
53 {
54
2/4
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
2 LOG_DEBUG("{}: Setting DataIdentifier on pinIndex {}", nameId(), otherPinIndex);
55
56 2 inputPins.at(connectedPinIndex).dataIdentifier = dataIdentifiers;
57
58
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 if (!inputPins.at(otherPinIndex).isPinLinked())
59 {
60 2 inputPins.at(otherPinIndex).dataIdentifier = dataIdentifiers;
61
2/2
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 2 times.
4 for (const auto& dataIdentifier : dataIdentifiers)
62 {
63
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 auto parentIdentifiers = NodeRegistry::GetParentNodeDataTypes(dataIdentifier);
64
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
2 std::erase(parentIdentifiers, NodeData::type());
65
3/6
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 11 taken 2 times.
✗ Branch 12 not taken.
2 inputPins.at(otherPinIndex).dataIdentifier.insert(inputPins.at(otherPinIndex).dataIdentifier.end(), parentIdentifiers.rbegin(), parentIdentifiers.rend());
66 2 }
67
68 // Update the dataIdentifier of the output pin to the same as input pin
69 2 outputPins.at(OUTPUT_PORT_INDEX_FLOW).dataIdentifier = dataIdentifiers;
70 }
71 else
72 {
73 std::vector<std::string> combinedIdentifiers;
74 for (const auto& dataIdentifier : inputPins.at(connectedPinIndex).dataIdentifier)
75 {
76 if (auto iter = std::find(inputPins.at(otherPinIndex).dataIdentifier.begin(), inputPins.at(otherPinIndex).dataIdentifier.end(), dataIdentifier);
77 iter != inputPins.at(otherPinIndex).dataIdentifier.end())
78 {
79 combinedIdentifiers.push_back(*iter);
80 }
81 }
82 if (!combinedIdentifiers.empty())
83 {
84 outputPins.at(OUTPUT_PORT_INDEX_FLOW).dataIdentifier = combinedIdentifiers;
85 return;
86 }
87
88 std::vector<std::string> connectedPinParents;
89 for (const auto& dataIdentifier : inputPins.at(connectedPinIndex).dataIdentifier)
90 {
91 auto parentIdentifiers = NodeRegistry::GetParentNodeDataTypes(dataIdentifier);
92 std::erase(parentIdentifiers, NodeData::type());
93 connectedPinParents.insert(connectedPinParents.begin(), parentIdentifiers.begin(), parentIdentifiers.end());
94 }
95
96 for (const auto& dataIdentifier : inputPins.at(otherPinIndex).dataIdentifier)
97 {
98 if (std::ranges::find(connectedPinParents, dataIdentifier) != connectedPinParents.end())
99 {
100 outputPins.at(OUTPUT_PORT_INDEX_FLOW).dataIdentifier = inputPins.at(otherPinIndex).dataIdentifier;
101 }
102 else
103 {
104 outputPins.at(OUTPUT_PORT_INDEX_FLOW).dataIdentifier = inputPins.at(connectedPinIndex).dataIdentifier;
105 }
106 }
107 }
108 }
109
110 2 void NAV::Merger::updateOutputPin(const std::vector<std::string>& oldDataIdentifiers)
111 {
112 // Check if connected links on output port are still valid
113
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 2 times.
2 for (auto& link : outputPins.at(OUTPUT_PORT_INDEX_FLOW).links)
114 {
115 if (auto* endPin = link.getConnectedPin())
116 {
117 if (outputPins.at(OUTPUT_PORT_INDEX_FLOW).canCreateLink(*endPin))
118 {
119 continue;
120 }
121
122 // If the link is not valid anymore, delete it
123 outputPins.at(OUTPUT_PORT_INDEX_FLOW).deleteLink(*endPin);
124 }
125 }
126
127 // Refresh all links connected to the output pin if the type changed
128
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 if (outputPins.at(OUTPUT_PORT_INDEX_FLOW).dataIdentifier != oldDataIdentifiers)
129 {
130
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 2 times.
2 for (auto& link : outputPins.at(OUTPUT_PORT_INDEX_FLOW).links)
131 {
132 if (auto* connectedPin = link.getConnectedPin())
133 {
134 outputPins.at(OUTPUT_PORT_INDEX_FLOW).recreateLink(*connectedPin);
135 }
136 }
137 }
138 2 }
139
140 4 bool NAV::Merger::onCreateLink(OutputPin& startPin, InputPin& endPin)
141 {
142 LOG_TRACE("{}: called for {} ==> {}", nameId(), size_t(startPin.id), size_t(endPin.id));
143
144
3/4
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 2 times.
4 if (endPin.parentNode->id != id) // Link on Output Port
145 {
146
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
2 if (!inputPins.at(INPUT_PORT_INDEX_FLOW_FIRST).isPinLinked()
147
2/10
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 2 times.
2 && !inputPins.at(INPUT_PORT_INDEX_FLOW_SECOND).isPinLinked())
148 {
149 outputPins.at(OUTPUT_PORT_INDEX_FLOW).dataIdentifier = endPin.dataIdentifier;
150 }
151 2 return true;
152 }
153
154
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 size_t connectedPinIndex = inputPinIndexFromId(endPin.id);
155
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 size_t otherPinIndex = connectedPinIndex == INPUT_PORT_INDEX_FLOW_FIRST ? INPUT_PORT_INDEX_FLOW_SECOND : INPUT_PORT_INDEX_FLOW_FIRST;
156
157
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
2 auto outputPinIdentifier = outputPins.at(OUTPUT_PORT_INDEX_FLOW).dataIdentifier;
158
159
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 setPinIdentifiers(connectedPinIndex, otherPinIndex, startPin.dataIdentifier);
160
161
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 updateOutputPin(outputPinIdentifier);
162
163 2 return true;
164 2 }
165
166 4 void NAV::Merger::afterDeleteLink([[maybe_unused]] OutputPin& startPin, InputPin& endPin)
167 {
168 LOG_TRACE("{}: called for {} ==> {}", nameId(), size_t(startPin.id), size_t(endPin.id));
169
170
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
4 if (endPin.parentNode->id != id) // Link on Output Pin
171 {
172 2 return;
173 }
174
175 // Link on Input Pin
176
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 for (size_t pinIdx = 0; pinIdx < inputPins.size(); pinIdx++)
177 {
178 4 auto& pin = inputPins[pinIdx];
179
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
4 if (endPin.id != pin.id) // The other pin (which is not deleted)
180 {
181
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (pin.isPinLinked())
182 {
183 size_t otherPinIndex = pinIdx == INPUT_PORT_INDEX_FLOW_FIRST ? INPUT_PORT_INDEX_FLOW_SECOND : INPUT_PORT_INDEX_FLOW_FIRST;
184
185 auto* otherNodePin = pin.link.getConnectedPin();
186
187 auto outputPinIdentifier = outputPins.at(OUTPUT_PORT_INDEX_FLOW).dataIdentifier;
188
189 setPinIdentifiers(pinIdx, otherPinIndex, otherNodePin->dataIdentifier);
190
191 updateOutputPin(outputPinIdentifier);
192 }
193 else
194 {
195
2/2
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 2 times.
6 for (auto& pinReset : inputPins)
196 {
197
2/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
8 pinReset.dataIdentifier = { NodeData::type() };
198 }
199 }
200 2 break;
201 }
202 }
203 4 }
204
205 202 void NAV::Merger::receiveData(InputPin::NodeDataQueue& queue, size_t /* pinIdx */)
206 {
207
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 202 times.
202 if (!(NAV::Node::callbacksEnabled))
208 {
209 NAV::Node::callbacksEnabled = true;
210 }
211
212
2/4
✓ Branch 1 taken 202 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 202 times.
✗ Branch 5 not taken.
202 invokeCallbacks(OUTPUT_PORT_INDEX_FLOW, queue.extract_front());
213 202 }
214