Logo Search packages:      
Sourcecode: zeromq version File versions  Download package

checksum_unittest.c

/* vim:ts=8:sts=8:sw=4:noai:noexpandtab
 *
 * unit tests for PGM checksum routines
 *
 * Copyright (c) 2009 Miru Limited.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */


#include <signal.h>
#include <stdlib.h>
#include <glib.h>
#include <check.h>


/* mock state */


/* mock functions for external references */


#define CHECKSUM_DEBUG
#include "checksum.c"


/* target:
 *    guint16
 *    pgm_inet_checksum (
 *          const void*       src,
 *          guint             len,
 *          int               csum
 *    )
 */

START_TEST (test_inet_pass_001)
{
      const char source[]  = "i am not a string";
      const guint16 answer = 0x1fda;            /* network order */

      guint16 csum = pgm_inet_checksum (source, sizeof(source), 0);
/* function calculates answer in host order */
      csum = g_htons (csum);
      g_message ("IP checksum of \"%s\" (%d) is %u (%u)",
            source, sizeof(source), csum, answer);

      fail_unless (answer == csum, "checksum mismatch");
}
END_TEST

START_TEST (test_inet_pass_002)
{
      char* source = alloca (65535);
      for (unsigned i = 0, j = 0; i < 65535; i++) {
            j = j * 1103515245 + 12345;
            source[i] = j;
      }
      const guint16 answer = 0x3fc0;            /* network order */

      guint16 csum = pgm_inet_checksum (source, 65535, 0);
/* function calculates answer in host order */
      csum = g_htons (csum);
      g_message ("IP checksum of 64KB is %u (%u)",
            csum, answer);

      fail_unless (answer == csum, "checksum mismatch");
}
END_TEST

START_TEST (test_inet_fail_001)
{
      pgm_inet_checksum (NULL, 0, 0);
      fail ("reached");
}
END_TEST

/* target:
 *    guint16
 *    pgm_csum_fold (
 *          guint32                 csum
 *    )
 */

START_TEST (test_fold_pass_001)
{
      const guint32 csum   = 0xdd250300;  /* network order */
      const guint16 answer = 0x1fda;

      guint16 folded_csum = pgm_csum_fold (g_ntohl (csum));
      folded_csum = g_htons (folded_csum);
      g_message ("32-bit checksum %u folds into %u (%u)", csum, folded_csum, answer);

      fail_unless (answer == folded_csum, "folded checksum mismatch");
}
END_TEST


/* target:
 *    guint32
 *    pgm_csum_partial (
 *          const void*       src,
 *          guint             len,
 *          guint32                 sum
 *    )
 */

START_TEST (test_partial_pass_001)
{
      const char source[]  = "i am not a string";
#if __BYTE_ORDER == __BIG_ENDIAN
      const guint32 answer = 0x0000e025;  /* network order */
#elif __BYTE_ORDER == __LITTLE_ENDIAN
      const guint32 answer = 0xe0250000;  /* network order */
#else
#     error "__BYTE_ORDER not supported."
#endif

      guint32 csum = pgm_csum_partial (source, sizeof(source), 0);
      csum = g_htonl (csum);
      g_message ("Partial checksum of \"%s\" is %u (%u)", source, csum, answer);

      fail_unless (answer == csum, "checksum mismatch");
}
END_TEST

START_TEST (test_partial_fail_001)
{
      pgm_csum_partial (NULL, 0, 0);
      fail ("reached");
}
END_TEST

/* target:
 *    guint32
 *    pgm_csum_partial_copy (
 *          const void*       src,
 *          void*             dst,
 *          guint             len,
 *          guint32                 sum
 *    )
 */

