void sample(void) { int r; L_DEBUG("debug"); L_INFO("info"); L_NOTICE("notice"); L_WARN("warn"); L_ERR("err"); sput_fail_if(0, "0 isn't false!"); sput_fail_unless(1, "1 isn't true!"); /* Play with smock */ sput_fail_unless(smock_empty(), "smock empty"); smock_push_int("in", 1); sput_fail_unless(!smock_empty(), "smock not empty"); smock_push_int("out", 2); smock_push_int("in", 3); smock_push_int("out", 6); r = dummy_callback(1); sput_fail_unless(r == 2, "dummy_callback broken"); r = dummy_callback(3); sput_fail_unless(r == 6, "dummy_callback broken"); /* In the end, we should be again gone. */ sput_fail_unless(smock_empty(), "smock empty"); }
static hncp create_hncp(void) { char buf[4] = "foo"; /* Feed in fake hwaddr for eth0+eth1 (hardcoded, ugh) */ smock_push("get_hwaddrs_buf", buf); smock_push_int("get_hwaddrs_len", sizeof(buf)); /* io init succeeds */ smock_push_bool("init_result", true); /* schedule happens _once_ */ smock_push("schedule", NULL); hncp o = hncp_create(); sput_fail_unless(o, "hncp_create -> hncp"); smock_is_empty(); /* clear the scheduled timeout - for now, we're empty slate anyway*/ smock_push_int("time", 0); /* second one occurs from originating us (no caching due to 0 return value) */ smock_push_int("time", 0); hncp_run(o); smock_is_empty(); return o; }
static void hncp_init_no_hwaddr(void) { /* Feed in fake hwaddr for eth0+eth1 (hardcoded, ugh) */ smock_push("get_hwaddrs_buf", NULL); smock_push_int("get_hwaddrs_len", 0); hncp o = hncp_create(); sput_fail_unless(!o, "hncp_create -> !hncp"); smock_is_empty(); }
static void hncp_rejoin_works(void) { hncp o = create_hncp(); int t = 123000; /* we'll try to join dummy_ifname; however, it fails. */ smock_is_empty(); one_join(false); smock_push_int("schedule", 0); smock_push_int("time", t); hncp_if_set_enabled(o, dummy_ifname, true); smock_is_empty(); /* make sure next timeout before HNCP_REJOIN_INTERVAL just re-schedules. */ t += HNCP_REJOIN_INTERVAL / 2; smock_push_int("time", t); smock_push_int("schedule", HNCP_REJOIN_INTERVAL / 2); hncp_run(o); smock_is_empty(); /* now that the time _has_ expired, we should try joining.. fail again. */ t += HNCP_REJOIN_INTERVAL / 2; smock_push_int("time", t); smock_push_int("schedule", HNCP_REJOIN_INTERVAL); one_join(false); hncp_run(o); smock_is_empty(); /* again try after HNCP_REJOIN_INTERVAL, it should work. trickle * scheduling should require exactly one random call. */ t += HNCP_REJOIN_INTERVAL; smock_push_int("time", t); smock_push_int("random", 0); smock_push_int("schedule", HNCP_TRICKLE_IMIN / 2); one_join(true); hncp_run(o); smock_is_empty(); /* no unregisters at end, as we first kill io, and then flush * structures (socket kill should take care of it in any case). */ destroy_hncp(o); }
static void hncp_init_iofail(void) { char buf[4] = "foo"; /* Feed in fake hwaddr for eth0+eth1 (hardcoded, ugh) */ smock_push("get_hwaddrs_buf", buf); smock_push_int("get_hwaddrs_len", sizeof(buf)); /* io init succeeds */ smock_push_bool("init_result", false); hncp o = hncp_create(); sput_fail_unless(!o, "hncp_create -> !hncp"); smock_is_empty(); }
void prefix_mock(__unused struct iface_user *u, __unused const char *ifname, __unused const struct prefix *prefix, __unused const struct prefix *excluded, hnetd_time_t valid_until, __unused hnetd_time_t preferred_until, __unused const void *dhcpv6_data, __unused size_t dhcpv6_len) { if (valid_until > hnetd_time()) { smock_push("prefix_prefix", (void*)prefix); smock_push_int64("prefix_valid", valid_until); smock_push_int64("prefix_preferred", preferred_until); smock_push("dhcpv6_data", (void*)dhcpv6_data); smock_push_int("dhcpv6_len", dhcpv6_len); } else { smock_push_bool("prefix_remove", true); } }
static void hncp_ok(void) { hncp o = create_hncp(); int t = 123000; int i; /* Pushing in a new subscriber should result in us being called. */ smock_is_empty(); smock_push_bool("node_callback", true); hncp_subscribe(o, &dummy_subscriber_1); hncp_subscribe(o, &dummy_subscriber_2); hncp_subscribe(o, &dummy_subscriber_3); hncp_subscribe(o, &dummy_subscriber_4); smock_is_empty(); one_join(true); smock_push_int("schedule", 0); hncp_if_set_enabled(o, dummy_ifname, true); smock_is_empty(); /* Ok. We're cooking with gas. */ smock_push_int("time", t); smock_push_int("random", 0); smock_push_int("schedule", HNCP_TRICKLE_IMIN / 2); hncp_run(o); smock_is_empty(); t += HNCP_TRICKLE_IMIN / 2 - 1; smock_push_int("time", t); smock_push_int("schedule", 1); hncp_run(o); smock_is_empty(); t += 1; /* Ok. we get timestamp -> woah, need to do something. */ smock_push_int("time", t); /* Should send stuff on an interface. */ smock_push("sendto_ifname", dummy_ifname); smock_push("sendto_dst", &o->multicast_address); smock_push_int("sendto_return", 1); /* And schedule next one (=end of interval). */ smock_push_int("schedule", HNCP_TRICKLE_IMIN / 2); hncp_run(o); smock_is_empty(); /* overshoot what we were asked for.. shouldn't be a problem. */ t += HNCP_TRICKLE_IMIN; smock_push_int("time", t); /* should be queueing next send, and now we go for 'max' value. */ smock_push_int("random", 999); smock_push_int("schedule", 2 * HNCP_TRICKLE_IMIN * (1000 + 999) / 2000); hncp_run(o); smock_is_empty(); /* run the clock until we hit HNCP_TRICKLE_IMAX/2 delay; or we run * out of iterations. */ check_timing = false; check_send = false; check_random = false; want_send = 0; for (i = 0 ; i < 100 ; i++) { current_hnetd_time = t; want_schedule = 0; hncp_run(o); if (want_schedule >= (HNCP_TRICKLE_IMAX / 2)) { sput_fail_unless(want_schedule <= HNCP_TRICKLE_IMAX, "reasonable timeout"); break; } t += want_schedule; current_hnetd_time += want_schedule; } sput_fail_unless(want_send <= i / 2, "few sends"); sput_fail_unless(i < 100, "did not encounter big enough delta"); /* then, run for few more iterations, making sure we don't hit too long ones. */ want_send = 0; for (i = 0 ; i < 10 ; i++) { current_hnetd_time = t; want_schedule = 0; hncp_run(o); sput_fail_unless(want_schedule <= HNCP_TRICKLE_IMAX, "reasonable timeout"); t += want_schedule; current_hnetd_time += want_schedule; } sput_fail_unless(want_send > 0 && want_send <= i / 2, "few sends"); check_timing = true; check_send = true; check_random = true; /* Ok, Trickle was in a stable state 'long' time. Make sure the * state resets once we push something new in. */ struct tlv_attr ta; L_NOTICE("add tlv a"); #define TLV_ID_A 123 #define TLV_ID_B 125 #define TLV_ID_C 127 #define TLV_ID_D 124 tlv_init(&ta, TLV_ID_A, 4); smock_push_int("schedule", 0); smock_push_int("local_tlv_callback", TLV_ID_A); hncp_add_tlv(o, &ta); smock_is_empty(); L_NOTICE("add tlv b"); tlv_init(&ta, TLV_ID_B, 4); /* should NOT cause extra schedule! */ smock_push_int("local_tlv_callback", TLV_ID_B); hncp_add_tlv(o, &ta); smock_is_empty(); L_NOTICE("running."); printf("last run starting\n"); smock_push_int("time", t); smock_push_int("random", 0); smock_push_int("schedule", 0); /* Should get notification about two added TLVs. */ smock_push_int("tlv_callback", TLV_ID_A); smock_push_int("tlv_callback", TLV_ID_B); smock_push_bool("republish_callback", true); hncp_run(o); smock_is_empty(); /* Adding / removing last entry have special handling. So let's * test both by adding and removing tlv c (which > a, b). */ /* Our interest in timing has waned by now though, so we disable * those checks. */ check_timing = false; check_random = false; /* So, let's add one more TLV. Make sure we get notification about it. */ L_NOTICE("add tlv c"); tlv_init(&ta, TLV_ID_C, 4); smock_push_int("local_tlv_callback", TLV_ID_C); hncp_add_tlv(o, &ta); smock_is_empty(); smock_push_int("tlv_callback", TLV_ID_C); smock_push_bool("republish_callback", true); hncp_run(o); smock_is_empty(); /* Remove it. */ L_NOTICE("remove tlv c"); smock_push_int("local_tlv_callback", -TLV_ID_C); hncp_remove_tlv(o, &ta); smock_is_empty(); smock_push_int("tlv_callback", -TLV_ID_C); smock_push_bool("republish_callback", true); hncp_run(o); smock_is_empty(); /* Add TLV D in the middle. */ L_NOTICE("add tlv d"); tlv_init(&ta, TLV_ID_D, 4); smock_push_int("local_tlv_callback", TLV_ID_D); hncp_add_tlv(o, &ta); smock_is_empty(); smock_push_int("tlv_callback", TLV_ID_D); smock_push_bool("republish_callback", true); hncp_run(o); smock_is_empty(); /* Unsubscribing should result in callbacks too. */ L_NOTICE("unsubscribe"); smock_push_int("local_tlv_callback", -TLV_ID_A); smock_push_int("local_tlv_callback", -TLV_ID_D); smock_push_int("local_tlv_callback", -TLV_ID_B); smock_push_int("tlv_callback", -TLV_ID_A); smock_push_int("tlv_callback", -TLV_ID_D); smock_push_int("tlv_callback", -TLV_ID_B); smock_push_bool("node_callback", false); hncp_unsubscribe(o, &dummy_subscriber_1); hncp_unsubscribe(o, &dummy_subscriber_2); hncp_unsubscribe(o, &dummy_subscriber_3); hncp_unsubscribe(o, &dummy_subscriber_4); smock_is_empty(); /* Re-enable checks */ check_timing = true; check_random = true; /* no unregisters at end, as we first kill io, and then flush * structures (socket kill should take care of it in any case). */ destroy_hncp(o); }
static void dncp_io_basic_2() { hncp_s h1, h2; dncp_s d1, d2; bool r; struct in6_addr a; char *msg = "foo"; char *ifname = LOOPBACK_NAME; (void)uloop_init(); memset(&h1, 0, sizeof(h1)); memset(&h2, 0, sizeof(h2)); memset(&d1, 0, sizeof(d1)); memset(&d2, 0, sizeof(d2)); h1.udp_port = 62000; h2.udp_port = 62001; h1.dncp = &d1; h2.dncp = &d2; d1.ext = &h1.ext; d2.ext = &h2.ext; r = hncp_io_init(&h1); sput_fail_unless(r, "dncp_io_init h1"); r = hncp_io_init(&h2); sput_fail_unless(r, "dncp_io_init h2"); /* Send a packet to ourselves */ (void)inet_pton(AF_INET6, "::1", &a); struct sockaddr_in6 src = { .sin6_family = AF_INET6, .sin6_port = htons(h1.udp_port), .sin6_addr = a #ifdef __APPLE__ , .sin6_len = sizeof(struct sockaddr_in6) #endif /* __APPLE__ */ }; struct sockaddr_in6 dst = { .sin6_family = AF_INET6, .sin6_port = htons(h2.udp_port), .sin6_addr = a #ifdef __APPLE__ , .sin6_len = sizeof(struct sockaddr_in6) #endif /* __APPLE__ */ }; smock_push_int("dncp_poll_io_recvfrom", 3); smock_push_int("dncp_poll_io_recvfrom_src", &src); smock_push_int("dncp_poll_io_recvfrom_dst", &dst); smock_push_int("dncp_poll_io_recvfrom_buf", msg); smock_push_int("dncp_poll_io_recvfrom_ifname", ifname); h1.ext.cb.send(&h1.ext, dncp_find_ep_by_name(h1.dncp, "lo"), NULL, &dst, msg, strlen(msg)); pending_packets++; uloop_run(); hncp_io_uninit(&h1); hncp_io_uninit(&h2); } int main(int argc, char **argv) { setbuf(stdout, NULL); /* so that it's in sync with stderr when redirected */ openlog("test_hncp_io", LOG_CONS | LOG_PERROR, LOG_DAEMON); sput_start_testing(); sput_enter_suite("hncp_io"); /* optional */ argc -= 1; argv += 1; sput_maybe_run_test(dncp_io_basic_2, do {} while(0)); sput_leave_suite(); /* optional */ sput_finish_testing(); return sput_get_return_value(); }
void extdata_mock(__unused struct iface_user *u, __unused const char *ifname, __unused const void *dhcpv6_data, size_t dhcpv6_len) { if (dhcpv6_len) smock_push_int("extdata", dhcpv6_len); }