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_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_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_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 iface_test_new_unmanaged(void) { iface_register_user(&user_mock); struct iface *iface = iface_create("test0", NULL, 0); sput_fail_unless(!!iface, "alloc unmanaged"); struct iface *iface2 = iface_get("test0"); sput_fail_unless(iface == iface2, "get after create"); struct iface *iface3 = iface_create("test0", NULL, 0); sput_fail_unless(iface == iface3, "create after create"); iface_remove(iface); sput_fail_unless(!iface_get("test0"), "delete"); smock_is_empty(); iface_unregister_user(&user_mock); }
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 destroy_hncp(hncp o) { smock_push("uninit", NULL); hncp_destroy(o); smock_is_empty(); }
void iface_test_new_managed(void) { struct in_addr v4source = {INADDR_LOOPBACK}; iface_register_user(&user_mock); struct prefix p = {IN6ADDR_LOOPBACK_INIT, 0}; char test[] = "test"; struct iface *iface00 = iface_create("test00", "test00", 0); iface_update_ipv4_uplink(iface00); iface_set_ipv4_uplink(iface00, &v4source, 24); iface_commit_ipv4_uplink(iface00); /* smock_pull_bool_is("test00", false); */ /* this was removed in the commit a5293745c235a057b6a477ffbd817937eaa9bc12 at 5/2015(!); */ struct iface *iface = iface_create("test0", "test0", 0); iface->carrier = true; iface_discover_border(iface); sput_fail_unless(!!iface, "alloc managed"); struct iface *iface2 = iface_get("test0"); sput_fail_unless(iface == iface2, "get after create"); struct iface *iface3 = iface_create("test0", "test0", 0); sput_fail_unless(iface == iface3, "create after create"); /* smock_pull_bool_is("test0", false); */ /* this was removed in the commit a5293745c235a057b6a477ffbd817937eaa9bc12 at 5/2015(!); */ uloop_cancelled = false; uloop_run(); smock_pull_bool_is("test0", true); iface_update_ipv4_uplink(iface); iface_set_ipv4_uplink(iface, &v4source, 24); iface_commit_ipv4_uplink(iface); smock_pull_bool_is("test0", false); iface_update_ipv4_uplink(iface); iface_commit_ipv4_uplink(iface); uloop_cancelled = false; uloop_run(); smock_pull_bool_is("test0", true); iface_update_ipv6_uplink(iface); iface_add_delegated(iface, &p, NULL, HNETD_TIME_MAX, 0, test, sizeof(test)); iface_commit_ipv6_uplink(iface); smock_pull_bool_is("test0", false); sput_fail_unless(!prefix_cmp(&p, (struct prefix *)smock_pull("prefix_prefix")), "prefix address"); smock_pull_int64_is("prefix_valid", HNETD_TIME_MAX); smock_pull_int64_is("prefix_preferred", 0); sput_fail_unless(!strcmp(smock_pull("dhcpv6_data"), "test"), "dhcpv6_data"); smock_pull_int_is("dhcpv6_len", sizeof(test)); iface_update_ipv4_uplink(iface); iface_set_ipv4_uplink(iface, &v4source, 24); iface_commit_ipv4_uplink(iface); iface_update_ipv6_uplink(iface); iface_commit_ipv6_uplink(iface); smock_pull_bool_is("prefix_remove", true); iface_update_ipv4_uplink(iface); iface_commit_ipv4_uplink(iface); uloop_cancelled = false; uloop_run(); smock_pull_bool_is("test0", true); iface_remove(iface); sput_fail_unless(!iface_get("test0"), "delete"); smock_pull_bool_is("test0", false); smock_is_empty(); iface_unregister_user(&user_mock); }