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.
- checksums.yaml +4 -4
- data/ext/facter/facter/CMakeLists.txt +1 -1
- data/ext/facter/facter/acceptance/Gemfile +3 -4
- data/ext/facter/facter/acceptance/Rakefile +342 -2
- data/ext/facter/facter/acceptance/config/aio/options.rb +6 -0
- data/ext/facter/facter/acceptance/config/git/options.rb +5 -1
- data/ext/facter/facter/acceptance/setup/aio/pre-suite/010_Install.rb +22 -0
- data/ext/facter/facter/acceptance/setup/aio/pre-suite/021_InstallAristaModule.rb +12 -0
- data/ext/facter/facter/acceptance/setup/aio/pre-suite/022_Remove_LD_PRELOAD.rb +11 -0
- data/ext/facter/facter/acceptance/setup/common/00_EnvSetup.rb +64 -0
- data/ext/facter/facter/acceptance/setup/common/pre-suite/000-delete-puppet-when-none.rb +11 -0
- data/ext/facter/facter/acceptance/setup/git/pre-suite/01_TestSetup.rb +31 -0
- data/ext/facter/facter/acceptance/tests/ticket_1238_hostname_fqdn.rb +20 -0
- data/ext/facter/facter/lib/CMakeLists.txt +3 -2
- data/ext/facter/facter/lib/Doxyfile +1 -1
- data/ext/facter/facter/lib/inc/facter/facts/fact.hpp +5 -0
- data/ext/facter/facter/lib/inc/internal/facts/aix/networking_resolver.hpp +0 -7
- data/ext/facter/facter/lib/inc/internal/facts/freebsd/networking_resolver.hpp +0 -7
- data/ext/facter/facter/lib/inc/internal/facts/linux/fips_resolver.hpp +31 -0
- data/ext/facter/facter/lib/inc/internal/facts/linux/networking_resolver.hpp +0 -7
- data/ext/facter/facter/lib/inc/internal/facts/openbsd/networking_resolver.hpp +0 -7
- data/ext/facter/facter/lib/inc/internal/facts/osx/networking_resolver.hpp +0 -7
- data/ext/facter/facter/lib/inc/internal/facts/posix/networking_resolver.hpp +0 -7
- data/ext/facter/facter/lib/inc/internal/facts/resolvers/fips_resolver.hpp +46 -0
- data/ext/facter/facter/lib/inc/internal/facts/resolvers/networking_resolver.hpp +2 -3
- data/ext/facter/facter/lib/inc/internal/facts/resolvers/ssh_resolver.hpp +6 -0
- data/ext/facter/facter/lib/inc/internal/facts/solaris/networking_resolver.hpp +0 -7
- data/ext/facter/facter/lib/schema/facter.yaml +38 -18
- data/ext/facter/facter/lib/src/cwrapper.cc +5 -0
- data/ext/facter/facter/lib/src/facts/aix/disk_resolver.cc +2 -11
- data/ext/facter/facter/lib/src/facts/aix/networking_resolver.cc +0 -5
- data/ext/facter/facter/lib/src/facts/freebsd/dmi_resolver.cc +5 -1
- data/ext/facter/facter/lib/src/facts/freebsd/networking_resolver.cc +1 -10
- data/ext/facter/facter/lib/src/facts/freebsd/virtualization_resolver.cc +1 -4
- data/ext/facter/facter/lib/src/facts/linux/collection.cc +2 -0
- data/ext/facter/facter/lib/src/facts/linux/fips_resolver.cc +31 -0
- data/ext/facter/facter/lib/src/facts/linux/networking_resolver.cc +1 -10
- data/ext/facter/facter/lib/src/facts/openbsd/networking_resolver.cc +1 -10
- data/ext/facter/facter/lib/src/facts/osx/networking_resolver.cc +1 -10
- data/ext/facter/facter/lib/src/facts/posix/networking_resolver.cc +2 -3
- data/ext/facter/facter/lib/src/facts/posix/ssh_resolver.cc +3 -2
- data/ext/facter/facter/lib/src/facts/resolvers/fips_resolver.cc +23 -0
- data/ext/facter/facter/lib/src/facts/resolvers/networking_resolver.cc +7 -23
- data/ext/facter/facter/lib/src/facts/resolvers/ssh_resolver.cc +1 -0
- data/ext/facter/facter/lib/src/facts/solaris/networking_resolver.cc +0 -5
- data/ext/facter/facter/lib/tests/facts/resolvers/ssh_resolver.cc +8 -1
- data/ext/facter/facter/lib/tests/facts/schema.cc +17 -0
- data/ext/facter/facter/locales/FACTER.pot +2 -23
- data/ext/facter/leatherman/CHANGELOG.md +16 -9
- data/ext/facter/leatherman/CMakeLists.txt +1 -2
- data/ext/facter/leatherman/appveyor.yml +26 -19
- data/ext/facter/leatherman/catch/CMakeLists.txt +1 -1
- data/ext/facter/leatherman/curl/tests/client_test.cc +396 -398
- data/ext/facter/leatherman/curl/tests/mock_curl.cc +2 -0
- data/ext/facter/leatherman/curl/tests/request_test.cc +66 -68
- data/ext/facter/leatherman/curl/tests/response_test.cc +50 -52
- data/ext/facter/leatherman/dynamic_library/tests/dynamic_library_tests.cc +71 -75
- data/ext/facter/leatherman/execution/src/execution.cc +3 -0
- data/ext/facter/leatherman/execution/src/posix/execution.cc +5 -6
- data/ext/facter/leatherman/execution/src/windows/execution.cc +2 -0
- data/ext/facter/leatherman/execution/tests/windows/execution.cc +4 -2
- data/ext/facter/leatherman/file_util/tests/directory_utils_test.cc +66 -68
- data/ext/facter/leatherman/file_util/tests/file_utils_test.cc +175 -177
- data/ext/facter/leatherman/json_container/inc/leatherman/json_container/json_container.hpp +7 -0
- data/ext/facter/leatherman/json_container/src/json_container.cc +10 -1
- data/ext/facter/leatherman/json_container/tests/json_container_test.cc +152 -8
- data/ext/facter/leatherman/locale/CMakeLists.txt +0 -7
- data/ext/facter/leatherman/locales/leatherman.pot +8 -13
- data/ext/facter/leatherman/logging/src/logging.cc +2 -0
- data/ext/facter/leatherman/util/tests/timer.cc +1 -3
- data/ext/facter/leatherman/vendor/Catch-1.10.0.zip +0 -0
- data/ext/facter/leatherman/vendor/nowide/doc/Doxyfile +4 -4
- data/ext/facter/leatherman/vendor/nowide/doc/LICENSE_1_0.txt +23 -0
- data/ext/facter/leatherman/vendor/nowide/doc/main.txt +62 -54
- data/ext/facter/leatherman/vendor/nowide/include/boost/nowide/convert.hpp +16 -16
- data/ext/facter/leatherman/vendor/nowide/include/boost/nowide/cstdio.hpp +4 -4
- data/ext/facter/leatherman/vendor/nowide/include/boost/nowide/utf8_codecvt.hpp +1 -1
- data/ext/facter/leatherman/vendor/nowide/src/iostream.cpp +32 -30
- data/ext/facter/leatherman/vendor/nowide/standalone/convert +6 -6
- data/ext/facter/leatherman/vendor/nowide/standalone/encoding_utf.hpp +1 -1
- data/ext/facter/leatherman/vendor/nowide/standalone/run_convert_and_build.sh +1 -3
- metadata +15 -6
- data/ext/facter/leatherman/cmake/FindICU.cmake +0 -690
- data/ext/facter/leatherman/scripts/travis_target.sh +0 -79
- data/ext/facter/leatherman/vendor/catch-1.4.0.zip +0 -0
@@ -6,7 +6,7 @@
|
|
6
6
|
#, fuzzy
|
7
7
|
msgid ""
|
8
8
|
msgstr ""
|
9
|
-
"Project-Id-Version: FACTER 3.
|
9
|
+
"Project-Id-Version: FACTER 3.11.0\n"
|
10
10
|
"Report-Msgid-Bugs-To: docs@puppet.com\n"
|
11
11
|
"POT-Creation-Date: \n"
|
12
12
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
@@ -275,20 +275,6 @@ msgstr ""
|
|
275
275
|
msgid "/dev/%1%"
|
276
276
|
msgstr ""
|
277
277
|
|
278
|
-
#. debug
|
279
|
-
#: lib/src/facts/aix/disk_resolver.cc
|
280
|
-
msgid ""
|
281
|
-
"Could not open device %1% for reading: %2% (%3%). Disk facts will not be "
|
282
|
-
"populated for this device"
|
283
|
-
msgstr ""
|
284
|
-
|
285
|
-
#. debug
|
286
|
-
#: lib/src/facts/aix/disk_resolver.cc
|
287
|
-
msgid ""
|
288
|
-
"Ioctl IOCINFO failed for device %1%: %2% (%3%). Disk facts will not be "
|
289
|
-
"populated for this device"
|
290
|
-
msgstr ""
|
291
|
-
|
292
278
|
#. warning
|
293
279
|
#: lib/src/facts/aix/disk_resolver.cc
|
294
280
|
msgid ""
|
@@ -642,7 +628,7 @@ msgstr ""
|
|
642
628
|
msgid "kenv lookup for {1}"
|
643
629
|
msgstr ""
|
644
630
|
|
645
|
-
#.
|
631
|
+
#. info
|
646
632
|
#: lib/src/facts/freebsd/dmi_resolver.cc
|
647
633
|
msgid "kenv lookup for {1} failed: {2} ({3})"
|
648
634
|
msgstr ""
|
@@ -1034,13 +1020,6 @@ msgstr ""
|
|
1034
1020
|
msgid "%02x:%02x:%02x:%02x:%02x:%02x"
|
1035
1021
|
msgstr ""
|
1036
1022
|
|
1037
|
-
#: lib/src/facts/resolvers/networking_resolver.cc
|
1038
|
-
#, c-format
|
1039
|
-
msgid ""
|
1040
|
-
"%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:"
|
1041
|
-
"%02x:%02x:%02x:%02x:%02x"
|
1042
|
-
msgstr ""
|
1043
|
-
|
1044
1023
|
#. error
|
1045
1024
|
#: lib/src/facts/resolvers/ruby_resolver.cc
|
1046
1025
|
msgid "error while resolving ruby {1} fact: {2}"
|
@@ -2,6 +2,22 @@
|
|
2
2
|
All notable changes to this project will be documented in this file.
|
3
3
|
This project adheres to [Semantic Versioning](http://semver.org/).
|
4
4
|
|
5
|
+
## [1.4.0]
|
6
|
+
|
7
|
+
### Changed
|
8
|
+
- Updated Catch library to 1.10.0.
|
9
|
+
- Updated Boost.Nowide to ec9672b
|
10
|
+
- Update Travis CI to use container-based builds
|
11
|
+
|
12
|
+
### Fixed
|
13
|
+
- Builds with Xcode 9
|
14
|
+
- Allow Leatherman.execute calls to opt into allowing tasks to finish without reading stdin (i.e. don't fail when the pipe is closed) via the `allow_stdin_unread` option. This specifically supports pxp-agent's task execution where input may or may not be used. (LTH-149)
|
15
|
+
|
16
|
+
## [1.3.0]
|
17
|
+
|
18
|
+
### Added
|
19
|
+
- A toPrettyJson routine to Leatherman.json\_container that pretty prints a valid JSON object.
|
20
|
+
|
5
21
|
## [1.2.2]
|
6
22
|
|
7
23
|
### Fixed
|
@@ -53,15 +69,6 @@ This is a pre-release version for Leatherman 1.0.0, containing backwards-incompa
|
|
53
69
|
### Changed
|
54
70
|
- Remove Ruby bindings for Fixnum and Bignum, replace with Integer for Ruby 2.4 support (LTH-124)
|
55
71
|
|
56
|
-
## [0.12.3]
|
57
|
-
|
58
|
-
This is a maintenance release to re-sync the code version with the tag, in order to make our internal automation happy
|
59
|
-
|
60
|
-
## [0.12.2]
|
61
|
-
|
62
|
-
### Added
|
63
|
-
- Leatherman can now be built with DEP on Windows
|
64
|
-
|
65
72
|
## [0.12.1]
|
66
73
|
|
67
74
|
### Fixed
|
@@ -1,5 +1,5 @@
|
|
1
1
|
cmake_minimum_required(VERSION 3.2.2)
|
2
|
-
project(leatherman VERSION 1.
|
2
|
+
project(leatherman VERSION 1.4.0)
|
3
3
|
|
4
4
|
if (WIN32)
|
5
5
|
link_libraries("-Wl,--nxcompat -Wl,--dynamicbase")
|
@@ -29,7 +29,6 @@ defoption(LEATHERMAN_DEBUG "Enable verbose logging messages from leatherman macr
|
|
29
29
|
defoption(LEATHERMAN_ENABLE_TESTING "Build the leatherman test binary" ${LEATHERMAN_DEFAULT_ENABLE})
|
30
30
|
defoption(LEATHERMAN_INSTALL "Install the leatherman libraries and headers" ${LEATHERMAN_DEFAULT_ENABLE})
|
31
31
|
defoption(LEATHERMAN_SHARED "Create shared libraries instead of static" FALSE)
|
32
|
-
defoption(LEATHERMAN_USE_ICU "Set when Boost is built with ICU" FALSE)
|
33
32
|
|
34
33
|
set(BUILDING_LEATHERMAN TRUE)
|
35
34
|
|
@@ -1,29 +1,36 @@
|
|
1
1
|
clone_depth: 10
|
2
|
-
|
3
|
-
|
4
|
-
-
|
5
|
-
-
|
6
|
-
|
7
|
-
|
8
|
-
-
|
9
|
-
|
2
|
+
environment:
|
3
|
+
matrix:
|
4
|
+
- shared: OFF
|
5
|
+
- shared: ON
|
6
|
+
|
7
|
+
init:
|
8
|
+
- |
|
9
|
+
choco install -y mingw-w64 -Version 5.2.0 -source https://www.myget.org/F/puppetlabs
|
10
|
+
choco install -y cmake -Version 3.2.2 -source https://www.myget.org/F/puppetlabs
|
11
|
+
choco install -y gettext -Version 0.19.6 -source https://www.myget.org/F/puppetlabs
|
12
|
+
choco install -y pl-toolchain-x64 -Version 2015.12.01.1 -source https://www.myget.org/F/puppetlabs
|
13
|
+
choco install -y pl-boost-x64 -Version 1.58.0.2 -source https://www.myget.org/F/puppetlabs
|
14
|
+
choco install -y pl-openssl-x64 -Version 1.0.24.1 -source https://www.myget.org/F/puppetlabs
|
15
|
+
choco install -y pl-curl-x64 -Version 7.46.0.1 -source https://www.myget.org/F/puppetlabs
|
16
|
+
|
17
|
+
- ps: |
|
18
|
+
$env:PATH = $env:PATH.Replace("Git\bin", "Git\cmd")
|
19
|
+
$env:PATH = $env:PATH.Replace("Git\usr\bin", "Git\cmd")
|
10
20
|
|
21
|
+
install:
|
11
22
|
- SET PATH=C:\Ruby21-x64\bin;C:\tools\mingw64\bin;C:\Program Files\gettext-iconv;%PATH%
|
12
|
-
- ps: $env:PATH = $env:PATH.Replace("Git\bin", "Git\cmd")
|
13
|
-
- ps: $env:PATH = $env:PATH.Replace("Git\usr\bin", "Git\cmd")
|
14
23
|
|
15
24
|
build_script:
|
16
|
-
- ps:
|
17
|
-
|
18
|
-
|
25
|
+
- ps: |
|
26
|
+
cmake -G "MinGW Makefiles" -DCMAKE_TOOLCHAIN_FILE="C:\tools\pl-build-tools\pl-build-toolchain.cmake" -DCMAKE_INSTALL_PREFIX=C:\tools\leatherman -DBOOST_STATIC=ON -DLEATHERMAN_SHARED="$env:shared" .
|
27
|
+
mingw32-make -j2
|
19
28
|
|
20
29
|
test_script:
|
21
|
-
- ps:
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
- shared: OFF
|
26
|
-
- shared: ON
|
30
|
+
- ps: |
|
31
|
+
ctest -V 2>&1 | %{ if ($_ -is [System.Management.Automation.ErrorRecord]) { $_ | c++filt } else { $_ } }
|
32
|
+
mingw32-make install
|
33
|
+
7z.exe a -t7z leatherman.7z C:\tools\leatherman\
|
27
34
|
|
28
35
|
artifacts:
|
29
36
|
- path: leatherman.7z
|
@@ -1 +1 @@
|
|
1
|
-
add_leatherman_vendored("
|
1
|
+
add_leatherman_vendored("Catch-1.10.0.zip" "Catch-1.10.0" "single_include")
|
@@ -15,6 +15,7 @@
|
|
15
15
|
using namespace std;
|
16
16
|
namespace fs = boost::filesystem;
|
17
17
|
namespace nw = boost::nowide;
|
18
|
+
using namespace leatherman::curl;
|
18
19
|
|
19
20
|
#define REQUIRE_THROWS_AS_WITH(expression, exception_type, msg_matcher) {\
|
20
21
|
try {\
|
@@ -47,354 +48,352 @@ void remove_temp_file() {
|
|
47
48
|
fs::remove(temp_path);
|
48
49
|
}
|
49
50
|
|
50
|
-
|
51
|
+
struct mock_client : client {
|
52
|
+
curl_handle const& get_handle() { return client::get_handle(); }
|
53
|
+
};
|
51
54
|
|
52
|
-
|
53
|
-
|
54
|
-
};
|
55
|
+
TEST_CASE("curl::client HTTP methods") {
|
56
|
+
mock_client test_client;
|
57
|
+
request test_request {"http://valid.com/"};
|
55
58
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
+
SECTION("GET succeeds on a given URL") {
|
60
|
+
auto resp = test_client.get(test_request);
|
61
|
+
REQUIRE(resp.status_code() == 200);
|
62
|
+
}
|
63
|
+
|
64
|
+
SECTION("POST succeeds on a given URL") {
|
65
|
+
auto resp = test_client.post(test_request);
|
66
|
+
REQUIRE(resp.status_code() == 200);
|
67
|
+
}
|
68
|
+
|
69
|
+
SECTION("PUT succeeds on a given URL") {
|
70
|
+
auto resp = test_client.put(test_request);
|
71
|
+
REQUIRE(resp.status_code() == 200);
|
72
|
+
}
|
73
|
+
|
74
|
+
SECTION("Request returns status code 404 on invalid URL") {
|
75
|
+
request invalid_test_request {"http://invalid.com/"};
|
76
|
+
auto resp = test_client.get(invalid_test_request);
|
77
|
+
REQUIRE(resp.status_code() == 404);
|
78
|
+
}
|
79
|
+
}
|
59
80
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
}
|
81
|
+
TEST_CASE("curl::client HTTP request setup") {
|
82
|
+
mock_client test_client;
|
83
|
+
request test_request {"http://valid.com"};
|
64
84
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
85
|
+
SECTION("HTTP method is set to GET given a GET request") {
|
86
|
+
auto resp = test_client.get(test_request);
|
87
|
+
CURL* const& handle = test_client.get_handle();
|
88
|
+
auto test_impl = reinterpret_cast<curl_impl* const>(handle);
|
89
|
+
REQUIRE(test_impl->method == curl_impl::http_method::get);
|
90
|
+
}
|
69
91
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
92
|
+
SECTION("HTTP method is set to POST given a POST request") {
|
93
|
+
auto resp = test_client.post(test_request);
|
94
|
+
CURL* const& handle = test_client.get_handle();
|
95
|
+
auto test_impl = reinterpret_cast<curl_impl* const>(handle);
|
96
|
+
REQUIRE(test_impl->method == curl_impl::http_method::post);
|
97
|
+
}
|
74
98
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
99
|
+
SECTION("HTTP method is set to PUT given a PUT request") {
|
100
|
+
auto resp = test_client.put(test_request);
|
101
|
+
CURL* const& handle = test_client.get_handle();
|
102
|
+
auto test_impl = reinterpret_cast<curl_impl* const>(handle);
|
103
|
+
REQUIRE(test_impl->method == curl_impl::http_method::put);
|
80
104
|
}
|
81
105
|
|
82
|
-
|
83
|
-
|
106
|
+
SECTION("cURL should receive the URL specified in the request") {
|
107
|
+
auto resp = test_client.get(test_request);
|
108
|
+
CURL* const& handle = test_client.get_handle();
|
109
|
+
auto test_impl = reinterpret_cast<curl_impl* const>(handle);
|
110
|
+
REQUIRE(test_impl->request_url == "http://valid.com");
|
111
|
+
}
|
112
|
+
}
|
113
|
+
|
114
|
+
TEST_CASE("curl::client header and body writing and reading") {
|
115
|
+
mock_client test_client;
|
116
|
+
|
117
|
+
/*
|
118
|
+
* Header writing and reading tests
|
119
|
+
*/
|
120
|
+
SECTION("Custom request headers should be honored in the request to the server") {
|
84
121
|
request test_request {"http://valid.com"};
|
122
|
+
test_request.add_header("header_name", "header_value");
|
123
|
+
auto resp = test_client.get(test_request);
|
124
|
+
CURL* const& handle = test_client.get_handle();
|
125
|
+
auto test_impl = reinterpret_cast<curl_impl* const>(handle);
|
126
|
+
REQUIRE(test_impl->header);
|
127
|
+
REQUIRE(test_impl->header->data == string("header_name: header_value"));
|
128
|
+
}
|
85
129
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
auto test_impl = reinterpret_cast<curl_impl* const>(handle);
|
97
|
-
REQUIRE(test_impl->method == curl_impl::http_method::post);
|
98
|
-
}
|
99
|
-
|
100
|
-
SECTION("HTTP method is set to PUT given a PUT request") {
|
101
|
-
auto resp = test_client.put(test_request);
|
102
|
-
CURL* const& handle = test_client.get_handle();
|
103
|
-
auto test_impl = reinterpret_cast<curl_impl* const>(handle);
|
104
|
-
REQUIRE(test_impl->method == curl_impl::http_method::put);
|
105
|
-
}
|
106
|
-
|
107
|
-
SECTION("cURL should receive the URL specified in the request") {
|
108
|
-
auto resp = test_client.get(test_request);
|
109
|
-
CURL* const& handle = test_client.get_handle();
|
110
|
-
auto test_impl = reinterpret_cast<curl_impl* const>(handle);
|
111
|
-
REQUIRE(test_impl->request_url == "http://valid.com");
|
112
|
-
}
|
113
|
-
}
|
114
|
-
|
115
|
-
TEST_CASE("curl::client header and body writing and reading") {
|
116
|
-
mock_client test_client;
|
130
|
+
SECTION("The header response delimiter should be ignored") {
|
131
|
+
request test_request {"http://response-delimiter.com/"};
|
132
|
+
auto resp = test_client.get(test_request);
|
133
|
+
int headers = 0;
|
134
|
+
resp.each_header([&](string const& name, string const& value) {
|
135
|
+
++headers;
|
136
|
+
return true;
|
137
|
+
});
|
138
|
+
REQUIRE(headers == 0);
|
139
|
+
}
|
117
140
|
|
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
|
-
SECTION("Non-standard response header should be parsed for name and value") {
|
143
|
-
request test_request {"http://nonstd-header.com/"};
|
144
|
-
auto resp = test_client.get(test_request);
|
145
|
-
REQUIRE(resp.header("nonstd_header_name"));
|
146
|
-
REQUIRE(*(resp.header("nonstd_header_name")) == "nonstd_header_value");
|
147
|
-
}
|
148
|
-
|
149
|
-
SECTION("Invalid headers should not be parsed or returned in the response") {
|
150
|
-
request test_request {"http://invalid-header.com/"};
|
151
|
-
auto resp = test_client.get(test_request);
|
152
|
-
int headers = 0;
|
153
|
-
resp.each_header([&](string const& name, string const& value) {
|
154
|
-
++headers;
|
155
|
-
return true;
|
156
|
-
});
|
157
|
-
REQUIRE(headers == 0);
|
158
|
-
}
|
159
|
-
|
160
|
-
/*
|
161
|
-
* Body writing and reading tests
|
162
|
-
*/
|
163
|
-
SECTION("Request body should be settable and readable") {
|
164
|
-
request test_request {"http://valid.com"};
|
165
|
-
test_request.body("Hello, I am a request body!", "message");
|
166
|
-
auto resp = test_client.get(test_request);
|
167
|
-
CURL* const& handle = test_client.get_handle();
|
168
|
-
auto test_impl = reinterpret_cast<curl_impl* const>(handle);
|
169
|
-
REQUIRE(test_impl->read_buffer == "Hello, I am a request body!");
|
170
|
-
}
|
171
|
-
|
172
|
-
SECTION("Response body should be what is in the data part of the cURL response") {
|
173
|
-
CURL* const& handle = test_client.get_handle();
|
174
|
-
auto test_impl = reinterpret_cast<curl_impl* const>(handle);
|
175
|
-
test_impl->resp_body = "Hello, I am a response body!";
|
176
|
-
request test_request {"http://valid.com"};
|
177
|
-
auto resp = test_client.get(test_request);
|
178
|
-
REQUIRE(resp.body() == "Hello, I am a response body!");
|
179
|
-
}
|
180
|
-
}
|
181
|
-
|
182
|
-
TEST_CASE("curl::client cookies") {
|
183
|
-
mock_client test_client;
|
141
|
+
SECTION("Non-standard response header should be parsed for name and value") {
|
142
|
+
request test_request {"http://nonstd-header.com/"};
|
143
|
+
auto resp = test_client.get(test_request);
|
144
|
+
REQUIRE(resp.header("nonstd_header_name"));
|
145
|
+
REQUIRE(*(resp.header("nonstd_header_name")) == "nonstd_header_value");
|
146
|
+
}
|
147
|
+
|
148
|
+
SECTION("Invalid headers should not be parsed or returned in the response") {
|
149
|
+
request test_request {"http://invalid-header.com/"};
|
150
|
+
auto resp = test_client.get(test_request);
|
151
|
+
int headers = 0;
|
152
|
+
resp.each_header([&](string const& name, string const& value) {
|
153
|
+
++headers;
|
154
|
+
return true;
|
155
|
+
});
|
156
|
+
REQUIRE(headers == 0);
|
157
|
+
}
|
158
|
+
|
159
|
+
/*
|
160
|
+
* Body writing and reading tests
|
161
|
+
*/
|
162
|
+
SECTION("Request body should be settable and readable") {
|
184
163
|
request test_request {"http://valid.com"};
|
164
|
+
test_request.body("Hello, I am a request body!", "message");
|
165
|
+
auto resp = test_client.get(test_request);
|
166
|
+
CURL* const& handle = test_client.get_handle();
|
167
|
+
auto test_impl = reinterpret_cast<curl_impl* const>(handle);
|
168
|
+
REQUIRE(test_impl->read_buffer == "Hello, I am a request body!");
|
169
|
+
}
|
185
170
|
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
REQUIRE(test_impl->cookie == "");
|
191
|
-
}
|
192
|
-
|
193
|
-
SECTION("Cookies should be present in the request when added") {
|
194
|
-
test_request.add_cookie("cookie_name", "cookie_val");
|
195
|
-
auto resp = test_client.get(test_request);
|
196
|
-
CURL* const& handle = test_client.get_handle();
|
197
|
-
auto test_impl = reinterpret_cast<curl_impl* const>(handle);
|
198
|
-
REQUIRE(test_impl->cookie == "cookie_name=cookie_val");
|
199
|
-
}
|
200
|
-
|
201
|
-
SECTION("Cookies should be removable from the request") {
|
202
|
-
test_request.add_cookie("cookie_0", "cookie_val_0");
|
203
|
-
test_request.add_cookie("cookie_1", "cookie_val_1");
|
204
|
-
test_request.remove_cookie("cookie_1");
|
205
|
-
auto resp = test_client.get(test_request);
|
206
|
-
CURL* const& handle = test_client.get_handle();
|
207
|
-
auto test_impl = reinterpret_cast<curl_impl* const>(handle);
|
208
|
-
REQUIRE(test_impl->cookie == "cookie_0=cookie_val_0");
|
209
|
-
}
|
210
|
-
|
211
|
-
SECTION("cURL should receieve cookies specified in the request") {
|
212
|
-
test_request.add_cookie("cookie_0", "cookie_val_0");
|
213
|
-
test_request.add_cookie("cookie_1", "cookie_val_1");
|
214
|
-
auto resp = test_client.get(test_request);
|
215
|
-
CURL* const& handle = test_client.get_handle();
|
216
|
-
auto test_impl = reinterpret_cast<curl_impl* const>(handle);
|
217
|
-
REQUIRE(test_impl->cookie == "cookie_0=cookie_val_0; cookie_1=cookie_val_1");
|
218
|
-
}
|
219
|
-
}
|
220
|
-
|
221
|
-
TEST_CASE("curl::client CA bundle and SSL setup") {
|
222
|
-
mock_client test_client;
|
171
|
+
SECTION("Response body should be what is in the data part of the cURL response") {
|
172
|
+
CURL* const& handle = test_client.get_handle();
|
173
|
+
auto test_impl = reinterpret_cast<curl_impl* const>(handle);
|
174
|
+
test_impl->resp_body = "Hello, I am a response body!";
|
223
175
|
request test_request {"http://valid.com"};
|
176
|
+
auto resp = test_client.get(test_request);
|
177
|
+
REQUIRE(resp.body() == "Hello, I am a response body!");
|
178
|
+
}
|
179
|
+
}
|
224
180
|
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
181
|
+
TEST_CASE("curl::client cookies") {
|
182
|
+
mock_client test_client;
|
183
|
+
request test_request {"http://valid.com"};
|
184
|
+
|
185
|
+
SECTION("There should be no cookies in the request by default") {
|
186
|
+
auto resp = test_client.get(test_request);
|
187
|
+
CURL* const& handle = test_client.get_handle();
|
188
|
+
auto test_impl = reinterpret_cast<curl_impl* const>(handle);
|
189
|
+
REQUIRE(test_impl->cookie == "");
|
190
|
+
}
|
191
|
+
|
192
|
+
SECTION("Cookies should be present in the request when added") {
|
193
|
+
test_request.add_cookie("cookie_name", "cookie_val");
|
194
|
+
auto resp = test_client.get(test_request);
|
195
|
+
CURL* const& handle = test_client.get_handle();
|
196
|
+
auto test_impl = reinterpret_cast<curl_impl* const>(handle);
|
197
|
+
REQUIRE(test_impl->cookie == "cookie_name=cookie_val");
|
198
|
+
}
|
199
|
+
|
200
|
+
SECTION("Cookies should be removable from the request") {
|
201
|
+
test_request.add_cookie("cookie_0", "cookie_val_0");
|
202
|
+
test_request.add_cookie("cookie_1", "cookie_val_1");
|
203
|
+
test_request.remove_cookie("cookie_1");
|
204
|
+
auto resp = test_client.get(test_request);
|
205
|
+
CURL* const& handle = test_client.get_handle();
|
206
|
+
auto test_impl = reinterpret_cast<curl_impl* const>(handle);
|
207
|
+
REQUIRE(test_impl->cookie == "cookie_0=cookie_val_0");
|
208
|
+
}
|
209
|
+
|
210
|
+
SECTION("cURL should receieve cookies specified in the request") {
|
211
|
+
test_request.add_cookie("cookie_0", "cookie_val_0");
|
212
|
+
test_request.add_cookie("cookie_1", "cookie_val_1");
|
213
|
+
auto resp = test_client.get(test_request);
|
214
|
+
CURL* const& handle = test_client.get_handle();
|
215
|
+
auto test_impl = reinterpret_cast<curl_impl* const>(handle);
|
216
|
+
REQUIRE(test_impl->cookie == "cookie_0=cookie_val_0; cookie_1=cookie_val_1");
|
217
|
+
}
|
218
|
+
}
|
219
|
+
|
220
|
+
TEST_CASE("curl::client CA bundle and SSL setup") {
|
221
|
+
mock_client test_client;
|
222
|
+
request test_request {"http://valid.com"};
|
223
|
+
|
224
|
+
SECTION("Path to CA certificate should be unspecified by default") {
|
225
|
+
auto resp = test_client.get(test_request);
|
226
|
+
CURL* const& handle = test_client.get_handle();
|
227
|
+
auto test_impl = reinterpret_cast<curl_impl* const>(handle);
|
228
|
+
REQUIRE(test_impl->cacert == "");
|
229
|
+
}
|
230
|
+
|
231
|
+
SECTION("cURL should receive the path to the CA certificate specified in the request") {
|
232
|
+
test_client.set_ca_cert("cacert");
|
233
|
+
auto resp = test_client.get(test_request);
|
234
|
+
CURL* const& handle = test_client.get_handle();
|
235
|
+
auto test_impl = reinterpret_cast<curl_impl* const>(handle);
|
236
|
+
REQUIRE(test_impl->cacert == "cacert");
|
237
|
+
}
|
238
|
+
|
239
|
+
SECTION("Client cert name should be unspecified by default") {
|
240
|
+
auto resp = test_client.get(test_request);
|
241
|
+
CURL* const& handle = test_client.get_handle();
|
242
|
+
auto test_impl = reinterpret_cast<curl_impl* const>(handle);
|
243
|
+
REQUIRE(test_impl->client_cert == "");
|
244
|
+
}
|
245
|
+
|
246
|
+
SECTION("cURL should receive the client cert name specified in the request") {
|
247
|
+
test_client.set_client_cert("cert", "key");
|
248
|
+
auto resp = test_client.get(test_request);
|
249
|
+
CURL* const& handle = test_client.get_handle();
|
250
|
+
auto test_impl = reinterpret_cast<curl_impl* const>(handle);
|
251
|
+
REQUIRE(test_impl->client_cert == "cert");
|
252
|
+
}
|
253
|
+
|
254
|
+
SECTION("Private keyfile name should be unspecified by default") {
|
255
|
+
auto resp = test_client.get(test_request);
|
256
|
+
CURL* const& handle = test_client.get_handle();
|
257
|
+
auto test_impl = reinterpret_cast<curl_impl* const>(handle);
|
258
|
+
REQUIRE(test_impl->client_key == "");
|
259
|
+
}
|
260
|
+
|
261
|
+
SECTION("cURL should receive the private keyfile name specified in the request") {
|
262
|
+
test_client.set_client_cert("cert", "key");
|
263
|
+
auto resp = test_client.get(test_request);
|
264
|
+
CURL* const& handle = test_client.get_handle();
|
265
|
+
auto test_impl = reinterpret_cast<curl_impl* const>(handle);
|
266
|
+
REQUIRE(test_impl->client_key == "key");
|
267
|
+
}
|
268
|
+
|
269
|
+
SECTION("cURL should make an HTTP request with the specified HTTP protocol") {
|
270
|
+
test_client.set_supported_protocols(CURLPROTO_HTTP);
|
271
|
+
auto resp = test_client.get(test_request);
|
272
|
+
CURL* const& handle = test_client.get_handle();
|
273
|
+
auto test_impl = reinterpret_cast<curl_impl* const>(handle);
|
274
|
+
REQUIRE(test_impl->protocols == CURLPROTO_HTTP);
|
275
|
+
}
|
276
|
+
|
277
|
+
SECTION("cURL defaults to all protocols if no protocols are specified") {
|
278
|
+
auto resp = test_client.get(test_request);
|
289
279
|
CURL* const& handle = test_client.get_handle();
|
290
280
|
auto test_impl = reinterpret_cast<curl_impl* const>(handle);
|
281
|
+
REQUIRE(test_impl->protocols == CURLPROTO_ALL);
|
282
|
+
}
|
283
|
+
}
|
284
|
+
|
285
|
+
TEST_CASE("curl::client errors") {
|
286
|
+
mock_client test_client;
|
287
|
+
request test_request {"http://valid.com/"};
|
288
|
+
CURL* const& handle = test_client.get_handle();
|
289
|
+
auto test_impl = reinterpret_cast<curl_impl* const>(handle);
|
290
|
+
|
291
|
+
/*
|
292
|
+
* Note: we do not currently test the case where cURL errors
|
293
|
+
* on curl_global_init, as the global init is done as part of
|
294
|
+
* static initialization in the cURL helper, and there is
|
295
|
+
* currently no way to force it to be reinitialized.
|
296
|
+
*/
|
297
|
+
|
298
|
+
SECTION("client fails to initialize a libcurl easy session") {
|
299
|
+
curl_fail_init mock_error {easy_init_error};
|
300
|
+
REQUIRE_THROWS_AS(mock_client(), http_exception);
|
301
|
+
}
|
302
|
+
|
303
|
+
SECTION("client fails to perform a cURL request") {
|
304
|
+
test_impl->test_failure_mode = curl_impl::error_mode::easy_perform_error;
|
305
|
+
REQUIRE_THROWS_AS(test_client.get(test_request), http_request_exception);
|
306
|
+
}
|
307
|
+
|
308
|
+
SECTION("client fails to set HTTP method to POST") {
|
309
|
+
test_impl->test_failure_mode = curl_impl::error_mode::http_post_error;
|
310
|
+
REQUIRE_THROWS_AS(test_client.post(test_request), http_curl_setup_exception);
|
311
|
+
}
|
312
|
+
|
313
|
+
SECTION("client fails to set HTTP method to PUT") {
|
314
|
+
test_impl->test_failure_mode = curl_impl::error_mode::http_put_error;
|
315
|
+
REQUIRE_THROWS_AS(test_client.put(test_request), http_curl_setup_exception);
|
316
|
+
}
|
317
|
+
|
318
|
+
SECTION("client fails to set the request URL") {
|
319
|
+
test_impl->test_failure_mode = curl_impl::error_mode::set_url_error;
|
320
|
+
REQUIRE_THROWS_AS(test_client.get(test_request), http_curl_setup_exception);
|
321
|
+
}
|
322
|
+
|
323
|
+
SECTION("client fails to set the request headers") {
|
324
|
+
test_impl->test_failure_mode = curl_impl::error_mode::set_header_error;
|
325
|
+
REQUIRE_THROWS_AS(test_client.get(test_request), http_curl_setup_exception);
|
326
|
+
}
|
327
|
+
|
328
|
+
SECTION("client fails to set cookies in the request") {
|
329
|
+
test_impl->test_failure_mode = curl_impl::error_mode::set_cookie_error;
|
330
|
+
REQUIRE_THROWS_AS(test_client.get(test_request), http_curl_setup_exception);
|
331
|
+
}
|
332
|
+
|
333
|
+
SECTION("client fails to set the header callback function") {
|
334
|
+
test_impl->test_failure_mode = curl_impl::error_mode::header_function_error;
|
335
|
+
REQUIRE_THROWS_AS(test_client.get(test_request), http_curl_setup_exception);
|
336
|
+
}
|
291
337
|
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
* static initialization in the cURL helper, and there is
|
296
|
-
* currently no way to force it to be reinitialized.
|
297
|
-
*/
|
298
|
-
|
299
|
-
SECTION("client fails to initialize a libcurl easy session") {
|
300
|
-
curl_fail_init mock_error {easy_init_error};
|
301
|
-
REQUIRE_THROWS_AS(mock_client test_client, http_exception);
|
302
|
-
}
|
303
|
-
|
304
|
-
SECTION("client fails to perform a cURL request") {
|
305
|
-
test_impl->test_failure_mode = curl_impl::error_mode::easy_perform_error;
|
306
|
-
REQUIRE_THROWS_AS(test_client.get(test_request), http_request_exception);
|
307
|
-
}
|
308
|
-
|
309
|
-
SECTION("client fails to set HTTP method to POST") {
|
310
|
-
test_impl->test_failure_mode = curl_impl::error_mode::http_post_error;
|
311
|
-
REQUIRE_THROWS_AS(test_client.post(test_request), http_curl_setup_exception);
|
312
|
-
}
|
313
|
-
|
314
|
-
SECTION("client fails to set HTTP method to PUT") {
|
315
|
-
test_impl->test_failure_mode = curl_impl::error_mode::http_put_error;
|
316
|
-
REQUIRE_THROWS_AS(test_client.put(test_request), http_curl_setup_exception);
|
317
|
-
}
|
318
|
-
|
319
|
-
SECTION("client fails to set the request URL") {
|
320
|
-
test_impl->test_failure_mode = curl_impl::error_mode::set_url_error;
|
321
|
-
REQUIRE_THROWS_AS(test_client.get(test_request), http_curl_setup_exception);
|
322
|
-
}
|
323
|
-
|
324
|
-
SECTION("client fails to set the request headers") {
|
325
|
-
test_impl->test_failure_mode = curl_impl::error_mode::set_header_error;
|
326
|
-
REQUIRE_THROWS_AS(test_client.get(test_request), http_curl_setup_exception);
|
327
|
-
}
|
328
|
-
|
329
|
-
SECTION("client fails to set cookies in the request") {
|
330
|
-
test_impl->test_failure_mode = curl_impl::error_mode::set_cookie_error;
|
331
|
-
REQUIRE_THROWS_AS(test_client.get(test_request), http_curl_setup_exception);
|
332
|
-
}
|
333
|
-
|
334
|
-
SECTION("client fails to set the header callback function") {
|
335
|
-
test_impl->test_failure_mode = curl_impl::error_mode::header_function_error;
|
336
|
-
REQUIRE_THROWS_AS(test_client.get(test_request), http_curl_setup_exception);
|
337
|
-
}
|
338
|
-
|
339
|
-
SECTION("client fails to set the header write location") {
|
340
|
-
test_impl->test_failure_mode = curl_impl::error_mode::header_context_error;
|
341
|
-
REQUIRE_THROWS_AS(test_client.get(test_request), http_curl_setup_exception);
|
342
|
-
}
|
343
|
-
|
344
|
-
SECTION("client fails to set the body writing callback function") {
|
345
|
-
test_impl->test_failure_mode = curl_impl::error_mode::write_body_function_error;
|
346
|
-
REQUIRE_THROWS_AS(test_client.get(test_request), http_curl_setup_exception);
|
347
|
-
}
|
348
|
-
|
349
|
-
SECTION("client fails to set the body write location") {
|
350
|
-
test_impl->test_failure_mode = curl_impl::error_mode::write_body_context_error;
|
351
|
-
REQUIRE_THROWS_AS(test_client.get(test_request), http_curl_setup_exception);
|
352
|
-
}
|
353
|
-
SECTION("client fails to set the read_body callback function") {
|
354
|
-
test_impl->test_failure_mode = curl_impl::error_mode::read_body_function_error;
|
355
|
-
REQUIRE_THROWS_AS(test_client.get(test_request), http_curl_setup_exception);
|
356
|
-
}
|
357
|
-
|
358
|
-
SECTION("client fails to set the read_body data source") {
|
359
|
-
test_impl->test_failure_mode = curl_impl::error_mode::read_body_context_error;
|
360
|
-
REQUIRE_THROWS_AS(test_client.get(test_request), http_curl_setup_exception);
|
361
|
-
}
|
362
|
-
|
363
|
-
SECTION("client fails to set the connection timeout") {
|
364
|
-
test_impl->test_failure_mode = curl_impl::error_mode::connect_timeout_error;
|
365
|
-
REQUIRE_THROWS_AS(test_client.get(test_request), http_curl_setup_exception);
|
366
|
-
}
|
367
|
-
|
368
|
-
SECTION("client fails to set the request timeout") {
|
369
|
-
test_impl->test_failure_mode = curl_impl::error_mode::request_timeout_error;
|
370
|
-
REQUIRE_THROWS_AS(test_client.get(test_request), http_curl_setup_exception);
|
371
|
-
}
|
372
|
-
|
373
|
-
SECTION("client fails to set certificate authority info") {
|
374
|
-
test_client.set_ca_cert("certfile");
|
375
|
-
test_impl->test_failure_mode = curl_impl::error_mode::ca_bundle_error;
|
376
|
-
REQUIRE_THROWS_AS(test_client.get(test_request), http_curl_setup_exception);
|
377
|
-
}
|
378
|
-
|
379
|
-
SECTION("client fails to set SSL cert info") {
|
380
|
-
test_client.set_client_cert("cert", "key");
|
381
|
-
test_impl->test_failure_mode = curl_impl::error_mode::ssl_cert_error;
|
382
|
-
REQUIRE_THROWS_AS(test_client.get(test_request), http_curl_setup_exception);
|
383
|
-
}
|
384
|
-
|
385
|
-
SECTION("client fails to set SSL key info") {
|
386
|
-
test_client.set_client_cert("cert", "key");
|
387
|
-
test_impl->test_failure_mode = curl_impl::error_mode::ssl_key_error;
|
388
|
-
REQUIRE_THROWS_AS(test_client.get(test_request), http_curl_setup_exception);
|
389
|
-
}
|
390
|
-
|
391
|
-
SECTION("client fails to make http call with https protocol only enabled") {
|
392
|
-
test_client.set_supported_protocols(CURLPROTO_HTTPS);
|
393
|
-
test_impl->test_failure_mode = curl_impl::error_mode::protocol_error;
|
394
|
-
REQUIRE_THROWS_AS(test_client.get(test_request), http_curl_setup_exception);
|
395
|
-
}
|
338
|
+
SECTION("client fails to set the header write location") {
|
339
|
+
test_impl->test_failure_mode = curl_impl::error_mode::header_context_error;
|
340
|
+
REQUIRE_THROWS_AS(test_client.get(test_request), http_curl_setup_exception);
|
396
341
|
}
|
397
342
|
|
343
|
+
SECTION("client fails to set the body writing callback function") {
|
344
|
+
test_impl->test_failure_mode = curl_impl::error_mode::write_body_function_error;
|
345
|
+
REQUIRE_THROWS_AS(test_client.get(test_request), http_curl_setup_exception);
|
346
|
+
}
|
347
|
+
|
348
|
+
SECTION("client fails to set the body write location") {
|
349
|
+
test_impl->test_failure_mode = curl_impl::error_mode::write_body_context_error;
|
350
|
+
REQUIRE_THROWS_AS(test_client.get(test_request), http_curl_setup_exception);
|
351
|
+
}
|
352
|
+
SECTION("client fails to set the read_body callback function") {
|
353
|
+
test_impl->test_failure_mode = curl_impl::error_mode::read_body_function_error;
|
354
|
+
REQUIRE_THROWS_AS(test_client.get(test_request), http_curl_setup_exception);
|
355
|
+
}
|
356
|
+
|
357
|
+
SECTION("client fails to set the read_body data source") {
|
358
|
+
test_impl->test_failure_mode = curl_impl::error_mode::read_body_context_error;
|
359
|
+
REQUIRE_THROWS_AS(test_client.get(test_request), http_curl_setup_exception);
|
360
|
+
}
|
361
|
+
|
362
|
+
SECTION("client fails to set the connection timeout") {
|
363
|
+
test_impl->test_failure_mode = curl_impl::error_mode::connect_timeout_error;
|
364
|
+
REQUIRE_THROWS_AS(test_client.get(test_request), http_curl_setup_exception);
|
365
|
+
}
|
366
|
+
|
367
|
+
SECTION("client fails to set the request timeout") {
|
368
|
+
test_impl->test_failure_mode = curl_impl::error_mode::request_timeout_error;
|
369
|
+
REQUIRE_THROWS_AS(test_client.get(test_request), http_curl_setup_exception);
|
370
|
+
}
|
371
|
+
|
372
|
+
SECTION("client fails to set certificate authority info") {
|
373
|
+
test_client.set_ca_cert("certfile");
|
374
|
+
test_impl->test_failure_mode = curl_impl::error_mode::ca_bundle_error;
|
375
|
+
REQUIRE_THROWS_AS(test_client.get(test_request), http_curl_setup_exception);
|
376
|
+
}
|
377
|
+
|
378
|
+
SECTION("client fails to set SSL cert info") {
|
379
|
+
test_client.set_client_cert("cert", "key");
|
380
|
+
test_impl->test_failure_mode = curl_impl::error_mode::ssl_cert_error;
|
381
|
+
REQUIRE_THROWS_AS(test_client.get(test_request), http_curl_setup_exception);
|
382
|
+
}
|
383
|
+
|
384
|
+
SECTION("client fails to set SSL key info") {
|
385
|
+
test_client.set_client_cert("cert", "key");
|
386
|
+
test_impl->test_failure_mode = curl_impl::error_mode::ssl_key_error;
|
387
|
+
REQUIRE_THROWS_AS(test_client.get(test_request), http_curl_setup_exception);
|
388
|
+
}
|
389
|
+
|
390
|
+
SECTION("client fails to make http call with https protocol only enabled") {
|
391
|
+
test_client.set_supported_protocols(CURLPROTO_HTTPS);
|
392
|
+
test_impl->test_failure_mode = curl_impl::error_mode::protocol_error;
|
393
|
+
REQUIRE_THROWS_AS(test_client.get(test_request), http_curl_setup_exception);
|
394
|
+
}
|
395
|
+
}
|
396
|
+
|
398
397
|
TEST_CASE("curl::client download_file") {
|
399
398
|
mock_client test_client;
|
400
399
|
temp_directory temp_dir;
|
@@ -542,74 +541,73 @@ namespace leatherman { namespace curl {
|
|
542
541
|
}
|
543
542
|
}
|
544
543
|
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
544
|
+
TEST_CASE("curl::client download_file errors") {
|
545
|
+
mock_client test_client;
|
546
|
+
temp_directory temp_dir;
|
547
|
+
fs::path temp_dir_path = fs::path(temp_dir.get_dir_name());
|
548
|
+
CURL* const& handle = test_client.get_handle();
|
549
|
+
auto test_impl = reinterpret_cast<curl_impl* const>(handle);
|
550
|
+
|
551
|
+
SECTION("when fopen fails, an http_file_operation_exception is thrown") {
|
552
|
+
fs::path parent_dir = temp_dir_path / "parent";
|
553
|
+
std::string file_path = (parent_dir / "child").string();
|
554
|
+
request req("");
|
555
|
+
REQUIRE_THROWS_AS_WITH(
|
556
|
+
test_client.download_file(req, file_path),
|
557
|
+
http_file_operation_exception,
|
558
|
+
Catch::Equals("File operation error: failed to open temporary file for writing"));
|
559
|
+
}
|
560
|
+
|
561
|
+
SECTION("when curl_easy_setopt fails, an http_curl_setup_exception is thrown and the temporary file is removed") {
|
562
|
+
request req("");
|
563
|
+
std::string file_path = (temp_dir_path / "file").string();
|
564
|
+
test_impl->test_failure_mode = curl_impl::error_mode::set_url_error;
|
565
|
+
REQUIRE_THROWS_AS(test_client.download_file(req, file_path), http_curl_setup_exception);
|
566
|
+
// Ensure that the temp file was removed
|
567
|
+
REQUIRE(fs::is_empty(temp_dir_path));
|
568
|
+
}
|
569
|
+
|
570
|
+
SECTION("when curl_easy_perform fails due to a CURLE_WRITE_ERROR, but the temporary file is removed, an http_file_operation_exception is thrown") {
|
571
|
+
std::string file_path = (temp_dir_path / "file").string();
|
572
|
+
request req("");
|
573
|
+
test_impl->test_failure_mode = curl_impl::error_mode::easy_perform_write_error;
|
574
|
+
REQUIRE_THROWS_AS_WITH(
|
575
|
+
test_client.download_file(req, file_path),
|
576
|
+
http_file_operation_exception,
|
577
|
+
Catch::StartsWith("File operation error: failed to write to the temporary file during download"));
|
578
|
+
}
|
579
|
+
|
580
|
+
SECTION("when curl_easy_perform fails for reasons other than a CURLE_WRITE_ERROR, but the temporary file is removed, only the errbuf message is contained in the thrown http_file_download_exception") {
|
581
|
+
std::string file_path = (temp_dir_path / "file").string();
|
582
|
+
request req("");
|
583
|
+
test_impl->test_failure_mode = curl_impl::error_mode::easy_perform_error;
|
584
|
+
REQUIRE_THROWS_AS_WITH(
|
585
|
+
test_client.download_file(req, file_path),
|
586
|
+
http_file_download_exception,
|
587
|
+
Catch::Equals("File download server side error: easy perform failed"));
|
588
|
+
|
589
|
+
// Ensure that the temp file was removed
|
590
|
+
REQUIRE(fs::is_empty(temp_dir_path));
|
591
|
+
}
|
551
592
|
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
curl::request req("");
|
574
|
-
test_impl->test_failure_mode = curl_impl::error_mode::easy_perform_write_error;
|
575
|
-
REQUIRE_THROWS_AS_WITH(
|
576
|
-
test_client.download_file(req, file_path),
|
577
|
-
curl::http_file_operation_exception,
|
578
|
-
Catch::StartsWith("File operation error: failed to write to the temporary file during download"));
|
579
|
-
}
|
580
|
-
|
581
|
-
SECTION("when curl_easy_perform fails for reasons other than a CURLE_WRITE_ERROR, but the temporary file is removed, only the errbuf message is contained in the thrown http_file_download_exception") {
|
582
|
-
std::string file_path = (temp_dir_path / "file").string();
|
583
|
-
curl::request req("");
|
584
|
-
test_impl->test_failure_mode = curl_impl::error_mode::easy_perform_error;
|
585
|
-
REQUIRE_THROWS_AS_WITH(
|
586
|
-
test_client.download_file(req, file_path),
|
587
|
-
curl::http_file_download_exception,
|
588
|
-
Catch::Equals("File download server side error: easy perform failed"));
|
589
|
-
|
590
|
-
// Ensure that the temp file was removed
|
591
|
-
REQUIRE(fs::is_empty(temp_dir_path));
|
592
|
-
}
|
593
|
-
|
594
|
-
SECTION("when renaming the temporary file to the user-provided file path fails, an http_file_operation_exception is thrown") {
|
595
|
-
std::string file_path = (temp_dir_path / "file").string();
|
596
|
-
curl::request req("https://download.com");
|
597
|
-
test_impl->trigger_external_failure = remove_temp_file;
|
598
|
-
REQUIRE_THROWS_AS_WITH(
|
599
|
-
test_client.download_file(req, file_path),
|
600
|
-
curl::http_file_operation_exception,
|
601
|
-
Catch::StartsWith("File operation error: failed to move over the temporary file's downloaded contents"));
|
602
|
-
}
|
603
|
-
|
604
|
-
SECTION("when writing the temporary file's contents to the response body fails, an http_file_operation_exception is thrown") {
|
605
|
-
std::string file_path = (temp_dir_path / "file").string();
|
606
|
-
request req("https://download_trigger_404.com");
|
607
|
-
test_impl->trigger_external_failure = remove_temp_file;
|
608
|
-
response res;
|
609
|
-
REQUIRE_THROWS_AS_WITH(
|
610
|
-
test_client.download_file(req, file_path, res),
|
611
|
-
curl::http_file_operation_exception,
|
612
|
-
Catch::StartsWith("File operation error: failed to write the temporary file's contents to the response body"));
|
613
|
-
}
|
614
|
-
}
|
615
|
-
}}
|
593
|
+
SECTION("when renaming the temporary file to the user-provided file path fails, an http_file_operation_exception is thrown") {
|
594
|
+
std::string file_path = (temp_dir_path / "file").string();
|
595
|
+
request req("https://download.com");
|
596
|
+
test_impl->trigger_external_failure = remove_temp_file;
|
597
|
+
REQUIRE_THROWS_AS_WITH(
|
598
|
+
test_client.download_file(req, file_path),
|
599
|
+
http_file_operation_exception,
|
600
|
+
Catch::StartsWith("File operation error: failed to move over the temporary file's downloaded contents"));
|
601
|
+
}
|
602
|
+
|
603
|
+
SECTION("when writing the temporary file's contents to the response body fails, an http_file_operation_exception is thrown") {
|
604
|
+
std::string file_path = (temp_dir_path / "file").string();
|
605
|
+
request req("https://download_trigger_404.com");
|
606
|
+
test_impl->trigger_external_failure = remove_temp_file;
|
607
|
+
response res;
|
608
|
+
REQUIRE_THROWS_AS_WITH(
|
609
|
+
test_client.download_file(req, file_path, res),
|
610
|
+
http_file_operation_exception,
|
611
|
+
Catch::StartsWith("File operation error: failed to write the temporary file's contents to the response body"));
|
612
|
+
}
|
613
|
+
}
|