DBC Framework
DBC parsing and CAN signal decoding framework
Loading...
Searching...
No Matches
tree_node_test.cpp
1// Standalone C++17 test: no Qt required.
2#include "dbc_tree_builder.h"
3#include <limits>
4#include <stdexcept>
5#include <type_traits>
6
7static void Check(bool condition) {
8 if (!condition) throw std::runtime_error("Tree navigation test failed");
9}
10
11static void CheckNavigation(const TreeNode &node) {
12 for (std::size_t row = 0; row < node.GetChildCount(); ++row) {
13 const TreeNode *child = node.GetChild(row);
14 Check(child->GetParent() == &node && child->GetRow() == row);
15 Check(child->GetParent()->GetChild(child->GetRow()) == child);
16 CheckNavigation(*child);
17 }
18 Check(!node.GetChild(node.GetChildCount()));
19 Check(!node.GetChild(std::numeric_limits<std::size_t>::max()));
20}
21
22static void CheckRejectedInsertion(TreeNode &parent, std::unique_ptr<TreeNode> &owner) {
23 const TreeNode *original = owner.get();
24 bool rejected = false;
25 try {
26 parent.AddChild(std::move(owner));
27 } catch (const std::invalid_argument &) {
28 rejected = true;
29 }
30 Check(rejected && owner.get() == original);
31 CheckNavigation(*owner);
32}
33
34int main() {
35 static_assert(!std::is_copy_constructible<TreeNode>::value, "Nodes have exclusive ownership");
36 static_assert(!std::is_copy_assignable<TreeNode>::value, "Nodes have exclusive ownership");
37 static_assert(!std::is_move_constructible<TreeNode>::value, "Node addresses must be stable");
38 static_assert(!std::is_move_assignable<TreeNode>::value, "Node addresses must be stable");
39 CheckNavigation(*DbcTreeBuilder().Build(DbcDatabase()));
40
41 DbcDatabase database;
42 FrameInfo frame;
43 frame.canId = 123U;
44 frame.name = "Frame";
45 SignalInfo signal;
46 signal.name = "Value";
47 frame.signals.push_back(signal);
48 signal.name = "Other";
49 frame.signals.push_back(signal);
50 database.frames.push_back(frame);
51 frame.isExtended = true;
52 database.frames.push_back(frame);
53 std::unique_ptr<TreeNode> root = DbcTreeBuilder().Build(database);
54 Check(root->GetParent() == nullptr && root->GetRow() == 0);
55 Check(!root->GetFrameKey() && !root->GetSignalKey());
56 root->AddChild(nullptr);
57 Check(root->GetChildCount() == 2 && !root->GetChild(2));
58 Check(!root->GetChild(std::numeric_limits<std::size_t>::max()));
59 CheckNavigation(*root);
60
61 const TreeNode *firstFrame = root->GetChild(0);
62 const TreeNode *firstSignal = firstFrame->GetChild(0);
63 const FrameKey standard(123U, false);
64 const FrameKey extended(123U, true);
65 Check(firstFrame->GetFrameKey() == standard && !firstFrame->GetSignalKey());
66 Check(firstSignal->GetFrameKey() == standard);
67 Check(firstSignal->GetSignalKey() == SignalKey(standard, "Value"));
68 Check(firstFrame->GetChild(1)->GetSignalKey() == SignalKey(standard, "Other"));
69 Check(root->GetChild(1)->GetFrameKey() == extended);
70 Check(root->GetChild(1)->GetChild(0)->GetSignalKey() == SignalKey(extended, "Value"));
71
72 TreeNode detached(signal);
73 Check(!detached.GetFrameKey() && !detached.GetSignalKey());
74 Check(!detached.GetParent() && detached.GetRow() == 0);
75 TreeNode detachedFrame(frame);
76 Check(detachedFrame.GetFrameKey() == extended && !detachedFrame.GetSignalKey());
77
78 // Reordering/reloading source metadata does not change the original tree's keys.
79 database.frames.clear();
80 database.frames.push_back(frame);
81 std::unique_ptr<TreeNode> replacement = DbcTreeBuilder().Build(database);
82 Check(replacement->GetChild(0)->GetFrameKey() == root->GetChild(1)->GetFrameKey());
83 Check(firstSignal->GetSignalKey() == SignalKey(standard, "Value"));
84
85 // Grow both child vectors, retaining all existing addresses and rows.
86 for (std::size_t index = 0; index < 64; ++index) {
87 root->AddChild(std::make_unique<TreeNode>(frame));
88 root->GetChild(0)->AddChild(std::make_unique<TreeNode>(signal));
89 }
90 Check(root->GetChild(0) == firstFrame && firstFrame->GetChild(0) == firstSignal);
91 CheckNavigation(*root);
92 CheckRejectedInsertion(*root, root);
93 CheckRejectedInsertion(*root->GetChild(0)->GetChild(0), root);
94
95 const TreeNode *original = root.get();
96 std::unique_ptr<TreeNode> transferred = std::move(root);
97 Check(!root && transferred.get() == original);
98 CheckNavigation(*transferred);
99 Check(firstSignal->GetSignalKey() == SignalKey(standard, "Value"));
100}
Builds a simple tree from parsed DBC database.
std::unique_ptr< TreeNode > Build(const DbcDatabase &database) const
Build tree representation of parsed DBC data.
Tree node for later use in model/view or other hierarchy consumers.
Definition tree_node.h:37
std::optional< SignalKey > GetSignalKey() const
Definition tree_node.cpp:91
const TreeNode * GetChild(std::size_t index) const
Get child by index.
Definition tree_node.cpp:45
const TreeNode * GetParent() const
Definition tree_node.cpp:75
std::size_t GetChildCount() const
Get child count.
Definition tree_node.cpp:41
std::size_t GetRow() const
Definition tree_node.cpp:79
std::optional< FrameKey > GetFrameKey() const
Definition tree_node.cpp:83
void AddChild(std::unique_ptr< TreeNode > &&child)
Add child node.
Definition tree_node.cpp:27
Metadata tree builder.
int main(int argc, char *argv[])
Parse a DBC file and demonstrate metadata lookup and CAN decoding.
Parsed DBC content stored in a simple internal form.
std::vector< FrameInfo > frames
Describes one CAN frame from a DBC file.
Definition frame_info.h:25
bool isExtended
Definition frame_info.h:28
std::string name
Definition frame_info.h:26
std::uint32_t canId
Definition frame_info.h:27
Stable frame identifier: normalized CAN ID and frame type.
Describes one signal inside a DBC frame.
Definition signal_info.h:25
std::string name
Definition signal_info.h:27