forked from autowarefoundation/autoware_universe
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtest_diagnostics_interface.cpp
176 lines (143 loc) · 6.17 KB
/
test_diagnostics_interface.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
// Copyright 2024 Autoware Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "autoware/universe_utils/ros/diagnostics_interface.hpp"
#include <rclcpp/rclcpp.hpp>
#include <diagnostic_msgs/msg/diagnostic_array.hpp>
#include <diagnostic_msgs/msg/diagnostic_status.hpp>
#include <diagnostic_msgs/msg/key_value.hpp>
#include <gtest/gtest.h>
using autoware::universe_utils::DiagnosticInterface;
class TestDiagnosticInterface : public ::testing::Test
{
protected:
void SetUp() override
{
// Create a test node
node_ = std::make_shared<rclcpp::Node>("test_diagnostics_interface");
}
// Automatically destroyed at the end of each test
std::shared_ptr<rclcpp::Node> node_;
};
/*
* Test clear():
* Verify that calling clear() resets DiagnosticStatus values, level, and message.
*/
TEST_F(TestDiagnosticInterface, ClearTest)
{
DiagnosticInterface module(node_.get(), "test_diagnostic");
// Add some key-value pairs and update level/message
module.add_key_value("param1", 42);
module.update_level_and_message(
diagnostic_msgs::msg::DiagnosticStatus::WARN, "Something is not OK");
// Call clear()
module.clear();
// After calling clear(), publish and check the contents of the message
diagnostic_msgs::msg::DiagnosticArray::ConstSharedPtr received_msg;
auto sub = node_->create_subscription<diagnostic_msgs::msg::DiagnosticArray>(
"/diagnostics", 10,
[&](diagnostic_msgs::msg::DiagnosticArray::ConstSharedPtr msg) { received_msg = msg; });
// Publish the message
module.publish(node_->now());
// Spin to allow the subscriber to receive messages
rclcpp::spin_some(node_);
ASSERT_NE(nullptr, received_msg);
ASSERT_FALSE(received_msg->status.empty());
const auto & status = received_msg->status.front();
// After clear(), key-value pairs should be empty
EXPECT_TRUE(status.values.empty());
// After clear(), level should be OK (=0)
EXPECT_EQ(status.level, diagnostic_msgs::msg::DiagnosticStatus::OK);
// After clear(), message is empty internally,
// but "OK" is set during publishing when level == OK
EXPECT_EQ(status.message, "OK");
}
/*
* Test add_key_value():
* Verify that adding the same key updates its value instead of adding a duplicate.
*/
TEST_F(TestDiagnosticInterface, AddKeyValueTest)
{
DiagnosticInterface module(node_.get(), "test_diagnostic");
// Call the template version of add_key_value() with different types
module.add_key_value("string_key", std::string("initial_value"));
module.add_key_value("int_key", 123);
module.add_key_value("bool_key", true);
// Overwrite the value for "string_key"
module.add_key_value("string_key", std::string("updated_value"));
// Capture the published message to verify its contents
diagnostic_msgs::msg::DiagnosticArray::ConstSharedPtr received_msg;
auto sub = node_->create_subscription<diagnostic_msgs::msg::DiagnosticArray>(
"/diagnostics", 10,
[&](diagnostic_msgs::msg::DiagnosticArray::ConstSharedPtr msg) { received_msg = msg; });
module.publish(node_->now());
rclcpp::spin_some(node_);
ASSERT_NE(nullptr, received_msg);
ASSERT_FALSE(received_msg->status.empty());
const auto & status = received_msg->status.front();
// Expect 3 key-value pairs
ASSERT_EQ(status.values.size(), 3U);
// Helper lambda to find a value by key
auto find_value = [&](const std::string & key) -> std::string {
for (const auto & kv : status.values) {
if (kv.key == key) {
return kv.value;
}
}
return "";
};
EXPECT_EQ(find_value("string_key"), "updated_value");
EXPECT_EQ(find_value("int_key"), "123");
EXPECT_EQ(find_value("bool_key"), "True");
// Status level should still be OK
EXPECT_EQ(status.level, diagnostic_msgs::msg::DiagnosticStatus::OK);
// Message should be "OK"
EXPECT_EQ(status.message, "OK");
}
/*
* Test update_level_and_message():
* Verify that the level is updated to the highest severity and
* that messages are concatenated if level > OK.
*/
TEST_F(TestDiagnosticInterface, UpdateLevelAndMessageTest)
{
DiagnosticInterface module(node_.get(), "test_diagnostic");
// Initial status is level=OK(0), message=""
module.update_level_and_message(diagnostic_msgs::msg::DiagnosticStatus::OK, "Initial OK");
// Update to WARN (1)
module.update_level_and_message(diagnostic_msgs::msg::DiagnosticStatus::WARN, "Low battery");
// Update to ERROR (2)
module.update_level_and_message(diagnostic_msgs::msg::DiagnosticStatus::ERROR, "Sensor failure");
// Another WARN (1) after ERROR should not downgrade the overall level
module.update_level_and_message(
diagnostic_msgs::msg::DiagnosticStatus::WARN, "Should not override error");
diagnostic_msgs::msg::DiagnosticArray::ConstSharedPtr received_msg;
auto sub = node_->create_subscription<diagnostic_msgs::msg::DiagnosticArray>(
"/diagnostics", 10,
[&](diagnostic_msgs::msg::DiagnosticArray::ConstSharedPtr msg) { received_msg = msg; });
module.publish(node_->now());
rclcpp::spin_some(node_);
ASSERT_NE(nullptr, received_msg);
ASSERT_FALSE(received_msg->status.empty());
const auto & status = received_msg->status.front();
// Final level should be ERROR (2)
EXPECT_EQ(status.level, diagnostic_msgs::msg::DiagnosticStatus::ERROR);
// The message should contain all parts that were added when level > OK.
// Thus, we expect something like:
// "Low battery; Sensor failure; Should not override error"
const std::string & final_message = status.message;
EXPECT_FALSE(final_message.find("Initial OK") != std::string::npos);
EXPECT_TRUE(final_message.find("Low battery") != std::string::npos);
EXPECT_TRUE(final_message.find("Sensor failure") != std::string::npos);
EXPECT_TRUE(final_message.find("Should not override error") != std::string::npos);
}