facter 3.9.6.cfacter.20180612 → 3.11.0.cfacter.20180319

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/ext/facter/facter/CMakeLists.txt +1 -1
  3. data/ext/facter/facter/acceptance/Gemfile +3 -4
  4. data/ext/facter/facter/acceptance/Rakefile +342 -2
  5. data/ext/facter/facter/acceptance/config/aio/options.rb +6 -0
  6. data/ext/facter/facter/acceptance/config/git/options.rb +5 -1
  7. data/ext/facter/facter/acceptance/setup/aio/pre-suite/010_Install.rb +22 -0
  8. data/ext/facter/facter/acceptance/setup/aio/pre-suite/021_InstallAristaModule.rb +12 -0
  9. data/ext/facter/facter/acceptance/setup/aio/pre-suite/022_Remove_LD_PRELOAD.rb +11 -0
  10. data/ext/facter/facter/acceptance/setup/common/00_EnvSetup.rb +64 -0
  11. data/ext/facter/facter/acceptance/setup/common/pre-suite/000-delete-puppet-when-none.rb +11 -0
  12. data/ext/facter/facter/acceptance/setup/git/pre-suite/01_TestSetup.rb +31 -0
  13. data/ext/facter/facter/acceptance/tests/ticket_1238_hostname_fqdn.rb +20 -0
  14. data/ext/facter/facter/lib/CMakeLists.txt +3 -2
  15. data/ext/facter/facter/lib/Doxyfile +1 -1
  16. data/ext/facter/facter/lib/inc/facter/facts/fact.hpp +5 -0
  17. data/ext/facter/facter/lib/inc/internal/facts/aix/networking_resolver.hpp +0 -7
  18. data/ext/facter/facter/lib/inc/internal/facts/freebsd/networking_resolver.hpp +0 -7
  19. data/ext/facter/facter/lib/inc/internal/facts/linux/fips_resolver.hpp +31 -0
  20. data/ext/facter/facter/lib/inc/internal/facts/linux/networking_resolver.hpp +0 -7
  21. data/ext/facter/facter/lib/inc/internal/facts/openbsd/networking_resolver.hpp +0 -7
  22. data/ext/facter/facter/lib/inc/internal/facts/osx/networking_resolver.hpp +0 -7
  23. data/ext/facter/facter/lib/inc/internal/facts/posix/networking_resolver.hpp +0 -7
  24. data/ext/facter/facter/lib/inc/internal/facts/resolvers/fips_resolver.hpp +46 -0
  25. data/ext/facter/facter/lib/inc/internal/facts/resolvers/networking_resolver.hpp +2 -3
  26. data/ext/facter/facter/lib/inc/internal/facts/resolvers/ssh_resolver.hpp +6 -0
  27. data/ext/facter/facter/lib/inc/internal/facts/solaris/networking_resolver.hpp +0 -7
  28. data/ext/facter/facter/lib/schema/facter.yaml +38 -18
  29. data/ext/facter/facter/lib/src/cwrapper.cc +5 -0
  30. data/ext/facter/facter/lib/src/facts/aix/disk_resolver.cc +2 -11
  31. data/ext/facter/facter/lib/src/facts/aix/networking_resolver.cc +0 -5
  32. data/ext/facter/facter/lib/src/facts/freebsd/dmi_resolver.cc +5 -1
  33. data/ext/facter/facter/lib/src/facts/freebsd/networking_resolver.cc +1 -10
  34. data/ext/facter/facter/lib/src/facts/freebsd/virtualization_resolver.cc +1 -4
  35. data/ext/facter/facter/lib/src/facts/linux/collection.cc +2 -0
  36. data/ext/facter/facter/lib/src/facts/linux/fips_resolver.cc +31 -0
  37. data/ext/facter/facter/lib/src/facts/linux/networking_resolver.cc +1 -10
  38. data/ext/facter/facter/lib/src/facts/openbsd/networking_resolver.cc +1 -10
  39. data/ext/facter/facter/lib/src/facts/osx/networking_resolver.cc +1 -10
  40. data/ext/facter/facter/lib/src/facts/posix/networking_resolver.cc +2 -3
  41. data/ext/facter/facter/lib/src/facts/posix/ssh_resolver.cc +3 -2
  42. data/ext/facter/facter/lib/src/facts/resolvers/fips_resolver.cc +23 -0
  43. data/ext/facter/facter/lib/src/facts/resolvers/networking_resolver.cc +7 -23
  44. data/ext/facter/facter/lib/src/facts/resolvers/ssh_resolver.cc +1 -0
  45. data/ext/facter/facter/lib/src/facts/solaris/networking_resolver.cc +0 -5
  46. data/ext/facter/facter/lib/tests/facts/resolvers/ssh_resolver.cc +8 -1
  47. data/ext/facter/facter/lib/tests/facts/schema.cc +17 -0
  48. data/ext/facter/facter/locales/FACTER.pot +2 -23
  49. data/ext/facter/leatherman/CHANGELOG.md +16 -9
  50. data/ext/facter/leatherman/CMakeLists.txt +1 -2
  51. data/ext/facter/leatherman/appveyor.yml +26 -19
  52. data/ext/facter/leatherman/catch/CMakeLists.txt +1 -1
  53. data/ext/facter/leatherman/curl/tests/client_test.cc +396 -398
  54. data/ext/facter/leatherman/curl/tests/mock_curl.cc +2 -0
  55. data/ext/facter/leatherman/curl/tests/request_test.cc +66 -68
  56. data/ext/facter/leatherman/curl/tests/response_test.cc +50 -52
  57. data/ext/facter/leatherman/dynamic_library/tests/dynamic_library_tests.cc +71 -75
  58. data/ext/facter/leatherman/execution/src/execution.cc +3 -0
  59. data/ext/facter/leatherman/execution/src/posix/execution.cc +5 -6
  60. data/ext/facter/leatherman/execution/src/windows/execution.cc +2 -0
  61. data/ext/facter/leatherman/execution/tests/windows/execution.cc +4 -2
  62. data/ext/facter/leatherman/file_util/tests/directory_utils_test.cc +66 -68
  63. data/ext/facter/leatherman/file_util/tests/file_utils_test.cc +175 -177
  64. data/ext/facter/leatherman/json_container/inc/leatherman/json_container/json_container.hpp +7 -0
  65. data/ext/facter/leatherman/json_container/src/json_container.cc +10 -1
  66. data/ext/facter/leatherman/json_container/tests/json_container_test.cc +152 -8
  67. data/ext/facter/leatherman/locale/CMakeLists.txt +0 -7
  68. data/ext/facter/leatherman/locales/leatherman.pot +8 -13
  69. data/ext/facter/leatherman/logging/src/logging.cc +2 -0
  70. data/ext/facter/leatherman/util/tests/timer.cc +1 -3
  71. data/ext/facter/leatherman/vendor/Catch-1.10.0.zip +0 -0
  72. data/ext/facter/leatherman/vendor/nowide/doc/Doxyfile +4 -4
  73. data/ext/facter/leatherman/vendor/nowide/doc/LICENSE_1_0.txt +23 -0
  74. data/ext/facter/leatherman/vendor/nowide/doc/main.txt +62 -54
  75. data/ext/facter/leatherman/vendor/nowide/include/boost/nowide/convert.hpp +16 -16
  76. data/ext/facter/leatherman/vendor/nowide/include/boost/nowide/cstdio.hpp +4 -4
  77. data/ext/facter/leatherman/vendor/nowide/include/boost/nowide/utf8_codecvt.hpp +1 -1
  78. data/ext/facter/leatherman/vendor/nowide/src/iostream.cpp +32 -30
  79. data/ext/facter/leatherman/vendor/nowide/standalone/convert +6 -6
  80. data/ext/facter/leatherman/vendor/nowide/standalone/encoding_utf.hpp +1 -1
  81. data/ext/facter/leatherman/vendor/nowide/standalone/run_convert_and_build.sh +1 -3
  82. metadata +15 -6
  83. data/ext/facter/leatherman/cmake/FindICU.cmake +0 -690
  84. data/ext/facter/leatherman/scripts/travis_target.sh +0 -79
  85. data/ext/facter/leatherman/vendor/catch-1.4.0.zip +0 -0
