mavtables  0.2.1
MAVLink router and firewall.
test_Options.cpp
Go to the documentation of this file.
1 // MAVLink router and firewall.
2 // Copyright (C) 2018 Michael R. Shannon <mrshannon.aerospace@gmail.com>
3 //
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 2 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
16 
17 
18 #include <stdexcept>
19 
20 #include "catch.hpp"
21 #include "fakeit.hpp"
22 
23 #include "config.hpp"
24 #include "Filesystem.hpp"
25 #include "Options.hpp"
26 
27 #include "common.hpp"
28 
29 
30 TEST_CASE("'find_config' returns the path to the highest priority "
31  "configuration file.", "[Options]")
32 {
33  std::vector<Filesystem::path> paths;
34  fakeit::Mock<Filesystem> fs_mock;
35  SECTION("First found is given by MAVTABLES_CONFIG_PATH environment "
36  "variable.")
37  {
38  fakeit::When(Method(fs_mock, exists)).AlwaysDo([&](auto p)
39  {
40  paths.push_back(p);
41  return p == Filesystem::path("mtbls.conf");
42  });
43  setenv("MAVTABLES_CONFIG_PATH", "mtbls.conf", true);
44  auto config_file = find_config(fs_mock.get());
45  REQUIRE(config_file.has_value());
46  REQUIRE(config_file.value() == "mtbls.conf");
47  unsetenv("MAVTABLES_CONFIG_PATH");
48  fakeit::Verify(Method(fs_mock, exists)).Exactly(1);
49  REQUIRE(paths.size() == 1);
50  REQUIRE(paths[0] == Filesystem::path("mtbls.conf"));
51  }
52  SECTION("First found is .mavtablesrc in current directory.")
53  {
54  fakeit::When(Method(fs_mock, exists)).AlwaysDo([&](auto p)
55  {
56  paths.push_back(p);
57  return p == Filesystem::path(".mavtablesrc");
58  });
59  setenv("MAVTABLES_CONFIG_PATH", "mtbls.conf", true);
60  auto config_file = find_config(fs_mock.get());
61  REQUIRE(config_file.has_value());
62  REQUIRE(config_file.value() == ".mavtablesrc");
63  unsetenv("MAVTABLES_CONFIG_PATH");
64  fakeit::Verify(Method(fs_mock, exists)).Exactly(2);
65  REQUIRE(paths.size() == 2);
66  REQUIRE(paths[0] == Filesystem::path("mtbls.conf"));
67  REQUIRE(paths[1] == Filesystem::path(".mavtablesrc"));
68  }
69  SECTION("First found is .mavtablesrc in HOME directory.")
70  {
71  Filesystem::path home_path(std::getenv("HOME"));
72  home_path /= Filesystem::path(".mavtablesrc");
73  fakeit::When(Method(fs_mock, exists)).AlwaysDo([&](auto p)
74  {
75  paths.push_back(p);
76  return p == home_path;
77  });
78  setenv("MAVTABLES_CONFIG_PATH", "mtbls.conf", true);
79  auto config_file = find_config(fs_mock.get());
80  REQUIRE(config_file.has_value());
81  REQUIRE(config_file.value() == home_path);
82  unsetenv("MAVTABLES_CONFIG_PATH");
83  fakeit::Verify(Method(fs_mock, exists)).Exactly(3);
84  REQUIRE(paths.size() == 3);
85  REQUIRE(paths[0] == Filesystem::path("mtbls.conf"));
86  REQUIRE(paths[1] == Filesystem::path(".mavtablesrc"));
87  REQUIRE(paths[2] == Filesystem::path(home_path));
88  }
89  SECTION("First found is PREFIX/etc/mavtables.conf.")
90  {
91  Filesystem::path home_path(std::getenv("HOME"));
92  home_path /= Filesystem::path(".mavtablesrc");
93  fakeit::When(Method(fs_mock, exists)).AlwaysDo([&](auto p)
94  {
95  paths.push_back(p);
96  return p == (PREFIX "/etc/mavtables.conf");
97  });
98  setenv("MAVTABLES_CONFIG_PATH", "mtbls.conf", true);
99  auto config_file = find_config(fs_mock.get());
100  REQUIRE(config_file.has_value());
101  REQUIRE(config_file.value() == (PREFIX "/etc/mavtables.conf"));
102  unsetenv("MAVTABLES_CONFIG_PATH");
103  fakeit::Verify(Method(fs_mock, exists)).Exactly(4);
104  REQUIRE(paths.size() == 4);
105  REQUIRE(paths[0] == Filesystem::path("mtbls.conf"));
106  REQUIRE(paths[1] == Filesystem::path(".mavtablesrc"));
107  REQUIRE(paths[2] == Filesystem::path(home_path));
108  REQUIRE(paths[3] == Filesystem::path(PREFIX "/etc/mavtables.conf"));
109  }
110  SECTION("Failed to find any configuration file.")
111  {
112  Filesystem::path home_path(std::getenv("HOME"));
113  home_path /= Filesystem::path(".mavtablesrc");
114  fakeit::When(Method(fs_mock, exists)).AlwaysDo([&](auto p)
115  {
116  paths.push_back(p);
117  return false;
118  });
119  setenv("MAVTABLES_CONFIG_PATH", "mtbls.conf", true);
120  auto config_file = find_config(fs_mock.get());
121  REQUIRE_FALSE(config_file.has_value());
122  unsetenv("MAVTABLES_CONFIG_PATH");
123  fakeit::Verify(Method(fs_mock, exists)).Exactly(4);
124  REQUIRE(paths.size() == 4);
125  REQUIRE(paths[0] == Filesystem::path("mtbls.conf"));
126  REQUIRE(paths[1] == Filesystem::path(".mavtablesrc"));
127  REQUIRE(paths[2] == Filesystem::path(home_path));
128  REQUIRE(paths[3] == Filesystem::path(PREFIX "/etc/mavtables.conf"));
129  }
130 }
131 
132 
133 TEST_CASE("Options's class prints the help message.", "[Options]")
134 {
135  MockCOut mock_cout;
136  std::string help_message =
137  "usage: <program name here>:\n"
138  " -h [ --help ] print this message\n"
139  " --config arg specify configuration file\n"
140  " --ast print AST of configuration file (do not run)\n"
141  " --version print version and license information\n"
142  " --loglevel arg level of logging, between 0 and 3\n\n";
143  SECTION("When given the '-h' flag.")
144  {
145  int argc = 2;
146  const char *argv[2] = {"<program name here>", "-h"};
147  Options options(argc, argv);
148  REQUIRE(mock_cout.buffer() == help_message);
149  REQUIRE_FALSE(options);
150  }
151  SECTION("When given the '--help' flag.")
152  {
153  int argc = 2;
154  const char *argv[2] = {"<program name here>", "--help"};
155  Options options(argc, argv);
156  REQUIRE(mock_cout.buffer() == help_message);
157  REQUIRE_FALSE(options);
158  }
159 }
160 
161 
162 TEST_CASE("Options's class prints version information when given the "
163  "'--version' flag.", "[Options]")
164 {
165  MockCOut mock_cout;
166  int argc = 2;
167  const char *argv[2] = {"<program name here>", "--version"};
168  Options options(argc, argv);
169  REQUIRE(
170  mock_cout.buffer() ==
171  "mavtables (SHAMU Project) v" + std::to_string(VERSION_MAJOR) +
172  "." + std::to_string(VERSION_MINOR) +
173  "." + std::to_string(VERSION_PATCH) +
174  "\nCopyright (C) 2018 Michael R. Shannon\n"
175  "\n"
176  "License: GPL v2.0 or any later version.\n"
177  "This is free software; see the source for copying conditions. "
178  "There is NO\nwarranty; not even for MERCHANTABILITY or FITNESS FOR A "
179  "PARTICULAR PURPOSE.\n");
180  REQUIRE_FALSE(options);
181 }
182 
183 
184 TEST_CASE("Options's class will use the given configuration file "
185  "(--config flag).", "[Options]")
186 {
187  MockCOut mock_cout;
188  std::vector<Filesystem::path> paths;
189  fakeit::Mock<Filesystem> fs_mock;
190  SECTION("File found.")
191  {
192  // Setup mocks.
193  fakeit::When(Method(fs_mock, exists)).AlwaysDo([&](auto p)
194  {
195  paths.push_back(p);
196  return p == Filesystem::path("examples/test.conf");
197  });
198  // Construct Options object.
199  int argc = 3;
200  const char *argv[3] = {"mavtables", "--config", "examples/test.conf"};
201  Options options(argc, argv, fs_mock.get());
202  // Verify Options object.
203  REQUIRE(options.config_file() == "examples/test.conf");
204  REQUIRE(options);
205  REQUIRE_FALSE(options.ast());
206  REQUIRE(options.run());
207  // Verify printing.
208  REQUIRE(mock_cout.buffer().empty());
209  // Verify exists calls.
210  fakeit::Verify(Method(fs_mock, exists)).Exactly(1);
211  REQUIRE(paths.size() == 1);
212  REQUIRE(paths[0] == Filesystem::path("examples/test.conf"));
213  }
214  SECTION("File not found (throws error).")
215  {
216  // Setup mocks.
217  fakeit::When(Method(fs_mock, exists)).AlwaysDo([&](auto p)
218  {
219  paths.push_back(p);
220  return false;
221  });
222  // Construct Options object.
223  int argc = 3;
224  const char *argv[3] =
225  {
226  "mavtables", "--config", "non_existant_file.conf"
227  };
228  // Verify Options object.
229  REQUIRE_THROWS_AS(
230  Options(argc, argv, fs_mock.get()), std::runtime_error);
231  REQUIRE_THROWS_WITH(
232  Options(argc, argv, fs_mock.get()),
233  "mavtables could not locate a configuration file");
234  // Verify printing.
235  REQUIRE(mock_cout.buffer().empty());
236  // Verify exists calls.
237  fakeit::Verify(Method(fs_mock, exists)).Exactly(2);
238  REQUIRE(paths.size() == 2);
239  REQUIRE(paths[0] == Filesystem::path("non_existant_file.conf"));
240  REQUIRE(paths[1] == Filesystem::path("non_existant_file.conf"));
241  }
242 }
243 
244 
245 TEST_CASE("Options's class finds the configuration file.", "[Options]")
246 {
247  MockCOut mock_cout;
248  std::vector<Filesystem::path> paths;
249  fakeit::Mock<Filesystem> fs_mock;
250  SECTION("First found is given by MAVTABLES_CONFIG_PATH environment "
251  "variable.")
252  {
253  // Setup mocks.
254  fakeit::When(Method(fs_mock, exists)).AlwaysDo([&](auto p)
255  {
256  paths.push_back(p);
257  return p == Filesystem::path("mtbls.conf");
258  });
259  setenv("MAVTABLES_CONFIG_PATH", "mtbls.conf", true);
260  // Construct Options object.
261  int argc = 1;
262  const char *argv[2] = {"mavtables"};
263  Options options(argc, argv, fs_mock.get());
264  unsetenv("MAVTABLES_CONFIG_PATH");
265  // Verify Options object.
266  REQUIRE(options.config_file() == "mtbls.conf");
267  REQUIRE(options);
268  REQUIRE_FALSE(options.ast());
269  REQUIRE(options.run());
270  // Verify printing.
271  REQUIRE(mock_cout.buffer().empty());
272  // Verify exists calls.
273  fakeit::Verify(Method(fs_mock, exists)).Exactly(1);
274  REQUIRE(paths.size() == 1);
275  REQUIRE(paths[0] == Filesystem::path("mtbls.conf"));
276  }
277  SECTION("First found is .mavtablesrc in current directory.")
278  {
279  // Setup mocks.
280  fakeit::When(Method(fs_mock, exists)).AlwaysDo([&](auto p)
281  {
282  paths.push_back(p);
283  return p == Filesystem::path(".mavtablesrc");
284  });
285  setenv("MAVTABLES_CONFIG_PATH", "mtbls.conf", true);
286  // Construct Options object.
287  int argc = 1;
288  const char *argv[2] = {"mavtables"};
289  Options options(argc, argv, fs_mock.get());
290  unsetenv("MAVTABLES_CONFIG_PATH");
291  // Verify Options object.
292  REQUIRE(options.config_file() == ".mavtablesrc");
293  REQUIRE(options);
294  REQUIRE_FALSE(options.ast());
295  REQUIRE(options.run());
296  // Verify printing.
297  REQUIRE(mock_cout.buffer().empty());
298  // Verify exists calls.
299  fakeit::Verify(Method(fs_mock, exists)).Exactly(2);
300  REQUIRE(paths.size() == 2);
301  REQUIRE(paths[0] == Filesystem::path("mtbls.conf"));
302  REQUIRE(paths[1] == Filesystem::path(".mavtablesrc"));
303  }
304  SECTION("First found is .mavtablesrc in HOME directory.")
305  {
306  // Setup mocks.
307  Filesystem::path home_path(std::getenv("HOME"));
308  home_path /= Filesystem::path(".mavtablesrc");
309  fakeit::When(Method(fs_mock, exists)).AlwaysDo([&](auto p)
310  {
311  paths.push_back(p);
312  return p == home_path;
313  });
314  setenv("MAVTABLES_CONFIG_PATH", "mtbls.conf", true);
315  // Construct Options object.
316  int argc = 1;
317  const char *argv[2] = {"mavtables"};
318  Options options(argc, argv, fs_mock.get());
319  unsetenv("MAVTABLES_CONFIG_PATH");
320  // Verify Options object.
321  REQUIRE(options.config_file() == home_path);
322  REQUIRE(options);
323  REQUIRE_FALSE(options.ast());
324  REQUIRE(options.run());
325  // Verify printing.
326  REQUIRE(mock_cout.buffer().empty());
327  // Verify exists calls.
328  fakeit::Verify(Method(fs_mock, exists)).Exactly(3);
329  REQUIRE(paths.size() == 3);
330  REQUIRE(paths[0] == Filesystem::path("mtbls.conf"));
331  REQUIRE(paths[1] == Filesystem::path(".mavtablesrc"));
332  REQUIRE(paths[2] == Filesystem::path(home_path));
333  }
334  SECTION("First found is PREFIX/etc/mavtables.conf.")
335  {
336  // Setup mocks.
337  Filesystem::path home_path(std::getenv("HOME"));
338  home_path /= Filesystem::path(".mavtablesrc");
339  fakeit::When(Method(fs_mock, exists)).AlwaysDo([&](auto p)
340  {
341  paths.push_back(p);
342  return p == (PREFIX "/etc/mavtables.conf");
343  });
344  setenv("MAVTABLES_CONFIG_PATH", "mtbls.conf", true);
345  // Construct Options object.
346  int argc = 1;
347  const char *argv[2] = {"mavtables"};
348  Options options(argc, argv, fs_mock.get());
349  unsetenv("MAVTABLES_CONFIG_PATH");
350  // Verify Options object.
351  REQUIRE(options.config_file() == (PREFIX "/etc/mavtables.conf"));
352  REQUIRE(options);
353  REQUIRE_FALSE(options.ast());
354  REQUIRE(options.run());
355  // Verify printing.
356  REQUIRE(mock_cout.buffer().empty());
357  // Verify exists calls.
358  fakeit::Verify(Method(fs_mock, exists)).Exactly(4);
359  REQUIRE(paths.size() == 4);
360  REQUIRE(paths[0] == Filesystem::path("mtbls.conf"));
361  REQUIRE(paths[1] == Filesystem::path(".mavtablesrc"));
362  REQUIRE(paths[2] == Filesystem::path(home_path));
363  REQUIRE(paths[3] == Filesystem::path(PREFIX "/etc/mavtables.conf"));
364  }
365  SECTION("Failed to find any configuration file.")
366  {
367  // Setup mocks.
368  Filesystem::path home_path(std::getenv("HOME"));
369  home_path /= Filesystem::path(".mavtablesrc");
370  fakeit::When(Method(fs_mock, exists)).AlwaysDo([&](auto p)
371  {
372  paths.push_back(p);
373  return false;
374  });
375  setenv("MAVTABLES_CONFIG_PATH", "mtbls.conf", true);
376  // Construct Options object.
377  int argc = 1;
378  const char *argv[2] = {"mavtables"};
379  REQUIRE_THROWS_AS(
380  Options(argc, argv, fs_mock.get()),
381  std::runtime_error);
382  REQUIRE_THROWS_WITH(
383  Options(argc, argv, fs_mock.get()),
384  "mavtables could not locate a configuration file");
385  unsetenv("MAVTABLES_CONFIG_PATH");
386  // Verify printing.
387  REQUIRE(mock_cout.buffer().empty());
388  // Verify exists calls.
389  fakeit::Verify(Method(fs_mock, exists)).Exactly(8);
390  REQUIRE(paths.size() == 8);
391  REQUIRE(paths[0] == Filesystem::path("mtbls.conf"));
392  REQUIRE(paths[1] == Filesystem::path(".mavtablesrc"));
393  REQUIRE(paths[2] == Filesystem::path(home_path));
394  REQUIRE(paths[3] == Filesystem::path(PREFIX "/etc/mavtables.conf"));
395  REQUIRE(paths[4] == Filesystem::path("mtbls.conf"));
396  REQUIRE(paths[5] == Filesystem::path(".mavtablesrc"));
397  REQUIRE(paths[6] == Filesystem::path(home_path));
398  REQUIRE(paths[7] == Filesystem::path(PREFIX "/etc/mavtables.conf"));
399  }
400 }
401 
402 
403 TEST_CASE("Options's class sets run to false and ast to true when the --ast "
404  "flag is given.", "[Options]")
405 {
406  MockCOut mock_cout;
407  // Setup mocks.
408  fakeit::Mock<Filesystem> fs_mock;
409  fakeit::When(Method(fs_mock, exists)).AlwaysReturn(true);
410  // Construct Options object.
411  int argc = 4;
412  const char *argv[4] =
413  {
414  "mavtables", "--ast", "--config", "test/mavtables.conf"
415  };
416  Options options(argc, argv);
417  // Verify Options object.
418  REQUIRE(options.config_file() == "test/mavtables.conf");
419  REQUIRE(options);
420  REQUIRE(options.ast());
421  REQUIRE_FALSE(options.run());
422  // Verify printing.
423  REQUIRE(mock_cout.buffer().empty());
424 }
425 
426 
427 TEST_CASE("Option's class has a loglevel option", "[Options]")
428 {
429  MockCOut mock_cout;
430  // Setup mocks.
431  fakeit::Mock<Filesystem> fs_mock;
432  fakeit::When(Method(fs_mock, exists)).AlwaysReturn(true);
433  SECTION("defaults to loglevel 0")
434  {
435  // Construct Options object.
436  int argc = 3;
437  const char *argv[3] = {"mavtables", "--config", "test/mavtables.conf"};
438  Options options(argc, argv);
439  // Verify Options object.
440  REQUIRE(options.loglevel() == 0);
441  // Verify printing.
442  REQUIRE(mock_cout.buffer().empty());
443  }
444  SECTION("sets the loglevel when the --loglevel is given")
445  {
446  // Construct Options object.
447  int argc = 5;
448  const char *argv[5] =
449  {
450  "mavtables", "--loglevel", "3", "--config", "test/mavtables.conf"
451  };
452  Options options(argc, argv);
453  // Verify Options object.
454  REQUIRE(options.loglevel() == 3);
455  // Verify printing.
456  REQUIRE(mock_cout.buffer().empty());
457  }
458 }
bool run()
Definition: Options.cpp:167
TEST_CASE("'find_config' returns the path to the highest priority " "configuration file.", "[Options]")
bool ast()
Definition: Options.cpp:135
unsigned int loglevel()
Definition: Options.cpp:156
std::string buffer()
Definition: common.hpp:75
std::optional< std::string > find_config(const Filesystem &filesystem)
Definition: Options.cpp:199
boost::filesystem::path path
Definition: Filesystem.hpp:40
std::string config_file()
Definition: Options.cpp:146