svn commit: r1931402 - in subversion/trunk: build/generator subversion/libsvn_subr subversion/tests/libsvn_subr

[email protected]
Newsgroups gmane.comp.version-control.subversion.svn
Message-ID <176872729474.3382480.14802110962870423018@svn02-us-east.apache.org>
Author: brane
Date: Sun Jan 18 09:08:13 2026
New Revision: 1931402

Log:
Add another test for the Adler-32 implementation. All code branches
should now be covered with tests, even if this new test is a bit
contrived.

* subversion/libsvn_subr/adler32.c
  (SVN__ADLER32_SIZE_MAX): Do not define this constant if SVN__ADLER32_STATIC
   is defined. This allows adler32-test.c to locally override the maximum
   block size.

* subversion/tests/libsvn_subr/adler32-test.c: Add a comment about sorting
   the constant arrays that contain test inputs.
  (do_random_test): Move common code from the dependent test functions
   that call to here.
  (test_magic_length, test_prime_length, test_power2_length): Rename from
   test_random_magic, test_random_prime and test_random_power2,
   respectively; and just call do_random_test.
  (local_adler32): New, defined implicitly by including adler32.c
   with a modified maximum block size.
  (test_large_size): New test case; exercises the unlikely code branch in
   our Adler-32 implementation.
  (test_funcs): Update the whole array.

Modified:
   subversion/trunk/build/generator/gen_base.py
   subversion/trunk/subversion/libsvn_subr/adler32.c
   subversion/trunk/subversion/tests/libsvn_subr/adler32-test.c

Modified: subversion/trunk/build/generator/gen_base.py
==============================================================================
--- subversion/trunk/build/generator/gen_base.py	Sun Jan 18 08:30:14 2026	(r1931401)
+++ subversion/trunk/build/generator/gen_base.py	Sun Jan 18 09:08:13 2026	(r1931402)
@@ -1288,6 +1288,9 @@ class IncludeDependencyInfo:
       if os.sep.join(['libsvn_subr', 'cmdline.c']) in fname \
            and 'config_keys.inc' == include_param:
         continue # generated by GeneratorBase.write_config_keys
