查看原文
其他

开发者说丨使用GDB调试Apollo单元测试程序

贺志国 Apollo开发者社区 2022-07-29


Apollo使用Google Test框架撰写单元测试用例。如果某个测试用例通不过,仅借助日志信息,很难弄清楚详细的失败原因。本文介绍使用GDB调试单元测试用例的方法,可供各位同学撰写单元测试代码提供一定的帮助。

下面是由社区荣誉布道师——贺志国提供的文章使用GDB调试Apollo单元测试程序进行详细讲解,希望这篇文章能给感兴趣的开发者带来更多帮助。


说明:本文修改后的代码已上传到GitHub网站Apollo项目中。



  以下,ENJOY  





以RelativeMap中的单元测试用例进行说明。


首先在文件夹

modules/map/relative_map/testdata/multi_lane_map中增加如下测试数据文件:

chassis_info.pb.txtlocalization_info.pb.txtleft.smoothedmiddle.smoothedright.smoothed


接下来增加单元测试文件

modules/map/relative_map/navigation_lane_test.cc,内部代码如下(涉及到的Google Test框架知识不作介绍,大家自行上网查询):


1#include "modules/map/relative_map/navigation_lane.h"
2
3#include 
4#include 
5#include "gtest/gtest.h"
6#include "third_party/json/json.hpp"
7
8#include "modules/canbus/proto/chassis.pb.h"
9#include "modules/common/adapters/adapter_manager.h"
10#include "modules/common/vehicle_state/vehicle_state_provider.h"
11#include "modules/map/relative_map/common/relative_map_gflags.h"
12#include "modules/map/relative_map/proto/navigation.pb.h"
13#include "modules/map/relative_map/proto/relative_map_config.pb.h"
14
15namespace apollo {
16namespace relative_map {
17
18using apollo::common::VehicleStateProvider;
19using apollo::common::adapter::AdapterConfig;
20using apollo::common::adapter::AdapterManager;
21using apollo::common::adapter::AdapterManagerConfig;
22using apollo::relative_map::NavigationInfo;
23using apollo::relative_map::NavigationLane;
24using apollo::relative_map::NavigationPath;
25using nlohmann::json;
26
27namespace {
28bool GetNavigationPathFromFile(const std::string& filename,
29                               NavigationPath* navigation_path) 
{
30  CHECK_NOTNULL(navigation_path);
31
32  std::ifstream ifs(filename, std::ios::in);
33  if (!ifs.is_open()) {
34    AERROR << "Failed to open " << filename;
35    return false;
36  }
37  std::string line_str;
38  while (std::getline(ifs, line_str)) {
39    try {
40      auto json_obj = json::parse(line_str);
41      auto* point = navigation_path->mutable_path()->add_path_point();
42      point->set_x(json_obj["x"]);
43      point->set_y(json_obj["y"]);
44      point->set_s(json_obj["s"]);
45      point->set_theta(json_obj["theta"]);
46      point->set_kappa(json_obj["kappa"]);
47      point->set_dkappa(json_obj["dkappa"]);
48    } catch (const std::exception& e) {
49      AERROR << "Failed to parse JSON data: " << e.what();
50      return false;
51    }
52  }
53
54  return true;
55}
56
57bool GenerateNavigationInfo(
58    const std::vector<std::string>& navigation_line_filenames,
59    NavigationInfo* navigation_info) 
{
60  CHECK_NOTNULL(navigation_info);
61
62  int i = 0;
63  for (const std::string& filename : navigation_line_filenames) {
64    auto* navigation_path = navigation_info->add_navigation_path();
65    if (!GetNavigationPathFromFile(filename, navigation_path)) {
66      continue;
67    }
68    navigation_path->set_path_priority(i);
69    navigation_path->mutable_path()->set_name("Navigation path " + i);
70    ++i;
71  }
72  return navigation_info->navigation_path_size() > 0;
73}
74}  // namespace
75
76class NavigationLaneTest : public testing::Test {
77 public:
78  virtual void SetUp() {
79    common::adapter::AdapterManagerConfig adapter_conf;
80    RelativeMapConfig config;
81
82    EXPECT_TRUE(common::util::GetProtoFromFile(
83        FLAGS_relative_map_adapter_config_filename, &adapter_conf));
84    EXPECT_TRUE(common::util::GetProtoFromFile(
85        FLAGS_relative_map_config_filename, &config));
86
87    navigation_lane_.SetConfig(config.navigation_lane());
88    map_param_ = config.map_param();
89    navigation_lane_.SetDefaultWidth(map_param_.default_left_width(),
90                                     map_param_.default_right_width());
91
92    data_file_dir_ = "modules/map/relative_map/testdata/multi_lane_map/";
93
94    localization::LocalizationEstimate localization;
95    canbus::Chassis chassis;
96    EXPECT_TRUE(common::util::GetProtoFromFile(
97        data_file_dir_ + "localization_info.pb.txt", &localization));
98    EXPECT_TRUE(common::util::GetProtoFromFile(
99        data_file_dir_ + "chassis_info.pb.txt", &chassis));
100    VehicleStateProvider::instance()->Update(localization, chassis);
101  }
102
103 protected:
104  NavigationLane navigation_lane_;
105  NavigationInfo navigation_info_;
106  MapGenerationParam map_param_;
107  std::vector<std::string> navigation_line_filenames_;
108  std::string data_file_dir_;
109};
110
111TEST_F(NavigationLaneTest, GenerateOneLaneMap) {
112  navigation_line_filenames_.clear();
113  navigation_info_.Clear();
114  navigation_line_filenames_.emplace_back(data_file_dir_ + "left.smoothed");
115  EXPECT_TRUE(
116      GenerateNavigationInfo(navigation_line_filenames_, &navigation_info_));
117  navigation_lane_.UpdateNavigationInfo(navigation_info_);
118  EXPECT_TRUE(navigation_lane_.GeneratePath());
119  EXPECT_GT(navigation_lane_.Path().path().path_point_size(), 0);
120
121  MapMsg map_msg;
122  EXPECT_TRUE(navigation_lane_.CreateMap(map_param_, &map_msg));
123  EXPECT_EQ(1, map_msg.hdmap().lane_size());
124}
125
126TEST_F(NavigationLaneTest, GenerateTwoLaneMap) {
127  navigation_line_filenames_.clear();
128  navigation_info_.Clear();
129  navigation_line_filenames_.emplace_back(data_file_dir_ + "left.smoothed");
130  navigation_line_filenames_.emplace_back(data_file_dir_ + "right.smoothed");
131  EXPECT_TRUE(
132      GenerateNavigationInfo(navigation_line_filenames_, &navigation_info_));
133  navigation_lane_.UpdateNavigationInfo(navigation_info_);
134  EXPECT_TRUE(navigation_lane_.GeneratePath());
135  EXPECT_GT(navigation_lane_.Path().path().path_point_size(), 0);
136
137  MapMsg map_msg;
138  EXPECT_TRUE(navigation_lane_.CreateMap(map_param_, &map_msg));
139  EXPECT_EQ(2, map_msg.hdmap().lane_size());
140}
141
142TEST_F(NavigationLaneTest, GenerateThreeLaneMap) {
143  navigation_line_filenames_.clear();
144  navigation_info_.Clear();
145  navigation_line_filenames_.emplace_back(data_file_dir_ + "left.smoothed");
146  navigation_line_filenames_.emplace_back(data_file_dir_ + "middle.smoothed");
147  navigation_line_filenames_.emplace_back(data_file_dir_ + "right.smoothed");
148  EXPECT_TRUE(
149      GenerateNavigationInfo(navigation_line_filenames_, &navigation_info_));
150  navigation_lane_.UpdateNavigationInfo(navigation_info_);
151  EXPECT_TRUE(navigation_lane_.GeneratePath());
152  EXPECT_GT(navigation_lane_.Path().path().path_point_size(), 0);
153
154  MapMsg map_msg;
155  EXPECT_TRUE(navigation_lane_.CreateMap(map_param_, &map_msg));
156  EXPECT_EQ(3, map_msg.hdmap().lane_size());
157}
158
159}  // namespace relative_map
160}  // namespace apollo

