INSTINCT Code Coverage Report


Directory: src/
File: internal/ConfigManager.cpp
Date: 2025-02-07 16:54:41
Exec Total Coverage
Lines: 64 122 52.5%
Functions: 5 9 55.6%
Branches: 136 508 26.8%

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 "ConfigManager.hpp"
10
11 #include <string>
12 #include <filesystem>
13 #include <fstream>
14 #include <iostream>
15 #include <boost/program_options/parsers.hpp>
16 #include <implot.h>
17 #include <implot_internal.h>
18
19 #include "internal/FlowManager.hpp"
20 #include "util/Logger.hpp"
21
22 #include <boost/tokenizer.hpp>
23
24 #include "util/Json.hpp"
25 #include "util/Plot/Colormap.hpp"
26 #include "internal/gui/windows/Screenshotter.hpp"
27
28 namespace bpo = boost::program_options;
29
30 /// Program option description
31 bpo::options_description program_options{ "Allowed options" }; // NOLINT
32
33 /// Map which stores all options
34 boost::program_options::variables_map NAV::ConfigManager::vm; // NOLINT
35
36 383 void NAV::ConfigManager::initialize()
37 {
38 LOG_TRACE("called");
39
40
2/2
✓ Branch 2 taken 264 times.
✓ Branch 3 taken 119 times.
383 if (program_options.options().empty())
41 {
42 // clang-format off
43 // See https://www.boost.org/doc/libs/1_72_0/doc/html/program_options.html
44
1/2
✓ Branch 1 taken 264 times.
✗ Branch 2 not taken.
264 program_options.add_options()
45
2/4
✓ Branch 1 taken 264 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 264 times.
✗ Branch 6 not taken.
264 ("config", bpo::value<std::vector<std::string>>()->multitoken(), "List of configuration files to read parameters from" )
46
1/2
✓ Branch 1 taken 264 times.
✗ Branch 2 not taken.
264 ("version,v", "Display the version number" )
47
1/2
✓ Branch 1 taken 264 times.
✗ Branch 2 not taken.
264 ("help,h", "Display this help message" )
48
3/6
✓ Branch 1 taken 264 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 264 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 264 times.
✗ Branch 8 not taken.
264 ("sigterm", bpo::bool_switch()->default_value(false), "Programm waits for -SIGUSR1 / -SIGINT / -SIGTERM" )
49
3/6
✓ Branch 1 taken 264 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 264 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 264 times.
✗ Branch 8 not taken.
264 ("duration", bpo::value<size_t>()->default_value(0), "Program execution duration [sec]" )
50
3/6
✓ Branch 1 taken 264 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 264 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 264 times.
✗ Branch 8 not taken.
264 ("nogui", bpo::bool_switch()->default_value(false), "Launch without the gui" )
51
3/6
✓ Branch 1 taken 264 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 264 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 264 times.
✗ Branch 8 not taken.
264 ("noinit", bpo::bool_switch()->default_value(false), "Do not initialize flows after loading them" )
52
2/4
✓ Branch 1 taken 264 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 264 times.
✗ Branch 5 not taken.
264 ("load,l", bpo::value<std::string>(), "Flow file to load" )
53
3/6
✓ Branch 1 taken 264 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 264 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 264 times.
✗ Branch 8 not taken.
264 ("rotate-output", bpo::bool_switch()->default_value(false), "Create new folders for output files" )
54
4/8
✓ Branch 1 taken 264 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 264 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 264 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 264 times.
✗ Branch 11 not taken.
792 ("output-path,o", bpo::value<std::string>()->default_value("logs"), "Directory path for logs and output files" )
55
4/8
✓ Branch 1 taken 264 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 264 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 264 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 264 times.
✗ Branch 11 not taken.
792 ("input-path,i", bpo::value<std::string>()->default_value("data"), "Directory path for searching input files" )
56
4/8
✓ Branch 1 taken 264 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 264 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 264 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 264 times.
✗ Branch 11 not taken.
792 ("flow-path,f", bpo::value<std::string>()->default_value("flow"), "Directory path for searching flow files" )
57
4/8
✓ Branch 1 taken 264 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 264 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 264 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 264 times.
✗ Branch 11 not taken.
792 ("implot-config", bpo::value<std::string>()->default_value("implot.json"), "Config file to read implot settings from" )
58
4/8
✓ Branch 1 taken 264 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 264 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 264 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 264 times.
✗ Branch 11 not taken.
792 ("global-log-level", bpo::value<std::string>()->default_value("trace"), "Global log level of all sinks (possible values: trace/debug/info/warning/error/critical/off" )
59
4/8
✓ Branch 1 taken 264 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 264 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 264 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 264 times.
✗ Branch 11 not taken.
792 ("console-log-level", bpo::value<std::string>()->default_value("info"), "Log level on the console (possible values: trace/debug/info/warning/error/critical/off" )
60
4/8
✓ Branch 1 taken 264 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 264 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 264 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 264 times.
✗ Branch 11 not taken.
792 ("file-log-level", bpo::value<std::string>()->default_value("debug"), "Log level to the log file (possible values: trace/debug/info/warning/error/critical/off" )
61
4/8
✓ Branch 1 taken 264 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 264 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 264 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 264 times.
✗ Branch 11 not taken.
1056 ("flush-log-level", bpo::value<std::string>()->default_value("info"), "Log level to flush on (possible values: trace/debug/info/warning/error/critical/off" )
62
2/4
✓ Branch 1 taken 264 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 264 times.
✗ Branch 5 not taken.
264 ("log-filter", bpo::value<std::string>(), "Filter/Regex for log messages" )
63 ;
64 // clang-format on
65 }
66 383 }
67
68 383 void NAV::ConfigManager::deinitialize()
69 {
70 383 vm.clear();
71 383 }
72
73 const boost::program_options::options_description& NAV::ConfigManager::GetProgramOptions()
74 {
75 return program_options;
76 }
77
78 383 std::vector<std::string> NAV::ConfigManager::FetchConfigs(const int argc, const char* argv[]) // NOLINT
79 {
80
2/4
✓ Branch 2 taken 383 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 383 times.
✗ Branch 6 not taken.
383 bpo::store(bpo::parse_command_line(argc, argv, program_options), vm);
81
82 383 std::vector<std::string> failedConfigFiles;
83
84 // if config file is available, the parameters from file will be added
85
4/6
✓ Branch 1 taken 383 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 383 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✓ Branch 8 taken 381 times.
766 if (vm.count("config"))
86 {
87
5/8
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 15 taken 4 times.
✓ Branch 16 taken 2 times.
8 for (const std::string& configFile : vm["config"].as<std::vector<std::string>>())
88 {
89
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 std::filesystem::path filepath{ configFile };
90
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 if (filepath.is_relative())
91 {
92
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 filepath = NAV::flow::GetProgramRootPath();
93
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 filepath /= configFile;
94 }
95
96
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 std::ifstream ifs{ filepath };
97
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 3 times.
4 if (ifs.good())
98 {
99
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 bpo::store(bpo::parse_config_file(ifs, program_options), vm);
100 }
101 else
102 {
103
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 failedConfigFiles.push_back(configFile);
104 }
105 4 }
106 }
107
108
1/2
✓ Branch 1 taken 383 times.
✗ Branch 2 not taken.
383 bpo::notify(vm);
109
110 383 return failedConfigFiles;
111 }
112
113 112 void NAV::ConfigManager::CheckOptions(const int argc, [[maybe_unused]] const char* argv[]) // NOLINT
114 {
115
1/2
✓ Branch 3 taken 112 times.
✗ Branch 4 not taken.
112 LOG_DEBUG("{} arguments were provided over the command line", argc);
116
117
2/2
✓ Branch 2 taken 448 times.
✓ Branch 3 taken 112 times.
560 for (const char* logger : { "global-log-level", "console-log-level", "file-log-level", "flush-log-level" })
118 {
119
5/14
✓ Branch 1 taken 448 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 448 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 448 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 448 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 448 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
1792 if (vm[logger].as<std::string>() != "trace"
120
8/18
✓ Branch 1 taken 112 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 112 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 112 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 112 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 112 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 112 times.
✓ Branch 16 taken 336 times.
✓ Branch 17 taken 448 times.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
672 && vm[logger].as<std::string>() != "debug"
121
9/18
✓ Branch 1 taken 112 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 112 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 112 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 112 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 112 times.
✓ Branch 15 taken 112 times.
✓ Branch 16 taken 336 times.
✓ Branch 17 taken 112 times.
✓ Branch 18 taken 336 times.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
672 && vm[logger].as<std::string>() != "info"
122
3/18
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 15 not taken.
✓ Branch 16 taken 448 times.
✓ Branch 17 taken 112 times.
✓ Branch 18 taken 336 times.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
448 && vm[logger].as<std::string>() != "warning"
123
2/18
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 15 not taken.
✓ Branch 16 taken 448 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 448 times.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
448 && vm[logger].as<std::string>() != "error"
124
2/18
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 15 not taken.
✓ Branch 16 taken 448 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 448 times.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
448 && vm[logger].as<std::string>() != "critical"
125
6/24
✓ Branch 1 taken 448 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 112 times.
✓ Branch 4 taken 336 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✓ Branch 20 taken 448 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 448 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 448 times.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
1456 && vm[logger].as<std::string>() != "off")
126 {
127 LOG_CRITICAL("The command line argument '{}' has to be one of 'trace/debug/info/warning/error/critical/off' but the value '{}' was provided", logger, vm[logger].as<std::string>());
128 }
129 }
130
131
2/2
✓ Branch 0 taken 896 times.
✓ Branch 1 taken 112 times.
1008 for (int i = 0; i < argc; i++)
132 {
133
2/4
✓ Branch 1 taken 896 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 896 times.
✗ Branch 6 not taken.
896 LOG_DEBUG("\targument[{}] = '{}'", i, argv[i]);
134 }
135
136
1/2
✓ Branch 4 taken 112 times.
✗ Branch 5 not taken.
112 LOG_DEBUG("{} arguments are set in the allowed variable map", vm.size());
137
138
2/2
✓ Branch 5 taken 1568 times.
✓ Branch 6 taken 112 times.
1680 for (const auto& value : vm)
139 {
140
2/2
✓ Branch 2 taken 112 times.
✓ Branch 3 taken 1456 times.
1568 if ([[maybe_unused]] const auto* v = boost::any_cast<size_t>(&value.second.value()))
141 {
142
2/4
✓ Branch 1 taken 112 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 112 times.
✗ Branch 6 not taken.
112 LOG_DEBUG("\tvm[{}] = '{}'", value.first, *v);
143 }
144
2/2
✓ Branch 2 taken 448 times.
✓ Branch 3 taken 1008 times.
1456 else if ([[maybe_unused]] const auto* v = boost::any_cast<bool>(&value.second.value())) // NOLINT(bugprone-bool-pointer-implicit-conversion)
145 {
146
2/4
✓ Branch 1 taken 448 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 448 times.
✗ Branch 6 not taken.
448 LOG_DEBUG("\tvm[{}] = '{}'", value.first, *v);
147 }
148
1/2
✓ Branch 2 taken 1008 times.
✗ Branch 3 not taken.
1008 else if ([[maybe_unused]] const auto* v = boost::any_cast<std::string>(&value.second.value()))
149 {
150
2/4
✓ Branch 1 taken 1008 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1008 times.
✗ Branch 6 not taken.
1008 LOG_DEBUG("\tvm[{}] = '{}'", value.first, *v);
151 }
152 else if ([[maybe_unused]] const auto* v = boost::any_cast<std::vector<std::string>>(&value.second.value()))
153 {
154 LOG_DEBUG("\tvm[{}] = '{}'", value.first, fmt::join(v->begin(), v->end(), ", "));
155 }
156 else
157 {
158 LOG_ERROR("The Log option vm[{}] could not be casted. Please report this to the developers.", value.first);
159 }
160 }
161 112 }
162
163 648 bool NAV::ConfigManager::HasKey(const std::string& key)
164 {
165 648 return vm.count(key);
166 }
167
168 std::vector<std::string> NAV::ConfigManager::GetKeys()
169 {
170 std::vector<std::string> keys;
171
172 for (auto& param : vm)
173 {
174 keys.push_back(param.first);
175 }
176
177 return keys;
178 }
179
180 void NAV::ConfigManager::SaveGlobalSettings()
181 {
182 // Save also global settings
183 std::ofstream filestream(flow::GetConfigPath() / "globals.json");
184 json j;
185 #ifdef IMGUI_IMPL_OPENGL_LOADER_GL3W
186 j["plotScreenshotImPlotStyleFile"] = gui::windows::plotScreenshotImPlotStyleFile;
187 j["copyScreenshotsToClipboard"] = gui::windows::copyScreenshotsToClipboard;
188 #endif
189 j["colormaps"] = ColormapsGlobal;
190
191 ImPlotContext& gp = *ImPlot::GetCurrentContext();
192 j["selectedImPlotColormap"] = gp.Style.Colormap;
193
194 constexpr int CMAP_USER_START = ImPlotColormap_Greys + 2;
195 for (int i = CMAP_USER_START; i < gp.ColormapData.Count; ++i)
196 {
197 j["ImPlotColormaps"][static_cast<size_t>(i - CMAP_USER_START)]["name"] = gp.ColormapData.GetName(i);
198 j["ImPlotColormaps"][static_cast<size_t>(i - CMAP_USER_START)]["qual"] = gp.ColormapData.IsQual(i);
199 for (int c = 0; c < gp.ColormapData.GetKeyCount(i); ++c)
200 {
201 j["ImPlotColormaps"][static_cast<size_t>(i - CMAP_USER_START)]["colors"][static_cast<size_t>(c)] =
202 ImGui::ColorConvertU32ToFloat4(gp.ColormapData.GetKeyColor(i, c));
203 }
204 }
205
206 filestream << std::setw(4) << j << std::endl; // NOLINT(performance-avoid-endl)
207 }
208
209 void NAV::ConfigManager::LoadGlobalSettings()
210 {
211 auto filepath = flow::GetConfigPath() / "globals.json";
212 std::ifstream filestream(filepath);
213
214 if (!filestream.good())
215 {
216 LOG_ERROR("Load Flow error: Could not open file: {}", filepath);
217 return;
218 }
219 json j;
220 filestream >> j;
221
222 if (j.contains("colormaps"))
223 {
224 j.at("colormaps").get_to(ColormapsGlobal);
225 }
226 #ifdef IMGUI_IMPL_OPENGL_LOADER_GL3W
227 if (j.contains("plotScreenshotImPlotStyleFile"))
228 {
229 j.at("plotScreenshotImPlotStyleFile").get_to(gui::windows::plotScreenshotImPlotStyleFile);
230 }
231 if (j.contains("copyScreenshotsToClipboard"))
232 {
233 j.at("copyScreenshotsToClipboard").get_to(gui::windows::copyScreenshotsToClipboard);
234 }
235 #endif
236 if (j.contains("ImPlotColormaps"))
237 {
238 for (size_t i = 0; i < j["ImPlotColormaps"].size(); ++i)
239 {
240 ImVector<ImVec4> custom;
241 for (const auto& c : j.at("ImPlotColormaps").at(i).at("colors"))
242 {
243 custom.push_back(c.get<ImVec4>());
244 }
245
246 ImPlot::AddColormap(j.at("ImPlotColormaps").at(i).at("name").get<std::string>().c_str(),
247 custom.Data, custom.Size, j.at("ImPlotColormaps").at(i).at("qual").get<bool>());
248 ImPlot::BustItemCache();
249 }
250 }
251 if (j.contains("selectedImPlotColormap"))
252 {
253 ImPlotContext& gp = *ImPlot::GetCurrentContext();
254 gp.Style.Colormap = j.at("selectedImPlotColormap").get<int>();
255 ImPlot::BustItemCache();
256 }
257 }
258