progress: cleanup, less memory

Keep only a single `start` time and calculate the rest in delta
microseconds since then. Separate timestamps and durations into separate
sub-structures for clarity.

remove progress.t_acceptdata
It was recorded in FTP accept but never used anywhere.

Closes #22547
This commit is contained in:
Stefan Eissing 2026-08-11 17:09:26 +02:00 committed by Daniel Stenberg
parent fbfb2499f0
commit 35843dd635
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2
13 changed files with 144 additions and 141 deletions

View file

@ -568,8 +568,7 @@ out:
next_expire_ms = Curl_timeleft_ms(data);
if(next_expire_ms < 0) {
failf(data, "Connection timeout after %" FMT_OFF_T " ms",
curlx_ptimediff_ms(Curl_pgrs_now(data),
&data->progress.t_startsingle));
Curl_pgrs_since_ms(data, NULL, TIMER_STARTSINGLE));
return CURLE_OPERATION_TIMEDOUT;
}
@ -741,8 +740,7 @@ static CURLcode is_connected(struct Curl_cfilter *cf,
proxy_peer ? "over proxy " : "",
proxy_peer ? proxy_peer->hostname : "",
proxy_peer ? " " : "",
curlx_ptimediff_ms(Curl_pgrs_now(data),
&data->progress.t_startsingle),
Curl_pgrs_since_ms(data, NULL, TIMER_STARTSINGLE),
curl_easy_strerror(result));
#ifdef SOCKETIMEDOUT

View file

@ -81,7 +81,7 @@ UNITTEST timediff_t timeleft_now_ms(struct Curl_easy *data,
timediff_t ctimeout_ms = (data->set.connecttimeout > 0) ?
data->set.connecttimeout : DEFAULT_CONNECT_TIMEOUT;
ctimeleft_ms = ctimeout_ms -
curlx_ptimediff_ms(pnow, &data->progress.t_startsingle);
Curl_pgrs_since_ms(data, pnow, TIMER_STARTSINGLE);
if(!ctimeleft_ms)
ctimeleft_ms = -1; /* 0 is "no limit", fake 1 ms expiry */
}
@ -91,7 +91,7 @@ UNITTEST timediff_t timeleft_now_ms(struct Curl_easy *data,
if(data->set.timeout) {
timeleft_ms = data->set.timeout -
curlx_ptimediff_ms(pnow, &data->progress.t_startop);
Curl_pgrs_since_ms(data, pnow, TIMER_STARTOP);
if(!timeleft_ms)
timeleft_ms = -1; /* 0 is "no limit", fake 1 ms expiry */
}

View file

@ -1398,7 +1398,6 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
conn, SECONDARYSOCKET);
}
conn->bits.do_more = FALSE;
Curl_pgrsTime(data, TIMER_STARTACCEPT);
Curl_expire(data, (data->set.accepttimeout > 0) ?
data->set.accepttimeout: DEFAULT_ACCEPT_TIMEOUT,
EXPIRE_FTP_ACCEPT);

View file

