]> git.ipfire.org Git - thirdparty/dbus.git/commitdiff
tests: Move _dbus_sha_test outside libdbus
authorSimon McVittie <smcv@collabora.com>
Wed, 3 Jul 2019 08:58:04 +0000 (09:58 +0100)
committerSimon McVittie <smcv@collabora.com>
Wed, 3 Jul 2019 10:18:49 +0000 (11:18 +0100)
Instead of exposing _dbus_sha_test() as a private exported symbol,
we can expose _dbus_sha_compute(), which is the only thing called by
the test that isn't already exported.

Signed-off-by: Simon McVittie <smcv@collabora.com>
dbus/dbus-sha.c
dbus/dbus-sha.h
dbus/dbus-test.h
test/CMakeLists.txt
test/Makefile.am
test/internals/misc-internals.h
test/internals/sha.c [new file with mode: 0644]

index bbe000d698085e496ee9f86f92133449582da1ae..6ff2f07721c37383b39bdcb131cd91698954b15c 100644 (file)
@@ -26,7 +26,6 @@
 #include "dbus-internals.h"
 #include "dbus-sha.h"
 #include "dbus-marshal-basic.h" /* for byteswap routines */
-#include <dbus/dbus-test-tap.h>
 #include <string.h>
 
 /* The following comments have the history of where this code
@@ -511,465 +510,3 @@ _dbus_sha_compute (const DBusString *data,
 }
 
 /** @} */ /* end of exported functions */
