#include "pico_config.h" #include "pico_eth.h" #include "pico_socket.h" #include "pico_stack.h" #include "pico_socket.h" #include "pico_queue.h" #include "pico_tree.h" #include "modules/pico_mld.c" #include "check.h" #include "pico_dev_null.c" Suite *pico_suite(void); void mock_callback(struct mld_timer *t); static uint32_t timers_added = 0; uint32_t pico_timer_add(pico_time expire, void (*timer)(pico_time, void *), void *arg) { IGNORE_PARAMETER(expire); IGNORE_PARAMETER(timer); IGNORE_PARAMETER(arg); return ++timers_added; } void mock_callback(struct mld_timer *t) { IGNORE_PARAMETER(t); } static int mcast_filter_cmp_ipv6(void *ka, void *kb) { union pico_address *a = ka, *b = kb; return memcmp(&a->ip6, &b->ip6, sizeof(struct pico_ip6)); } static int mcast_sources_cmp_ipv6(void *ka, void *kb) { union pico_address *a = ka, *b = kb; return memcmp(&a->ip6, &b->ip6, sizeof(struct pico_ip6)); } static PICO_TREE_DECLARE(_MCASTFilter, mcast_filter_cmp_ipv6); START_TEST(tc_pico_mld_fill_hopbyhop) { struct pico_ipv6_hbhoption *hbh = NULL; /* Not-null case tested by unit_ipv6.c */ fail_if(pico_mld_fill_hopbyhop(hbh) != NULL); } END_TEST START_TEST(tc_pico_mld_check_hopbyhop) { struct pico_ipv6_hbhoption *hbh = NULL; struct pico_ipv6_hbhoption _hbh; uint8_t *p; uint8_t options[8] = { PICO_PROTO_ICMP6, 0, PICO_IPV6_EXTHDR_OPT_ROUTER_ALERT, \ PICO_IPV6_EXTHDR_OPT_ROUTER_ALERT_DATALEN, 0, 0, 1, 0 }; int i = 0; int test = 0; fail_if(pico_mld_check_hopbyhop(hbh) != -1); _hbh.type = 1; _hbh.len = 0; fail_if(pico_mld_check_hopbyhop(&_hbh) != -1); _hbh.type = PICO_PROTO_ICMP6; _hbh.len = 1; fail_if(pico_mld_check_hopbyhop(&_hbh) != -1); hbh = (struct pico_ipv6_hbhoption *) PICO_ZALLOC(sizeof(struct pico_ipv6_hbhoption) + 7); hbh->type = PICO_PROTO_ICMP6; hbh->len = 0; for(test = 0; test < 7; test++) { p = (uint8_t *)hbh + sizeof(struct pico_ipv6_hbhoption); for(i = 0; i < 6; i++ ) { if(i != test) *(p++) = options[i + 2]; else *(p++) = 9; } if(test != 6) fail_if(pico_mld_check_hopbyhop(hbh) != -1); else fail_if(pico_mld_check_hopbyhop(hbh) != 0); } } END_TEST START_TEST(tc_pico_mld_v1querier_expired) { struct mld_timer *t = PICO_ZALLOC(sizeof(struct mld_timer)); struct pico_ip6 addr = {{0}}; struct pico_device *dev = pico_null_create("dummy2"); struct pico_frame *f = pico_frame_alloc(sizeof(struct pico_frame)); t->f = f; pico_string_to_ipv6("AAAA::109", addr.addr); /* void function, just check for side effects */ /* No link */ pico_mld_v1querier_expired(t); f->dev = dev; pico_ipv6_link_add(dev, addr, addr); pico_mld_v1querier_expired(t); } END_TEST START_TEST(tc_pico_mld_send_report) { struct pico_frame *f; struct pico_device *dev = pico_null_create("dummy1"); struct pico_ip6 addr; struct pico_ipv6_link *link; struct mcast_parameters p; f = pico_proto_ipv6.alloc(&pico_proto_ipv6, dev, sizeof(struct mldv2_report) + MLD_ROUTER_ALERT_LEN + sizeof(struct mldv2_group_record) + (0 * sizeof(struct pico_ip6))); pico_string_to_ipv6("AAAA::110", addr.addr); p.mcast_link.ip6 = addr; /* No link */ fail_if(pico_mld_send_report(&p, f) != -1); link = pico_ipv6_link_add(dev, addr, addr); p.event = 0; link->mcast_compatibility = PICO_MLDV1; fail_if(pico_mld_send_report(&p, f) != 0); link->mcast_compatibility = 99; fail_if(pico_mld_send_report(&p, f) != -1); } END_TEST START_TEST(tc_pico_mld_report_expired) { struct mld_timer *t = PICO_ZALLOC(sizeof(struct mld_timer)); struct pico_ip6 zero = {0}; t->mcast_link = zero; t->mcast_group = zero; /* void function, just check for side effects */ pico_mld_report_expired(t); } END_TEST START_TEST(tc_pico_mld_delete_parameter) { struct mcast_parameters p; fail_if(pico_mld_delete_parameter(&p) != -1); } END_TEST START_TEST(tc_mldt_type_compare) { struct mld_timer a; struct mld_timer b; a.type = 1; b.type = 2; fail_if(mldt_type_compare(&a, &b) != -1); fail_if(mldt_type_compare(&b, &a) != 1); fail_if(mld_timer_cmp(&b, &a) != 1); } END_TEST START_TEST(tc_pico_mld_is_checksum_valid) { struct pico_frame *f; f = pico_proto_ipv6.alloc(&pico_proto_ipv6, NULL, sizeof(struct mldv2_report) + MLD_ROUTER_ALERT_LEN + sizeof(struct mldv2_group_record) + (0 * sizeof(struct pico_ip6))); fail_if(pico_mld_is_checksum_valid(f) == 1); } END_TEST START_TEST(tc_pico_mld_find_parameter) { struct pico_ip6 mcast_link, mcast_group; struct mcast_parameters test = { 0 }; fail_if(pico_mld_find_parameter(NULL, NULL) != NULL); pico_string_to_ipv6("AAAA::111", mcast_link.addr); fail_if(pico_mld_find_parameter(&mcast_link, NULL) != NULL); pico_string_to_ipv6("AAAA::211", mcast_group.addr); fail_if(pico_mld_find_parameter(&mcast_link, &mcast_group) != NULL); test.mcast_link.ip6 = mcast_link; test.mcast_group.ip6 = mcast_group; pico_tree_insert(&MLDParameters, &test); fail_if(pico_mld_find_parameter(&mcast_link, &mcast_group) == NULL); pico_tree_delete(&MLDParameters, &test); } END_TEST START_TEST(tc_pico_mld_timer_expired) { struct mld_timer *t, *s; t = PICO_ZALLOC(sizeof(struct mld_timer)); t->stopped = MLD_TIMER_STOPPED; t->type = 0; pico_string_to_ipv6("AAAA::112", t->mcast_link.addr); pico_string_to_ipv6("AAAA::112", t->mcast_group.addr); /* void function, just check for side effects */ pico_mld_timer_expired(0, (void *)t); pico_tree_insert(&MLDTimers, t); s = PICO_ZALLOC(sizeof(struct mld_timer)); memcpy(s, t, sizeof(struct mld_timer)); /* t will be freed next test */ pico_mld_timer_expired(0, (void *)t); /* will be freed */ s->stopped++; s->start = PICO_TIME_MS() * 2; s->type++; pico_tree_insert(&MLDTimers, s); t = PICO_ZALLOC(sizeof(struct mld_timer)); memcpy(t, s, sizeof(struct mld_timer)); /* s will be freed next test */ pico_mld_timer_expired(0, (void *)s); /* s will be freed */ t->mld_callback = mock_callback; pico_mld_timer_expired(0, (void *)t); /* t will be freed */ } END_TEST START_TEST(tc_pico_mld_send_done) { struct mcast_parameters p; fail_if(pico_mld_send_done(&p, NULL) != 0); } END_TEST START_TEST(tc_mld_stsdifs) { struct mcast_parameters *p; struct pico_device *dev = pico_null_create("dummy3"); struct pico_ipv6_link *link; struct mld_timer *t = PICO_ZALLOC(sizeof(struct mld_timer)); /* Building example frame */ p = PICO_ZALLOC(sizeof(struct mcast_parameters)); pico_string_to_ipv6("AAAA::113", p->mcast_link.ip6.addr); pico_string_to_ipv6("FF00::e007:707", p->mcast_group.ip6.addr); /* no link */ fail_if(mld_stsdifs(p) != -1); link = pico_ipv6_link_add(dev, p->mcast_link.ip6, p->mcast_link.ip6); link->mcast_compatibility = PICO_MLDV1; /* no timer */ fail_if(mld_stsdifs(p) != -1); t->type = MLD_TIMER_GROUP_REPORT; t->mcast_link = p->mcast_link.ip6; t->mcast_group = p->mcast_group.ip6; pico_tree_insert(&MLDTimers, t); fail_if(mld_stsdifs(p) != 0); /* set flag */ pico_mld_flag = 1; fail_if(mld_stsdifs(p) != 0); } END_TEST START_TEST(tc_mld_srsf) { struct mcast_parameters *p; /* Building example frame */ p = PICO_ZALLOC(sizeof(struct mcast_parameters)); pico_string_to_ipv6("AAAA::114", p->mcast_link.ip6.addr); pico_string_to_ipv6("FF00::e007:707", p->mcast_group.ip6.addr); fail_if(mld_srsf(p) != -1); } END_TEST START_TEST(tc_mld_srst) { struct mcast_parameters *p; struct pico_device *dev = pico_null_create("dummy3"); struct pico_ipv6_link *link; struct pico_mcast_group g; /* Building example frame */ p = PICO_ZALLOC(sizeof(struct mcast_parameters)); pico_string_to_ipv6("AAAA::99", p->mcast_link.ip6.addr); pico_string_to_ipv6("FF00::e007:707", p->mcast_group.ip6.addr); p->MCASTFilter = &_MCASTFilter; p->filter_mode = 0; g.filter_mode = 0; g.mcast_addr = p->mcast_group; g.MCASTSources.root = &LEAF; g.MCASTSources.compare = mcast_sources_cmp_ipv6; pico_tree_insert(&MLDParameters, p); /* no link */ fail_if(mld_srst(p) != -1); link = pico_ipv6_link_add(dev, p->mcast_link.ip6, p->mcast_link.ip6); link->mcast_compatibility = PICO_MLDV1; /* invalid proto */ fail_if(mld_srst(p) != -1); link->mcast_compatibility = PICO_MLDV2; pico_tree_insert(link->MCASTGroups, &g); fail_if(mld_srst(p) != 0); pico_tree_delete(&MLDParameters, p); } END_TEST START_TEST(tc_mld_mrsrrt) { struct mcast_parameters *p; struct pico_device *dev = pico_null_create("dummy3"); struct pico_ipv6_link *link; /* Building example frame */ p = PICO_ZALLOC(sizeof(struct mcast_parameters)); pico_string_to_ipv6("AAAA::115", p->mcast_link.ip6.addr); pico_string_to_ipv6("FF00::e007:707", p->mcast_group.ip6.addr); /* no link */ fail_if(mld_mrsrrt(p) != -1); link = pico_ipv6_link_add(dev, p->mcast_link.ip6, p->mcast_link.ip6); link->mcast_compatibility = PICO_MLDV1; /* wrong proto */ fail_if(mld_mrsrrt(p) != -1); link->mcast_compatibility = PICO_MLDV2; p->f = pico_proto_ipv6.alloc(&pico_proto_ipv6, dev, sizeof(struct mldv2_report) + MLD_ROUTER_ALERT_LEN + sizeof(struct mldv2_group_record) + (0 * sizeof(struct pico_ip6))); fail_if(mld_mrsrrt(p) != -1); } END_TEST START_TEST(tc_pico_mld_process_in) { struct mcast_parameters *p; struct pico_device *dev = pico_null_create("dummy3"); struct pico_ipv6_link *link; uint8_t i, j, _i, _j; int result = 0; struct pico_mcast_group g; struct mldv2_report *report; /* Building example frame */ p = PICO_ZALLOC(sizeof(struct mcast_parameters)); pico_string_to_ipv6("AAAA::101", p->mcast_link.ip6.addr); pico_string_to_ipv6("FF00::e007:707", p->mcast_group.ip6.addr); /* no link */ fail_if(pico_mld_generate_report(p) != -1); link = pico_ipv6_link_add(dev, p->mcast_link.ip6, p->mcast_link.ip6); pico_string_to_ipv6("AAAA::100", p->mcast_group.ip6.addr); fail_if(pico_mld_generate_report(p) != -1); pico_string_to_ipv6("FF00::e007:707", p->mcast_group.ip6.addr); link->mcast_compatibility = PICO_MLDV1; g.mcast_addr = p->mcast_group; g.MCASTSources.root = &LEAF; g.MCASTSources.compare = mcast_sources_cmp_ipv6; /* No mcastsources tree */ link->mcast_compatibility = PICO_MLDV2; fail_if(pico_mld_generate_report(p) != -1); pico_tree_insert(link->MCASTGroups, &g); pico_tree_insert(&MLDParameters, p); link->mcast_compatibility = 99; fail_if(pico_mld_generate_report(p) != -1); link->mcast_compatibility = PICO_MLDV1; fail_if(pico_mld_generate_report(p) != 0); link->mcast_compatibility = PICO_MLDV2; for(_j = 0; _j < 3; _j++) { /* FILTER */ (_j == 2) ? (result = -1) : (result = 0); for(_i = 0; _i < 3; _i++) { /* FILTER */ if(_i == 2) result = -1; for(i = 0; i < 3; i++) { /* STATES */ for(j = 0; j < 6; j++) { /* EVENTS */ p->MCASTFilter = &_MCASTFilter; p->filter_mode = _i; g.filter_mode = _j; if(p->event == MLD_EVENT_DELETE_GROUP || p->event == MLD_EVENT_QUERY_RECV) p->event++; fail_if(pico_mld_generate_report(p) != result); p->state = i; p->event = j; if(result != -1 && p->f) { /* in some combinations, no frame is created */ report = (struct mldv2_report *)(p->f->transport_hdr + MLD_ROUTER_ALERT_LEN); report->crc = short_be(pico_icmp6_checksum(p->f)); fail_if(pico_mld_process_in(p->f) != 0); } } } } } pico_tree_delete(&MLDParameters, p); } END_TEST START_TEST(tc_mld_rtimrtct) { struct mld_timer *t = PICO_ZALLOC(sizeof(struct mld_timer)); struct mcast_parameters p; pico_string_to_ipv6("AAAA::102", t->mcast_link.addr); pico_string_to_ipv6("AAAA::102", t->mcast_group.addr); p.mcast_link.ip6 = t->mcast_link; p.mcast_group.ip6 = t->mcast_group; t->type = MLD_TIMER_GROUP_REPORT; /* not in tree */ fail_if(mld_rtimrtct(&p) != -1); pico_mld_timer_start(t); fail_if(mld_rtimrtct(&p) != 0); } END_TEST START_TEST(tc_mld_stcl) { struct mld_timer *t = PICO_ZALLOC(sizeof(struct mld_timer)); struct mcast_parameters p; pico_string_to_ipv6("AAAA::103", t->mcast_link.addr); pico_string_to_ipv6("AAAA::103", t->mcast_group.addr); p.mcast_link.ip6 = t->mcast_link; p.mcast_group.ip6 = t->mcast_group; t->type = MLD_TIMER_GROUP_REPORT; /* not in tree */ fail_if(mld_stcl(&p) != -1); pico_mld_timer_start(t); fail_if(mld_stcl(&p) != 0); } END_TEST START_TEST(tc_pico_mld_compatibility_mode) { struct pico_frame *f; struct pico_device *dev = pico_null_create("dummy1"); struct pico_ip6 addr; f = pico_proto_ipv6.alloc(&pico_proto_ipv6, NULL, sizeof(struct mldv2_report) + MLD_ROUTER_ALERT_LEN + sizeof(struct mldv2_group_record) + (0 * sizeof(struct pico_ip6))); pico_string_to_ipv6("AAAA::104", addr.addr); /* No link */ fail_if(pico_mld_compatibility_mode(f) != -1); pico_ipv6_link_add(dev, addr, addr); f->dev = dev; /* MLDv2 query */ f->buffer_len = 28 + PICO_SIZE_IP6HDR + MLD_ROUTER_ALERT_LEN; fail_if(pico_mld_compatibility_mode(f) != 0); /* MLDv1 query */ f->buffer_len = 24 + PICO_SIZE_IP6HDR + MLD_ROUTER_ALERT_LEN; fail_if(pico_mld_compatibility_mode(f) != 0); /* Invalid Query */ f->buffer_len = 25 + PICO_SIZE_IP6HDR + MLD_ROUTER_ALERT_LEN; fail_if(pico_mld_compatibility_mode(f) == 0); /* MLDv2 query + timer amready running */ f->dev = dev; f->buffer_len = 28 + PICO_SIZE_IP6HDR + MLD_ROUTER_ALERT_LEN + PICO_SIZE_ETHHDR; fail_if(pico_mld_compatibility_mode(f) != -1); } END_TEST START_TEST(tc_pico_mld_timer_reset) { struct mld_timer *t = PICO_ZALLOC(sizeof(struct mld_timer)); pico_string_to_ipv6("AAAA::105", t->mcast_link.addr); pico_string_to_ipv6("AAAA::105", t->mcast_group.addr); t->type = 0; fail_if(pico_mld_timer_reset(t) != -1); } END_TEST START_TEST(tc_pico_mld_state_change) { struct pico_ip6 mcast_link, mcast_group; struct mcast_parameters p; pico_string_to_ipv6("AAAA::106", mcast_link.addr); pico_string_to_ipv6("AAAA::106", mcast_group.addr); p.mcast_link.ip6 = mcast_link; p.mcast_group.ip6 = mcast_group; fail_if(pico_mld_state_change(NULL, &mcast_group, 0, NULL, PICO_MLD_STATE_CREATE) != -1); /* All host group */ pico_string_to_ipv6("FF01:0:0:0:0:0:0:1", mcast_group.addr); fail_if(pico_mld_state_change(&mcast_link, &mcast_group, 0, NULL, PICO_MLD_STATE_CREATE) != 0); pico_string_to_ipv6("AAAA::107", mcast_group.addr); fail_if(pico_mld_state_change(&mcast_link, &mcast_group, 0, NULL, 99) != -1); pico_tree_insert(&MLDParameters, &p); fail_if(pico_mld_state_change(&mcast_link, &mcast_group, 0, NULL, 99) != -1); pico_tree_delete(&MLDParameters, &p); } END_TEST START_TEST(tc_pico_mld_analyse_packet) { struct pico_frame *f; struct pico_device *dev = pico_null_create("dummy0"); struct pico_ip6 addr; struct pico_ip6 local; struct pico_ipv6_hdr *ip6; struct pico_ipv6_hbhoption *hbh; struct pico_icmp6_hdr *mld; f = pico_proto_ipv6.alloc(&pico_proto_ipv6, dev, sizeof(struct mld_message) + MLD_ROUTER_ALERT_LEN); pico_string_to_ipv6("AAAA::108", addr.addr); pico_string_to_ipv6("FE80::1", local.addr); /* No link */ fail_if(pico_mld_analyse_packet(f) != NULL); pico_ipv6_link_add(dev, addr, addr); ip6 = (struct pico_ipv6_hdr *) f->net_hdr; ip6->hop = 99; /* Incorrect hop */ fail_if(pico_mld_analyse_packet(f) != NULL); ip6->hop = 1; hbh = (struct pico_ipv6_hbhoption *) f->transport_hdr; pico_mld_fill_hopbyhop(hbh); hbh->type = 99; /* incorrect hop by hop */ fail_if(pico_mld_analyse_packet(f) != NULL); pico_mld_fill_hopbyhop(hbh); ip6->src = addr; /* Not link local */ fail_if(pico_mld_analyse_packet(f) != NULL); memcpy(&ip6->src, PICO_IP6_ANY, sizeof(struct pico_ip6)); fail_if(pico_mld_analyse_packet(f) != NULL); ip6->src = local; mld = (struct pico_icmp6_hdr *) (f->transport_hdr + MLD_ROUTER_ALERT_LEN); mld->type = 0; /* wrong type */ fail_if(pico_mld_analyse_packet(f) != NULL); /* all correct */ mld->type = PICO_MLD_QUERY; fail_if(pico_mld_analyse_packet(f) == NULL); mld->type = PICO_MLD_REPORT; fail_if(pico_mld_analyse_packet(f) == NULL); mld->type = PICO_MLD_DONE; fail_if(pico_mld_analyse_packet(f) == NULL); mld->type = PICO_MLD_REPORTV2; fail_if(pico_mld_analyse_packet(f) == NULL); } END_TEST START_TEST(tc_pico_mld_discard) { mld_discard(NULL); } END_TEST Suite *pico_suite(void) { Suite *s = suite_create("PicoTCP"); TCase *TCase_pico_mld_fill_hopbyhop = tcase_create("Unit test for pico_mld_fill_hopbyhop"); TCase *TCase_pico_mld_check_hopbyhop = tcase_create("Unit test for pico_mld_check_hopbyhop"); TCase *TCase_pico_mld_report_expired = tcase_create("Unit test for pico_mld_report_expired"); TCase *TCase_mldt_type_compare = tcase_create("Unit test for mldt_type_compare"); TCase *TCase_pico_mld_analyse_packet = tcase_create("Unit test for pico_mld_analyse_packet"); TCase *TCase_pico_mld_discard = tcase_create("Unit test for pico_mld_discard"); TCase *TCase_pico_mld_compatibility_mode = tcase_create("Unit test for pico_mld_compatibility"); TCase *TCase_pico_mld_v1querier_expired = tcase_create("Unit test for pico_mld_v1querier_expired"); TCase *TCase_pico_mld_delete_parameter = tcase_create("Unit test for pico_mld_delete_parameter"); TCase *TCase_pico_mld_timer_expired = tcase_create("Unit test for pico_mld_timer_expired"); TCase *TCase_pico_mld_timer_reset = tcase_create("Unit test for pico_mld_timer_reset"); TCase *TCase_pico_mld_send_done = tcase_create("Unit test for pico_mld_send_done"); TCase *TCase_pico_mld_is_checksum_valid = tcase_create("Unit test for pico_mld_is_checksum"); TCase *TCase_pico_mld_find_parameter = tcase_create("Unit test for pico_mld_find_parameter"); TCase *TCase_pico_mld_state_change = tcase_create("Unit test for pico_mld_state_change"); TCase *TCase_mld_srst = tcase_create("Unit test for pico_mld_srst"); TCase *TCase_mld_stcl = tcase_create("Unit test for pico_mld_stcl"); TCase *TCase_pico_mld_process_in = tcase_create("Unit test for pico_mld_process_in"); TCase *TCase_pico_mld_send_report = tcase_create("Unit test for pico_mld_send_report"); TCase *TCase_mld_stsdifs = tcase_create("Unit test for mld_stsdifs"); TCase *TCase_mld_srsf = tcase_create("Unit test for mld_srsf"); TCase *TCase_mld_rtimrtct = tcase_create("Unit test for mld_rtimrtct"); TCase *TCase_mld_mrsrrt = tcase_create("Unit test for mld_mrsrrt"); tcase_add_test(TCase_pico_mld_fill_hopbyhop, tc_pico_mld_fill_hopbyhop); suite_add_tcase(s, TCase_pico_mld_fill_hopbyhop); tcase_add_test(TCase_pico_mld_check_hopbyhop, tc_pico_mld_check_hopbyhop); suite_add_tcase(s, TCase_pico_mld_check_hopbyhop); tcase_add_test(TCase_pico_mld_report_expired, tc_pico_mld_report_expired); suite_add_tcase(s, TCase_pico_mld_report_expired); tcase_add_test(TCase_mldt_type_compare, tc_mldt_type_compare); suite_add_tcase(s, TCase_mldt_type_compare); tcase_add_test(TCase_pico_mld_analyse_packet, tc_pico_mld_analyse_packet); suite_add_tcase(s, TCase_pico_mld_analyse_packet); tcase_add_test(TCase_pico_mld_discard, tc_pico_mld_discard); suite_add_tcase(s, TCase_pico_mld_discard); tcase_add_test(TCase_pico_mld_compatibility_mode, tc_pico_mld_compatibility_mode); suite_add_tcase(s, TCase_pico_mld_compatibility_mode); tcase_add_test(TCase_pico_mld_v1querier_expired, tc_pico_mld_v1querier_expired); suite_add_tcase(s, TCase_pico_mld_v1querier_expired); tcase_add_test(TCase_pico_mld_delete_parameter, tc_pico_mld_delete_parameter); suite_add_tcase(s, TCase_pico_mld_delete_parameter); tcase_add_test(TCase_pico_mld_timer_expired, tc_pico_mld_timer_expired); suite_add_tcase(s, TCase_pico_mld_timer_expired); tcase_add_test(TCase_pico_mld_timer_reset, tc_pico_mld_timer_reset); suite_add_tcase(s, TCase_pico_mld_timer_reset); tcase_add_test(TCase_pico_mld_send_done, tc_pico_mld_send_done); suite_add_tcase(s, TCase_pico_mld_send_done); tcase_add_test(TCase_pico_mld_is_checksum_valid, tc_pico_mld_is_checksum_valid); suite_add_tcase(s, TCase_pico_mld_is_checksum_valid); tcase_add_test(TCase_pico_mld_find_parameter, tc_pico_mld_find_parameter); suite_add_tcase(s, TCase_pico_mld_find_parameter); tcase_add_test(TCase_pico_mld_state_change, tc_pico_mld_state_change); suite_add_tcase(s, TCase_pico_mld_state_change); tcase_add_test(TCase_mld_srst, tc_mld_srst); suite_add_tcase(s, TCase_mld_srst); tcase_add_test(TCase_mld_stcl, tc_mld_stcl); suite_add_tcase(s, TCase_mld_stcl); tcase_add_test(TCase_pico_mld_process_in, tc_pico_mld_process_in); suite_add_tcase(s, TCase_pico_mld_process_in); tcase_add_test(TCase_pico_mld_send_report, tc_pico_mld_send_report); suite_add_tcase(s, TCase_pico_mld_send_report); tcase_add_test(TCase_mld_stsdifs, tc_mld_stsdifs); suite_add_tcase(s, TCase_mld_stsdifs); tcase_add_test(TCase_mld_srsf, tc_mld_srsf); suite_add_tcase(s, TCase_mld_srsf); tcase_add_test(TCase_mld_rtimrtct, tc_mld_rtimrtct); suite_add_tcase(s, TCase_mld_rtimrtct); tcase_add_test(TCase_mld_mrsrrt, tc_mld_mrsrrt); suite_add_tcase(s, TCase_mld_mrsrrt); return s; } int main(void) { int fails; Suite *s = pico_suite(); SRunner *sr = srunner_create(s); srunner_run_all(sr, CK_NORMAL); fails = srunner_ntests_failed(sr); srunner_free(sr); return fails; }