mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-13 06:33:44 +01:00
Add a type to map names to short identifiers
We'll be using this for four kinds of identifier in dispatch.c
This commit is contained in:
parent
9a61d3f5ad
commit
dfd7a7f5b6
@ -8,6 +8,7 @@ endif
|
|||||||
src_lib_libtor_container_a_SOURCES = \
|
src_lib_libtor_container_a_SOURCES = \
|
||||||
src/lib/container/bloomfilt.c \
|
src/lib/container/bloomfilt.c \
|
||||||
src/lib/container/map.c \
|
src/lib/container/map.c \
|
||||||
|
src/lib/container/namemap.c \
|
||||||
src/lib/container/order.c \
|
src/lib/container/order.c \
|
||||||
src/lib/container/smartlist.c
|
src/lib/container/smartlist.c
|
||||||
|
|
||||||
@ -21,5 +22,7 @@ noinst_HEADERS += \
|
|||||||
src/lib/container/bloomfilt.h \
|
src/lib/container/bloomfilt.h \
|
||||||
src/lib/container/handles.h \
|
src/lib/container/handles.h \
|
||||||
src/lib/container/map.h \
|
src/lib/container/map.h \
|
||||||
|
src/lib/container/namemap.h \
|
||||||
|
src/lib/container/namemap_st.h \
|
||||||
src/lib/container/order.h \
|
src/lib/container/order.h \
|
||||||
src/lib/container/smartlist.h
|
src/lib/container/smartlist.h
|
||||||
|
184
src/lib/container/namemap.c
Normal file
184
src/lib/container/namemap.c
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
/* Copyright (c) 2003-2004, Roger Dingledine
|
||||||
|
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||||
|
* Copyright (c) 2007-2018, The Tor Project, Inc. */
|
||||||
|
/* See LICENSE for licensing information */
|
||||||
|
|
||||||
|
#include "orconfig.h"
|
||||||
|
#include "lib/container/smartlist.h"
|
||||||
|
#include "lib/container/namemap.h"
|
||||||
|
#include "lib/container/namemap_st.h"
|
||||||
|
#include "lib/log/util_bug.h"
|
||||||
|
#include "lib/malloc/malloc.h"
|
||||||
|
#include "lib/string/printf.h"
|
||||||
|
|
||||||
|
#include "ext/siphash.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/** Helper for namemap hashtable implementation: compare two entries. */
|
||||||
|
static inline int
|
||||||
|
mapped_name_eq(const mapped_name_t *a, const mapped_name_t *b)
|
||||||
|
{
|
||||||
|
return !strcmp(a->name, b->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Helper for namemap hashtable implementation: hash an entry. */
|
||||||
|
static inline unsigned
|
||||||
|
mapped_name_hash(const mapped_name_t *a)
|
||||||
|
{
|
||||||
|
return (unsigned) siphash24g(a->name, strlen(a->name));
|
||||||
|
}
|
||||||
|
|
||||||
|
HT_PROTOTYPE(namemap_ht, mapped_name_t, node, mapped_name_hash,
|
||||||
|
mapped_name_eq)
|
||||||
|
HT_GENERATE2(namemap_ht, mapped_name_t, node, mapped_name_hash,
|
||||||
|
mapped_name_eq, 0.6, tor_reallocarray_, tor_free_)
|
||||||
|
|
||||||
|
/** Set up an uninitialized <b>map</b>. */
|
||||||
|
void
|
||||||
|
namemap_init(namemap_t *map)
|
||||||
|
{
|
||||||
|
memset(map, 0, sizeof(*map));
|
||||||
|
HT_INIT(namemap_ht, &map->ht);
|
||||||
|
map->names = smartlist_new();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Return the name that <b>map</b> associates with a given <b>id</b>, or
|
||||||
|
* NULL if there is no such name. */
|
||||||
|
const char *
|
||||||
|
namemap_get_name(const namemap_t *map, unsigned id)
|
||||||
|
{
|
||||||
|
if (map->names && id < (unsigned)smartlist_len(map->names)) {
|
||||||
|
mapped_name_t *name = smartlist_get(map->names, (int)id);
|
||||||
|
return name->name;
|
||||||
|
} else {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the name that <b>map</b> associates with a given <b>id</b>, or a
|
||||||
|
* pointer to a statically allocated string describing the value of <b>id</b>
|
||||||
|
* if no such name exists.
|
||||||
|
**/
|
||||||
|
const char *
|
||||||
|
namemap_fmt_name(const namemap_t *map, unsigned id)
|
||||||
|
{
|
||||||
|
static char buf[32];
|
||||||
|
|
||||||
|
const char *name = namemap_get_name(map, id);
|
||||||
|
if (name)
|
||||||
|
return name;
|
||||||
|
|
||||||
|
tor_snprintf(buf, sizeof(buf), "{%u}", id);
|
||||||
|
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper: As namemap_get_id(), but requires that <b>name</b> is
|
||||||
|
* <b>namelen</b> charaters long, and that <b>namelen</b> is no more than
|
||||||
|
* MAX_NAMEMAP_NAME_LEN.
|
||||||
|
*/
|
||||||
|
static unsigned
|
||||||
|
namemap_get_id_unchecked(const namemap_t *map,
|
||||||
|
const char *name,
|
||||||
|
size_t namelen)
|
||||||
|
{
|
||||||
|
union {
|
||||||
|
mapped_name_t n;
|
||||||
|
char storage[MAX_NAMEMAP_NAME_LEN + sizeof(mapped_name_t) + 1];
|
||||||
|
} u;
|
||||||
|
memcpy(u.n.name, name, namelen);
|
||||||
|
u.n.name[namelen] = 0;
|
||||||
|
const mapped_name_t *found = HT_FIND(namemap_ht, &map->ht, &u.n);
|
||||||
|
if (found) {
|
||||||
|
tor_assert(map->names);
|
||||||
|
tor_assert(smartlist_get(map->names, found->intval) == found);
|
||||||
|
return found->intval;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NAMEMAP_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the identifier currently associated by <b>map</b> with the name
|
||||||
|
* <b>name</b>, or NAMEMAP_ERR if no such identifier exists.
|
||||||
|
**/
|
||||||
|
unsigned
|
||||||
|
namemap_get_id(const namemap_t *map,
|
||||||
|
const char *name)
|
||||||
|
{
|
||||||
|
size_t namelen = strlen(name);
|
||||||
|
if (namelen > MAX_NAMEMAP_NAME_LEN) {
|
||||||
|
return NAMEMAP_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return namemap_get_id_unchecked(map, name, namelen);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the identifier associated by <b>map</b> with the name
|
||||||
|
* <b>name</b>, allocating a new identifier in <b>map</b> if none exists.
|
||||||
|
*
|
||||||
|
* Return NAMEMAP_ERR if <b>name</b> is too long, or if there are no more
|
||||||
|
* identifiers we can allocate.
|
||||||
|
**/
|
||||||
|
unsigned
|
||||||
|
namemap_get_or_create_id(namemap_t *map,
|
||||||
|
const char *name)
|
||||||
|
{
|
||||||
|
size_t namelen = strlen(name);
|
||||||
|
if (namelen > MAX_NAMEMAP_NAME_LEN) {
|
||||||
|
return NAMEMAP_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PREDICT_UNLIKELY(map->names == NULL))
|
||||||
|
map->names = smartlist_new();
|
||||||
|
|
||||||
|
unsigned found = namemap_get_id_unchecked(map, name, namelen);
|
||||||
|
if (found != NAMEMAP_ERR)
|
||||||
|
return found;
|
||||||
|
|
||||||
|
unsigned new_id = (unsigned)smartlist_len(map->names);
|
||||||
|
if (new_id == NAMEMAP_ERR)
|
||||||
|
return NAMEMAP_ERR; /* Can't allocate any more. */
|
||||||
|
|
||||||
|
mapped_name_t *insert = tor_malloc_zero(
|
||||||
|
offsetof(mapped_name_t, name) + namelen + 1);
|
||||||
|
memcpy(insert->name, name, namelen+1);
|
||||||
|
insert->intval = new_id;
|
||||||
|
|
||||||
|
HT_INSERT(namemap_ht, &map->ht, insert);
|
||||||
|
smartlist_add(map->names, insert);
|
||||||
|
|
||||||
|
return new_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Return the number of entries in 'names' */
|
||||||
|
size_t
|
||||||
|
namemap_get_size(const namemap_t *map)
|
||||||
|
{
|
||||||
|
if (PREDICT_UNLIKELY(map->names == NULL))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return smartlist_len(map->names);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Release all storage held in <b>map</b>.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
namemap_clear(namemap_t *map)
|
||||||
|
{
|
||||||
|
if (!map)
|
||||||
|
return;
|
||||||
|
|
||||||
|
HT_CLEAR(namemap_ht, &map->ht);
|
||||||
|
if (map->names) {
|
||||||
|
SMARTLIST_FOREACH(map->names, mapped_name_t *, n,
|
||||||
|
tor_free(n));
|
||||||
|
smartlist_free(map->names);
|
||||||
|
}
|
||||||
|
memset(map, 0, sizeof(*map));
|
||||||
|
}
|
35
src/lib/container/namemap.h
Normal file
35
src/lib/container/namemap.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/* Copyright (c) 2003-2004, Roger Dingledine
|
||||||
|
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||||
|
* Copyright (c) 2007-2018, The Tor Project, Inc. */
|
||||||
|
/* See LICENSE for licensing information */
|
||||||
|
|
||||||
|
#ifndef TOR_NAMEMAP_H
|
||||||
|
#define TOR_NAMEMAP_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \file namemap.h
|
||||||
|
*
|
||||||
|
* \brief Header for namemap.c
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include "lib/cc/compat_compiler.h"
|
||||||
|
#include "ext/ht.h"
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
typedef struct namemap_t namemap_t;
|
||||||
|
|
||||||
|
/** Returned in place of an identifier when an error occurs. */
|
||||||
|
#define NAMEMAP_ERR UINT_MAX
|
||||||
|
|
||||||
|
void namemap_init(namemap_t *map);
|
||||||
|
const char *namemap_get_name(const namemap_t *map, unsigned id);
|
||||||
|
const char *namemap_fmt_name(const namemap_t *map, unsigned id);
|
||||||
|
unsigned namemap_get_id(const namemap_t *map,
|
||||||
|
const char *name);
|
||||||
|
unsigned namemap_get_or_create_id(namemap_t *map,
|
||||||
|
const char *name);
|
||||||
|
size_t namemap_get_size(const namemap_t *map);
|
||||||
|
void namemap_clear(namemap_t *map);
|
||||||
|
|
||||||
|
#endif
|
34
src/lib/container/namemap_st.h
Normal file
34
src/lib/container/namemap_st.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
/* Copyright (c) 2003-2004, Roger Dingledine
|
||||||
|
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||||
|
* Copyright (c) 2007-2018, The Tor Project, Inc. */
|
||||||
|
/* See LICENSE for licensing information */
|
||||||
|
|
||||||
|
#ifndef NAMEMAP_ST_H
|
||||||
|
#define NAMEMAP_ST_H
|
||||||
|
|
||||||
|
#include "lib/cc/compat_compiler.h"
|
||||||
|
#include "ext/ht.h"
|
||||||
|
|
||||||
|
struct smartlist_t;
|
||||||
|
|
||||||
|
/** Longest allowed name that's allowed in a namemap_t. */
|
||||||
|
#define MAX_NAMEMAP_NAME_LEN 128
|
||||||
|
|
||||||
|
/** An entry inside a namemap_t. Maps a string to a numeric identifier. */
|
||||||
|
typedef struct mapped_name_t {
|
||||||
|
HT_ENTRY(mapped_name_t) node;
|
||||||
|
unsigned intval;
|
||||||
|
char name[FLEXIBLE_ARRAY_MEMBER];
|
||||||
|
} mapped_name_t;
|
||||||
|
|
||||||
|
/** A structure that allocates small numeric identifiers for names and maps
|
||||||
|
* back and forth between them. */
|
||||||
|
struct namemap_t {
|
||||||
|
HT_HEAD(namemap_ht, mapped_name_t) ht;
|
||||||
|
struct smartlist_t *names;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Macro to initialize a namemap. */
|
||||||
|
#define NAMEMAP_INIT() { HT_INITIALIZER(), NULL }
|
||||||
|
|
||||||
|
#endif
|
@ -148,6 +148,7 @@ src_test_test_SOURCES += \
|
|||||||
src/test/test_logging.c \
|
src/test/test_logging.c \
|
||||||
src/test/test_mainloop.c \
|
src/test/test_mainloop.c \
|
||||||
src/test/test_microdesc.c \
|
src/test/test_microdesc.c \
|
||||||
|
src/test/test_namemap.c \
|
||||||
src/test/test_netinfo.c \
|
src/test/test_netinfo.c \
|
||||||
src/test/test_nodelist.c \
|
src/test/test_nodelist.c \
|
||||||
src/test/test_oom.c \
|
src/test/test_oom.c \
|
||||||
|
@ -857,6 +857,7 @@ struct testgroup_t testgroups[] = {
|
|||||||
{ "consdiff/", consdiff_tests },
|
{ "consdiff/", consdiff_tests },
|
||||||
{ "consdiffmgr/", consdiffmgr_tests },
|
{ "consdiffmgr/", consdiffmgr_tests },
|
||||||
{ "container/", container_tests },
|
{ "container/", container_tests },
|
||||||
|
{ "container/namemap/", namemap_tests },
|
||||||
{ "control/", controller_tests },
|
{ "control/", controller_tests },
|
||||||
{ "control/btrack/", btrack_tests },
|
{ "control/btrack/", btrack_tests },
|
||||||
{ "control/event/", controller_event_tests },
|
{ "control/event/", controller_event_tests },
|
||||||
|
@ -234,6 +234,7 @@ extern struct testcase_t link_handshake_tests[];
|
|||||||
extern struct testcase_t logging_tests[];
|
extern struct testcase_t logging_tests[];
|
||||||
extern struct testcase_t mainloop_tests[];
|
extern struct testcase_t mainloop_tests[];
|
||||||
extern struct testcase_t microdesc_tests[];
|
extern struct testcase_t microdesc_tests[];
|
||||||
|
extern struct testcase_t namemap_tests[];
|
||||||
extern struct testcase_t netinfo_tests[];
|
extern struct testcase_t netinfo_tests[];
|
||||||
extern struct testcase_t nodelist_tests[];
|
extern struct testcase_t nodelist_tests[];
|
||||||
extern struct testcase_t oom_tests[];
|
extern struct testcase_t oom_tests[];
|
||||||
|
154
src/test/test_namemap.c
Normal file
154
src/test/test_namemap.c
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
/* Copyright (c) 2018, The Tor Project, Inc. */
|
||||||
|
/* See LICENSE for licensing information */
|
||||||
|
|
||||||
|
#include "test/test.h"
|
||||||
|
|
||||||
|
#include "lib/cc/torint.h"
|
||||||
|
#include "lib/container/namemap.h"
|
||||||
|
#include "lib/container/namemap_st.h"
|
||||||
|
#include "lib/malloc/malloc.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_namemap_empty(void *arg)
|
||||||
|
{
|
||||||
|
(void)arg;
|
||||||
|
|
||||||
|
namemap_t m;
|
||||||
|
namemap_init(&m);
|
||||||
|
namemap_t m2 = NAMEMAP_INIT();
|
||||||
|
|
||||||
|
tt_uint_op(0, OP_EQ, namemap_get_size(&m));
|
||||||
|
tt_uint_op(NAMEMAP_ERR, OP_EQ, namemap_get_id(&m, "hello"));
|
||||||
|
tt_uint_op(NAMEMAP_ERR, OP_EQ, namemap_get_id(&m, "hello"));
|
||||||
|
tt_uint_op(NAMEMAP_ERR, OP_EQ, namemap_get_id(&m, "hello128"));
|
||||||
|
tt_uint_op(NAMEMAP_ERR, OP_EQ, namemap_get_id(&m, ""));
|
||||||
|
tt_uint_op(0, OP_EQ, namemap_get_size(&m));
|
||||||
|
|
||||||
|
tt_uint_op(0, OP_EQ, namemap_get_size(&m2));
|
||||||
|
tt_uint_op(NAMEMAP_ERR, OP_EQ, namemap_get_id(&m2, "hello"));
|
||||||
|
tt_uint_op(NAMEMAP_ERR, OP_EQ, namemap_get_id(&m2, "hello"));
|
||||||
|
tt_uint_op(NAMEMAP_ERR, OP_EQ, namemap_get_id(&m2, "hello128"));
|
||||||
|
tt_uint_op(NAMEMAP_ERR, OP_EQ, namemap_get_id(&m2, ""));
|
||||||
|
tt_uint_op(0, OP_EQ, namemap_get_size(&m));
|
||||||
|
|
||||||
|
done:
|
||||||
|
namemap_clear(&m);
|
||||||
|
namemap_clear(&m2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_namemap_toolong(void *arg)
|
||||||
|
{
|
||||||
|
(void)arg;
|
||||||
|
namemap_t m;
|
||||||
|
char *ok = NULL;
|
||||||
|
char *toolong = NULL;
|
||||||
|
namemap_init(&m);
|
||||||
|
|
||||||
|
ok = tor_malloc_zero(MAX_NAMEMAP_NAME_LEN+1);
|
||||||
|
memset(ok, 'x', MAX_NAMEMAP_NAME_LEN);
|
||||||
|
|
||||||
|
toolong = tor_malloc_zero(MAX_NAMEMAP_NAME_LEN+2);
|
||||||
|
memset(toolong, 'x', MAX_NAMEMAP_NAME_LEN+1);
|
||||||
|
|
||||||
|
tt_uint_op(NAMEMAP_ERR, OP_EQ, namemap_get_id(&m, ok));
|
||||||
|
tt_uint_op(NAMEMAP_ERR, OP_EQ, namemap_get_id(&m, toolong));
|
||||||
|
unsigned u1 = namemap_get_or_create_id(&m, toolong);
|
||||||
|
unsigned u2 = namemap_get_or_create_id(&m, ok);
|
||||||
|
tt_uint_op(u1, OP_EQ, NAMEMAP_ERR);
|
||||||
|
tt_uint_op(u2, OP_NE, NAMEMAP_ERR);
|
||||||
|
tt_uint_op(u2, OP_EQ, namemap_get_id(&m, ok));
|
||||||
|
tt_uint_op(NAMEMAP_ERR, OP_EQ, namemap_get_id(&m, toolong));
|
||||||
|
|
||||||
|
tt_str_op(ok, OP_EQ, namemap_get_name(&m, u2));
|
||||||
|
tt_ptr_op(NULL, OP_EQ, namemap_get_name(&m, u1));
|
||||||
|
|
||||||
|
done:
|
||||||
|
tor_free(ok);
|
||||||
|
tor_free(toolong);
|
||||||
|
namemap_clear(&m);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_namemap_blackbox(void *arg)
|
||||||
|
{
|
||||||
|
(void)arg;
|
||||||
|
|
||||||
|
namemap_t m1, m2;
|
||||||
|
namemap_init(&m1);
|
||||||
|
namemap_init(&m2);
|
||||||
|
|
||||||
|
unsigned u1 = namemap_get_or_create_id(&m1, "hello");
|
||||||
|
unsigned u2 = namemap_get_or_create_id(&m1, "world");
|
||||||
|
tt_uint_op(u1, OP_NE, NAMEMAP_ERR);
|
||||||
|
tt_uint_op(u2, OP_NE, NAMEMAP_ERR);
|
||||||
|
tt_uint_op(u1, OP_NE, u2);
|
||||||
|
|
||||||
|
tt_uint_op(u1, OP_EQ, namemap_get_id(&m1, "hello"));
|
||||||
|
tt_uint_op(u1, OP_EQ, namemap_get_or_create_id(&m1, "hello"));
|
||||||
|
tt_uint_op(u2, OP_EQ, namemap_get_id(&m1, "world"));
|
||||||
|
tt_uint_op(u2, OP_EQ, namemap_get_or_create_id(&m1, "world"));
|
||||||
|
|
||||||
|
tt_uint_op(NAMEMAP_ERR, OP_EQ, namemap_get_id(&m1, "HELLO"));
|
||||||
|
tt_uint_op(NAMEMAP_ERR, OP_EQ, namemap_get_id(&m2, "hello"));
|
||||||
|
|
||||||
|
unsigned u3 = namemap_get_or_create_id(&m2, "hola");
|
||||||
|
tt_uint_op(u3, OP_NE, NAMEMAP_ERR);
|
||||||
|
tt_uint_op(NAMEMAP_ERR, OP_EQ, namemap_get_id(&m1, "hola"));
|
||||||
|
tt_uint_op(u3, OP_EQ, namemap_get_or_create_id(&m2, "hola"));
|
||||||
|
tt_uint_op(u3, OP_EQ, namemap_get_id(&m2, "hola"));
|
||||||
|
|
||||||
|
unsigned int u4 = namemap_get_or_create_id(&m1, "hola");
|
||||||
|
tt_uint_op(u4, OP_NE, NAMEMAP_ERR);
|
||||||
|
tt_uint_op(u4, OP_EQ, namemap_get_id(&m1, "hola"));
|
||||||
|
tt_uint_op(u3, OP_EQ, namemap_get_id(&m2, "hola"));
|
||||||
|
|
||||||
|
tt_str_op("hello", OP_EQ, namemap_get_name(&m1, u1));
|
||||||
|
tt_str_op("world", OP_EQ, namemap_get_name(&m1, u2));
|
||||||
|
tt_str_op("hola", OP_EQ, namemap_get_name(&m2, u3));
|
||||||
|
tt_str_op("hola", OP_EQ, namemap_get_name(&m1, u4));
|
||||||
|
|
||||||
|
tt_ptr_op(NULL, OP_EQ, namemap_get_name(&m2, u3 + 10));
|
||||||
|
|
||||||
|
done:
|
||||||
|
namemap_clear(&m1);
|
||||||
|
namemap_clear(&m2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_namemap_internals(void *arg)
|
||||||
|
{
|
||||||
|
(void)arg;
|
||||||
|
// This test actually assumes know something about the identity layout.
|
||||||
|
namemap_t m;
|
||||||
|
namemap_init(&m);
|
||||||
|
|
||||||
|
tt_uint_op(0, OP_EQ, namemap_get_or_create_id(&m, "that"));
|
||||||
|
tt_uint_op(0, OP_EQ, namemap_get_or_create_id(&m, "that"));
|
||||||
|
tt_uint_op(1, OP_EQ, namemap_get_or_create_id(&m, "is"));
|
||||||
|
tt_uint_op(1, OP_EQ, namemap_get_or_create_id(&m, "is"));
|
||||||
|
|
||||||
|
tt_uint_op(0, OP_EQ, namemap_get_id(&m, "that"));
|
||||||
|
tt_uint_op(0, OP_EQ, namemap_get_id(&m, "that"));
|
||||||
|
tt_uint_op(1, OP_EQ, namemap_get_id(&m, "is"));
|
||||||
|
tt_uint_op(2, OP_EQ, namemap_get_or_create_id(&m, "not"));
|
||||||
|
tt_uint_op(1, OP_EQ, namemap_get_or_create_id(&m, "is"));
|
||||||
|
tt_uint_op(2, OP_EQ, namemap_get_or_create_id(&m, "not"));
|
||||||
|
|
||||||
|
done:
|
||||||
|
namemap_clear(&m);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define T(name) \
|
||||||
|
{ #name, test_namemap_ ## name , 0, NULL, NULL }
|
||||||
|
|
||||||
|
struct testcase_t namemap_tests[] = {
|
||||||
|
T(empty),
|
||||||
|
T(toolong),
|
||||||
|
T(blackbox),
|
||||||
|
T(internals),
|
||||||
|
END_OF_TESTCASES
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user