-
-#ifdef DBUS_ENABLE_EMBEDDED_TESTS
-#include "dbus-test.h"
-#include <stdio.h>
-
-static dbus_bool_t
-check_sha_binary (const unsigned char *input,
-                  int                  input_len,
-                  const char          *expected)
-{
-  DBusString input_str;
-  DBusString expected_str;
-  DBusString results;
-
-  _dbus_string_init_const_len (&input_str, (const char *) input, input_len);
-  _dbus_string_init_const (&expected_str, expected);
-
-  if (!_dbus_string_init (&results))
-    _dbus_test_fatal ("no memory for SHA-1 results");
-
-  if (!_dbus_sha_compute (&input_str, &results))
-    _dbus_test_fatal ("no memory for SHA-1 results");
-
-  if (!_dbus_string_equal (&expected_str, &results))
-    {
-      _dbus_warn ("Expected hash %s got %s for SHA-1 sum",
-                  expected,
-                  _dbus_string_get_const_data (&results));
-      _dbus_string_free (&results);
-      return FALSE;
-    }
-
-  _dbus_string_free (&results);
-  return TRUE;
-}
-
-static dbus_bool_t
-check_sha_str (const char *input,
-               const char *expected)
-{
-  return check_sha_binary ((unsigned char *) input, strlen (input), expected);
-}
-
-static dbus_bool_t
-decode_compact_string (const DBusString *line,
-                       DBusString       *decoded)
-{
-  int n_bits;
-  dbus_bool_t current_b;
-  int offset;
-  int next;
-  long val;
-  int length_bytes;
-  
-  offset = 0;
-  next = 0;
-
-  if (!_dbus_string_parse_int (line, offset, &val, &next))
-    {
-      fprintf (stderr, "could not parse length at start of compact string: %s\n",
-               _dbus_string_get_const_data (line));
-      return FALSE;
-    }
-
-  _dbus_string_skip_blank (line, next, &next);
-  
-  offset = next;
-  if (!_dbus_string_parse_int (line, offset, &val, &next))
-    {
-      fprintf (stderr, "could not parse start bit 'b' in compact string: %s\n",
-               _dbus_string_get_const_data (line));
-      return FALSE;
-    }
-  
-  if (!(val == 0 || val == 1))
-    {
-      fprintf (stderr, "the value 'b' must be 0 or 1, see sha-1/Readme.txt\n");
-      return FALSE;
-    }
-
-  _dbus_string_skip_blank (line, next, &next);
-  
-  current_b = val;
-  n_bits = 0;
-  
-  while (next < _dbus_string_get_length (line))
-    {
-      int total_bits;
-      
-      offset = next;
-
-      if (_dbus_string_get_byte (line, offset) == '^')
-        break;
-      
-      if (!_dbus_string_parse_int (line, offset, &val, &next))
-        {
-          fprintf (stderr, "could not parse bit count in compact string\n");
-          return FALSE;
-        }
-
-      /* We now append "val" copies of "current_b" bits to the string */
-      total_bits = n_bits + val;
-      while (n_bits < total_bits)
-        {
-          int byte_containing_next_bit = n_bits / 8;
-          int bit_containing_next_bit = 7 - (n_bits % 8);
-          unsigned char old_byte;
-          
-          if (byte_containing_next_bit >= _dbus_string_get_length (decoded))
-            {
-              if (!_dbus_string_set_length (decoded, byte_containing_next_bit + 1))
-                _dbus_test_fatal ("no memory to extend to next byte");
-            }
-
-          old_byte = _dbus_string_get_byte (decoded, byte_containing_next_bit);
-          old_byte |= current_b << bit_containing_next_bit;
-
-#if 0
-          _dbus_test_diag ("Appending bit %d to byte %d at bit %d resulting in byte 0x%x",
-                  current_b, byte_containing_next_bit,
-                  bit_containing_next_bit, old_byte);
-#endif
-          
-          _dbus_string_set_byte (decoded, byte_containing_next_bit, old_byte);
-          
-          ++n_bits;
-        }
-
-      _dbus_string_skip_blank (line, next, &next);
-          
-      current_b = !current_b;
-    }
-
-  length_bytes = (n_bits / 8 + ((n_bits % 8) ? 1 : 0));
-  
-  if (_dbus_string_get_length (decoded) != length_bytes)
-    {
-      fprintf (stderr, "Expected length %d bytes %d bits for compact string, got %d bytes\n",
-               length_bytes, n_bits, _dbus_string_get_length (decoded));
-      return FALSE;
-    }
-  else
-    return TRUE;
-}
-
-static dbus_bool_t
-get_next_expected_result (DBusString *results,
-                          DBusString *result)
-{
-  DBusString line;
-  dbus_bool_t retval;
-
-  retval = FALSE;
-  
-  if (!_dbus_string_init (&line))
-    _dbus_test_fatal ("no memory");
-  
- next_iteration:
-  while (_dbus_string_pop_line (results, &line))
-    {
-      _dbus_string_delete_leading_blanks (&line);
-
-      if (_dbus_string_get_length (&line) == 0)
-        goto next_iteration;
-      else if (_dbus_string_starts_with_c_str (&line, "#"))
-        goto next_iteration;
-      else if (_dbus_string_starts_with_c_str (&line, "H>"))
-        {
-          /* don't print */
-        }
-      else if (_dbus_string_starts_with_c_str (&line, "D>") ||
-               _dbus_string_starts_with_c_str (&line, "<D"))
-        goto next_iteration;
-      else
-        {
-          int i;
-          
-          if (!_dbus_string_move (&line, 0, result, 0))
-            _dbus_test_fatal ("no memory");
-
-          i = 0;
-          while (i < _dbus_string_get_length (result))
-            {
-              unsigned char c = _dbus_string_get_byte (result, i);
-
-              switch (c)
-                {
-                case 'A':
-                  _dbus_string_set_byte (result, i, 'a');
-                  break;
-                case 'B':
-                  _dbus_string_set_byte (result, i, 'b');
-                  break;
-                case 'C':
-                  _dbus_string_set_byte (result, i, 'c');
-                  break;
-                case 'D':
-                  _dbus_string_set_byte (result, i, 'd');
-                  break;
-                case 'E':
-                  _dbus_string_set_byte (result, i, 'e');
-                  break;
-                case 'F':
-                  _dbus_string_set_byte (result, i, 'f');
-                  break;
-                case '^':
-                case ' ':
-                  _dbus_string_delete (result, i, 1);
-                  --i; /* to offset ++i below */
-                  break;
-                default:
-                  if ((c < '0' || c > '9') && (c < 'a' || c > 'f'))
-                    _dbus_test_fatal ("invalid SHA-1 test script");
-                }
-
-              ++i;
-            }
-          
-          break;
-        }
-    }
-  
-  retval = TRUE;
-  
-  /* out: */
-  _dbus_string_free (&line);
-  return retval;
-}
-
-static dbus_bool_t
-process_test_data (const char *test_data_dir)
-{
-  DBusString tests_file;
-  DBusString results_file;
-  DBusString tests;
-  DBusString results;
-  DBusString line;
-  DBusString tmp;
-  int line_no;
-  dbus_bool_t retval;
-  int success_count;
-  DBusError error = DBUS_ERROR_INIT;
-
-  retval = FALSE;
-  
-  if (!_dbus_string_init (&tests_file))
-    _dbus_test_fatal ("no memory");
-
-  if (!_dbus_string_init (&results_file))
-    _dbus_test_fatal ("no memory");
-
-  if (!_dbus_string_init (&tests))
-    _dbus_test_fatal ("no memory");
-
-  if (!_dbus_string_init (&results))
-    _dbus_test_fatal ("no memory");
-
-  if (!_dbus_string_init (&line))
-    _dbus_test_fatal ("no memory");
-
-  if (!_dbus_string_append (&tests_file, test_data_dir))
-    _dbus_test_fatal ("no memory");
-
-  if (!_dbus_string_append (&results_file, test_data_dir))
-    _dbus_test_fatal ("no memory");
-
-  _dbus_string_init_const (&tmp, "sha-1/byte-messages.sha1");
-  if (!_dbus_concat_dir_and_file (&tests_file, &tmp))
-    _dbus_test_fatal ("no memory");
-
-  _dbus_string_init_const (&tmp, "sha-1/byte-hashes.sha1");
-  if (!_dbus_concat_dir_and_file (&results_file, &tmp))
-    _dbus_test_fatal ("no memory");
-
-  if (!_dbus_file_get_contents (&tests, &tests_file, &error))
-    {
-      fprintf (stderr, "could not load test data file %s: %s\n",
-               _dbus_string_get_const_data (&tests_file),
-               error.message);
-      dbus_error_free (&error);
-      goto out;
-    }
-
-  if (!_dbus_file_get_contents (&results, &results_file, &error))
-    {
-      fprintf (stderr, "could not load results data file %s: %s\n",
-               _dbus_string_get_const_data (&results_file), error.message);
-      dbus_error_free (&error);
-      goto out;
-    }
-
-  success_count = 0;
-  line_no = 0;
- next_iteration:
-  while (_dbus_string_pop_line (&tests, &line))
-    {
-      line_no += 1;
-
-      _dbus_string_delete_leading_blanks (&line);
-
-      if (_dbus_string_get_length (&line) == 0)
-        goto next_iteration;
-      else if (_dbus_string_starts_with_c_str (&line, "#"))
-        goto next_iteration;
-      else if (_dbus_string_starts_with_c_str (&line, "H>"))
-        {
-          _dbus_test_diag ("SHA-1: %s", _dbus_string_get_const_data (&line));
-
-          if (_dbus_string_find (&line, 0, "Type 3", NULL))
-            {
-              /* See sha-1/Readme.txt - the "Type 3" tests are
-               * random seeds, rather than data to be hashed.
-               * we'd have to do a little bit more implementation
-               * to use those tests.
-               */
-              
-              _dbus_test_diag (" (ending tests due to Type 3 tests seen - this is normal)");
-              break;
-            }
-        }
-      else if (_dbus_string_starts_with_c_str (&line, "D>") ||
-               _dbus_string_starts_with_c_str (&line, "<D"))
-        goto next_iteration;
-      else
-        {
-          DBusString test;
-          DBusString result;
-          DBusString next_line;
-          DBusString expected;
-          dbus_bool_t success;
-
-          success = FALSE;
-          
-          if (!_dbus_string_init (&next_line))
-            _dbus_test_fatal ("no memory");
-
-          if (!_dbus_string_init (&expected))
-            _dbus_test_fatal ("no memory");
-          
-          if (!_dbus_string_init (&test))
-            _dbus_test_fatal ("no memory");
-
-          if (!_dbus_string_init (&result))
-            _dbus_test_fatal ("no memory");
-
-          /* the "compact strings" are "^"-terminated not
-           * newline-terminated so readahead to find the
-           * "^"
-           */
-          while (!_dbus_string_find (&line, 0, "^", NULL) &&
-                 _dbus_string_pop_line (&tests, &next_line))
-            {
-              if (!_dbus_string_append_byte (&line, ' ') ||
-                  !_dbus_string_move (&next_line, 0, &line,
-                                      _dbus_string_get_length (&line)))
-                _dbus_test_fatal ("no memory");
-            }
-          
-          if (!decode_compact_string (&line, &test))
-            {
-              fprintf (stderr, "Failed to decode line %d as a compact string\n",
-                       line_no);
-              goto failure;
-            }
-          
-          if (!_dbus_sha_compute (&test, &result))
-            _dbus_test_fatal ("no memory for SHA-1 result");
-
-          if (!get_next_expected_result (&results, &expected))
-            {
-              fprintf (stderr, "Failed to read an expected result\n");
-              goto failure;
-            }
-          
-          if (!_dbus_string_equal (&result, &expected))
-            {              
-              fprintf (stderr, " for line %d got hash %s expected %s\n",
-                       line_no,
-                       _dbus_string_get_const_data (&result),
-                       _dbus_string_get_const_data (&expected));
-              goto failure;
-            }
-          else
-            {
-              success_count += 1;
-            }
-
-          success = TRUE;
-
-        failure:
-          _dbus_string_free (&test);
-          _dbus_string_free (&result);
-          _dbus_string_free (&next_line);
-          _dbus_string_free (&expected);
-
-          if (!success)
-            goto out;
-        }
-    }
-
-  retval = TRUE;
-
-  _dbus_test_diag ("Passed the %d SHA-1 tests in the test file",
-          success_count);
-  
- out:
-  _dbus_string_free (&tests_file);
-  _dbus_string_free (&results_file);
-  _dbus_string_free (&tests);
-  _dbus_string_free (&results);
-  _dbus_string_free (&line);
-
-  return retval;
-}
-
-/**
- * @ingroup DBusSHAInternals
- * Unit test for SHA computation.
- *
- * @returns #TRUE on success.
- */
-dbus_bool_t
-_dbus_sha_test (const char *test_data_dir)
-{
-  unsigned char all_bytes[256];
-  int i;
-
-  if (test_data_dir != NULL)
-    {
-      if (!process_test_data (test_data_dir))
-        return FALSE;
-    }
-  else
-    _dbus_test_diag ("No test data dir");
-  
-  i = 0;
-  while (i < 256)
-    {
-      all_bytes[i] = i;
-      ++i;
-    }
-
-  if (!check_sha_binary (all_bytes, 256,
-                         "4916d6bdb7f78e6803698cab32d1586ea457dfc8"))
-    return FALSE;
-
-#define CHECK(input,expected) if (!check_sha_str (input, expected)) return FALSE
-
-  CHECK ("", "da39a3ee5e6b4b0d3255bfef95601890afd80709");
-  CHECK ("a", "86f7e437faa5a7fce15d1ddcb9eaeaea377667b8");
-  CHECK ("abc", "a9993e364706816aba3e25717850c26c9cd0d89d");
-  CHECK ("message digest", "c12252ceda8be8994d5fa0290a47231c1d16aae3");
-  CHECK ("abcdefghijklmnopqrstuvwxyz", "32d10c7b8cf96570ca04ce37f2a19d84240d3a89");
-  CHECK ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
-         "761c457bf73b14d27e9e9265c46f4b4dda11f940");
-  CHECK ("12345678901234567890123456789012345678901234567890123456789012345678901234567890",
-         "50abf5706a150990a08b2c5ea40fa0e585554732");
-
-  return TRUE;
-}
-
-#endif /* DBUS_ENABLE_EMBEDDED_TESTS */
index c48035b99390cf5c9e962819e1337ff2e30c6c98..988cd5a9d71b6906ef6a0036204f30c72b7f4679 100644 (file)
@@ -47,6 +47,7 @@ void        _dbus_sha_update  (DBusSHAContext   *context,
                                const DBusString *data);
 dbus_bool_t _dbus_sha_final   (DBusSHAContext   *context,
                                DBusString       *results);
