]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
tool_progress: fix large time outputs and decimal size display
authorDaniel Stenberg <daniel@haxx.se>
Sat, 3 Jan 2026 16:50:26 +0000 (17:50 +0100)
committerDaniel Stenberg <daniel@haxx.se>
Sat, 3 Jan 2026 23:16:59 +0000 (00:16 +0100)
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

src/tool_progress.c
src/tool_progress.h
tests/data/Makefile.am
tests/data/test1622 [new file with mode: 0644]
tests/tunit/Makefile.inc
tests/tunit/tool1622.c [new file with mode: 0644]

index d2d932b0008750409de411d337f438124aac4cd3..641347310142a83643213d31306ebfef6cd7d032 100644 (file)
@@ -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] = "--";
index 41b36ca024a05a34edd9f9f4eba796665ce3edf8..7a474f8b2d46757d79838449a8c0d65bcb002bd4 100644 (file)
@@ -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 */
index de75499a183e85ddc9f68e9090116dc4b95b6966..386bd9455f75aa8520431253cd6a118d42fe7114 100644 (file)
@@ -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 (file)
index 0000000..7cd49b5
--- /dev/null
@@ -0,0 +1,160 @@
+<?xml version="1.0" encoding="US-ASCII"?>
+<testcase>
+<info>
+<keywords>
+unittest
+tool-progress
+</keywords>
+</info>
+
+# Client-side
+<client>
+<features>
+unittest
+</features>
+<name>
+tool time and size progress output
+</name>
+<tool>
+tool%TESTNUMBER
+</tool>
+</client>
+
+<verify>
+<stdout>
+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
+</stdout>
+</verify>
+</testcase>
index adf66c43e9db2ddd7c84d8cf1f886ef4133f41fe..419606568688471be7ceccc74422901a5e8ba7d5 100644 (file)
@@ -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 (file)
index 0000000..e33ba5d
--- /dev/null
@@ -0,0 +1,75 @@
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  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 "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
+}