2022-11-05 15:29:00 +00:00
|
|
|
/*
|
|
|
|
* BIRD -- Simple Network Management Protocol (SNMP) Unit tests
|
|
|
|
*
|
|
|
|
* (c) 2022 Vojtech Vilimek <vojtech.vilimek@nic.cz>
|
|
|
|
* (c) 2022 CZ.NIC z.s.p.o
|
|
|
|
*
|
|
|
|
* Can be freely distributed and used under the terms of the GNU GPL.
|
|
|
|
*/
|
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
#include <stdarg.h>
|
|
|
|
|
2022-11-05 15:29:00 +00:00
|
|
|
#include "test/birdtest.h"
|
2023-03-24 14:02:23 +00:00
|
|
|
#include "test/bt-utils.h"
|
2022-11-05 15:29:00 +00:00
|
|
|
|
2024-05-21 13:43:41 +00:00
|
|
|
#include "bgp4_mib.h"
|
2022-11-05 15:29:00 +00:00
|
|
|
#include "subagent.h"
|
|
|
|
#include "snmp.h"
|
2022-11-15 15:29:03 +00:00
|
|
|
#include "snmp_utils.h"
|
2024-04-22 10:55:33 +00:00
|
|
|
#include "mib_tree.h"
|
|
|
|
|
2024-05-21 13:43:41 +00:00
|
|
|
/*************************************************************************
|
|
|
|
*
|
|
|
|
* TODO: reject OIDs longer than OID_MAX_LEN in subagent.c/snmp_utils.c
|
|
|
|
*
|
|
|
|
*************************************************************************/
|
|
|
|
|
|
|
|
// TODO: limit for prefixed OID used for walking is 27 ids (32 - 4inet -1prefix
|
|
|
|
// resp. 33 - 4inet-1prefix-1empty)
|
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
// TODO test walk state stack overflow
|
|
|
|
// TODO hint for child len alloc size
|
|
|
|
|
|
|
|
static int t_oid_empty(void);
|
|
|
|
static int t_oid_compare(void);
|
|
|
|
static int t_oid_prefixize(void);
|
2024-07-04 14:33:44 +00:00
|
|
|
static int t_walk_oid_desc(void);
|
2024-07-22 16:12:28 +00:00
|
|
|
static int t_walk_oid_compare(void);
|
2024-04-22 10:55:33 +00:00
|
|
|
static int t_tree_find(void);
|
|
|
|
static int t_tree_traversal(void);
|
|
|
|
static int t_tree_leafs(void);
|
|
|
|
static int t_tree_add(void);
|
|
|
|
static int t_tree_delete(void);
|
|
|
|
|
|
|
|
#define SNMP_BUFFER_SIZE 1024
|
2024-05-21 13:43:41 +00:00
|
|
|
#define TESTS_NUM 32
|
2024-04-22 10:55:33 +00:00
|
|
|
#define SMALL_TESTS_NUM 10
|
|
|
|
static int tree_sizes[] = { 0, 1, 10, 100, 1000 };
|
|
|
|
|
2024-07-04 14:33:44 +00:00
|
|
|
/* smaller than theoretical maximum (2^32) to fit in memory */
|
2024-04-22 10:55:33 +00:00
|
|
|
#define OID_MAX_ID 16
|
2022-11-05 15:29:00 +00:00
|
|
|
|
|
|
|
#define SNMP_EXPECTED(actual, expected) \
|
|
|
|
bt_debug("%s expected: %3u actual: %3u\n", \
|
|
|
|
#expected, expected, actual);
|
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
static inline struct oid *
|
|
|
|
oid_allocate(uint size)
|
2022-11-05 15:29:00 +00:00
|
|
|
{
|
2024-04-22 10:55:33 +00:00
|
|
|
return tmp_alloc(sizeof(struct oid) + size * sizeof(u32));
|
2022-11-05 15:29:00 +00:00
|
|
|
}
|
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
static inline void
|
|
|
|
oid_init2(struct oid *oid, u8 n_subid, u8 prefix, u8 include, va_list ids)
|
2022-11-05 15:29:00 +00:00
|
|
|
{
|
2024-04-22 10:55:33 +00:00
|
|
|
oid->n_subid = n_subid;
|
|
|
|
oid->prefix = prefix;
|
|
|
|
oid->include = include;
|
|
|
|
oid->reserved = 0;
|
2023-03-24 14:02:23 +00:00
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
for (u8 i = 0; i < n_subid; i++)
|
|
|
|
{
|
|
|
|
u32 id = va_arg(ids, u32);
|
|
|
|
oid->ids[i] = id;
|
|
|
|
}
|
2022-11-05 15:29:00 +00:00
|
|
|
}
|
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
static inline void
|
|
|
|
oid_init(struct oid *oid, u8 n_subid, u8 prefix, u8 include, ...)
|
2022-11-15 15:29:03 +00:00
|
|
|
{
|
2024-04-22 10:55:33 +00:00
|
|
|
va_list ids;
|
|
|
|
va_start(ids, include);
|
|
|
|
oid_init2(oid, n_subid, prefix, include, ids);
|
|
|
|
va_end(ids);
|
|
|
|
}
|
2023-03-31 07:56:03 +00:00
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
static inline struct oid *
|
|
|
|
oid_create(u8 n_subid, u8 prefix, u8 include, ...)
|
|
|
|
{
|
|
|
|
struct oid *result = tmp_alloc(snmp_oid_size_from_len(n_subid));
|
|
|
|
va_list ids;
|
2023-03-31 07:56:03 +00:00
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
va_start(ids, include);
|
|
|
|
oid_init2(result, n_subid, prefix, include, ids);
|
|
|
|
va_end(ids);
|
2022-11-15 15:29:03 +00:00
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
return result;
|
|
|
|
}
|
2022-11-15 15:29:03 +00:00
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
static u32
|
|
|
|
xrandom(u32 max)
|
|
|
|
{
|
|
|
|
return (bt_random() % max);
|
|
|
|
}
|
2022-11-15 15:29:03 +00:00
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
static u32
|
|
|
|
oid_random_id(void)
|
|
|
|
{
|
|
|
|
return (bt_random() % (OID_MAX_ID));
|
|
|
|
}
|
2023-03-31 07:56:03 +00:00
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
static struct oid *
|
|
|
|
random_prefixed_oid(void)
|
|
|
|
{
|
2024-05-21 13:43:41 +00:00
|
|
|
u32 len = xrandom(OID_MAX_LEN + 1 - (ARRAY_SIZE(snmp_internet) + 1));
|
2023-03-31 07:56:03 +00:00
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
u8 prefix = (u8) xrandom(UINT8_MAX + 1);
|
2022-11-15 15:29:03 +00:00
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
if (!prefix)
|
|
|
|
return oid_create(0, 0, 0, 0);
|
2022-11-15 15:29:03 +00:00
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
struct oid *random = tmp_alloc(snmp_oid_size_from_len(len));
|
|
|
|
/* (xrandom(2) * bt_random()) has 0.5 probability to have value 0 and
|
|
|
|
* 0.5 to have random u32 (including zero) */
|
|
|
|
oid_init(random, 0, prefix, xrandom(2) * bt_random());
|
|
|
|
random->n_subid = len;
|
2022-11-15 15:29:03 +00:00
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
for (u32 id = 0; id < len; id++)
|
|
|
|
random->ids[id] = oid_random_id();
|
2023-03-31 07:56:03 +00:00
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
return random;
|
2022-11-15 15:29:03 +00:00
|
|
|
}
|
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
static struct oid *
|
|
|
|
random_no_prefix_oid(void)
|
2022-11-15 15:29:03 +00:00
|
|
|
{
|
2024-04-22 10:55:33 +00:00
|
|
|
/* probability that the random OID is prefixable is practically zero */
|
|
|
|
u32 len = xrandom(OID_MAX_LEN + 1);
|
2022-11-15 15:29:03 +00:00
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
struct oid *random = tmp_alloc(snmp_oid_size_from_len(len));
|
|
|
|
/* (xrandom(2) * bt_random()) has 0.5 probability to have value 0 and
|
|
|
|
* 0.5 to have random u32 (including zero) */
|
|
|
|
oid_init(random, 0, 0, xrandom(2) * bt_random());
|
|
|
|
random->n_subid = len;
|
2023-03-31 07:56:03 +00:00
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
for (u32 id = 0; id < len; id++)
|
|
|
|
random->ids[id] = oid_random_id();
|
2023-03-31 07:56:03 +00:00
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
return random;
|
|
|
|
}
|
2022-11-15 15:29:03 +00:00
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
static struct oid *
|
|
|
|
random_prefixable_oid(void)
|
|
|
|
{
|
|
|
|
/* generate the len without the snmp_internet prefix included and prefix ID */
|
|
|
|
u32 len = xrandom(OID_MAX_LEN + 1 - (ARRAY_SIZE(snmp_internet) + 1));
|
2022-11-15 15:29:03 +00:00
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
struct oid *random = tmp_alloc(
|
|
|
|
snmp_oid_size_from_len(len + ARRAY_SIZE(snmp_internet) + 1));
|
|
|
|
/* (xrandom(2) * bt_random()) has 0.5 probability to have value 0 and
|
|
|
|
* 0.5 to have random u32 (including zero) */
|
|
|
|
oid_init(random, 0, 0, xrandom(2) * bt_random());
|
|
|
|
random->n_subid = len + ARRAY_SIZE(snmp_internet) + 1;
|
2022-11-15 15:29:03 +00:00
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
for (u32 inet_id = 0; inet_id < ARRAY_SIZE(snmp_internet); inet_id++)
|
|
|
|
random->ids[inet_id] = snmp_internet[inet_id];
|
2023-03-24 14:02:23 +00:00
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
random->ids[ARRAY_SIZE(snmp_internet)] = xrandom(UINT8_MAX + 1);
|
2023-03-31 07:56:03 +00:00
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
for (u32 id = 0; id < len; id++)
|
|
|
|
random->ids[id + ARRAY_SIZE(snmp_internet) + 1] = oid_random_id();
|
2022-11-15 15:29:03 +00:00
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
return random;
|
|
|
|
}
|
2022-11-15 15:29:03 +00:00
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
static struct oid *
|
|
|
|
random_oid(void)
|
|
|
|
{
|
|
|
|
u32 option = xrandom(3);
|
|
|
|
|
|
|
|
if (option == 0)
|
|
|
|
return random_prefixed_oid();
|
|
|
|
else if (option == 1)
|
|
|
|
return random_no_prefix_oid();
|
|
|
|
else
|
|
|
|
return random_prefixable_oid();
|
|
|
|
}
|
2022-11-15 15:29:03 +00:00
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
static int
|
|
|
|
t_oid_empty(void)
|
|
|
|
{
|
|
|
|
struct lp_state tmps;
|
|
|
|
lp_save(tmp_linpool, &tmps);
|
2023-03-24 14:02:23 +00:00
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
bt_assert(snmp_is_oid_empty(NULL) == 0);
|
2022-11-15 15:29:03 +00:00
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
{
|
|
|
|
struct oid *blank = oid_create(0, 0, 0 /* no ids */);
|
|
|
|
bt_assert(snmp_is_oid_empty(blank) == 1);
|
|
|
|
lp_restore(tmp_linpool, &tmps);
|
|
|
|
}
|
2022-11-15 15:29:03 +00:00
|
|
|
|
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
{
|
|
|
|
struct oid *prefixed = oid_create(3, 100, 1,
|
|
|
|
/* ids */ ~((u32) 0), 0, 256);
|
|
|
|
bt_assert(snmp_is_oid_empty(prefixed) == 0);
|
|
|
|
lp_restore(tmp_linpool, &tmps);
|
|
|
|
}
|
2023-03-31 07:56:03 +00:00
|
|
|
|
2022-11-15 15:29:03 +00:00
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
{
|
|
|
|
struct oid *to_prefix = oid_create(8, 0, 1,
|
|
|
|
/* ids */ 1, 3, 6, 1, 100, ~((u32) 0), 0, 256);
|
|
|
|
bt_assert(snmp_is_oid_empty(to_prefix) == 0);
|
|
|
|
lp_restore(tmp_linpool, &tmps);
|
|
|
|
}
|
2022-11-15 15:29:03 +00:00
|
|
|
|
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
{
|
|
|
|
struct oid *unprefixable = oid_create(2, 0, 0,
|
|
|
|
/* ids */ 65535, 4);
|
|
|
|
bt_assert(snmp_is_oid_empty(unprefixable) == 0);
|
|
|
|
lp_restore(tmp_linpool, &tmps);
|
|
|
|
}
|
2023-03-31 07:56:03 +00:00
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
{
|
|
|
|
struct oid *unprefixable2 = oid_create(8, 0, 1,
|
|
|
|
/* ids */ 1, 3, 6, 2, 1, 2, 15, 6);
|
|
|
|
bt_assert(snmp_is_oid_empty(unprefixable2) == 0);
|
|
|
|
lp_restore(tmp_linpool, &tmps);
|
|
|
|
}
|
2022-11-15 15:29:03 +00:00
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
tmp_flush();
|
2022-11-15 15:29:03 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2022-11-29 15:30:20 +00:00
|
|
|
static int
|
|
|
|
t_oid_compare(void)
|
|
|
|
{
|
2024-04-22 10:55:33 +00:00
|
|
|
struct lp_state tmps;
|
|
|
|
lp_save(tmp_linpool, &tmps);
|
2022-11-29 15:30:20 +00:00
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
/* same length, no prefix */
|
|
|
|
struct oid *l1 = oid_create(5, 0, 1,
|
|
|
|
/* ids */ 1, 2, 3, 4, 5);
|
2022-11-29 15:30:20 +00:00
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
struct oid *r1 = oid_create(5, 0, 0,
|
|
|
|
/* ids */ 1, 2, 3, 4, 6);
|
2022-11-29 15:30:20 +00:00
|
|
|
|
|
|
|
bt_assert(snmp_oid_compare(l1, r1) == -1);
|
|
|
|
bt_assert(snmp_oid_compare(r1, l1) == 1);
|
|
|
|
|
|
|
|
bt_assert(snmp_oid_compare(l1, l1) == 0);
|
|
|
|
bt_assert(snmp_oid_compare(r1, r1) == 0);
|
|
|
|
|
|
|
|
/* same results for prefixed oids */
|
|
|
|
l1->prefix = 1;
|
|
|
|
r1->prefix = 1;
|
|
|
|
|
|
|
|
bt_assert(snmp_oid_compare(l1, r1) == -1);
|
|
|
|
bt_assert(snmp_oid_compare(r1, l1) == 1);
|
|
|
|
|
|
|
|
bt_assert(snmp_oid_compare(l1, l1) == 0);
|
|
|
|
bt_assert(snmp_oid_compare(r1, r1) == 0);
|
|
|
|
|
2023-03-24 14:02:23 +00:00
|
|
|
/* different prefix -- has higher priority */
|
|
|
|
l1->prefix = 8;
|
|
|
|
r1->prefix = 4;
|
|
|
|
|
|
|
|
bt_assert(snmp_oid_compare(l1, r1) == 1);
|
|
|
|
bt_assert(snmp_oid_compare(r1, l1) == -1);
|
|
|
|
|
|
|
|
bt_assert(snmp_oid_compare(l1, l1) == 0);
|
|
|
|
bt_assert(snmp_oid_compare(r1, r1) == 0);
|
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
lp_restore(tmp_linpool, &tmps);
|
2022-11-29 15:30:20 +00:00
|
|
|
|
2023-03-24 14:02:23 +00:00
|
|
|
|
2022-11-29 15:30:20 +00:00
|
|
|
/* different length, no prefix */
|
2024-04-22 10:55:33 +00:00
|
|
|
l1 = oid_create(4, 0, 0,
|
|
|
|
/* ids */ 1, 2, 3, 4);
|
2022-11-29 15:30:20 +00:00
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
r1 = oid_create(5, 0, 1,
|
|
|
|
/* ids */ 1, 2, 3, 4, 1);
|
2022-11-29 15:30:20 +00:00
|
|
|
|
|
|
|
bt_assert(snmp_oid_compare(l1, r1) == -1);
|
|
|
|
bt_assert(snmp_oid_compare(r1, l1) == 1);
|
|
|
|
|
|
|
|
bt_assert(snmp_oid_compare(l1, l1) == 0);
|
|
|
|
bt_assert(snmp_oid_compare(r1, r1) == 0);
|
|
|
|
|
|
|
|
/* same results for prefixed oids */
|
|
|
|
l1->prefix = 3;
|
|
|
|
r1->prefix = 3;
|
|
|
|
|
|
|
|
bt_assert(snmp_oid_compare(l1, r1) == -1);
|
|
|
|
bt_assert(snmp_oid_compare(r1, l1) == 1);
|
|
|
|
|
|
|
|
bt_assert(snmp_oid_compare(l1, l1) == 0);
|
|
|
|
bt_assert(snmp_oid_compare(r1, r1) == 0);
|
|
|
|
|
2023-03-24 14:02:23 +00:00
|
|
|
/* different prefix -- has higher priority */
|
|
|
|
l1->prefix = 17;
|
|
|
|
r1->prefix = 14;
|
|
|
|
|
|
|
|
bt_assert(snmp_oid_compare(l1, r1) == 1);
|
|
|
|
bt_assert(snmp_oid_compare(r1, l1) == -1);
|
|
|
|
|
|
|
|
bt_assert(snmp_oid_compare(l1, l1) == 0);
|
|
|
|
bt_assert(snmp_oid_compare(r1, r1) == 0);
|
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
lp_restore(tmp_linpool, &tmps);
|
2022-11-29 15:30:20 +00:00
|
|
|
|
2023-03-24 14:02:23 +00:00
|
|
|
|
|
|
|
/* inverse order different length, no prefix */
|
2024-04-22 10:55:33 +00:00
|
|
|
l1 = oid_create(4, 0, 0,
|
|
|
|
/* ids */ 1, 2, 3, 5);
|
2022-11-29 15:30:20 +00:00
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
r1 = oid_create(5, 0, 0,
|
|
|
|
/* ids */ 1, 2, 3, 4, 1);
|
2022-11-29 15:30:20 +00:00
|
|
|
|
|
|
|
bt_assert(snmp_oid_compare(l1, r1) == 1);
|
|
|
|
bt_assert(snmp_oid_compare(r1, l1) == -1);
|
|
|
|
|
|
|
|
bt_assert(snmp_oid_compare(l1, l1) == 0);
|
|
|
|
bt_assert(snmp_oid_compare(r1, r1) == 0);
|
|
|
|
|
|
|
|
/* same results for prefixed oids */
|
|
|
|
l1->prefix = 254;
|
|
|
|
r1->prefix = 254;
|
|
|
|
|
|
|
|
bt_assert(snmp_oid_compare(l1, r1) == 1);
|
|
|
|
bt_assert(snmp_oid_compare(r1, l1) == -1);
|
|
|
|
|
|
|
|
bt_assert(snmp_oid_compare(l1, l1) == 0);
|
|
|
|
bt_assert(snmp_oid_compare(r1, r1) == 0);
|
|
|
|
|
2023-03-24 14:02:23 +00:00
|
|
|
/* different prefix -- has higher priority */
|
|
|
|
l1->prefix = 127;
|
|
|
|
r1->prefix = 35;
|
|
|
|
|
|
|
|
bt_assert(snmp_oid_compare(l1, r1) == 1);
|
|
|
|
bt_assert(snmp_oid_compare(r1, l1) == -1);
|
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
lp_restore(tmp_linpool, &tmps);
|
2022-11-29 15:30:20 +00:00
|
|
|
|
2023-03-24 14:02:23 +00:00
|
|
|
|
2022-11-29 15:30:20 +00:00
|
|
|
/* ==== MIXED PREFIXED / NON PREFIXED OID compare ==== */
|
|
|
|
/* same length, mixed */
|
2024-04-22 10:55:33 +00:00
|
|
|
l1 = oid_create(6, 0, 1,
|
|
|
|
/* ids */ 1, 2, 17, 3, 21, 4);
|
2022-11-29 15:30:20 +00:00
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
r1 = oid_create(1, 5, 1,
|
|
|
|
/* ids */ 3);
|
2022-11-29 15:30:20 +00:00
|
|
|
|
|
|
|
bt_assert(snmp_oid_compare(l1, r1) == -1);
|
|
|
|
bt_assert(snmp_oid_compare(r1, l1) == 1);
|
|
|
|
|
|
|
|
bt_assert(snmp_oid_compare(l1, l1) == 0);
|
|
|
|
bt_assert(snmp_oid_compare(r1, r1) == 0);
|
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
lp_restore(tmp_linpool, &tmps);
|
|
|
|
|
|
|
|
struct oid *super = oid_create(4, 0, 0, /* ids */ 1, 3, 6, 1);
|
|
|
|
struct oid *weird = oid_create(4, 70, 0, /* ids */ 9, 10, 10, 12);
|
|
|
|
|
|
|
|
bt_assert(snmp_oid_compare(super, weird) != 0);
|
|
|
|
|
2024-05-21 13:43:41 +00:00
|
|
|
struct oid *pref = oid_create(0, 7, 0); // no ids, only prefix
|
|
|
|
struct oid *no_pref = oid_create(5, 0, 0, /* ids */ 1, 3, 6, 1, 7);
|
|
|
|
|
|
|
|
bt_assert(snmp_oid_compare(pref, no_pref) == 0);
|
|
|
|
|
|
|
|
struct oid *inet = oid_create(4, 0, 0, /* ids */ 1, 3, 6, 1);
|
|
|
|
|
|
|
|
bt_assert(snmp_oid_compare(inet, pref) < 0);
|
|
|
|
bt_assert(snmp_oid_compare(pref, inet) > 0);
|
|
|
|
bt_assert(snmp_oid_compare(inet, no_pref) < 0);
|
|
|
|
bt_assert(snmp_oid_compare(no_pref, inet) > 0);
|
|
|
|
|
|
|
|
struct oid *pref2 = oid_create(0, 16, 0); // no ids, only prefix
|
|
|
|
struct oid *no_pref2 = oid_create(5, 0, 0, /* ids */ 1, 3, 6, 1, 16);
|
|
|
|
|
|
|
|
bt_assert(snmp_oid_compare(pref2, no_pref2) == 0);
|
|
|
|
bt_assert(snmp_oid_compare(no_pref2, pref2) == 0);
|
|
|
|
|
|
|
|
bt_assert(snmp_oid_compare(pref, pref2) < 0);
|
2024-05-24 13:20:30 +00:00
|
|
|
bt_assert(snmp_oid_compare(pref2, pref) > 0);
|
2024-05-21 13:43:41 +00:00
|
|
|
bt_assert(snmp_oid_compare(pref, no_pref2) < 0);
|
|
|
|
bt_assert(snmp_oid_compare(no_pref2, pref) > 0);
|
|
|
|
bt_assert(snmp_oid_compare(no_pref, pref2) < 0);
|
|
|
|
bt_assert(snmp_oid_compare(pref2, no_pref) > 0);
|
|
|
|
bt_assert(snmp_oid_compare(no_pref, no_pref2) < 0);
|
|
|
|
bt_assert(snmp_oid_compare(no_pref2, no_pref) > 0);
|
|
|
|
|
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
tmp_flush();
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct oid *
|
|
|
|
snmp_oid_prefixize(struct snmp_proto *p, const struct oid *oid, struct snmp_pdu *c)
|
|
|
|
{
|
2024-07-22 16:12:28 +00:00
|
|
|
snmp_vb_to_tx(p, oid, c);
|
|
|
|
struct agentx_varbind *vb = c->sr_vb_start;
|
2024-04-22 10:55:33 +00:00
|
|
|
bt_assert(vb->reserved == 0);
|
|
|
|
return &vb->name;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* t_oid_prefixize - test prefixing aspect of function snmp_vb_to_tx()
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
t_oid_prefixize(void)
|
|
|
|
{
|
|
|
|
lp_state tmps = { };
|
|
|
|
struct snmp_proto *snmp_proto = NULL;
|
|
|
|
|
|
|
|
byte *buffer = tmp_alloc(SNMP_BUFFER_SIZE);
|
|
|
|
const struct snmp_pdu copy = {
|
|
|
|
.buffer = buffer,
|
|
|
|
.size = SNMP_BUFFER_SIZE,
|
|
|
|
.error = AGENTX_RES_NO_ERROR,
|
|
|
|
.index = 0,
|
|
|
|
};
|
|
|
|
struct snmp_pdu c;
|
|
|
|
|
|
|
|
lp_save(tmp_linpool, &tmps);
|
|
|
|
|
|
|
|
|
|
|
|
/* testing prefixable OIDs */
|
|
|
|
for (int test = 0; test < TESTS_NUM; test++)
|
|
|
|
{
|
|
|
|
const struct oid *oid = random_prefixable_oid();
|
|
|
|
|
|
|
|
u8 subids = oid->n_subid;
|
|
|
|
u8 include = oid->include;
|
|
|
|
u32 pid = oid->ids[ARRAY_SIZE(snmp_internet)];
|
|
|
|
|
|
|
|
/* reset to the default snmp_pdu */
|
|
|
|
c = copy; memset(buffer, 0, snmp_oid_size(oid) + 8);
|
|
|
|
|
|
|
|
struct oid *new = snmp_oid_prefixize(snmp_proto, oid, &c);
|
|
|
|
|
|
|
|
bt_assert(new->n_subid == subids - (ARRAY_SIZE(snmp_internet) + 1));
|
|
|
|
bt_assert(new->prefix == pid);
|
|
|
|
bt_assert(!!new->include == !!include);
|
|
|
|
bt_assert(new->reserved == 0);
|
|
|
|
|
|
|
|
for (u32 i = 0; i < new->n_subid; i++)
|
|
|
|
{
|
|
|
|
bt_assert(new->ids[i] == oid->ids[i + ARRAY_SIZE(snmp_internet) + 1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (u32 j = 0; j < ARRAY_SIZE(snmp_internet); j++)
|
|
|
|
bt_assert(oid->ids[j] == snmp_internet[j]);
|
|
|
|
|
|
|
|
lp_restore(tmp_linpool, &tmps);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* testing already prefixed OIDs */
|
|
|
|
for (int test = 0; test < TESTS_NUM; test++)
|
|
|
|
{
|
|
|
|
const struct oid *prefixed = random_prefixed_oid();
|
|
|
|
|
|
|
|
/* reset to the default snmp_pdu */
|
|
|
|
c = copy; memset(buffer, 0, snmp_oid_size(prefixed) + 8);
|
|
|
|
|
|
|
|
struct oid *new = snmp_oid_prefixize(snmp_proto, prefixed, &c);
|
|
|
|
|
|
|
|
bt_assert(new->n_subid == prefixed->n_subid);
|
|
|
|
bt_assert(new->prefix == prefixed->prefix);
|
|
|
|
bt_assert(!!new->include == !!prefixed->include);
|
|
|
|
bt_assert(new->reserved == 0);
|
|
|
|
bt_assert(!memcmp(&new->ids[0], &prefixed->ids[0], new->n_subid * sizeof(u32)));
|
|
|
|
|
|
|
|
lp_restore(tmp_linpool, &tmps);
|
|
|
|
}
|
|
|
|
|
|
|
|
lp_restore(tmp_linpool, &tmps);
|
|
|
|
|
|
|
|
/* testing non-prefixable OIDs */
|
|
|
|
for (int test = 0; test < TESTS_NUM; test++)
|
|
|
|
{
|
|
|
|
const struct oid *oid = random_no_prefix_oid();
|
|
|
|
|
|
|
|
/* test that the OID is _really_ not prefixable */
|
|
|
|
if (oid->n_subid > ARRAY_SIZE(snmp_internet) &&
|
|
|
|
oid->ids[ARRAY_SIZE(snmp_internet) + 1] <= UINT8_MAX)
|
|
|
|
{
|
|
|
|
for (u32 i = 0; i < ARRAY_SIZE(snmp_internet); i++)
|
|
|
|
if (oid->ids[i] != snmp_internet[i]) goto continue_testing;
|
|
|
|
|
|
|
|
break; /* outer for loop */
|
|
|
|
}
|
|
|
|
|
|
|
|
continue_testing:
|
|
|
|
|
|
|
|
/* reset to the default snmp_pdu */
|
|
|
|
c = copy; memset(buffer, 0, snmp_oid_size(oid) + 8);
|
|
|
|
|
|
|
|
struct oid *new = snmp_oid_prefixize(snmp_proto, oid, &c);
|
|
|
|
|
|
|
|
bt_assert(new->n_subid == oid->n_subid);
|
|
|
|
bt_assert(new->prefix == oid->prefix);
|
|
|
|
bt_assert(!!new->include == !!oid->include);
|
|
|
|
bt_assert(new->reserved == 0);
|
|
|
|
bt_assert(!memcmp(&new->ids[0], &oid->ids[0], new->n_subid * sizeof(u32)));
|
|
|
|
|
|
|
|
lp_restore(tmp_linpool, &tmps);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int test = 0; test < SMALL_TESTS_NUM; test++)
|
|
|
|
{
|
|
|
|
const struct oid *oid;
|
|
|
|
{
|
|
|
|
struct oid *work = random_prefixable_oid();
|
|
|
|
|
|
|
|
/* include also the prefix ID (at index 4) */
|
|
|
|
u32 index = xrandom(ARRAY_SIZE(snmp_internet) + 1);
|
|
|
|
/* change randomly picked id at index from 0..5 (included) */
|
|
|
|
u32 random = bt_random();
|
|
|
|
if (index == ARRAY_SIZE(snmp_internet) && random > 255)
|
|
|
|
work->ids[index] = random;
|
|
|
|
else if (index != ARRAY_SIZE(snmp_internet) && work->ids[index] != random)
|
|
|
|
work->ids[index] = random;
|
|
|
|
else
|
|
|
|
continue;
|
|
|
|
oid = work;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* reset to the default snmp_pdu */
|
|
|
|
c = copy; memset(buffer, 0, snmp_oid_size(oid) + 8);
|
|
|
|
|
|
|
|
struct oid *new = snmp_oid_prefixize(snmp_proto, oid, &c);
|
|
|
|
|
|
|
|
bt_assert(new->n_subid == oid->n_subid);
|
|
|
|
bt_assert(new->prefix == oid->prefix);
|
|
|
|
bt_assert(!!new->include == !!oid->include);
|
|
|
|
bt_assert(new->reserved == 0);
|
|
|
|
bt_assert(!memcmp(&new->ids[0], &oid->ids[0], new->n_subid * sizeof(u32)));
|
|
|
|
|
|
|
|
lp_restore(tmp_linpool, &tmps);
|
|
|
|
}
|
|
|
|
|
|
|
|
tmp_flush();
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2024-05-21 13:43:41 +00:00
|
|
|
static inline void
|
|
|
|
walk_to_oid_one(pool *pool, const struct oid *oid)
|
|
|
|
{
|
|
|
|
struct mib_tree storage, *tree = &storage;
|
|
|
|
mib_tree_init(pool, tree);
|
|
|
|
|
|
|
|
struct mib_walk_state walk;
|
|
|
|
mib_tree_walk_init(&walk, tree);
|
|
|
|
|
|
|
|
const struct oid *inet_pref = oid_create(1, 0, 0, /* ids */ 1);
|
|
|
|
mib_tree_remove(tree, inet_pref);
|
|
|
|
|
|
|
|
(void) mib_tree_add(pool, tree, oid, xrandom(2));
|
|
|
|
mib_tree_find(tree, &walk, oid);
|
|
|
|
|
|
|
|
char buf[1024];
|
2024-07-22 16:12:28 +00:00
|
|
|
struct oid *from_walk = (struct oid *) buf;
|
2024-05-21 13:43:41 +00:00
|
|
|
|
|
|
|
int r = mib_tree_walk_to_oid(&walk, from_walk,
|
|
|
|
(1024 - sizeof(struct oid)) / sizeof(u32));
|
|
|
|
|
|
|
|
/* the memory limit should not be breached */
|
|
|
|
bt_assert(r == 0);
|
|
|
|
|
|
|
|
bt_assert(snmp_oid_compare(from_walk, oid) == 0);
|
|
|
|
|
|
|
|
/* cleanup */
|
|
|
|
mib_tree_remove(tree, inet_pref);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* test MIB tree walk to OID */
|
|
|
|
static int
|
|
|
|
t_walk_to_oid(void)
|
|
|
|
{
|
|
|
|
lp_state tmps;
|
|
|
|
lp_save(tmp_linpool, &tmps);
|
|
|
|
|
|
|
|
|
|
|
|
pool *pool = &root_pool;
|
|
|
|
|
|
|
|
for (int test = 0; test < TESTS_NUM; test++)
|
|
|
|
{
|
|
|
|
|
|
|
|
walk_to_oid_one(pool, random_prefixed_oid());
|
|
|
|
walk_to_oid_one(pool, random_no_prefix_oid());
|
|
|
|
walk_to_oid_one(pool, random_prefixable_oid());
|
|
|
|
/* only a one of above */
|
|
|
|
//walk_to_oid_one(random_oid);
|
|
|
|
|
|
|
|
lp_restore(tmp_linpool, &tmps);
|
|
|
|
}
|
|
|
|
|
|
|
|
tmp_flush();
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2024-07-04 14:33:44 +00:00
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
static void
|
|
|
|
test_both(void *buffer, uint size, const struct oid *left, const struct oid
|
|
|
|
*right, const struct oid *expected)
|
|
|
|
{
|
|
|
|
memset(buffer, 0, size);
|
|
|
|
snmp_oid_common_ancestor(left, right, buffer);
|
|
|
|
bt_assert(snmp_oid_compare(buffer, expected) == 0);
|
|
|
|
|
|
|
|
memset(buffer, 0, size);
|
|
|
|
snmp_oid_common_ancestor(right, left, buffer);
|
|
|
|
bt_assert(snmp_oid_compare(buffer, expected) == 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
#define TEST_BOTH(l, r, e) test_both(buffer, 1024, l, r, e)
|
|
|
|
static int
|
|
|
|
t_oid_ancestor(void)
|
|
|
|
{
|
|
|
|
const struct oid *null = oid_create(0, 0, 0);
|
|
|
|
const struct oid *shorter = oid_create(3, 15, 0, /* ids */ 192, 1, 7);
|
|
|
|
const struct oid *prefixed = oid_create(4, 15, 0, /* ids */ 192, 1, 7, 82);
|
|
|
|
const struct oid *no_prefix = oid_create(9, 0, 0, /* ids */ 1, 3, 6, 1, 15, 192, 1, 7, 82);
|
|
|
|
const struct oid *outside = oid_create(7, 0, 0, /* ids */ 4, 3, 2, 1, 8, 0, 2);
|
|
|
|
const struct oid *prefix_only = oid_create(0, 15, 0);
|
|
|
|
const struct oid *prefix_only2 = oid_create(0, 9, 0);
|
|
|
|
const struct oid *partial = oid_create(3, 0, 0, /* ids */ 1, 3, 6);
|
|
|
|
const struct oid *no_inet = oid_create(5, 0, 0, /* ids */ 1, 3, 6, 2, 5);
|
|
|
|
|
|
|
|
const struct oid *inet = oid_create(4, 0, 0, /* ids */ 1, 3, 6, 1);
|
|
|
|
|
|
|
|
|
|
|
|
const struct oid *oids[] = {
|
|
|
|
null, shorter, prefixed, no_prefix, outside, prefix_only, partial, no_inet, inet
|
|
|
|
};
|
|
|
|
|
|
|
|
char buffer[1024];
|
|
|
|
|
|
|
|
/* skip null oid */
|
|
|
|
for (size_t o = 1; o < ARRAY_SIZE(oids); o++)
|
|
|
|
TEST_BOTH(null, oids[o], null);
|
|
|
|
|
|
|
|
for (size_t o = 0; o < ARRAY_SIZE(oids); o++)
|
|
|
|
TEST_BOTH(oids[o], oids[o], oids[o]);
|
|
|
|
|
|
|
|
TEST_BOTH(partial, no_prefix, partial);
|
|
|
|
TEST_BOTH(partial, prefixed, partial);
|
|
|
|
TEST_BOTH(partial, prefix_only, partial);
|
|
|
|
TEST_BOTH(partial, prefix_only2, partial);
|
|
|
|
|
|
|
|
TEST_BOTH(prefix_only2, prefixed, inet);
|
|
|
|
TEST_BOTH(prefix_only2, no_prefix, inet);
|
|
|
|
|
|
|
|
TEST_BOTH(prefix_only2, inet, inet);
|
|
|
|
|
|
|
|
TEST_BOTH(prefix_only, prefix_only2, inet);
|
|
|
|
|
|
|
|
TEST_BOTH(prefix_only, prefixed, prefix_only);
|
|
|
|
TEST_BOTH(prefix_only, no_prefix, prefix_only);
|
|
|
|
|
|
|
|
TEST_BOTH(prefix_only, inet, inet);
|
|
|
|
|
|
|
|
/* skip null oid */
|
|
|
|
for (size_t o = 1; o < ARRAY_SIZE(oids); o++)
|
|
|
|
{
|
|
|
|
if (oids[o] == outside) continue;
|
|
|
|
|
|
|
|
TEST_BOTH(outside, oids[o], null);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_BOTH(no_inet, partial, partial);
|
|
|
|
TEST_BOTH(no_inet, inet, partial);
|
|
|
|
TEST_BOTH(no_inet, prefix_only, partial);
|
|
|
|
TEST_BOTH(no_inet, prefix_only2, partial);
|
|
|
|
TEST_BOTH(no_inet, prefixed, partial);
|
|
|
|
TEST_BOTH(no_inet, no_prefix, partial);
|
|
|
|
|
|
|
|
TEST_BOTH(shorter, prefixed, shorter);
|
|
|
|
TEST_BOTH(shorter, no_prefix, shorter);
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2024-07-22 16:12:28 +00:00
|
|
|
/* really: static int test_snmp_oid_compare(const struct oid **left, const struct oid **right); */
|
2024-04-22 10:55:33 +00:00
|
|
|
static int
|
|
|
|
test_snmp_oid_compare(const void *left, const void *right)
|
|
|
|
{
|
|
|
|
return snmp_oid_compare(
|
|
|
|
*((const struct oid **) left),
|
|
|
|
*((const struct oid **) right)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
generate_raw_oids(struct oid *oids[], int size, struct oid *(*generator)(void))
|
|
|
|
{
|
|
|
|
for (int i = 0; i < size; i++)
|
|
|
|
{
|
|
|
|
/* binary version of ~5% */
|
|
|
|
if (i > 0 && xrandom(256) <= 13)
|
|
|
|
{
|
|
|
|
/* at this chance, we create a copy instead of generating new oid */
|
|
|
|
oids[i] = tmp_alloc(snmp_oid_size(oids[i-1]));
|
|
|
|
memcpy(oids[i], oids[i-1], snmp_oid_size(oids[i-1]));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
oids[i] = generator();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
generate_oids(struct oid *oids[], struct oid *sorted[], int size, struct oid *(*generator)(void))
|
|
|
|
{
|
|
|
|
generate_raw_oids(oids, size, generator);
|
|
|
|
|
|
|
|
memcpy(sorted, oids, size * sizeof(struct oid *));
|
|
|
|
|
|
|
|
qsort(sorted, (size_t) size, sizeof(struct oid *),
|
|
|
|
test_snmp_oid_compare);
|
|
|
|
|
|
|
|
// test sizes 0, 1, 2, 10, ...
|
|
|
|
int last_used = 0;
|
|
|
|
for (int index = 0; index < size; index++)
|
|
|
|
{
|
|
|
|
if (snmp_oid_compare(sorted[last_used], sorted[index]) != 0)
|
|
|
|
sorted[++last_used] = sorted[index];
|
|
|
|
}
|
|
|
|
|
|
|
|
/* delete old pointers */
|
|
|
|
for (int i = last_used + 1; i < size; i++)
|
|
|
|
sorted[i] = NULL;
|
|
|
|
|
|
|
|
return (size > 1) ? last_used + 1 : size;
|
|
|
|
}
|
|
|
|
|
2024-07-04 14:33:44 +00:00
|
|
|
static int
|
|
|
|
t_walk_oid_desc(void)
|
|
|
|
{
|
|
|
|
lp_state tmps;
|
|
|
|
lp_save(tmp_linpool, &tmps);
|
|
|
|
|
|
|
|
pool *pool = &root_pool;
|
|
|
|
|
|
|
|
struct mib_tree storage, *tree = &storage;
|
|
|
|
mib_tree_init(pool, tree);
|
|
|
|
|
|
|
|
STATIC_ASSERT(ARRAY_SIZE(tree_sizes) > 0);
|
|
|
|
int size = tree_sizes[ARRAY_SIZE(tree_sizes) - 1];
|
|
|
|
ASSERT(size > 0);
|
|
|
|
struct oid **oids = mb_alloc(pool, size * sizeof(struct oid *));
|
|
|
|
struct oid **sorted = mb_alloc(pool, size * sizeof(struct oid *));
|
|
|
|
|
|
|
|
(void) generate_oids(oids, sorted, size, random_oid);
|
|
|
|
|
|
|
|
for (int i = 0; i < size; i++)
|
|
|
|
(void) mib_tree_add(pool, tree, oids[i], 0);
|
|
|
|
|
|
|
|
for (int test = 0; test < size; test++)
|
|
|
|
{
|
|
|
|
int i = xrandom(size);
|
|
|
|
|
|
|
|
char buffer[1024];
|
2024-07-22 16:12:28 +00:00
|
|
|
struct oid *oid = (struct oid *) buffer;
|
2024-07-04 14:33:44 +00:00
|
|
|
|
2024-07-22 16:12:28 +00:00
|
|
|
memcpy(oid, oids[i], snmp_oid_size(oids[i]));
|
2024-07-04 14:33:44 +00:00
|
|
|
|
|
|
|
struct mib_walk_state walk;
|
|
|
|
mib_tree_walk_init(&walk, NULL);
|
|
|
|
(void) mib_tree_find(tree, &walk, oid);
|
|
|
|
|
|
|
|
int type = xrandom(4);
|
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
bt_assert(mib_tree_walk_is_oid_descendant(&walk, oids[i]) == 0);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 1:
|
|
|
|
{
|
|
|
|
/* oid is longer than walk or has same length */
|
|
|
|
u8 ids = LOAD_U8(oid->n_subid);
|
|
|
|
u32 upto = MIN(OID_MAX_LEN - ids, 16);
|
|
|
|
|
|
|
|
if (!upto)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
u32 new = xrandom(upto) + 1;
|
|
|
|
STORE_U8(oid->n_subid, ids + new);
|
|
|
|
|
|
|
|
for (u32 i = 0; i < new; i++)
|
|
|
|
STORE_U32(oid->ids[ids + i], xrandom(OID_MAX_ID));
|
|
|
|
|
|
|
|
bt_assert(mib_tree_walk_is_oid_descendant(&walk, oid) > 0);
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 2:
|
|
|
|
case 3:
|
|
|
|
{
|
|
|
|
/* oid is shorter than walk */
|
|
|
|
u8 ids = LOAD_U8(oid->n_subid);
|
|
|
|
|
|
|
|
if (ids == 0 || ids == OID_MAX_LEN)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
u32 split = (ids > 1) ? xrandom(ids - 1) + 1 : 0;
|
|
|
|
u32 ext = (type == 3) ? xrandom(MIN(OID_MAX_LEN - ids, 16)) : 0;
|
|
|
|
|
|
|
|
STORE_U16(oid->n_subid, split + ext);
|
|
|
|
for (u32 i = 0; i < ext; i++)
|
|
|
|
STORE_U32(oid->ids[split + i], xrandom(OID_MAX_ID));
|
|
|
|
|
|
|
|
int no_change = 1;
|
2024-07-22 16:12:28 +00:00
|
|
|
for (u32 j = 0; j < MIN(ids - split, ext); j++)
|
2024-07-04 14:33:44 +00:00
|
|
|
{
|
|
|
|
if (LOAD_U32(oid->ids[split + j]) != LOAD_U32(oids[i]->ids[split + j]))
|
2024-07-22 16:12:28 +00:00
|
|
|
no_change = 0;
|
2024-07-04 14:33:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (no_change)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
bt_assert(mib_tree_walk_is_oid_descendant(&walk, oid) < 0);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
struct mib_walk_state walk;
|
|
|
|
mib_tree_walk_init(&walk, tree);
|
|
|
|
|
|
|
|
u32 zero = 0;
|
2024-07-22 16:12:28 +00:00
|
|
|
const struct oid *null_oid = (struct oid *) &zero;
|
2024-07-04 14:33:44 +00:00
|
|
|
u32 index = xrandom(size);
|
|
|
|
|
|
|
|
bt_assert(mib_tree_walk_is_oid_descendant(&walk, null_oid) == 0);
|
|
|
|
bt_assert(mib_tree_walk_is_oid_descendant(&walk, oids[index]) > 0);
|
|
|
|
(void) mib_tree_find(tree, &walk, oids[index]);
|
|
|
|
bt_assert(mib_tree_walk_is_oid_descendant(&walk, null_oid) < 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
u32 null_oid = 0;
|
|
|
|
mib_tree_remove(tree, (struct oid *) &null_oid);
|
|
|
|
lp_restore(tmp_linpool, &tmps);
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2024-07-22 16:12:28 +00:00
|
|
|
static int
|
|
|
|
t_walk_oid_compare(void)
|
|
|
|
{
|
|
|
|
lp_state tmps;
|
|
|
|
lp_save(tmp_linpool, &tmps);
|
|
|
|
|
|
|
|
pool *pool = &root_pool;
|
|
|
|
|
|
|
|
struct mib_tree storage, *tree = &storage;
|
|
|
|
mib_tree_init(pool, tree);
|
|
|
|
|
|
|
|
STATIC_ASSERT(ARRAY_SIZE(tree_sizes) > 0);
|
|
|
|
int size = tree_sizes[ARRAY_SIZE(tree_sizes) - 1];
|
|
|
|
ASSERT(size > 0);
|
|
|
|
struct oid **oids = mb_alloc(pool, size * sizeof(struct oid *));
|
|
|
|
struct oid **sorted = mb_alloc(pool, size * sizeof(struct oid *));
|
|
|
|
|
|
|
|
(void) generate_oids(oids, sorted, size, random_oid);
|
|
|
|
|
|
|
|
for (int i = 0; i < size; i++)
|
|
|
|
(void) mib_tree_add(pool, tree, oids[i], 0);
|
|
|
|
|
|
|
|
for (int test = 0; test < size; test++)
|
|
|
|
{
|
|
|
|
int i = xrandom(size);
|
|
|
|
|
|
|
|
char buffer[1024];
|
|
|
|
struct oid *oid = (struct oid *) buffer;
|
|
|
|
|
|
|
|
memcpy(oid, oids[i], snmp_oid_size(oids[i]));
|
|
|
|
|
|
|
|
struct mib_walk_state walk;
|
|
|
|
mib_tree_walk_init(&walk, NULL);
|
|
|
|
(void) mib_tree_find(tree, &walk, oids[i]);
|
|
|
|
|
|
|
|
int type = xrandom(4);
|
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
bt_assert(mib_tree_walk_oid_compare(&walk, oids[i]) == 0);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 1:
|
|
|
|
{
|
|
|
|
/* oid is longer than walk or has same length */
|
|
|
|
u8 ids = LOAD_U8(oid->n_subid);
|
|
|
|
u32 upto = MIN(OID_MAX_LEN - ids, 16);
|
|
|
|
|
|
|
|
if (!upto)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
u32 new = xrandom(upto) + 1;
|
|
|
|
STORE_U8(oid->n_subid, ids + new);
|
|
|
|
ASSERT(snmp_oid_size(oid) < 1024);
|
|
|
|
|
|
|
|
for (u32 i = 0; i < new; i++)
|
|
|
|
STORE_U32(oid->ids[ids + i], xrandom(OID_MAX_ID));
|
|
|
|
|
|
|
|
|
|
|
|
bt_assert(mib_tree_walk_oid_compare(&walk, oid) < 0);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 2:
|
|
|
|
case 3:
|
|
|
|
{
|
|
|
|
/* oid is shorter than walk */
|
|
|
|
u8 ids = LOAD_U8(oid->n_subid);
|
|
|
|
|
|
|
|
if (ids == 0 || ids == OID_MAX_LEN)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
u32 split = (ids > 1) ? xrandom(ids - 1) + 1 : 0;
|
|
|
|
u32 ext = (type == 3) ? xrandom(MIN(OID_MAX_LEN - ids, 16)) : 0;
|
|
|
|
|
|
|
|
STORE_U16(oid->n_subid, split + ext);
|
|
|
|
for (u32 i = 0; i < ext; i++)
|
|
|
|
STORE_U32(oid->ids[split + i], xrandom(OID_MAX_ID));
|
|
|
|
|
|
|
|
int cmp_res = 0;
|
|
|
|
for (u32 j = 0; j < MIN(ids - split, ext) && !cmp_res; j++)
|
|
|
|
cmp_res = LOAD_U32(oids[i]->ids[split + j]) - LOAD_U32(oid->ids[split + j]);
|
|
|
|
|
|
|
|
if (!cmp_res && split + ext == ids)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!cmp_res && split < ids && ext == 0)
|
|
|
|
cmp_res = +1;
|
|
|
|
|
|
|
|
if (!cmp_res && split < ids && split + ext > ids)
|
|
|
|
cmp_res = -1;
|
|
|
|
|
|
|
|
if (cmp_res < 0)
|
|
|
|
cmp_res = -1;
|
|
|
|
else if (cmp_res > 0)
|
|
|
|
cmp_res = +1;
|
|
|
|
|
|
|
|
bt_assert(mib_tree_walk_oid_compare(&walk, oid) == cmp_res);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
struct mib_walk_state walk;
|
|
|
|
mib_tree_walk_init(&walk, tree);
|
|
|
|
|
|
|
|
u32 zero = 0;
|
|
|
|
const struct oid *null_oid = (struct oid *) &zero;
|
|
|
|
u32 index = xrandom(size);
|
|
|
|
|
|
|
|
bt_assert(mib_tree_walk_oid_compare(&walk, null_oid) == 0);
|
|
|
|
bt_assert(mib_tree_walk_oid_compare(&walk, oids[index]) < 0);
|
|
|
|
(void) mib_tree_find(tree, &walk, oids[index]);
|
|
|
|
bt_assert(mib_tree_walk_oid_compare(&walk, null_oid) > 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
u32 null_oid = 0;
|
|
|
|
mib_tree_remove(tree, (struct oid *) &null_oid);
|
|
|
|
lp_restore(tmp_linpool, &tmps);
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
static void UNUSED
|
|
|
|
print_dups(const struct oid *oids[], uint size)
|
|
|
|
{
|
|
|
|
for (uint i = 0; i < size; i++)
|
|
|
|
for (uint j = i + 1; j < size; j++)
|
|
|
|
if (snmp_oid_compare(oids[i], oids[j]) == 0)
|
|
|
|
log(L_WARN "pair (%u, %u)", i, j);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void UNUSED
|
|
|
|
print_all(const struct oid *oids[], uint size)
|
|
|
|
{
|
|
|
|
for (uint i = 0; i < size; i++)
|
|
|
|
snmp_oid_log(oids[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int
|
|
|
|
oid_is_leaf(const struct oid *oid, const struct oid *leafs[], uint leaf_idx)
|
|
|
|
{
|
|
|
|
for (uint l = 0; l < leaf_idx; l++)
|
|
|
|
if (snmp_oid_compare(oid, leafs[l]) == 0)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
all_invalid(const struct oid *oids[], const byte *invalid, uint size, uint index)
|
|
|
|
{
|
|
|
|
if (!invalid[index])
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
for (uint i = 0; i < size; i++)
|
|
|
|
{
|
|
|
|
if (i == index) continue;
|
|
|
|
|
|
|
|
if (snmp_oid_compare(oids[i], oids[index]) == 0 &&
|
|
|
|
!invalid[i])
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
count_error(const struct oid *oids[], const byte *invalid, uint size)
|
|
|
|
{
|
|
|
|
int error = 0;
|
|
|
|
for (uint i = 0; i < size; i++)
|
|
|
|
{
|
|
|
|
if (!invalid[i]) continue;
|
|
|
|
|
|
|
|
int skip = 0;
|
|
|
|
for (uint j = 0; j < i; j++)
|
|
|
|
{
|
|
|
|
if (snmp_oid_compare(oids[i], oids[j]) == 0)
|
|
|
|
{
|
|
|
|
skip = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (skip) continue;
|
|
|
|
|
|
|
|
if (all_invalid(oids, invalid, size, i))
|
|
|
|
error++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
gen_test_add(struct oid *(*generator)(void))
|
|
|
|
{
|
|
|
|
lp_state tmps;
|
|
|
|
lp_save(tmp_linpool, &tmps);
|
|
|
|
|
|
|
|
pool *pool = &root_pool;
|
|
|
|
|
|
|
|
for (int test = 0; test < TESTS_NUM; test++)
|
|
|
|
{
|
|
|
|
size_t tsz = ARRAY_SIZE(tree_sizes);
|
|
|
|
|
|
|
|
int size = tree_sizes[test % tsz];
|
|
|
|
int with_leafs = (test % (2 * tsz)) < tsz;
|
|
|
|
int no_inet_prefix = (test % (4 * tsz)) < (2 * tsz);
|
|
|
|
|
|
|
|
struct oid **oids = mb_alloc(pool, size * sizeof(struct oid *));
|
|
|
|
byte *types = mb_alloc(pool, size * sizeof(byte));
|
2024-05-21 13:43:41 +00:00
|
|
|
byte *invalid_hist = mb_alloc(pool, size * sizeof(byte));
|
2024-04-22 10:55:33 +00:00
|
|
|
struct oid **sorted = mb_alloc(pool, size * sizeof(struct oid *));
|
|
|
|
struct oid **leafs = (with_leafs) ? mb_alloc(pool, size * sizeof(struct oid *))
|
|
|
|
: NULL;
|
|
|
|
int leaf_idx = 0;
|
|
|
|
int empty_prefix_added = 0;
|
|
|
|
int distinct = generate_oids(oids, sorted, size, generator);
|
|
|
|
|
|
|
|
struct mib_tree storage, *tree = &storage;
|
|
|
|
mib_tree_init(pool, tree);
|
|
|
|
|
|
|
|
if (no_inet_prefix)
|
|
|
|
{
|
|
|
|
/* remove the node .1 and all children */
|
|
|
|
const struct oid *inet_pref = oid_create(1, 0, 0, /* ids */ 1);
|
|
|
|
mib_tree_remove(tree, inet_pref);
|
|
|
|
}
|
|
|
|
|
|
|
|
int invalid_counter = 0;
|
|
|
|
int counter = 0;
|
|
|
|
int cut = 0;
|
|
|
|
for (int i = 0; i < size; i++)
|
|
|
|
{
|
|
|
|
int invalid = 0;
|
|
|
|
int is_leaf = (with_leafs) ? (int) xrandom(2) : 0;
|
|
|
|
types[i] = (byte) is_leaf;
|
|
|
|
|
|
|
|
int will_cut = 0;
|
|
|
|
int oid_nulled = snmp_is_oid_empty(oids[i]);
|
|
|
|
|
|
|
|
if (oid_nulled && is_leaf)
|
|
|
|
invalid = 1;
|
|
|
|
|
2024-05-21 13:43:41 +00:00
|
|
|
if (!no_inet_prefix)
|
|
|
|
{
|
|
|
|
char buffer[1024];
|
2024-07-22 16:12:28 +00:00
|
|
|
struct oid *o = (struct oid *) buffer;
|
2024-05-21 13:43:41 +00:00
|
|
|
|
|
|
|
struct oid *inet = oid_create(4, 0, 0, /* ids */ 1, 3, 6, 1);
|
|
|
|
snmp_oid_common_ancestor(oids[i], inet, o);
|
|
|
|
|
|
|
|
/* If the standard internet prefix is present,
|
|
|
|
* then the prefix leafs are invalid. */
|
|
|
|
if (snmp_oid_compare(oids[i], o) == 0)
|
|
|
|
invalid = is_leaf;
|
|
|
|
}
|
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
/* check existence of ancestor node of a new leaf */
|
|
|
|
for (int oi = 0; !invalid && !oid_nulled && oi < i; oi++)
|
|
|
|
{
|
|
|
|
char buffer[1024];
|
2024-07-22 16:12:28 +00:00
|
|
|
struct oid *o = (struct oid *) buffer;
|
2024-04-22 10:55:33 +00:00
|
|
|
|
|
|
|
if (invalid_hist[oi])
|
|
|
|
continue;
|
|
|
|
|
|
|
|
int other_is_leaf = (int) types[oi];
|
|
|
|
|
|
|
|
if (snmp_oid_compare(oids[oi], oids[i]) == 0 &&
|
|
|
|
!snmp_is_oid_empty(oids[i]))
|
|
|
|
{
|
|
|
|
if (other_is_leaf == is_leaf)
|
|
|
|
will_cut = 1;
|
|
|
|
else if (other_is_leaf != is_leaf)
|
|
|
|
invalid = 1;
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
snmp_oid_common_ancestor(oids[oi], oids[i], o);
|
|
|
|
|
|
|
|
if ((snmp_oid_compare(oids[i], o) == 0 && is_leaf) ||
|
|
|
|
(snmp_oid_compare(oids[oi], o) == 0 && other_is_leaf))
|
|
|
|
{
|
|
|
|
invalid = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!invalid && will_cut)
|
|
|
|
cut++;
|
|
|
|
|
|
|
|
if (is_leaf && !invalid)
|
|
|
|
/* leafs could have duplicates */
|
|
|
|
leafs[leaf_idx++] = oids[i];
|
|
|
|
|
|
|
|
mib_node_u *node = mib_tree_add(pool, tree, oids[i], is_leaf);
|
|
|
|
|
|
|
|
bt_assert((node == NULL) == invalid);
|
|
|
|
|
|
|
|
invalid_hist[i] = 0;
|
|
|
|
if (invalid)
|
|
|
|
{
|
|
|
|
invalid_hist[i] = 1;
|
|
|
|
invalid_counter++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (node != NULL && (!snmp_is_oid_empty(oids[i]) || !empty_prefix_added))
|
|
|
|
counter++;
|
|
|
|
|
|
|
|
if (snmp_is_oid_empty(oids[i]) && !is_leaf)
|
|
|
|
empty_prefix_added = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int error = count_error((const struct oid **) oids, invalid_hist, size);
|
|
|
|
bt_assert(counter - cut == distinct - error);
|
|
|
|
|
|
|
|
lp_restore(tmp_linpool, &tmps);
|
|
|
|
mb_free(oids);
|
|
|
|
mb_free(sorted);
|
|
|
|
mb_free(leafs);
|
|
|
|
}
|
2022-11-29 15:30:20 +00:00
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2022-11-05 15:29:00 +00:00
|
|
|
static int
|
2024-04-22 10:55:33 +00:00
|
|
|
t_tree_add(void)
|
2022-11-05 15:29:00 +00:00
|
|
|
{
|
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
gen_test_add(random_prefixed_oid);
|
|
|
|
gen_test_add(random_no_prefix_oid);
|
|
|
|
gen_test_add(random_prefixable_oid);
|
|
|
|
gen_test_add(random_oid);
|
2022-11-05 15:29:00 +00:00
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
return 1;
|
|
|
|
}
|
2022-11-05 15:29:00 +00:00
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
static int
|
|
|
|
gen_test_find(struct oid *(*generator)(void))
|
|
|
|
{
|
|
|
|
lp_state tmps;
|
|
|
|
lp_save(tmp_linpool, &tmps);
|
2022-11-05 15:29:00 +00:00
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
pool *pool = &root_pool;
|
2022-11-05 15:29:00 +00:00
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
for (int test = 0; test < TESTS_NUM; test++)
|
|
|
|
{
|
|
|
|
size_t tsz = ARRAY_SIZE(tree_sizes);
|
|
|
|
|
|
|
|
int size = tree_sizes[test % tsz];
|
|
|
|
int with_leafs = (test % (2 * tsz)) < tsz;
|
|
|
|
int no_inet_prefix = (test % (4 * tsz)) < (2 * tsz);
|
|
|
|
|
|
|
|
struct oid **oids = mb_alloc(pool, size * sizeof(struct oid *));
|
|
|
|
mib_node_u **nodes = mb_alloc(pool, size * sizeof(mib_node_u *));
|
|
|
|
struct oid **searched = mb_alloc(pool, size * sizeof(struct oid *));
|
|
|
|
byte *types = mb_alloc(pool, size * sizeof(byte));
|
|
|
|
|
|
|
|
/* enough to hold snmp_internet copy */
|
|
|
|
uint longest_inet_pref_len = 0;
|
|
|
|
struct oid *longest_inet_pref = oid_create(4, 0, 0, /* ids */ 0, 0, 0, 0);
|
|
|
|
|
|
|
|
generate_raw_oids(oids, size, generator);
|
|
|
|
generate_raw_oids(searched, size, generator);
|
|
|
|
|
|
|
|
struct mib_tree storage, *tree = &storage;
|
|
|
|
mib_tree_init(pool, tree);
|
|
|
|
|
|
|
|
if (no_inet_prefix)
|
|
|
|
{
|
|
|
|
/* remove the node .1 and all children */
|
|
|
|
const struct oid *inet_pref = oid_create(1, 0, 0, /* ids */ 1);
|
|
|
|
mib_tree_remove(tree, inet_pref);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < size; i++)
|
|
|
|
types[i] = (byte) ((with_leafs) ? xrandom(2) : 0);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* by default initialized MIB tree will have internet prefix have inserted
|
|
|
|
*/
|
|
|
|
if (!no_inet_prefix)
|
|
|
|
{
|
|
|
|
memcpy(longest_inet_pref->ids, snmp_internet, sizeof(snmp_internet));
|
|
|
|
longest_inet_pref_len = 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < size; i++)
|
|
|
|
{
|
|
|
|
nodes[i] = mib_tree_add(pool, tree, oids[i], types[i]);
|
|
|
|
|
|
|
|
if (nodes[i] == NULL) continue;
|
|
|
|
|
|
|
|
if (snmp_oid_is_prefixed(oids[i]))
|
|
|
|
{
|
|
|
|
memcpy(longest_inet_pref->ids, snmp_internet, sizeof(snmp_internet));
|
|
|
|
longest_inet_pref_len = 4;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (uint j = 0; j < MIN(LOAD_U8(oids[i]->n_subid),
|
|
|
|
ARRAY_SIZE(snmp_internet)); j++)
|
|
|
|
{
|
|
|
|
if (LOAD_U32(oids[i]->ids[j]) == snmp_internet[j] &&
|
|
|
|
j >= longest_inet_pref_len)
|
|
|
|
{
|
|
|
|
longest_inet_pref->ids[j] = snmp_internet[j];
|
|
|
|
longest_inet_pref_len = j + 1;
|
|
|
|
}
|
|
|
|
else if (LOAD_U32(oids[i]->ids[j]) == snmp_internet[j])
|
|
|
|
;
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < size; i++)
|
|
|
|
{
|
|
|
|
for (int j = 0; j < size; j++)
|
|
|
|
{
|
|
|
|
if (nodes[i] != NULL &&
|
|
|
|
nodes[j] != NULL &&
|
|
|
|
snmp_oid_compare(oids[i], oids[j]) == 0)
|
|
|
|
bt_assert(nodes[i] == nodes[j]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-21 13:43:41 +00:00
|
|
|
mib_node_u *last = NULL;
|
2024-04-22 10:55:33 +00:00
|
|
|
for (int i = 0; i < size; i++)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* This solves cases where we tried to insert
|
|
|
|
* both leaf and inner node for same OID.
|
|
|
|
* Result of insertion should be NULL in cases
|
|
|
|
* when the insertion is inconsistent with the current tree state.
|
|
|
|
* (the first insertion wins)
|
|
|
|
*/
|
|
|
|
int expected_precise = 1;
|
|
|
|
mib_node_u *expected = nodes[i];
|
2024-05-21 13:43:41 +00:00
|
|
|
|
|
|
|
if (!no_inet_prefix)
|
|
|
|
{
|
|
|
|
char buf[1024];
|
2024-07-22 16:12:28 +00:00
|
|
|
struct oid *o = (struct oid *) buf;
|
2024-05-21 13:43:41 +00:00
|
|
|
snmp_oid_common_ancestor(oids[i], longest_inet_pref, o);
|
|
|
|
if (snmp_oid_compare(oids[i], o) == 0)
|
|
|
|
expected_precise = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (snmp_is_oid_empty(oids[i]))
|
|
|
|
{
|
|
|
|
expected_precise = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int j = 0; expected_precise && j < size; j++)
|
2024-04-22 10:55:33 +00:00
|
|
|
{
|
|
|
|
if (i == j) continue;
|
|
|
|
|
|
|
|
if (snmp_oid_compare(oids[i], oids[j]) == 0 &&
|
|
|
|
types[i] != types[j] && nodes[i] == NULL)
|
|
|
|
{
|
2024-05-21 13:43:41 +00:00
|
|
|
if (nodes[j] != NULL)
|
|
|
|
{
|
|
|
|
expected = nodes[j];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* else expected = NULL; */
|
2024-04-22 10:55:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
char buf[1024];
|
2024-07-22 16:12:28 +00:00
|
|
|
struct oid *o = (struct oid *) buf;
|
2024-04-22 10:55:33 +00:00
|
|
|
|
|
|
|
snmp_oid_common_ancestor(oids[i], oids[j], o);
|
|
|
|
|
|
|
|
/* oids[j] lies on path from root to oids[i] */
|
|
|
|
if (snmp_oid_compare(oids[i], o) == 0 &&
|
|
|
|
nodes[j] != NULL &&
|
|
|
|
expected == NULL)
|
|
|
|
{
|
|
|
|
expected_precise = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-21 13:43:41 +00:00
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
struct mib_walk_state walk;
|
2024-05-21 13:43:41 +00:00
|
|
|
//mib_tree_walk_init(&walk, tree, 0);
|
|
|
|
mib_tree_walk_init(&walk, NULL);
|
2024-04-22 10:55:33 +00:00
|
|
|
mib_node_u *found = mib_tree_find(tree, &walk, oids[i]);
|
|
|
|
|
2024-05-21 13:43:41 +00:00
|
|
|
bt_assert(walk.stack_pos <= MIB_WALK_STACK_SIZE + 1);
|
|
|
|
bt_assert(walk.id_pos <= OID_MAX_LEN);
|
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
if (expected_precise)
|
|
|
|
bt_assert(found == expected);
|
|
|
|
else
|
|
|
|
/* found is an auto-inserted node on path to some dest OID */
|
|
|
|
bt_assert(found != NULL);
|
2024-05-21 13:43:41 +00:00
|
|
|
|
|
|
|
last = found;
|
|
|
|
|
|
|
|
/* test finding with walk state not pointing at the root of the tree */
|
2024-05-24 13:20:30 +00:00
|
|
|
u8 subids = LOAD_U8(oids[i]->n_subid);
|
2024-05-21 13:43:41 +00:00
|
|
|
if (subids > 0)
|
|
|
|
{
|
|
|
|
found = NULL;
|
|
|
|
u32 new_ids = xrandom(subids);
|
|
|
|
mib_tree_walk_init(&walk, (xrandom(2)) ? tree : NULL);
|
|
|
|
|
|
|
|
STORE_U8(oids[i]->n_subid, new_ids);
|
|
|
|
|
|
|
|
mib_node_u *ignored UNUSED;
|
|
|
|
ignored = mib_tree_find(tree, &walk, oids[i]);
|
|
|
|
|
|
|
|
STORE_U8(oids[i]->n_subid, subids);
|
|
|
|
|
|
|
|
found = mib_tree_find(tree, &walk, oids[i]);
|
|
|
|
|
|
|
|
/* see above */
|
|
|
|
if (expected_precise)
|
|
|
|
bt_assert(found == expected);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* test that the result is same as direct searched from tree root */
|
|
|
|
bt_assert(found == last);
|
|
|
|
bt_assert(found != NULL);
|
|
|
|
}
|
|
|
|
}
|
2024-04-22 10:55:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (int search = 0; search < size; search++)
|
|
|
|
{
|
|
|
|
int has_node = 0;
|
|
|
|
for (int stored = 0; stored < size; stored++)
|
|
|
|
{
|
|
|
|
char buf[1024];
|
2024-07-22 16:12:28 +00:00
|
|
|
struct oid *o = (struct oid *) buf;
|
2024-04-22 10:55:33 +00:00
|
|
|
snmp_oid_common_ancestor(oids[stored], searched[search], o);
|
|
|
|
|
2024-05-21 13:43:41 +00:00
|
|
|
/* test if OID oids[stored] is valid and if it forms a path from root
|
|
|
|
* with OID searched[search] */
|
2024-04-22 10:55:33 +00:00
|
|
|
if (nodes[stored] != NULL && snmp_oid_compare(searched[search], o) == 0)
|
|
|
|
{
|
|
|
|
has_node = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const struct oid *oid = searched[search];
|
|
|
|
if (!has_node && !snmp_oid_is_prefixed(oid))
|
|
|
|
{
|
|
|
|
for (uint i = 0; i < MIN(ARRAY_SIZE(snmp_internet),
|
|
|
|
LOAD_U8(oid->n_subid)); i++)
|
|
|
|
{
|
|
|
|
if (longest_inet_pref->ids[i] != 0 &&
|
|
|
|
longest_inet_pref->ids[i] == oid->ids[i])
|
|
|
|
has_node = 1;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
has_node = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (has_node && LOAD_U8(oid->n_subid) > ARRAY_SIZE(snmp_internet))
|
|
|
|
has_node = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct mib_walk_state walk;
|
2024-05-21 13:43:41 +00:00
|
|
|
mib_tree_walk_init(&walk, NULL);
|
|
|
|
//mib_tree_walk_init(&walk, tree); /* TODO should work also like this */
|
2024-04-22 10:55:33 +00:00
|
|
|
mib_node_u *found = mib_tree_find(tree, &walk, searched[search]);
|
|
|
|
bt_assert(has_node == (found != NULL));
|
2024-05-21 13:43:41 +00:00
|
|
|
|
|
|
|
bt_assert(walk.stack_pos <= MIB_WALK_STACK_SIZE + 1);
|
|
|
|
bt_assert(walk.id_pos <= OID_MAX_LEN);
|
|
|
|
|
|
|
|
last = found;
|
|
|
|
|
|
|
|
u8 subids = LOAD_U8(searched[search]->n_subid);
|
|
|
|
if (subids > 0)
|
|
|
|
{
|
|
|
|
found = NULL;
|
|
|
|
u32 new_ids = xrandom(subids);
|
|
|
|
mib_tree_walk_init(&walk, (xrandom(2)) ? tree : NULL);
|
|
|
|
|
|
|
|
STORE_U8(searched[search]->n_subid, new_ids);
|
2024-05-24 13:20:30 +00:00
|
|
|
|
2024-05-21 13:43:41 +00:00
|
|
|
mib_node_u *ignored UNUSED;
|
|
|
|
ignored = mib_tree_find(tree, &walk, searched[search]);
|
2024-05-24 13:20:30 +00:00
|
|
|
|
2024-05-21 13:43:41 +00:00
|
|
|
STORE_U8(searched[search]->n_subid, subids);
|
|
|
|
|
|
|
|
found = mib_tree_find(tree, &walk, searched[search]);
|
|
|
|
|
|
|
|
bt_assert(has_node == (found != NULL));
|
|
|
|
|
|
|
|
bt_assert(walk.stack_pos <= MIB_WALK_STACK_SIZE + 1);
|
|
|
|
bt_assert(walk.id_pos <= OID_MAX_LEN);
|
|
|
|
|
|
|
|
/* test that the result is same as direct search from tree root */
|
|
|
|
bt_assert(last == found);
|
|
|
|
}
|
2024-04-22 10:55:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
lp_restore(tmp_linpool, &tmps);
|
|
|
|
mb_free(oids);
|
|
|
|
mb_free(nodes);
|
|
|
|
mb_free(searched);
|
|
|
|
mb_free(types);
|
|
|
|
}
|
2022-11-05 15:29:00 +00:00
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
tmp_flush();
|
|
|
|
return 1;
|
|
|
|
}
|
2022-11-05 15:29:00 +00:00
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
static int
|
|
|
|
t_tree_find(void)
|
|
|
|
{
|
2022-11-05 15:29:00 +00:00
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
gen_test_find(random_prefixed_oid);
|
|
|
|
gen_test_find(random_no_prefix_oid);
|
|
|
|
gen_test_find(random_prefixable_oid);
|
|
|
|
gen_test_find(random_oid);
|
2023-03-31 07:56:03 +00:00
|
|
|
|
2022-11-05 15:29:00 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2024-05-21 13:43:41 +00:00
|
|
|
#if 0
|
2024-04-22 10:55:33 +00:00
|
|
|
static int
|
|
|
|
delete_cleanup(const struct oid *oid, struct oid *oids[], mib_node_u *valid[], int size)
|
|
|
|
{
|
|
|
|
uint counter = 0;
|
|
|
|
for (int i = 0; i < size; i++)
|
|
|
|
{
|
|
|
|
char buf[1024];
|
2024-07-22 16:12:28 +00:00
|
|
|
struct oid *o = (struct oid *) buf;
|
2024-04-22 10:55:33 +00:00
|
|
|
|
|
|
|
if (oid == oids[i])
|
|
|
|
{
|
|
|
|
counter++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
snmp_oid_common_ancestor(oid, oids[i], o);
|
|
|
|
|
|
|
|
if (snmp_oid_compare(oid, o) == 0)
|
|
|
|
{
|
|
|
|
valid[i] = NULL;
|
|
|
|
counter++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return counter;
|
|
|
|
}
|
2024-05-21 13:43:41 +00:00
|
|
|
#endif
|
2024-04-22 10:55:33 +00:00
|
|
|
|
|
|
|
static int
|
2024-05-21 13:43:41 +00:00
|
|
|
gen_test_delete_remove(struct oid *(*generator)(void), int remove)
|
2024-04-22 10:55:33 +00:00
|
|
|
{
|
|
|
|
lp_state tmps;
|
|
|
|
lp_save(tmp_linpool, &tmps);
|
|
|
|
|
|
|
|
pool *pool = &root_pool;
|
|
|
|
|
|
|
|
for (int test = 0; test < TESTS_NUM; test++)
|
|
|
|
{
|
|
|
|
size_t tsz = ARRAY_SIZE(tree_sizes);
|
|
|
|
|
|
|
|
int size = tree_sizes[test % tsz];
|
|
|
|
int with_leafs = (test % (2 * tsz)) < tsz;
|
2024-05-21 13:43:41 +00:00
|
|
|
int no_inet_prefix = (test % (4 * tsz)) < (2 * tsz);
|
2024-04-22 10:55:33 +00:00
|
|
|
|
|
|
|
struct oid **oids = mb_alloc(pool, size * sizeof(struct oid *));
|
2024-05-21 13:43:41 +00:00
|
|
|
struct oid **sorted = mb_alloc(pool, size * sizeof(struct oid *));
|
|
|
|
mib_node_u **nodes = mb_alloc(pool, size * sizeof(mib_node_u *));
|
2024-04-22 10:55:33 +00:00
|
|
|
byte *types = mb_alloc(pool, size * sizeof(byte));
|
|
|
|
|
|
|
|
struct mib_tree storage, *tree = &storage;
|
2024-05-21 13:43:41 +00:00
|
|
|
mib_tree_init(pool, tree);
|
2024-04-22 10:55:33 +00:00
|
|
|
|
2024-05-21 13:43:41 +00:00
|
|
|
if (no_inet_prefix)
|
|
|
|
{
|
|
|
|
/* remove the node .1 and all children */
|
|
|
|
const struct oid *inet_pref = oid_create(1, 0, 0, /* ids */ 1);
|
|
|
|
mib_tree_remove(tree, inet_pref);
|
|
|
|
}
|
|
|
|
|
|
|
|
int distinct = generate_oids(oids, sorted, size, generator);
|
2024-04-22 10:55:33 +00:00
|
|
|
|
|
|
|
for (int i = 0; i < size; i++)
|
|
|
|
{
|
|
|
|
int is_leaf;
|
|
|
|
is_leaf = types[i] = (byte) (with_leafs) ? xrandom(2) : 0;
|
2024-05-21 13:43:41 +00:00
|
|
|
(void) mib_tree_add(pool, tree, oids[i], is_leaf);
|
2024-04-22 10:55:33 +00:00
|
|
|
}
|
|
|
|
|
2024-05-21 13:43:41 +00:00
|
|
|
for (int d = 0; d < distinct; d++)
|
2024-04-22 10:55:33 +00:00
|
|
|
{
|
2024-05-21 13:43:41 +00:00
|
|
|
struct mib_walk_state walk;
|
|
|
|
mib_tree_walk_init(&walk, NULL);
|
|
|
|
//mib_tree_walk_init(&walk, tree); TODO
|
|
|
|
nodes[d] = mib_tree_find(tree, &walk, sorted[d]);
|
|
|
|
}
|
2024-04-22 10:55:33 +00:00
|
|
|
|
2024-05-21 13:43:41 +00:00
|
|
|
/* we need to populate the nodes array after all insertions because
|
|
|
|
* some insertion may fail (== NULL) because we try to insert a leaf */
|
|
|
|
#if 0
|
|
|
|
for (int i = 0; i < size; i++)
|
|
|
|
{
|
|
|
|
struct mib_walk_state walk;
|
|
|
|
mib_tree_walk_init(&walk, tree, 0);
|
|
|
|
nodes[i] = mib_tree_find(tree, &walk, oids[i]);
|
|
|
|
}
|
|
|
|
#endif
|
2024-04-22 10:55:33 +00:00
|
|
|
|
2024-05-21 13:43:41 +00:00
|
|
|
int deleted, invalid_counter;
|
|
|
|
/* test deletion one of the inserted OIDs */
|
|
|
|
for (int round = 0; round < (size + 3) / 4 + remove; round++)
|
|
|
|
{
|
|
|
|
/* note: we do not run any rounds for size zero because xrandom(0)
|
|
|
|
* does not exist */
|
|
|
|
int i;
|
|
|
|
struct oid *oid;
|
|
|
|
if (!remove)
|
2024-04-22 10:55:33 +00:00
|
|
|
{
|
2024-05-21 13:43:41 +00:00
|
|
|
/* this way we are also testing remove non-existent tree nodes */
|
|
|
|
i = xrandom(size); /* not xrandom(distinct) */
|
|
|
|
oid = oids[i];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
i = -1; /* break fast */
|
|
|
|
oid = generator();
|
|
|
|
}
|
2024-04-22 10:55:33 +00:00
|
|
|
|
2024-05-21 13:43:41 +00:00
|
|
|
struct mib_walk_state walk;
|
|
|
|
mib_tree_walk_init(&walk, NULL);
|
|
|
|
// mib_tree_walk_init(&walk, tree); TODO
|
|
|
|
mib_node_u *node = mib_tree_find(tree, &walk, oid);
|
|
|
|
|
|
|
|
if (node == NULL)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!remove)
|
|
|
|
deleted = mib_tree_delete(tree, &walk);
|
|
|
|
else
|
|
|
|
deleted = mib_tree_remove(tree, oid);
|
2024-04-22 10:55:33 +00:00
|
|
|
|
2024-05-21 13:43:41 +00:00
|
|
|
bt_assert(deleted > 0 || snmp_is_oid_empty(oid));
|
2024-04-22 10:55:33 +00:00
|
|
|
|
2024-05-21 13:43:41 +00:00
|
|
|
invalid_counter = 0;
|
|
|
|
int counted_removed = 0;
|
|
|
|
for (int j = 0; j < distinct; j++)
|
|
|
|
{
|
|
|
|
//mib_tree_walk_init(&walk, tree, 0);
|
|
|
|
mib_tree_walk_init(&walk, NULL);
|
|
|
|
mib_node_u *node = mib_tree_find(tree, &walk, sorted[j]);
|
2024-05-24 13:20:30 +00:00
|
|
|
|
2024-05-21 13:43:41 +00:00
|
|
|
if (snmp_is_oid_empty(oid))
|
|
|
|
;
|
|
|
|
/* the oid could have multiple instances in the oids dataset */
|
|
|
|
else if (snmp_oid_compare(oid, sorted[j]) == 0 && !counted_removed)
|
2024-04-22 10:55:33 +00:00
|
|
|
{
|
2024-05-21 13:43:41 +00:00
|
|
|
invalid_counter++;
|
|
|
|
counted_removed = 1;
|
|
|
|
bt_assert(node == NULL);
|
2024-04-22 10:55:33 +00:00
|
|
|
nodes[j] = NULL;
|
2024-05-21 13:43:41 +00:00
|
|
|
}
|
|
|
|
else if (node != nodes[j])
|
|
|
|
{
|
2024-04-22 10:55:33 +00:00
|
|
|
invalid_counter++;
|
2024-05-21 13:43:41 +00:00
|
|
|
bt_assert(node == NULL);
|
|
|
|
nodes[j] = NULL;
|
2024-04-22 10:55:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-21 13:43:41 +00:00
|
|
|
/* we do not count the internal node that are included in the deleted */
|
|
|
|
bt_assert(deleted >= invalid_counter);
|
2024-04-22 10:55:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
lp_restore(tmp_linpool, &tmps);
|
|
|
|
mb_free(oids);
|
2024-05-21 13:43:41 +00:00
|
|
|
mb_free(sorted);
|
2024-04-22 10:55:33 +00:00
|
|
|
mb_free(nodes);
|
|
|
|
}
|
|
|
|
|
|
|
|
tmp_flush();
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
t_tree_delete(void)
|
|
|
|
{
|
|
|
|
|
2024-05-21 13:43:41 +00:00
|
|
|
gen_test_delete_remove(random_prefixed_oid, 0);
|
|
|
|
gen_test_delete_remove(random_no_prefix_oid, 0);
|
|
|
|
gen_test_delete_remove(random_prefixable_oid, 0);
|
|
|
|
gen_test_delete_remove(random_oid, 0);
|
2024-04-22 10:55:33 +00:00
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
t_tree_remove(void)
|
|
|
|
{
|
2024-05-21 13:43:41 +00:00
|
|
|
|
|
|
|
gen_test_delete_remove(random_prefixed_oid, 1);
|
|
|
|
gen_test_delete_remove(random_no_prefix_oid, 1);
|
|
|
|
gen_test_delete_remove(random_prefixable_oid, 1);
|
|
|
|
gen_test_delete_remove(random_oid, 1);
|
|
|
|
|
|
|
|
return 1;
|
2024-04-22 10:55:33 +00:00
|
|
|
}
|
|
|
|
|
2024-05-21 13:43:41 +00:00
|
|
|
static void
|
|
|
|
gen_test_traverse(struct oid *(*generator)(void))
|
|
|
|
{
|
|
|
|
lp_state tmps;
|
|
|
|
lp_save(tmp_linpool, &tmps);
|
|
|
|
|
|
|
|
pool *pool = &root_pool;
|
|
|
|
|
|
|
|
for (int test = 0; test < TESTS_NUM; test++)
|
|
|
|
{
|
|
|
|
size_t tsz = ARRAY_SIZE(tree_sizes);
|
|
|
|
|
|
|
|
int size = tree_sizes[test % tsz];
|
|
|
|
int with_leafs = (test % (2 * tsz)) < tsz;
|
|
|
|
int no_inet_prefix = (test % (4 * tsz)) < (2 * tsz);
|
|
|
|
|
|
|
|
struct oid **oids = mb_alloc(pool, size * sizeof(struct oid *));
|
|
|
|
struct oid **sorted = mb_alloc(pool, size * sizeof(struct oid *));
|
|
|
|
mib_node_u **nodes = mb_allocz(pool, size * sizeof(mib_node_u *));
|
|
|
|
|
|
|
|
const int distinct = generate_oids(oids, sorted, size, generator);
|
|
|
|
|
|
|
|
struct mib_tree storage, *tree = &storage;
|
|
|
|
mib_tree_init(pool, tree);
|
|
|
|
|
|
|
|
if (no_inet_prefix)
|
|
|
|
{
|
|
|
|
/* remove the node .1 and all children */
|
|
|
|
const struct oid *inet_pref = oid_create(1, 0, 0, /* ids */ 1);
|
|
|
|
mib_tree_remove(tree, inet_pref);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int o = 0; o < size; o++)
|
|
|
|
{
|
|
|
|
int is_leaf = (with_leafs) ? (int) xrandom(2) : 0;
|
|
|
|
(void) mib_tree_add(pool, tree, oids[o], is_leaf);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int d = 0; d < distinct; d++)
|
|
|
|
{
|
|
|
|
struct mib_walk_state walk;
|
|
|
|
mib_tree_walk_init(&walk, NULL);
|
|
|
|
nodes[d] = mib_tree_find(tree, &walk, sorted[d]);
|
|
|
|
}
|
|
|
|
|
2024-05-24 13:20:30 +00:00
|
|
|
int bound = 0;
|
2024-05-21 13:43:41 +00:00
|
|
|
|
|
|
|
for (int d = 0; d < distinct; d++)
|
|
|
|
{
|
|
|
|
if (snmp_oid_is_prefixed(sorted[d]))
|
|
|
|
bound += 5;
|
|
|
|
bound += (int)LOAD_U8(sorted[d]->n_subid);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!no_inet_prefix)
|
|
|
|
bound += (ARRAY_SIZE(snmp_internet) + 1);
|
|
|
|
|
|
|
|
struct mib_walk_state walk;
|
|
|
|
mib_tree_walk_init(&walk, tree);
|
|
|
|
|
|
|
|
char buf[1024], buf2[1024];
|
2024-07-22 16:12:28 +00:00
|
|
|
struct oid *oid = (struct oid *) buf;
|
|
|
|
struct oid *last = (struct oid *) buf2;
|
2024-05-21 13:43:41 +00:00
|
|
|
memset(oid, 0, sizeof(struct oid)); /* create a null OID */
|
|
|
|
memset(last, 0, sizeof(struct oid));
|
|
|
|
|
|
|
|
int oid_index = 0;
|
|
|
|
if (size > 0 && snmp_is_oid_empty(sorted[oid_index]))
|
|
|
|
oid_index++;
|
|
|
|
|
|
|
|
mib_node_u *current;
|
|
|
|
int i = 0;
|
|
|
|
while ((current = mib_tree_walk_next(tree, &walk)) != NULL && i++ < bound)
|
|
|
|
{
|
|
|
|
memcpy(last, oid, snmp_oid_size(oid));
|
|
|
|
mib_tree_walk_to_oid(&walk, oid,
|
|
|
|
(1024 - sizeof(struct oid) / sizeof(u32)));
|
|
|
|
|
|
|
|
bt_assert(snmp_oid_compare(last, oid) < 0);
|
|
|
|
|
|
|
|
while (oid_index < distinct && nodes[oid_index] == NULL)
|
|
|
|
oid_index++;
|
|
|
|
|
|
|
|
if (oid_index < distinct && snmp_oid_compare(sorted[oid_index], oid) == 0)
|
|
|
|
oid_index++;
|
|
|
|
}
|
|
|
|
|
|
|
|
bt_assert(current == NULL);
|
|
|
|
while (oid_index < distinct && nodes[oid_index] == NULL)
|
|
|
|
oid_index++;
|
|
|
|
|
|
|
|
/* the bound check is only for that the loop is finite */
|
|
|
|
bt_assert(i <= bound + 2);
|
|
|
|
|
|
|
|
current = mib_tree_walk_next(tree, &walk);
|
|
|
|
bt_assert(current == NULL);
|
|
|
|
bt_assert(oid_index == distinct);
|
|
|
|
|
|
|
|
mb_free(oids);
|
|
|
|
mb_free(sorted);
|
|
|
|
mb_free(nodes);
|
|
|
|
|
|
|
|
lp_restore(tmp_linpool, &tmps);
|
|
|
|
}
|
|
|
|
|
|
|
|
tmp_flush();
|
|
|
|
}
|
2024-04-22 10:55:33 +00:00
|
|
|
|
|
|
|
static int
|
|
|
|
t_tree_traversal(void)
|
|
|
|
{
|
2024-05-21 13:43:41 +00:00
|
|
|
gen_test_traverse(random_prefixed_oid);
|
|
|
|
gen_test_traverse(random_no_prefix_oid);
|
|
|
|
gen_test_traverse(random_prefixable_oid);
|
|
|
|
gen_test_traverse(random_oid);
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gen_test_leafs(struct oid *(*generator)(void))
|
|
|
|
{
|
|
|
|
lp_state tmps;
|
|
|
|
lp_save(tmp_linpool, &tmps);
|
|
|
|
|
|
|
|
pool *pool = &root_pool;
|
|
|
|
|
|
|
|
for (int test = 0; test < TESTS_NUM; test++)
|
|
|
|
{
|
|
|
|
size_t tsz = ARRAY_SIZE(tree_sizes);
|
|
|
|
|
|
|
|
int size = tree_sizes[test % tsz];
|
|
|
|
int with_leafs = (test % (2 * tsz)) < tsz;
|
|
|
|
int no_inet_prefix = (test % (4 * tsz)) < (2 * tsz);
|
|
|
|
|
|
|
|
struct oid **oids = mb_alloc(pool, size * sizeof(struct oid *));
|
|
|
|
struct oid **sorted = mb_alloc(pool, size * sizeof(struct oid *));
|
|
|
|
mib_node_u **nodes = mb_allocz(pool, size * sizeof(mib_node_u *));
|
|
|
|
|
|
|
|
const int distinct = generate_oids(oids, sorted, size, generator);
|
|
|
|
|
|
|
|
struct mib_tree storage, *tree = &storage;
|
|
|
|
mib_tree_init(pool, tree);
|
|
|
|
|
|
|
|
if (no_inet_prefix)
|
|
|
|
{
|
|
|
|
/* remove the node .1 and all children */
|
|
|
|
const struct oid *inet_pref = oid_create(1, 0, 0, /* ids */ 1);
|
|
|
|
mib_tree_remove(tree, inet_pref);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int o = 0; o < size; o++)
|
|
|
|
{
|
|
|
|
int is_leaf = (with_leafs) ? (int) xrandom(2) : 0;
|
|
|
|
(void) mib_tree_add(pool, tree, oids[o], is_leaf);
|
|
|
|
}
|
|
|
|
|
|
|
|
int leafs = 0;
|
|
|
|
for (int d = 0; d < distinct; d++)
|
|
|
|
{
|
|
|
|
struct mib_walk_state walk;
|
|
|
|
mib_tree_walk_init(&walk, NULL);
|
|
|
|
nodes[d] = mib_tree_find(tree, &walk, sorted[d]);
|
|
|
|
|
|
|
|
/* count only leafs that was successfully inserted without duplicits */
|
|
|
|
if (nodes[d] != NULL && mib_node_is_leaf(nodes[d]))
|
|
|
|
leafs++;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct mib_walk_state walk;
|
|
|
|
mib_tree_walk_init(&walk, tree);
|
|
|
|
if (!with_leafs)
|
|
|
|
{
|
2024-07-22 16:12:28 +00:00
|
|
|
struct mib_leaf *leaf = mib_tree_walk_next_leaf(tree, &walk, 0);
|
2024-05-21 13:43:41 +00:00
|
|
|
bt_assert(leaf == NULL);
|
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
char buf[1024], buf2[1024];
|
2024-07-22 16:12:28 +00:00
|
|
|
struct oid *oid = (struct oid *) buf;
|
|
|
|
struct oid *last = (struct oid *) buf2;
|
2024-05-21 13:43:41 +00:00
|
|
|
memset(oid, 0, sizeof(struct oid)); /* create a null OID */
|
|
|
|
memset(last, 0, sizeof(struct oid));
|
|
|
|
|
|
|
|
int oid_index = 0;
|
|
|
|
|
|
|
|
struct mib_leaf *current;
|
|
|
|
int i = 0; /* iteration counter ~ leafs found */
|
2024-07-22 16:12:28 +00:00
|
|
|
while ((current = mib_tree_walk_next_leaf(tree, &walk, 0)) != NULL && i++ < leafs)
|
2024-05-21 13:43:41 +00:00
|
|
|
{
|
|
|
|
memcpy(last, oid, snmp_oid_size(oid));
|
|
|
|
mib_tree_walk_to_oid(&walk, oid,
|
|
|
|
(1024 - sizeof(struct oid) / sizeof(u32)));
|
|
|
|
|
|
|
|
bt_assert(snmp_oid_compare(last, oid) < 0);
|
|
|
|
bt_assert(mib_node_is_leaf(((mib_node_u *)current)));
|
2024-05-24 13:20:30 +00:00
|
|
|
|
|
|
|
while (oid_index < distinct &&
|
2024-05-21 13:43:41 +00:00
|
|
|
(nodes[oid_index] == NULL || !mib_node_is_leaf(nodes[oid_index])))
|
|
|
|
oid_index++;
|
|
|
|
|
|
|
|
if (oid_index < distinct && snmp_oid_compare(sorted[oid_index], oid) == 0)
|
|
|
|
oid_index++;
|
|
|
|
}
|
|
|
|
|
|
|
|
bt_assert(current == NULL);
|
|
|
|
while (oid_index < distinct &&
|
|
|
|
(nodes[oid_index] == NULL || !mib_node_is_leaf(nodes[oid_index])))
|
|
|
|
oid_index++;
|
|
|
|
|
2024-07-22 16:12:28 +00:00
|
|
|
current = mib_tree_walk_next_leaf(tree, &walk, 0);
|
2024-05-21 13:43:41 +00:00
|
|
|
bt_assert(current == NULL);
|
2024-05-24 13:20:30 +00:00
|
|
|
bt_assert(oid_index == distinct);
|
2024-05-21 13:43:41 +00:00
|
|
|
bt_assert(i == leafs);
|
|
|
|
|
|
|
|
mb_free(oids);
|
|
|
|
mb_free(sorted);
|
|
|
|
mb_free(nodes);
|
|
|
|
|
|
|
|
lp_restore(tmp_linpool, &tmps);
|
|
|
|
}
|
|
|
|
|
|
|
|
tmp_flush();
|
2024-04-22 10:55:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
t_tree_leafs(void)
|
|
|
|
{
|
2024-05-21 13:43:41 +00:00
|
|
|
|
|
|
|
gen_test_leafs(random_prefixed_oid);
|
|
|
|
gen_test_leafs(random_no_prefix_oid);
|
|
|
|
gen_test_leafs(random_prefixable_oid);
|
|
|
|
gen_test_leafs(random_oid);
|
|
|
|
|
|
|
|
return 1;
|
2024-04-22 10:55:33 +00:00
|
|
|
}
|
|
|
|
|
2024-05-21 13:43:41 +00:00
|
|
|
#if 0
|
2024-04-22 10:55:33 +00:00
|
|
|
static int
|
|
|
|
t_tree_all(void)
|
|
|
|
{
|
2024-05-21 13:43:41 +00:00
|
|
|
/* random sequences of insertion/deletion/searches and walks */
|
2024-04-22 10:55:33 +00:00
|
|
|
return 0; /* failed */
|
|
|
|
}
|
2024-05-21 13:43:41 +00:00
|
|
|
#endif
|
2024-04-22 10:55:33 +00:00
|
|
|
|
|
|
|
|
2022-11-05 15:29:00 +00:00
|
|
|
int main(int argc, char **argv)
|
|
|
|
{
|
|
|
|
bt_init(argc, argv);
|
2023-03-24 14:02:23 +00:00
|
|
|
bt_bird_init();
|
|
|
|
|
2024-07-04 14:33:44 +00:00
|
|
|
//unsigned seed = rand();
|
|
|
|
unsigned seed = 1000789714;
|
2024-05-21 13:43:41 +00:00
|
|
|
log("random seed is %d", seed);
|
|
|
|
srandom(seed);
|
2022-11-15 15:29:03 +00:00
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
bt_test_suite(t_oid_empty, "Function that determines if the OID is empty");
|
|
|
|
bt_test_suite(t_oid_compare, "Function defining lexicographical order on OIDs");
|
|
|
|
bt_test_suite(t_oid_prefixize, "Function transforming OID to prefixed form");
|
|
|
|
bt_test_suite(t_oid_ancestor, "Function finding common ancestor of two OIDs");
|
2024-05-21 13:43:41 +00:00
|
|
|
bt_test_suite(t_walk_to_oid, "Function transforming MIB tree walk state to OID");
|
2024-07-22 16:12:28 +00:00
|
|
|
bt_test_suite(t_walk_oid_desc, "Function testing relation being subtree between MIB tree walk and OID");
|
|
|
|
bt_test_suite(t_walk_oid_compare, "Function comparing MIB tree walk and OID");
|
2022-11-15 15:29:03 +00:00
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
bt_test_suite(t_tree_find, "MIB tree search");
|
|
|
|
bt_test_suite(t_tree_traversal, "MIB tree traversal");
|
|
|
|
bt_test_suite(t_tree_leafs, "MIB tree leafs traversal");
|
|
|
|
bt_test_suite(t_tree_add, "MIB tree insertion");
|
2024-05-21 13:43:41 +00:00
|
|
|
bt_test_suite(t_tree_delete, "MIB tree deletion");
|
|
|
|
bt_test_suite(t_tree_remove, "MIB tree removal");
|
|
|
|
//bt_test_suite(t_tree_all, "MIB tree random find, add, delete mix");
|
2022-11-29 15:30:20 +00:00
|
|
|
|
2022-11-05 15:29:00 +00:00
|
|
|
return bt_exit_value();
|
|
|
|
}
|