- allow to specify when they are wanted on starting a resolve - match dns cache entries accordingly. An entry which never tried to get HTTPS-RRs is no answer for a resolve that wants it. - fix late arrivals of resolve answers to match the "async" records that started them - if it still exists. - provide for multiple "async" resolves in a transfer at the same time. We may need to resolve an IP interface while the main connection resolve has not finished yet. - allow lookup of HTTPS-RR information as soon as it is available, even if A/AAAA queries are still ongoing. For this, the "async" infrastructure is changed: - Defined bits for DNS queries `CURL_DNSQ_A`, `CURL_DNSQ_AAAA` and `CURL_DNSQ_HTTPS`. These replace `ip_version` which says nothing about HTTPS. Use them in dns cache entries for matching. - enhance the `async->id` to be a unique `uint32_t` for resolves inside one multi. This is weak, as the id may wrap around. However it is combined with the `mid` of the easy handle, making collisions highly unlikely. `data->state.async` is only accessed in few places where the mid/async-id match is performed. - vtls: for ECH supporting TLS backends (openssl, rustls, wolfssl), retrieve the HTTPS-RR information from the dns connection filter. Delay the connect if the HTTPS-RR is needed, but has not been resolved yet. The implementation of all this is complete for the threaded resolver. c-ares resolver and DoH do not take advantage of all new async features yet. To be done in separate PRs. Details: c-ares: cleanup settings and initialisation. Any ares channel is only being created on starting a resolve and propagating operations in setopt.c to the channel are not helpful. Changed threaded+ares pollset handling so that they do not overwrite each others `ASYNC_NAME` timeouts. Add trace name 'threads' for tracing thread queue and pool used by threaded resolver. Closes #21175 |
||
|---|---|---|
| .. | ||
| .gitignore | ||
| CMakeLists.txt | ||
| Makefile.am | ||
| Makefile.inc | ||
| README.md | ||
| unit1300.c | ||
| unit1302.c | ||
| unit1303.c | ||
| unit1304.c | ||
| unit1305.c | ||
| unit1307.c | ||
| unit1309.c | ||
| unit1323.c | ||
| unit1330.c | ||
| unit1395.c | ||
| unit1396.c | ||
| unit1397.c | ||
| unit1398.c | ||
| unit1399.c | ||
| unit1600.c | ||
| unit1601.c | ||
| unit1602.c | ||
| unit1603.c | ||
| unit1605.c | ||
| unit1606.c | ||
| unit1607.c | ||
| unit1608.c | ||
| unit1609.c | ||
| unit1610.c | ||
| unit1611.c | ||
| unit1612.c | ||
| unit1614.c | ||
| unit1615.c | ||
| unit1616.c | ||
| unit1620.c | ||
| unit1625.c | ||
| unit1626.c | ||
| unit1627.c | ||
| unit1636.c | ||
| unit1650.c | ||
| unit1651.c | ||
| unit1652.c | ||
| unit1653.c | ||
| unit1654.c | ||
| unit1655.c | ||
| unit1656.c | ||
| unit1657.c | ||
| unit1658.c | ||
| unit1660.c | ||
| unit1661.c | ||
| unit1663.c | ||
| unit1664.c | ||
| unit1666.c | ||
| unit1667.c | ||
| unit1668.c | ||
| unit1669.c | ||
| unit1674.c | ||
| unit1979.c | ||
| unit1980.c | ||
| unit2600.c | ||
| unit2601.c | ||
| unit2602.c | ||
| unit2603.c | ||
| unit2604.c | ||
| unit2605.c | ||
| unit3200.c | ||
| unit3205.c | ||
| unit3211.c | ||
| unit3212.c | ||
| unit3213.c | ||
| unit3214.c | ||
| unit3216.c | ||
| unit3219.c | ||
| unit3300.c | ||
| unit3301.c | ||
Unit tests
The goal is to add tests for all functions in libcurl. If functions are too big and complicated, we should split them into smaller and testable ones.
Build Unit Tests
./configure --enable-debug is required for the unit tests to build. To
enable unit tests, there is a separate static libcurl built that is used
exclusively for linking unit test programs. Build everything as normal, and
then you can run the unit test cases as well.
Run Unit Tests
Unit tests are run as part of the regular test suite. If you have built
everything to run unit tests, to can do 'make test' at the root level. Or you
can cd tests and make and then invoke individual unit tests with
./runtests.pl NNNN where NNNN is the specific test number.
Debug Unit Tests
If a specific test fails you get told. The test case then has output left in
the %LOGDIR subdirectory, but most importantly you can re-run the test again
using gdb by doing ./runtests.pl -g NNNN. That is, add a -g to make it
start up gdb and run the same case using that.
Write Unit Tests
We put tests that focus on an area or a specific function into a single C
source file. The source file should be named unitNNNN.c where NNNN is a
previously unused number.
Add your test to tests/unit/Makefile.inc (if it is a unit test). Add your
test data filename to tests/data/Makefile.am
You also need a separate file called tests/data/testNNNN (using the same
number) that describes your test case. See the test1300 file for inspiration
and the tests/FILEFORMAT.md documentation.
For the actual C file, here's a simple example:
#include "unitcheck.h"
#include "a libcurl header.h" /* from the lib directory */
static CURLcode test_unit9998(const char *arg)
{
UNITTEST_BEGIN_SIMPLE
/* here you start doing things and checking that the results are good */
fail_unless( size == 0 , "initial size should be zero" );
fail_if( head == NULL , "head should not be initiated to NULL" );
/* you end the test code like this: */
UNITTEST_END_SIMPLE
}
Here's an example using optional initialization and cleanup:
#include "unitcheck.h"
#include "a libcurl header.h" /* from the lib directory */
static CURLcode t9999_setup(void)
{
/* whatever you want done first */
return CURLE_OK;
}
static void t9999_stop(void)
{
/* done before shutting down and exiting */
}
static CURLcode test_unit9999(const char *arg)
{
UNITTEST_BEGIN(t9999_setup())
/* here you start doing things and checking that the results are good */
fail_unless( size == 0 , "initial size should be zero" );
fail_if( head == NULL , "head should not be initiated to NULL" );
/* you end the test code like this: */
UNITTEST_END(t9999_stop())
}
Testing static functions
Lots of internal functions are made static, and they should be static if they are private within a single source file.
The curl build system provides a way to write unit tests that let us properly test these functions while keeping them static in release builds.
A function that is static in the build but should be provided for unit testing
needs to replace its static keyword with UNITTEST and it needs to have a
prototype provided immediately above it.
An example add_two_integers() function for unit testing:
UNITTEST int add_two_integers(int a, int b);
UNITTEST int add_two_integers(int a, int b)
{
return a + b;
}
Since the function is static and is private for this source file, it should not have its prototype in any header file.
When building unit tests, the build system automatically generates the
lib/unitprotos.h header file with all the prototypes for UNITTEST
functions provided in any libcurl C source code files. (This is done by the
scripts/extract-unit-protos script.)