+DBUS_EMBEDDED_TESTS_EXPORT
 dbus_bool_t _dbus_sha_compute (const DBusString *data,
                                DBusString       *ascii_output);
 
index 197e0dc7aa7826cf5450200d8823517b75897ee4..804b5a705bb04b56db5a49129e034c9404fc4116 100644 (file)
@@ -46,9 +46,6 @@ dbus_bool_t _dbus_mem_pool_test          (const char *test_data_dir);
 DBUS_PRIVATE_EXPORT
 dbus_bool_t _dbus_address_test           (const char *test_data_dir);
 
-DBUS_PRIVATE_EXPORT
-dbus_bool_t _dbus_sha_test               (const char *test_data_dir);
-
 DBUS_PRIVATE_EXPORT
 dbus_bool_t _dbus_keyring_test           (const char *test_data_dir);
 
index 2b8db2f6aa3fd0599e9205770f25e9b3026faf01..554500485a3d89c52f9ae36337c87e60c40fec52 100644 (file)
@@ -128,6 +128,7 @@ if(DBUS_ENABLE_EMBEDDED_TESTS)
         internals/dbus-sysdeps-util.c
         internals/misc-internals.c
         internals/misc-internals.h
+        internals/sha.c
     )
     add_test_executable(test-misc-internals "${SOURCES}" dbus-testutils)
     set_target_properties(test-misc-internals PROPERTIES COMPILE_FLAGS ${DBUS_INTERNAL_CLIENT_DEFINITIONS})
