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_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 one_join(bool ok) { smock_push("set_enable_ifname", dummy_ifname); smock_push_bool("set_enable_enabled", true); smock_push_bool("set_enable_result", ok); }
void intiface_mock(__unused struct iface_user *u, __unused const char *ifname, bool enabled) { smock_push_bool(ifname, enabled); uloop_end(); }