@@ -161,6 +161,7 @@ namespace leatherman { namespace execution {
161
161
  // Represents information about a pipe
162
162
  struct pipe
163
163
  {
164
+ // cppcheck-suppress passedByValue
164
165
  pipe(string pipe_name, scoped_descriptor desc, function<bool(string const&)> cb) :
165
166
  name(move(pipe_name)),
166
167
  descriptor(move(desc)),
@@ -169,6 +170,7 @@ namespace leatherman { namespace execution {
169
170
  {
170
171
  }
171
172
 
173
+ // cppcheck-suppress passedByValue
172
174
  pipe(string pipe_name, scoped_descriptor desc, string buf) :
173
175
  name(move(pipe_name)),
174
176
  descriptor(move(desc)),
@@ -221,8 +223,7 @@ namespace leatherman { namespace execution {
221
223
  int result = select(max + 1, &read_set, &write_set, nullptr, timeout ? &read_timeout : nullptr);
222
224
  if (result == -1) {
223
225
  if (errno != EINTR) {
224
- LOG_ERROR(format_error(_("select call failed")));
225
- throw execution_exception(_("child i/o failed."));
226
+ throw execution_exception(format_error(_("select call failed waiting for child i/o")));
226
227
  }
227
228
  // Interrupted by signal
228
229
  LOG_DEBUG("select call was interrupted and will be retried.");
@@ -505,15 +506,13 @@ namespace leatherman { namespace execution {
505
506
  struct sigaction sa = {};
506
507
  sa.sa_handler = timer_handler;
507
508
  if (sigaction(SIGALRM, &sa, nullptr) == -1) {
508
- LOG_ERROR(format_error(_("sigaction failed")));
509
- throw execution_exception(format_error(_("failed to setup timer")));
509
+ throw execution_exception(format_error(_("sigaction failed while setting up timeout")));
510
510
  }
511
511
 
512
512
  itimerval timer = {};
513
513
  timer.it_value.tv_sec = static_cast<decltype(timer.it_interval.tv_sec)>(timeout);
514
514
  if (setitimer(ITIMER_REAL, &timer, nullptr) == -1) {
515
- LOG_ERROR(format_error(_("setitimer failed")));
516
- throw execution_exception(format_error(_("failed to setup timer")));
515
+ throw execution_exception(format_error(_("setitimer failed while setting up timeout")));
517
516
  }
518
517
 
519
518
  // Set the resource to disable the timer
@@ -215,6 +215,7 @@ namespace leatherman { namespace execution {
215
215
  // Represents information about a pipe
216
216
  struct pipe
217
217
  {
218
+ // cppcheck-suppress passedByValue
218
219
  pipe(string pipe_name, scoped_handle pipe_handle, function<bool(string const&)> cb) :
219
220
  name(move(pipe_name)),
220
221
  handle(move(pipe_handle)),
@@ -226,6 +227,7 @@ namespace leatherman { namespace execution {
226
227
  init();
227
228
  }
228
229
 
230
+ // cppcheck-suppress passedByValue
229
231
  pipe(string pipe_name, scoped_handle pipe_handle, string buf) :
230
232
  name(move(pipe_name)),
231
233
  handle(move(pipe_handle)),
@@ -143,8 +143,10 @@ SCENARIO("executing commands with execution::execute") {
143
143
  auto exec = execute("cmd.exe", { "/c", CMAKE_BIN_DIRECTORY "/lth_cat.exe", "prefix", "suffix", "overwhelm", "stderr" },
144
144
  "hello\ngoodbye", 0, { execution_options::merge_environment });
145
145
  REQUIRE(exec.success);
146
- REQUIRE(exec.output == lth_cat::prefix+lth_cat::overwhelm+"hello\n"+lth_cat::overwhelm+"goodbye\n"+lth_cat::overwhelm+lth_cat::suffix);
147
- REQUIRE(exec.error == "hello\ngoodbye\n");
146
+ auto expected = lth_cat::prefix+lth_cat::overwhelm+"hello\n"+lth_cat::overwhelm+"goodbye\n"+lth_cat::overwhelm+lth_cat::suffix;
147
+ boost::replace_all(expected, "\n", "\r\n");
148
+ REQUIRE(exec.output == expected);
149
+ REQUIRE(exec.error == "hello\r\ngoodbye\r\n");
148
150
  REQUIRE(exec.exit_code == 0);
149
151
  }
150
152
  WHEN("requested to write stdout to file") {
@@ -4,86 +4,84 @@
4
4
  #include "fixtures.hpp"
5
5
  #include <boost/filesystem.hpp>
6
6
 
7
- namespace leatherman { namespace file_util {
7
+ using namespace leatherman::file_util;
8
8
 
9
- TEST_CASE("file_util::each_file", "[utils]") {
9
+ TEST_CASE("file_util::each_file", "[utils]") {
10
10
 
11
- temp_directory directory;
12
- atomic_write_to_file("1\n", directory.get_dir_name() + "/test1");
13
- atomic_write_to_file("2\n", directory.get_dir_name() + "/test2");
14
- atomic_write_to_file("3\n", directory.get_dir_name() + "/test3");
11
+ temp_directory directory;
12
+ atomic_write_to_file("1\n", directory.get_dir_name() + "/test1");
13
+ atomic_write_to_file("2\n", directory.get_dir_name() + "/test2");
14
+ atomic_write_to_file("3\n", directory.get_dir_name() + "/test3");
15
15
 
16
- SECTION("each file should be visited") {
17
- std::set<std::string> file_contents;
18
- each_file(directory.get_dir_name(), [&file_contents](std::string const &path) {
19
- file_contents.insert(read(path));
20
- return true;
21
- });
22
- REQUIRE(file_contents.size() == 3u);
23
- REQUIRE(file_contents.find("1\n") != file_contents.end());
24
- REQUIRE(file_contents.find("2\n") != file_contents.end());
25
- REQUIRE(file_contents.find("3\n") != file_contents.end());
26
- }
27
-
28
- SECTION("can find a file to match a pattern") {
29
- std::string content = "N/A";
30
- each_file(directory.get_dir_name(), [&content](std::string const &path) {
31
- return read(path, content);
32
- }, "[0-1]");
33
- REQUIRE(content == "1\n");
34
- }
16
+ SECTION("each file should be visited") {
17
+ std::set<std::string> file_contents;
18
+ each_file(directory.get_dir_name(), [&file_contents](std::string const &path) {
19
+ file_contents.insert(read(path));
20
+ return true;
21
+ });
22
+ REQUIRE(file_contents.size() == 3u);
23
+ REQUIRE(file_contents.find("1\n") != file_contents.end());
24
+ REQUIRE(file_contents.find("2\n") != file_contents.end());
25
+ REQUIRE(file_contents.find("3\n") != file_contents.end());
26
+ }
35
27
 
36
- SECTION("only one file returned from false callback"){
37
- int count = 0;
38
- each_file(directory.get_dir_name(), [&count](std::string const& path){
39
- count++;
40
- return false;
41
- });
42
- REQUIRE(count == 1);
43
- }
28
+ SECTION("can find a file to match a pattern") {
29
+ std::string content = "N/A";
30
+ each_file(directory.get_dir_name(), [&content](std::string const &path) {
31
+ return read(path, content);
32
+ }, "[0-1]");
33
+ REQUIRE(content == "1\n");
34
+ }
44
35
 
36
+ SECTION("only one file returned from false callback"){
37
+ int count = 0;
38
+ each_file(directory.get_dir_name(), [&count](std::string const& path){
39
+ count++;
40
+ return false;
41
+ });
42
+ REQUIRE(count == 1);
45
43
  }
46
44
 
47
- TEST_CASE("file_util::each_subdirectory", "[utils]") {
48
- temp_directory directory;
49
- boost::filesystem::create_directory(directory.get_dir_name() + "/test1");
50
- atomic_write_to_file("1", directory.get_dir_name() + "/test1/t1");
51
- boost::filesystem::create_directory(directory.get_dir_name() + "/test2");
52
- atomic_write_to_file("2a", directory.get_dir_name() + "/test2/t2a");
53
- atomic_write_to_file("2b", directory.get_dir_name() + "/test2/t2b");
45
+ }
46
+
47
+ TEST_CASE("file_util::each_subdirectory", "[utils]") {
48
+ temp_directory directory;
49
+ boost::filesystem::create_directory(directory.get_dir_name() + "/test1");
50
+ atomic_write_to_file("1", directory.get_dir_name() + "/test1/t1");
51
+ boost::filesystem::create_directory(directory.get_dir_name() + "/test2");
52
+ atomic_write_to_file("2a", directory.get_dir_name() + "/test2/t2a");
53
+ atomic_write_to_file("2b", directory.get_dir_name() + "/test2/t2b");
54
54
 
55
- SECTION("each subdirectory should be visited") {
56
- int counter = 0;
57
- each_subdirectory(directory.get_dir_name(), [&counter](std::string const &path) {
58
- each_file(path, [&counter](std::string const &file) {
59
- counter++;
60
- return true;
61
- });
55
+ SECTION("each subdirectory should be visited") {
56
+ int counter = 0;
57
+ each_subdirectory(directory.get_dir_name(), [&counter](std::string const &path) {
58
+ each_file(path, [&counter](std::string const &file) {
59
+ counter++;
62
60
  return true;
63
61
  });
64
- REQUIRE(counter == 3);
65
- }
62
+ return true;
63
+ });
64
+ REQUIRE(counter == 3);
65
+ }
66
66
 
67
- SECTION("can find directories that match a pattern") {
68
- int counter = 0;
69
- each_subdirectory(directory.get_dir_name(), [&counter](std::string const &path) {
70
- each_file(path, [&counter](std::string const &file) {
71
- counter++;
72
- return true;
73
- });
67
+ SECTION("can find directories that match a pattern") {
68
+ int counter = 0;
69
+ each_subdirectory(directory.get_dir_name(), [&counter](std::string const &path) {
70
+ each_file(path, [&counter](std::string const &file) {
71
+ counter++;
74
72
  return true;
75
- }, "[2-3]");
76
- REQUIRE(counter == 2);
77
- }
78
-
79
- SECTION("only one directory found from false callback"){
80
- int count = 0;
81
- each_subdirectory(directory.get_dir_name(), [&count](std::string const& path){
82
- count++;
83
- return false;
84
73
  });
85
- REQUIRE(count == 1);
86
- }
74
+ return true;
75
+ }, "[2-3]");
76
+ REQUIRE(counter == 2);
87
77
  }
88
78
 
89
- }} //namespace leatherman::file_util
79
+ SECTION("only one directory found from false callback"){
80
+ int count = 0;
81
+ each_subdirectory(directory.get_dir_name(), [&count](std::string const& path){
82
+ count++;
83
+ return false;
84
+ });
85
+ REQUIRE(count == 1);
86
+ }
87
+ }
@@ -7,191 +7,189 @@
7
7
  #include <windows.h>
8
8
  #endif
9
9
 
10
- namespace leatherman { namespace file_util {
10
+ using namespace leatherman::file_util;
11
11
 
12
- TEST_CASE("file_util::tilde_expand", "[utils]") {
12
+ TEST_CASE("file_util::tilde_expand", "[utils]") {
13
13
 
14
14
  #ifdef _WIN32
15
- _putenv("USERPROFILE=/testhome");
15
+ _putenv("USERPROFILE=/testhome");
16
16
  #else
17
- setenv("HOME", "/testhome", 1);
17
+ setenv("HOME", "/testhome", 1);
18
18
  #endif
19
19
 
20
- SECTION("empty path should be empty") {
21
- REQUIRE(tilde_expand("") == "");
22
- }
23
-
24
- SECTION("spaces should be preserved") {
25
- REQUIRE(tilde_expand("i like spaces") == "i like spaces");
26
- }
27
-
28
- SECTION("should expand using environment variable") {
29
- CHECK(tilde_expand("~") == "/testhome");
30
- CHECK(tilde_expand("~/") == "/testhome/");
31
- CHECK(tilde_expand("~/foo") == "/testhome/foo");
32
- }
33
-
34
- SECTION("only a ~ at the start") {
35
- REQUIRE(tilde_expand("/foo/bar~") == "/foo/bar~");
36
- }
37
-
38
- SECTION("~baz/foo does not expand") {
39
- REQUIRE(tilde_expand("~baz/foo") == "~baz/foo");
40
- }
41
-
42
- SECTION("it should expand the home directory path") {
43
- REQUIRE(tilde_expand("~/foo") != "~/foo");
44
- }
45
-
46
- SECTION("it should not expand the working directory path") {
47
- REQUIRE(tilde_expand("./foo") == "./foo");
48
- }
49
-
50
- auto home_path = get_home_path();
51
-
52
- SECTION("it should expand ~ to the HOME env var") {
53
- REQUIRE(tilde_expand("~") == home_path);
54
- }
55
-
56
- SECTION("it should expand ~ as the base directory") {
57
- std::string expected_path{home_path + "/spam"};
58
- std::string expanded_path{tilde_expand("~/spam")};
59
- REQUIRE(expanded_path == expected_path);
60
- }
61
- }
62
-
63
- TEST_CASE("shell_quote", "[utils]") {
64
- SECTION("empty string") {
65
- REQUIRE(shell_quote("") == "\"\"");
66
- }
67
-
68
- SECTION("single word") {
69
- REQUIRE(shell_quote("plain") == "\"plain\"");
70
- }
71
-
72
- SECTION("words separated by space") {
73
- REQUIRE(shell_quote("a space") == "\"a space\"");
74
- }
75
-
76
- SECTION("exclamation mark") {
77
- REQUIRE(shell_quote("!csh") == "\"!csh\"");
78
- }
79
-
80
- SECTION("single quote before expression") {
81
- REQUIRE(shell_quote("'open quote") == "\"'open quote\"");
82
- }
83
-
84
- SECTION("single quote after expression") {
85
- REQUIRE(shell_quote("close quote'") == "\"close quote'\"");
86
- }
87
-
88
- SECTION("double quote before expression") {
89
- REQUIRE(shell_quote("\"open doublequote")
90
- == "\"\\\"open doublequote\"");
91
- }
92
-
93
- SECTION("double quote after expression") {
94
- REQUIRE(shell_quote("close doublequote\"")
95
- == "\"close doublequote\\\"\"");
96
- }
97
- }
98
-
99
- TEST_CASE("lth_file::file_readable", "[utils]") {
100
- SECTION("it can check that a file does not exist") {
101
- auto file_path = unique_fixture_path().string();
102
- CAPTURE(file_path);
103
- REQUIRE_FALSE(file_readable(file_path));
104
- }
105
-
106
- SECTION("directories are not readable") {
107
- temp_directory dir_path;
108
- REQUIRE_FALSE(file_readable(dir_path.get_dir_name()));
109
- }
110
- }
111
-
112
- TEST_CASE("lth_file::atomic_write_to_file", "[utils]") {
113
- SECTION("it can write to a regular file, ensure it exists, and delete it") {
114
- auto file_path = unique_fixture_path().string();
115
- REQUIRE_FALSE(file_readable(file_path));
116
- atomic_write_to_file("test\n", file_path);
117
- REQUIRE(file_readable(file_path));
118
- boost::filesystem::remove(file_path);
119
- REQUIRE_FALSE(file_readable(file_path));
120
- }
121
-
122
- SECTION("can write to an existing file") {
123
- temp_file file("existing file");
124
- REQUIRE(file_readable(file.get_file_name()));
125
- atomic_write_to_file("test", file.get_file_name());
126
- REQUIRE(file_readable(file.get_file_name()));
127
- REQUIRE(read(file.get_file_name()) == "test");
128
- }
20
+ SECTION("empty path should be empty") {
21
+ REQUIRE(tilde_expand("") == "");
22
+ }
23
+
24
+ SECTION("spaces should be preserved") {
25
+ REQUIRE(tilde_expand("i like spaces") == "i like spaces");
26
+ }
27
+
28
+ SECTION("should expand using environment variable") {
29
+ CHECK(tilde_expand("~") == "/testhome");
30
+ CHECK(tilde_expand("~/") == "/testhome/");
31
+ CHECK(tilde_expand("~/foo") == "/testhome/foo");
32
+ }
33
+
34
+ SECTION("only a ~ at the start") {
35
+ REQUIRE(tilde_expand("/foo/bar~") == "/foo/bar~");
36
+ }
37
+
38
+ SECTION("~baz/foo does not expand") {
39
+ REQUIRE(tilde_expand("~baz/foo") == "~baz/foo");
40
+ }
41
+
42
+ SECTION("it should expand the home directory path") {
43
+ REQUIRE(tilde_expand("~/foo") != "~/foo");
44
+ }
45
+
46
+ SECTION("it should not expand the working directory path") {
47
+ REQUIRE(tilde_expand("./foo") == "./foo");
48
+ }
49
+
50
+ auto home_path = get_home_path();
51
+
52
+ SECTION("it should expand ~ to the HOME env var") {
53
+ REQUIRE(tilde_expand("~") == home_path);
54
+ }
55
+
56
+ SECTION("it should expand ~ as the base directory") {
57
+ std::string expected_path{home_path + "/spam"};
58
+ std::string expanded_path{tilde_expand("~/spam")};
59
+ REQUIRE(expanded_path == expected_path);
60
+ }
61
+ }
62
+
63
+ TEST_CASE("shell_quote", "[utils]") {
64
+ SECTION("empty string") {
65
+ REQUIRE(shell_quote("") == "\"\"");
66
+ }
67
+
68
+ SECTION("single word") {
69
+ REQUIRE(shell_quote("plain") == "\"plain\"");
70
+ }
71
+
72
+ SECTION("words separated by space") {
73
+ REQUIRE(shell_quote("a space") == "\"a space\"");
74
+ }
75
+
76
+ SECTION("exclamation mark") {
77
+ REQUIRE(shell_quote("!csh") == "\"!csh\"");
78
+ }
79
+
80
+ SECTION("single quote before expression") {
81
+ REQUIRE(shell_quote("'open quote") == "\"'open quote\"");
82
+ }
83
+
84
+ SECTION("single quote after expression") {
85
+ REQUIRE(shell_quote("close quote'") == "\"close quote'\"");
86
+ }
87
+
88
+ SECTION("double quote before expression") {
89
+ REQUIRE(shell_quote("\"open doublequote")
90
+ == "\"\\\"open doublequote\"");
91
+ }
92
+
93
+ SECTION("double quote after expression") {
94
+ REQUIRE(shell_quote("close doublequote\"")
95
+ == "\"close doublequote\\\"\"");
96
+ }
97
+ }
98
+
99
+ TEST_CASE("lth_file::file_readable", "[utils]") {
100
+ SECTION("it can check that a file does not exist") {
101
+ auto file_path = unique_fixture_path().string();
102
+ CAPTURE(file_path);
103
+ REQUIRE_FALSE(file_readable(file_path));
104
+ }
105
+
106
+ SECTION("directories are not readable") {
107
+ temp_directory dir_path;
108
+ REQUIRE_FALSE(file_readable(dir_path.get_dir_name()));
109
+ }
110
+ }
111
+
112
+ TEST_CASE("lth_file::atomic_write_to_file", "[utils]") {
113
+ SECTION("it can write to a regular file, ensure it exists, and delete it") {
114
+ auto file_path = unique_fixture_path().string();
115
+ REQUIRE_FALSE(file_readable(file_path));
116
+ atomic_write_to_file("test\n", file_path);
117
+ REQUIRE(file_readable(file_path));
118
+ boost::filesystem::remove(file_path);
119
+ REQUIRE_FALSE(file_readable(file_path));
120
+ }
121
+
122
+ SECTION("can write to an existing file") {
123
+ temp_file file("existing file");
124
+ REQUIRE(file_readable(file.get_file_name()));
125
+ atomic_write_to_file("test", file.get_file_name());
126
+ REQUIRE(file_readable(file.get_file_name()));
127
+ REQUIRE(read(file.get_file_name()) == "test");
128
+ }
129
129
 
130
130
  #ifndef _WIN32
131
- SECTION("can write a file with permissions") {
132
- auto file_path = unique_fixture_path().string();
133
- REQUIRE_FALSE(file_readable(file_path));
134
- auto perms = boost::filesystem::owner_read | boost::filesystem::owner_write;
135
- atomic_write_to_file("test\n", file_path, perms, std::ios::binary);
136
- REQUIRE(file_readable(file_path));
137
- auto stat = boost::filesystem::status(file_path);
138
- REQUIRE(stat.permissions() == perms);
139
- boost::filesystem::remove(file_path);
140
- REQUIRE_FALSE(file_readable(file_path));
141
- }
131
+ SECTION("can write a file with permissions") {
132
+ auto file_path = unique_fixture_path().string();
133
+ REQUIRE_FALSE(file_readable(file_path));
134
+ auto perms = boost::filesystem::owner_read | boost::filesystem::owner_write;
135
+ atomic_write_to_file("test\n", file_path, perms, std::ios::binary);
136
+ REQUIRE(file_readable(file_path));
137
+ auto stat = boost::filesystem::status(file_path);
138
+ REQUIRE(stat.permissions() == perms);
139
+ boost::filesystem::remove(file_path);
140
+ REQUIRE_FALSE(file_readable(file_path));
141
+ }
142
142
  #endif
143
+ }
144
+
145
+ TEST_CASE("file_util::read", "[utils]") {
146
+
147
+ SECTION("trying to read a nonexistent file returns the empty string"){
148
+ std::string contents;
149
+ REQUIRE(read("does_not_exist") == "");
150
+ REQUIRE_FALSE(read("does_not_exist", contents));
151
+ REQUIRE(contents.empty());
152
+ }
153
+
154
+ SECTION("it can read from a file") {
155
+ auto file_path = unique_fixture_path().string();
156
+ atomic_write_to_file("test\n", file_path);
157
+ REQUIRE(file_readable(file_path));
158
+ std::string contents;
159
+ REQUIRE(read(file_path, contents));
160
+ REQUIRE(contents == "test\n");
161
+ REQUIRE(read(file_path) == "test\n");
162
+ boost::filesystem::remove(file_path);
143
163
  }
164
+ }
144
165
 
145
- TEST_CASE("file_util::read", "[utils]") {
146
-
147
- SECTION("trying to read a nonexistent file returns the empty string"){
148
- std::string contents;
149
- REQUIRE(read("does_not_exist") == "");
150
- REQUIRE_FALSE(read("does_not_exist", contents));
151
- REQUIRE(contents.empty());
152
- }
153
-
154
- SECTION("it can read from a file") {
155
- auto file_path = unique_fixture_path().string();
156
- atomic_write_to_file("test\n", file_path);
157
- REQUIRE(file_readable(file_path));
158
- std::string contents;
159
- REQUIRE(read(file_path, contents));
160
- REQUIRE(contents == "test\n");
161
- REQUIRE(read(file_path) == "test\n");
162
- boost::filesystem::remove(file_path);
163
- }
164
- }
165
-
166
- TEST_CASE("file_util::each_line", "[utils]") {
167
-
168
- SECTION("trying to read a nonexistent file returns false") {
169
- REQUIRE_FALSE(each_line("does_not_exist", [](std::string &line) {
170
- FAIL("should not be called");
171
- return true;
172
- }));
173
- }
174
-
175
- SECTION("an action is performed on each line of a file") {
176
- temp_file file("test1\ntest2\ntest3\n");
177
- int i = 0;
178
- REQUIRE(each_line(file.get_file_name(), [&i](std::string const &line) {
179
- i++;
180
- return line == ("test" + std::to_string(i));
181
- }));
182
- REQUIRE(i == 3);
183
- }
184
-
185
- SECTION("a callback that returns false stops at the first line"){
186
- temp_file file("test1\ntest2\ntest3\n");
187
- std::vector<std::string> lines;
188
- REQUIRE(each_line(file.get_file_name(), [&](std::string& line) {
189
- lines.emplace_back(move(line));
190
- return false;
191
- }));
192
- REQUIRE(lines.size() == 1u);
193
- REQUIRE(lines[0] == "test1");
194
- }
195
- }
196
-
197
- }} // namespace leatherman::file_util
166
+ TEST_CASE("file_util::each_line", "[utils]") {
167
+
168
+ SECTION("trying to read a nonexistent file returns false") {
169
+ REQUIRE_FALSE(each_line("does_not_exist", [](std::string &line) {
170
+ FAIL("should not be called");
171
+ return true;
172
+ }));
173
+ }
174
+
175
+ SECTION("an action is performed on each line of a file") {
176
+ temp_file file("test1\ntest2\ntest3\n");
177
+ int i = 0;
178
+ REQUIRE(each_line(file.get_file_name(), [&i](std::string const &line) {
179
+ i++;
180
+ return line == ("test" + std::to_string(i));
181
+ }));
182
+ REQUIRE(i == 3);
183
+ }
184
+
185
+ SECTION("a callback that returns false stops at the first line"){
186
+ temp_file file("test1\ntest2\ntest3\n");
187
+ std::vector<std::string> lines;
188
+ REQUIRE(each_line(file.get_file_name(), [&](std::string& line) {
189
+ lines.emplace_back(move(line));
190
+ return false;
191
+ }));
192
+ REQUIRE(lines.size() == 1u);
193
+ REQUIRE(lines[0] == "test1");
194
+ }
195
+ }