static const bool iteration0_base[] = { 1, 0, 1, 0, };
static const bool iteration1_base[] = { 1, 1, 1, 1, };
static const bool iteration2_base[] = { 0, 1, 0, 1, };
+static const bool iteration3_base[] = { 1, 0, 1, 0, };
/*
* DELTA
static const bool deltas_1to2[] = { 1, 0, 1, 0, 0, 0, 0, 0, };
static const bool deltas_2to2[] = { 0, 0, 0, 0, 0, 0, 0, 0, };
+/* Deltas with rules that override each other */
+static const bool deltas_0to3_ovrd[] = { 1, 1, 1, 1, 1, 1, 1, 1, };
+static const bool deltas_1to3_ovrd[] = { 1, 1, 1, 1, 1, 0, 1, 0, };
+static const bool deltas_2to3_ovrd[] = { 0, 1, 0, 1, 1, 0, 1, 0, };
+static const bool deltas_3to3_ovrd[] = { 0, 0, 0, 0, 0, 0, 0, 0, };
+
+/* Deltas cleaned up */
+static const bool deltas_0to3_clean[] = { 0, 0, 0, 0, 0, 0, 0, 0, };
+static const bool deltas_1to3_clean[] = { 0, 1, 0, 1, 0, 0, 0, 0, };
+static const bool deltas_2to3_clean[] = { 0, 1, 0, 1, 1, 0, 1, 0, };
+static const bool deltas_3to3_clean[] = { 0, 0, 0, 0, 0, 0, 0, 0, };
+
/* Impersonator functions */
+serial_t current_min_serial = 0;
+
serial_t
-clients_get_min_serial(void)
+clients_get_min_serial(serial_t *result)
{
+ *result = current_min_serial;
return 0;
}
ck_abort_msg("Expected no callbacks, got VRP %u/%s/%u/%u.",
vrp->asn, addr, vrp->prefix_length, vrp->max_prefix_length);
+ return -EINVAL;
}
static array_index
array[index] = true;
return 0;
-
}
static void
ck_assert_uint_eq(expected_base[i], actual_base[i]);
}
+static int
+vrp_add(struct delta const *delta, void *arg)
+{
+ struct deltas *deltas = arg;
+ struct vrp const *vrp;
+ struct v4_address v4;
+ struct v6_address v6;
+
+ vrp = &delta->vrp;
+ switch (vrp->addr_fam) {
+ case AF_INET:
+ v4.prefix.len = vrp->prefix_length;
+ v4.prefix.addr = vrp->prefix.v4;
+ v4.max_length = vrp->max_prefix_length;
+ deltas_add_roa_v4(deltas, vrp->asn, &v4, delta->flags);
+ break;
+ case AF_INET6:
+ v6.prefix.len = vrp->prefix_length;
+ v6.prefix.addr = vrp->prefix.v6;
+ v6.max_length = vrp->max_prefix_length;
+ deltas_add_roa_v6(deltas, vrp->asn, &v6, delta->flags);
+ break;
+ default:
+ ck_abort_msg("Unknown addr family");
+ }
+ return 0;
+}
+
+static void
+filter_deltas(struct deltas_db *db)
+{
+ struct deltas_db tmp;
+ struct delta_group group;
+ struct deltas *deltas;
+
+ group.serial = 0;
+ ck_assert_int_eq(0, deltas_create(&deltas));
+ group.deltas = deltas;
+ ck_assert_int_eq(0, vrps_foreach_filtered_delta(db, vrp_add,
+ group.deltas));
+ deltas_db_init(&tmp);
+ ck_assert_int_eq(0, deltas_db_add(&tmp, &group));
+
+ *db = tmp;
+}
+
static void
-check_deltas(serial_t from, serial_t to, bool const *expected_deltas)
+check_deltas(serial_t from, serial_t to, bool const *expected_deltas,
+ bool filter)
{
serial_t actual_serial;
bool actual_deltas[8];
&deltas));
ck_assert_uint_eq(to, actual_serial);
+ if (filter)
+ filter_deltas(&deltas);
+
memset(actual_deltas, 0, sizeof(actual_deltas));
ARRAYLIST_FOREACH(&deltas, group, i)
ck_assert_int_eq(0, deltas_foreach(group->serial, group->deltas,
ck_assert_uint_eq(expected_deltas[i], actual_deltas[i]);
}
-START_TEST(test_basic)
+static void
+check_no_deltas(serial_t from, serial_t to)
{
+ serial_t actual_serial;
struct deltas_db deltas;
- serial_t serial;
- bool changed;
- bool iterated_entries[8];
deltas_db_init(&deltas);
+ ck_assert_int_eq(-ESRCH, vrps_get_deltas_from(from, &actual_serial,
+ &deltas));
+}
+
+static void
+create_deltas_0to1(struct deltas_db *deltas, serial_t *serial, bool *changed,
+ bool *iterated_entries)
+{
+ current_min_serial = 0;
+
+ deltas_db_init(deltas);
ck_assert_int_eq(0, vrps_init());
/* First validation not yet performed: Tell routers to wait */
- ck_assert_int_eq(-EAGAIN, get_last_serial_number(&serial));
+ ck_assert_int_eq(-EAGAIN, get_last_serial_number(serial));
ck_assert_int_eq(-EAGAIN, vrps_foreach_base_roa(vrp_fail,
- iterated_entries, &serial));
- ck_assert_int_eq(-EAGAIN, vrps_get_deltas_from(0, &serial, &deltas));
+ iterated_entries, serial));
+ ck_assert_int_eq(-EAGAIN, vrps_get_deltas_from(0, serial, deltas));
/* First validation: One tree, no deltas */
- ck_assert_int_eq(0, vrps_update(&changed));
+ ck_assert_int_eq(0, vrps_update(changed));
check_serial(0);
check_base(0, iteration0_base);
- check_deltas(0, 0, deltas_0to0);
+ check_deltas(0, 0, deltas_0to0, false);
/* Second validation: One tree, added deltas */
- ck_assert_int_eq(0, vrps_update(&changed));
+ ck_assert_int_eq(0, vrps_update(changed));
check_serial(1);
check_base(1, iteration1_base);
- check_deltas(0, 1, deltas_0to1);
- check_deltas(1, 1, deltas_1to1);
+ check_deltas(0, 1, deltas_0to1, false);
+ check_deltas(1, 1, deltas_1to1, false);
+}
+
+START_TEST(test_basic)
+{
+ struct deltas_db deltas;
+ serial_t serial;
+ bool changed;
+ bool iterated_entries[8];
+
+ create_deltas_0to1(&deltas, &serial, &changed, iterated_entries);
+
+ /* Third validation: One tree, removed deltas */
+ ck_assert_int_eq(0, vrps_update(&changed));
+ check_serial(2);
+ check_base(2, iteration2_base);
+ check_deltas(0, 2, deltas_0to2, false);
+ check_deltas(1, 2, deltas_1to2, false);
+ check_deltas(2, 2, deltas_2to2, false);
+
+ vrps_destroy();
+}
+END_TEST
+
+START_TEST(test_delta_forget)
+{
+ struct deltas_db deltas;
+ serial_t serial;
+ bool changed;
+ bool iterated_entries[8];
+
+ create_deltas_0to1(&deltas, &serial, &changed, iterated_entries);
+
+ /*
+ * Assume that the client(s) already have serial 1 (serial 2 will be
+ * created) so serial 0 isn't needed anymore.
+ */
+ current_min_serial = 1;
+
+ /* Third validation: One tree, removed deltas and delta 0 removed */
+ ck_assert_int_eq(0, vrps_update(&changed));
+ check_serial(2);
+ check_base(2, iteration2_base);
+ check_no_deltas(0, 2);
+ check_deltas(1, 2, deltas_1to2, false);
+ check_deltas(2, 2, deltas_2to2, false);
+
+ vrps_destroy();
+
+ /* Return to its initial value */
+ current_min_serial = 0;
+}
+END_TEST
+
+START_TEST(test_delta_ovrd)
+{
+ struct deltas_db deltas;
+ serial_t serial;
+ bool changed;
+ bool iterated_entries[8];
+
+ create_deltas_0to1(&deltas, &serial, &changed, iterated_entries);
/* Third validation: One tree, removed deltas */
ck_assert_int_eq(0, vrps_update(&changed));
check_serial(2);
check_base(2, iteration2_base);
- check_deltas(0, 2, deltas_0to2);
- check_deltas(1, 2, deltas_1to2);
- check_deltas(2, 2, deltas_2to2);
+ check_deltas(0, 2, deltas_0to2, false);
+ check_deltas(1, 2, deltas_1to2, false);
+ check_deltas(2, 2, deltas_2to2, false);
+
+ /* Fourth validation with deltas that override each other */
+ ck_assert_int_eq(0, vrps_update(&changed));
+ check_serial(3);
+ check_base(3, iteration3_base);
+ check_deltas(0, 3, deltas_0to3_ovrd, false);
+ check_deltas(1, 3, deltas_1to3_ovrd, false);
+ check_deltas(2, 3, deltas_2to3_ovrd, false);
+ check_deltas(3, 3, deltas_3to3_ovrd, false);
+
+ /* Check "cleaned up" deltas */
+ check_deltas(0, 3, deltas_0to3_clean, true);
+ check_deltas(1, 3, deltas_1to3_clean, true);
+ check_deltas(2, 3, deltas_2to3_clean, true);
+ check_deltas(3, 3, deltas_3to3_clean, true);
vrps_destroy();
+
+ /* Return to its initial value */
+ current_min_serial = 0;
}
END_TEST
core = tcase_create("Core");
tcase_add_test(core, test_basic);
+ tcase_add_test(core, test_delta_forget);
+ tcase_add_test(core, test_delta_ovrd);
suite = suite_create("VRP Database");
suite_add_tcase(suite, core);