<左右滑动以查看完整代码>


最后,在编译文件modules/map/relative_map/BUILD中添加如下内容:

1filegroup(
2    name = "testdata",
3    srcs = glob([
4        "testdata/**",
5    ]),
6)
7
8cc_test(
9    name = "navigation_lane_test",
10    size = "small",
11    srcs = [
12        "navigation_lane_test.cc",
13    ], 
14    data = [
15        ":testdata",
16    ],   
17    deps = [
18        ":relative_map_lib",
19        "//modules/common",        
20        "//third_party/json",
21        "@gtest//:main",
22    ],
23)

<左右滑动以查看完整代码>


重新编译整个Apollo项目。




重新编译Apollo项目后,会在bazel-bin/modules/map/relative_map/目录中生成可执行程序navigation_lane_test,直接使用GDB在Docker中调试该程序即可,具体操作步骤如下:


1# 进入Apollo项目根目录(我的路径为:`~/code/apollo`,你需要修改为自己的路径)
2cd ~/code/apollo
3# 启动Apollo项目的Docker(注意:2.0以上版本在后面加上一个“-C”选项,
4# 表示从中国服务器拉取镜像文件,以加快下载速度)
5bash docker/scripts/dev_start.sh
6# 进入Docker
7bash docker/scripts/dev_into.sh

<左右滑动以查看完整代码>


1gdb -q bazel-bin/modules/map/relative_map/navigation_lane_test

<左右滑动以查看完整代码>


进入GDB调试界面后,使用l命令查看源代码,使用b 138在源代码第138行(可根据需要修改为自己所需的代码位置 )设置断点,使用r命令运行navigation_lane_test程序,进入断点暂停后,使用p navigation_lane_查看当前变量值(可根据需要修改为其他变量名),使用n单步调试一条语句,使用s单步调试进入函数内部,使用c继续执行后续程序。如果哪个部分测试通不过,调试信息会立刻告诉你具体原因,可使用bt查看当前调用堆栈



以上是"使用GDB调试Apollo单元测试程序"的全部内容,更多话题讨论、技术交流可以扫描下方二维码添加『Apollo小哥哥』为好友,进开发者交流群。






* 以上内容为开发者原创,不代表百度官方言论。

内容来自开发者CSDN:

https://blog.csdn.net/davidhopper/article/details/82589722,欢迎大家收藏点赞。已获开发者授权,原文地址请戳阅读原文。






您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存