From: Vincent Bernat Date: Sun, 5 Jul 2009 17:30:56 +0000 (+0200) Subject: Unit tests for packing/unpacking. X-Git-Tag: 0.5.0~53 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2acc14181074a882633693a2fa9c91dc06c9d30b;p=thirdparty%2Flldpd.git Unit tests for packing/unpacking. We build a static library liblldpd.la to ease linking to tests. liblldpd.la is equal to lldpd except: - no main (but lldpd_main instead) - no link to netsnmp (because libtool try to link many many more things) --- diff --git a/Makefile.am b/Makefile.am index c28b8c16..75efe649 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,2 +1,3 @@ -SUBDIRS = src man +ACLOCAL_AMFLAGS = -I m4 +SUBDIRS = src man tests dist_doc_DATA = README diff --git a/configure.ac b/configure.ac index 466a7e2b..d74bcd01 100644 --- a/configure.ac +++ b/configure.ac @@ -6,10 +6,16 @@ AC_INIT(lldpd, 0.5.0, bernat@luffy.cx) AM_INIT_AUTOMAKE([foreign]) AC_CONFIG_SRCDIR([src/lldpd.c]) AC_CONFIG_HEADER([config.h]) -AC_CONFIG_FILES([Makefile src/Makefile man/Makefile]) +AC_CONFIG_FILES([Makefile src/Makefile man/Makefile tests/Makefile]) +AC_CONFIG_MACRO_DIR([m4]) # Checks for programs. AC_PROG_CC +AC_PROG_LIBTOOL + +# Unit tests +PKG_CHECK_MODULES([CHECK], [check >= 0.9.4], have_check=yes, have_check=no) +AM_CONDITIONAL(HAVE_CHECK, test x$have_check = xyes) # Checks for libraries. AC_ARG_WITH(snmp, diff --git a/src/Makefile.am b/src/Makefile.am index 82329974..79e9d812 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,14 +1,19 @@ sbin_PROGRAMS = lldpd lldpctl +noinst_LTLIBRARIES = liblldpd.la COMMON = log.c ctl.c lldpd.h lldp.h cdp.h compat.h sonmp.h edp.h -lldpd_SOURCES = frame.h frame.c lldpd.c lldp.c cdp.c sonmp.c edp.c interfaces.c client.c priv.c privsep_fdpass.c dmi.c $(COMMON) +liblldpd_la_SOURCES = frame.h frame.c lldpd.c lldp.c cdp.c sonmp.c edp.c interfaces.c client.c priv.c privsep_fdpass.c dmi.c $(COMMON) lldpctl_SOURCES = lldpctl.c $(COMMON) -lldpd_LDADD = @LIBOBJS@ +liblldpd_la_LIBADD = @LTLIBOBJS@ lldpctl_LDADD = @LIBOBJS@ lldpctl_CFLAGS = -DCLIENT_ONLY +lldpd_SOURCES = main.c +lldpd_LDADD = liblldpd.la + if USE_SNMP -lldpd_SOURCES += agent.c agent_priv.c +liblldpd_la_SOURCES += agent.c agent_priv.c lldpd_LDADD += @NETSNMP_LIB@ endif + diff --git a/src/lldpd.c b/src/lldpd.c index 63989b55..20bd73b2 100644 --- a/src/lldpd.c +++ b/src/lldpd.c @@ -724,7 +724,7 @@ lldpd_exit() } int -main(int argc, char *argv[]) +lldpd_main(int argc, char *argv[]) { struct lldpd *cfg; struct lldpd_chassis *lchassis; diff --git a/src/lldpd.h b/src/lldpd.h index de76fa63..796786c4 100644 --- a/src/lldpd.h +++ b/src/lldpd.h @@ -35,6 +35,7 @@ #include #include #include +#include #include "compat.h" #include "lldp.h" @@ -344,6 +345,7 @@ void lldpd_port_cleanup(struct lldpd_port *, int); void lldpd_chassis_cleanup(struct lldpd_chassis *, int); int lldpd_callback_add(struct lldpd *, int, void(*fn)(CALLBACK_SIG), void *); void lldpd_callback_del(struct lldpd *, int, void(*fn)(CALLBACK_SIG)); +int lldpd_main(int, char **); /* lldp.c */ int lldp_send(PROTO_SEND_SIG); diff --git a/src/main.c b/src/main.c new file mode 100644 index 00000000..5670e9fa --- /dev/null +++ b/src/main.c @@ -0,0 +1,7 @@ +#include "lldpd.h" + +int +main(int argc, char **argv) +{ + return lldpd_main(argc, argv); +} diff --git a/tests/Makefile.am b/tests/Makefile.am new file mode 100644 index 00000000..0a8a08b4 --- /dev/null +++ b/tests/Makefile.am @@ -0,0 +1,16 @@ +TESTS = check_pack + +if HAVE_CHECK + +check_PROGRAMS = check_pack + +check_pack_SOURCES = check_pack.c \ + $(top_builddir)/src/lldpd.h +check_pack_CFLAGS = @CHECK_CFLAGS@ +check_pack_LDADD = $(top_builddir)/src/liblldpd.la @CHECK_LIBS@ + +if USE_SNMP +check_pack_LDADD += @NETSNMP_LIB@ +endif + +endif diff --git a/tests/check_pack.c b/tests/check_pack.c new file mode 100644 index 00000000..a6cc3a79 --- /dev/null +++ b/tests/check_pack.c @@ -0,0 +1,542 @@ +#include +#include +#include +#include +#include +#include +#include +#include "../src/lldpd.h" + +struct hmsg *h = NULL; + +void +setup() +{ + h = (struct hmsg *)calloc(1, MAX_HMSGSIZE); + fail_unless(h != NULL); +} + +void teardown() +{ + free(h); h = NULL; +} + +START_TEST (test_pack_byte) +{ + /* Packing a single byte */ + char byte = 18; + void *p; + p = (char*)&h->data; + fail_unless(ctl_msg_pack_structure("b", &byte, sizeof(char), + h, &p) != -1); + mark_point(); + p = (char*)&h->data; + fail_unless(ctl_msg_unpack_structure("b", &byte, sizeof(char), + h, &p) != -1); + ck_assert_int_eq(byte, 18); +} +END_TEST + +START_TEST (test_pack_word) +{ + /* Packing a single word */ + u_int16_t word = 7874; + void *p; + p = (char*)&h->data; + fail_unless(ctl_msg_pack_structure("w", &word, sizeof(u_int16_t), + h, &p) != -1); + mark_point(); + p = (char*)&h->data; + fail_unless(ctl_msg_unpack_structure("w", &word, sizeof(u_int16_t), + h, &p) != -1); + ck_assert_int_eq(word, 7874); +} +END_TEST + +START_TEST (test_pack_long) +{ + /* Packing a single long */ + u_int32_t l = 14523657; + void *p; + p = (char*)&h->data; + fail_unless(ctl_msg_pack_structure("l", &l, sizeof(u_int32_t), + h, &p) != -1); + mark_point(); + p = (char*)&h->data; + fail_unless(ctl_msg_unpack_structure("l", &l, sizeof(u_int32_t), + h, &p) != -1); + ck_assert_int_eq(l, 14523657); +} +END_TEST + +START_TEST (test_pack_time) +{ + /* Packing a single time_t */ + time_t t = time(NULL); + time_t t2; + void *p; + t2 = t; + p = (char*)&h->data; + fail_unless(ctl_msg_pack_structure("t", &t, sizeof(time_t), + h, &p) != -1); + mark_point(); + p = (char*)&h->data; + fail_unless(ctl_msg_unpack_structure("t", &t, sizeof(time_t), + h, &p) != -1); + ck_assert_int_eq(t, t2); +} +END_TEST + +START_TEST (test_pack_string) +{ + /* Packing a single string */ + char *s = "My simple string"; + char *rs; + void *p; + p = (char*)&h->data; + fail_unless(ctl_msg_pack_structure("s", &s, sizeof(char *), + h, &p) != -1); + mark_point(); + p = (char*)&h->data; + fail_unless(ctl_msg_unpack_structure("s", &rs, sizeof(char *), + h, &p) != -1); + ck_assert_str_eq(s, rs); + ck_assert_str_eq(rs, "My simple string"); + free(rs); +} +END_TEST + +START_TEST (test_pack_null_string) +{ + /* Packing a single empty string */ + char *s = ""; + char *rs; + void *p; + p = (char*)&h->data; + fail_unless(ctl_msg_pack_structure("s", &s, sizeof(char *), + h, &p) != -1); + mark_point(); + p = (char*)&h->data; + fail_unless(ctl_msg_unpack_structure("s", &rs, sizeof(char *), + h, &p) != -1); + ck_assert_str_eq(s, rs); + ck_assert_int_eq(strlen(rs), 0); + free(rs); +} +END_TEST + +struct tpls { + char *s; + int l; +}; + +START_TEST (test_pack_len_string) +{ + /* Packing a single string with its length */ + struct tpls t; + void *p; + + t.s = "My string"; + t.l = strlen(t.s); + + p = (char*)&h->data; + fail_unless(ctl_msg_pack_structure("C", &t, sizeof(struct tpls), + h, &p) != -1); + mark_point(); + p = (char*)&h->data; + fail_unless(ctl_msg_unpack_structure("C", &t, sizeof(struct tpls), + h, &p) != -1); + ck_assert_int_eq(t.l, strlen("My string")); + fail_unless(memcmp(t.s, "My string", t.l) == 0); + free(t.s); +} +END_TEST + +struct tps1 { + u_int8_t a; + u_int16_t b; + u_int32_t c; + u_int8_t d; + void *e; + u_int8_t f; + time_t g; +}; + +START_TEST (test_pack_structures1) +{ + /* Test padding */ + struct tps1 t; + void *p; + t.a = 129; + t.b = 37814; + t.c = 3456781258; + t.d = 14; + t.e = &t; + t.f = 47; + t.g = 1246799447; + + p = (char*)&h->data; + fail_unless(ctl_msg_pack_structure("bwlbPbt", &t, sizeof(struct tps1), + h, &p) != -1); + mark_point(); + p = (char*)&h->data; + fail_unless(ctl_msg_unpack_structure("bwlbPbt", &t, sizeof(struct tps1), + h, &p) != -1); + ck_assert_int_eq(t.a, 129); + ck_assert_int_eq(t.b, 37814); + ck_assert_int_eq(t.c, 3456781258); + ck_assert_int_eq(t.d, 14); + ck_assert_int_eq(t.f, 47); + ck_assert_int_eq(t.g, 1246799447); +} +END_TEST + +struct tps2 { + u_int8_t a; + void *b; + u_int16_t c; + void *d; + u_int32_t e; + void *f; + time_t g; + void *h; + u_int8_t i; +}; + +START_TEST (test_pack_structures2) +{ + /* More padding */ + struct tps2 t; + void *p; + t.a = 129; + t.c = 37814; + t.e = 3456781258; + t.g = 1246799447; + t.i = 12; + + p = (char*)&h->data; + fail_unless(ctl_msg_pack_structure("bPwPlPtPb", &t, sizeof(struct tps2), + h, &p) != -1); + mark_point(); + p = (char*)&h->data; + fail_unless(ctl_msg_unpack_structure("bPwPlPtPb", &t, sizeof(struct tps2), + h, &p) != -1); + ck_assert_int_eq(t.a, 129); + ck_assert_int_eq(t.c, 37814); + ck_assert_int_eq(t.e, 3456781258); + ck_assert_int_eq(t.g, 1246799447); + ck_assert_int_eq(t.i, 12); +} +END_TEST + +struct tps3 { + u_int8_t a; + char *b; + u_int16_t c; + char *d; + u_int32_t e; + char *f; + time_t g; + char *h; + u_int8_t i; + char *j; + int l; + u_int8_t k; + char *m; +}; + +START_TEST (test_pack_structures3) +{ + /* More padding, with strings */ + struct tps3 t; + void *p; + t.a = 129; + t.b = "First string"; + t.c = 37814; + t.d = "Second string"; + t.e = 3456781258; + t.f = "Third string"; + t.g = 1246799447; + t.h = "Fourth string"; + t.i = 12; + t.j = "Fifth string"; + t.l = strlen(t.j); + t.k = 89; + t.m = "Last string"; + + p = (char*)&h->data; + fail_unless(ctl_msg_pack_structure("bswslstsbCbs", &t, sizeof(struct tps3), + h, &p) != -1); + mark_point(); + p = (char*)&h->data; + fail_unless(ctl_msg_unpack_structure("bswslstsbCbs", &t, sizeof(struct tps3), + h, &p) != -1); + ck_assert_int_eq(t.a, 129); + ck_assert_str_eq(t.b, "First string"); + ck_assert_int_eq(t.c, 37814); + ck_assert_str_eq(t.d, "Second string"); + ck_assert_int_eq(t.e, 3456781258); + ck_assert_str_eq(t.f, "Third string"); + ck_assert_int_eq(t.g, 1246799447); + ck_assert_str_eq(t.h, "Fourth string"); + ck_assert_int_eq(t.i, 12); + ck_assert_int_eq(t.l, strlen("Fifth string")); + fail_unless(memcmp(t.j, "Fifth string", t.l) == 0); + ck_assert_int_eq(t.k, 89); + ck_assert_str_eq(t.m, "Last string"); + free(t.b); free(t.d); free(t.f); free(t.h); free(t.j); free(t.m); +} +END_TEST + +struct tps4_1 { + u_int8_t a; + u_int16_t b; + u_int32_t c; + time_t d; + u_int8_t e; + void *f; + u_int8_t g; + char *h; + u_int8_t i; +}; +#define TPS41 "(bwltbPbsb)" + +struct tps4 { + u_int8_t a; + struct tps4_1 b; + u_int16_t c; + struct tps4_1 d; + u_int32_t e; + struct tps4_1 f; + void *g; + struct tps4_1 h; + struct tps4_1 i; + u_int8_t j; +}; +#define TPS4 "b" TPS41 "w" TPS41 "l" TPS41 "P" TPS41 TPS41 "b" + +START_TEST (test_pack_structures4) +{ + /* More padding, with substructures */ + struct tps4 t; + void *p; + t.a = 129; + t.b.a = 178; + t.b.b = 37894; + t.b.c = 345678914; + t.b.d = 345781741; + t.b.e = 74; + t.b.g = 78; + t.b.h = "First string"; + t.b.i = 230; + t.c = 37814; + t.d.a = t.b.a + 1; + t.d.b = t.b.b + 1; + t.d.c = t.b.c + 1; + t.d.d = t.b.d + 1; + t.d.e = t.b.e + 1; + t.d.g = t.b.g + 1; + t.d.h = "Second string"; + t.d.i = t.b.i + 1; + t.e = 3456781258; + t.f.a = t.b.a + 2; + t.f.b = t.b.b + 2; + t.f.c = t.b.c + 2; + t.f.d = t.b.d + 2; + t.f.e = t.b.e + 2; + t.f.g = t.b.g + 2; + t.f.h = "Third string"; + t.f.i = t.b.i + 2; + t.h.a = t.b.a + 3; + t.h.b = t.b.b + 3; + t.h.c = t.b.c + 3; + t.h.d = t.b.d + 3; + t.h.e = t.b.e + 3; + t.h.g = t.b.g + 3; + t.h.h = "Fourth string"; + t.h.i = t.b.i + 3; + t.i.a = t.b.a + 4; + t.i.b = t.b.b + 4; + t.i.c = t.b.c + 4; + t.i.d = t.b.d + 4; + t.i.e = t.b.e + 4; + t.i.g = t.b.g + 4; + t.i.h = "Fifth string"; + t.i.i = t.b.i + 4; + t.j = 12; + + p = (char*)&h->data; + fail_unless(ctl_msg_pack_structure(TPS4, &t, sizeof(struct tps4), + h, &p) != -1); + mark_point(); + p = (char*)&h->data; + fail_unless(ctl_msg_unpack_structure(TPS4, &t, sizeof(struct tps4), + h, &p) != -1); + + ck_assert_int_eq(t.a, 129); + ck_assert_int_eq(t.b.a, 178); + ck_assert_int_eq(t.b.b, 37894); + ck_assert_int_eq(t.b.c, 345678914); + ck_assert_int_eq(t.b.d, 345781741); + ck_assert_int_eq(t.b.e, 74); + ck_assert_int_eq(t.b.g, 78); + ck_assert_str_eq(t.b.h, "First string"); + ck_assert_int_eq(t.b.i, 230); + ck_assert_int_eq(t.c, 37814); + ck_assert_int_eq(t.d.a, t.b.a + 1); + ck_assert_int_eq(t.d.b, t.b.b + 1); + ck_assert_int_eq(t.d.c, t.b.c + 1); + ck_assert_int_eq(t.d.d, t.b.d + 1); + ck_assert_int_eq(t.d.e, t.b.e + 1); + ck_assert_int_eq(t.d.g, t.b.g + 1); + ck_assert_str_eq(t.d.h, "Second string"); + ck_assert_int_eq(t.d.i, t.b.i + 1); + ck_assert_int_eq(t.e, 3456781258); + ck_assert_int_eq(t.f.a, t.b.a + 2); + ck_assert_int_eq(t.f.b, t.b.b + 2); + ck_assert_int_eq(t.f.c, t.b.c + 2); + ck_assert_int_eq(t.f.d, t.b.d + 2); + ck_assert_int_eq(t.f.e, t.b.e + 2); + ck_assert_int_eq(t.f.g, t.b.g + 2); + ck_assert_str_eq(t.f.h, "Third string"); + ck_assert_int_eq(t.f.i, t.b.i + 2); + ck_assert_int_eq(t.h.a, t.b.a + 3); + ck_assert_int_eq(t.h.b, t.b.b + 3); + ck_assert_int_eq(t.h.c, t.b.c + 3); + ck_assert_int_eq(t.h.d, t.b.d + 3); + ck_assert_int_eq(t.h.e, t.b.e + 3); + ck_assert_int_eq(t.h.g, t.b.g + 3); + fail_unless(strcmp(t.h.h, "Fourth string") == 0); + ck_assert_int_eq(t.h.i, t.b.i + 3); + ck_assert_int_eq(t.i.a, t.b.a + 4); + ck_assert_int_eq(t.i.b, t.b.b + 4); + ck_assert_int_eq(t.i.c, t.b.c + 4); + ck_assert_int_eq(t.i.d, t.b.d + 4); + ck_assert_int_eq(t.i.e, t.b.e + 4); + ck_assert_int_eq(t.i.g, t.b.g + 4); + ck_assert_str_eq(t.i.h, "Fifth string"); + ck_assert_int_eq(t.i.i, t.b.i + 4); + ck_assert_int_eq(t.j, 12); + free(t.i.h); free(t.h.h); free(t.f.h); free(t.d.h); free(t.b.h); +} +END_TEST + +struct tps51 { + u_int8_t a; + u_int16_t b; + u_int32_t c; + u_int8_t e; + time_t f; + u_int16_t g; + u_int8_t h; + u_int32_t i; + u_int16_t j; +}; +#define TPS51 "(bwlbtwblw)" + +struct tps52 { + u_int8_t a; + struct tps51 b; + u_int16_t c; + struct tps51 d; + u_int32_t e; + struct tps51 f; + struct tps51 g; + u_int8_t h; +}; +#define TPS52 "(b" TPS51 "w" TPS51 "l" TPS51 TPS51 "b)" + +struct tps53 { + u_int8_t a; + struct tps52 b; + u_int16_t c; + struct tps52 d; + u_int32_t e; + struct tps51 f; + struct tps52 g; + u_int8_t h; +}; +#define TPS53 "(b" TPS52 "w" TPS52 "l" TPS51 TPS52 "b)" + +struct tps5 { + u_int8_t a; + struct tps51 b; + u_int16_t c; + struct tps53 d; + u_int32_t e; + struct tps53 f; + struct tps53 g; + u_int8_t h; +}; +#define TPS5 "(b" TPS51 "w" TPS53 "l" TPS53 TPS53 "b)" + +START_TEST (test_pack_structures5) +{ + /* More padding, with recursive substructures */ + struct tps5 t; + struct tps5 tc; + int f, n; + void *p; + + f = open("/dev/urandom", O_RDONLY); + fail_unless(f != -1); + n = read(f, &t, sizeof(struct tps5)); + fail_unless(n == sizeof(struct tps5), + "Should have read %d bytes from /dev/random but got %d", + sizeof(struct tps5), n); + memcpy(&tc, &t, sizeof(struct tps5)); + close(f); + + p = (char*)&h->data; + fail_unless(ctl_msg_pack_structure(TPS5, &t, sizeof(struct tps5), + h, &p) != -1); + mark_point(); + p = (char*)&h->data; + fail_unless(ctl_msg_unpack_structure(TPS5, &t, sizeof(struct tps5), + h, &p) != -1); + + fail_unless(memcmp(&t, &tc, sizeof(struct tps5)) == 0); +} +END_TEST + +Suite * +pack_suite(void) +{ + Suite *s = suite_create("Packing"); + + /* Single objects packing/unpacking */ + TCase *tc_core = tcase_create("Single objects"); + tcase_add_checked_fixture(tc_core, setup, teardown); + tcase_add_test(tc_core, test_pack_byte); + tcase_add_test(tc_core, test_pack_word); + tcase_add_test(tc_core, test_pack_long); + tcase_add_test(tc_core, test_pack_time); + tcase_add_test(tc_core, test_pack_string); + tcase_add_test(tc_core, test_pack_null_string); + tcase_add_test(tc_core, test_pack_len_string); + suite_add_tcase(s, tc_core); + + /* Complex structure packing/unpacking */ + TCase *tc_structures = tcase_create("Structures"); + tcase_add_checked_fixture(tc_structures, setup, teardown); + tcase_add_test(tc_structures, test_pack_structures1); + tcase_add_test(tc_structures, test_pack_structures2); + tcase_add_test(tc_structures, test_pack_structures3); + tcase_add_test(tc_structures, test_pack_structures4); + tcase_add_test(tc_structures, test_pack_structures5); + suite_add_tcase(s, tc_structures); + + return s; +} + +int +main() +{ + int number_failed; + Suite *s = pack_suite (); + SRunner *sr = srunner_create (s); + srunner_run_all (sr, CK_ENV); + number_failed = srunner_ntests_failed (sr); + srunner_free (sr); + return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; +}