summaryrefslogtreecommitdiffstats
path: root/3rdparty/openpgm-svn-r1085/pgm/checksum_unittest.c
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/openpgm-svn-r1085/pgm/checksum_unittest.c')
-rw-r--r--3rdparty/openpgm-svn-r1085/pgm/checksum_unittest.c278
1 files changed, 278 insertions, 0 deletions
diff --git a/3rdparty/openpgm-svn-r1085/pgm/checksum_unittest.c b/3rdparty/openpgm-svn-r1085/pgm/checksum_unittest.c
new file mode 100644
index 0000000..a25d36a
--- /dev/null
+++ b/3rdparty/openpgm-svn-r1085/pgm/checksum_unittest.c
@@ -0,0 +1,278 @@
+/* vim:ts=8:sts=8:sw=4:noai:noexpandtab
+ *
+ * unit tests for PGM checksum routines
+ *
+ * Copyright (c) 2009-2010 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 <stdbool.h>
+#include <stdlib.h>
+#include <glib.h>
+#include <check.h>
+
+
+/* mock state */
+
+
+/* mock functions for external references */
+
+size_t
+pgm_transport_pkt_offset2 (
+ const bool can_fragment,
+ const bool use_pgmcc
+ )
+{
+ return 0;
+}
+
+
+#define CHECKSUM_DEBUG
+#include "checksum.c"
+
+
+/* target:
+ * uint16_t
+ * pgm_inet_checksum (
+ * const void* src,
+ * uint16_t len,
+ * uint16_t 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 */