+      if os.sep.join(['tests', 'libsvn_subr', 'adler32-test.c']) in fname \
+           and '../../libsvn_subr/adler32.c' == include_param:
+        continue # adler32-test.c inludes the source file on purpose
       elif direct_possibility_fname in domain_fnames:
         self._upd_dep_hash(hdrs, direct_possibility_fname, type_code)
       elif (len(domain_fnames) == 1

Modified: subversion/trunk/subversion/libsvn_subr/adler32.c
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/adler32.c	Sun Jan 18 08:30:14 2026	(r1931401)
+++ subversion/trunk/subversion/libsvn_subr/adler32.c	Sun Jan 18 09:08:13 2026	(r1931402)
@@ -47,10 +47,17 @@ typedef z_size_t svn__adler32_size_t;
 #else
 typedef uInt svn__adler32_size_t;
 #define svn__adler32_impl adler32
-#endif
-#define SVN__ADLER32_SIZE_MAX (~(svn__adler32_size_t)0)
+#endif  /* SVN_ZLIB_HAS_ADLER32_Z */
+
 #define svn__adler32_fn(c,d,s) svn__adler32_impl((c), (const Bytef *)(d), (s))
 
+/* See adler32-test.c which invokes dark magic in order to test the
+   (len > SVN__ADLER32_SIZE_MAX) branch of the implementation. */
+#ifndef SVN__ADLER32_STATIC
+#define SVN__ADLER32_STATIC
+#define SVN__ADLER32_SIZE_MAX (~(svn__adler32_size_t)0)
+#endif
+
 /*
  * 65521 is the largest prime less than 65536.
  * "That 65521 is prime is important to avoid a possible large class of
@@ -62,7 +69,7 @@ typedef uInt svn__adler32_size_t;
  * Start with CHECKSUM and update the checksum by processing a chunk
  * of DATA sized LEN.
  */
-apr_uint32_t
+SVN__ADLER32_STATIC apr_uint32_t
 svn__adler32(apr_uint32_t checksum, const char *data, apr_off_t len)
 {
   /* Process large amounts of data in max-sized chunks.

Modified: subversion/trunk/subversion/tests/libsvn_subr/adler32-test.c
==============================================================================
--- subversion/trunk/subversion/tests/libsvn_subr/adler32-test.c	Sun Jan 18 08:30:14 2026	(r1931401)
+++ subversion/trunk/subversion/tests/libsvn_subr/adler32-test.c	Sun Jan 18 09:08:13 2026	(r1931402)
@@ -51,6 +51,8 @@ static const char *make_random_data(apr_
 }
 
 
+/* NOTE: The following constant arrays of data sizes must
+         be sorted in ascending order. */
 static const apr_off_t magic[8] = {
   0, 1, 79, 80, 81, 5551, 5552, 5553
 };
@@ -110,59 +112,86 @@ static const apr_off_t power2[66] = {
 
 
 static svn_error_t *
-do_random_test(apr_uint32_t *seed,
-               const apr_off_t lengths[],
+do_random_test(const apr_off_t lengths[],
                const apr_size_t array_size,
                apr_pool_t *pool)
 {
-  const char *data = make_random_data(seed, lengths[array_size - 1], pool);
+  apr_uint32_t seed;
+  const apr_off_t length = lengths[array_size - 1];
+  const char *data = make_random_data(&seed, length, pool);
+
+  apr_uint32_t value_from_svn;
+  uLong value_from_zlib;
   int i;
 
   for (i = 0; i < array_size; ++i)
     {
-      apr_uint32_t value_from_svn = svn__adler32(0, data, lengths[i]);
-      uLong value_from_zlib = adler32(0, (const Bytef*)data, (uInt)lengths[i]);
-      SVN_TEST_ASSERT(value_from_svn == value_from_zlib);
+      /* This will blow up if the lengths array isn't sorted. */
+      SVN_TEST_ASSERT(lengths[i] <= length);
+
+      value_from_svn = svn__adler32(0, data, lengths[i]);
+      value_from_zlib = adler32(0, (const Bytef*)data, (uInt)lengths[i]);
+      if (value_from_svn != value_from_zlib)
+        {
+          fprintf(stderr, "SEED: %lu\n", (unsigned long)seed);
+          SVN_TEST_ASSERT(value_from_svn == value_from_zlib);
+        }
     }
 
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+test_magic_length(apr_pool_t *pool)
+{
+  return do_random_test(magic, sizeof(magic) / sizeof(magic[0]), pool);
+}
 
 static svn_error_t *
-test_random_magic(apr_pool_t *pool)
+test_prime_length(apr_pool_t *pool)
 {
-  apr_uint32_t seed;
-  svn_error_t *err = do_random_test(&seed, magic,
-                                    sizeof(magic) / sizeof(magic[0]),
-                                    pool);
-  if (err)
-    fprintf(stderr, "SEED: %lu\n", (unsigned long)seed);
-  return err;
+  return do_random_test(prime, sizeof(prime) / sizeof(prime[0]), pool);
 }
 
 static svn_error_t *
-test_random_prime(apr_pool_t *pool)
+test_power2_length(apr_pool_t *pool)
 {
-  apr_uint32_t seed;
-  svn_error_t *err = do_random_test(&seed, prime,
-                                    sizeof(prime) / sizeof(prime[0]),
-                                    pool);
-  if (err)
-    fprintf(stderr, "SEED: %lu\n", (unsigned long)seed);
-  return err;
+  return do_random_test(power2, sizeof(power2) / sizeof(power2[0]), pool);
 }
 
+
+/* Insert a static implementation of svn__adler32() with the maximum data
+   size set low enough that we can test the rarely used large-block branch
+   of the code without allocating too many terabytes of memory. */
+#define SVN__ADLER32_STATIC static
+#define svn__adler32 local_adler32
+#define SVN__ADLER32_SIZE_MAX (256U * 256U - 1U) /* 2^16 - 1 = 0xFFFF */
+#include "../../libsvn_subr/adler32.c"
+#undef svn__adler32
+#undef SVN__ADLER32_STATIC
+
 static svn_error_t *
-test_random_power2(apr_pool_t *pool)
+test_large_size(apr_pool_t *pool)
 {
   apr_uint32_t seed;
-  svn_error_t *err = do_random_test(&seed, power2,
-                                    sizeof(power2) / sizeof(power2[0]),
-                                    pool);
-  if (err)
-    fprintf(stderr, "SEED: %lu\n", (unsigned long)seed);
-  return err;
+  const svn__adler32_size_t length = 256 * 256 * 256; /* 2^24 = 16 MiB */
+  const char *data = make_random_data(&seed, length, pool);
+
+  apr_uint32_t value_from_svn;
+  uLong value_from_zlib;
+
+  SVN_TEST_ASSERT(length > 256 * SVN__ADLER32_SIZE_MAX);
+
+  value_from_svn = local_adler32(0, data, length);
+  value_from_zlib = svn__adler32_fn(0, data, length);
+
+  if (value_from_svn != value_from_zlib)
+    {
+      fprintf(stderr, "SEED: %lu\n", (unsigned long)seed);
+      SVN_TEST_ASSERT(value_from_svn == value_from_zlib);
+    }
+
+  return SVN_NO_ERROR;
 }
 
 
@@ -173,12 +202,14 @@ static int max_threads = 4;
 static struct svn_test_descriptor_t test_funcs[] =
   {
     SVN_TEST_NULL,
-    SVN_TEST_PASS2(test_random_magic,
-                   "adler32 random with magic length"),
-    SVN_TEST_PASS2(test_random_prime,
-                   "adler32 random with prime length"),
-    SVN_TEST_PASS2(test_random_power2,
-                   "adler32 random with 2^n length"),
+    SVN_TEST_PASS2(test_magic_length,
+                   "adler32 with magic length"),
+    SVN_TEST_PASS2(test_prime_length,
+                   "adler32 with prime length"),
+    SVN_TEST_PASS2(test_power2_length,
+                   "adler32 with 2^n length"),
+    SVN_TEST_PASS2(test_large_size,
+                   "adler32 with data size > block size"),
     SVN_TEST_NULL
   };
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.