From: Daniel Stenberg Date: Sat, 3 Jan 2026 16:50:26 +0000 (+0100) Subject: tool_progress: fix large time outputs and decimal size display X-Git-Tag: curl-8_18_0~19 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b32e66a8ee775b74af22b94feccfb868142a0cc2;p=thirdparty%2Fcurl.git tool_progress: fix large time outputs and decimal size display Time output: - was broken for really large times - now uses spaces instead of --:--:-- - >99999y is now the largest shown time - show HH:MM:SS as long as hours are fewer than 100 Size: - made the decimal output always only use a single decimal Test: - Add test 1622 to verify these functions Closes #20177 --- diff --git a/src/tool_progress.c b/src/tool_progress.c index d2d932b000..6413473101 100644 --- a/src/tool_progress.c +++ b/src/tool_progress.c @@ -29,7 +29,7 @@ /* The point of this function would be to return a string of the input data, but never longer than 5 columns (+ one zero byte). Add suffix k, M, G when suitable... */ -static char *max5data(curl_off_t bytes, char *max5, size_t mlen) +UNITTEST char *max5data(curl_off_t bytes, char *max5, size_t mlen) { /* a signed 64-bit value is 8192 petabytes maximum */ const char unit[] = { 'k', 'M', 'G', 'T', 'P', 'E', 0 }; @@ -43,9 +43,9 @@ static char *max5data(curl_off_t bytes, char *max5, size_t mlen) curl_off_t nbytes = bytes / 1024; if(nbytes < 100) { /* display with a decimal */ - curl_msnprintf(max5, mlen, "%2" CURL_FORMAT_CURL_OFF_T ".%0" + curl_msnprintf(max5, mlen, "%2" CURL_FORMAT_CURL_OFF_T ".%" CURL_FORMAT_CURL_OFF_T "%c", bytes / 1024, - (bytes % 1024) / (1024 / 10), unit[k]); + (bytes % 1024) * 10 / 1024, unit[k]); break; } else if(nbytes < 10000) { @@ -85,33 +85,39 @@ int xferinfo_cb(void *clientp, return 0; } -/* Provide a string that is 2 + 1 + 2 + 1 + 2 = 8 letters long (plus the zero - byte) */ -static void time2str(char *r, size_t rlen, curl_off_t seconds) +/* Provide a time string that is 8 letters long (plus the zero byte) */ +UNITTEST void time2str(char *r, size_t rlen, curl_off_t seconds) { curl_off_t h; if(seconds <= 0) { - curlx_strcopy(r, rlen, "--:--:--", 8); + curlx_strcopy(r, rlen, " ", 8); return; } h = seconds / 3600; if(h <= 99) { curl_off_t m = (seconds - (h * 3600)) / 60; curl_off_t s = (seconds - (h * 3600)) - (m * 60); - curl_msnprintf(r, rlen, "%2" CURL_FORMAT_CURL_OFF_T - ":%02" CURL_FORMAT_CURL_OFF_T - ":%02" CURL_FORMAT_CURL_OFF_T, h, m, s); + curl_msnprintf(r, rlen, "%02" FMT_OFF_T ":%02" FMT_OFF_T ":" + "%02" FMT_OFF_T, h, m, s); } else { - /* this equals to more than 99 hours, switch to a more suitable output - format to fit within the limits. */ curl_off_t d = seconds / 86400; h = (seconds - (d * 86400)) / 3600; if(d <= 999) - curl_msnprintf(r, rlen, "%3" CURL_FORMAT_CURL_OFF_T - "d %02" CURL_FORMAT_CURL_OFF_T "h", d, h); - else - curl_msnprintf(r, rlen, "%7" CURL_FORMAT_CURL_OFF_T "d", d); + curl_msnprintf(r, rlen, "%3" FMT_OFF_T "d %02" FMT_OFF_T "h", d, h); + else { /* more than 999 days */ + curl_off_t m = d / 30; + if(m <= 999) { + curl_msnprintf(r, rlen, "%3" FMT_OFF_T "m %02" FMT_OFF_T "d", m, d%30); + } + else { /* more than 999 months */ + curl_off_t y = d / 365; + if(y <= 99999) + curl_msnprintf(r, rlen, "%7" FMT_OFF_T "y", y); + else + curlx_strcopy(r, rlen, " >99999y", 8); + } + } } } @@ -163,9 +169,9 @@ bool progress_meter(CURLM *multi, struct curltime *start, bool final) tool_stderr); } if(final || (diff > 500)) { - char time_left[10]; - char time_total[10]; - char time_spent[10]; + char time_left[9]; + char time_total[9]; + char time_spent[9]; char buffer[3][6]; curl_off_t spent = curlx_timediff_ms(now, *start) / 1000; char dlpercen[4] = "--"; diff --git a/src/tool_progress.h b/src/tool_progress.h index 41b36ca024..7a474f8b2d 100644 --- a/src/tool_progress.h +++ b/src/tool_progress.h @@ -34,6 +34,13 @@ int xferinfo_cb(void *clientp, bool progress_meter(CURLM *multi, struct curltime *start, bool final); +struct per_transfer; void progress_finalize(struct per_transfer *per); +#ifdef UNITTESTS +UNITTEST char *max5data(curl_off_t bytes, char *max5, size_t mlen); +UNITTEST void time2str(char *r, size_t rlen, curl_off_t seconds); + +#endif + #endif /* HEADER_CURL_TOOL_PROGRESS_H */ diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am index de75499a18..386bd9455f 100644 --- a/tests/data/Makefile.am +++ b/tests/data/Makefile.am @@ -214,7 +214,7 @@ test1590 test1591 test1592 test1593 test1594 test1595 test1596 test1597 \ test1598 test1599 test1600 test1601 test1602 test1603 test1604 test1605 \ test1606 test1607 test1608 test1609 test1610 test1611 test1612 test1613 \ test1614 test1615 test1616 test1617 \ -test1620 test1621 \ +test1620 test1621 test1622 \ \ test1630 test1631 test1632 test1633 test1634 test1635 \ \ diff --git a/tests/data/test1622 b/tests/data/test1622 new file mode 100644 index 0000000000..7cd49b5a98 --- /dev/null +++ b/tests/data/test1622 @@ -0,0 +1,160 @@ + + + + +unittest +tool-progress + + + +# Client-side + + +unittest + + +tool time and size progress output + + +tool%TESTNUMBER + + + + + +time2str + 0 - %SP%SP%SP%SP%SP%SP%SP%SP + 1 - 00:00:01 + 3 - 00:00:03 + 7 - 00:00:07 + 15 - 00:00:15 + 31 - 00:00:31 + 63 - 00:01:03 + 127 - 00:02:07 + 255 - 00:04:15 + 511 - 00:08:31 + 1023 - 00:17:03 + 2047 - 00:34:07 + 4095 - 01:08:15 + 8191 - 02:16:31 + 16383 - 04:33:03 + 32767 - 09:06:07 + 65535 - 18:12:15 + 131071 - 36:24:31 + 262143 - 72:49:03 + 524287 - 6d 01h + 1048575 - 12d 03h + 2097151 - 24d 06h + 4194303 - 48d 13h + 8388607 - 97d 02h + 16777215 - 194d 04h + 33554431 - 388d 08h + 67108863 - 776d 17h + 134217727 - 51m 23d + 268435455 - 103m 16d + 536870911 - 207m 03d + 1073741823 - 414m 07d + 2147483647 - 828m 15d + 4294967295 - 136y + 8589934591 - 272y + 17179869183 - 544y + 34359738367 - 1089y + 68719476735 - 2179y + 137438953471 - 4358y + 274877906943 - 8716y + 549755813887 - 17432y + 1099511627775 - 34865y + 2199023255551 - 69730y + 4398046511103 - >99999y + 8796093022207 - >99999y + 17592186044415 - >99999y + 35184372088831 - >99999y + 70368744177663 - >99999y + 140737488355327 - >99999y + 281474976710655 - >99999y + 562949953421311 - >99999y + 1125899906842623 - >99999y + 2251799813685247 - >99999y + 4503599627370495 - >99999y + 9007199254740991 - >99999y + 18014398509481983 - >99999y + 36028797018963967 - >99999y + 72057594037927935 - >99999y + 144115188075855871 - >99999y + 288230376151711743 - >99999y + 576460752303423487 - >99999y + 1152921504606846975 - >99999y + 2305843009213693951 - >99999y + 4611686018427387903 - >99999y +max5data + 0 - 0 + 1 - 1 + 3 - 3 + 7 - 7 + 15 - 15 + 31 - 31 + 63 - 63 + 127 - 127 + 255 - 255 + 511 - 511 + 1023 - 1023 + 2047 - 2047 + 4095 - 4095 + 8191 - 8191 + 16383 - 16383 + 32767 - 32767 + 65535 - 65535 + 131071 - 127k + 262143 - 255k + 524287 - 511k + 1048575 - 1023k + 2097151 - 2047k + 4194303 - 4095k + 8388607 - 8191k + 16777215 - 15.9M + 33554431 - 31.9M + 67108863 - 63.9M + 134217727 - 127M + 268435455 - 255M + 536870911 - 511M + 1073741823 - 1023M + 2147483647 - 2047M + 4294967295 - 4095M + 8589934591 - 8191M + 17179869183 - 15.9G + 34359738367 - 31.9G + 68719476735 - 63.9G + 137438953471 - 127G + 274877906943 - 255G + 549755813887 - 511G + 1099511627775 - 1023G + 2199023255551 - 2047G + 4398046511103 - 4095G + 8796093022207 - 8191G + 17592186044415 - 15.9T + 35184372088831 - 31.9T + 70368744177663 - 63.9T + 140737488355327 - 127T + 281474976710655 - 255T + 562949953421311 - 511T + 1125899906842623 - 1023T + 2251799813685247 - 2047T + 4503599627370495 - 4095T + 9007199254740991 - 8191T + 18014398509481983 - 15.9P + 36028797018963967 - 31.9P + 72057594037927935 - 63.9P + 144115188075855871 - 127P + 288230376151711743 - 255P + 576460752303423487 - 511P + 1152921504606846975 - 1023P + 2305843009213693951 - 2047P + 4611686018427387903 - 4095P + 131072 - 128k + 12645826 - 12.0M + 1073741824 - 1024M + 12938588979 - 12.0G + 1099445657078333 - 999T + + + diff --git a/tests/tunit/Makefile.inc b/tests/tunit/Makefile.inc index adf66c43e9..4196065686 100644 --- a/tests/tunit/Makefile.inc +++ b/tests/tunit/Makefile.inc @@ -32,4 +32,5 @@ FIRST_C = ../libtest/first.c TESTS_C = \ tool1394.c \ tool1604.c \ - tool1621.c + tool1621.c \ + tool1622.c diff --git a/tests/tunit/tool1622.c b/tests/tunit/tool1622.c new file mode 100644 index 0000000000..e33ba5dbea --- /dev/null +++ b/tests/tunit/tool1622.c @@ -0,0 +1,75 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) Daniel Stenberg, , 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 "tool_progress.h" + +static CURLcode test_tool1622(const char *arg) +{ + UNITTEST_BEGIN_SIMPLE + { + char buffer[9]; + curl_off_t secs; + int i; + static const curl_off_t check[] = { + /* bytes to check */ + 131072, + 12645826, + 1073741824, + 12938588979, + 1099445657078333, + 0 /* end of list */ + }; + + puts("time2str"); + for(i = 0, secs = 0; i < 63; i++) { + time2str(buffer, sizeof(buffer), secs); + curl_mprintf("%20" FMT_OFF_T " - %s\n", secs, buffer); + if(strlen(buffer) != 8) { + curl_mprintf("^^ was too long!\n"); + } + secs *= 2; + secs++; + } + puts("max5data"); + for(i = 0, secs = 0; i < 63; i++) { + max5data(secs, buffer, sizeof(buffer)); + curl_mprintf("%20" FMT_OFF_T " - %s\n", secs, buffer); + if(strlen(buffer) != 5) { + curl_mprintf("^^ was too long!\n"); + } + secs *= 2; + secs++; + } + for(i = 0; check[i]; i++) { + secs = check[i]; + max5data(secs, buffer, sizeof(buffer)); + curl_mprintf("%20" FMT_OFF_T " - %s\n", secs, buffer); + if(strlen(buffer) != 5) { + curl_mprintf("^^ was too long!\n"); + } + } + } + UNITTEST_END_SIMPLE +}