You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2015/09/10 20:57:33 UTC

svn commit: r1702310 - in /subversion/trunk/subversion: svnfsfs/stats-cmd.c tests/cmdline/svnfsfs_tests.py

Author: stefan2
Date: Thu Sep 10 18:57:32 2015
New Revision: 1702310

URL: http://svn.apache.org/r1702310
Log:
Fix division by zero bug when running 'svnfsfs stats' on an empty repo.

* subversion/svnfsfs/stats-cmd.c
  (print_extensions_by_changes): Don't show anything if there are no entries.
  (get_percentage): New utility function.
  (print_extensions_by_nodes,
   print_extensions_by_reps): Use the new utility to show correct percentages
                              even if there are only 0 length items.

* subversion/tests/cmdline/svnfsfs_tests.py
  (test_stats_on_empty_repo): New test.
  (test_list): Register new test.

Found by: philipm

Modified:
    subversion/trunk/subversion/svnfsfs/stats-cmd.c
    subversion/trunk/subversion/tests/cmdline/svnfsfs_tests.py

Modified: subversion/trunk/subversion/svnfsfs/stats-cmd.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/svnfsfs/stats-cmd.c?rev=1702310&r1=1702309&r2=1702310&view=diff
==============================================================================
--- subversion/trunk/subversion/svnfsfs/stats-cmd.c (original)
+++ subversion/trunk/subversion/svnfsfs/stats-cmd.c Thu Sep 10 18:57:32 2015
@@ -20,6 +20,8 @@
  * ====================================================================
  */
 
+#include <assert.h>
+
 #include "svn_fs.h"
 #include "svn_pools.h"
 #include "svn_sorts.h"
@@ -235,6 +237,10 @@ print_extensions_by_changes(svn_fs_fs__s
     {
       svn_fs_fs__extension_info_t *info
         = APR_ARRAY_IDX(data, i, svn_fs_fs__extension_info_t *);
+
+      /* If there are elements, then their count cannot be 0. */
+      assert(stats->file_histogram.total.count);
+
       sum += info->node_histogram.total.count;
       printf(_("%11s %20s (%2d%%) representations\n"),
              info->extension,
@@ -243,11 +249,28 @@ print_extensions_by_changes(svn_fs_fs__s
                    stats->file_histogram.total.count));
     }
 
-  printf(_("%11s %20s (%2d%%) representations\n"),
-         "(others)",
-         svn__ui64toa_sep(stats->file_histogram.total.count - sum, ',', pool),
-         (int)((stats->file_histogram.total.count - sum) * 100 /
-               stats->file_histogram.total.count));
+  if (stats->file_histogram.total.count)
+    {
+      printf(_("%11s %20s (%2d%%) representations\n"),
+             "(others)",
+             svn__ui64toa_sep(stats->file_histogram.total.count - sum, ',',
+                              pool),
+             (int)((stats->file_histogram.total.count - sum) * 100 /
+                   stats->file_histogram.total.count));
+    }
+}
+
+/* Calculate a percentage, handling edge cases. */
+static int
+get_percentage(apr_uint64_t part,
+               apr_uint64_t total)
+{
+  /* This include total == 0. */
+  if (part >= total)
+    return 100;
+
+  /* Standard case. */
+  return (int)(part * 100.0 / total);
 }
 
 /* Print the (up to) 16 extensions in STATS with the largest total size of
@@ -269,15 +292,20 @@ print_extensions_by_nodes(svn_fs_fs__sta
       printf(_("%11s %20s (%2d%%) bytes\n"),
              info->extension,
              svn__ui64toa_sep(info->node_histogram.total.sum, ',', pool),
-             (int)(info->node_histogram.total.sum * 100 /
-                   stats->file_histogram.total.sum));
+             get_percentage(info->node_histogram.total.sum,
+                            stats->file_histogram.total.sum));
     }
 
-  printf(_("%11s %20s (%2d%%) bytes\n"),
-         "(others)",
-         svn__ui64toa_sep(stats->file_histogram.total.sum - sum, ',', pool),
-         (int)((stats->file_histogram.total.sum - sum) * 100 /
-               stats->file_histogram.total.sum));
+  if (stats->file_histogram.total.sum > sum)
+    {
+      /* Total sum can't be zero here. */
+      printf(_("%11s %20s (%2d%%) bytes\n"),
+             "(others)",
+             svn__ui64toa_sep(stats->file_histogram.total.sum - sum, ',',
+                              pool),
+             get_percentage(stats->file_histogram.total.sum - sum,
+                            stats->file_histogram.total.sum));
+    }
 }
 
 /* Print the (up to) 16 extensions in STATS with the largest total size of
@@ -299,16 +327,20 @@ print_extensions_by_reps(svn_fs_fs__stat
       printf(_("%11s %20s (%2d%%) bytes\n"),
              info->extension,
              svn__ui64toa_sep(info->rep_histogram.total.sum, ',', pool),
-             (int)(info->rep_histogram.total.sum * 100 /
-                   stats->rep_size_histogram.total.sum));
+             get_percentage(info->rep_histogram.total.sum,
+                            stats->rep_size_histogram.total.sum));
     }
 
-  printf(_("%11s %20s (%2d%%) bytes\n"),
-         "(others)",
-         svn__ui64toa_sep(stats->rep_size_histogram.total.sum - sum, ',',
-                          pool),
-         (int)((stats->rep_size_histogram.total.sum - sum) * 100 /
-               stats->rep_size_histogram.total.sum));
+  if (stats->rep_size_histogram.total.sum > sum)
+    {
+      /* Total sum can't be zero here. */
+      printf(_("%11s %20s (%2d%%) bytes\n"),
+             "(others)",
+             svn__ui64toa_sep(stats->rep_size_histogram.total.sum - sum, ',',
+                              pool),
+             get_percentage(stats->rep_size_histogram.total.sum - sum,
+                            stats->rep_size_histogram.total.sum));
+    }
 }
 
 /* Print per-extension histograms for the most frequent extensions in STATS.

Modified: subversion/trunk/subversion/tests/cmdline/svnfsfs_tests.py
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/svnfsfs_tests.py?rev=1702310&r1=1702309&r2=1702310&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/svnfsfs_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/svnfsfs_tests.py Thu Sep 10 18:57:32 2015
@@ -302,6 +302,15 @@ def load_index_sharded(sbox):
   svntest.actions.run_and_verify_svnadmin(expected_output, [],
                                           "verify", sbox.repo_dir)
 
+@SkipUnless(svntest.main.is_fs_type_fsfs)
+def test_stats_on_empty_repo(sbox):
+  "stats on empty repo shall not crash"
+
+  sbox.build(create_wc=False, empty=True)
+
+  exit_code, output, errput = \
+    svntest.actions.run_and_verify_svnfsfs(None, [], 'stats', sbox.repo_dir)
+
 ########################################################################
 # Run the tests
 
@@ -310,6 +319,7 @@ def load_index_sharded(sbox):
 test_list = [ None,
               test_stats,
               load_index_sharded,
+              test_stats_on_empty_repo,
              ]
 
 if __name__ == '__main__':