From 099d144b16b05508bb08b880b4123eb4a6af3a04 Mon Sep 17 00:00:00 2001 From: Petros Kanellopoulos Date: Sun, 29 Jan 2023 16:13:14 +0100 Subject: [PATCH 1/7] Contribution docs: Project structure, Building and Testing A new part of the docs has been added, contribution.md, which aims to ease the way towards contributing to cpr by offering an introduction to the project. A basic intro and guide for making test/debug builds has been added. --- _layouts/default.html | 5 +++++ contribution.md | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 contribution.md diff --git a/_layouts/default.html b/_layouts/default.html index 3405297..0cc0128 100644 --- a/_layouts/default.html +++ b/_layouts/default.html @@ -52,6 +52,11 @@

User Guide

+

For Contributors

+

This project is maintained by Fabian Sauter and Tim Stack

diff --git a/contribution.md b/contribution.md new file mode 100644 index 0000000..673daad --- /dev/null +++ b/contribution.md @@ -0,0 +1,40 @@ +--- +layout: default +title: cpr - For Developers +--- + +## Overview and Filesystem Structure +Here we aim to cover some topics that will make getting into CPR development and debugging easier. This is not intended to be a thorough documentation of each function, class and template within the project. Rather, it aims to ease the process of contributing to CPR by covering some relevant topics. + +In this document, we will be referencing files by their filename, relative to the appropriate root folder. Here are some particularly relevant ones, relative to project root: + +* header files have the suffix `.h` and are located in `include/cpr`. +* source files have the suffix `.cpp` and are located in `cpr`. +* most files related to testing are located in `test`. + +## Building, Testing and Debugging +For a project that relies on template metaprogramming, such as CPR, compiling tests ensures that templates are instantiated during compilation. Testing and debugging features are enabled through setting certain cmake variables, which can be found in full in `CMakeLists.txt`. We'd like to single out `CPR_BUILD_TESTS` and `CPR_DEBUG_SANITIZER_FLAG_ALL`, which enable the building of tests and the usage of a number of sanitizers. A debug build could be achieved as follows: + +{% raw %} +```bash +# Make a build directory inside project root +$ mkdir build && cd build + +# Make a Debug build with tests and sanitizers enabled +$ cmake -DCPR_BUILD_TESTS=1 -DCPR_DEBUG_SANITIZER_FLAG_ALL=1 -DCMAKE_BUILD_TYPE=Debug .. + +# Build the project. The '-- -j7' part enables parallelization of build tasks. +# You may use a different number depending on your hardware, or omit this bit. +$ cmake --build . -- -j7 + +# Run all tests +$ cmake --build . --target test + +# Run a specific test set +$ ./bin/session_tests + +# See more options to run test suites, such as isolating specific tests +$ ./bin/session_tests --help +``` +{% endraw %} + From f7bb373bd742c057b0a92540eb1837640ddaf918 Mon Sep 17 00:00:00 2001 From: Petros Kanellopoulos Date: Sat, 4 Feb 2023 17:59:26 +0100 Subject: [PATCH 2/7] Expansion of the build and debug instructions, project structure --- contribution.md | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/contribution.md b/contribution.md index 673daad..0d4e9f1 100644 --- a/contribution.md +++ b/contribution.md @@ -34,7 +34,24 @@ $ cmake --build . --target test $ ./bin/session_tests # See more options to run test suites, such as isolating specific tests -$ ./bin/session_tests --help +$ ./bin/download_tests --help + +# Debug a test set +$ gdb ./bin/multiperform_tests + +# See all targets for different Makefiles +$ make help +$ cd test && make help ``` {% endraw %} +## Project Structure +Here we will briefly describe different functional parts of CPR, and mention the headers that are most relevant to them. As any software project's, of course, CPR's parts are interconnected, and most classes play a part in most operations. Here, we will constrain ourselves to the most crucial ones. Where relevant headers are suggested, it's recommended to also look at the appropriate source file, if it exists. +### The API Interface +Relevant Headers: `api.h`, `cpr.h` + +Here we have the templates that are instantiated to create the cpr API methods. The namespace `priv` contains the intternal functions, particularly relevant for the `Multi`-methods. +### The Session class +Relevant Headers: `session.h` + +This class implements most of the logic used by `cpr`. Here, the `curl` `easy-` or `multi-` sessions are constructed, executed, the result packed in a `Response` instance and returned. It is _Moveable_, not _Copyable_, and can have shared ownership. Usage of the `Session` class usually entails construction, the setting of various parameters, either through the `Session::SetParam` methods like, for example, `Session::SetUrl`, or the equivalent polymorphic `Session::SetOption` method, and finally calling the appropriate method, like `Session::Get`. The set-up for the `curl` session happens, to a large degree, inside the `Session::PrepareAction` methods (where `Action` is the corresponding HTTP action). From ca32ca3c85634b64b0e83969bb2b3d0fb1cded46 Mon Sep 17 00:00:00 2001 From: Petros Kanellopoulos Date: Wed, 8 Feb 2023 15:42:07 +0100 Subject: [PATCH 3/7] A skeleton of the file has been completed A first version for various subchapter has also been added. --- contribution.md | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/contribution.md b/contribution.md index 0d4e9f1..a5ac9d2 100644 --- a/contribution.md +++ b/contribution.md @@ -8,12 +8,12 @@ Here we aim to cover some topics that will make getting into CPR development and In this document, we will be referencing files by their filename, relative to the appropriate root folder. Here are some particularly relevant ones, relative to project root: -* header files have the suffix `.h` and are located in `include/cpr`. -* source files have the suffix `.cpp` and are located in `cpr`. -* most files related to testing are located in `test`. +* header files have the suffix `.h` and are located in [`include/cpr`](https://github.com/libcpr/cpr/tree/master/include/cpr). +* source files have the suffix `.cpp` and are located in [`cpr`](https://github.com/libcpr/cpr/tree/master/cpr). +* most files related to testing are located in [`test`](https://github.com/libcpr/cpr/tree/master/test). ## Building, Testing and Debugging -For a project that relies on template metaprogramming, such as CPR, compiling tests ensures that templates are instantiated during compilation. Testing and debugging features are enabled through setting certain cmake variables, which can be found in full in `CMakeLists.txt`. We'd like to single out `CPR_BUILD_TESTS` and `CPR_DEBUG_SANITIZER_FLAG_ALL`, which enable the building of tests and the usage of a number of sanitizers. A debug build could be achieved as follows: +For a project that relies on template metaprogramming, such as CPR, compiling tests ensures that templates are instantiated during compilation. Testing and debugging features are enabled through setting certain cmake variables, which can be found in full in [`CMakeLists.txt`](https://github.com/libcpr/cpr/blob/master/CMakeLists.txt). We'd like to single out `CPR_BUILD_TESTS` and `CPR_DEBUG_SANITIZER_FLAG_ALL`, which enable the building of tests and the usage of a number of sanitizers. A debug build could be achieved as follows: {% raw %} ```bash @@ -48,10 +48,29 @@ $ cd test && make help ## Project Structure Here we will briefly describe different functional parts of CPR, and mention the headers that are most relevant to them. As any software project's, of course, CPR's parts are interconnected, and most classes play a part in most operations. Here, we will constrain ourselves to the most crucial ones. Where relevant headers are suggested, it's recommended to also look at the appropriate source file, if it exists. ### The API Interface -Relevant Headers: `api.h`, `cpr.h` +Relevant Headers: [`api.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/api.h), [`cpr.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/cpr.h) -Here we have the templates that are instantiated to create the cpr API methods. The namespace `priv` contains the intternal functions, particularly relevant for the `Multi`-methods. +Here we have the templates that are instantiated to create the cpr API methods. The namespace `priv` contains internal functions, particularly relevant for the `Multi`-methods. ### The Session class -Relevant Headers: `session.h` +Relevant Headers: [`session.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/session.h) This class implements most of the logic used by `cpr`. Here, the `curl` `easy-` or `multi-` sessions are constructed, executed, the result packed in a `Response` instance and returned. It is _Moveable_, not _Copyable_, and can have shared ownership. Usage of the `Session` class usually entails construction, the setting of various parameters, either through the `Session::SetParam` methods like, for example, `Session::SetUrl`, or the equivalent polymorphic `Session::SetOption` method, and finally calling the appropriate method, like `Session::Get`. The set-up for the `curl` session happens, to a large degree, inside the `Session::PrepareAction` methods (where `Action` is the corresponding HTTP action). + +### Response Wrappers +Relevant Headers: [`response.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/response.h), [`async_wrapper.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/async_wrapper.h) + +Responses from API/Session actions come packaged in these classes. `Response` is the main container for a response, while `cpr::AsyncWrapper` is a container for a (cancellable or non-cancellable) asynchronous response with an interface compatible with [`std::future`](https://en.cppreference.com/w/cpp/thread/future). + +### Parameter Containers +Relevant Headers: [`auth.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/auth.h), [`bearer.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/bearer.h), [`body.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/body.h), [`buffer.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/buffer.h), [`callback.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/callback.h), [`cert_info.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/cert_info.h), [`connect_timeout.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/connect_timeout.h), [`cookies.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/cookies.h), [`cprtypes.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/cprtypes.h), [`file.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/file.h), [`interface.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/interface.h), [`limit_rate.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/limit_rate.h), [`local_port.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/local_port.h), ... + +These classes are aimed to be used in order to supply arguments to `CPR` requests in an object-oriented way. To see how they are handled, it usually is a good idea to look at the implementation of the polymorphic `Session::SetOption` method. + +### Placeholder +Relevant Headers: `ph.h` + +Text goes here. + +## Testing and Writing Tests + +Test suites for CPR use the [gtest](https://google.github.io/googletest/) framework, and CPR's own [HttpServer](https://github.com/libcpr/cpr/blob/master/test/httpServer.hpp) in order to test behaviours. To see the various URIs that can be used to test different aspects of CPR's functionality, in may be useful to look at the implementation of [`HttpServer::OnRequest`](https://github.com/libcpr/cpr/blob/master/test/httpServer.cpp), and then at the different `HttpServer::OnRequest` methods for a more detailed look at each URI's implementation. From 60e9c7027a4d8e63dac2e12653da4564698410a2 Mon Sep 17 00:00:00 2001 From: Petros Kanellopoulos Date: Mon, 3 Apr 2023 17:25:34 +0200 Subject: [PATCH 4/7] Project Structure and introduction to writing tests --- contribution.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/contribution.md b/contribution.md index a5ac9d2..07f98c0 100644 --- a/contribution.md +++ b/contribution.md @@ -57,19 +57,20 @@ Relevant Headers: [`session.h`](https://github.com/libcpr/cpr/blob/master/includ This class implements most of the logic used by `cpr`. Here, the `curl` `easy-` or `multi-` sessions are constructed, executed, the result packed in a `Response` instance and returned. It is _Moveable_, not _Copyable_, and can have shared ownership. Usage of the `Session` class usually entails construction, the setting of various parameters, either through the `Session::SetParam` methods like, for example, `Session::SetUrl`, or the equivalent polymorphic `Session::SetOption` method, and finally calling the appropriate method, like `Session::Get`. The set-up for the `curl` session happens, to a large degree, inside the `Session::PrepareAction` methods (where `Action` is the corresponding HTTP action). ### Response Wrappers -Relevant Headers: [`response.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/response.h), [`async_wrapper.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/async_wrapper.h) +Relevant Headers: [`response.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/response.h), [`async_wrapper.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/async_wrapper.h), [`error.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/error.h) -Responses from API/Session actions come packaged in these classes. `Response` is the main container for a response, while `cpr::AsyncWrapper` is a container for a (cancellable or non-cancellable) asynchronous response with an interface compatible with [`std::future`](https://en.cppreference.com/w/cpp/thread/future). +Responses from API/Session actions come packaged in these classes. `Response` is the main container for a response, while `cpr::AsyncWrapper` is a container for a (cancellable or non-cancellable) asynchronous response with an interface compatible with [`std::future`](https://en.cppreference.com/w/cpp/thread/future). The class `Error` works as an object-oriented container to describe errors that occur during transfer. ### Parameter Containers -Relevant Headers: [`auth.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/auth.h), [`bearer.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/bearer.h), [`body.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/body.h), [`buffer.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/buffer.h), [`callback.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/callback.h), [`cert_info.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/cert_info.h), [`connect_timeout.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/connect_timeout.h), [`cookies.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/cookies.h), [`cprtypes.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/cprtypes.h), [`file.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/file.h), [`interface.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/interface.h), [`limit_rate.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/limit_rate.h), [`local_port.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/local_port.h), ... +Relevant Headers: [`accept_encoding.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/accept_encoding.h), [`auth.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/auth.h), [`bearer.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/bearer.h), [`body.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/body.h), [`buffer.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/buffer.h), [`callback.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/callback.h), [`cert_info.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/cert_info.h), [`connect_timeout.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/connect_timeout.h), [`cookies.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/cookies.h), [`cprtypes.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/cprtypes.h), [`file.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/file.h), [`http_version.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/http_version.h), [`interface.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/interface.h), [`limit_rate.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/limit_rate.h), [`local_port.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/local_port.h), [`local_port_range.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/local_port_range.h), [`parameters.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/parameters.h), [`low_speed.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/low_speed.h), [`payload.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/payload.h), [`proxies.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/proxies.h), [`proxyauth.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/proxyauth.h), [`range.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/range.h), [`redirect.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/redirect.h), [`reserve_size.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/reserve_size.h), [`resolve.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/resolve.h), [`ssl_options.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/ssl_options.h) -These classes are aimed to be used in order to supply arguments to `CPR` requests in an object-oriented way. To see how they are handled, it usually is a good idea to look at the implementation of the polymorphic `Session::SetOption` method. +These containers are intended to be provided to API functions in order to generate template instantiations that execute the specific request(s). They contain limited logic, and much of their functionality is contingent on their constructors. They are aimed to be used in order to supply arguments to `CPR` requests in an object-oriented way. To see how they are handled, it usually is a good idea to look at the implementation of the polymorphic `Session::SetOption` method. -### Placeholder -Relevant Headers: `ph.h` +### Infrastructure for Asynchronous Requests +Relevant Headers: [`async.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/async.h), [`singleton.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/singleton.h), [`threadpool.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/threadpool.h) -Text goes here. +These are headers used by the Asynchronous and Multiple Asynchronous requests API features. These are used to instantiate a [`std::packaged_task`](https://en.cppreference.com/w/cpp/thread/packaged_task), which is emplaced on a queue (see `Threadpool::tasks`), and the `std::future` associated with the task is returned by the API function to the caller wrapped in a `cpr::AsyncWrapper`. +Elements of the `tasks` queue are popped by the worker threads of the `cpr::GlobalThreadpool` (see `async.h`), and processed by instantiating a `cpr::Session` and resolving the request within the thread. Once the return value of the request has been generated (usually a `cpr::Response`), it can be gotten through `AsyncWrapper::get`. ## Testing and Writing Tests From 635be2092b143d656e6a35cdbe0ab6e5704dda25 Mon Sep 17 00:00:00 2001 From: RuleOfThrees <109949523+RuleOfThrees@users.noreply.github.com> Date: Wed, 5 Apr 2023 14:17:27 +0200 Subject: [PATCH 5/7] Code review improvements on contribution.md Co-authored-by: Fabian Sauter --- contribution.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contribution.md b/contribution.md index 07f98c0..b641708 100644 --- a/contribution.md +++ b/contribution.md @@ -8,9 +8,9 @@ Here we aim to cover some topics that will make getting into CPR development and In this document, we will be referencing files by their filename, relative to the appropriate root folder. Here are some particularly relevant ones, relative to project root: -* header files have the suffix `.h` and are located in [`include/cpr`](https://github.com/libcpr/cpr/tree/master/include/cpr). -* source files have the suffix `.cpp` and are located in [`cpr`](https://github.com/libcpr/cpr/tree/master/cpr). -* most files related to testing are located in [`test`](https://github.com/libcpr/cpr/tree/master/test). +* Header files have the suffix `.h` and are located in [`include/cpr`](https://github.com/libcpr/cpr/tree/master/include/cpr). +* Source files have the suffix `.cpp` and are located in [`cpr`](https://github.com/libcpr/cpr/tree/master/cpr). +* Most files related to testing are located in [`test`](https://github.com/libcpr/cpr/tree/master/test). ## Building, Testing and Debugging For a project that relies on template metaprogramming, such as CPR, compiling tests ensures that templates are instantiated during compilation. Testing and debugging features are enabled through setting certain cmake variables, which can be found in full in [`CMakeLists.txt`](https://github.com/libcpr/cpr/blob/master/CMakeLists.txt). We'd like to single out `CPR_BUILD_TESTS` and `CPR_DEBUG_SANITIZER_FLAG_ALL`, which enable the building of tests and the usage of a number of sanitizers. A debug build could be achieved as follows: From fba8a645157433b2795f71f9b4d6ee8d1619d092 Mon Sep 17 00:00:00 2001 From: RuleOfThrees <109949523+RuleOfThrees@users.noreply.github.com> Date: Wed, 5 Apr 2023 14:21:36 +0200 Subject: [PATCH 6/7] Apply suggestions from code review Co-authored-by: Fabian Sauter --- contribution.md | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/contribution.md b/contribution.md index b641708..2d1cca2 100644 --- a/contribution.md +++ b/contribution.md @@ -13,7 +13,11 @@ In this document, we will be referencing files by their filename, relative to th * Most files related to testing are located in [`test`](https://github.com/libcpr/cpr/tree/master/test). ## Building, Testing and Debugging -For a project that relies on template metaprogramming, such as CPR, compiling tests ensures that templates are instantiated during compilation. Testing and debugging features are enabled through setting certain cmake variables, which can be found in full in [`CMakeLists.txt`](https://github.com/libcpr/cpr/blob/master/CMakeLists.txt). We'd like to single out `CPR_BUILD_TESTS` and `CPR_DEBUG_SANITIZER_FLAG_ALL`, which enable the building of tests and the usage of a number of sanitizers. A debug build could be achieved as follows: +For a project that relies on template meta programming, such as CPR, compiling tests ensures that templates are instantiated during compilation. +Test and debug options are controlled via a set of CMake variables. +They are located inside the root [`CMakeLists.txt`](https://github.com/libcpr/cpr/blob/master/CMakeLists.txt) file. +Take a look at the option definitions starting with `cpr_option(...)`. +We'd like to single out `CPR_BUILD_TESTS` and `CPR_DEBUG_SANITIZER_FLAG_ALL`, which enable building tests and the usage of a number of sanitizers. A debug build could be achieved as follows: {% raw %} ```bash @@ -21,14 +25,15 @@ For a project that relies on template metaprogramming, such as CPR, compiling te $ mkdir build && cd build # Make a Debug build with tests and sanitizers enabled -$ cmake -DCPR_BUILD_TESTS=1 -DCPR_DEBUG_SANITIZER_FLAG_ALL=1 -DCMAKE_BUILD_TYPE=Debug .. +$ cmake -DCPR_BUILD_TESTS=ON -DCPR_DEBUG_SANITIZER_FLAG_ALL=ON -DCMAKE_BUILD_TYPE=Debug .. -# Build the project. The '-- -j7' part enables parallelization of build tasks. +# Build the project. The '--parallel' part enables parallel build tasks. Without specifying any number behind `--parallel`, you allow CMake to pick the appropriate number of parallel build tasks. +# To set a specific number (n) of parallel build tasks: '--paralle n' # You may use a different number depending on your hardware, or omit this bit. -$ cmake --build . -- -j7 +$ cmake --build . --parallel # Run all tests -$ cmake --build . --target test +$ cmake --build . --target test --parallel # Run a specific test set $ ./bin/session_tests @@ -46,7 +51,9 @@ $ cd test && make help {% endraw %} ## Project Structure -Here we will briefly describe different functional parts of CPR, and mention the headers that are most relevant to them. As any software project's, of course, CPR's parts are interconnected, and most classes play a part in most operations. Here, we will constrain ourselves to the most crucial ones. Where relevant headers are suggested, it's recommended to also look at the appropriate source file, if it exists. +Here we briefly describe different functional parts of CPR, and mention the headers that are most relevant to them. As any software project's, of course, CPR's parts are interconnected, and most classes play a part in most operations. +We will constrain ourselves to the most crucial ones. +Where relevant headers are suggested, it's recommended to also look at the appropriate source file, if it exists. ### The API Interface Relevant Headers: [`api.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/api.h), [`cpr.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/cpr.h) @@ -69,9 +76,8 @@ These containers are intended to be provided to API functions in order to genera ### Infrastructure for Asynchronous Requests Relevant Headers: [`async.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/async.h), [`singleton.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/singleton.h), [`threadpool.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/threadpool.h) -These are headers used by the Asynchronous and Multiple Asynchronous requests API features. These are used to instantiate a [`std::packaged_task`](https://en.cppreference.com/w/cpp/thread/packaged_task), which is emplaced on a queue (see `Threadpool::tasks`), and the `std::future` associated with the task is returned by the API function to the caller wrapped in a `cpr::AsyncWrapper`. -Elements of the `tasks` queue are popped by the worker threads of the `cpr::GlobalThreadpool` (see `async.h`), and processed by instantiating a `cpr::Session` and resolving the request within the thread. Once the return value of the request has been generated (usually a `cpr::Response`), it can be gotten through `AsyncWrapper::get`. +These headers are used by the Asynchronous and Multiple Asynchronous requests API features. They are used to instantiate a [`std::packaged_task`](https://en.cppreference.com/w/cpp/thread/packaged_task), which is emplaced on a queue (see `Threadpool::tasks`), and the `std::future` associated with the task is returned by the API function to the caller wrapped in a `cpr::AsyncWrapper`. +Elements of the `tasks` queue are popped by worker threads of `cpr::GlobalThreadpool` (see `async.h`), and processed by instantiating a `cpr::Session` and resolving the request within the thread. Once the return value of the request has been generated (usually a `cpr::Response`), it can be gotten through `AsyncWrapper::get`. ## Testing and Writing Tests - Test suites for CPR use the [gtest](https://google.github.io/googletest/) framework, and CPR's own [HttpServer](https://github.com/libcpr/cpr/blob/master/test/httpServer.hpp) in order to test behaviours. To see the various URIs that can be used to test different aspects of CPR's functionality, in may be useful to look at the implementation of [`HttpServer::OnRequest`](https://github.com/libcpr/cpr/blob/master/test/httpServer.cpp), and then at the different `HttpServer::OnRequest` methods for a more detailed look at each URI's implementation. From 460a2b1f5db8e28d02f53aa0c71519b394aa232d Mon Sep 17 00:00:00 2001 From: Petros Kanellopoulos Date: Thu, 6 Apr 2023 14:53:58 +0200 Subject: [PATCH 7/7] Corrections as result of code review * ctest suggested for running tests, and the executables maintained only for gdb debugging. * Newlines added to improve readability * references to the library now use the lower-case cpr term Co-authored-by: Fabian Sauter --- contribution.md | 72 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 56 insertions(+), 16 deletions(-) diff --git a/contribution.md b/contribution.md index 2d1cca2..f353b65 100644 --- a/contribution.md +++ b/contribution.md @@ -4,7 +4,7 @@ title: cpr - For Developers --- ## Overview and Filesystem Structure -Here we aim to cover some topics that will make getting into CPR development and debugging easier. This is not intended to be a thorough documentation of each function, class and template within the project. Rather, it aims to ease the process of contributing to CPR by covering some relevant topics. +Here we aim to cover some topics that will make getting into cpr development and debugging easier. This is not intended to be a thorough documentation of each function, class and template within the project. Rather, it aims to ease the process of contributing to cpr by covering some relevant topics. In this document, we will be referencing files by their filename, relative to the appropriate root folder. Here are some particularly relevant ones, relative to project root: @@ -28,15 +28,15 @@ $ mkdir build && cd build $ cmake -DCPR_BUILD_TESTS=ON -DCPR_DEBUG_SANITIZER_FLAG_ALL=ON -DCMAKE_BUILD_TYPE=Debug .. # Build the project. The '--parallel' part enables parallel build tasks. Without specifying any number behind `--parallel`, you allow CMake to pick the appropriate number of parallel build tasks. -# To set a specific number (n) of parallel build tasks: '--paralle n' +# To set a specific number (n) of parallel build tasks: '--parallel n' # You may use a different number depending on your hardware, or omit this bit. $ cmake --build . --parallel # Run all tests -$ cmake --build . --target test --parallel +$ ctest -# Run a specific test set -$ ./bin/session_tests +# Run a specific test set via regular expression +$ ctest -R "cpr_(session|post)_tests" # See more options to run test suites, such as isolating specific tests $ ./bin/download_tests --help @@ -51,33 +51,73 @@ $ cd test && make help {% endraw %} ## Project Structure -Here we briefly describe different functional parts of CPR, and mention the headers that are most relevant to them. As any software project's, of course, CPR's parts are interconnected, and most classes play a part in most operations. +Here we briefly describe different functional parts of cpr, and mention the headers that are most relevant to them. As any software project's, of course, cpr's parts are interconnected, and most classes play a part in most operations. We will constrain ourselves to the most crucial ones. Where relevant headers are suggested, it's recommended to also look at the appropriate source file, if it exists. ### The API Interface -Relevant Headers: [`api.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/api.h), [`cpr.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/cpr.h) +Relevant Headers: +[`api.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/api.h), +[`cpr.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/cpr.h) Here we have the templates that are instantiated to create the cpr API methods. The namespace `priv` contains internal functions, particularly relevant for the `Multi`-methods. + ### The Session class -Relevant Headers: [`session.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/session.h) +Relevant Headers: +[`session.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/session.h) -This class implements most of the logic used by `cpr`. Here, the `curl` `easy-` or `multi-` sessions are constructed, executed, the result packed in a `Response` instance and returned. It is _Moveable_, not _Copyable_, and can have shared ownership. Usage of the `Session` class usually entails construction, the setting of various parameters, either through the `Session::SetParam` methods like, for example, `Session::SetUrl`, or the equivalent polymorphic `Session::SetOption` method, and finally calling the appropriate method, like `Session::Get`. The set-up for the `curl` session happens, to a large degree, inside the `Session::PrepareAction` methods (where `Action` is the corresponding HTTP action). +This class implements most of the logic used by cpr. Here, the `curl` `easy-` or `multi-` sessions are constructed, executed, the result packed in a `Response` instance and returned. It is _Moveable_, not _Copyable_, and can have shared ownership. +Usage of the `Session` class usually entails construction and the setting of various parameters, either through the `Session::SetParam` methods like, for example, `Session::SetUrl`, or the equivalent polymorphic `Session::SetOption` method, and finally calling the appropriate method, like `Session::Get`. +The set-up for the `curl` session happens, to a large degree, inside the `Session::PrepareAction` methods (where `Action` is the corresponding HTTP action). ### Response Wrappers -Relevant Headers: [`response.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/response.h), [`async_wrapper.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/async_wrapper.h), [`error.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/error.h) +Relevant Headers: +[`async_wrapper.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/async_wrapper.h), +[`error.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/error.h) +[`response.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/response.h), -Responses from API/Session actions come packaged in these classes. `Response` is the main container for a response, while `cpr::AsyncWrapper` is a container for a (cancellable or non-cancellable) asynchronous response with an interface compatible with [`std::future`](https://en.cppreference.com/w/cpp/thread/future). The class `Error` works as an object-oriented container to describe errors that occur during transfer. +Responses from API/Session actions come packaged in these classes. `Response` is the main container for a response, while `cpr::AsyncWrapper` is a container for a (cancellable or non-cancellable) asynchronous response with an interface compatible with [`std::future`](https://en.cppreference.com/w/cpp/thread/future). +The class `Error` works as an object-oriented container to describe errors that occur during transfer. ### Parameter Containers -Relevant Headers: [`accept_encoding.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/accept_encoding.h), [`auth.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/auth.h), [`bearer.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/bearer.h), [`body.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/body.h), [`buffer.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/buffer.h), [`callback.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/callback.h), [`cert_info.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/cert_info.h), [`connect_timeout.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/connect_timeout.h), [`cookies.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/cookies.h), [`cprtypes.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/cprtypes.h), [`file.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/file.h), [`http_version.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/http_version.h), [`interface.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/interface.h), [`limit_rate.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/limit_rate.h), [`local_port.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/local_port.h), [`local_port_range.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/local_port_range.h), [`parameters.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/parameters.h), [`low_speed.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/low_speed.h), [`payload.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/payload.h), [`proxies.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/proxies.h), [`proxyauth.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/proxyauth.h), [`range.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/range.h), [`redirect.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/redirect.h), [`reserve_size.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/reserve_size.h), [`resolve.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/resolve.h), [`ssl_options.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/ssl_options.h) - -These containers are intended to be provided to API functions in order to generate template instantiations that execute the specific request(s). They contain limited logic, and much of their functionality is contingent on their constructors. They are aimed to be used in order to supply arguments to `CPR` requests in an object-oriented way. To see how they are handled, it usually is a good idea to look at the implementation of the polymorphic `Session::SetOption` method. +Relevant Headers: +[`accept_encoding.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/accept_encoding.h), +[`auth.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/auth.h), +[`bearer.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/bearer.h), +[`body.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/body.h), +[`buffer.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/buffer.h), +[`callback.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/callback.h), +[`cert_info.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/cert_info.h), +[`connect_timeout.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/connect_timeout.h), +[`cookies.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/cookies.h), +[`cprtypes.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/cprtypes.h), +[`file.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/file.h), +[`http_version.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/http_version.h), +[`interface.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/interface.h), +[`limit_rate.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/limit_rate.h), +[`local_port.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/local_port.h), +[`local_port_range.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/local_port_range.h), +[`low_speed.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/low_speed.h), +[`parameters.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/parameters.h), +[`payload.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/payload.h), +[`proxies.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/proxies.h), +[`proxyauth.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/proxyauth.h), +[`range.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/range.h), +[`redirect.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/redirect.h), +[`reserve_size.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/reserve_size.h), +[`resolve.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/resolve.h), +[`ssl_options.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/ssl_options.h) + +These containers are intended to be provided to API functions in order to generate template instantiations that execute the specific request(s). They contain limited logic, and much of their functionality is contingent on their constructors. They are aimed to be used in order to supply arguments to cpr requests in an object-oriented way. To see how they are handled, it usually is a good idea to look at the implementation of the polymorphic `Session::SetOption` method. ### Infrastructure for Asynchronous Requests -Relevant Headers: [`async.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/async.h), [`singleton.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/singleton.h), [`threadpool.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/threadpool.h) +Relevant Headers: +[`async.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/async.h), +[`async_wrapper.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/async_wrapper.h), +[`singleton.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/singleton.h), +[`threadpool.h`](https://github.com/libcpr/cpr/blob/master/include/cpr/threadpool.h) These headers are used by the Asynchronous and Multiple Asynchronous requests API features. They are used to instantiate a [`std::packaged_task`](https://en.cppreference.com/w/cpp/thread/packaged_task), which is emplaced on a queue (see `Threadpool::tasks`), and the `std::future` associated with the task is returned by the API function to the caller wrapped in a `cpr::AsyncWrapper`. Elements of the `tasks` queue are popped by worker threads of `cpr::GlobalThreadpool` (see `async.h`), and processed by instantiating a `cpr::Session` and resolving the request within the thread. Once the return value of the request has been generated (usually a `cpr::Response`), it can be gotten through `AsyncWrapper::get`. ## Testing and Writing Tests -Test suites for CPR use the [gtest](https://google.github.io/googletest/) framework, and CPR's own [HttpServer](https://github.com/libcpr/cpr/blob/master/test/httpServer.hpp) in order to test behaviours. To see the various URIs that can be used to test different aspects of CPR's functionality, in may be useful to look at the implementation of [`HttpServer::OnRequest`](https://github.com/libcpr/cpr/blob/master/test/httpServer.cpp), and then at the different `HttpServer::OnRequest` methods for a more detailed look at each URI's implementation. +Test suites for cpr use the [gtest](https://google.github.io/googletest/) framework, and cpr's own [HttpServer](https://github.com/libcpr/cpr/blob/master/test/httpServer.hpp) in order to test behaviours. To see the various URIs that can be used to test different aspects of cpr's functionality, in may be useful to look at the implementation of [`HttpServer::OnRequest`](https://github.com/libcpr/cpr/blob/master/test/httpServer.cpp), and then at the different `HttpServer::OnRequest` methods for a more detailed look at each URI's implementation.