mirror of
https://github.com/curl/curl.git
synced 2026-06-13 19:45:39 +03:00
Whack the times reported for a transfer (see https://curl.se/libcurl/c/curl_easy_getinfo.html#TIMES) into order for all variations of up-/download, http/ftp etc. Make sure they are reported in the documented order. There is still the *possibility* of PRETRANSFER being longer then POSTTRANSFER, if a server sends a response before an upload is done. POST is the time the first response byte is received, and PRE is the time the last byte was sent by curl. This may happen with more likelihood on HTTP/2 and 3 for a server rejected upload. But for successful uploads, the answer will almost over come afterwards. Undo the previous twists in lib500.c tests, adjust pytest timeline checks. Fixes #21828 Reported-by: BazaarAcc32 on github Closes #21843
135 lines
4.6 KiB
C
135 lines
4.6 KiB
C
/***************************************************************************
|
|
* _ _ ____ _
|
|
* Project ___| | | | _ \| |
|
|
* / __| | | | |_) | |
|
|
* | (__| |_| | _ <| |___
|
|
* \___|\___/|_| \_\_____|
|
|
*
|
|
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
|
|
*
|
|
* This software is licensed as described in the file COPYING, which
|
|
* you should have received as part of this distribution. The terms
|
|
* are also available at https://curl.se/docs/copyright.html.
|
|
*
|
|
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
|
* copies of the Software, and permit persons to whom the Software is
|
|
* furnished to do so, under the terms of the COPYING file.
|
|
*
|
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
|
* KIND, either express or implied.
|
|
*
|
|
* SPDX-License-Identifier: curl
|
|
*
|
|
***************************************************************************/
|
|
#include "unitcheck.h"
|
|
#include "urldata.h"
|
|
#include "progress.h"
|
|
|
|
static CURLcode t1399_setup(struct Curl_easy **easy)
|
|
{
|
|
CURLcode result = CURLE_OK;
|
|
|
|
global_init(CURL_GLOBAL_ALL);
|
|
*easy = curl_easy_init();
|
|
if(!*easy) {
|
|
curl_global_cleanup();
|
|
return CURLE_OUT_OF_MEMORY;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
static void t1399_stop(struct Curl_easy *easy)
|
|
{
|
|
curl_easy_cleanup(easy);
|
|
curl_global_cleanup();
|
|
}
|
|
|
|
/*
|
|
* Invoke Curl_pgrsTime for TIMER_STARTSINGLE to trigger the behavior that
|
|
* manages is_t_startransfer_set, but fake the t_startsingle time for purposes
|
|
* of the test.
|
|
*/
|
|
static void fake_t_startsingle_time(struct Curl_easy *data,
|
|
struct curltime fake_now,
|
|
int seconds_offset)
|
|
{
|
|
Curl_pgrsTime(data, TIMER_STARTSINGLE);
|
|
data->progress.t_startsingle.tv_sec = fake_now.tv_sec + seconds_offset;
|
|
data->progress.t_startsingle.tv_usec = fake_now.tv_usec;
|
|
}
|
|
|
|
static bool usec_matches_seconds(timediff_t time_usec, int expected_seconds)
|
|
{
|
|
static int usec_magnitude = 1000000;
|
|
|
|
int time_sec = (int)(time_usec / usec_magnitude);
|
|
bool same = (time_sec == expected_seconds);
|
|
curl_mfprintf(stderr, "is %d us same as %d seconds? %s\n",
|
|
(int)time_usec, expected_seconds,
|
|
same ? "Yes" : "No");
|
|
return same;
|
|
}
|
|
|
|
static void expect_timer_seconds(struct Curl_easy *data, int seconds)
|
|
{
|
|
char msg[64];
|
|
curl_msnprintf(msg, sizeof(msg), "about %d seconds should have passed",
|
|
seconds);
|
|
fail_unless(usec_matches_seconds(data->progress.t_nslookup, seconds), msg);
|
|
fail_unless(usec_matches_seconds(data->progress.t_connect, seconds), msg);
|
|
fail_unless(usec_matches_seconds(data->progress.t_appconnect, seconds), msg);
|
|
fail_unless(usec_matches_seconds(data->progress.t_pretransfer, seconds),
|
|
msg);
|
|
fail_unless(usec_matches_seconds(data->progress.t_starttransfer, seconds),
|
|
msg);
|
|
}
|
|
|
|
/* Scenario: simulate a redirect. When a redirect occurs, t_nslookup,
|
|
* t_connect, t_appconnect, t_pretransfer, and t_starttransfer are additive.
|
|
* E.g., if t_starttransfer took 2 seconds initially and took another 1
|
|
* second for the redirect request, then the resulting t_starttransfer should
|
|
* be 3 seconds. */
|
|
static CURLcode test_unit1399(const char *arg)
|
|
{
|
|
struct Curl_easy *data;
|
|
struct curltime now = curlx_now();
|
|
|
|
UNITTEST_BEGIN(t1399_setup(&data))
|
|
|
|
data->multi = NULL;
|
|
data->progress.now = now;
|
|
data->progress.t_nslookup = 0;
|
|
data->progress.t_connect = 0;
|
|
data->progress.t_appconnect = 0;
|
|
data->progress.t_pretransfer = 0;
|
|
data->progress.t_starttransfer = 0;
|
|
data->progress.t_redirect = 0;
|
|
data->progress.start.tv_sec = now.tv_sec - 2;
|
|
data->progress.start.tv_usec = now.tv_usec;
|
|
fake_t_startsingle_time(data, now, -2);
|
|
|
|
Curl_pgrsTime(data, TIMER_NAMELOOKUP);
|
|
Curl_pgrsTime(data, TIMER_CONNECT);
|
|
Curl_pgrsTime(data, TIMER_APPCONNECT);
|
|
Curl_pgrsTime(data, TIMER_PRETRANSFER);
|
|
Curl_pgrsTime(data, TIMER_STARTTRANSFER);
|
|
|
|
expect_timer_seconds(data, 2);
|
|
|
|
/* now simulate the redirect */
|
|
data->progress.t_redirect = data->progress.t_starttransfer + 1;
|
|
fake_t_startsingle_time(data, now, -1);
|
|
|
|
Curl_pgrsTime(data, TIMER_NAMELOOKUP);
|
|
Curl_pgrsTime(data, TIMER_CONNECT);
|
|
Curl_pgrsTime(data, TIMER_APPCONNECT);
|
|
Curl_pgrsTime(data, TIMER_PRETRANSFER);
|
|
/* ensure t_starttransfer is only set on the first invocation by attempting
|
|
* to set it twice */
|
|
Curl_pgrsTime(data, TIMER_STARTTRANSFER);
|
|
Curl_pgrsTime(data, TIMER_STARTTRANSFER);
|
|
|
|
expect_timer_seconds(data, 3);
|
|
|
|
UNITTEST_END(t1399_stop(data))
|
|
}
|