diff options
Diffstat (limited to '3rdparty/openpgm-svn-r1085/pgm/checksum_unittest.c')
-rw-r--r-- | 3rdparty/openpgm-svn-r1085/pgm/checksum_unittest.c | 278 |
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 */ |