START_TEST (test_partial_copy_pass_001)
{
      const char source[] = "i am not a string";
#if __BYTE_ORDER == __BIG_ENDIAN
      const guint32 answer = 0x0000e025;  /* network order */
#elif __BYTE_ORDER == __LITTLE_ENDIAN
      const guint32 answer = 0xe0250000;  /* network order */
#else
#     error "__BYTE_ORDER not supported."
#endif

      char dest[1024];
      guint32 csum_source = pgm_csum_partial_copy (source, dest, sizeof(source), 0);
      csum_source = g_htonl (csum_source);
      guint32 csum_dest   = pgm_csum_partial (dest, sizeof(source), 0);
      csum_dest = g_htonl (csum_dest);
      g_message ("Partial copy checksum of \"%s\" is %u, partial checksum is %u (%u)",
               source, csum_source, csum_dest, answer);
      fail_unless (answer == csum_source, "checksum mismatch in partial-copy");
      fail_unless (answer == csum_dest,   "checksum mismatch in partial");
}
END_TEST

START_TEST (test_partial_copy_fail_001)
{
      pgm_csum_partial_copy (NULL, NULL, 0, 0);
      fail ("reached");
}
END_TEST

/* target:
 *    guint32
 *    pgm_csum_block_add (
 *          guint32                 csum,
 *          guint32                 csum2,
 *          guint             offset
 *    )
 */

START_TEST (test_block_add_pass_001)
{
      const char source[] = "i am not a string";
      const guint16 answer = 0x1fda;            /* network order */

      guint32 csum_a = pgm_csum_partial (source, sizeof(source) / 2, 0);
      guint32 csum_b = pgm_csum_partial (source + (sizeof(source) / 2), sizeof(source) - (sizeof(source) / 2), 0);
      guint32 csum   = pgm_csum_block_add (csum_a, csum_b, sizeof(source) / 2);
      guint16 fold   = pgm_csum_fold (csum);
/* convert to display in network order */
      csum_a = g_htonl (csum_a);
      csum_b = g_htonl (csum_b);
      csum   = g_htonl (csum);
      fold   = g_htons (fold);
      g_message ("Checksum A:%u + B:%u = %u -> %u (%u)",
               csum_a, csum_b, csum, fold, answer);
      fail_unless (answer == fold, "checksum mismatch");
}
END_TEST


static
Suite*
make_test_suite (void)
{
      Suite* s;

      s = suite_create (__FILE__);

      TCase* tc_inet = tcase_create ("inet");
      suite_add_tcase (s, tc_inet);
      tcase_add_test (tc_inet, test_inet_pass_001);
      tcase_add_test (tc_inet, test_inet_pass_002);
      tcase_add_test_raise_signal (tc_inet, test_inet_fail_001, SIGABRT);

      TCase* tc_fold = tcase_create ("fold");
      suite_add_tcase (s, tc_fold);
      tcase_add_test (tc_fold, test_fold_pass_001);

      TCase* tc_block_add = tcase_create ("block-add");
      suite_add_tcase (s, tc_block_add);
      tcase_add_test (tc_block_add, test_block_add_pass_001);

      TCase* tc_partial = tcase_create ("partial");
      suite_add_tcase (s, tc_partial);
      tcase_add_test (tc_partial, test_partial_pass_001);
      tcase_add_test_raise_signal (tc_partial, test_partial_fail_001, SIGABRT);

      TCase* tc_partial_copy = tcase_create ("partial-copy");
      suite_add_tcase (s, tc_partial_copy);
      tcase_add_test (tc_partial_copy, test_partial_copy_pass_001);
      tcase_add_test_raise_signal (tc_partial_copy, test_partial_copy_fail_001, SIGABRT);
      return s;
}

static
Suite*
make_master_suite (void)
{
      Suite* s = suite_create ("Master");
      return s;
}

int
main (void)
{
      SRunner* sr = srunner_create (make_master_suite ());
      srunner_add_suite (sr, make_test_suite ());
      srunner_run_all (sr, CK_ENV);
      int number_failed = srunner_ntests_failed (sr);
      srunner_free (sr);
      return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
}

/* eof */

Generated by  Doxygen 1.6.0   Back to index