facter 3.9.6.cfacter.20180612 → 3.11.0.cfacter.20180319
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
}
|