@ -43,15 +43,9 @@ void Curl_initinfo(struct Curl_easy *data)
struct Progress *pro = &data->progress;
struct PureInfo *info = &data->info;
pro->t_nslookup = 0;
pro->t_connect = 0;
pro->t_appconnect = 0;
pro->t_pretransfer = 0;
pro->t_posttransfer = 0;
pro->t_starttransfer = 0;
pro->timespent = 0;
pro->t_redirect = 0;
pro->is_t_startransfer_set = FALSE;
memset(&pro->delta, 0, sizeof(pro->delta));
memset(&pro->total, 0, sizeof(pro->total));
pro->startransfer_added = FALSE;
info->httpcode = 0;
info->httpproxycode = 0;
@ -436,31 +430,31 @@ static CURLcode getinfo_offt(struct Curl_easy *data, CURLINFO info,
data->progress.ul.total_size : -1;
break;
case CURLINFO_TOTAL_TIME_T:
*param_offt = data->progress.timespent;
*param_offt = data->progress.total.spent_us;
break;
case CURLINFO_NAMELOOKUP_TIME_T:
*param_offt = data->progress.t_nslookup;
*param_offt = data->progress.total.nslookup_us;
break;
case CURLINFO_CONNECT_TIME_T:
*param_offt = data->progress.t_connect;
*param_offt = data->progress.total.connect_us;
break;
case CURLINFO_APPCONNECT_TIME_T:
*param_offt = data->progress.t_appconnect;
*param_offt = data->progress.total.appconnect_us;
break;
case CURLINFO_PRETRANSFER_TIME_T:
*param_offt = data->progress.t_pretransfer;
*param_offt = data->progress.total.pretransfer_us;
break;
case CURLINFO_POSTTRANSFER_TIME_T:
*param_offt = data->progress.t_posttransfer;
*param_offt = data->progress.total.posttransfer_us;
break;
case CURLINFO_STARTTRANSFER_TIME_T:
*param_offt = data->progress.t_starttransfer;
*param_offt = data->progress.total.starttransfer_us;
break;
case CURLINFO_QUEUE_TIME_T:
*param_offt = data->progress.t_postqueue;
*param_offt = data->progress.total.queued_us;
break;
case CURLINFO_REDIRECT_TIME_T:
*param_offt = data->progress.t_redirect;
*param_offt = data->progress.delta.startredirect_us;
break;
case CURLINFO_RETRY_AFTER:
*param_offt = data->info.retry_after;
@ -512,22 +506,22 @@ static CURLcode getinfo_double(struct Curl_easy *data, CURLINFO info,
#endif
switch(info) {
case CURLINFO_TOTAL_TIME:
*param_doublep = DOUBLE_SECS(data->progress.timespent);
*param_doublep = DOUBLE_SECS(data->progress.total.spent_us);
break;
case CURLINFO_NAMELOOKUP_TIME:
*param_doublep = DOUBLE_SECS(data->progress.t_nslookup);
*param_doublep = DOUBLE_SECS(data->progress.total.nslookup_us);
break;
case CURLINFO_CONNECT_TIME:
*param_doublep = DOUBLE_SECS(data->progress.t_connect);
*param_doublep = DOUBLE_SECS(data->progress.total.connect_us);
break;
case CURLINFO_APPCONNECT_TIME:
*param_doublep = DOUBLE_SECS(data->progress.t_appconnect);
*param_doublep = DOUBLE_SECS(data->progress.total.appconnect_us);
break;
case CURLINFO_PRETRANSFER_TIME:
*param_doublep = DOUBLE_SECS(data->progress.t_pretransfer);
*param_doublep = DOUBLE_SECS(data->progress.total.pretransfer_us);
break;
case CURLINFO_STARTTRANSFER_TIME:
*param_doublep = DOUBLE_SECS(data->progress.t_starttransfer);
*param_doublep = DOUBLE_SECS(data->progress.total.starttransfer_us);
break;
case CURLINFO_SIZE_UPLOAD:
*param_doublep = (double)data->progress.ul.cur_size;
@ -550,7 +544,7 @@ static CURLcode getinfo_double(struct Curl_easy *data, CURLINFO info,
(double)data->progress.ul.total_size : -1;
break;
case CURLINFO_REDIRECT_TIME:
*param_doublep = DOUBLE_SECS(data->progress.t_redirect);
*param_doublep = DOUBLE_SECS(data->progress.delta.startredirect_us);
break;
default:

View file

@ -1826,29 +1826,25 @@ static bool multi_handle_timeout(struct Curl_easy *data,
timeout_ms = Curl_timeleft_ms(data);
if(timeout_ms < 0) {
/* Handle timed out */
struct curltime since;
if(Curl_is_connecting(data))
since = data->progress.t_startsingle;
else
since = data->progress.t_startop;
timerid base_timer = Curl_is_connecting(data) ?
TIMER_STARTSINGLE : TIMER_STARTOP;
timediff_t elapsed_ms = Curl_pgrs_since_ms(data, NULL, base_timer);
if(data->mstate == MSTATE_CONNECTING)
failf(data, "%s timed out after %" FMT_TIMEDIFF_T " milliseconds",
data->conn->bits.dns_resolved ? "Connection" : "Resolving",
curlx_ptimediff_ms(Curl_pgrs_now(data), &since));
elapsed_ms);
else {
struct SingleRequest *k = &data->req;
if(k->size != -1) {
failf(data, "Operation timed out after %" FMT_TIMEDIFF_T
" milliseconds with %" FMT_OFF_T " out of %"
FMT_OFF_T " bytes received",
curlx_ptimediff_ms(Curl_pgrs_now(data), &since),
k->bytecount, k->size);
elapsed_ms, k->bytecount, k->size);
}
else {
failf(data, "Operation timed out after %" FMT_TIMEDIFF_T
" milliseconds with %" FMT_OFF_T " bytes received",
curlx_ptimediff_ms(Curl_pgrs_now(data), &since),
k->bytecount);
elapsed_ms, k->bytecount);
}
}
*result = CURLE_OPERATION_TIMEDOUT;

View file

@ -188,7 +188,7 @@ const struct curltime *Curl_pgrs_now(struct Curl_easy *data)
int Curl_pgrsDone(struct Curl_easy *data)
{
int rc;
data->progress.lastshow = 0;
data->progress.delta.lastshow_us = -1;
rc = Curl_pgrsUpdate(data); /* the final (forced) update */
if(rc)
return rc;
@ -247,7 +247,6 @@ static const char * const pgrs_timer_names[] = {
"PGRS-PRETRANSFER",
"PGRS-STARTTRANSFER",
"PGRS-POSTRANSFER",
"PGRS-STARTACCEPT",
"PGRS-REDIRECT",
};
@ -274,34 +273,33 @@ void Curl_pgrsTimeWas(struct Curl_easy *data, timerid timer,
break;
case TIMER_STARTOP:
/* This is set at the start of a transfer */
data->progress.t_startop = timestamp;
data->progress.t_startqueue = timestamp;
data->progress.t_postqueue = 0;
data->progress.delta.startop_us =
curlx_ptimediff_us(&timestamp, &data->progress.start);
data->progress.delta.startqueue_us = data->progress.delta.startop_us;
break;
case TIMER_STARTSINGLE:
/* This is set at the start of each single transfer */
data->progress.t_startsingle = timestamp;
data->progress.is_t_startransfer_set = FALSE;
data->progress.delta.startsingle_us =
curlx_ptimediff_us(&timestamp, &data->progress.start);
data->progress.startransfer_added = FALSE;
break;
case TIMER_POSTQUEUE:
/* Queue time is accumulative from all involved redirects */
data->progress.t_postqueue +=
curlx_ptimediff_us(&timestamp, &data->progress.t_startqueue);
break;
case TIMER_STARTACCEPT:
data->progress.t_acceptdata = timestamp;
data->progress.total.queued_us +=
curlx_ptimediff_us(&timestamp, &data->progress.start) -
data->progress.delta.startqueue_us;
break;
case TIMER_NAMELOOKUP:
delta = &data->progress.t_nslookup;
delta = &data->progress.total.nslookup_us;
break;
case TIMER_CONNECT:
delta = &data->progress.t_connect;
delta = &data->progress.total.connect_us;
break;
case TIMER_APPCONNECT:
delta = &data->progress.t_appconnect;
delta = &data->progress.total.appconnect_us;
break;
case TIMER_PRETRANSFER:
delta = &data->progress.t_pretransfer;
delta = &data->progress.total.pretransfer_us;
break;
case TIMER_STARTTRANSFER:
/* prevent updating t_starttransfer unless:
@ -310,25 +308,27 @@ void Curl_pgrsTimeWas(struct Curl_easy *data, timerid timer,
* This prevents repeated invocations of the function from incorrectly
* changing the t_starttransfer time.
*/
if(data->progress.is_t_startransfer_set) {
if(data->progress.startransfer_added) {
CURL_TRC_M(data, "[%s] ignored", pgrs_timer_name(timer));
return;
}
data->progress.is_t_startransfer_set = TRUE;
delta = &data->progress.t_starttransfer;
data->progress.startransfer_added = TRUE;
delta = &data->progress.total.starttransfer_us;
break;
case TIMER_POSTRANSFER:
delta = &data->progress.t_posttransfer;
delta = &data->progress.total.posttransfer_us;
break;
case TIMER_REDIRECT:
data->progress.t_redirect = curlx_ptimediff_us(&timestamp,
&data->progress.start);
data->progress.t_startqueue = timestamp;
data->progress.delta.startredirect_us =
curlx_ptimediff_us(&timestamp, &data->progress.start);
/* transfer starts queueing again */
data->progress.delta.startqueue_us =
data->progress.delta.startredirect_us;
break;
}
if(delta) {
timediff_t us = curlx_ptimediff_us(&timestamp,
&data->progress.t_startsingle);
timediff_t us = curlx_ptimediff_us(&timestamp, &data->progress.start) -
data->progress.delta.startsingle_us;
if(us < 1)
us = 1; /* make sure at least one microsecond passed */
*delta += us;
@ -350,13 +350,17 @@ void Curl_pgrsTime(struct Curl_easy *data, timerid timer)
Curl_pgrsTimeWas(data, timer, *Curl_pgrs_now(data));
}
void Curl_pgrsStartNow(struct Curl_easy *data)
void Curl_pgrsStart(struct Curl_easy *data, const struct curltime *pnow)
{
struct Progress *p = &data->progress;
if(!pnow)
pnow = Curl_pgrs_now(data);
p->speeder_c = 0; /* reset the progress meter display */
p->start = *Curl_pgrs_now(data);
p->is_t_startransfer_set = FALSE;
p->start = *pnow;
memset(&p->delta, 0, sizeof(p->delta));
memset(&p->total, 0, sizeof(p->total));
p->startransfer_added = FALSE;
p->dl.cur_size = 0;
p->ul.cur_size = 0;
/* the sizes are unknown at start */
@ -456,21 +460,22 @@ static bool progress_calc(struct Curl_easy *data,
{
struct Progress * const p = &data->progress;
int i_next, i_oldest, i_latest;
timediff_t duration_us;
timediff_t duration_us, elapsed_us;
curl_off_t amount;
/* The time spent so far (from the start) in microseconds */
p->timespent = curlx_ptimediff_us(pnow, &p->start);
p->dl.speed = trspeed(p->dl.cur_size, p->timespent);
p->ul.speed = trspeed(p->ul.cur_size, p->timespent);
elapsed_us = curlx_ptimediff_us(pnow, &p->start);
p->total.spent_us = elapsed_us;
p->dl.speed = trspeed(p->dl.cur_size, p->total.spent_us);
p->ul.speed = trspeed(p->ul.cur_size, p->total.spent_us);
if(!p->speeder_c) { /* no previous record exists */
p->speed_amount[0] = p->dl.cur_size + p->ul.cur_size;
p->speed_time[0] = *pnow;
p->speed_time[0] = elapsed_us;
p->speeder_c++;
/* use the overall average at the start */
p->current_speed = p->ul.speed + p->dl.speed;
p->lastshow = pnow->tv_sec;
p->delta.lastshow_us = elapsed_us;
return TRUE;
}
/* We have at least one record now. Where to put the next and
@ -480,11 +485,11 @@ static bool progress_calc(struct Curl_easy *data,
/* Make a new record only when some time has passed.
* Too frequent calls otherwise ruin the history. */
if(curlx_ptimediff_ms(pnow, &p->speed_time[i_latest]) >= 1000) {
if((elapsed_us - p->speed_time[i_latest]) >= (1000 * 1000)) {
p->speeder_c++;
i_latest = i_next;
p->speed_amount[i_latest] = p->dl.cur_size + p->ul.cur_size;
p->speed_time[i_latest] = *pnow;
p->speed_time[i_latest] = elapsed_us;
}
else if(data->req.done) {
/* When a transfer is done, and we did not have a current speed
@ -493,7 +498,7 @@ static bool progress_calc(struct Curl_easy *data,
* reported speed since it no longer measures a full second. */
if(!p->current_speed) {
p->speed_amount[i_latest] = p->dl.cur_size + p->ul.cur_size;
p->speed_time[i_latest] = *pnow;
p->speed_time[i_latest] = elapsed_us;
}
}
else {
@ -507,8 +512,7 @@ static bool progress_calc(struct Curl_easy *data,
/* How much we transferred between oldest and current records */
amount = p->speed_amount[i_latest] - p->speed_amount[i_oldest];
/* How long this took */
duration_us = curlx_ptimediff_us(&p->speed_time[i_latest],
&p->speed_time[i_oldest]);
duration_us = p->speed_time[i_latest] - p->speed_time[i_oldest];
if(duration_us <= 0)
duration_us = 1;
@ -522,9 +526,10 @@ static bool progress_calc(struct Curl_easy *data,
p->current_speed = amount * 1000000 / duration_us;
}
if((p->lastshow == pnow->tv_sec) && !data->req.done)
if((p->delta.lastshow_us >= 0) && !data->req.done &&
((elapsed_us - p->delta.lastshow_us) >= (1000 * 1000)))
return FALSE;
p->lastshow = pnow->tv_sec;
p->delta.lastshow_us = elapsed_us;
return TRUE;
}
@ -569,7 +574,7 @@ static void progress_meter(struct Curl_easy *data)
char time_left[8];
char time_total[8];
char time_spent[8];
curl_off_t cur_secs = (curl_off_t)p->timespent / 1000000; /* seconds */
curl_off_t cur_secs = (curl_off_t)p->total.spent_us / 1000000;
if(!p->headers_out) {
if(data->state.resume_from) {
@ -731,5 +736,24 @@ void Curl_pgrsUpdate_nometer(struct Curl_easy *data)
void Curl_pgrsCompleted(struct Curl_easy *data)
{
struct Progress * const p = &data->progress;
p->timespent = curlx_ptimediff_us(Curl_pgrs_now(data), &p->start);
p->total.spent_us = curlx_ptimediff_us(Curl_pgrs_now(data), &p->start);
}
timediff_t Curl_pgrs_since_ms(struct Curl_easy *data,
const struct curltime *pnow,
timerid timer)
{
if(!pnow)
pnow = Curl_pgrs_now(data);
switch(timer) {
case TIMER_STARTOP:
return (curlx_ptimediff_us(pnow, &data->progress.start) -
data->progress.delta.startop_us) / 1000;
case TIMER_STARTSINGLE:
return (curlx_ptimediff_us(pnow, &data->progress.start) -
data->progress.delta.startsingle_us) / 1000;
default:
DEBUGASSERT(0);
return 0;
}
}

View file

@ -38,7 +38,6 @@ typedef enum {
TIMER_PRETRANSFER,
TIMER_STARTTRANSFER,
TIMER_POSTRANSFER,
TIMER_STARTACCEPT,
TIMER_REDIRECT,
TIMER_LAST /* must be last */
} timerid;
@ -47,7 +46,7 @@ typedef enum {
const struct curltime *Curl_pgrs_now(struct Curl_easy *data);
int Curl_pgrsDone(struct Curl_easy *data);
void Curl_pgrsStartNow(struct Curl_easy *data);
void Curl_pgrsStart(struct Curl_easy *data, const struct curltime *pnow);
void Curl_pgrsSetDownloadSize(struct Curl_easy *data, curl_off_t size);
void Curl_pgrsSetUploadSize(struct Curl_easy *data, curl_off_t size);
CURLcode Curl_pgrs_deliver_check(struct Curl_easy *data, size_t delta);
@ -85,4 +84,8 @@ void Curl_pgrsEarlyData(struct Curl_easy *data, curl_off_t sent);
void Curl_pgrsCompleted(struct Curl_easy *data);
timediff_t Curl_pgrs_since_ms(struct Curl_easy *data,
const struct curltime *pnow,
timerid timer);
#endif /* HEADER_CURL_PROGRESS_H */

View file

@ -988,8 +988,6 @@ static CURLcode tftp_connect(struct Curl_easy *data, bool *done)
conn->bits.bound = TRUE;
}
Curl_pgrsStartNow(data);
*done = TRUE;
return CURLE_OK;

View file

@ -386,15 +386,13 @@ CURLcode Curl_sendrecv(struct Curl_easy *data)
failf(data, "Operation timed out after %" FMT_TIMEDIFF_T
" milliseconds with %" FMT_OFF_T " out of %"
FMT_OFF_T " bytes received",
curlx_ptimediff_ms(Curl_pgrs_now(data),
&data->progress.t_startsingle),
Curl_pgrs_since_ms(data, NULL, TIMER_STARTSINGLE),
k->bytecount, k->size);
}
else {
failf(data, "Operation timed out after %" FMT_TIMEDIFF_T
" milliseconds with %" FMT_OFF_T " bytes received",
curlx_ptimediff_ms(Curl_pgrs_now(data),
&data->progress.t_startsingle),
Curl_pgrs_since_ms(data, NULL, TIMER_STARTSINGLE),
k->bytecount);
}
result = CURLE_OPERATION_TIMEDOUT;
@ -555,7 +553,7 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
Curl_initinfo(data); /* reset session-specific information "variables" */
Curl_pgrsResetTransferSizes(data);
Curl_pgrsStartNow(data);
Curl_pgrsStart(data, NULL);
/* In case the handle is reused and an authentication method was picked
in the session we need to make sure we only use the one(s) we now

View file

@ -438,43 +438,43 @@ struct pgrs_dir {
struct Progress {
struct curltime now; /* current time of processing */
time_t lastshow; /* time() of the last displayed progress meter or NULL to
force redraw at next call */
struct curltime start; /* when transfer was initialized, set once */
struct pgrs_dir ul;
struct pgrs_dir dl;
curl_off_t deliver; /* amount of data delivered to application */
curl_off_t current_speed; /* uses the currently fastest transfer */
curl_off_t earlydata_sent;
timediff_t timespent;
timediff_t t_postqueue;
timediff_t t_nslookup;
timediff_t t_connect;
timediff_t t_appconnect;
timediff_t t_pretransfer;
timediff_t t_posttransfer;
timediff_t t_starttransfer;
timediff_t t_redirect;
struct curltime start;
struct curltime t_startsingle;
struct curltime t_startop;
struct curltime t_startqueue;
struct curltime t_acceptdata;
struct {
timediff_t startop_us; /* since start when operations started */
timediff_t startsingle_us; /* since start when last request started */
timediff_t startqueue_us; /* since start when last entered queueing */
timediff_t startredirect_us; /* since start when last redirected */
timediff_t lastshow_us; /* since start when last progress shown */
} delta;
struct {
timediff_t spent_us; /* all time spent since start */
timediff_t queued_us; /* time spent since startsingle's for queueing */
timediff_t nslookup_us; /* same for name resolves */
timediff_t connect_us; /* same for connects */
timediff_t appconnect_us; /* same for application connects, e.g. TLS */
timediff_t pretransfer_us; /* same until requests were sent */
timediff_t starttransfer_us; /* same until responses started */
timediff_t posttransfer_us; /* same until responses ended */
} total;
#define CURL_SPEED_RECORDS (5 + 1) /* 6 entries for 5 seconds */
curl_off_t speed_amount[CURL_SPEED_RECORDS];
struct curltime speed_time[CURL_SPEED_RECORDS];
timediff_t speed_time[CURL_SPEED_RECORDS];
uint32_t speeder_c;
BIT(hide);
BIT(ul_size_known);
BIT(dl_size_known);
BIT(headers_out); /* when the headers have been written */
BIT(callback); /* set when progress callback is used */
BIT(is_t_startransfer_set);
BIT(startransfer_added);
};
struct auth {

View file

@ -230,8 +230,7 @@ static CURLcode cf_dns_start(struct Curl_cfilter *cf,
else if(result == CURLE_OPERATION_TIMEDOUT) { /* took too long */
failf(data, "Failed to resolve '%s' with timeout after %"
FMT_TIMEDIFF_T " ms", ctx->peer->hostname,
curlx_ptimediff_ms(Curl_pgrs_now(data),
&data->progress.t_startsingle));
Curl_pgrs_since_ms(data, NULL, TIMER_STARTSINGLE));
return CURLE_OPERATION_TIMEDOUT;
}
else {

View file

@ -139,10 +139,10 @@ static CURLcode test_unit1303(const char *arg)
};
/* this is the pretended start time of the transfer */
easy->progress.t_startsingle.tv_sec = BASE;
easy->progress.t_startsingle.tv_usec = 0;
easy->progress.t_startop.tv_sec = BASE;
easy->progress.t_startop.tv_usec = 0;
easy->progress.start.tv_sec = BASE;
easy->progress.start.tv_usec = 0;
easy->progress.delta.startsingle_us = 0;
easy->progress.delta.startop_us = 0;
for(i = 0; i < CURL_ARRAYSIZE(run); i++) {
timediff_t timeout;

View file

@ -46,16 +46,14 @@ static void t1399_stop(struct Curl_easy *easy)
/*
* Invoke Curl_pgrsTime for TIMER_STARTSINGLE to trigger the behavior that
* manages is_t_startransfer_set, but fake the t_startsingle time for purposes
* manages startransfer, but fake the startsingle_us 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;
data->progress.delta.startsingle_us = (seconds_offset * 1000 * 1000);
}
static bool usec_matches_seconds(timediff_t time_usec, int expected_seconds)
@ -72,16 +70,15 @@ static bool usec_matches_seconds(timediff_t time_usec, int expected_seconds)
static void expect_timer_seconds(struct Curl_easy *data, int seconds)
{
struct Progress *p = &data->progress;
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);
fail_unless(usec_matches_seconds(p->total.nslookup_us, seconds), msg);
fail_unless(usec_matches_seconds(p->total.connect_us, seconds), msg);
fail_unless(usec_matches_seconds(p->total.appconnect_us, seconds), msg);
fail_unless(usec_matches_seconds(p->total.pretransfer_us, seconds), msg);
fail_unless(usec_matches_seconds(p->total.starttransfer_us, seconds), msg);
}
/* Scenario: simulate a redirect. When a redirect occurs, t_nslookup,
@ -98,15 +95,12 @@ static CURLcode test_unit1399(const char *arg)
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;
memset(&data->progress.delta, 0, sizeof(data->progress.delta));
memset(&data->progress.total, 0, sizeof(data->progress.total));
data->progress.start.tv_sec = now.tv_sec - 2;
data->progress.start.tv_usec = now.tv_usec;
fake_t_startsingle_time(data, now, -2);
fake_t_startsingle_time(data, 0);
Curl_pgrsTime(data, TIMER_NAMELOOKUP);
Curl_pgrsTime(data, TIMER_CONNECT);
@ -117,8 +111,8 @@ static CURLcode test_unit1399(const char *arg)
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);
data->progress.delta.startredirect_us = 1 * 1000 * 1000;
fake_t_startsingle_time(data, 1);
Curl_pgrsTime(data, TIMER_NAMELOOKUP);
Curl_pgrsTime(data, TIMER_CONNECT);