index 8f14ae18b37bbf524274526dd17bee9744fc5692..e29c954e5e30effb21b504b17d1f4c077b4fb7d8 100644 (file)
@@ -249,6 +249,7 @@ test_misc_internals_SOURCES = \
        internals/dbus-sysdeps-util.c \
        internals/misc-internals.c \
        internals/misc-internals.h \
+       internals/sha.c \
        $(NULL)
 test_misc_internals_LDADD = libdbus-testutils.la
 
index 700af46e77e36cd73d56a00ef3510718b8cef082..47e85aae2b5979ddca888dc30f514d4d2d5a488e 100644 (file)
@@ -32,5 +32,6 @@ dbus_bool_t _dbus_marshal_byteswap_test  (const char *test_data_dir);
 dbus_bool_t _dbus_marshal_validate_test  (const char *test_data_dir);
 dbus_bool_t _dbus_string_test            (const char *test_data_dir);
 dbus_bool_t _dbus_sysdeps_test           (const char *test_data_dir);
+dbus_bool_t _dbus_sha_test               (const char *test_data_dir);
 
 #endif
diff --git a/test/internals/sha.c b/test/internals/sha.c
new file mode 100644 (file)
index 0000000..b6f93ca
--- /dev/null
@@ -0,0 +1,491 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-sha.c SHA-1 implementation
+ *
+ * Copyright (C) 2003 Red Hat Inc.
+ * Copyright (C) 1995 A. M. Kuchling
+ * Copyright (C) 2017 Thomas Zimmermann
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <config.h>
+#include "misc-internals.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include <dbus/dbus-internals.h>
+#include <dbus/dbus-sha.h>
+#include <dbus/dbus-test-tap.h>
+#include <dbus/dbus-test.h>
+
+static dbus_bool_t
+check_sha_binary (const unsigned char *input,
+                  int                  input_len,
+                  const char          *expected)
+{
+  DBusString input_str;
+  DBusString expected_str;
+  DBusString results;
+
+  _dbus_string_init_const_len (&input_str, (const char *) input, input_len);
+  _dbus_string_init_const (&expected_str, expected);
+
+  if (!_dbus_string_init (&results))
+    _dbus_test_fatal ("no memory for SHA-1 results");
+
+  if (!_dbus_sha_compute (&input_str, &results))
+    _dbus_test_fatal ("no memory for SHA-1 results");
+
+  if (!_dbus_string_equal (&expected_str, &results))
+    {
+      _dbus_warn ("Expected hash %s got %s for SHA-1 sum",
+                  expected,
+                  _dbus_string_get_const_data (&results));
+      _dbus_string_free (&results);
+      return FALSE;
+    }
+
+  _dbus_string_free (&results);
+  return TRUE;
+}
+
+static dbus_bool_t
+check_sha_str (const char *input,
+               const char *expected)
+{
+  return check_sha_binary ((unsigned char *) input, strlen (input), expected);
+}
+
+static dbus_bool_t
+decode_compact_string (const DBusString *line,
+                       DBusString       *decoded)
+{
+  int n_bits;
+  dbus_bool_t current_b;
+  int offset;
+  int next;
+  long val;
+  int length_bytes;
+
+  offset = 0;
+  next = 0;
+
+  if (!_dbus_string_parse_int (line, offset, &val, &next))
+    {
+      fprintf (stderr, "could not parse length at start of compact string: %s\n",
+               _dbus_string_get_const_data (line));
+      return FALSE;
+    }
+
+  _dbus_string_skip_blank (line, next, &next);
+
+  offset = next;
+  if (!_dbus_string_parse_int (line, offset, &val, &next))
+    {
+      fprintf (stderr, "could not parse start bit 'b' in compact string: %s\n",
+               _dbus_string_get_const_data (line));
+      return FALSE;
+    }
+
+  if (!(val == 0 || val == 1))
+    {
+      fprintf (stderr, "the value 'b' must be 0 or 1, see sha-1/Readme.txt\n");
+      return FALSE;
+    }
+
+  _dbus_string_skip_blank (line, next, &next);
+
+  current_b = val;
+  n_bits = 0;
+
+  while (next < _dbus_string_get_length (line))
+    {
+      int total_bits;
+
+      offset = next;
+
+      if (_dbus_string_get_byte (line, offset) == '^')
+        break;
+
+      if (!_dbus_string_parse_int (line, offset, &val, &next))
+        {
+          fprintf (stderr, "could not parse bit count in compact string\n");
+          return FALSE;
+        }
+
+      /* We now append "val" copies of "current_b" bits to the string */
+      total_bits = n_bits + val;
+      while (n_bits < total_bits)
+        {
+          int byte_containing_next_bit = n_bits / 8;
+          int bit_containing_next_bit = 7 - (n_bits % 8);
+          unsigned char old_byte;
+
+          if (byte_containing_next_bit >= _dbus_string_get_length (decoded))
+            {
+              if (!_dbus_string_set_length (decoded, byte_containing_next_bit + 1))
+                _dbus_test_fatal ("no memory to extend to next byte");
+            }
+
+          old_byte = _dbus_string_get_byte (decoded, byte_containing_next_bit);
+          old_byte |= current_b << bit_containing_next_bit;
+
+#if 0
+          _dbus_test_diag ("Appending bit %d to byte %d at bit %d resulting in byte 0x%x",
+                  current_b, byte_containing_next_bit,
+                  bit_containing_next_bit, old_byte);
+#endif
+
+          _dbus_string_set_byte (decoded, byte_containing_next_bit, old_byte);
+
+          ++n_bits;
+        }
+
+      _dbus_string_skip_blank (line, next, &next);
+
+      current_b = !current_b;
+    }
+
+  length_bytes = (n_bits / 8 + ((n_bits % 8) ? 1 : 0));
+
+  if (_dbus_string_get_length (decoded) != length_bytes)
+    {
+      fprintf (stderr, "Expected length %d bytes %d bits for compact string, got %d bytes\n",
+               length_bytes, n_bits, _dbus_string_get_length (decoded));
+      return FALSE;
+    }
+  else
+    return TRUE;
+}
+
+static dbus_bool_t
+get_next_expected_result (DBusString *results,
+                          DBusString *result)
+{
+  DBusString line;
+  dbus_bool_t retval;
+
+  retval = FALSE;
+
+  if (!_dbus_string_init (&line))
+    _dbus_test_fatal ("no memory");
+
+ next_iteration:
+  while (_dbus_string_pop_line (results, &line))
+    {
+      _dbus_string_delete_leading_blanks (&line);
+
+      if (_dbus_string_get_length (&line) == 0)
+        goto next_iteration;
+      else if (_dbus_string_starts_with_c_str (&line, "#"))
+        goto next_iteration;
+      else if (_dbus_string_starts_with_c_str (&line, "H>"))
+        {
+          /* don't print */
+        }
+      else if (_dbus_string_starts_with_c_str (&line, "D>") ||
+               _dbus_string_starts_with_c_str (&line, "<D"))
+        goto next_iteration;
+      else
+        {
+          int i;
+
+          if (!_dbus_string_move (&line, 0, result, 0))
+            _dbus_test_fatal ("no memory");
+
+          i = 0;
+          while (i < _dbus_string_get_length (result))
+            {
+              unsigned char c = _dbus_string_get_byte (result, i);
+
+              switch (c)
+                {
+                case 'A':
+                  _dbus_string_set_byte (result, i, 'a');
+                  break;
+                case 'B':
+                  _dbus_string_set_byte (result, i, 'b');
+                  break;
+                case 'C':
+                  _dbus_string_set_byte (result, i, 'c');
+                  break;
+                case 'D':
+                  _dbus_string_set_byte (result, i, 'd');
+                  break;
+                case 'E':
+                  _dbus_string_set_byte (result, i, 'e');
+                  break;
+                case 'F':
+                  _dbus_string_set_byte (result, i, 'f');
+                  break;
+                case '^':
+                case ' ':
+                  _dbus_string_delete (result, i, 1);
+                  --i; /* to offset ++i below */
+                  break;
+                default:
+                  if ((c < '0' || c > '9') && (c < 'a' || c > 'f'))
+                    _dbus_test_fatal ("invalid SHA-1 test script");
+                }
+
+              ++i;
+            }
+
+          break;
+        }
+    }
+
+  retval = TRUE;
+
+  /* out: */
+  _dbus_string_free (&line);
+  return retval;
+}
+
+static dbus_bool_t
+process_test_data (const char *test_data_dir)
+{
+  DBusString tests_file;
+  DBusString results_file;
+  DBusString tests;
+  DBusString results;
+  DBusString line;
+  DBusString tmp;
+  int line_no;
+  dbus_bool_t retval;
+  int success_count;
+  DBusError error = DBUS_ERROR_INIT;
+
+  retval = FALSE;
+
+  if (!_dbus_string_init (&tests_file))
+    _dbus_test_fatal ("no memory");
+
+  if (!_dbus_string_init (&results_file))
+    _dbus_test_fatal ("no memory");
+
+  if (!_dbus_string_init (&tests))
+    _dbus_test_fatal ("no memory");
+
+  if (!_dbus_string_init (&results))
+    _dbus_test_fatal ("no memory");
+
+  if (!_dbus_string_init (&line))
+    _dbus_test_fatal ("no memory");
+
+  if (!_dbus_string_append (&tests_file, test_data_dir))
+    _dbus_test_fatal ("no memory");
+
+  if (!_dbus_string_append (&results_file, test_data_dir))
+    _dbus_test_fatal ("no memory");
+
+  _dbus_string_init_const (&tmp, "sha-1/byte-messages.sha1");
+  if (!_dbus_concat_dir_and_file (&tests_file, &tmp))
+    _dbus_test_fatal ("no memory");
+
+  _dbus_string_init_const (&tmp, "sha-1/byte-hashes.sha1");
+  if (!_dbus_concat_dir_and_file (&results_file, &tmp))
+    _dbus_test_fatal ("no memory");
+
+  if (!_dbus_file_get_contents (&tests, &tests_file, &error))
+    {
+      fprintf (stderr, "could not load test data file %s: %s\n",
+               _dbus_string_get_const_data (&tests_file),
+               error.message);
+      dbus_error_free (&error);
+      goto out;
+    }
+
+  if (!_dbus_file_get_contents (&results, &results_file, &error))
+    {
+      fprintf (stderr, "could not load results data file %s: %s\n",
+               _dbus_string_get_const_data (&results_file), error.message);
+      dbus_error_free (&error);
+      goto out;
+    }
+
+  success_count = 0;
+  line_no = 0;
+ next_iteration:
+  while (_dbus_string_pop_line (&tests, &line))
+    {
+      line_no += 1;
+
+      _dbus_string_delete_leading_blanks (&line);
+
+      if (_dbus_string_get_length (&line) == 0)
+        goto next_iteration;
+      else if (_dbus_string_starts_with_c_str (&line, "#"))
+        goto next_iteration;
+      else if (_dbus_string_starts_with_c_str (&line, "H>"))
+        {
+          _dbus_test_diag ("SHA-1: %s", _dbus_string_get_const_data (&line));
+
+          if (_dbus_string_find (&line, 0, "Type 3", NULL))
+            {
+              /* See sha-1/Readme.txt - the "Type 3" tests are
+               * random seeds, rather than data to be hashed.
+               * we'd have to do a little bit more implementation
+               * to use those tests.
+               */
+
+              _dbus_test_diag (" (ending tests due to Type 3 tests seen - this is normal)");
+              break;
+            }
+        }
+      else if (_dbus_string_starts_with_c_str (&line, "D>") ||
+               _dbus_string_starts_with_c_str (&line, "<D"))
+        goto next_iteration;
+      else
+        {
+          DBusString test;
+          DBusString result;
+          DBusString next_line;
+          DBusString expected;
+          dbus_bool_t success;
+
+          success = FALSE;
+
+          if (!_dbus_string_init (&next_line))
+            _dbus_test_fatal ("no memory");
+
+          if (!_dbus_string_init (&expected))
+            _dbus_test_fatal ("no memory");
+
+          if (!_dbus_string_init (&test))
+            _dbus_test_fatal ("no memory");
+
+          if (!_dbus_string_init (&result))
+            _dbus_test_fatal ("no memory");
+
+          /* the "compact strings" are "^"-terminated not
+           * newline-terminated so readahead to find the
+           * "^"
+           */
+          while (!_dbus_string_find (&line, 0, "^", NULL) &&
+                 _dbus_string_pop_line (&tests, &next_line))
+            {
+              if (!_dbus_string_append_byte (&line, ' ') ||
+                  !_dbus_string_move (&next_line, 0, &line,
+                                      _dbus_string_get_length (&line)))
+                _dbus_test_fatal ("no memory");
+            }
+
+          if (!decode_compact_string (&line, &test))
+            {
+              fprintf (stderr, "Failed to decode line %d as a compact string\n",
+                       line_no);
+              goto failure;
+            }
+
+          if (!_dbus_sha_compute (&test, &result))
+            _dbus_test_fatal ("no memory for SHA-1 result");
+
+          if (!get_next_expected_result (&results, &expected))
+            {
+              fprintf (stderr, "Failed to read an expected result\n");
+              goto failure;
+            }
+
+          if (!_dbus_string_equal (&result, &expected))
+            {
+              fprintf (stderr, " for line %d got hash %s expected %s\n",
+                       line_no,
+                       _dbus_string_get_const_data (&result),
+                       _dbus_string_get_const_data (&expected));
+              goto failure;
+            }
+          else
+            {
+              success_count += 1;
+            }
+
+          success = TRUE;
+
+        failure:
+          _dbus_string_free (&test);
+          _dbus_string_free (&result);
+          _dbus_string_free (&next_line);
+          _dbus_string_free (&expected);
+
+          if (!success)
+            goto out;
+        }
+    }
+
+  retval = TRUE;
+
+  _dbus_test_diag ("Passed the %d SHA-1 tests in the test file",
+          success_count);
+
+ out:
+  _dbus_string_free (&tests_file);
+  _dbus_string_free (&results_file);
+  _dbus_string_free (&tests);
+  _dbus_string_free (&results);
+  _dbus_string_free (&line);
+
+  return retval;
+}
+
+/**
+ * @ingroup DBusSHAInternals
+ * Unit test for SHA computation.
+ *
+ * @returns #TRUE on success.
+ */
+dbus_bool_t
+_dbus_sha_test (const char *test_data_dir)
+{
+  unsigned char all_bytes[256];
+  int i;
+
+  if (test_data_dir != NULL)
+    {
+      if (!process_test_data (test_data_dir))
+        return FALSE;
+    }
+  else
+    _dbus_test_diag ("No test data dir");
+
+  i = 0;
+  while (i < 256)
+    {
+      all_bytes[i] = i;
+      ++i;
+    }
+
+  if (!check_sha_binary (all_bytes, 256,
+                         "4916d6bdb7f78e6803698cab32d1586ea457dfc8"))
+    return FALSE;
+
+#define CHECK(input,expected) if (!check_sha_str (input, expected)) return FALSE
+
+  CHECK ("", "da39a3ee5e6b4b0d3255bfef95601890afd80709");
+  CHECK ("a", "86f7e437faa5a7fce15d1ddcb9eaeaea377667b8");
+  CHECK ("abc", "a9993e364706816aba3e25717850c26c9cd0d89d");
+  CHECK ("message digest", "c12252ceda8be8994d5fa0290a47231c1d16aae3");
+  CHECK ("abcdefghijklmnopqrstuvwxyz", "32d10c7b8cf96570ca04ce37f2a19d84240d3a89");
+  CHECK ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
+         "761c457bf73b14d27e9e9265c46f4b4dda11f940");
+  CHECK ("12345678901234567890123456789012345678901234567890123456789012345678901234567890",
+         "50abf5706a150990a08b2c5ea40fa0e585554732");
+
+  return TRUE;
+}