diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/Makefile.am | 13 | ||||
-rw-r--r-- | tests/aspath_test.c | 269 | ||||
-rw-r--r-- | tests/bgp_capability_test.c | 145 | ||||
-rw-r--r-- | tests/bgp_mp_attr_test.c | 139 | ||||
-rw-r--r-- | tests/ecommunity_test.c | 27 | ||||
-rw-r--r-- | tests/heavy-thread.c | 26 | ||||
-rw-r--r-- | tests/heavy-wq.c | 54 | ||||
-rw-r--r-- | tests/heavy.c | 26 | ||||
-rw-r--r-- | tests/main.c | 34 | ||||
-rw-r--r-- | tests/test-checksum.c | 101 | ||||
-rw-r--r-- | tests/test-list_util.c | 2112 | ||||
-rw-r--r-- | tests/test-privs.c | 28 | ||||
-rw-r--r-- | tests/test-sig.c | 10 | ||||
-rw-r--r-- | tests/test-stream.c | 10 | ||||
-rw-r--r-- | tests/test-symtab.c | 344 | ||||
-rw-r--r-- | tests/test-vector.c | 1377 |
16 files changed, 4298 insertions, 417 deletions
diff --git a/tests/Makefile.am b/tests/Makefile.am index 4ab507bb..d6e24db7 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -5,8 +5,9 @@ AM_CFLAGS = $(PICFLAGS) AM_LDFLAGS = $(PILDFLAGS) noinst_PROGRAMS = testsig testbuffer testmemory heavy heavywq heavythread \ - aspathtest testprivs teststream testbgpcap ecommtest \ - testbgpmpattr testchecksum + aspathtest testprivs teststream testbgpcap ecommtest \ + testbgpmpattr testchecksum testvector testsymtab \ + testlistutil testsig_SOURCES = test-sig.c testbuffer_SOURCES = test-buffer.c @@ -21,6 +22,9 @@ testbgpcap_SOURCES = bgp_capability_test.c ecommtest_SOURCES = ecommunity_test.c testbgpmpattr_SOURCES = bgp_mp_attr_test.c testchecksum_SOURCES = test-checksum.c +testvector_SOURCES = test-vector.c +testsymtab_SOURCES = test-symtab.c +testlistutil_SOURCES = test-list_util.c testsig_LDADD = ../lib/libzebra.la @LIBCAP@ testbuffer_LDADD = ../lib/libzebra.la @LIBCAP@ @@ -34,4 +38,7 @@ aspathtest_LDADD = ../lib/libzebra.la @LIBCAP@ -lm ../bgpd/libbgp.a testbgpcap_LDADD = ../lib/libzebra.la @LIBCAP@ -lm ../bgpd/libbgp.a ecommtest_LDADD = ../lib/libzebra.la @LIBCAP@ -lm ../bgpd/libbgp.a testbgpmpattr_LDADD = ../lib/libzebra.la @LIBCAP@ -lm ../bgpd/libbgp.a -testchecksum_LDADD = ../lib/libzebra.la @LIBCAP@ +testchecksum_LDADD = ../lib/libzebra.la @LIBCAP@ +testvector_LDADD = ../lib/libzebra.la @LIBCAP@ +testsymtab_LDADD = ../lib/libzebra.la @LIBCAP@ +testlistutil_LDADD = ../lib/libzebra.la @LIBCAP@ diff --git a/tests/aspath_test.c b/tests/aspath_test.c index 4a2ce9aa..11008b25 100644 --- a/tests/aspath_test.c +++ b/tests/aspath_test.c @@ -22,7 +22,7 @@ struct thread_master *master = NULL; static int failed = 0; /* specification for a test - what the results should be */ -struct test_spec +struct test_spec { const char *shouldbe; /* the string the path should parse to */ const char *shouldbe_delete_confed; /* ditto, but once confeds are deleted */ @@ -45,9 +45,9 @@ static struct test_segment { const u_char asdata[1024]; int len; struct test_spec sp; -} test_segments [] = +} test_segments [] = { - { /* 0 */ + { /* 0 */ "seq1", "seq(8466,3,52737,4096)", { 0x2,0x4, 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00 }, @@ -69,7 +69,7 @@ static struct test_segment { { /* 2 */ "seq3", "seq(8466,3,52737,4096,8722,4)", - { 0x2,0x6, 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, + { 0x2,0x6, 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x22,0x12, 0x00,0x04}, 14, { "8466 3 52737 4096 8722 4", @@ -91,7 +91,7 @@ static struct test_segment { "seq(8467, 59649) set(4196,48658) set(17322,30745)", { 0x2,0x2, 0x21,0x13, 0xe9,0x01, 0x1,0x2, 0x10,0x64, 0xbe,0x12, - 0x1,0x2, 0x43,0xaa, 0x78,0x19 }, + 0x1,0x2, 0x43,0xaa, 0x78,0x19 }, 18, { "8467 59649 {4196,48658} {17322,30745}", "8467 59649 {4196,48658} {17322,30745}", @@ -151,7 +151,7 @@ static struct test_segment { { /* 10 */ "seq4", "seq(8466,2,52737,4096,8722,4)", - { 0x2,0x6, 0x21,0x12, 0x00,0x02, 0xce,0x01, 0x10,0x00, + { 0x2,0x6, 0x21,0x12, 0x00,0x02, 0xce,0x01, 0x10,0x00, 0x22,0x12, 0x00,0x04}, 14, { "8466 2 52737 4096 8722 4", @@ -161,7 +161,7 @@ static struct test_segment { { /* 11 */ "tripleseq1", "seq(8466,2,52737) seq(4096,8722,4) seq(8722)", - { 0x2,0x3, 0x21,0x12, 0x00,0x02, 0xce,0x01, + { 0x2,0x3, 0x21,0x12, 0x00,0x02, 0xce,0x01, 0x2,0x3, 0x10,0x00, 0x22,0x12, 0x00,0x04, 0x2,0x1, 0x22,0x12}, 20, @@ -169,7 +169,7 @@ static struct test_segment { "8466 2 52737 4096 8722 4 8722", 7, 0, NOT_ALL_PRIVATE, 4096, 1, 8466 }, }, - { /* 12 */ + { /* 12 */ "someprivate", "seq(8466,64512,52737,65535)", { 0x2,0x4, 0x21,0x12, 0xfc,0x00, 0xce,0x01, 0xff,0xff }, @@ -178,7 +178,7 @@ static struct test_segment { "8466 64512 52737 65535", 4, 0, NOT_ALL_PRIVATE, 65535, 4, 8466 }, }, - { /* 13 */ + { /* 13 */ "allprivate", "seq(65534,64512,64513,65535)", { 0x2,0x4, 0xff,0xfe, 0xfc,0x00, 0xfc,0x01, 0xff,0xff }, @@ -187,7 +187,7 @@ static struct test_segment { "65534 64512 64513 65535", 4, 0, ALL_PRIVATE, 65534, 4, 65534 }, }, - { /* 14 */ + { /* 14 */ "long", "seq(8466,3,52737,4096,34285,<repeated 49 more times>)", { 0x2,0xfa, 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x85,0xed, @@ -266,7 +266,7 @@ static struct test_segment { "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " "8466 3 52737 4096 34285 8466 3 52737 4096 34285", - + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " @@ -294,7 +294,7 @@ static struct test_segment { "8466 3 52737 4096 34285 8466 3 52737 4096 34285", 250, 0, NOT_ALL_PRIVATE, 4096, 4, 8466 }, }, - { /* 15 */ + { /* 15 */ "seq1extra", "seq(8466,3,52737,4096,3456)", { 0x2,0x5, 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x0d,0x80 }, @@ -310,7 +310,7 @@ static struct test_segment { 0, { "", "", 0, 0, 0, 0, 0, 0 }, }, - { /* 17 */ + { /* 17 */ "redundantset", "seq(8466,3,52737,4096,3456) set(7099,8153,8153,8153)", { 0x2,0x5, 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x0d,0x80, @@ -338,7 +338,7 @@ static struct test_segment { { /* 19 */ "reconcile_new_asp", "set(2457,61697,4369), seq(1842,41591,51793)", - { + { 0x1,0x3, 0x09,0x99, 0xf1,0x01, 0x11,0x11, 0x2,0x3, 0x07,0x32, 0xa2,0x77, 0xca,0x51 }, 16, @@ -391,7 +391,7 @@ static struct test_segment { "23456 23456 23456 6435 59408", 5, 0, NOT_ALL_PRIVATE, 59408, 1, 23456 }, }, - { /* 24 */ + { /* 24 */ "redundantset2", "seq(8466,3,52737,4096,3456) set(7099,8153,8153,8153,7099)", { 0x2,0x5, 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x0d,0x80, @@ -403,7 +403,7 @@ static struct test_segment { "8466 3 52737 4096 3456 {7099,8153}", 6, 0, NOT_ALL_PRIVATE, 4096, 4, 8466 }, }, - { /* 25 */ + { /* 25 */ "zero-size overflow", "#ASNs = 0, data = seq(8466 3 52737 4096 3456)", { 0x2,0x0, 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x0d,0x80 }, @@ -411,17 +411,17 @@ static struct test_segment { { NULL, NULL, 0, 0, 0, 0, 0, 0 }, }, - { /* 26 */ + { /* 26 */ "zero-size overflow + valid segment", "seq(#AS=0:8466 3 52737),seq(4096 3456)", - { 0x2,0x0, 0x21,0x12, 0x00,0x03, 0xce,0x01, + { 0x2,0x0, 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x2,0x2, 0x10,0x00, 0x0d,0x80 }, 14 , { NULL, NULL, 0, 0, 0, 0, 0, 0 }, }, - { /* 27 */ + { /* 27 */ "invalid segment type", "type=8(4096 3456)", { 0x8,0x2, 0x10,0x00, 0x0d,0x80 }, @@ -453,7 +453,7 @@ static struct aspath_tests { AS2_DATA, 0, 0, { BGP_ATTR_FLAG_TRANS, - BGP_ATTR_AS_PATH, + BGP_ATTR_AS_PATH, 10, }, 3, @@ -466,7 +466,7 @@ static struct aspath_tests { AS2_DATA, -1, 0, { BGP_ATTR_FLAG_TRANS, - BGP_ATTR_AS_PATH, + BGP_ATTR_AS_PATH, 8, }, 3, @@ -479,7 +479,7 @@ static struct aspath_tests { AS2_DATA, -1, 0, { BGP_ATTR_FLAG_TRANS, - BGP_ATTR_AS_PATH, + BGP_ATTR_AS_PATH, 12, }, 3, @@ -492,7 +492,7 @@ static struct aspath_tests { AS2_DATA, -1, 0, { BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL, - BGP_ATTR_AS_PATH, + BGP_ATTR_AS_PATH, 10, }, 3, @@ -505,7 +505,7 @@ static struct aspath_tests { AS2_DATA, -1, 0, { BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL, - BGP_ATTR_AS4_PATH, + BGP_ATTR_AS4_PATH, 10, }, 3, @@ -518,7 +518,7 @@ static struct aspath_tests { AS4_DATA, -1, PEER_CAP_AS4_RCV, { BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL, - BGP_ATTR_AS4_PATH, + BGP_ATTR_AS4_PATH, 10, }, 3, @@ -531,7 +531,7 @@ static struct aspath_tests { AS4_DATA, 0, PEER_CAP_AS4_RCV|PEER_CAP_AS4_ADV, { BGP_ATTR_FLAG_TRANS, - BGP_ATTR_AS_PATH, + BGP_ATTR_AS_PATH, 18, }, 3, @@ -544,7 +544,7 @@ static struct aspath_tests { AS4_DATA, -1, PEER_CAP_AS4_RCV|PEER_CAP_AS4_ADV, { BGP_ATTR_FLAG_TRANS, - BGP_ATTR_AS_PATH, + BGP_ATTR_AS_PATH, 16, }, 3, @@ -557,7 +557,7 @@ static struct aspath_tests { AS4_DATA, -1, PEER_CAP_AS4_RCV|PEER_CAP_AS4_ADV, { BGP_ATTR_FLAG_TRANS, - BGP_ATTR_AS_PATH, + BGP_ATTR_AS_PATH, 20, }, 3, @@ -570,7 +570,7 @@ static struct aspath_tests { AS4_DATA, -1, PEER_CAP_AS4_RCV|PEER_CAP_AS4_ADV, { BGP_ATTR_FLAG_TRANS, - BGP_ATTR_AS_PATH, + BGP_ATTR_AS_PATH, 22, }, 3, @@ -583,7 +583,7 @@ static struct aspath_tests { AS4_DATA, -1, PEER_CAP_AS4_RCV|PEER_CAP_AS4_ADV, { BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL, - BGP_ATTR_AS_PATH, + BGP_ATTR_AS_PATH, 18, }, 3, @@ -596,7 +596,7 @@ static struct aspath_tests { AS4_DATA, -1, PEER_CAP_AS4_ADV, { BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL, - BGP_ATTR_AS4_PATH, + BGP_ATTR_AS4_PATH, 14, }, 3, @@ -609,7 +609,7 @@ static struct tests { const struct test_segment *test1; const struct test_segment *test2; struct test_spec sp; -} prepend_tests[] = +} prepend_tests[] = { /* 0 */ { &test_segments[0], &test_segments[1], @@ -691,7 +691,7 @@ static struct tests { "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " "8466 2 52737 4096 8722 4 8722", - + "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " "8466 3 52737 4096 34285 8466 3 52737 4096 34285 " @@ -757,7 +757,7 @@ struct tests reconcile_tests[] = }, { NULL, NULL, { NULL, 0, 0, 0, 0, 0, 0, } }, }; - + struct tests aggregate_tests[] = { { &test_segments[0], &test_segments[2], @@ -790,7 +790,7 @@ struct tests aggregate_tests[] = { NULL, NULL, { NULL, 0, 0} }, }; -struct compare_tests +struct compare_tests { int test_index1; int test_index2; @@ -830,17 +830,17 @@ make_aspath (const u_char *data, size_t len, int use32bit) { struct stream *s = NULL; struct aspath *as; - + if (len) { s = stream_new (len); stream_put (s, data, len); } - as = aspath_parse (s, len, use32bit); - + as = aspath_parse (s, len, use32bit, 0); + if (s) stream_free (s); - + return as; } @@ -857,7 +857,7 @@ printbytes (const u_char *bytes, int len) i++; } printf ("\n"); -} +} /* validate the given aspath */ static int @@ -868,33 +868,33 @@ validate (struct aspath *as, const struct test_spec *sp) const u_char *out; static struct stream *s; struct aspath *asinout, *asconfeddel, *asstr, *as4; - + if (as == NULL && sp->shouldbe == NULL) { printf ("Correctly failed to parse\n"); return fails; } - + out = aspath_snmp_pathseg (as, &bytes); asinout = make_aspath (out, bytes, 0); - + /* Excercise AS4 parsing a bit, with a dogfood test */ if (!s) s = stream_new (4096); bytes4 = aspath_put (s, as, 1); as4 = make_aspath (STREAM_DATA(s), bytes4, 1); - + asstr = aspath_str2aspath (sp->shouldbe); - + asconfeddel = aspath_delete_confed_seq (aspath_dup (asinout)); - + printf ("got: %s\n", aspath_print(as)); - + /* the parsed path should match the specified 'shouldbe' string. * We should pass the "eat our own dog food" test, be able to output * this path and then input it again. Ie the path resulting from: * - * aspath_parse(aspath_put(as)) + * aspath_parse(aspath_put(as)) * * should: * @@ -909,7 +909,7 @@ validate (struct aspath *as, const struct test_spec *sp) * * aspath_parse(aspath_put(as,USE32BIT)) * - * Confederation related tests: + * Confederation related tests: * - aspath_delete_confed_seq(aspath) should match shouldbe_confed * - aspath_delete_confed_seq should be idempotent. */ @@ -930,9 +930,9 @@ validate (struct aspath *as, const struct test_spec *sp) fails++; printf ("shouldbe:\n%s\n", sp->shouldbe); printf ("as4:\n%s\n", aspath_print (as4)); - printf ("hash keys: in: %d out->in: %d\n", + printf ("hash keys: in: %d out->in: %d\n", aspath_key_make (as), aspath_key_make (asinout)); - printf ("hops: %d, counted %d %d\n", sp->hops, + printf ("hops: %d, counted %d %d\n", sp->hops, aspath_count_hops (as), aspath_count_hops (asinout) ); printf ("confeds: %d, counted %d %d\n", sp->confeds, @@ -942,13 +942,13 @@ validate (struct aspath *as, const struct test_spec *sp) printbytes (out, bytes); } /* basic confed related tests */ - if ((aspath_print (asconfeddel) == NULL + if ((aspath_print (asconfeddel) == NULL && sp->shouldbe_delete_confed != NULL) - || (aspath_print (asconfeddel) != NULL + || (aspath_print (asconfeddel) != NULL && sp->shouldbe_delete_confed == NULL) || strcmp(aspath_print (asconfeddel), sp->shouldbe_delete_confed) /* delete_confed_seq should be idempotent */ - || (aspath_key_make (asconfeddel) + || (aspath_key_make (asconfeddel) != aspath_key_make (aspath_delete_confed_seq (asconfeddel)))) { failed++; @@ -965,7 +965,7 @@ validate (struct aspath *as, const struct test_spec *sp) fails++; printf ("asstr: %s\n", aspath_print (asstr)); } - + /* loop, private and first as checks */ if ((sp->does_loop && aspath_loop_check (as, sp->does_loop) == 0) || (sp->doesnt_loop && aspath_loop_check (as, sp->doesnt_loop) != 0) @@ -983,13 +983,13 @@ validate (struct aspath *as, const struct test_spec *sp) printf ("private check: %d %d\n", sp->private_as, aspath_private_as_check (as)); } - aspath_unintern (asinout); - aspath_unintern (as4); - + aspath_unintern (&asinout); + aspath_unintern (&as4); + aspath_free (asconfeddel); aspath_free (asstr); stream_reset (s); - + return fails; } @@ -1004,9 +1004,9 @@ empty_get_test () printf ("%s\n", OK); else printf ("%s!\n", FAILED); - + printf ("\n"); - + aspath_free (as); } @@ -1015,22 +1015,22 @@ static void parse_test (struct test_segment *t) { struct aspath *asp; - + printf ("%s: %s\n", t->name, t->desc); asp = make_aspath (t->asdata, t->len, 0); - + printf ("aspath: %s\nvalidating...:\n", aspath_print (asp)); if (!validate (asp, &t->sp)) printf (OK "\n"); else printf (FAILED "\n"); - + printf ("\n"); - + if (asp) - aspath_unintern (asp); + aspath_unintern (&asp); } /* prepend testing */ @@ -1038,27 +1038,27 @@ static void prepend_test (struct tests *t) { struct aspath *asp1, *asp2, *ascratch; - + printf ("prepend %s: %s\n", t->test1->name, t->test1->desc); printf ("to %s: %s\n", t->test2->name, t->test2->desc); - + asp1 = make_aspath (t->test1->asdata, t->test1->len, 0); asp2 = make_aspath (t->test2->asdata, t->test2->len, 0); - + ascratch = aspath_dup (asp2); - aspath_unintern (asp2); - + aspath_unintern (&asp2); + asp2 = aspath_prepend (asp1, ascratch); - + printf ("aspath: %s\n", aspath_print (asp2)); - + if (!validate (asp2, &t->sp)) printf ("%s\n", OK); else printf ("%s!\n", FAILED); - + printf ("\n"); - aspath_unintern (asp1); + aspath_unintern (&asp1); aspath_free (asp2); } @@ -1067,27 +1067,27 @@ static void empty_prepend_test (struct test_segment *t) { struct aspath *asp1, *asp2, *ascratch; - + printf ("empty prepend %s: %s\n", t->name, t->desc); - + asp1 = make_aspath (t->asdata, t->len, 0); asp2 = aspath_empty (); - + ascratch = aspath_dup (asp2); - aspath_unintern (asp2); - + aspath_unintern (&asp2); + asp2 = aspath_prepend (asp1, ascratch); - + printf ("aspath: %s\n", aspath_print (asp2)); - + if (!validate (asp2, &t->sp)) printf (OK "\n"); else printf (FAILED "!\n"); - + printf ("\n"); if (asp1) - aspath_unintern (asp1); + aspath_unintern (&asp1); aspath_free (asp2); } @@ -1096,23 +1096,23 @@ static void as4_reconcile_test (struct tests *t) { struct aspath *asp1, *asp2, *ascratch; - + printf ("reconciling %s:\n %s\n", t->test1->name, t->test1->desc); printf ("with %s:\n %s\n", t->test2->name, t->test2->desc); - + asp1 = make_aspath (t->test1->asdata, t->test1->len, 0); asp2 = make_aspath (t->test2->asdata, t->test2->len, 0); - + ascratch = aspath_reconcile_as4 (asp1, asp2); - + if (!validate (ascratch, &t->sp)) printf (OK "\n"); else printf (FAILED "!\n"); - + printf ("\n"); - aspath_unintern (asp1); - aspath_unintern (asp2); + aspath_unintern (&asp1); + aspath_unintern (&asp2); aspath_free (ascratch); } @@ -1122,23 +1122,23 @@ static void aggregate_test (struct tests *t) { struct aspath *asp1, *asp2, *ascratch; - + printf ("aggregate %s: %s\n", t->test1->name, t->test1->desc); printf ("with %s: %s\n", t->test2->name, t->test2->desc); - + asp1 = make_aspath (t->test1->asdata, t->test1->len, 0); asp2 = make_aspath (t->test2->asdata, t->test2->len, 0); - + ascratch = aspath_aggregate (asp1, asp2); - + if (!validate (ascratch, &t->sp)) printf (OK "\n"); else printf (FAILED "!\n"); - + printf ("\n"); - aspath_unintern (asp1); - aspath_unintern (asp2); + aspath_unintern (&asp1); + aspath_unintern (&asp2); aspath_free (ascratch); /* aspath_unintern (ascratch);*/ } @@ -1156,23 +1156,23 @@ cmp_test () struct test_segment *t1 = &test_segments[left_compare[i].test_index1]; struct test_segment *t2 = &test_segments[left_compare[i].test_index2]; struct aspath *asp1, *asp2; - + printf ("left cmp %s: %s\n", t1->name, t1->desc); printf ("and %s: %s\n", t2->name, t2->desc); - + asp1 = make_aspath (t1->asdata, t1->len, 0); asp2 = make_aspath (t2->asdata, t2->len, 0); - + if (aspath_cmp_left (asp1, asp2) != left_compare[i].shouldbe_cmp || aspath_cmp_left (asp2, asp1) != left_compare[i].shouldbe_cmp - || aspath_cmp_left_confed (asp1, asp2) + || aspath_cmp_left_confed (asp1, asp2) != left_compare[i].shouldbe_confed - || aspath_cmp_left_confed (asp2, asp1) + || aspath_cmp_left_confed (asp2, asp1) != left_compare[i].shouldbe_confed) { failed++; printf (FAILED "\n"); - printf ("result should be: cmp: %d, confed: %d\n", + printf ("result should be: cmp: %d, confed: %d\n", left_compare[i].shouldbe_cmp, left_compare[i].shouldbe_confed); printf ("got: cmp %d, cmp_confed: %d\n", @@ -1183,47 +1183,50 @@ cmp_test () } else printf (OK "\n"); - + printf ("\n"); - aspath_unintern (asp1); - aspath_unintern (asp2); + aspath_unintern (&asp1); + aspath_unintern (&asp2); } } static int handle_attr_test (struct aspath_tests *t) { - struct bgp bgp = { 0 }; + struct bgp bgp = { 0 }; struct peer peer = { 0 }; - struct attr attr = { 0 }; + struct attr attr = { 0 }; int ret; int initfail = failed; struct aspath *asp; size_t datalen; - + char host[] = { "none" } ; + asp = make_aspath (t->segment->asdata, t->segment->len, 0); - + peer.ibuf = stream_new (BGP_MAX_PACKET_SIZE); peer.obuf = stream_fifo_new (); peer.bgp = &bgp; - peer.host = (char *)"none"; + peer.host = host ; +#if 0 peer.fd = -1; +#endif peer.cap = t->cap; - + stream_write (peer.ibuf, t->attrheader, t->len); datalen = aspath_put (peer.ibuf, asp, t->as4 == AS4_DATA); - + ret = bgp_attr_parse (&peer, &attr, t->len + datalen, NULL, NULL); - + if (ret != t->result) { printf ("bgp_attr_parse returned %d, expected %d\n", ret, t->result); - printf ("datalen %d\n", datalen); + printf ("datalen %d\n", (int)datalen); failed++; } if (ret != 0) goto out; - + if (attr.aspath == NULL) { printf ("aspath is NULL!\n"); @@ -1240,9 +1243,9 @@ handle_attr_test (struct aspath_tests *t) out: if (attr.aspath) - aspath_unintern (attr.aspath); + aspath_unintern (&attr.aspath); if (asp) - aspath_unintern (asp); + aspath_unintern (&asp); return failed - initfail; } @@ -1250,7 +1253,7 @@ static void attr_test (struct aspath_tests *t) { printf ("%s\n", t->desc); - printf ("%s\n\n", handle_attr_test (t) ? FAILED : OK); + printf ("%s\n\n", handle_attr_test (t) ? FAILED : OK); } int @@ -1260,54 +1263,54 @@ main (void) bgp_master_init (); master = bm->master; bgp_attr_init (); - + while (test_segments[i].name) { printf ("test %u\n", i); parse_test (&test_segments[i]); empty_prepend_test (&test_segments[i++]); } - + i = 0; while (prepend_tests[i].test1) { printf ("prepend test %u\n", i); prepend_test (&prepend_tests[i++]); } - + i = 0; while (aggregate_tests[i].test1) { printf ("aggregate test %u\n", i); aggregate_test (&aggregate_tests[i++]); } - + i = 0; - + while (reconcile_tests[i].test1) { printf ("reconcile test %u\n", i); as4_reconcile_test (&reconcile_tests[i++]); } - + i = 0; - + cmp_test(); - + i = 0; - + empty_get_test(); - + i = 0; - + while (aspath_tests[i].desc) { printf ("aspath_attr test %d\n", i); attr_test (&aspath_tests[i++]); } - + printf ("failures: %d\n", failed); printf ("aspath count: %ld\n", aspath_count()); - + return (failed + aspath_count()); } diff --git a/tests/bgp_capability_test.c b/tests/bgp_capability_test.c index 0dbf4fb9..cae9a12d 100644 --- a/tests/bgp_capability_test.c +++ b/tests/bgp_capability_test.c @@ -1,4 +1,5 @@ #include <zebra.h> +#include "miyagi.h" #include "vty.h" #include "stream.h" @@ -36,7 +37,7 @@ static struct test_segment { #define SHOULD_ERR -1 int parses; /* whether it should parse or not */ int peek_for; /* what peek_for_as4_capability should say */ - + /* AFI/SAFI validation */ int validate_afi; afi_t afi; @@ -44,10 +45,10 @@ static struct test_segment { #define VALID_AFI 1 #define INVALID_AFI 0 int afi_valid; -} test_segments [] = +} test_segments [] = { /* 0 */ - { "caphdr", + { "caphdr", "capability header, and no more", { CAPABILITY_CODE_REFRESH, 0x0 }, 2, SHOULD_PARSE, @@ -114,7 +115,7 @@ static struct test_segment mp_segments[] = { CAPABILITY_CODE_MP, 0x4, 0x0, 0x1, 0x0, 0x80 }, 6, SHOULD_PARSE, 0, 1, AFI_IP, BGP_SAFI_VPNV4, VALID_AFI, - }, + }, /* 9 */ { "MP7", "MP IP4/VPNv6", @@ -150,9 +151,9 @@ static struct test_segment misc_segments[] = /* 13 */ { "ORF", "ORF, simple, single entry, single tuple", - { /* hdr */ CAPABILITY_CODE_ORF, 0x7, - /* mpc */ 0x0, 0x1, 0x0, 0x1, - /* num */ 0x1, + { /* hdr */ CAPABILITY_CODE_ORF, 0x7, + /* mpc */ 0x0, 0x1, 0x0, 0x1, + /* num */ 0x1, /* tuples */ 0x40, 0x3 }, 9, SHOULD_PARSE, @@ -161,18 +162,18 @@ static struct test_segment misc_segments[] = { "ORF-many", "ORF, multi entry/tuple", { /* hdr */ CAPABILITY_CODE_ORF, 0x21, - /* mpc */ 0x0, 0x1, 0x0, 0x1, - /* num */ 0x3, + /* mpc */ 0x0, 0x1, 0x0, 0x1, + /* num */ 0x3, /* tuples */ 0x40, ORF_MODE_BOTH, 0x80, ORF_MODE_RECEIVE, 0x80, ORF_MODE_SEND, - /* mpc */ 0x0, 0x2, 0x0, 0x1, - /* num */ 0x3, + /* mpc */ 0x0, 0x2, 0x0, 0x1, + /* num */ 0x3, /* tuples */ 0x40, ORF_MODE_BOTH, 0x80, ORF_MODE_RECEIVE, 0x80, ORF_MODE_SEND, /* mpc */ 0x0, 0x2, 0x0, 0x2, - /* num */ 0x3, + /* num */ 0x3, /* tuples */ 0x40, ORF_MODE_RECEIVE, 0x80, ORF_MODE_SEND, 0x80, ORF_MODE_BOTH, @@ -183,18 +184,18 @@ static struct test_segment misc_segments[] = { "ORFlo", "ORF, multi entry/tuple, hdr length too short", { /* hdr */ CAPABILITY_CODE_ORF, 0x15, - /* mpc */ 0x0, 0x1, 0x0, 0x1, - /* num */ 0x3, + /* mpc */ 0x0, 0x1, 0x0, 0x1, + /* num */ 0x3, /* tuples */ 0x40, 0x3, 0x80, 0x1, 0x80, 0x2, - /* mpc */ 0x0, 0x1, 0x0, 0x1, - /* num */ 0x3, + /* mpc */ 0x0, 0x1, 0x0, 0x1, + /* num */ 0x3, /* tuples */ 0x40, 0x3, 0x80, 0x1, 0x80, 0x2, /* mpc */ 0x0, 0x2, 0x0, 0x2, - /* num */ 0x3, + /* num */ 0x3, /* tuples */ 0x40, 0x3, 0x80, 0x1, 0x80, 0x2, @@ -205,18 +206,18 @@ static struct test_segment misc_segments[] = { "ORFlu", "ORF, multi entry/tuple, length too long", { /* hdr */ 0x3, 0x22, - /* mpc */ 0x0, 0x1, 0x0, 0x1, - /* num */ 0x3, + /* mpc */ 0x0, 0x1, 0x0, 0x1, + /* num */ 0x3, /* tuples */ 0x40, 0x3, 0x80, 0x1, 0x80, 0x2, - /* mpc */ 0x0, 0x2, 0x0, 0x1, - /* num */ 0x3, + /* mpc */ 0x0, 0x2, 0x0, 0x1, + /* num */ 0x3, /* tuples */ 0x40, 0x3, 0x80, 0x1, 0x80, 0x2, /* mpc */ 0x0, 0x2, 0x0, 0x2, - /* num */ 0x3, + /* num */ 0x3, /* tuples */ 0x40, 0x3, 0x80, 0x1, 0x80, 0x2, @@ -227,18 +228,18 @@ static struct test_segment misc_segments[] = { "ORFnu", "ORF, multi entry/tuple, entry number too long", { /* hdr */ 0x3, 0x21, - /* mpc */ 0x0, 0x1, 0x0, 0x1, - /* num */ 0x3, + /* mpc */ 0x0, 0x1, 0x0, 0x1, + /* num */ 0x3, /* tuples */ 0x40, 0x3, 0x80, 0x1, 0x80, 0x2, - /* mpc */ 0x0, 0x2, 0x0, 0x1, - /* num */ 0x4, + /* mpc */ 0x0, 0x2, 0x0, 0x1, + /* num */ 0x4, /* tuples */ 0x40, 0x3, 0x80, 0x1, 0x80, 0x2, /* mpc */ 0x0, 0x2, 0x0, 0x2, - /* num */ 0x3, + /* num */ 0x3, /* tuples */ 0x40, 0x3, 0x80, 0x1, 0x80, 0x2, @@ -249,13 +250,13 @@ static struct test_segment misc_segments[] = { "ORFno", "ORF, multi entry/tuple, entry number too short", { /* hdr */ 0x3, 0x21, - /* mpc */ 0x0, 0x1, 0x0, 0x1, - /* num */ 0x3, + /* mpc */ 0x0, 0x1, 0x0, 0x1, + /* num */ 0x3, /* tuples */ 0x40, 0x3, 0x80, 0x1, 0x80, 0x2, - /* mpc */ 0x0, 0x2, 0x0, 0x1, - /* num */ 0x1, + /* mpc */ 0x0, 0x2, 0x0, 0x1, + /* num */ 0x1, /* tuples */ 0x40, 0x3, 0x80, 0x1, 0x80, 0x2, @@ -271,18 +272,18 @@ static struct test_segment misc_segments[] = { "ORFpad", "ORF, multi entry/tuple, padded to align", { /* hdr */ 0x3, 0x22, - /* mpc */ 0x0, 0x1, 0x0, 0x1, - /* num */ 0x3, + /* mpc */ 0x0, 0x1, 0x0, 0x1, + /* num */ 0x3, /* tuples */ 0x40, 0x3, 0x80, 0x1, 0x80, 0x2, - /* mpc */ 0x0, 0x2, 0x0, 0x1, - /* num */ 0x3, + /* mpc */ 0x0, 0x2, 0x0, 0x1, + /* num */ 0x3, /* tuples */ 0x40, 0x3, 0x80, 0x1, 0x80, 0x2, /* mpc */ 0x0, 0x2, 0x0, 0x2, - /* num */ 0x3, + /* num */ 0x3, /* tuples */ 0x40, 0x3, 0x80, 0x1, 0x80, 0x2, @@ -401,7 +402,7 @@ static struct test_segment misc_segments[] = }; /* DYNAMIC message */ -struct test_segment dynamic_cap_msgs[] = +struct test_segment dynamic_cap_msgs[] = { { "DynCap", "Dynamic Capability Message, IP/Multicast", @@ -439,7 +440,7 @@ struct test_segment opt_params[] = { 0x02, 0x06, 0x01, 0x04, 0x00, 0x01, 0x00, 0x01, /* MP IPv4/Uni */ 0x02, 0x06, 0x01, 0x04, 0x00, 0x02, 0x00, 0x01, /* MP IPv6/Uni */ 0x02, 0x02, 0x80, 0x00, /* RR (old) */ - 0x02, 0x02, 0x02, 0x00, /* RR */ + 0x02, 0x02, 0x02, 0x00, /* RR */ }, 24, SHOULD_PARSE, }, @@ -449,7 +450,7 @@ struct test_segment opt_params[] = 0x01, 0x04, 0x00, 0x01, 0x00, 0x01, /* MP IPv4/Uni */ 0x01, 0x04, 0x00, 0x02, 0x00, 0x01, /* MP IPv6/Uni */ 0x80, 0x00, /* RR (old) */ - 0x02, 0x00, /* RR */ + 0x02, 0x00, /* RR */ }, 18, SHOULD_PARSE, }, @@ -469,7 +470,7 @@ struct test_segment opt_params[] = 0x01, 0x04, 0x00, 0x01, 0x00, 0x01, /* MP IPv4/Uni */ 0x01, 0x04, 0x00, 0x02, 0x00, 0x01, /* MP IPv6/Uni */ 0x80, 0x00, /* RR (old) */ - 0x02, 0x00, /* RR */ + 0x02, 0x00, /* RR */ 0x41, 0x04, 0x00, 0x03, 0x00, 0x06 /* AS4: 1996614 */ }, 24, SHOULD_PARSE, 196614, @@ -503,6 +504,8 @@ struct test_segment opt_params[] = { NULL, NULL, {0}, 0, 0} }; +extern int bgp_capability_receive(struct peer*, bgp_size_t) ; + /* basic parsing test */ static void parse_test (struct peer *peer, struct test_segment *t, int type) @@ -513,11 +516,11 @@ parse_test (struct peer *peer, struct test_segment *t, int type) int oldfailed = failed; int len = t->len; #define RANDOM_FUZZ 35 - + stream_reset (peer->ibuf); stream_put (peer->ibuf, NULL, RANDOM_FUZZ); stream_set_getp (peer->ibuf, RANDOM_FUZZ); - + switch (type) { case CAPABILITY: @@ -532,7 +535,7 @@ parse_test (struct peer *peer, struct test_segment *t, int type) break; } stream_write (peer->ibuf, t->data, t->len); - + printf ("%s: %s\n", t->name, t->desc); switch (type) @@ -546,7 +549,7 @@ parse_test (struct peer *peer, struct test_segment *t, int type) printf ("peek_for_as4: as4 is %u\n", as4); /* and it should leave getp as it found it */ assert (stream_get_getp (peer->ibuf) == RANDOM_FUZZ); - + ret = bgp_open_option_parse (peer, len, &capability); break; case DYNCAP: @@ -556,49 +559,49 @@ parse_test (struct peer *peer, struct test_segment *t, int type) printf ("unknown type %u\n", type); exit(1); } - + if (!ret && t->validate_afi) { safi_t safi = t->safi; - + if (bgp_afi_safi_valid_indices (t->afi, &safi) != t->afi_valid) failed++; - + printf ("MP: %u/%u (%u): recv %u, nego %u\n", t->afi, t->safi, safi, peer->afc_recv[t->afi][safi], peer->afc_nego[t->afi][safi]); - + if (t->afi_valid == VALID_AFI) { - + if (!peer->afc_recv[t->afi][safi]) failed++; if (!peer->afc_nego[t->afi][safi]) failed++; } } - - if (as4 != t->peek_for) + + if (as4 != (uint32_t)t->peek_for) { printf ("as4 %u != %u\n", as4, t->peek_for); failed++; } - + printf ("parsed?: %s\n", ret ? "no" : "yes"); - + if (ret != t->parses) failed++; - + if (tty) - printf ("%s", (failed > oldfailed) ? VT100_RED "failed!" VT100_RESET + printf ("%s", (failed > oldfailed) ? VT100_RED "failed!" VT100_RESET : VT100_GREEN "OK" VT100_RESET); else printf ("%s", (failed > oldfailed) ? "failed!" : "OK" ); - + if (failed) printf (" (%u)", failed); - + printf ("\n\n"); } @@ -610,7 +613,7 @@ main (void) { struct peer *peer; int i, j; - + conf_bgp_debug_fsm = -1UL; conf_bgp_debug_events = -1UL; conf_bgp_debug_packet = -1UL; @@ -621,26 +624,26 @@ main (void) term_bgp_debug_packet = -1UL; term_bgp_debug_normal = -1UL; term_bgp_debug_as4 = -1UL; - + master = thread_master_create (); bgp_master_init (); - - if (fileno (stdout) >= 0) + + if (fileno (stdout) >= 0) tty = isatty (fileno (stdout)); - + if (bgp_get (&bgp, &asn, NULL)) return -1; - + peer = peer_create_accept (bgp); - peer->host = "foo"; - + peer->host = miyagi("foo"); + for (i = AFI_IP; i < AFI_MAX; i++) for (j = SAFI_UNICAST; j < SAFI_MAX; j++) { peer->afc[i][j] = 1; peer->afc_adv[i][j] = 1; } - + i = 0; while (mp_segments[i].name) parse_test (peer, &mp_segments[i++], CAPABILITY); @@ -649,9 +652,9 @@ main (void) * one of the afc_nego's */ i = 0; - while (test_segments[i].name) + while (test_segments[i].name) parse_test (peer, &test_segments[i++], CAPABILITY); - + i = 0; while (misc_segments[i].name) parse_test (peer, &misc_segments[i++], CAPABILITY); @@ -661,12 +664,12 @@ main (void) parse_test (peer, &opt_params[i++], OPT_PARAM); SET_FLAG (peer->cap, PEER_CAP_DYNAMIC_ADV); - peer->status = Established; - + peer->state = bgp_peer_pEstablished; + i = 0; while (dynamic_cap_msgs[i].name) parse_test (peer, &dynamic_cap_msgs[i++], DYNCAP); - + printf ("failures: %d\n", failed); return failed; } diff --git a/tests/bgp_mp_attr_test.c b/tests/bgp_mp_attr_test.c index dde0df2f..6a445acf 100644 --- a/tests/bgp_mp_attr_test.c +++ b/tests/bgp_mp_attr_test.c @@ -1,4 +1,5 @@ #include <zebra.h> +#include "miyagi.h" #include "vty.h" #include "stream.h" @@ -36,17 +37,17 @@ static struct test_segment { #define SHOULD_PARSE 0 #define SHOULD_ERR -1 int parses; /* whether it should parse or not */ - + /* AFI/SAFI validation */ afi_t afi; safi_t safi; #define VALID_AFI 1 #define INVALID_AFI 0 int afi_valid; -} mp_reach_segments [] = +} mp_reach_segments [] = { { "IPv6", - "IPV6 MP Reach, global nexthop, 1 NLRI", + "IPV6 MP Reach, global nexthop, 1 NLRI", { /* AFI / SAFI */ 0x0, AFI_IP6, SAFI_UNICAST, /* nexthop bytes */ 16, @@ -57,12 +58,12 @@ static struct test_segment { /* SNPA (defunct, MBZ) */ 0x0, /* NLRI tuples */ 32, 0xff, 0xfe, 0x1, 0x2, /* fffe:102::/32 */ }, - (4 + 16 + 1 + 5), + (4 + 16 + 1 + 5), SHOULD_PARSE, AFI_IP6, SAFI_UNICAST, VALID_AFI, }, { "IPv6-2", - "IPV6 MP Reach, global nexthop, 2 NLRIs", + "IPV6 MP Reach, global nexthop, 2 NLRIs", { /* AFI / SAFI */ 0x0, AFI_IP6, SAFI_UNICAST, /* nexthop bytes */ 16, @@ -71,18 +72,18 @@ static struct test_segment { 0x3, 0x4, 0x5, 0x6, 0xa1, 0xa2, 0xa3, 0xa4, /* SNPA (defunct, MBZ) */ 0x0, - /* NLRI tuples */ 32, + /* NLRI tuples */ 32, 0xff, 0xfe, 0x1, 0x2, /* fffe:102::/32 */ 64, 0xff, 0xfe, 0x0, 0x1, /* fffe:1:2:3::/64 */ 0x0, 0x2, 0x0, 0x3, }, - (4 + 16 + 1 + 5 + 9), + (4 + 16 + 1 + 5 + 9), SHOULD_PARSE, AFI_IP6, SAFI_UNICAST, VALID_AFI, }, { "IPv6-default", - "IPV6 MP Reach, global nexthop, 2 NLRIs + default", + "IPV6 MP Reach, global nexthop, 2 NLRIs + default", { /* AFI / SAFI */ 0x0, AFI_IP6, SAFI_UNICAST, /* nexthop bytes */ 16, @@ -91,7 +92,7 @@ static struct test_segment { 0x3, 0x4, 0x5, 0x6, 0xa1, 0xa2, 0xa3, 0xa4, /* SNPA (defunct, MBZ) */ 0x0, - /* NLRI tuples */ 32, + /* NLRI tuples */ 32, 0xff, 0xfe, 0x1, 0x2, /* fffe:102::/32 */ 64, 0xff, 0xfe, 0x0, 0x1, /* fffe:1:2:3::/64 */ @@ -103,7 +104,7 @@ static struct test_segment { AFI_IP6, SAFI_UNICAST, VALID_AFI, }, { "IPv6-lnh", - "IPV6 MP Reach, global+local nexthops, 2 NLRIs + default", + "IPV6 MP Reach, global+local nexthops, 2 NLRIs + default", { /* AFI / SAFI */ 0x0, AFI_IP6, SAFI_UNICAST, /* nexthop bytes */ 32, @@ -116,7 +117,7 @@ static struct test_segment { 0x2, 0x10, 0x2, 0xff, 0x1, 0x2, 0x3, 0x4, /* SNPA (defunct, MBZ) */ 0x0, - /* NLRI tuples */ 32, + /* NLRI tuples */ 32, 0xff, 0xfe, 0x1, 0x2, /* fffe:102::/32 */ 64, 0xff, 0xfe, 0x0, 0x1, /* fffe:1:2:3::/64 */ @@ -128,7 +129,7 @@ static struct test_segment { AFI_IP6, SAFI_UNICAST, VALID_AFI, }, { "IPv6-nhlen", - "IPV6 MP Reach, inappropriate nexthop length", + "IPV6 MP Reach, inappropriate nexthop length", { /* AFI / SAFI */ 0x0, AFI_IP6, SAFI_UNICAST, /* nexthop bytes */ 4, @@ -141,7 +142,7 @@ static struct test_segment { 0x2, 0x10, 0x2, 0xff, 0x1, 0x2, 0x3, 0x4, /* SNPA (defunct, MBZ) */ 0x0, - /* NLRI tuples */ 32, + /* NLRI tuples */ 32, 0xff, 0xfe, 0x1, 0x2, /* fffe:102::/32 */ 64, 0xff, 0xfe, 0x0, 0x1, /* fffe:1:2:3::/64 */ @@ -153,7 +154,7 @@ static struct test_segment { AFI_IP6, SAFI_UNICAST, VALID_AFI, }, { "IPv6-nhlen2", - "IPV6 MP Reach, invalid nexthop length", + "IPV6 MP Reach, invalid nexthop length", { /* AFI / SAFI */ 0x0, AFI_IP6, SAFI_UNICAST, /* nexthop bytes */ 5, @@ -166,7 +167,7 @@ static struct test_segment { 0x2, 0x10, 0x2, 0xff, 0x1, 0x2, 0x3, 0x4, /* SNPA (defunct, MBZ) */ 0x0, - /* NLRI tuples */ 32, + /* NLRI tuples */ 32, 0xff, 0xfe, 0x1, 0x2, /* fffe:102::/32 */ 64, 0xff, 0xfe, 0x0, 0x1, /* fffe:1:2:3::/64 */ @@ -178,7 +179,7 @@ static struct test_segment { AFI_IP6, SAFI_UNICAST, VALID_AFI, }, { "IPv6-nhlen3", - "IPV6 MP Reach, nexthop length overflow", + "IPV6 MP Reach, nexthop length overflow", { /* AFI / SAFI */ 0x0, AFI_IP6, SAFI_UNICAST, /* nexthop bytes */ 32, @@ -192,7 +193,7 @@ static struct test_segment { AFI_IP6, SAFI_UNICAST, VALID_AFI, }, { "IPv6-nhlen4", - "IPV6 MP Reach, nexthop length short", + "IPV6 MP Reach, nexthop length short", { /* AFI / SAFI */ 0x0, AFI_IP6, SAFI_UNICAST, /* nexthop bytes */ 16, @@ -205,7 +206,7 @@ static struct test_segment { 0x2, 0x10, 0x2, 0xff, 0x1, 0x2, 0x3, 0x4, /* SNPA (defunct, MBZ) */ 0x0, - /* NLRI tuples */ 32, + /* NLRI tuples */ 32, 0xff, 0xfe, 0x1, 0x2, /* fffe:102::/32 */ 64, 0xff, 0xfe, 0x0, 0x1, /* fffe:1:2:3::/64 */ @@ -217,7 +218,7 @@ static struct test_segment { AFI_IP6, SAFI_UNICAST, VALID_AFI, }, { "IPv6-nlri", - "IPV6 MP Reach, NLRI bitlen overflow", + "IPV6 MP Reach, NLRI bitlen overflow", { /* AFI / SAFI */ 0x0, AFI_IP6, SAFI_UNICAST, /* nexthop bytes */ 32, @@ -230,7 +231,7 @@ static struct test_segment { 0x2, 0x10, 0x2, 0xff, 0x1, 0x2, 0x3, 0x4, /* SNPA (defunct, MBZ) */ 0x0, - /* NLRI tuples */ 120, + /* NLRI tuples */ 120, 0xff, 0xfe, 0x1, 0x2, /* fffe:102::/32 */ 64, 0xff, 0xfe, 0x0, 0x1, /* fffe:1:2:3::/64 */ @@ -242,11 +243,11 @@ static struct test_segment { AFI_IP6, SAFI_UNICAST, VALID_AFI, }, { "IPv4", - "IPv4 MP Reach, 2 NLRIs + default", + "IPv4 MP Reach, 2 NLRIs + default", { /* AFI / SAFI */ 0x0, AFI_IP, SAFI_UNICAST, /* nexthop bytes */ 4, - /* Nexthop */ 192, 168, 0, 1, + /* Nexthop */ 192, 168, 0, 1, /* SNPA (defunct, MBZ) */ 0x0, /* NLRI tuples */ 16, 10, 1, /* 10.1/16 */ 17, 10, 2, 3, /* 10.2.3/17 */ @@ -257,11 +258,11 @@ static struct test_segment { AFI_IP, SAFI_UNICAST, VALID_AFI, }, { "IPv4-nhlen", - "IPv4 MP Reach, nexthop lenth overflow", + "IPv4 MP Reach, nexthop lenth overflow", { /* AFI / SAFI */ 0x0, AFI_IP, SAFI_UNICAST, /* nexthop bytes */ 32, - /* Nexthop */ 192, 168, 0, 1, + /* Nexthop */ 192, 168, 0, 1, /* SNPA (defunct, MBZ) */ 0x0, /* NLRI tuples */ 16, 10, 1, /* 10.1/16 */ 17, 10, 2, 3, /* 10.2.3/17 */ @@ -272,14 +273,14 @@ static struct test_segment { AFI_IP, SAFI_UNICAST, VALID_AFI, }, { "IPv4-nlrilen", - "IPv4 MP Reach, nlri lenth overflow", + "IPv4 MP Reach, nlri lenth overflow", { /* AFI / SAFI */ 0x0, AFI_IP, SAFI_UNICAST, /* nexthop bytes */ 4, - /* Nexthop */ 192, 168, 0, 1, + /* Nexthop */ 192, 168, 0, 1, /* SNPA (defunct, MBZ) */ 0x0, /* NLRI tuples */ 16, 10, 1, /* 10.1/16 */ - 30, 10, + 30, 10, 0, /* 0/0 */ }, (4 + 4 + 1 + 3 + 2 + 1), @@ -287,13 +288,13 @@ static struct test_segment { AFI_IP, SAFI_UNICAST, VALID_AFI, }, { "IPv4-vpnv4", - "IPv4/VPNv4 MP Reach, RD, Nexthop, 3 NLRIs", + "IPv4/VPNv4 MP Reach, RD, Nexthop, 3 NLRIs", { /* AFI / SAFI */ 0x0, AFI_IP, BGP_SAFI_VPNV4, /* nexthop bytes */ 12, /* RD */ 0, 0, 1, 2, 0, 0xff, 3, 4, - /* Nexthop */ 192, 168, 0, 1, + /* Nexthop */ 192, 168, 0, 1, /* SNPA (defunct, MBZ) */ 0x0, /* NLRI tuples */ 16, 10, 1, /* 10.1/16 */ 17, 10, 2, 3, /* 10.2.3/17 */ @@ -305,17 +306,17 @@ static struct test_segment { }, /* From bug #385 */ { "IPv6-bug", - "IPv6, global nexthop, 1 default NLRI", + "IPv6, global nexthop, 1 default NLRI", { /* AFI / SAFI */ 0x0, 0x2, 0x1, /* nexthop bytes */ 0x20, - /* Nexthop (global) */ 0x20, 0x01, 0x04, 0x70, + /* Nexthop (global) */ 0x20, 0x01, 0x04, 0x70, 0x00, 0x01, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, - /* Nexthop (local) */ 0xfe, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, + /* Nexthop (local) */ 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x0c, 0xdb, 0xff, + 0x02, 0x0c, 0xdb, 0xff, 0xfe, 0xfe, 0xeb, 0x00, /* SNPA (defunct, MBZ) */ 0, /* NLRI tuples */ /* Should have 0 here for ::/0, but dont */ @@ -324,7 +325,7 @@ static struct test_segment { SHOULD_ERR, AFI_IP6, SAFI_UNICAST, VALID_AFI, }, - + { NULL, NULL, {0}, 0, 0} }; @@ -332,34 +333,34 @@ static struct test_segment { static struct test_segment mp_unreach_segments [] = { { "IPv6-unreach", - "IPV6 MP Unreach, 1 NLRI", + "IPV6 MP Unreach, 1 NLRI", { /* AFI / SAFI */ 0x0, AFI_IP6, SAFI_UNICAST, /* NLRI tuples */ 32, 0xff, 0xfe, 0x1, 0x2, /* fffe:102::/32 */ }, - (3 + 5), + (3 + 5), SHOULD_PARSE, AFI_IP6, SAFI_UNICAST, VALID_AFI, }, { "IPv6-unreach2", - "IPV6 MP Unreach, 2 NLRIs", + "IPV6 MP Unreach, 2 NLRIs", { /* AFI / SAFI */ 0x0, AFI_IP6, SAFI_UNICAST, - /* NLRI tuples */ 32, + /* NLRI tuples */ 32, 0xff, 0xfe, 0x1, 0x2, /* fffe:102::/32 */ 64, 0xff, 0xfe, 0x0, 0x1, /* fffe:1:2:3::/64 */ 0x0, 0x2, 0x0, 0x3, }, - (3 + 5 + 9), + (3 + 5 + 9), SHOULD_PARSE, AFI_IP6, SAFI_UNICAST, VALID_AFI, }, { "IPv6-unreach-default", - "IPV6 MP Unreach, 2 NLRIs + default", + "IPV6 MP Unreach, 2 NLRIs + default", { /* AFI / SAFI */ 0x0, AFI_IP6, SAFI_UNICAST, - /* NLRI tuples */ 32, + /* NLRI tuples */ 32, 0xff, 0xfe, 0x1, 0x2, /* fffe:102::/32 */ 64, 0xff, 0xfe, 0x0, 0x1, /* fffe:1:2:3::/64 */ @@ -371,10 +372,10 @@ static struct test_segment mp_unreach_segments [] = AFI_IP6, SAFI_UNICAST, VALID_AFI, }, { "IPv6-unreach-nlri", - "IPV6 MP Unreach, NLRI bitlen overflow", + "IPV6 MP Unreach, NLRI bitlen overflow", { /* AFI / SAFI */ 0x0, AFI_IP6, SAFI_UNICAST, - /* NLRI tuples */ 120, + /* NLRI tuples */ 120, 0xff, 0xfe, 0x1, 0x2, /* fffe:102::/32 */ 64, 0xff, 0xfe, 0x0, 0x1, /* fffe:1:2:3::/64 */ @@ -386,7 +387,7 @@ static struct test_segment mp_unreach_segments [] = AFI_IP6, SAFI_UNICAST, VALID_AFI, }, { "IPv4-unreach", - "IPv4 MP Unreach, 2 NLRIs + default", + "IPv4 MP Unreach, 2 NLRIs + default", { /* AFI / SAFI */ 0x0, AFI_IP, SAFI_UNICAST, /* NLRI tuples */ 16, 10, 1, /* 10.1/16 */ @@ -398,11 +399,11 @@ static struct test_segment mp_unreach_segments [] = AFI_IP, SAFI_UNICAST, VALID_AFI, }, { "IPv4-unreach-nlrilen", - "IPv4 MP Unreach, nlri length overflow", + "IPv4 MP Unreach, nlri length overflow", { /* AFI / SAFI */ 0x0, AFI_IP, SAFI_UNICAST, /* NLRI tuples */ 16, 10, 1, /* 10.1/16 */ - 30, 10, + 30, 10, 0, /* 0/0 */ }, (3 + 3 + 2 + 1), @@ -410,13 +411,13 @@ static struct test_segment mp_unreach_segments [] = AFI_IP, SAFI_UNICAST, VALID_AFI, }, { "IPv4-unreach-vpnv4", - "IPv4/VPNv4 MP Unreach, RD, 3 NLRIs", + "IPv4/VPNv4 MP Unreach, RD, 3 NLRIs", { /* AFI / SAFI */ 0x0, AFI_IP, BGP_SAFI_VPNV4, /* nexthop bytes */ 12, /* RD */ 0, 0, 1, 2, 0, 0xff, 3, 4, - /* Nexthop */ 192, 168, 0, 1, + /* Nexthop */ 192, 168, 0, 1, /* SNPA (defunct, MBZ) */ 0x0, /* NLRI tuples */ 16, 10, 1, /* 10.1/16 */ 17, 10, 2, 3, /* 10.2.3/17 */ @@ -439,13 +440,13 @@ parse_test (struct peer *peer, struct test_segment *t, int type) struct attr attr; struct bgp_nlri nlri; #define RANDOM_FUZZ 35 - + stream_reset (peer->ibuf); stream_put (peer->ibuf, NULL, RANDOM_FUZZ); stream_set_getp (peer->ibuf, RANDOM_FUZZ); - + stream_write (peer->ibuf, t->data, t->len); - + printf ("%s: %s\n", t->name, t->desc); if (type == BGP_ATTR_MP_REACH_NLRI) @@ -456,30 +457,30 @@ parse_test (struct peer *peer, struct test_segment *t, int type) if (!ret) { safi_t safi = t->safi; - + if (bgp_afi_safi_valid_indices (t->afi, &safi) != t->afi_valid) failed++; - + printf ("MP: %u/%u (%u): recv %u, nego %u\n", t->afi, t->safi, safi, peer->afc_recv[t->afi][safi], peer->afc_nego[t->afi][safi]); } - + printf ("parsed?: %s\n", ret ? "no" : "yes"); - + if (ret != t->parses) failed++; - + if (tty) - printf ("%s", (failed > oldfailed) ? VT100_RED "failed!" VT100_RESET + printf ("%s", (failed > oldfailed) ? VT100_RED "failed!" VT100_RESET : VT100_GREEN "OK" VT100_RESET); else printf ("%s", (failed > oldfailed) ? "failed!" : "OK" ); - + if (failed) printf (" (%u)", failed); - + printf ("\n\n"); } @@ -491,7 +492,7 @@ main (void) { struct peer *peer; int i, j; - + conf_bgp_debug_fsm = -1UL; conf_bgp_debug_events = -1UL; conf_bgp_debug_packet = -1UL; @@ -502,26 +503,26 @@ main (void) term_bgp_debug_packet = -1UL; term_bgp_debug_normal = -1UL; term_bgp_debug_as4 = -1UL; - + master = thread_master_create (); bgp_master_init (); - - if (fileno (stdout) >= 0) + + if (fileno (stdout) >= 0) tty = isatty (fileno (stdout)); - + if (bgp_get (&bgp, &asn, NULL)) return -1; - + peer = peer_create_accept (bgp); - peer->host = "foo"; - + peer->host = miyagi("foo") ; + for (i = AFI_IP; i < AFI_MAX; i++) for (j = SAFI_UNICAST; j < SAFI_MAX; j++) { peer->afc[i][j] = 1; peer->afc_adv[i][j] = 1; } - + i = 0; while (mp_reach_segments[i].name) parse_test (peer, &mp_reach_segments[i++], BGP_ATTR_MP_REACH_NLRI); diff --git a/tests/ecommunity_test.c b/tests/ecommunity_test.c index 418f659f..3a67228d 100644 --- a/tests/ecommunity_test.c +++ b/tests/ecommunity_test.c @@ -1,4 +1,5 @@ #include <zebra.h> +#include "miyagi.h" #include "vty.h" #include "stream.h" @@ -15,7 +16,7 @@ struct thread_master *master = NULL; static int failed = 0; /* specification for a test - what the results should be */ -struct test_spec +struct test_spec { const char *shouldbe; /* the string the path should parse to */ }; @@ -28,7 +29,7 @@ static struct test_segment { const u_char data[1024]; int len; struct test_spec sp; -} test_segments [] = +} test_segments [] = { { /* 0 */ "ipaddr", @@ -73,7 +74,7 @@ validate (struct ecommunity *ecom, const struct test_spec *sp) int fails = 0; struct ecommunity *etmp; char *str1, *str2; - + printf ("got:\n %s\n", ecommunity_str (ecom)); str1 = ecommunity_ecom2str (ecom, ECOMMUNITY_FORMAT_COMMUNITY_LIST); etmp = ecommunity_str2com (str1, 0, 1); @@ -81,7 +82,7 @@ validate (struct ecommunity *ecom, const struct test_spec *sp) str2 = ecommunity_ecom2str (etmp, ECOMMUNITY_FORMAT_COMMUNITY_LIST); else str2 = NULL; - + if (strcmp (sp->shouldbe, str1)) { failed++; @@ -94,13 +95,13 @@ validate (struct ecommunity *ecom, const struct test_spec *sp) fails++; printf ("dogfood: in %s\n" " in->out %s\n", - str1, + str1, (etmp && str2) ? str2 : "NULL"); } - ecommunity_free (etmp); + ecommunity_free (&etmp); XFREE (MTYPE_ECOMMUNITY_STR, str1); XFREE (MTYPE_ECOMMUNITY_STR, str2); - + return fails; } @@ -109,10 +110,10 @@ static void parse_test (struct test_segment *t) { struct ecommunity *ecom; - + printf ("%s: %s\n", t->name, t->desc); - ecom = ecommunity_parse (t->data, t->len); + ecom = ecommunity_parse (miyagi(t->data), t->len); printf ("ecom: %s\nvalidating...:\n", ecommunity_str (ecom)); @@ -120,12 +121,12 @@ parse_test (struct test_segment *t) printf ("OK\n"); else printf ("failed\n"); - + printf ("\n"); - ecommunity_unintern (ecom); + ecommunity_unintern (&ecom); } - + int main (void) { @@ -133,7 +134,7 @@ main (void) ecommunity_init(); while (test_segments[i].name) parse_test (&test_segments[i++]); - + printf ("failures: %d\n", failed); //printf ("aspath count: %ld\n", aspath_count()); return failed; diff --git a/tests/heavy-thread.c b/tests/heavy-thread.c index cd3a3b9d..f7a99cc5 100644 --- a/tests/heavy-thread.c +++ b/tests/heavy-thread.c @@ -59,17 +59,17 @@ slow_func (struct vty *vty, const char *str, const int i) { double x = 1; int j; - + for (j = 0; j < 300; j++) x += sin(x)*j; - + if ((i % ITERS_LATER) == 0) printf ("%s: %d, temporary error, save this somehow and do it later..\n", __func__, i); - + if ((i % ITERS_ERR) == 0) printf ("%s: hard error\n", __func__); - + if ((i % ITERS_PRINT) == 0) printf ("%s did %d, x = %g\n", str, i, x); } @@ -78,8 +78,8 @@ static int clear_something (struct thread *thread) { struct work_state *ws = THREAD_ARG(thread); - - /* this could be like iterating through 150k of route_table + + /* this could be like iterating through 150k of route_table * or worse, iterating through a list of peers, to bgp_stop them with * each having 150k route tables to process... */ @@ -93,7 +93,7 @@ clear_something (struct thread *thread) return 0; } } - + /* All done! */ XFREE (MTYPE_TMP, ws->str); XFREE (MTYPE_TMP, ws); @@ -114,22 +114,22 @@ DEFUN (clear_foo, vty_out (vty, "%% string argument required%s", VTY_NEWLINE); return CMD_WARNING; } - + str = argv_concat (argv, argc, 0); - + if ((ws = XMALLOC(MTYPE_TMP, sizeof(*ws))) == NULL) { zlog_err ("%s: unable to allocate work_state", __func__); return CMD_WARNING; } - + if (!(ws->str = XSTRDUP (MTYPE_TMP, str))) { zlog_err ("%s: unable to xstrdup", __func__); XFREE (MTYPE_TMP, ws); return CMD_WARNING; } - + ws->vty = vty; ws->i = ITERS_FIRST; @@ -138,8 +138,10 @@ DEFUN (clear_foo, return CMD_SUCCESS; } +extern void test_init(void) ; + void -test_init() +test_init(void) { install_element (VIEW_NODE, &clear_foo_cmd); } diff --git a/tests/heavy-wq.c b/tests/heavy-wq.c index a2c609d4..bf3ab85a 100644 --- a/tests/heavy-wq.c +++ b/tests/heavy-wq.c @@ -66,7 +66,7 @@ heavy_wq_add (struct vty *vty, const char *str, int i) zlog_err ("%s: unable to allocate hn", __func__); return; } - + hn->i = i; if (!(hn->str = XSTRDUP (MTYPE_PREFIX_LIST_STR, str))) { @@ -74,47 +74,47 @@ heavy_wq_add (struct vty *vty, const char *str, int i) XFREE (MTYPE_PREFIX_LIST, hn); return; } - + work_queue_add (heavy_wq, hn); - + return; } static void -slow_func_err (struct work_queue *wq, struct work_queue_item *item) +slow_func_err (struct work_queue *wq, work_queue_item item) { printf ("%s: running error function\n", __func__); } static void -slow_func_del (struct work_queue *wq, void *data) +slow_func_del (struct work_queue *wq, work_queue_item item) { - struct heavy_wq_node *hn = data; + struct heavy_wq_node *hn = item->args.data; assert (hn && hn->str); printf ("%s: %s\n", __func__, hn->str); XFREE (MTYPE_PREFIX_LIST_STR, hn->str); - hn->str = NULL; + hn->str = NULL; XFREE(MTYPE_PREFIX_LIST, hn); } static wq_item_status -slow_func (struct work_queue *wq, void *data) +slow_func (struct work_queue *wq, work_queue_item item) { - struct heavy_wq_node *hn = data; + struct heavy_wq_node *hn = item->args.data; double x = 1; int j; - + assert (hn && hn->str); - + for (j = 0; j < 300; j++) x += sin(x)*j; - + if ((hn->i % ITERS_LATER) == 0) return WQ_RETRY_LATER; - + if ((hn->i % ITERS_ERR) == 0) return WQ_RETRY_NOW; - + if ((hn->i % ITERS_PRINT) == 0) printf ("%s did %d, x = %g\n", hn->str, hn->i, x); @@ -125,8 +125,8 @@ static void clear_something (struct vty *vty, const char *str) { int i; - - /* this could be like iterating through 150k of route_table + + /* this could be like iterating through 150k of route_table * or worse, iterating through a list of peers, to bgp_stop them with * each having 150k route tables to process... */ @@ -146,9 +146,9 @@ DEFUN (clear_foo, vty_out (vty, "%% string argument required%s", VTY_NEWLINE); return CMD_WARNING; } - + str = argv_concat (argv, argc, 0); - + clear_something (vty, str); XFREE (MTYPE_TMP, str); return CMD_SUCCESS; @@ -162,18 +162,20 @@ heavy_wq_init () zlog_err ("%s: could not get new work queue!", __func__); return -1; } - - heavy_wq->spec.workfunc = &slow_func; - heavy_wq->spec.errorfunc = &slow_func_err; + + heavy_wq->spec.workfunc = &slow_func; + heavy_wq->spec.errorfunc = &slow_func_err; heavy_wq->spec.del_item_data = &slow_func_del; - heavy_wq->spec.max_retries = 3; - heavy_wq->spec.hold = 1000; - + heavy_wq->spec.max_retries = 3; + heavy_wq->spec.hold = 1000; + return 0; } -void -test_init() +extern void test_init(void) ; + +extern void +test_init(void) { install_element (VIEW_NODE, &clear_foo_cmd); heavy_wq_init(); diff --git a/tests/heavy.c b/tests/heavy.c index 577a4816..901fb10f 100644 --- a/tests/heavy.c +++ b/tests/heavy.c @@ -50,27 +50,27 @@ slow_func (struct vty *vty, const char *str, const int i) { double x = 1; int j; - + for (j = 0; j < 300; j++) x += sin(x)*j; - + if ((i % ITERS_LATER) == 0) - printf ("%s: %d, temporary error, save this somehow and do it later..\n", + printf ("%s: %d, temporary error, save this somehow and do it later..\n", __func__, i); - + if ((i % ITERS_ERR) == 0) printf ("%s: hard error\n", __func__); - + if ((i % ITERS_PRINT) == 0) - printf ("%s did %d, x = %g%s", str, i, x, VTY_NEWLINE); + printf ("%s did %d, x = %g%s", str, i, x, VTY_NEWLINE); } static void clear_something (struct vty *vty, const char *str) { int i; - - /* this could be like iterating through 150k of route_table + + /* this could be like iterating through 150k of route_table * or worse, iterating through a list of peers, to bgp_stop them with * each having 150k route tables to process... */ @@ -90,9 +90,9 @@ DEFUN (clear_foo, vty_out (vty, "%% string argument required%s", VTY_NEWLINE); return CMD_WARNING; } - + str = argv_concat (argv, argc, 0); - + clear_something (vty, str); XFREE (MTYPE_TMP, str); return CMD_SUCCESS; @@ -104,8 +104,10 @@ slow_vty_init() install_element (VIEW_NODE, &clear_foo_cmd); } -void -test_init() +extern void test_init(void) ; + +extern void +test_init(void) { slow_vty_init(); } diff --git a/tests/main.c b/tests/main.c index e0fbb4d5..f735e1e1 100644 --- a/tests/main.c +++ b/tests/main.c @@ -32,7 +32,7 @@ extern void test_init(); struct thread_master *master; -struct option longopts[] = +struct option longopts[] = { { "daemon", no_argument, NULL, 'd'}, { "config_file", required_argument, NULL, 'f'}, @@ -51,12 +51,14 @@ DEFUN (daemon_exit, exit(0); } +extern int test_timer (struct thread *thread) ; + static int timer_count; -int +extern int test_timer (struct thread *thread) { int *count = THREAD_ARG(thread); - + printf ("run %d of timer\n", (*count)++); thread_add_timer (master, test_timer, count, 5); return 0; @@ -81,7 +83,7 @@ usage (char *progname, int status) if (status != 0) fprintf (stderr, "Try `%s --help' for more information.\n", progname); else - { + { printf ("Usage : %s [OPTION...]\n\ Daemon which does 'slow' things.\n\n\ -d, --daemon Runs in daemon mode\n\ @@ -95,8 +97,8 @@ Report bugs to %s\n", progname, ZEBRA_BUG_ADDRESS); } exit (status); } - - + + /* main routine. */ int main (int argc, char **argv) @@ -108,7 +110,7 @@ main (int argc, char **argv) char *progname; struct thread thread; char *config_file = NULL; - + /* Set umask before anything for security */ umask (0027); @@ -118,16 +120,16 @@ main (int argc, char **argv) /* master init. */ master = thread_master_create (); - while (1) + while (1) { int opt; opt = getopt_long (argc, argv, "dhf:A:P:v", longopts, 0); - + if (opt == EOF) break; - switch (opt) + switch (opt) { case 0: break; @@ -146,7 +148,7 @@ main (int argc, char **argv) { vty_port = 0; break; - } + } vty_port = atoi (optarg); vty_port = (vty_port ? vty_port : 4000); break; @@ -182,16 +184,16 @@ main (int argc, char **argv) /* Create VTY socket */ vty_serv_sock (vty_addr, vty_port, "/tmp/.heavy.sock"); - + /* Configuration file read*/ if (!config_file) usage (progname, 1); vty_read_config (config_file, NULL); - + test_timer_init(); - - test_init(); - + + test_init(); + /* Fetch next active thread. */ while (thread_fetch (master, &thread)) thread_call (&thread); diff --git a/tests/test-checksum.c b/tests/test-checksum.c index bd156baa..076dd4ad 100644 --- a/tests/test-checksum.c +++ b/tests/test-checksum.c @@ -13,7 +13,7 @@ struct acc_vals { struct csum_vals { struct acc_vals a; - int x; + int x; int y; }; @@ -24,25 +24,27 @@ typedef uint16_t testoff_t; /* Fletcher Checksum -- Refer to RFC1008. */ #define MODX 4102 - + /* Accumulator phase of checksum */ -static -struct acc_vals +static struct acc_vals +accumulate (u_char *buffer, testsz_t len, testoff_t off) + __attribute__((unused)) ; +static struct acc_vals accumulate (u_char *buffer, testsz_t len, testoff_t off) { u_int8_t *p; u_int16_t *csum; int i, init_len, partial_len; struct acc_vals ret; - + csum = (u_int16_t *) (buffer + off); *(csum) = 0; - + p = buffer; ret.c0 = 0; ret.c1 = 0; init_len = len; - + while (len != 0) { partial_len = MIN(len, MODX); @@ -62,9 +64,9 @@ accumulate (u_char *buffer, testsz_t len, testoff_t off) } /* The final reduction phase. - * This one should be the original ospfd version + * This one should be the original ospfd version */ -static u_int16_t +static u_int16_t reduce_ospfd (struct csum_vals *vals, testsz_t len, testoff_t off) { #define x vals->x @@ -73,7 +75,7 @@ reduce_ospfd (struct csum_vals *vals, testsz_t len, testoff_t off) #define c1 vals->a.c1 x = ((len - off - 1) * c0 - c1) % 255; - + if (x <= 0) x += 255; y = 510 - c0 - x; @@ -81,7 +83,7 @@ reduce_ospfd (struct csum_vals *vals, testsz_t len, testoff_t off) y -= 255; /* take care endian issue. */ - return htons ((x << 8) + y); + return htons ((x << 8) + y); #undef x #undef y #undef c0 @@ -89,7 +91,7 @@ reduce_ospfd (struct csum_vals *vals, testsz_t len, testoff_t off) } /* slightly different concatenation */ -static u_int16_t +static u_int16_t reduce_ospfd1 (struct csum_vals *vals, testsz_t len, testoff_t off) { #define x vals->x @@ -105,7 +107,7 @@ reduce_ospfd1 (struct csum_vals *vals, testsz_t len, testoff_t off) y -= 255; /* take care endian issue. */ - return htons ((x << 8) | (y & 0xff)); + return htons ((x << 8) | (y & 0xff)); #undef x #undef y #undef c0 @@ -113,7 +115,7 @@ reduce_ospfd1 (struct csum_vals *vals, testsz_t len, testoff_t off) } /* original isisd version */ -static u_int16_t +static u_int16_t reduce_isisd (struct csum_vals *vals, testsz_t len, testoff_t off) { #define x vals->x @@ -121,7 +123,7 @@ reduce_isisd (struct csum_vals *vals, testsz_t len, testoff_t off) #define c0 vals->a.c0 #define c1 vals->a.c1 u_int32_t mul; - + mul = (len - off)*(c0); x = mul - c0 - c1; y = c1 - mul - 1; @@ -148,7 +150,7 @@ reduce_isisd (struct csum_vals *vals, testsz_t len, testoff_t off) } /* Is the -1 in y wrong perhaps? */ -static u_int16_t +static u_int16_t reduce_isisd_yfix (struct csum_vals *vals, testsz_t len, testoff_t off) { #define x vals->x @@ -156,7 +158,7 @@ reduce_isisd_yfix (struct csum_vals *vals, testsz_t len, testoff_t off) #define c0 vals->a.c0 #define c1 vals->a.c1 u_int32_t mul; - + mul = (len - off)*(c0); x = mul - c0 - c1; y = c1 - mul; @@ -183,7 +185,7 @@ reduce_isisd_yfix (struct csum_vals *vals, testsz_t len, testoff_t off) } /* Move the mods yp */ -static u_int16_t +static u_int16_t reduce_isisd_mod (struct csum_vals *vals, testsz_t len, testoff_t off) { #define x vals->x @@ -191,7 +193,7 @@ reduce_isisd_mod (struct csum_vals *vals, testsz_t len, testoff_t off) #define c0 vals->a.c0 #define c1 vals->a.c1 u_int32_t mul; - + mul = (len - off)*(c0); x = mul - c1 - c0; y = c1 - mul - 1; @@ -218,7 +220,7 @@ reduce_isisd_mod (struct csum_vals *vals, testsz_t len, testoff_t off) } /* Move the mods up + fix y */ -static u_int16_t +static u_int16_t reduce_isisd_mody (struct csum_vals *vals, testsz_t len, testoff_t off) { #define x vals->x @@ -226,7 +228,7 @@ reduce_isisd_mody (struct csum_vals *vals, testsz_t len, testoff_t off) #define c0 vals->a.c0 #define c1 vals->a.c1 u_int32_t mul; - + mul = (len - off)*(c0); x = mul - c0 - c1; y = c1 - mul; @@ -264,7 +266,7 @@ struct reductions_t { { .name = "isisd-mody", .f = reduce_isisd_mody }, { NULL, NULL }, }; - + /* The original ospfd checksum */ static u_int16_t ospfd_checksum (u_char *buffer, testsz_t len, testoff_t off) @@ -276,7 +278,7 @@ ospfd_checksum (u_char *buffer, testsz_t len, testoff_t off) csum = (u_int16_t *) (buffer + off); *(csum) = 0; - + sp = buffer; for (ep = sp + len; sp < ep; sp = q) @@ -292,27 +294,27 @@ ospfd_checksum (u_char *buffer, testsz_t len, testoff_t off) c0 %= 255; c1 %= 255; } - + ospfd_vals.a.c0 = c0; ospfd_vals.a.c1 = c1; - + //printf ("%s: len %u, off %u, c0 %d, c1 %d\n", // __func__, len, off, c0, c1); x = ((int)(len - off - 1) * (int)c0 - (int)c1) % 255; - + if (x <= 0) x += 255; y = 510 - c0 - x; if (y > 255) y -= 255; - + ospfd_vals.x = x; ospfd_vals.y = y; - + buffer[off] = x; buffer[off + 1] = y; - + /* take care endian issue. */ checksum = htons ((x << 8) | (y & 0xff)); @@ -334,15 +336,15 @@ iso_csum_create (u_char * buffer, testsz_t len, testoff_t off) int i, init_len, partial_len; checksum = 0; - + csum = (u_int16_t *) (buffer + off); *(csum) = checksum; - + p = buffer; c0 = 0; c1 = 0; init_len = len; - + while (len != 0) { partial_len = MIN(len, MODX); @@ -361,7 +363,7 @@ iso_csum_create (u_char * buffer, testsz_t len, testoff_t off) isisd_vals.a.c0 = c0; isisd_vals.a.c1 = c1; - + mul = (init_len - off) * c0; x = mul - c1 - c0; @@ -379,14 +381,14 @@ iso_csum_create (u_char * buffer, testsz_t len, testoff_t off) x = 255; if (y == 0) y = 1; - + isisd_vals.x = x; isisd_vals.y = y; - + checksum = htons((x << 8) | (y & 0xFF)); - + *(csum) = checksum; - + /* return the checksum for user usage */ return checksum; } @@ -399,7 +401,7 @@ verify (u_char * buffer, testsz_t len) u_int32_t c1; u_int16_t checksum; int i, partial_len; - + p = buffer; checksum = 0; @@ -427,6 +429,8 @@ verify (u_char * buffer, testsz_t len) return 1; } +extern int in_cksum_optimized(void *parg, int nbytes) ; + int /* return checksum in low-order 16 bits */ in_cksum_optimized(void *parg, int nbytes) { @@ -458,6 +462,7 @@ in_cksum_optimized(void *parg, int nbytes) return(answer); } +extern int in_cksum_rfc(void *parg, int count) ; int /* return checksum in low-order 16 bits */ in_cksum_rfc(void *parg, int count) @@ -495,29 +500,29 @@ main(int argc, char **argv) u_char buffer[BUFSIZE]; int exercise = 0; #define EXERCISESTEP 257 - + srandom (time (NULL)); - + while (1) { u_int16_t ospfd, isisd, lib, in_csum, in_csum_res, in_csum_rfc; int i,j; exercise += EXERCISESTEP; exercise %= MAXDATALEN; - + for (i = 0; i < exercise; i += sizeof (long int)) { long int rand = random (); - + for (j = sizeof (long int); j > 0; j--) buffer[i + (sizeof (long int) - j)] = (rand >> (j * 8)) & 0xff; } - + in_csum = in_cksum(buffer, exercise); in_csum_res = in_cksum_optimized(buffer, exercise); in_csum_rfc = in_cksum_rfc(buffer, exercise); if (in_csum_res != in_csum || in_csum != in_csum_rfc) printf ("verify: in_chksum failed in_csum:%x, in_csum_res:%x," - "in_csum_rfc %x, len:%d\n", + "in_csum_rfc %x, len:%d\n", in_csum, in_csum_res, in_csum_rfc, exercise); ospfd = ospfd_checksum (buffer, exercise + sizeof(u_int16_t), exercise); @@ -529,7 +534,7 @@ main(int argc, char **argv) lib = fletcher_checksum (buffer, exercise + sizeof(u_int16_t), exercise); if (verify (buffer, exercise + sizeof(u_int16_t))) printf ("verify: lib failed\n"); - + if (ospfd != lib) { printf ("Mismatch in values at size %u\n" "ospfd: 0x%04x\tc0: %d\tc1: %d\tx: %d\ty: %d\n" @@ -540,12 +545,12 @@ main(int argc, char **argv) isisd, isisd_vals.a.c0, isisd_vals.a.c1, isisd_vals.x, isisd_vals.y, lib ); - + /* Investigate reduction phase discrepencies */ if (ospfd_vals.a.c0 == isisd_vals.a.c0 && ospfd_vals.a.c1 == isisd_vals.a.c1) { printf ("\n"); - for (i = 0; reducts[i].name != NULL; i++) { + for (i = 0; reducts[i].name != NULL; i++) { ospfd = reducts[i].f (&ospfd_vals, exercise + sizeof (u_int16_t), exercise); @@ -553,7 +558,7 @@ main(int argc, char **argv) reducts[i].name, ospfd_vals.x & 0xff, ospfd_vals.y & 0xff, ospfd); } } - + printf ("\n u_char testdata [] = {\n "); for (i = 0; i < exercise; i++) { printf ("0x%02x,%s", diff --git a/tests/test-list_util.c b/tests/test-list_util.c new file mode 100644 index 00000000..fc81a562 --- /dev/null +++ b/tests/test-list_util.c @@ -0,0 +1,2112 @@ +#include <zebra.h> +#include <list_util.h> +#include <string.h> + +/* List util torture tests + * + */ + +struct thread_master *master; /* allow lib/zebra.c to link ! */ + +/* prototypes */ +int main(int argc, char **argv); + +static void test_ssl(void); +static void test_sdl(void); +static void test_ddl(void); + +#define test_assert(true, message) \ + do { if (!(true)) test_assert_fail(#true, message, __func__, __LINE__) ; \ + } while (0) + +static void +test_assert_fail(const char* true, const char* message, const char* func, + int line) +{ + printf("*** %s %d: (%s) not true: %s\n", func, line, true, message) ; + +} ; + +/*============================================================================== + * The tests. + */ +int +main(int argc, char **argv) +{ + printf("Starting list_util tests -- %s\n", +#ifdef __GNUC__LIST_UTIL + "GNUC version" +#else + "not GNUC version" +#endif + " -- v0.01 26-Feb-2010") ; + + srand(22) ; /* Consistent testing required */ + + test_ssl() ; + test_sdl() ; + test_ddl() ; + + return 0; +} + +/*------------------------------------------------------------------------------ + * Construct a majic mark from two addresses + */ +static unsigned majic(void* a, void* b) +{ + uintptr_t z = (uintptr_t)a ^ (uintptr_t)b ^ (uintptr_t)&majic ; + return z ; +} ; + +/*============================================================================== + * Single Base, Single Link + * + * ssl_push(base, item, next) -- add at head of list + * ssl_del(base, item, next) -- delete from list + * ssl_del_head(base, next) -- delete head of list + * ssl_pop(dst, base, next) -- pop head of list, if any + * ssl_head(base) -- return head of list + * ssl_next(item, next) -- step to next item, if any + * + * Cases to cover: + * + * a) adding when list is empty + * b) adding when list is not empty + * c) deletion of first item and more than one item on list + * d) deletion of first item when only one item on the list + * e) deletion of arbitrary item (list implicitly not empty) + * f) deletion when item not on list and list not empty + * g) deletion when item not on list and list is empty + * h) deletion of NULL item and list not empty + * i) deletion of NULL item and list empty + * j) pop of head when list not empty + * k) pop of head when list contains one item + * l) pop of head when list empty + * m) deletion of head when list not empty + * n) deletion of head when contains one item + * o) deletion of head when list empty + * p) head when list not empty + * q) head when list is empty + * r) next when not last + * s) next when last + */ + +typedef struct ssl_test* ssl_test ; +struct ssl_test +{ + ssl_test next ; /* pointer at start of structure */ + + unsigned majic ; + char dummy ; + + ssl_test other_next ; /* pointer elsewhere in structure */ +} ; + +struct ssl_test_parent +{ + unsigned rubbish ; + char fred ; + + ssl_test base ; + + int z[5] ; +} ; + +static struct ssl_test_parent ssl_parent ; + +static void +test_ssl(void) +{ + ssl_test base = NULL ; + + ssl_test del = NULL ; + ssl_test other_del = NULL ; + ssl_test last = NULL ; + ssl_test first = NULL ; + + struct ssl_test dummy ; + + int n = 47 ; + + int i_del = 7 ; /* NB: neither of these may be 0 or 1 */ + int i_other_del = 37 ; + + ssl_test prev ; + ssl_test this ; + ssl_test other_this ; + ssl_test take ; + ssl_test temp ; + + int i ; + int ret ; + + static struct ssl_test_parent* other = &ssl_parent ; + + memset(other, 77, sizeof(struct ssl_test_parent)) ; + other->base = NULL ; + + /* Repeated insertion, starting from empty list + * + * a) adding when list is empty + * b) adding when list is not empty + * + * Creates lists for following tests. + */ + printf("=== Testing ssl -- Single Base, Single Link -- stuff\n") ; + + printf(" Creating list of items") ; + for (i = 1 ; i <= n ; ++i) + { + ssl_test this = calloc(1, sizeof(struct ssl_test)) ; + + if (last == NULL) + last = this ; + + this->majic = majic(this, &base) ; + + this->dummy = i ; + + ssl_push(base, this, next) ; + if (i & 1) + ssl_push(other->base, this, other_next) ; + else + ssl_push(ssl_parent.base, this, other_next) ; + + if (i == i_del) + del = this ; + if (i == i_other_del) + other_del = this ; + + first = this ; + + printf("+") ; + } ; + + test_assert((base == first) && (other->base == first), + "Failed to create consistent lists") ; + printf("\n") ; + + passert((del != base) && (del != last)) ; + passert((other_del != base) && (other_del != last)) ; + + /* Walk to check that have the expected items + * + * l) head when list not empty + * r) next when not last + * s) next when last + */ + printf(" Walking list of items") ; + + this = ssl_head(base) ; + test_assert(this == first, "ssl_head failed") ; + + this = ssl_head(other->base) ; + test_assert(this == first, "ssl_head failed") ; + + this = ssl_head(ssl_parent.base) ; + test_assert(this == first, "ssl_head failed") ; + + this = ssl_next(del, next) ; + test_assert((this == del->next) && (this != NULL), "ssl_next failed") ; + this = ssl_next(last, next) ; + test_assert((this == last->next) && (this == NULL), + "ssl_next failed at end") ; + + this = ssl_next(other_del, other_next) ; + test_assert((this == other_del->other_next) && (this != NULL), + "ssl_next failed") ; + this = ssl_next(last, other_next) ; + test_assert((this == last->other_next) && (this == NULL), + "ssl_next failed at end") ; + + this = base ; + other_this = other->base ; + + prev = NULL ; + i = n ; + while (1) + { + test_assert(this == other_this, "this and other_this not in step") ; + if (this == NULL) + break ; + + test_assert(this != prev, "this is same as prev") ; + prev = this ; + + test_assert(this->dummy == i--, "don't have the right dummy") ; + test_assert(this->majic == majic(this, &base), + "don't have the right majic") ; + + printf(".") ; + this = ssl_next(this, next) ; + other_this = ssl_next(other_this, other_next) ; + } ; + printf("\n") ; + + /* Deletion specifically at the start of the list + * + * c) deletion of first item and more than one item on list + */ + printf(" Deleting the first item") ; + + this = base ; + first = base->next ; + ret = ssl_del(base, this, next) ; + test_assert(ret == 0, "ssl_del did not return 0") ; + test_assert(first == base, "ssl_del of first item failed") ; + + this = other->base ; + ret = ssl_del(other->base, this, other_next) ; + test_assert(ret == 0, "ssl_del did not return 0") ; + test_assert(first == other->base, "ssl_del of first item failed") ; + + printf("\n") ; + + --n ; /* one less on the lists ! */ + + /* Deletion of items from arbitrary place in list + * + * e) deletion of arbitrary item (list implicitly not empty) + */ + printf(" Deleting arbitrary items") ; + ret = ssl_del(base, del, next) ; + test_assert(ret == 0, "ssl_del did not return 0") ; + ret = ssl_del(ssl_parent.base, other_del, other_next) ; + test_assert(ret == 0, "ssl_del did not return 0") ; + printf("\n") ; + + /* Deletion of items from arbitrary place in list + * + * f) deletion when item not on list and list not empty + */ + printf(" Deleting non-existant items") ; + ret = ssl_del(base, &dummy, next) ; + test_assert(ret == -1, "ssl_del did not return -1") ; + ret = ssl_del(other->base, &dummy, other_next) ; + test_assert(ret == -1, "ssl_del did not return -1") ; + printf("\n") ; + + /* Deletion of NULL items + * + * h) deletion of NULL item and list not empty + */ + printf(" Deleting NULL items") ; + + this = NULL ; + + ret = ssl_del(base, this, next) ; + test_assert(ret == 0, "ssl_del did not return 0") ; + + ret = ssl_del(ssl_parent.base, this, other_next) ; + test_assert(ret == 0, "ssl_del did not return 0") ; + + printf("\n") ; + + /* Scan lists to check after deletion */ + printf(" Base list scan") ; + + this = base ; + prev = NULL ; + i = n ; + while (1) + { + if (this == NULL) + break ; + + test_assert(this != prev, "this is same as prev") ; + prev = this ; + + if (i == i_del) + --i ; + + test_assert(this->dummy == i--, "don't have the right dummy") ; + test_assert(this->majic == majic(this, &base), + "don't have the right majic") ; + + printf("*") ; + this = ssl_next(this, next) ; + } ; + printf("\n") ; + + printf(" Other list scan") ; + + other_this = other->base ; + prev = NULL ; + i = n ; + while (1) + { + if (other_this == NULL) + break ; + + test_assert(other_this != prev, "this is same as prev") ; + prev = other_this ; + + if (i == i_other_del) + --i ; + + test_assert(other_this->dummy == i--, "don't have the right dummy") ; + test_assert(other_this->majic == majic(other_this, &base), + "don't have the right majic") ; + + printf("*") ; + other_this = ssl_next(other_this, other_next) ; + } ; + printf("\n") ; + + /* Dismantle lists + * + * j) pop of head when list not empty + * k) pop of head when list contains one item + * l) pop of head when list empty + * p) head when list not empty + * q) head when list is empty + */ + printf(" Popping the head until list is empty\n") ; + printf(" Base list") ; + + prev = NULL ; + i = n ; + while (1) + { + this = base ; + test_assert(this == ssl_head(base), "this is not head !") ; + + temp = ssl_pop(&take, base, next) ; + test_assert(this == take, "this is not same as deleted head !") ; + test_assert(temp == take, "temp is not same as deleted head !") ; + + if (this == NULL) + break ; + + test_assert(base == this->next, "ssl_pop broken") ; + + test_assert(this != prev, "this is same as prev") ; + prev = this ; + + if (i == i_del) + --i ; + + test_assert(this->dummy == i--, "don't have the right dummy") ; + test_assert(this->majic == majic(this, &base), + "don't have the right majic") ; + printf("-") ; + } ; + test_assert(i == 0, "not the expected final value of 'i'") ; + test_assert(base == NULL, "Base list should be empty") ; + + this = ssl_head(base) ; + test_assert(this == NULL, "ssl_head of empty list failed") ; + + printf("\n") ; + + printf(" Other list") ; + + prev = NULL ; + i = n ; + while (1) + { + this = other->base ; + test_assert(this == ssl_head(other->base), "this is not head !") ; + + if (i & 1) + temp = ssl_pop(&take, other->base, other_next) ; + else + temp = ssl_pop(&take, ssl_parent.base, other_next) ; + + test_assert(this == take, "this is not same as deleted head !") ; + test_assert(temp == take, "temp is not same as deleted head !") ; + + if (this == NULL) + break ; + + test_assert(other->base == this->other_next, "ssl_pop broken") ; + + test_assert(this != prev, "this is same as prev") ; + prev = this ; + + if (i == i_other_del) + --i ; + + test_assert(this->dummy == i--, "don't have the right dummy") ; + test_assert(this->majic == majic(this, &base), + "don't have the right majic") ; + printf("-") ; + } ; + test_assert(i == 0, "not the expected final value of 'i'") ; + test_assert(other->base == NULL, "Other list should be empty") ; + + this = ssl_head(other->base) ; + test_assert(this == NULL, "ssl_head of empty list failed") ; + + printf("\n") ; + + /* Rebuild lists to do: + * + * m) deletion of head when list not empty + * n) deletion of head when contains one item + * o) deletion of head when list empty + */ + passert((base == NULL) && (other->base == NULL)) ; + + last = NULL ; + first = NULL ; + prev = NULL ; + printf(" Building list of items again") ; + for (i = 1 ; i <= n ; ++i) + { + ssl_test this = calloc(1, sizeof(struct ssl_test)) ; + + if (last == NULL) + last = this ; + + this->majic = majic(this, &base) ; + this->dummy = i ; + + ssl_push(base, this, next) ; + if (i & 1) + ssl_push(ssl_parent.base, this, other_next) ; + else + ssl_push(other->base, this, other_next) ; + + test_assert(this->next == prev, "broken ssl_push") ; + test_assert(this->other_next == prev, "broken ssl_push") ; + + test_assert(base == this, "broken ssl_push") ; + test_assert(other->base == this, "broken ssl_push") ; + + first = this ; + prev = this ; + + printf("+") ; + } ; + + printf("\n") ; + + printf(" Deleting the head until list is empty\n") ; + printf(" Base list") ; + + prev = NULL ; + i = n ; + while (1) + { + this = base ; + + ssl_del_head(base, next) ; + + if (this == NULL) + break ; + + test_assert(base == this->next, "ssl_del_head broken") ; + + test_assert(this != prev, "this is same as prev") ; + prev = this ; + + test_assert(this->dummy == i--, "don't have the right dummy") ; + test_assert(this->majic == majic(this, &base), + "don't have the right majic") ; + printf("-") ; + } ; + test_assert(i == 0, "not the expected final value of 'i'") ; + test_assert(base == NULL, "Base list should be empty") ; + + printf("\n") ; + + printf(" Other list") ; + + prev = NULL ; + i = n ; + while (1) + { + this = other->base ; + + if (i & 1) + ssl_del_head(ssl_parent.base, other_next) ; + else + ssl_del_head(other->base, other_next) ; + + if (this == NULL) + break ; + + test_assert(other->base == this->other_next, "ssl_del_head broken") ; + + test_assert(this != prev, "this is same as prev") ; + prev = this ; + + test_assert(this->dummy == i--, "don't have the right dummy") ; + test_assert(this->majic == majic(this, &base), + "don't have the right majic") ; + printf("-") ; + } ; + test_assert(i == 0, "not the expected final value of 'i'") ; + test_assert(other->base == NULL, "Other list should be empty") ; + + printf("\n") ; + + /* Final few tests + * + * d) deletion of first item when only one item on the list + * g) deletion when item not on list and list is empty + * i) deletion of NULL item and list empty + */ + + /* Deletion of items from arbitrary place in list */ + printf(" Miscellaneous") ; + + del->next = &dummy ; + ssl_push(base, del, next) ; + test_assert((base == del) && (del->next == NULL), "ssl_push failed ??") ; + ssl_del(base, del, next) ; + test_assert(base == NULL, "ssl_del of first and only item failed") ; + + other_del->other_next = &dummy ; + ssl_push(other->base, other_del, other_next) ; + test_assert((other->base == other_del) && (other_del->other_next == NULL), + "ssl_push failed ??") ; + ssl_del(other->base, other_del, other_next) ; + test_assert(other->base == NULL, "ssl_del of first and only item failed") ; + + ret = ssl_del(base, del, next) ; + test_assert(ret == -1, "ssl_del did not return -1") ; + test_assert(base == NULL, "ssl_del on empty list") ; + + ret = ssl_del(other->base, other_del, other_next) ; + test_assert(ret == -1, "ssl_del did not return -1") ; + test_assert(other->base == NULL, "ssl_del on empty list") ; + + this = NULL ; + + ret = ssl_del(base, this, next) ; + test_assert(ret == 0, "ssl_del did not return 0") ; + test_assert(base == NULL, "ssl_del on empty list") ; + + ret = ssl_del(other->base, this, other_next) ; + test_assert(ret == 0, "ssl_del did not return 0") ; + test_assert(other->base == NULL, "ssl_del on empty list") ; + + printf("\n") ; + +} ; + +/*============================================================================== + * Single Base, Double Link + * + * sdl_push(base, item, list) -- add at head of list + * sdl_del(base, item, list) -- delete from list + * sdl_pop(&dst, base, next) -- pop head of list, if any + * sdl_head(base) -- return head of list + * sdl_next(item, next) -- step to next item, if any + * sdl_prev(item, next) -- step to prev item, if any + * + * Cases to cover: + * + * a) adding when list is empty + * b) adding when list is not empty + * c) deletion of first item and more than one item on list + * d) deletion of first item when only one item on the list + * e) deletion of arbitrary item (list implicitly not empty) + * f) deletion of NULL item and list not empty + * g) deletion of NULL item and list empty + * h) pop of head when list not empty + * i) pop of head when list contains one item + * j) pop of head when list empty + * k) deletion of head when list not empty + * l) deletion of head when list contains one item + * m) deletion of head when list empty + * n) head when list not empty + * o) head when list is empty + * p) next when not last + * q) next when last + * r) prev when not first + * s) prev when first + * + * NB: unlike single link stuff, cannot attempt to remove item which is + * not on the list ! + */ + +typedef struct sdl_test* sdl_test ; +struct sdl_test +{ + struct dl_list_pair(sdl_test) list ; + + unsigned majic ; + char dummy ; + + struct dl_list_pair(sdl_test) other_list ; +}; + +struct sdl_test_parent +{ + long rubbish ; + char fred ; + + sdl_test base ; + + int z[7] ; +} ; + +static struct sdl_test_parent sdl_parent ; + +static void +test_sdl(void) +{ + sdl_test base = NULL ; + + sdl_test del = NULL ; + sdl_test other_del = NULL ; + sdl_test last = NULL ; + sdl_test first = NULL ; + + struct sdl_test dummy ; + + int n = 57 ; + + int i_del = 9 ; /* NB: neither of these may be 0 or 1 */ + int i_other_del = 49 ; + + sdl_test prev ; + sdl_test this ; + sdl_test other_this ; + sdl_test take ; + sdl_test temp ; + + int i ; + + static struct sdl_test_parent* other = &sdl_parent ; + + memset(other, 99, sizeof(struct sdl_test_parent)) ; + other->base = NULL ; + + /* Repeated insertion, starting from empty list + * + * a) adding when list is empty + * b) adding when list is not empty + * + * Creates lists for following tests. + */ + printf("=== Testing sdl -- Single Base, Double Link -- stuff\n") ; + + printf(" Creating list of items") ; + for (i = 1 ; i <= n ; ++i) + { + sdl_test this = calloc(1, sizeof(struct sdl_test)) ; + + if (last == NULL) + last = this ; + + this->majic = majic(this, &base) ; + + this->dummy = i ; + + sdl_push(base, this, list) ; + if (i & 1) + sdl_push(other->base, this, other_list) ; + else + sdl_push(sdl_parent.base, this, other_list) ; + + if (i == i_del) + del = this ; + if (i == i_other_del) + other_del = this ; + + first = this ; + + printf("+") ; + } ; + + test_assert((base == first) && (other->base == first), + "Failed to create consistent lists") ; + + printf("\n") ; + + passert((del != base) && (del != last)) ; + passert((other_del != base) && (other_del != last)) ; + + /* Walk to check that have the expected items + * + * n) head when list not empty + * p) next when not last + * q) next when last + * r) prev when not first + * s) prev when first + */ + printf(" Walking list of items") ; + + this = sdl_head(base) ; + test_assert(this == first, "sdl_head failed") ; + + this = sdl_head(other->base) ; + test_assert(this == first, "sdl_head failed") ; + + this = sdl_head(sdl_parent.base) ; + test_assert(this == first, "sdl_head failed") ; + + /* next on both lists */ + this = sdl_next(first, list) ; + test_assert((this == first->list.next) && (this != NULL), + "sdl_next failed at start") ; + this = sdl_next(del, list) ; + test_assert((this == del->list.next) && (this != NULL), "sdl_next failed") ; + this = sdl_next(last, list) ; + test_assert((this == last->list.next) && (this == NULL), + "sdl_next failed at end") ; + + this = sdl_next(first, other_list) ; + test_assert((this == first->other_list.next) && (this != NULL), + "sdl_next failed at start") ; + this = sdl_next(other_del, other_list) ; + test_assert((this == other_del->other_list.next) && (this != NULL), + "sdl_next failed") ; + this = sdl_next(last, other_list) ; + test_assert((this == last->other_list.next) && (this == NULL), + "sdl_next failed at end") ; + + /* prev on both lists */ + this = sdl_prev(first, list) ; + test_assert((this == first->list.prev) && (this == NULL), + "sdl_prev failed at start") ; + this = sdl_prev(del, list) ; + test_assert((this == del->list.prev) && (this != NULL), "sdl_prev failed") ; + this = sdl_prev(last, list) ; + test_assert((this == last->list.prev) && (this != NULL), + "sdl_prev failed at end") ; + + this = sdl_prev(first, other_list) ; + test_assert((this == first->other_list.prev) && (this == NULL), + "sdl_prev failed at start") ; + this = sdl_prev(other_del, other_list) ; + test_assert((this == other_del->other_list.prev) && (this != NULL), + "sdl_prev failed") ; + this = sdl_prev(last, other_list) ; + test_assert((this == last->other_list.prev) && (this != NULL), + "sdl_prev failed at end") ; + + this = base ; + other_this = other->base ; + + prev = NULL ; + i = n ; + while (1) + { + test_assert(this == other_this, "this and other_this not in step") ; + if (this == NULL) + break ; + + test_assert(this != prev, "this is same as prev") ; + prev = this ; + + test_assert(this->dummy == i--, "don't have the right dummy") ; + test_assert(this->majic == majic(this, &base), + "don't have the right majic") ; + + printf(".") ; + this = sdl_next(this, list) ; + other_this = sdl_next(other_this, other_list) ; + } ; + printf("\n") ; + + /* Deletion specifically at the start of the list + * + * c) deletion of first item and more than one item on list + */ + printf(" Deleting the first item") ; + + this = base ; + first = base->list.next ; + sdl_del(base, this, list) ; + test_assert(first == base, "sdl_del of first item failed") ; + test_assert((base == NULL) || (base->list.prev == NULL), "sdl_del failed") ; + + this = other->base ; + sdl_del(sdl_parent.base, this, other_list) ; + test_assert(first == other->base, "sdl_del of first item failed") ; + test_assert((base == NULL) || (base->other_list.prev == NULL), + "sdl_del failed") ; + + printf("\n") ; + + --n ; /* one less on the lists ! */ + + /* Deletion of items from arbitrary place in list + * + * e) deletion of arbitrary item (list implicitly not empty) + */ + printf(" Deleting arbitrary items") ; + sdl_del(base, del, list) ; + test_assert((base == NULL) || (base->list.prev == NULL), "sdl_del failed") ; + sdl_del(sdl_parent.base, other_del, other_list) ; + test_assert((base == NULL) || (base->other_list.prev == NULL), + "sdl_del failed") ; + printf("\n") ; + + /* Deletion of NULL items + * + * f) deletion of NULL item and list not empty + */ + printf(" Deleting NULL items") ; + this = NULL ; + sdl_del(base, this, list) ; + test_assert((base == NULL) || (base->list.prev == NULL), "sdl_del failed") ; + sdl_del(other->base, this, other_list) ; + test_assert((base == NULL) || (base->other_list.prev == NULL), + "sdl_del failed") ; + printf("\n") ; + + /* Scan lists to check after deletion */ + printf(" Base list scan") ; + + this = base ; + prev = NULL ; + i = n ; + while (1) + { + if (this == NULL) + break ; + + test_assert(this != prev, "this is same as prev") ; + test_assert(this->list.prev == prev, "broken prev pointer") ; + + if (i == i_del) + --i ; + + test_assert(this->dummy == i--, "don't have the right dummy") ; + test_assert(this->majic == majic(this, &base), + "don't have the right majic") ; + printf("*") ; + + prev = this ; + this = sdl_next(this, list) ; + + test_assert(this == prev->list.next, "broken sdl_next") ; + if (this != NULL) + test_assert(prev == sdl_prev(this, list), "broken sdl_prev") ; + } ; + printf("\n") ; + + printf(" Other list scan") ; + + this = other->base ; + prev = NULL ; + i = n ; + while (1) + { + if (this == NULL) + break ; + + test_assert(this != prev, "this is same as prev") ; + test_assert(this->other_list.prev == prev, "broken prev pointer") ; + + if (i == i_other_del) + --i ; + + test_assert(this->dummy == i--, "don't have the right dummy") ; + test_assert(this->majic == majic(this, &base), + "don't have the right majic") ; + + printf("*") ; + + prev = this ; + this = sdl_next(this, other_list) ; + + test_assert(this == prev->other_list.next, "broken sdl_next") ; + if (this != NULL) + test_assert(prev == sdl_prev(this, other_list), "broken sdl_prev") ; + } ; + printf("\n") ; + + /* Dismantle lists + * + * h) pop of head when list not empty + * i) pop of head when list contains one item + * j) pop of head when list empty + * o) head when list is empty + */ + printf(" Popping the head until list is empty\n") ; + printf(" Base list") ; + + prev = NULL ; + i = n ; + while (1) + { + this = sdl_head(base) ; + test_assert(this == base, "broken sdl_head !") ; + + temp = sdl_pop(&take, base, list) ; + test_assert(this == take, "take is not same as deleted head !") ; + test_assert(this == temp, "temp is not same as deleted head !") ; + if (base != NULL) + test_assert(base->list.prev == NULL, "sdl_pop failed") ; + + if (this == NULL) + break ; + + test_assert(this != prev, "this is same as prev") ; + prev = this ; + + if (i == i_del) + --i ; + + test_assert(this->dummy == i--, "don't have the right dummy") ; + test_assert(this->majic == majic(this, &base), + "don't have the right majic") ; + printf("-") ; + } ; + test_assert(i == 0, "not the expected final value of 'i'") ; + test_assert(base == NULL, "Base list should be empty") ; + + this = sdl_head(base) ; + test_assert(this == NULL, "sdl_head of empty list failed") ; + + printf("\n") ; + + printf(" Other list") ; + + prev = NULL ; + i = n ; + while (1) + { + this = sdl_head(other->base) ; + test_assert(this == other->base, "broken sdl_head !") ; + + if (i & 1) + temp = sdl_pop(&take, sdl_parent.base, other_list) ; + else + temp = sdl_pop(&take, other->base, other_list) ; + + test_assert(this == take, "take is not same as deleted head !") ; + test_assert(this == temp, "temp is not same as deleted head !") ; + if (other->base != NULL) + test_assert(other->base->other_list.prev == NULL, + "sdl_pop failed") ; + if (this == NULL) + break ; + + test_assert(this != prev, "this is same as prev") ; + prev = this ; + + if (i == i_other_del) + --i ; + + test_assert(this->dummy == i--, "don't have the right dummy") ; + test_assert(this->majic == majic(this, &base), + "don't have the right majic") ; + + printf("-") ; + } ; + test_assert(i == 0, "not the expected final value of 'i'") ; + test_assert(other->base == NULL, "Other list should be empty") ; + + this = sdl_head(other->base) ; + test_assert(this == NULL, "sdl_head of empty list failed") ; + + printf("\n") ; + + /* Rebuild lists to do: + * + * k) deletion of head when list not empty + * l) deletion of head when list contains one item + * m) deletion of head when list empty + */ + passert((base == NULL) && (other->base == NULL)) ; + + last = NULL ; + first = NULL ; + prev = NULL ; + printf(" Building list of items again") ; + for (i = 1 ; i <= n ; ++i) + { + sdl_test this = calloc(1, sizeof(struct sdl_test)) ; + + if (last == NULL) + last = this ; + + this->majic = majic(this, &base) ; + this->dummy = i ; + + sdl_push(base, this, list) ; + if (i & 1) + sdl_push(sdl_parent.base, this, other_list) ; + else + sdl_push(other->base, this, other_list) ; + + test_assert(this->list.next == prev, "broken sdl_push") ; + test_assert(this->other_list.next == prev, "broken sdl_push") ; + + test_assert(base == this, "broken sdl_push") ; + test_assert(other->base == this, "broken sdl_push") ; + + first = this ; + prev = this ; + + printf("+") ; + } ; + + printf("\n") ; + + printf(" Deleting the head until list is empty\n") ; + printf(" Base list") ; + + prev = NULL ; + i = n ; + while (1) + { + this = base ; + + sdl_del_head(base, list) ; + + if (this == NULL) + break ; + + test_assert(base == this->list.next, "sdl_del_head broken") ; + if (base != NULL) + test_assert(base->list.prev == NULL, "sdl_del_head broken") ; + + test_assert(this != prev, "this is same as prev") ; + prev = this ; + + test_assert(this->dummy == i--, "don't have the right dummy") ; + test_assert(this->majic == majic(this, &base), + "don't have the right majic") ; + printf("-") ; + } ; + test_assert(i == 0, "not the expected final value of 'i'") ; + test_assert(base == NULL, "Base list should be empty") ; + + printf("\n") ; + + printf(" Other list") ; + + prev = NULL ; + i = n ; + while (1) + { + this = other->base ; + + if (i & 1) + sdl_del_head(other->base, other_list) ; + else + sdl_del_head(sdl_parent.base, other_list) ; + + if (this == NULL) + break ; + + test_assert(other->base == this->other_list.next, "sdl_del_head broken") ; + if (other->base != NULL) + test_assert(other->base->other_list.prev == NULL, + "sdl_del_head broken") ; + + test_assert(this != prev, "this is same as prev") ; + prev = this ; + + test_assert(this->dummy == i--, "don't have the right dummy") ; + test_assert(this->majic == majic(this, &base), + "don't have the right majic") ; + printf("-") ; + } ; + test_assert(i == 0, "not the expected final value of 'i'") ; + test_assert(other->base == NULL, "Other list should be empty") ; + + printf("\n") ; + + /* Final few tests + * + * d) deletion of first item when only one item on the list + * g) deletion of NULL item and list empty + */ + + /* Deletion of items from arbitrary place in list */ + printf(" Miscellaneous") ; + + del->list.next = &dummy ; + sdl_push(base, del, list) ; + test_assert((base == del) && (del->list.next == NULL), "sdl_push failed ??") ; + sdl_del(base, del, list) ; + test_assert(base == NULL, "sdl_del of first and only item failed") ; + + other_del->other_list.next = &dummy ; + sdl_push(other->base, other_del, other_list) ; + test_assert((other->base == other_del) && (other_del->other_list.next == NULL), + "sdl_push failed ??") ; + sdl_del(other->base, other_del, other_list) ; + test_assert(other->base == NULL, "sdl_del of first and only item failed") ; + + this = NULL ; + sdl_del(base, this, list) ; + test_assert(base == NULL, "sdl_del of NULL item with empty list") ; + + sdl_del(other->base, this, other_list) ; + test_assert(other->base == NULL, "sdl_del of NULL item with empty list") ; + + printf("\n") ; +} ; + +/*============================================================================== + * Double Base, Double Link + * + * ddl_init(base) -- initialise base + * ddl_push(base, item, list) -- insert at head of list + * ddl_append(base, item, list) -- insert at tail of list + * ddl_in_after(after, base, item, list) -- insert after + * ddl_in_before(before, base, item, list) -- insert before + * ddl_pop(&dst, base, next) -- pop head of list, if any + * ddl_crop(&dst, base, next) -- crop tail of list, if any + * ddl_del(base, item, list) -- delete from list + * ddl_del_head(base, next) -- delete head of list + * ddl_del_tail(base, next) -- delete tail of list + * ddl_head(base) -- return head of list + * ddl_tail(base) -- return tail of list + * ddl_next(item, next) -- step to next item, if any + * ddl_prev(item, next) -- step to prev item, if any + * + * Cases to cover: + */ + +/* Testing runs two lists through struct ddt_item objects. */ + +enum list { a_list, b_list, list_count } ; + +typedef struct ddt_item* ddt_item ; + +struct ddt_list_pair dl_list_pair(ddt_item) ; /* Example struct constructor */ +struct ddt_base_pair dl_base_pair(ddt_item) ; + +typedef struct dl_base_pair(ddt_item) ddt_base_pair_t ; + /* Example typedef constructor */ +typedef struct dl_base_pair(ddt_item)* p_ddt_base_pair ; + /* Example typedef constructor */ + +typedef struct ddt_list_pair* ddt_list_pair ; +typedef struct ddt_base_pair* ddt_base_pair ; + +typedef struct ddt_rank* ddt_rank ; + +struct ddt_rank /* information for each list */ +{ + struct ddt_list_pair list ; /* the thing we are testing */ + + int lister ; + int list_found ; + unsigned majic ; + + int ordinal ; +}; + +struct ddt_item /* the test items */ +{ + struct ddt_rank a ; + + char a_rubbish[21] ; + + struct ddt_rank b ; + + char b_rubbish[19] ; +} ; + +/* The test list base pairs, and pointers to the actual bases, for use in + * the verification code. + */ +static ddt_base_pair ddt_bases[list_count] ; + +/* For some tests want to construct lists and know the first, last and + * somewhere between items. + */ + +enum where { first, middle, last, where_count } ; + +struct ddt_test_list_items +{ + struct + { + ddt_item where[where_count] ; + } list[list_count] ; +} ; + +/*------------------------------------------------------------------------------ + * The test list items -- keep track here also for use in verification. + */ +enum { ddt_max_items = 1000 } ; + +static unsigned ddt_item_count = 0 ; +static unsigned ddt_item_alloc = 0 ; +static ddt_item ddt_items[ddt_max_items] ; + +static inline ddt_item +ddt_new_item(void) +{ + ddt_item item ; + + assert(ddt_item_count <= ddt_item_alloc) ; + + if (ddt_item_count == ddt_item_alloc) + { + assert(ddt_item_alloc < ddt_max_items) ; + ddt_items[ddt_item_alloc++] = malloc(sizeof(struct ddt_item)) ; + } ; + + item = ddt_items[ddt_item_count++] ; + + memset(item, ddt_item_count & 0xFF, sizeof(struct ddt_item)) ; + + item->a.lister = 0 ; + item->b.lister = 0 ; + + item->a.ordinal = 0 ; + item->b.ordinal = 0 ; + + return item ; +} ; + +/*------------------------------------------------------------------------------ + * Given an item and a list ordinal, return pointer to "rank" for item. + */ +static inline ddt_rank +ddt_get_rank(ddt_item item, enum list l) +{ + if (item == NULL) + return NULL ; + + if (l == a_list) + return &item->a ; + if (l == b_list) + return &item->b ; + + assert(0) ; +} ; + +/*------------------------------------------------------------------------------ + * Keep track of what should be found on the lists, and majic marker to check + * that don't get lost and point into space. + */ +static inline unsigned +ddt_get_majic(ddt_item item, enum list l) +{ + return majic(item, ddt_bases[l]) ; +} ; + +static void +ddt_test_list_add(ddt_item item, enum list l) +{ + ddt_rank rank = ddt_get_rank(item, l) ; + + test_assert(rank->lister == 0, "already on list") ; + + rank->lister = 1 ; + rank->majic = ddt_get_majic(item, l) ; + rank->ordinal = 0 ; /* unknown ordinal */ +} ; + +static void +ddt_test_list_del(ddt_item item, enum list l) +{ + ddt_rank rank ; + + if (item == NULL) + return ; + + rank = ddt_get_rank(item, l) ; + + test_assert(rank->lister == 1, "not on list") ; + + rank->lister = 0 ; + rank->majic = 0 ; +} ; + +/*------------------------------------------------------------------------------ + * Verification code. + * + * Blunt instrument to check that all known lists are valid. Checks: + * + * * bases are both NULL together, or both not NULL. + * + * * first and last items on the list have suitable prev/next pointers. + * + * * walk list to confirm, for each item: + * + * -- prev pointer valid for each item + * -- item majic is correct (so not pointing somewhere invalid) + * -- item is supposed to be on the list + * -- item has not already been seen on list (list bent) + * -- ordinal, if not zero, is bigger than any previous non-zero ordinal + * + * * last item visited on walk is what the tail points to + * + * * for any items which are supposed to be on list, but were not found + */ +static void +ddt_verify_lists(void) +{ + ddt_base_pair base ; + ddt_rank r ; + ddt_item this ; + ddt_item prev ; + int l ; + int i ; + + /* Wash the found flags */ + for (l = 0 ; l < list_count ; ++l) + for (i = 0 ; i < (int)ddt_item_count ; ++i) + ddt_get_rank(ddt_items[i], l)->list_found = 0 ; + + /* Walk the lists */ + for (l = 0 ; l < list_count ; ++l) + { + int ordinal = 0 ; + + base = ddt_bases[l] ; + if (base == NULL) + continue ; + + if ((base->head == NULL) || (base->tail == NULL)) + test_assert(base->head == base->tail, "broken list bases") ; + else + { + r = ddt_get_rank(base->head, l) ; + test_assert(r->list.prev == NULL, "broken list first item->prev") ; + r = ddt_get_rank(base->tail, l) ; + test_assert(r->list.next == NULL, "broken list last item->next") ; + + this = base->head ; + prev = NULL ; + + while (this != NULL) + { + r = ddt_get_rank(this, l) ; + + test_assert(r->list.prev == prev, "broken item->prev") ; + + test_assert(r->lister, "should not be on this list") ; + + test_assert(!r->list_found, "circular list") ; + r->list_found = 1 ; + + if (r->ordinal != 0) + { + test_assert(r->ordinal > ordinal, "list out of order") ; + ordinal = r->ordinal ; + } + + test_assert(r->majic == ddt_get_majic(this, l), + "wrong sort of majic") ; + prev = this ; + this = r->list.next ; + } ; + + test_assert(base->tail == prev, "broken tail pointer") ; + } ; + } ; + + /* Verify that did not miss anything should have found */ + /* Wash the found flags */ + for (l = 0 ; l < list_count ; ++l) + for (i = 0 ; i < (int)ddt_item_count ; ++i) + { + r = ddt_get_rank(ddt_items[i], l) ; + + if (r->lister) + test_assert(r->list_found, "should have found this on list") ; + } ; +} ; + +/*------------------------------------------------------------------------------ + * Reset the test list handling + * + */ +static void +ddt_reset_lists(void) +{ + int l ; + + for (l = 0 ; l < list_count ; ++l) + ddl_init(*(ddt_bases[l])) ; + + ddt_item_count = 0 ; +} ; + +/*------------------------------------------------------------------------------ + * Make lists with 'n' items each. + * + * If 'n' 0..3, makes lists with exactly that many items. + * + * Otherwise, list length has +/- 25% jitter. + */ +static void +ddt_test_make_lists(struct ddt_test_list_items* test, int n) +{ + ddt_base_pair base ; + ddt_item item ; + ddt_rank rank ; + enum list l ; + int t ; + int m ; + + int req[list_count] ; + int mid[list_count] ; + + /* Capture the requirements */ + t = 0 ; + m = 1 ; + for (l = 0 ; l < list_count ; ++l) + { + m += m ; + int j = (n + 1) / 4 ; + + if (n <= 3) + req[l] = n ; + else + req[l] = n - j + (rand() % (j + j + 1)) ; + + mid[l] = req[l] / 2 ; + + t += req[l] ; + + test->list[l].where[first] = NULL ; + test->list[l].where[middle] = NULL ; + test->list[l].where[last] = NULL ; + } ; + + ddt_reset_lists() ; + + /* Have t = total number of items still required + * m = 2^n -- where there are 'n' lists + */ + while (t != 0) + { + int b ; + int r ; + r = (rand() % (m - 1)) + 1 ; /* bit pattern, at least one set */ + + item = ddt_new_item() ; + + b = 1 ; + for (l = 0 ; l < list_count ; ++l) + { + if ((req[l] != 0) && ((r & b) != 0)) + { + --req[l] ; + --t ; + + ddt_test_list_add(item, l) ; + + if (test->list[l].where[first] == NULL) + test->list[l].where[first] = item ; + + if (mid[l]-- == 0) + test->list[l].where[middle] = item ; + + test->list[l].where[last] = item ; + + base = ddt_bases[l] ; + rank = ddt_get_rank(item, l) ; + + if (base->head == NULL) + { + base->head = item ; + base->tail = item ; + rank->list.next = NULL ; + rank->list.prev = NULL ; + } + else if (rand() & 1) + { + rank->list.next = base->head ; + rank->list.prev = NULL ; + ddt_get_rank(base->head, l)->list.prev = item ; + base->head = item ; + } + else + { + rank->list.next = NULL ; + rank->list.prev = base->tail ; + ddt_get_rank(base->tail, l)->list.next = item ; + base->tail = item ; + } + } ; + b <<= 1 ; + } + } ; + + /* Number the items */ + for (l = 0 ; l < list_count ; ++l) + { + int o = 0 ; + + base = ddt_bases[l] ; + + item = base->head ; + while (item != NULL) + { + rank = ddt_get_rank(item, l) ; + rank->ordinal = ++o ; /* first is 1 */ + item = rank->list.next ; + } ; + } ; + + ddt_verify_lists() ; +} ; + +/*------------------------------------------------------------------------------ + * ddl_init(base) -- initialise base + * ddl_push(base, item, list) -- insert at head of list + * ddl_append(base, item, list) -- insert at tail of list + * ddl_in_after(after, base, item, list) -- insert after + * ddl_in_before(before, base, item, list) -- insert before + * ddl_pop(&dst, base, next) -- pop head of list, if any + * ddl_crop(&dst, base, next) -- crop tail of list, if any + * ddl_del(base, item, list) -- delete from list + * ddl_del_head(base, next) -- delete head of list + * ddl_del_tail(base, next) -- delete tail of list + * ddl_head(base) -- return head of list + * ddl_tail(base) -- return tail of list + * ddl_next(item, next) -- step to next item, if any + * ddl_prev(item, next) -- step to prev item, if any + */ + +static struct ddt_parent +{ + char zlxq[37] ; + + struct ddt_base_pair base ; + + char qxlz[45] ; +} ddt_parent ; + +static void +test_ddl(void) +{ + struct ddt_base_pair a_base ; + struct ddt_parent* b ; + + struct ddt_test_list_items test ; + int n ; + int o ; + + int base_n = 23 ; + int rand_n = 17 ; + + printf("=== Testing ddl -- Double Base, Double Link -- stuff\n") ; + + /* Initialise the test support */ + ddt_bases[a_list] = &a_base ; + ddt_bases[b_list] = &ddt_parent.base ; + + ddt_item_count = 0 ; + ddt_item_alloc = 0 ; + + /* Initialise the list bases */ + b = &ddt_parent ; + memset(b, 42, sizeof(struct ddt_parent)) ; + + ddl_init(a_base) ; + ddl_init(b->base) ; + + ddt_verify_lists() ; /* start as mean to go on */ + + + /* ddl_push(base, item, list) -- insert at head of list + * + * Cases: (a) empty list + * (b) list with one item + * (c) list with multiple items + */ + printf(" ddl_push test") ; + ddt_reset_lists() ; + + n = base_n + (rand() % rand_n) ; + while (n) + { + ddt_item item ; + int r ; + + printf(".") ; + + item = ddt_new_item() ; + r = (rand() % 3) + 1 ; + + if (r & 1) + { + ddl_push(a_base, item, a.list) ; + test_assert(a_base.head == item, "ddl_push broken") ; + ddt_test_list_add(item, a_list) ; + item->a.ordinal = n ; + } ; + ddt_verify_lists() ; + + if (r & 2) + { + ddl_push(b->base, item, b.list) ; + test_assert(b->base.head == item, "ddl_push broken") ; + ddt_test_list_add(item, b_list) ; + item->b.ordinal = n ; + } ; + ddt_verify_lists() ; + + --n ; + } ; + printf("\n") ; + + /* ddl_append(base, item, list) -- insert at tail of list + * + * Cases: (a) empty list + * (b) list with one item + * (c) list with multiple items + */ + printf(" ddl_append test") ; + ddt_reset_lists() ; + + n = base_n + (rand() % rand_n) ; + o = 0 ; + while (n) + { + ddt_item item ; + int r ; + + printf(".") ; + ++o ; + + item = ddt_new_item() ; + r = (rand() % 3) + 1 ; + + if (r & 1) + { + ddl_append(a_base, item, a.list) ; + test_assert(a_base.tail == item, "ddl_append broken") ; + ddt_test_list_add(item, a_list) ; + item->a.ordinal = o ; + } ; + ddt_verify_lists() ; + + if (r & 2) + { + ddl_append(b->base, item, b.list) ; + test_assert(b->base.tail == item, "ddl_append broken") ; + ddt_test_list_add(item, b_list) ; + item->b.ordinal = o ; + } ; + ddt_verify_lists() ; + + --n ; + } ; + printf("\n") ; + + /* ddl_in_after(after, base, item, list) -- insert after + * + * Cases: (a) after first and only (so is also last) + * (b) after first when more than one + * (c) after last when more than one + * (d) after something between + */ + printf(" ddl_in_after test") ; + + n = base_n + (rand() % rand_n) ; + while (n) + { + ddt_item item ; + ddt_item after ; + + printf(".") ; + ddt_test_make_lists(&test, n) ; + + item = ddt_new_item() ; + after = test.list[a_list].where[n % where_count] ; + ddl_in_after(after, a_base, item, a.list) ; + test_assert(after->a.list.next == item, "ddl_in_after broken") ; + test_assert(item->a.list.prev == after, "ddl_in_after broken") ; + ddt_test_list_add(item, a_list) ; + ddt_verify_lists() ; + + item = ddt_new_item() ; + after = test.list[b_list].where[n % where_count] ; + ddl_in_after(after, b->base, item, b.list) ; + test_assert(after->b.list.next == item, "ddl_in_after broken") ; + test_assert(item->b.list.prev == after, "ddl_in_after broken") ; + ddt_test_list_add(item, b_list) ; + ddt_verify_lists() ; + + --n ; + } ; + printf("\n") ; + + /* ddl_in_before(before, base, item, list) -- insert before + * + * Cases: (a) before first and only (so is also last) + * (b) before first when more than one + * (c) before last when more than one + * (d) before something between + */ + printf(" ddl_in_before test") ; + + n = base_n + (rand() % rand_n) ; + while (n) + { + ddt_item item ; + ddt_item before ; + + printf(".") ; + + ddt_test_make_lists(&test, n) ; + + item = ddt_new_item() ; + before = test.list[a_list].where[n % where_count] ; + ddl_in_before(before, a_base, item, a.list) ; + test_assert(before->a.list.prev == item, "ddl_in_before broken") ; + test_assert(item->a.list.next == before, "ddl_in_before broken") ; + ddt_test_list_add(item, a_list) ; + ddt_verify_lists() ; + + item = ddt_new_item() ; + before = test.list[b_list].where[n % where_count] ; + ddl_in_before(before, b->base, item, b.list) ; + test_assert(before->b.list.prev == item, "ddl_in_before broken") ; + test_assert(item->b.list.next == before, "ddl_in_before broken") ; + ddt_test_list_add(item, b_list) ; + ddt_verify_lists() ; + + --n ; + } ; + printf("\n") ; + + /* ddl_pop(&dst, base, next) -- pop head of list, if any + * + * Cases: (a) list with more than one item + * (b) list with one item + * (c) empty list + */ + printf(" ddl_pop test") ; + + n = base_n + (rand() % rand_n) ; + while (n >= 0) + { + ddt_item item ; + ddt_item temp ; + ddt_item peek ; + int ordinal ; + + printf(".") ; + + ddt_test_make_lists(&test, n) ; + + ordinal = 0 ; + while (1) + { + peek = a_base.head ; + temp = ddl_pop(&item, a_base, a.list) ; + test_assert(temp == item, "ddl_pop broken") ; + test_assert(peek == item, "ddl_pop broken") ; + + ddt_test_list_del(item, a_list) ; + ddt_verify_lists() ; + + if (item == NULL) + break ; + + ++ordinal ; + test_assert(item->a.ordinal == ordinal, "ddl_pop not in order") ; + } ; + + ordinal = 0 ; + while (1) + { + peek = b->base.head ; + temp = ddl_pop(&item, b->base, b.list) ; + test_assert(temp == item, "ddl_pop broken") ; + test_assert(peek == item, "ddl_pop broken") ; + + ddt_test_list_del(item, b_list) ; + ddt_verify_lists() ; + + if (item == NULL) + break ; + + ++ordinal ; + test_assert(item->b.ordinal == ordinal, "ddl_pop not in order") ; + } ; + + --n ; + } ; + printf("\n") ; + + /* ddl_crop(&dst, base, next) -- crop tail of list, if any + * + * Cases: (a) list with more than one item + * (b) list with one item + * (c) empty list + */ + + printf(" ddl_crop test") ; + + n = base_n + (rand() % rand_n) ; + while (n >= 0) + { + ddt_item item ; + ddt_item temp ; + ddt_item peek ; + int ordinal ; + + printf(".") ; + + ddt_test_make_lists(&test, n) ; + + ordinal = 0 ; + while (1) + { + peek = a_base.tail ; + temp = ddl_crop(&item, a_base, a.list) ; + test_assert(temp == item, "ddl_crop broken") ; + test_assert(peek == item, "ddl_crop broken") ; + + ddt_test_list_del(item, a_list) ; + ddt_verify_lists() ; + + if (item == NULL) + break ; + + if (ordinal == 0) + ordinal = item->a.ordinal ; + else + { + test_assert(ordinal > 0, "ordinal out of whack") ; + --ordinal ; + test_assert(item->a.ordinal == ordinal, "ddl_crop not in order") ; + } ; + } ; + + ordinal = 0 ; + while (1) + { + peek = b->base.tail ; + temp = ddl_crop(&item, b->base, b.list) ; + test_assert(temp == item, "ddl_crop broken") ; + test_assert(peek == item, "ddl_crop broken") ; + + ddt_test_list_del(item, b_list) ; + ddt_verify_lists() ; + + if (item == NULL) + break ; + + if (ordinal == 0) + ordinal = item->b.ordinal ; + else + { + test_assert(ordinal > 0, "ordinal out of whack") ; + --ordinal ; + test_assert(item->b.ordinal == ordinal, "ddl_crop not in order") ; + } ; + } ; + + --n ; + } ; + printf("\n") ; + + /* ddl_del(base, item, list) -- delete from list + * + * Cases: (a) first and only (so is also last) + * (b) first when more than one + * (c) last when more than one + * (d) something between + */ + printf(" ddl_del test") ; + + n = base_n + (rand() % rand_n) ; + while (n) + { + ddt_item item ; + + printf(".") ; + + ddt_test_make_lists(&test, n) ; + + item = test.list[a_list].where[n % where_count] ; + ddl_del(a_base, item, a.list) ; + ddt_test_list_del(item, a_list) ; + ddt_verify_lists() ; + + item = test.list[b_list].where[n % where_count] ; + ddl_del(b->base, item, b.list) ; + ddt_test_list_del(item, b_list) ; + ddt_verify_lists() ; + + --n ; + } ; + printf("\n") ; + + /* ddl_del_head(base, next) -- delete head of list + * + * Cases: (a) list with more than one item + * (b) list with one item + * (c) empty list + */ + printf(" ddl_del_head test") ; + + n = base_n + (rand() % rand_n) ; + while (n >= 0) + { + ddt_item item ; + ddt_item peek ; + + printf(".") ; + + ddt_test_make_lists(&test, n) ; + + while (1) + { + item = a_base.head ; + peek = (item != NULL) ? item->a.list.next : NULL ; + + ddl_del_head(a_base, a.list) ; + + test_assert(a_base.head == peek, "ddl_del_head broken") ; + + ddt_test_list_del(item, a_list) ; + ddt_verify_lists() ; + + if (item == NULL) + break ; + } ; + + while (1) + { + item = b->base.head ; + peek = (item != NULL) ? item->b.list.next : NULL ; + + ddl_del_head(b->base, b.list) ; + + test_assert(b->base.head == peek, "ddl_del_head broken") ; + + ddt_test_list_del(item, b_list) ; + ddt_verify_lists() ; + + if (item == NULL) + break ; + } ; + + --n ; + } ; + printf("\n") ; + + /* ddl_del_tail(base, next) -- delete tail of list + * + * Cases: (a) list with more than one item + * (b) list with one item + * (c) empty list + */ + printf(" ddl_del_tail test") ; + + n = base_n + (rand() % rand_n) ; + while (n >= 0) + { + ddt_item item ; + ddt_item peek ; + + printf(".") ; + + ddt_test_make_lists(&test, n) ; + + while (1) + { + item = a_base.tail ; + peek = (item != NULL) ? item->a.list.prev : NULL ; + + ddl_del_tail(a_base, a.list) ; + + test_assert(a_base.tail == peek, "ddl_del_tail broken") ; + + ddt_test_list_del(item, a_list) ; + ddt_verify_lists() ; + + if (item == NULL) + break ; + } ; + + while (1) + { + item = b->base.tail ; + peek = (item != NULL) ? item->b.list.prev : NULL ; + + ddl_del_tail(b->base, b.list) ; + + test_assert(b->base.tail == peek, "ddl_del_tail broken") ; + + ddt_test_list_del(item, b_list) ; + ddt_verify_lists() ; + + if (item == NULL) + break ; + } ; + + --n ; + } ; + printf("\n") ; + + /* ddl_head(base) -- return head of list + * ddl_tail(base) -- return tail of list + * + * Cases: (a) list with more than one item + * (b) list with one item + * (c) empty list + */ + printf(" ddl_head & ddl_tail test") ; + + n = base_n + (rand() % rand_n) ; + while (n >= 0) + { + printf(".") ; + + ddt_test_make_lists(&test, n) ; + + test_assert(ddl_head(a_base) == a_base.head, "ddl_head broken") ; + test_assert(ddl_tail(a_base) == a_base.tail, "ddl_head broken") ; + test_assert(ddl_head(b->base) == b->base.head, "ddl_head broken") ; + test_assert(ddl_tail(b->base) == b->base.tail, "ddl_head broken") ; + + --n ; + } ; + printf("\n") ; + + + /* ddl_next(item, next) -- step to next item, if any + * ddl_prev(item, next) -- step to prev item, if any + * + * Cases: (a) at first and only (so is also last) + * (b) at first when more than one + * (c) at last when more than one + * (d) at something between + */ + printf(" ddl_next and ddl_prev test") ; + + n = base_n + (rand() % rand_n) ; + while (n) + { + ddt_item item ; + ddt_item where ; + + printf(".") ; + + ddt_test_make_lists(&test, n) ; + + where = test.list[a_list].where[n % where_count] ; + item = ddl_next(where, a.list) ; + test_assert(item == where->a.list.next, "ddl_next broken") ; + + where = test.list[b_list].where[n % where_count] ; + item = ddl_next(where, b.list) ; + test_assert(item == where->b.list.next, "ddl_next broken") ; + + where = test.list[a_list].where[n % where_count] ; + item = ddl_prev(where, a.list) ; + test_assert(item == where->a.list.prev, "ddl_prev broken") ; + + where = test.list[b_list].where[n % where_count] ; + item = ddl_prev(where, b.list) ; + test_assert(item == where->b.list.prev, "ddl_prev broken") ; + + --n ; + } ; + printf("\n") ; + + +} + +/* + * TODO + * + */ diff --git a/tests/test-privs.c b/tests/test-privs.c index a888ea0f..568fe79a 100644 --- a/tests/test-privs.c +++ b/tests/test-privs.c @@ -125,26 +125,42 @@ main (int argc, char **argv) #define PRIV_STATE() \ ((test_privs.current_state() == ZPRIVS_RAISED) ? "Raised" : "Lowered") - printf ("%s\n", PRIV_STATE()); + printf ("Initial state: %s\n", PRIV_STATE()); + + test_privs.change(ZPRIVS_RAISE); + printf ("Change raise: state: %s\n", PRIV_STATE()); + test_privs.change(ZPRIVS_RAISE); + printf ("Change raise: state: %s\n", PRIV_STATE()); - printf ("%s\n", PRIV_STATE()); test_privs.change(ZPRIVS_LOWER); + printf ("Change lower: state: %s\n", PRIV_STATE()); + + test_privs.change(ZPRIVS_LOWER); + printf ("Change lower: state: %s\n", PRIV_STATE()); - printf ("%s\n", PRIV_STATE()); + printf ("Get ids %s\n", PRIV_STATE()); zprivs_get_ids (&ids); /* terminate privileges */ zprivs_terminate(&test_privs); /* but these should continue to work... */ - printf ("%s\n", PRIV_STATE()); + printf ("Terminated state: %s\n", PRIV_STATE()); + + test_privs.change(ZPRIVS_RAISE); + printf ("Change raise: state: %s\n", PRIV_STATE()); + test_privs.change(ZPRIVS_RAISE); + printf ("Change raise: state: %s\n", PRIV_STATE()); - printf ("%s\n", PRIV_STATE()); test_privs.change(ZPRIVS_LOWER); + printf ("Change lower: state: %s\n", PRIV_STATE()); + + test_privs.change(ZPRIVS_LOWER); + printf ("Change lower: state: %s\n", PRIV_STATE()); - printf ("%s\n", PRIV_STATE()); + printf ("Get ids %s\n", PRIV_STATE()); zprivs_get_ids (&ids); printf ("terminating\n"); diff --git a/tests/test-sig.c b/tests/test-sig.c index 63aab6f0..d9eb24f0 100644 --- a/tests/test-sig.c +++ b/tests/test-sig.c @@ -2,6 +2,10 @@ #include <sigevent.h> #include "lib/log.h" +extern void sighup (void) ; +extern void sigusr1 (void) ; +extern void sigusr2 (void) ; + void sighup (void) { @@ -20,7 +24,7 @@ sigusr2 (void) printf ("processed usr2\n"); } -struct quagga_signal_t sigs[] = +struct quagga_signal_t sigs[] = { { .signal = SIGHUP, @@ -44,13 +48,13 @@ main (void) { master = thread_master_create (); signal_init (master, Q_SIGC(sigs), sigs); - + zlog_default = openzlog("testsig", ZLOG_NONE, LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON); zlog_set_level (NULL, ZLOG_DEST_SYSLOG, ZLOG_DISABLED); zlog_set_level (NULL, ZLOG_DEST_STDOUT, LOG_DEBUG); zlog_set_level (NULL, ZLOG_DEST_MONITOR, ZLOG_DISABLED); - + while (thread_fetch (master, &t)) thread_call (&t); diff --git a/tests/test-stream.c b/tests/test-stream.c index 785ce588..e145436f 100644 --- a/tests/test-stream.c +++ b/tests/test-stream.c @@ -2,7 +2,7 @@ #include <stream.h> #include <thread.h> -static long int ham = 0xdeadbeefdeadbeef; +static int64_t ham = 0xdeadbeefdeadbeef; struct thread_master *master; static void @@ -11,9 +11,9 @@ print_stream (struct stream *s) size_t getp = stream_get_getp (s); printf ("endp: %ld, readable: %ld, writeable: %ld\n", - stream_get_endp (s), - STREAM_READABLE (s), - STREAM_WRITEABLE (s)); + (long int)stream_get_endp (s), + (long int)STREAM_READABLE (s), + (long int)STREAM_WRITEABLE (s)); while (STREAM_READABLE (s)) { @@ -48,7 +48,7 @@ main (void) printf ("c: 0x%hhx\n", stream_getc (s)); printf ("w: 0x%hx\n", stream_getw (s)); printf ("l: 0x%x\n", stream_getl (s)); - printf ("q: 0x%lx\n", stream_getq (s)); + printf ("q: 0x%llx\n", (long long unsigned)stream_getq (s)); return 0; } diff --git a/tests/test-symtab.c b/tests/test-symtab.c new file mode 100644 index 00000000..ed83e607 --- /dev/null +++ b/tests/test-symtab.c @@ -0,0 +1,344 @@ +#include <zebra.h> +#include <symtab.h> + +/* Symtab torture tests + * + */ + +/* prototypes */ +void assert_true(int result, const char * message); +int main(int argc, char **argv); +void test_symbol_table_init_new(void); +void test_symbol_table_lookup(void); +void call_back_function_set(symbol sym, void* value); +void call_back_function_change(symbol sym, void* value); +void call_back_function_unset(symbol sym, void* value); +void test_call_back(void); +void test_ref(void); +void test_ref_heavy(void); + +struct thread_master *master; + +void +assert_true(int result, const char * message) +{ + if (!result) + { + printf("Assert failed: %s\n", message); + } +} + +int +main(int argc, char **argv) +{ + + test_symbol_table_init_new(); + test_symbol_table_lookup(); + test_call_back(); + test_ref(); + test_ref_heavy(); + + return 0; +} + +void +test_symbol_table_init_new(void) +{ + symbol_table table = NULL; + char name[] = "name"; + char value[] = "value"; + symbol sym = NULL; + symbol sym2 = NULL; + void * old_value = NULL; + + printf("test_symbol_table_init_new\n"); + table = symbol_table_init_new(table, NULL, 0, 0, NULL, NULL); + assert_true(table != NULL, "table == NULL"); + + /* expect to not find */ + sym = symbol_lookup(table, name, 0); + assert_true(sym == NULL, "sym != NULL"); + + /* add */ + sym = symbol_lookup(table, name, 1); + symbol_set_value(sym, value); + assert_true(sym != NULL, "sym == NULL"); + assert_true(strcmp(symbol_get_name(sym), name) == 0, "strcmp(symbol_get_name(sym), name) != 0"); + + /* find */ + sym2 = symbol_lookup(table, name, 0); + assert_true(sym == sym2, "sym != sym2"); + assert_true(symbol_get_value(sym) == value, "symbol_get_value(sym) != value"); + + old_value = symbol_delete(sym); + assert_true(value == old_value, "value != old_value"); + + while ((old_value = symbol_table_ream(table, 1)) != NULL) + { + } + +} + +void +test_symbol_table_lookup(void) +{ + symbol_table table = NULL; + char buf[20]; + symbol sym = NULL; + int i; + char *value = NULL; + const int len = 100000; + struct symbol_walker itr; + vector v = NULL; + + printf("test_symbol_table_lookup\n"); + table = symbol_table_init_new(table, NULL, 0, 0, NULL, NULL); + + /* add */ + for (i = 0; i < len; ++i) + { + sprintf(buf, "%d-name", i); + sym = symbol_lookup(table, buf, 1); + assert_true(sym != NULL, "add: sym == NULL"); + assert_true(strcmp(symbol_get_name(sym), buf) == 0, + "strcmp(symbol_get_name(sym), buf) != 0"); + + sprintf(buf, "%d-value", i); + value = strdup(buf); + symbol_set_value(sym, value); + assert_true(symbol_get_value(sym) == value, + "symbol_get_value(sym) != value"); + } + + /* find */ + for (i = 0; i < len; ++i) + { + sprintf(buf, "%d-name", i); + sym = symbol_lookup(table, buf, 0); + assert_true(sym != NULL, "find: sym == NULL"); + assert_true(strcmp(symbol_get_name(sym), buf) == 0, + "strcmp(symbol_get_name(sym), buf) != 0"); + + sprintf(buf, "%d-value", i); + assert_true(strcmp(symbol_get_value(sym), buf) == 0, + "strcmp(symbol_get_value(sym), buf) != 0"); + } + + /* walk with symbol_walker */ + symbol_walk_start(table, &itr); + i = 0; + do + { + sym = symbol_walk_next(&itr); + if (sym != NULL) { + ++i; + } + } while (sym != NULL); + assert_true(i == len, "i != len"); + + /* extract vector */ + v = symbol_table_extract(table, NULL, NULL, 1, NULL); + assert_true(vector_end(v) == (unsigned)len, "vector_get_end(v) != len"); + vector_free(v); + + while ((value = symbol_table_ream(table, 1)) != NULL) + { + free(value); + } +} + +void +test_call_back(void) +{ + symbol_table table = NULL; + char name[] = "name"; + char value[] = "value"; + char new_value[] = "new value"; + symbol sym = NULL; + + printf("test_call_back\n"); + table = symbol_table_init_new(table, NULL, 0, 0, NULL, NULL); + assert_true(table != NULL, "table == NULL"); + + /* add */ + symbol_table_set_value_call_back(table, call_back_function_set); + sym = symbol_lookup(table, name, 1); + symbol_set_value(sym, value); + + /* change */ + symbol_table_set_value_call_back(table, call_back_function_change); + sym = symbol_lookup(table, name, 1); + symbol_set_value(sym, new_value); + + /* delete */ + symbol_table_set_value_call_back(table, call_back_function_unset); + symbol_unset_value(sym); + + while ((symbol_table_ream(table, 1)) != NULL) + { + } +} + +void call_back_function_set(symbol sym, void* value) +{ + assert_true(symbol_get_value(sym) != NULL && value == NULL, + "symbol_get_value(sym) == NULL || value != NULL"); +} + +void call_back_function_change(symbol sym, void* value) +{ + assert_true(symbol_get_value(sym) != NULL && value != NULL, + "symbol_get_value(sym) == NULL || value == NULL"); +} + + +void call_back_function_unset(symbol sym, void* value) +{ + assert_true(symbol_get_value(sym) == NULL && value != NULL, + "symbol_get_value(sym) != NULL || value == NULL"); +} + +void +test_ref(void) +{ + symbol_table table = NULL; + char name[] = "name"; + char value[] = "value"; + symbol sym = NULL; + symbol_ref ref = NULL; + symbol_ref ref1 = NULL; + symbol_ref ref2 = NULL; + struct symbol_ref walk; + const int num_refs = 2; + long int itag = 0; + + printf("test_ref\n"); + table = symbol_table_init_new(table, NULL, 0, 0, NULL, NULL); + + /* add */ + sym = symbol_lookup(table, name, 1); + symbol_set_value(sym, value); + + /* create references, in reverse order so that walk in order */ + ref2 = symbol_set_ref(NULL, sym); + assert_true(ref2 != NULL, "ref2 == NULL"); + sym_ref_set_i_tag(ref2, 2); + assert_true(sym_ref_i_tag(ref2) == 2, "sym_ref_i_tag(ref2) != 2"); + + ref1 = symbol_set_ref(NULL, sym); + assert_true(ref1 != NULL, "ref1 == NULL"); + sym_ref_set_i_tag(ref1, 1); + assert_true(sym_ref_i_tag(ref1) == 1, "sym_ref_i_tag(ref1) != 1"); + + /* walk references */ + itag = 1; + symbol_ref_walk_start(sym, &walk) ; + assert_true(sym->ref_list == &walk, "sym->ref_list != &walk"); + assert_true(walk.next == ref1, "walk.next != ref1"); + assert_true(ref1->next == ref2, "ref1->next != ref2"); + assert_true(ref2->next == NULL, "ref2->next != NULL"); + + while ((ref = symbol_ref_walk_step(&walk)) != NULL) + { + assert_true(sym_ref_i_tag(ref) == itag, "sym_ref_i_tag(ref) != itag"); + ++itag; + } + assert_true(itag == num_refs + 1, "itag != num_refs + 1"); + + symbol_ref_walk_end(&walk); + + /* clean up */ + symbol_unset_ref(ref1, 1); + symbol_unset_ref(ref2, 1); + + while ((symbol_table_ream(table, 1)) != NULL) + { + } +} + +void +test_ref_heavy(void) +{ + symbol_table table = NULL; + char name[] = "name"; + char value[] = "value"; + symbol sym = NULL; + symbol_ref ref = NULL; + struct symbol_ref walk; + const long int num_refs = 100000; + long int itag = 0; + + printf("test_ref_heavy\n"); + table = symbol_table_init_new(table, NULL, 0, 0, NULL, NULL); + + /* add */ + sym = symbol_lookup(table, name, 1); + symbol_set_value(sym, value); + + /* create references, in reverse order so that walk in order */ + for (itag = num_refs; itag > 0; --itag) + { + ref = symbol_set_ref(NULL, sym); + assert_true(ref != NULL, "ref == NULL"); + sym_ref_set_i_tag(ref, itag); + assert_true(sym_ref_i_tag(ref) == itag, "sym_ref_i_tag(ref) != itag"); + } + + /* walk references */ + itag = 1; + symbol_ref_walk_start(sym, &walk) ; + assert_true(sym->ref_list == &walk, "sym->ref_list != &walk"); + + while ((ref = symbol_ref_walk_step(&walk)) != NULL) + { + assert_true(sym_ref_i_tag(ref) == itag, "sym_ref_i_tag(ref) != itag"); + ++itag; + symbol_unset_ref(ref, 1); + } + assert_true(itag == num_refs + 1, "itag != num_refs + 1"); + + symbol_ref_walk_end(&walk); + + while ((symbol_table_ream(table, 1)) != NULL) + { + } +} + + +/* + * + * TODO + * + +symbol_table_set_parent +symbol_table_get_parent +symbol_hash_string +symbol_hash_bytes +symbol_table_set_value_call_back +symbol_table_free +symbol_unset_value +symbol_select_cmp +symbol_sort_cmp +symbol_table_extract +symbol_sort_cmp +symbol_get_name_len +symbol_get_table +symbol_zero_ref +symbol_dec_ref +symbol_init_ref +symbol_set_ref +symbol_unset_ref +symbol_unset_ref_free +symbol_unset_ref_keep +sym_ref_symbol +sym_ref_value +sym_ref_name +sym_ref_name_len +sym_ref_parent +sym_ref_p_tag +sym_ref_u_tag +sym_ref_i_tag +sym_ref_set_parent +sym_ref_set_p_tag +sym_ref_set_i_tag + */ diff --git a/tests/test-vector.c b/tests/test-vector.c new file mode 100644 index 00000000..808a7666 --- /dev/null +++ b/tests/test-vector.c @@ -0,0 +1,1377 @@ +#include <zebra.h> +#include <vector.h> + +/* Vector torture tests + * + */ + +/* prototypes */ +void assert_true(int result, const char * message); +int main(int argc, char **argv); +void test_vector_init(void); +void test_vector_set_index(void); +void test_vector_lookup(void); +void test_vector_lookup_ensure(void); +void test_vector_unset(void); +void test_vector_set_index_null(void); +void test_vector_copy(void); +void test_vector_set(void); +void test_vector_growth(void); + +/* GMCH interface */ +void test_vector_init_new(void); +void test_vector_set_item(void); +void test_vector_insert_item(void); +void test_vector_insert_item_here(void); +void test_vector_delete_item(void); +void do_test_insert(const int rider); +int sort_cmp(const void* const* a, const void* const* b); +void test_vector_sort(void); +void test_vector_bsearch(void); +void test_vector_move_item_here(void); +void do_test_move_item_here(const int rider, vector_index ins, vector_index src, + char strings[][10], const vector_index len) ; +void test_vector_part_reverse(void); +void test_vector_copy_here(void); +void test_vector_move_here(void); +void test_vector_copy_append(void); +void test_vector_move_append(void); +void test_vector_insert(void); +void test_vector_delete(void); +void test_vector_discard(void); +void test_vector_sak(void); + +struct thread_master *master; + +/* objects to put in the vectors */ +static char s0[5]; +static char s1000[5]; +static char s2000[5]; + +void +assert_true(int result, const char * message) +{ + if (!result) + { + printf("Assert failed: %s\n", message); + } +} + +int +main(int argc, char **argv) +{ + strcpy(s0, "0"); + strcpy(s1000, "1000"); + strcpy(s2000, "2000"); + + test_vector_init(); + test_vector_set_index(); + test_vector_lookup(); + test_vector_lookup_ensure(); + test_vector_unset(); + test_vector_set_index_null(); + test_vector_copy(); + test_vector_set(); + test_vector_growth(); + + /* GMCH interface */ + test_vector_init_new(); + test_vector_set_item(); + test_vector_insert_item(); + test_vector_insert_item_here(); + test_vector_delete_item(); + test_vector_sort(); + test_vector_bsearch(); + test_vector_move_item_here(); + test_vector_part_reverse(); + test_vector_copy_here(); + test_vector_move_here(); + test_vector_copy_append(); + test_vector_move_append(); + test_vector_insert(); + test_vector_delete(); + test_vector_discard(); + test_vector_sak(); + + return 0; +} + +void +test_vector_init(void) +{ + vector v = NULL; + + printf("test_vector_init\n"); + v = vector_init(10); + + assert_true(v != NULL, + "v == NULL"); + assert_true(vector_count(v) == 0, + "vector_count != 0"); + assert_true(vector_active(v) == 0, + "vector_active != 0"); + + vector_free(v); +} + +void +test_vector_set_index(void) +{ + vector v = NULL; + + printf("test_vector_set_index\n"); + v = vector_init(0); + + vector_set_index(v, 1000, s1000); + assert_true(vector_count(v) == 1, + "vector_count != 1"); + assert_true(vector_active(v) == 1001, + "vector_active != 1001"); + assert_true(vector_slot(v,1000) == s1000, + "vector_slot != 1000"); + + vector_free(v); +} + +void +test_vector_lookup(void) +{ + vector v = NULL; + + printf("test_vector_lookup\n"); + v = vector_init(0); + + vector_set_index(v, 1000, s1000); + + assert_true(vector_lookup(v,1000) == s1000, + "vector_lookup != 1000"); + assert_true(vector_lookup(v,1001) == NULL, + "vector_lookup != NULL"); + + vector_free(v); +} + +void +test_vector_lookup_ensure(void) +{ + vector v = NULL; + + printf("test_vector_lookup_ensure\n"); + v = vector_init(0); + + vector_set_index(v, 1000, s1000); + + assert_true(vector_lookup_ensure(v,1000) == s1000, + "vector_lookup_ensure != 1000"); + assert_true(vector_lookup_ensure(v,1001) == NULL, + "vector_lookup_ensure != NULL"); + + vector_free(v); +} + +void +test_vector_unset(void) +{ + vector v = NULL; + + printf("test_vector_unset\n"); + v = vector_init(0); + + vector_set_index(v, 1000, s1000); + vector_set_index(v, 2000, s2000); + assert_true(vector_count(v) == 2, + "vector_count != 2"); + assert_true(vector_active(v) == 2001, + "vector_active != 2001"); + + vector_unset(v, 2000); + assert_true(vector_count(v) == 1, + "vector_count != 1"); + assert_true(vector_active(v) == 1001, + "vector_active != 1001"); + + vector_free(v); +} + +void +test_vector_set_index_null(void) +{ + vector v = NULL; + + printf("test_vector_set_index_null\n"); + v = vector_init(0); + + vector_set_index(v, 1000, s1000); + vector_set_index(v, 2000, s2000); + assert_true(vector_count(v) == 2, + "vector_count != 2"); + assert_true(vector_active(v) == 2001, + "vector_active != 2001"); + + /* storing a NULL is not the same as vector_unset() */ + vector_set_index(v, 2000, NULL); + assert_true(vector_count(v) == 1, + "vector_count != 1"); + assert_true(vector_active(v) == 2001, + "vector_active != 2001"); + + /* GMCH change in semantics */ + vector_unset(v, 1000); + assert_true(vector_count(v) == 0, + "vector_count != 0"); + assert_true(vector_active(v) == 2001, + "vector_active != 2001 ignore post GMCH"); + assert_true(vector_active(v) == 0, + "vector_active != 0 ignore pre GMCH"); + + vector_free(v); +} + +void +test_vector_copy(void) +{ + vector v1 = NULL; + vector v2 = NULL; + int i; + const int len = 100; + char buf[10]; + + printf("test_vector_copy\n"); + + /* to help debug objects are strings of their index */ + v1 = vector_init(0); + for (i = 0; i < len; ++i) + { + sprintf(buf, "%d", i); + vector_set_index(v1, i, strdup(buf)); + } + + v2 = vector_copy(v1); + assert_true(v2 != NULL, "v2 == NULL"); + assert_true(v1 != v2, "v1 == v2"); + + /* check contents are the same */ + for (i = 0; i < len; ++i) + { + assert_true(vector_slot(v1, i) == vector_slot(v2, i), "v1 != v2"); + } + + /* free contents */ + for (i = 0; i < len; ++i) + { + free(vector_slot(v1, i)); + } + + vector_free(v1); + vector_free(v2); +} + +void +test_vector_set(void) +{ + vector v = NULL; + int i; + const int len = 1000; + char buf[10]; + + printf("test_vector_set\n"); + + /* to help debug objects are strings of their index */ + v = vector_init(0); + for (i = 0; i < len; ++i) + { + sprintf(buf, "%d", i); + vector_set_index(v, i, strdup(buf)); + } + + assert_true(vector_count(v) == (unsigned)len, + "vector_count != 1000"); + assert_true(vector_active(v) == (unsigned)len, + "vector_active != 1000"); + + vector_set(v, s1000); + assert_true(vector_count(v) == len + 1, + "vector_count != 1001"); + assert_true(vector_active(v) == len + 1, + "vector_active != 1001"); + assert_true(vector_slot(v,1000) == s1000, + "vector_slot != 1000"); + + /* free contents */ + for (i = 0; i < len; ++i) + { + free(vector_slot(v, i)); + } + + vector_free(v); +} + +void +test_vector_growth(void) +{ + vector v = NULL; + int i; + const int len = 150000; + char buf[10]; + + printf("test_vector_growth\n"); + + /* to help debug objects are strings of their index */ + v = vector_init(0); + for (i = 0; i < len; ++i) + { + sprintf(buf, "%d", i); + vector_set_index(v, i, strdup(buf)); + } + + assert_true(vector_count(v) == (unsigned)len, + "vector_count != len"); + assert_true(vector_active(v) == (unsigned)len, + "vector_active != len"); + + /* check contents are correct */ + for (i = 0; i < len; ++i) + { + sprintf(buf, "%d", i); + assert_true(strcmp(vector_slot(v, i), buf) == 0, "vector_slot(v, i) != buf"); + } + + /* free contents */ + for (i = 0; i < len; ++i) + { + free(vector_slot(v, i)); + } + + vector_free(v); +} + + +/* post GMCH interface */ + +void +test_vector_init_new(void) +{ + vector v = NULL; + void * item = NULL; + + printf("test_vector_init_new\n"); + + v = vector_init_new(v, 0); + assert_true(v != NULL, "v == NULL"); + assert_true(vector_is_empty(v), "!vector_is_empty(v)"); + assert_true(vector_end(v) == 0, "vector_end(v) != 0"); + + vector_push_item(v, s0); + assert_true(vector_end(v) == 1, "vector_end(v) != 1"); + + item = vector_pop_item(v); + assert_true(item == s0, "item != s0"); + assert_true(vector_is_empty(v), "!vector_is_empty(v)"); + assert_true(vector_end(v) == 0, "vector_end(v) != 0"); + + vector_free(v); +} + +void +test_vector_set_item(void) +{ + vector v = NULL; + void * item = NULL; + + printf("test_vector_set_item\n"); + + v = vector_init_new(v, 0); + vector_set_item(v, 0, s0); + vector_set_item(v, 1000, s1000); + vector_set_item(v, 2000, s2000); + assert_true(vector_end(v) == 2001, "vector_end(v) != 2001"); + + item = vector_get_item(v, 0); + assert_true(item == s0, "item != s0"); + item = vector_get_item(v, 1000); + assert_true(item == s1000, "item != s1000"); + item = vector_get_item(v, 2000); + assert_true(item == s2000, "item != s2000"); + + item = vector_get_first_item(v); + assert_true(item == s0, "item != s0"); + + item = vector_get_last_item(v); + assert_true(item == s2000, "item != s2000"); + + vector_free(v); +} +void +test_vector_insert_item(void) +{ + do_test_insert(2); +} + +void +test_vector_insert_item_here(void) +{ + do_test_insert(-1); + do_test_insert(0); + do_test_insert(1); +} + +void +test_vector_delete_item(void) +{ + do_test_insert(3); +} + +void +do_test_insert(const int rider) +{ + vector v = NULL; + const vector_index len = 100; + const vector_index ins = 50; + vector_index i; + char buf[10]; + vector_index check_end = len + 1; + vector_index check_ins = ins; + int check_shift = 1; + + switch(rider) + { + case -1: + printf("test_vector_insert_here before\n"); + break; + case 0: + printf("test_vector_insert_here at\n"); + check_shift = 0; + check_end = len; + break; + case 1: + printf("test_vector_insert_here after\n"); + check_ins++; + break; + case 2: + printf("test_vector_insert\n"); + break; + case 3: + printf("test_vector_delete\n"); + check_shift = -1; + check_end = len - 1; + break; + } + + v = vector_init_new(v, 0); + + for (i = 0; i < len; ++i) + { + sprintf(buf, "%d", i); + vector_set_item(v, i, strdup(buf)); + } + + switch(rider) + { + case -1: + case 0: + case 1: + vector_insert_item_here(v, ins, rider, strdup(s1000)); + break; + case 2: + vector_insert_item(v, ins, strdup(s1000)); + break; + case 3: + free(vector_delete_item(v, ins)); + break; + } + + assert_true(vector_end(v) == check_end, "vector_end(v) != check_end"); + + /* check contents are correct */ + for (i = 0; i < check_ins; ++i) + { + sprintf(buf, "%d", i); + assert_true(strcmp(vector_get_item(v, i), buf) == 0, + "vector_get_item(v, i) != buf"); + } + + if (rider != 3) + { + assert_true(strcmp(vector_get_item(v, check_ins), s1000) == 0, + "vector_get_item(v, check_ins) != s1000"); + } + + for (i = check_ins + 1; i < check_end; ++i) + { + sprintf(buf, "%d", i - check_shift); + assert_true(strcmp(vector_get_item(v, i), buf) == 0, "vector_get_item(v, i) != buf"); + } + + /* free contents */ + for (i = 0; i < vector_end(v); ++i) + { + free(vector_slot(v, i)); + } + + vector_free(v); +} + +void +test_vector_sort(void) +{ + vector v = NULL; + int i; + const int len = 100; + char buf[10]; + + printf("test_vector_sort\n"); + + v = vector_init(0); + + vector_sort(v, sort_cmp); /* null sort */ + + /* initialize backwards, using width so that lexical = numerical order */ + for (i = 0; i < len; ++i) + { + sprintf(buf, "%9d", i); + vector_set_index(v, len - i - 1, strdup(buf)); + } + + vector_sort(v, sort_cmp); + + /* check contents are correct */ + for (i = 0; i < len; ++i) + { + sprintf(buf, "%9d", i); + assert_true(strcmp(vector_slot(v, i), buf) == 0, "vector_slot(v, i) != buf"); + } + + /* free contents */ + for (i = 0; i < len; ++i) + { + free(vector_slot(v, i)); + } + + vector_free(v); +} + +int +sort_cmp(const void* const* a, const void* const* b) +{ + return strcmp(*a, *b); +} + +void +test_vector_bsearch(void) +{ + vector v = NULL; + int i; + const int len = 2000; + char buf[20]; + char target[20]; + vector_index target_index = 0; + int result; + vector_index index; + + printf("test_vector_bsearch\n"); + + sprintf(target, "%9u", target_index); + v = vector_init(0); + + index = vector_bsearch(v, sort_cmp, target, &result); /* null search */ + assert_true(index == 0, "index != 0"); + assert_true(result == -1, "result != -1"); + + /* initialize, using width so that lexical = numerical order */ + for (i = 0; i < len; ++i) + { + sprintf(buf, "%9d", i); + vector_set_index(v, i, strdup(buf)); + } + + for (target_index = 0; target_index < (unsigned)len; ++target_index) + { + sprintf(target, "%9u", target_index); + index = vector_bsearch(v, sort_cmp, target, &result); + assert_true(index == target_index, "index != target_index"); + assert_true(result == 0, "result != 0"); + assert_true(strcmp(vector_get_item(v, index), target) == 0, + "strcmp(vector_get_item(v, index), target)) != 0"); + } + + /* free contents */ + for (i = 0; i < len; ++i) + { + free(vector_slot(v, i)); + } + + vector_free(v); +} + +void +test_vector_move_item_here(void) +{ + const uint n = 20 ; + const uint l = n - 1 ; + char strings[n][10] ; + uint i ; + + for (i = 0 ; i < n ; ++i) + sprintf(strings[i], "item=%2u", i) ; + + do_test_move_item_here(-1, 8, 16, strings, n); + do_test_move_item_here( 0, 8, 16, strings, n); + do_test_move_item_here(+1, 8, 16, strings, n); + + do_test_move_item_here(-1, 16, 8, strings, n); + do_test_move_item_here( 0, 16, 8, strings, n); + do_test_move_item_here(+1, 16, 8, strings, n); + + do_test_move_item_here(-1, 9, 9, strings, n); + do_test_move_item_here( 0, 9, 9, strings, n); + do_test_move_item_here(+1, 9, 9, strings, n); + + do_test_move_item_here(-1, 10, 9, strings, n); + do_test_move_item_here( 0, 10, 9, strings, n); + do_test_move_item_here(+1, 10, 9, strings, n); + + do_test_move_item_here(-1, 9, 10, strings, n); + do_test_move_item_here( 0, 9, 10, strings, n); + do_test_move_item_here(+1, 9, 10, strings, n); + + do_test_move_item_here(-1, 11, 9, strings, n); + do_test_move_item_here( 0, 11, 9, strings, n); + do_test_move_item_here(+1, 11, 9, strings, n); + + do_test_move_item_here(-1, 9, 11, strings, n); + do_test_move_item_here( 0, 9, 11, strings, n); + do_test_move_item_here(+1, 9, 11, strings, n); + + do_test_move_item_here(-1, 0, 10, strings, n); + do_test_move_item_here( 0, 0, 10, strings, n); + do_test_move_item_here(+1, 0, 10, strings, n); + + do_test_move_item_here(-1, 10, 0, strings, n); + do_test_move_item_here( 0, 10, 0, strings, n); + do_test_move_item_here(+1, 10, 0, strings, n); + + do_test_move_item_here(-1, 0, l, strings, n); + do_test_move_item_here( 0, 0, l, strings, n); + do_test_move_item_here(+1, 0, l, strings, n); + + do_test_move_item_here(-1, l, 0, strings, n); + do_test_move_item_here( 0, l, 0, strings, n); + do_test_move_item_here(+1, l, 0, strings, n); + + do_test_move_item_here(-1, 10, l, strings, n); + do_test_move_item_here( 0, 10, l, strings, n); + do_test_move_item_here(+1, 10, l, strings, n); + + do_test_move_item_here(-1, l, 10, strings, n); + do_test_move_item_here( 0, l, 10, strings, n); + do_test_move_item_here(+1, l, 10, strings, n); + + do_test_move_item_here(-1, 0, 0, strings, n); + do_test_move_item_here( 0, 0, 0, strings, n); + do_test_move_item_here(+1, 0, 0, strings, n); + + do_test_move_item_here(-1, 1, 1, strings, n); + do_test_move_item_here( 0, 1, 1, strings, n); + do_test_move_item_here(+1, 1, 1, strings, n); + + do_test_move_item_here(-1, 0, 1, strings, n); + do_test_move_item_here( 0, 0, 1, strings, n); + do_test_move_item_here(+1, 0, 1, strings, n); + + do_test_move_item_here(-1, 1, 0, strings, n); + do_test_move_item_here( 0, 1, 0, strings, n); + do_test_move_item_here(+1, 1, 0, strings, n); + + do_test_move_item_here(-1, 0, 2, strings, n); + do_test_move_item_here( 0, 0, 2, strings, n); + do_test_move_item_here(+1, 0, 2, strings, n); + + do_test_move_item_here(-1, 2, 0, strings, n); + do_test_move_item_here( 0, 2, 0, strings, n); + do_test_move_item_here(+1, 2, 0, strings, n); + + do_test_move_item_here(-1, l, l, strings, n); + do_test_move_item_here( 0, l, l, strings, n); + do_test_move_item_here(+1, l, l, strings, n); + + do_test_move_item_here(-1,l-1, l, strings, n); + do_test_move_item_here( 0,l-1, l, strings, n); + do_test_move_item_here(+1,l-1, l, strings, n); + + do_test_move_item_here(-1, l,l-1, strings, n); + do_test_move_item_here( 0, l,l-1, strings, n); + do_test_move_item_here(+1, l,l-1, strings, n); +} + +void +do_test_move_item_here(const int rider, vector_index ins, vector_index src, + char strings[][10], const vector_index len) +{ + vector v = NULL; + vector_index i, e, check_end ; + vector_index hi, lo ; + char* expect[len] ; + + p_vector_item dest_item = NULL; + + switch(rider) + { + case -1: + printf("test_vector_move_here before dst=%2d, src=%2d\n", src, ins); + break; + + case 0: + printf("test_vector_move_here at dst=%2d, src=%2d\n", src, ins); + --check_end ; + break; + + case 1: + printf("test_vector_move_here after dst=%2d, src=%2d\n", src, ins); + break; + } ; + + /* Build the test vector and perform action */ + + v = vector_init_new(v, 0); + + for (i = 0; i < len; ++i) + vector_set_item(v, i, strdup(strings[i])); + + dest_item = vector_get_item(v, ins); /* item to free if rider == 0 */ + + vector_move_item_here(v, ins, rider, src); + + /* Build the expected result. */ + + if (ins <= src) + { + lo = ins ; + hi = src ; + } + else + { + lo = src ; + hi = ins ; + } ; + + check_end = (rider != 0) ? len : len - 1 ; + i = 0 ; + e = 0 ; + + while (i < lo) + expect[i++] = strings[e++] ; + + if (lo == hi) + { + /* Special case -- do nothing if rider != 0 + * drop entry if rider == 0 + */ + if (rider == 0) + ++e ; + } + else if (lo == (hi - 1)) + { + /* Special case -- ins and src next to each other ! + * + * If rider != 0 -- insert ins and src in the required order + * If rider == 0 -- insert just src + */ + if (rider < 0) + { + expect[i++] = strings[src] ; + expect[i++] = strings[ins] ; + } + else if (rider == 0) + { + expect[i++] = strings[src] ; + } + else + { + expect[i++] = strings[ins] ; + expect[i++] = strings[src] ; + } ; + e += 2 ; + } + else + { + /* Now we know that ins and src are separated by at least 1 entry. + */ + uint be ; + + be = hi - 1 ; + + if (ins < src) + { + /* At insertion point, so insert ins and src in the required order + * or insert juist the src. + */ + if (rider < 0) + { + expect[i++] = strings[src] ; + expect[i++] = strings[ins] ; + ++be ; + } + else if (rider == 0) + { + expect[i++] = strings[src] ; + } + else + { + expect[i++] = strings[ins] ; + expect[i++] = strings[src] ; + ++be ; + } ; + + ++be ; + } ; + + e += 1 ; + + while (i < be) + expect[i++] = strings[e++] ; + + if (ins > src) + { + /* At insertion point, so insert ins and src in the required order + * or insert juist the src. + */ + if (rider < 0) + { + expect[i++] = strings[src] ; + expect[i++] = strings[ins] ; + } + else if (rider == 0) + { + expect[i++] = strings[src] ; + } + else + { + expect[i++] = strings[ins] ; + expect[i++] = strings[src] ; + } ; + } ; + + e = hi + 1 ; + } ; + + while (i < check_end) + expect[i++] = strings[e++] ; + + /* check contents are correct */ + assert_true(vector_end(v) == check_end, "vector_end(v) != check_end"); + + for (i = 0 ; i < check_end ; ++i) + { + if (strcmp(vector_get_item(v, i), expect[i]) != 0) + { + assert_true(0, "vector_get_item(v, i) != expected") ; + break ; + } ; + } ; + + /* free contents */ + for (i = 0; i < vector_end(v); ++i) + free(vector_slot(v, i)); + + if (rider == 0) + free(dest_item); + + vector_free(v); +} + +void +test_vector_part_reverse(void) +{ + vector v = NULL; + const vector_index len = 100; + const vector_index rstart = 50; + const vector_index rstop = 70; + vector_index i; + char buf[10]; + + printf("test_vector_part_reverse\n"); + + v = vector_init_new(v, 0); + + for (i = 0; i < len; ++i) + { + sprintf(buf, "%u", i); + vector_set_item(v, i, strdup(buf)); + } + + vector_part_reverse(v, rstart, rstop - rstart); + assert_true(vector_end(v) == len, "vector_end(v) != len"); + + /* check contents are correct */ + + /* before reversed section */ + for (i = 0; i < rstart - 1; ++i) + { + sprintf(buf, "%u", i); + assert_true(strcmp(vector_get_item(v, i), buf) == 0, + "before reversed vector_get_item(v, i) != buf"); + } + + /* reversed section */ + for (i = rstart; i < rstop; ++i) + { + sprintf(buf, "%u", rstop - (i - rstart + 1)); + assert_true(strcmp(vector_get_item(v, i), buf) == 0, + "reversed vector_get_item(v, i) != buf"); + } + + /* after reversed section */ + for (i = rstop; i < len; ++i) + { + sprintf(buf, "%u", i); + assert_true(strcmp(vector_get_item(v, i), buf) == 0, + "after reversed vector_get_item(v, i) != buf"); + } + + /* free contents */ + for (i = 0; i < vector_end(v); ++i) + { + free(vector_slot(v, i)); + } + + vector_free(v); +} + +void +test_vector_copy_here(void) +{ + vector v1 = NULL; + vector v2 = NULL; + vector_index i; + const vector_index len = 100; + char buf[10]; + + printf("test_vector_copy_here\n"); + + /* to help debug objects are strings of their index */ + v1 = vector_init(0); + for (i = 0; i < len; ++i) + { + sprintf(buf, "%u", i); + vector_set_index(v1, i, strdup(buf)); + } + + v2 = vector_copy_here(v2, v1); + assert_true(v2 != NULL, "v2 == NULL"); + assert_true(v1 != v2, "v1 == v2"); + + /* check contents are the same */ + for (i = 0; i < len; ++i) + { + assert_true(vector_get_item(v1, i) == vector_get_item(v2, i), "v1 != v2"); + } + + /* free contents */ + for (i = 0; i < len; ++i) + { + free(vector_get_item(v1, i)); + } + + vector_free(v1); + vector_free(v2); +} + +void +test_vector_move_here(void) +{ + vector v1 = NULL; + vector v2 = NULL; + vector_index i; + const vector_index len = 100; + char buf[10]; + + printf("test_vector_move_here\n"); + + /* to help debug objects are strings of their index */ + v1 = vector_init(0); + for (i = 0; i < len; ++i) + { + sprintf(buf, "%u", i); + vector_set_index(v1, i, strdup(buf)); + } + + v2 = vector_move_here(v2, v1); + assert_true(v2 != NULL, "v2 == NULL"); + assert_true(v1 != v2, "v1 == v2"); + assert_true(vector_end(v1) == 0, "vector_end(v1) != 0"); + + /* check contents are the same */ + for (i = 0; i < len; ++i) + { + sprintf(buf, "%u", i); + assert_true(strcmp(vector_get_item(v2, i), buf) == 0, + "vector_get_item(v2, i) != buf"); + } + + /* free contents */ + for (i = 0; i < len; ++i) + { + free(vector_get_item(v2, i)); + } + + vector_free(v1); + vector_free(v2); +} + +void +test_vector_copy_append(void) +{ + vector v1 = NULL; + vector v2 = NULL; + vector_index i; + const vector_index len = 100; + char buf[10]; + + printf("test_vector_copy_append\n"); + + /* to help debug objects are strings of their index */ + v2 = vector_init(0); + for (i = 0; i < len; ++i) + { + sprintf(buf, "%u", i); + vector_set_index(v2, i, strdup(buf)); + } + + v1 = vector_init(0); + for (i = len; i < 2 * len; ++i) + { + sprintf(buf, "%u", i); + vector_set_index(v1, i - len, strdup(buf)); + } + + v2 = vector_copy_append(v2, v1); + assert_true(v2 != NULL, "v2 == NULL"); + assert_true(v1 != v2, "v1 == v2"); + assert_true(vector_end(v2) == 2 * len, "vector_end(v2) != 2 * len"); + + /* check contents */ + for (i = 0; i < 2 * len; ++i) + { + sprintf(buf, "%u", i); + assert_true(strcmp(vector_get_item(v2, i), buf) == 0, + "vector_get_item(v2, i) != buf"); + } + + /* free contents */ + for (i = 0; i < 2 * len; ++i) + { + free(vector_get_item(v2, i)); + } + + vector_free(v1); + vector_free(v2); +} + +void +test_vector_move_append(void) +{ + vector v1 = NULL; + vector v2 = NULL; + vector_index i; + const vector_index len = 100; + char buf[10]; + + printf("test_vector_move_append\n"); + + /* to help debug objects are strings of their index */ + v2 = vector_init(0); + for (i = 0; i < len; ++i) + { + sprintf(buf, "%u", i); + vector_set_index(v2, i, strdup(buf)); + } + + v1 = vector_init(0); + for (i = len; i < 2 * len; ++i) + { + sprintf(buf, "%u", i); + vector_set_index(v1, i - len, strdup(buf)); + } + + v2 = vector_move_append(v2, v1); + assert_true(v2 != NULL, "v2 == NULL"); + assert_true(v1 != v2, "v1 == v2"); + assert_true(vector_end(v2) == 2 * len, "vector_end(v2) != 2 * len"); + assert_true(vector_end(v1) == 0, "vector_end(v1) != 0"); + + /* check contents */ + for (i = 0; i < 2 * len; ++i) + { + sprintf(buf, "%u", i); + assert_true(strcmp(vector_get_item(v2, i), buf) == 0, + "vector_get_item(v2, i) != buf"); + } + + /* free contents */ + for (i = 0; i < 2 * len; ++i) + { + free(vector_get_item(v2, i)); + } + + vector_free(v1); + vector_free(v2); +} + +void +test_vector_insert(void) +{ + vector v = NULL; + vector_index i; + const vector_index len = 100; + const vector_index istart = 50; + const vector_index istop = 70; + char buf[10]; + + printf("test_vector_insert\n"); + + /* to help debug objects are strings of their index */ + + v = vector_init(0); + for (i = 0; i < len; ++i) + { + sprintf(buf, "%u", i); + vector_set_index(v, i, strdup(buf)); + } + + vector_insert(v, istart, istop - istart); + assert_true(vector_end(v) == len + (istop - istart), + "vector_end(v) != len + (istop - istart)"); + + /* check contents */ + for (i = 0; i < istart; ++i) + { + sprintf(buf, "%u", i); + assert_true(strcmp(vector_get_item(v, i), buf) == 0, + "vector_get_item(v, i) != buf"); + } + + for (i = istart + 1; i < istop; ++i) + { + assert_true(vector_get_item(v, i) == NULL, + "vector_get_item(v, i) != NULL"); + } + + for (i = istop; i < len + (istop - istart); ++i) + { + sprintf(buf, "%u", i - (istop - istart)); + assert_true(strcmp(vector_get_item(v, i), buf) == 0, + "vector_get_item(v, i) != buf"); + } + + /* free contents */ + for (i = 0; i < len + (istop - istart); ++i) + { + free(vector_get_item(v, i)); + } + + vector_free(v); +} + +void +test_vector_delete(void) +{ + vector v = NULL; + vector_index i; + const vector_index len = 100; + const vector_index dstart = 50; + const vector_index dstop = 70; + char buf[10]; + + printf("test_vector_delete\n"); + + /* to help debug objects are strings of their index */ + + v = vector_init(0); + for (i = 0; i < len; ++i) + { + if (i < dstart || i >= dstop) + { + sprintf(buf, "%u", i); + vector_set_index(v, i, strdup(buf)); + } + else + { + vector_set_index(v, i, s0); + } + } + + vector_delete(v, dstart, dstop - dstart); + assert_true(vector_end(v) == len - (dstop - dstart), + "vector_end(v) != len - (dstop - dstart)"); + + /* check contents */ + for (i = 0; i < dstart; ++i) + { + sprintf(buf, "%u", i); + assert_true(strcmp(vector_get_item(v, i), buf) == 0, + "vector_get_item(v, i) != buf"); + } + + for (i = dstart; i < len - (dstop - dstart); ++i) + { + sprintf(buf, "%u", i + (dstop - dstart)); + assert_true(strcmp(vector_get_item(v, i), buf) == 0, + "vector_get_item(v, i) != buf"); + } + + /* free contents */ + for (i = 0; i < len - (dstop - dstart); ++i) + { + free(vector_get_item(v, i)); + } + + vector_free(v); +} + +void +test_vector_discard(void) +{ + vector v = NULL; + vector_index i; + const vector_index len = 100; + const vector_index dstart = 50; + char buf[10]; + + printf("test_vector_discard\n"); + + /* to help debug objects are strings of their index */ + + v = vector_init(0); + for (i = 0; i < len; ++i) + { + if (i < dstart) + { + sprintf(buf, "%u", i); + vector_set_index(v, i, strdup(buf)); + } + else + { + vector_set_index(v, i, s0); + } + } + + vector_discard(v, dstart); + assert_true(vector_end(v) == dstart, + "vector_end(v) != dstart"); + + /* check contents */ + for (i = 0; i < dstart; ++i) + { + sprintf(buf, "%u", i); + assert_true(strcmp(vector_get_item(v, i), buf) == 0, + "vector_get_item(v, i) != buf"); + } + + /* free contents */ + for (i = 0; i < dstart; ++i) + { + free(vector_get_item(v, i)); + } + + vector_free(v); +} + +void +test_vector_sak(void) +{ + vector v1 = NULL; + vector v2 = NULL; + vector v3 = NULL; + vector_index i; + const vector_index len = 100; + const vector_index sstart = 60; + const vector_index sstop = 70; + const vector_index dstart = 40; + const vector_index dstop = 50; + char buf[10]; + + printf("test_vector_sak\n"); + + /* to help debug objects are strings of their index */ + + v2 = vector_init(0); + v3 = vector_init(0); + for (i = 0; i < len; ++i) + { + sprintf(buf, "%u", i); + vector_set_index(v2, i, strdup(buf)); + vector_set_index(v3, i, strdup(buf)); + } + + v1 = vector_sak(1, v1, v2, dstart, dstop - dstart, + v3, sstart, sstop - sstart, 0); + assert_true(v1 != NULL, "v1 == NULL"); + + assert_true(vector_end(v1) == (dstop - dstart), + "vector_end(v1) != (dstop - dstart)"); + assert_true(vector_end(v2) == len, + "vector_end(v2) != len"); + assert_true(vector_end(v3) == len, + "vector_end(v3) != len"); + + /* check contents v1 */ + for (i = 0; i < dstop - dstart; ++i) + { + sprintf(buf, "%u", i + dstart); + assert_true(vector_get_item(v1, i) != NULL, + "vector_get_item(v1, i) == NULL"); + assert_true(strcmp(vector_get_item(v1, i), buf) == 0, + "vector_get_item(v1, i) != buf"); + } + + /* check contents v2 */ + for (i = 0; i < dstart; ++i) + { + sprintf(buf, "%u", i); + assert_true(strcmp(vector_get_item(v2, i), buf) == 0, + "vector_get_item(v2, i) != buf"); + } + for (i = dstart; i < dstop; ++i) + { + sprintf(buf, "%u", i - dstart + sstart); + assert_true(strcmp(vector_get_item(v2, i), buf) == 0, + "vector_get_item(v2, i) != buf"); + } + for (i = dstop; i < len; ++i) + { + sprintf(buf, "%u", i); + assert_true(strcmp(vector_get_item(v2, i), buf) == 0, + "vector_get_item(v2, i) != buf"); + } + + /* check contents v3 */ + for (i = 0; i < len; ++i) + { + sprintf(buf, "%u", i); + assert_true(strcmp(vector_get_item(v3, i), buf) == 0, + "vector_get_item(v3, i) != buf"); + } + + /* free contents */ + for (i = 0; i < len; ++i) + { + free(vector_get_item(v3, i)); + } + + vector_free(v1); + vector_free(v2); + vector_free(v3); +} +/* + * TODO + * + +vector_re_init +vector_reset +vector_ream +vector_sak +vector_chop +vector_decant +vector_extend_by_1 + +*/ |