summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Silverstone <dsilvers@netsurf-browser.org>2010-03-27 14:45:09 (GMT)
committer Daniel Silverstone <dsilvers@netsurf-browser.org>2010-03-27 14:45:09 (GMT)
commit02fdaeaf41359941559dd63e24805e78a9ee27e5 (patch)
tree609a59135c5a3f605f5f57ae6786fff719e9510d
parent470b8a37ecade509f16dad398d4d33000b05ddfb (diff)
downloadlibwapcaplet-02fdaeaf41359941559dd63e24805e78a9ee27e5.tar.gz
libwapcaplet-02fdaeaf41359941559dd63e24805e78a9ee27e5.tar.bz2
Simplify libwapcaplet and remove context objects.
Remove the lwc_context type from the API and ensure that all strings belong to the one internment context. This removes a lot of API and simplifies a lot of function calls, however it does mean that clients of the library *MUST* be better at reffing and unreffing strings or it'll explode. svn path=/trunk/libwapcaplet/; revision=10159
-rw-r--r--include/libwapcaplet/libwapcaplet.h174
-rw-r--r--src/libwapcaplet.c188
-rw-r--r--test/Makefile2
-rw-r--r--test/basictests.c538
-rw-r--r--test/memorytests.c246
-rw-r--r--test/testmain.c2
6 files changed, 383 insertions, 767 deletions
diff --git a/include/libwapcaplet/libwapcaplet.h b/include/libwapcaplet/libwapcaplet.h
index 3b0899d..b71306c 100644
--- a/include/libwapcaplet/libwapcaplet.h
+++ b/include/libwapcaplet/libwapcaplet.h
@@ -14,135 +14,189 @@
#include <stdint.h>
/**
- * Memory allocator type
+ * Memory allocator function type
+ *
+ * @param ptr The old pointer to reallocate (NULL for new allocations).
+ * @param size The size of block to allocate.
+ * @param pw The private pointer for the allocator.
+ * @return The newly allocated/resized pointer or NULL on error.
*/
typedef void *(*lwc_allocator_fn)(void *ptr, size_t size, void *pw);
/**
- * A string internment context.
- */
-typedef struct lwc_context_s lwc_context;
-
-/**
* An interned string.
*/
typedef struct lwc_string_s lwc_string;
/**
- * Error codes which libwapcaplet might return.
+ * Result codes which libwapcaplet might return.
*/
typedef enum lwc_error_e {
- lwc_error_ok = 0,
- lwc_error_oom = 1,
- lwc_error_range = 2
+ lwc_error_ok = 0, /**< No error. */
+ lwc_error_initialised = 1, /**< Library already initialised. */
+ lwc_error_oom = 2, /**< Out of memory. */
+ lwc_error_range = 3, /**< Substring internment out of range. */
} lwc_error;
/**
- * Create an internment context.
- *
- * This creates an internment context with a weak ref of one.
- *
- * You should reference the context with lwc_context_ref to convert
- * that to a strong reference when you decide where to store it.
+ * The type of a hash value used in libwapcaplet.
*/
-extern lwc_error lwc_create_context(lwc_allocator_fn alloc, void *pw,
- lwc_context **ret);
+typedef uint32_t lwc_hash;
/**
- * Increment the reference count for an internment context.
- */
-extern lwc_context *lwc_context_ref(lwc_context *ctx);
-
-/**
- * Decrement the reference count for an internment context.
+ * Initialise the library.
+ *
+ * Initialise the library with an allocator function. All strings
+ * interned will be allocated via this function, as will any
+ * structures required to manage libwapcaplet. In this manner, all
+ * interned strings are directly comparable, no matter what interned
+ * them.
*
- * @note If the reference count reaches zero, the context will be freed.
+ * @note If you require to know how much memory libwapcaplet is using
+ * then you should use a counting allocator function.
+ *
+ * @param alloc The allocator to use for libwapcaplet allocations.
+ * @param pw The private word to pass to \a alloc.
+ * @param buckets The number of buckets to use by default, or zero to
+ * allow the implementation to choose for itself.
+ * @return The result of initialising. If not OK do not use
+ * any further wapcaplet functions.
*/
-extern void lwc_context_unref(lwc_context *ctx);
+extern lwc_error lwc_initialise(lwc_allocator_fn alloc, void *pw, lwc_hash buckets);
/**
* Intern a string.
*
- * If the string was already present, its reference count is incremented.
+ * Take a copy of the string data referred to by \a s and \a slen and
+ * intern it. The resulting ::lwc_string can be used for simple and
+ * caseless comparisons by ::lwc_string_isequal and
+ * ::lwc_string_caseless_isequal respectively.
+ *
+ * @param s Pointer to the start of the string to intern.
+ * @param slen Length of the string in characters. (Not including any
+ * terminators)
+ * @param ret Pointer to ::lwc_string pointer to fill out.
+ * @return Result of operation, if not OK then the value pointed
+ * to by \a ret will not be valid.
+ *
+ * @note The memory pointed to by \a s is not referenced by the result.
+ * @note If the string was already present, its reference count is
+ * incremented rather than allocating more memory.
*
- * The returned string is guaranteed to be NUL-terminated.
+ * @note The returned string is currently NULL-terminated but this
+ * will not necessarily be the case in future. Try not to rely
+ * on it.
*/
-extern lwc_error lwc_context_intern(lwc_context *ctx,
- const char *s, size_t slen,
- lwc_string **ret);
+extern lwc_error lwc_intern_string(const char *s, size_t slen,
+ lwc_string **ret);
/**
* Intern a substring.
+ *
+ * Intern a subsequence of the provided ::lwc_string.
+ *
+ * @param str String to acquire substring from.
+ * @param ssoffset Substring offset into \a str.
+ * @param sslen Substring length.
+ * @param ret Pointer to pointer to ::lwc_string to fill out.
+ * @return Result of operation, if not OK then the value
+ * pointed to by \a ret will not be valid.
*/
-extern lwc_error lwc_context_intern_substring(lwc_context *ctx,
- lwc_string *str,
- size_t ssoffset, size_t sslen,
- lwc_string **ret);
+extern lwc_error lwc_intern_substring(lwc_string *str,
+ size_t ssoffset, size_t sslen,
+ lwc_string **ret);
/**
* Increment the reference count on an lwc_string.
*
- * Use this if copying the string and intending both sides to retain
+ * This increases the reference count on the given string. You should
+ * use this when copying a string pointer into a persistent data
+ * structure.
+ *
+ * @verb
+ * myobject->str = lwc_string_ref(myparent->str);
+ * @endverb
+ *
+ * @param str The string to create another reference to.
+ * @return The string pointer to use in your new data structure.
+ *
+ * @note Use this if copying the string and intending both sides to retain
* ownership.
*/
-extern lwc_string *lwc_context_string_ref(lwc_context *ctx, lwc_string *str);
+extern lwc_string *lwc_string_ref(lwc_string *str);
/**
* Release a reference on an lwc_string.
*
- * If the reference count reaches zero then the string will be freed.
+ * This decreases the reference count on the given ::lwc_string.
+ *
+ * @param str The string to unref.
+ * @return The result of the operation, if not OK then the string
+ * was not unreffed.
+ *
+ * @note If the reference count reaches zero then the string will be
+ * freed.
*/
-extern void lwc_context_string_unref(lwc_context *ctx, lwc_string *str);
+extern void lwc_string_unref(lwc_string *str);
/**
* Check if two interned strings are equal.
*
- * @note The strings must be from the same intern context and that
- * must be the context passed in.
+ * @param str1 The first string in the comparison.
+ * @param str2 The second string in the comparison.
+ * @param ret A pointer to a boolean to be filled out with the result.
+ * @return Result of operation, if not ok then value pointed to
+ * by \a ret will not be valid.
*/
-#define lwc_context_string_isequal(ctx, str1, str2, ret) \
+#define lwc_string_isequal(str1, str2, ret) \
(*ret = (str1 == str2)), lwc_error_ok
/**
* Check if two interned strings are case-insensitively equal.
*
- * @note The strings must be from the same intern context and that
- * must be the context passed in.
+ * @param str1 The first string in the comparison.
+ * @param str2 The second string in the comparison.
+ * @param ret A pointer to a boolean to be filled out with the result.
+ * @return Result of operation, if not ok then value pointed to
+ * by \a ret will not be valid.
*/
-extern lwc_error lwc_context_string_caseless_isequal(lwc_context *ctx,
- lwc_string *str1,
- lwc_string *str2,
- bool *ret);
+extern lwc_error lwc_string_caseless_isequal(lwc_string *str1,
+ lwc_string *str2,
+ bool *ret);
/**
* Retrieve the data pointer for an interned string.
*
+ * @param str The string to retrieve the data pointer for.
+ * @return The C string data pointer for \a str.
+ *
* @note The data we point at belongs to the string and will
- * die with the string. Keep a ref if you need it.
+ * die with the string. Keep a ref if you need it.
+ * @note You may not rely on the NULL termination of the strings
+ * in future. Any code relying on it currently should be
+ * modified to use ::lwc_string_length if possible.
*/
extern const char *lwc_string_data(lwc_string *str);
/**
* Retrieve the data length for an interned string.
*
- * @note The data we point at belongs to the string and will
- * die with the string. Keep a ref if you need it.
+ * @param str The string to retrieve the length of.
+ * @return The length of \a str.
*/
extern size_t lwc_string_length(lwc_string *str);
/**
* Retrieve (or compute if unavailable) a hash value for the content of the string.
*
+ * @param str The string to get the hash for.
+ * @return The 32 bit hash of \a str.
+ *
* @note This API should only be used as a convenient way to retrieve a hash
- * value for the string. This hash value should not be relied on to be
- * unique within an invocation of the program, nor should it be relied upon
- * to be stable between invocations of the program. Never use the hash
- * value as a way to directly identify the value of the string.
+ * value for the string. This hash value should not be relied on to be
+ * unique within an invocation of the program, nor should it be relied upon
+ * to be stable between invocations of the program. Never use the hash
+ * value as a way to directly identify the value of the string.
*/
extern uint32_t lwc_string_hash_value(lwc_string *str);
-/**
- * Retrieve the size, in bytes, of internment context \a ctx.
- */
-extern size_t lwc_context_size(lwc_context *ctx);
-
#endif /* libwapcaplet_h_ */
diff --git a/src/libwapcaplet.c b/src/libwapcaplet.c
index 4996c6f..c452889 100644
--- a/src/libwapcaplet.c
+++ b/src/libwapcaplet.c
@@ -1,4 +1,4 @@
-/* libwapcaplet.h
+/* libwapcaplet.c
*
* String internment and management tools.
*
@@ -15,7 +15,6 @@
#define UNUSED(x) ((x) = (x))
#endif
-typedef uint32_t lwc_hash;
typedef uint32_t lwc_refcounter;
static inline lwc_hash
@@ -45,101 +44,70 @@ struct lwc_string_s {
#define STR_OF(str) ((char *)(str + 1))
#define CSTR_OF(str) ((const char *)(str + 1))
-#define NR_BUCKETS (4091)
+#define NR_BUCKETS_DEFAULT (4091)
-struct lwc_context_s {
+typedef struct lwc_context_s {
lwc_allocator_fn alloc;
void * alloc_pw;
- lwc_string * buckets[NR_BUCKETS];
- lwc_refcounter refcnt;
- bool refweak;
- size_t size;
-};
+ lwc_string ** buckets;
+ lwc_hash bucketcount;
+} lwc_context;
+
+static lwc_context *ctx = NULL;
+
+#define LWC_ALLOC(s) ctx->alloc(NULL, s, ctx->alloc_pw)
+#define LWC_FREE(p) ctx->alloc(p, 0, ctx->alloc_pw)
+
+typedef lwc_hash (*lwc_hasher)(const char *, size_t);
+typedef int (*lwc_strncmp)(const char *, const char *, size_t);
+typedef void (*lwc_memcpy)(char *, const char *, size_t);
lwc_error
-lwc_create_context(lwc_allocator_fn alloc, void *pw,
- lwc_context **ret)
+lwc_initialise(lwc_allocator_fn alloc, void *pw, lwc_hash buckets)
{
assert(alloc);
-
- *ret = alloc(NULL, sizeof(lwc_context), pw);
-
- if (*ret == NULL)
- return lwc_error_oom;
-
- memset(*ret, 0, sizeof(lwc_context));
- (*ret)->alloc = alloc;
- (*ret)->alloc_pw = pw;
- (*ret)->refcnt = 1;
- (*ret)->refweak = true;
- (*ret)->size = sizeof(lwc_context);
+ if (ctx != NULL)
+ return lwc_error_initialised;
- return lwc_error_ok;
-}
-
-lwc_context *
-lwc_context_ref(lwc_context *ctx)
-{
- assert(ctx);
+ ctx = alloc(NULL, sizeof(lwc_context), pw);
- if (ctx->refweak == true)
- ctx->refweak = false;
- else
- ctx->refcnt++;
-
- return ctx;
-}
-
-#define LWC_ALLOC(s) ctx->alloc(NULL, s, ctx->alloc_pw)
-#define LWC_FREE(p) ctx->alloc(p, 0, ctx->alloc_pw)
-
-void
-lwc_context_unref(lwc_context *ctx)
-{
- int bucket_nr;
- lwc_string *s, *s_next;
+ if (ctx == NULL)
+ return lwc_error_oom;
- assert(ctx);
+ memset(ctx, 0, sizeof(lwc_context));
- if (--(ctx->refcnt))
- return;
+ ctx->bucketcount = (buckets > 0) ? buckets : NR_BUCKETS_DEFAULT;
+ ctx->alloc = alloc;
+ ctx->alloc_pw = pw;
+ ctx->buckets = alloc(NULL, sizeof(lwc_string *) * ctx->bucketcount, pw);
- for (bucket_nr = 0; bucket_nr < NR_BUCKETS; ++bucket_nr) {
- s = ctx->buckets[bucket_nr];
- while (s != NULL) {
- s_next = s->next;
- LWC_FREE(s);
- s = s_next;
- }
+ if (ctx->buckets == NULL) {
+ alloc(ctx, 0, pw);
+ return lwc_error_oom;
}
- LWC_FREE(ctx);
+ memset(ctx->buckets, 0, sizeof(lwc_string *) * ctx->bucketcount);
+
+ return lwc_error_ok;
}
-typedef lwc_hash (*lwc_hasher)(const char *, size_t);
-typedef int (*lwc_strncmp)(const char *, const char *, size_t);
-typedef void (*lwc_memcpy)(char *, const char *, size_t);
-
static lwc_error
-__lwc_context_intern(lwc_context *ctx,
- const char *s, size_t slen,
- lwc_string **ret,
- lwc_hasher hasher,
- lwc_strncmp compare,
- lwc_memcpy copy)
+__lwc_intern(const char *s, size_t slen,
+ lwc_string **ret,
+ lwc_hasher hasher,
+ lwc_strncmp compare,
+ lwc_memcpy copy)
{
lwc_hash h;
lwc_hash bucket;
lwc_string *str;
- size_t required_size;
- assert(ctx);
assert((s != NULL) || (slen == 0));
assert(ret);
h = hasher(s, slen);
- bucket = h % NR_BUCKETS;
+ bucket = h % ctx->bucketcount;
str = ctx->buckets[bucket];
while (str != NULL) {
@@ -154,9 +122,7 @@ __lwc_context_intern(lwc_context *ctx,
}
/* Add one for the additional NUL. */
- required_size = sizeof(lwc_string) + slen + 1;
-
- *ret = str = LWC_ALLOC(required_size);
+ *ret = str = LWC_ALLOC(sizeof(lwc_string) + slen + 1);
if (str == NULL)
return lwc_error_oom;
@@ -167,9 +133,6 @@ __lwc_context_intern(lwc_context *ctx,
str->next->prevptr = &(str->next);
ctx->buckets[bucket] = str;
- /* Keep context size in sync */
- ctx->size += required_size;
-
str->len = slen;
str->hash = h;
str->refcnt = 1;
@@ -184,22 +147,19 @@ __lwc_context_intern(lwc_context *ctx,
}
lwc_error
-lwc_context_intern(lwc_context *ctx,
- const char *s, size_t slen,
- lwc_string **ret)
+lwc_intern_string(const char *s, size_t slen,
+ lwc_string **ret)
{
- return __lwc_context_intern(ctx, s, slen, ret,
- lwc_calculate_hash,
- strncmp, (lwc_memcpy)memcpy);
+ return __lwc_intern(s, slen, ret,
+ lwc_calculate_hash,
+ strncmp, (lwc_memcpy)memcpy);
}
lwc_error
-lwc_context_intern_substring(lwc_context *ctx,
- lwc_string *str,
- size_t ssoffset, size_t sslen,
- lwc_string **ret)
+lwc_intern_substring(lwc_string *str,
+ size_t ssoffset, size_t sslen,
+ lwc_string **ret)
{
- assert(ctx);
assert(str);
assert(ret);
@@ -208,15 +168,12 @@ lwc_context_intern_substring(lwc_context *ctx,
if ((ssoffset + sslen) > str->len)
return lwc_error_range;
- return lwc_context_intern(ctx, CSTR_OF(str) + ssoffset, sslen, ret);
+ return lwc_intern_string(CSTR_OF(str) + ssoffset, sslen, ret);
}
lwc_string *
-lwc_context_string_ref(lwc_context *ctx, lwc_string *str)
+lwc_string_ref(lwc_string *str)
{
- UNUSED(ctx);
-
- assert(ctx);
assert(str);
str->refcnt++;
@@ -225,9 +182,8 @@ lwc_context_string_ref(lwc_context *ctx, lwc_string *str)
}
void
-lwc_context_string_unref(lwc_context *ctx, lwc_string *str)
+lwc_string_unref(lwc_string *str)
{
- assert(ctx);
assert(str);
if (--(str->refcnt) > 1)
@@ -242,11 +198,8 @@ lwc_context_string_unref(lwc_context *ctx, lwc_string *str)
str->next->prevptr = str->prevptr;
if (str->insensitive != NULL && str->refcnt == 0)
- lwc_context_string_unref(ctx, str->insensitive);
+ lwc_string_unref(str->insensitive);
- /* Reduce context size by appropriate amount (+1 for trailing NUL) */
- ctx->size -= sizeof(lwc_string) + str->len + 1;
-
#ifndef NDEBUG
memset(str, 0xA5, sizeof(*str) + str->len);
#endif
@@ -280,10 +233,11 @@ lwc_calculate_lcase_hash(const char *str, size_t len)
}
static int
-lwc_lcase_strcmp(const char *s1, const char *s2, size_t n)
+lwc_lcase_strncmp(const char *s1, const char *s2, size_t n)
{
while (n--) {
if (*s1++ != dolower(*s2++))
+ /** @todo Test this somehow? */
return 1;
}
return 0;
@@ -298,39 +252,34 @@ lwc_lcase_memcpy(char *target, const char *source, size_t n)
}
static lwc_error
-lwc_context_intern_caseless(lwc_context *ctx,
- lwc_string *str)
+lwc_intern_caseless_string(lwc_string *str)
{
- assert(ctx);
assert(str);
assert(str->insensitive == NULL);
- return __lwc_context_intern(ctx, CSTR_OF(str),
- str->len, &(str->insensitive),
- lwc_calculate_lcase_hash,
- lwc_lcase_strcmp,
- lwc_lcase_memcpy);
-
+ return __lwc_intern(CSTR_OF(str),
+ str->len, &(str->insensitive),
+ lwc_calculate_lcase_hash,
+ lwc_lcase_strncmp,
+ lwc_lcase_memcpy);
}
lwc_error
-lwc_context_string_caseless_isequal(lwc_context *ctx,
- lwc_string *str1,
- lwc_string *str2,
- bool *ret)
+lwc_string_caseless_isequal(lwc_string *str1,
+ lwc_string *str2,
+ bool *ret)
{
lwc_error err;
- assert(ctx);
assert(str1);
assert(str2);
if (str1->insensitive == NULL) {
- err = lwc_context_intern_caseless(ctx, str1);
+ err = lwc_intern_caseless_string(str1);
if (err != lwc_error_ok)
return err;
}
if (str2->insensitive == NULL) {
- err = lwc_context_intern_caseless(ctx, str2);
+ err = lwc_intern_caseless_string(str2);
if (err != lwc_error_ok)
return err;
}
@@ -364,12 +313,3 @@ lwc_string_hash_value(lwc_string *str)
return str->hash;
}
-
-size_t
-lwc_context_size(lwc_context *ctx)
-{
- assert(ctx);
-
- return ctx->size;
-}
-
diff --git a/test/Makefile b/test/Makefile
index 9ce2c1c..2ba343a 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -1,3 +1,3 @@
-DIR_TEST_ITEMS := testrunner:testmain.c;basictests.c;memorytests.c
+DIR_TEST_ITEMS := testrunner:testmain.c;basictests.c
include build/makefiles/Makefile.subdir
diff --git a/test/basictests.c b/test/basictests.c
index cedb0c3..210b82c 100644
--- a/test/basictests.c
+++ b/test/basictests.c
@@ -12,6 +12,10 @@
#include "tests.h"
+#ifndef UNUSED
+#define UNUSED(x) (void)(x)
+#endif
+
static void *last_pw = NULL;
static void *
trivial_alloc_fn(void *p, size_t s, void *pw)
@@ -22,383 +26,225 @@ trivial_alloc_fn(void *p, size_t s, void *pw)
#ifndef NDEBUG
/* All the basic assert() tests */
-START_TEST (test_lwc_context_creation_bad_alloc_aborts)
-{
- lwc_context *ctx = NULL;
- lwc_error err;
-
- err = lwc_create_context(NULL, NULL, &ctx);
-}
-END_TEST
-
-START_TEST (test_lwc_context_destruction_aborts)
-{
- lwc_context_unref(NULL);
-}
-END_TEST
-
-START_TEST (test_lwc_context_ref_aborts)
-{
- lwc_context_ref(NULL);
-}
-END_TEST
-
-START_TEST (test_lwc_context_unref_aborts)
-{
- lwc_context_unref(NULL);
-}
-END_TEST
-
-START_TEST (test_lwc_context_intern_aborts1)
-{
- lwc_context_intern(NULL, NULL, 0, NULL);
-}
-END_TEST
-
-START_TEST (test_lwc_context_intern_aborts2)
+START_TEST (test_lwc_intern_string_aborts1)
{
- lwc_context *ctx;
-
- fail_unless(lwc_create_context(trivial_alloc_fn, NULL, &ctx) == lwc_error_ok,
- "Unable to create context");
-
- lwc_context_intern(ctx, NULL, 0, NULL);
+ lwc_intern_string(NULL, 0, NULL);
}
END_TEST
-START_TEST (test_lwc_context_intern_aborts3)
+START_TEST (test_lwc_intern_string_aborts2)
{
- lwc_context *ctx;
-
- fail_unless(lwc_create_context(trivial_alloc_fn, NULL, &ctx) == lwc_error_ok,
- "Unable to create context");
-
- lwc_context_intern(ctx, "A", 1, NULL);
+ lwc_intern_string("A", 1, NULL);
}
END_TEST
-START_TEST (test_lwc_context_intern_substring_aborts1)
+START_TEST (test_lwc_intern_substring_aborts1)
{
- lwc_context_intern_substring(NULL, NULL, 0, 0, NULL);
+ lwc_intern_substring(NULL, 0, 0, NULL);
}
END_TEST
-START_TEST (test_lwc_context_intern_substring_aborts2)
+START_TEST (test_lwc_intern_substring_aborts2)
{
- lwc_context *ctx;
- fail_unless(lwc_create_context(trivial_alloc_fn, NULL, &ctx) == lwc_error_ok,
- "Unable to create context");
-
- lwc_context_intern_substring(ctx, NULL, 0, 0, NULL);
-}
-END_TEST
-
-START_TEST (test_lwc_context_intern_substring_aborts3)
-{
- lwc_context *ctx;
lwc_string *str;
- fail_unless(lwc_create_context(trivial_alloc_fn, NULL, &ctx) == lwc_error_ok,
- "Unable to create context");
- fail_unless(lwc_context_intern(ctx, "Jam", 3, &str) == lwc_error_ok,
+ fail_unless(lwc_initialise(trivial_alloc_fn, NULL, 0) == lwc_error_ok,
+ "unable to initialise the library");
+ fail_unless(lwc_intern_string("Jam", 3, &str) == lwc_error_ok,
"unable to intern 'Jam'");
- lwc_context_intern_substring(ctx, str, 100, 1, NULL);
+ lwc_intern_substring(str, 88, 77, NULL);
}
END_TEST
-START_TEST (test_lwc_context_intern_substring_aborts4)
+START_TEST (test_lwc_string_ref_aborts)
{
- lwc_context *ctx;
- lwc_string *str;
- fail_unless(lwc_create_context(trivial_alloc_fn, NULL, &ctx) == lwc_error_ok,
- "Unable to create context");
- fail_unless(lwc_context_intern(ctx, "Jam", 3, &str) == lwc_error_ok,
- "unable to intern 'Jam'");
-
- lwc_context_intern_substring(ctx, str, 1, 10, NULL);
+ lwc_string_ref(NULL);
}
END_TEST
-START_TEST (test_lwc_context_intern_substring_aborts5)
+START_TEST (test_lwc_string_unref_aborts)
{
- lwc_context *ctx;
- lwc_string *str;
- fail_unless(lwc_create_context(trivial_alloc_fn, NULL, &ctx) == lwc_error_ok,
- "Unable to create context");
- fail_unless(lwc_context_intern(ctx, "Jam", 3, &str) == lwc_error_ok,
- "unable to intern 'Jam'");
-
- lwc_context_intern_substring(ctx, str, 1, 2, NULL);
+ lwc_string_unref(NULL);
}
END_TEST
-START_TEST (test_lwc_context_string_ref_aborts1)
+START_TEST (test_lwc_string_data_aborts)
{
- lwc_context_string_ref(NULL, NULL);
+ lwc_string_data(NULL);
}
END_TEST
-START_TEST (test_lwc_context_string_ref_aborts2)
+START_TEST (test_lwc_string_length_aborts)
{
- lwc_context *ctx;
- fail_unless(lwc_create_context(trivial_alloc_fn, NULL, &ctx) == lwc_error_ok,
- "Unable to create context");
- lwc_context_string_ref(ctx, NULL);
+ lwc_string_length(NULL);
}
END_TEST
-START_TEST (test_lwc_context_string_unref_aborts1)
+START_TEST (test_lwc_string_hash_value_aborts)
{
- lwc_context_string_unref(NULL, NULL);
+ lwc_string_hash_value(NULL);
}
END_TEST
-START_TEST (test_lwc_context_string_unref_aborts2)
-{
- lwc_context *ctx;
- fail_unless(lwc_create_context(trivial_alloc_fn, NULL, &ctx) == lwc_error_ok,
- "Unable to create context");
- lwc_context_string_unref(ctx, NULL);
-}
-END_TEST
+#endif
-START_TEST (test_lwc_string_data_aborts)
+START_TEST (test_lwc_double_initialise_fails)
{
- lwc_string_data(NULL);
+ fail_unless(lwc_initialise(trivial_alloc_fn, NULL, 0) == lwc_error_ok,
+ "Unable to initialise library");
+ fail_unless(lwc_initialise(trivial_alloc_fn, NULL, 0) == lwc_error_initialised,
+ "Able to initialise library a second time");
}
END_TEST
-START_TEST (test_lwc_string_length_aborts)
+static void *enomem_allocator(void *ptr, size_t n, void *pw)
{
- lwc_string_length(NULL);
+ int *pi = (int*)pw;
+ UNUSED(ptr);
+ UNUSED(n);
+
+ if (*pi > 0) {
+ *pi -= 1;
+ return realloc(ptr, n);
+ }
+
+ return NULL;
}
-END_TEST
-START_TEST (test_lwc_string_hash_value_aborts)
+START_TEST (test_lwc_initialise_fails_with_no_memory)
{
- lwc_string_hash_value(NULL);
+ int permitted = 0;
+ fail_unless(lwc_initialise(enomem_allocator, &permitted, 0) == lwc_error_oom,
+ "Able to initialise library with no memory available?!");
}
END_TEST
-START_TEST (test_lwc_context_size_aborts)
+START_TEST (test_lwc_initialise_fails_with_low_memory)
{
- lwc_context_size(NULL);
+ int permitted = 1;
+ fail_unless(lwc_initialise(enomem_allocator, &permitted, 0) == lwc_error_oom,
+ "Able to initialise library with no memory available?!");
}
END_TEST
-#endif
-
-START_TEST (test_lwc_context_creation_ok)
+START_TEST (test_lwc_intern_fails_with_no_memory)
{
- lwc_context *ctx = NULL;
- lwc_error err;
+ int permitted = 2; /* context and buckets */
+ lwc_string *str;
+
+ fail_unless(lwc_initialise(enomem_allocator, &permitted, 0) == lwc_error_ok,
+ "Unable to initialise library");
+ fail_unless(lwc_intern_string("Hello", 5, &str) == lwc_error_oom,
+ "Able to allocate string despite enomem.");
- err = lwc_create_context(trivial_alloc_fn, NULL, &ctx);
- fail_unless(ctx != NULL,
- "Unable to create context");
- fail_unless(err == lwc_error_ok,
- "Created context but returned !ok");
}
END_TEST
-START_TEST (test_lwc_context_destruction_ok)
+START_TEST (test_lwc_caseless_compare_fails_with_no_memory1)
{
- lwc_context *ctx = NULL;
+ int permitted = 3; /* ctx, buckets, 1 string */
+ lwc_string *str;
+ bool result = true;
- fail_unless(lwc_create_context(trivial_alloc_fn, NULL, &ctx) == lwc_error_ok,
- "Unable to create context");
+ fail_unless(lwc_initialise(enomem_allocator, &permitted, 0) == lwc_error_ok,
+ "Unable to initialise library");
+ fail_unless(lwc_intern_string("Hello", 5, &str) == lwc_error_ok,
+ "Unable to allocate string.");
+ fail_unless(lwc_string_caseless_isequal(str, str, &result) == lwc_error_oom,
+ "Able to caselessly compare despite no memory");
- lwc_context_unref(ctx);
}
END_TEST
-START_TEST (test_lwc_reffed_context_destruction_ok)
+START_TEST (test_lwc_caseless_compare_fails_with_no_memory2)
{
- lwc_context *ctx = NULL;
-
- fail_unless(lwc_create_context(trivial_alloc_fn, NULL, &ctx) == lwc_error_ok,
- "Unable to create context");
+ int permitted = 5; /* ctx, buckets, 3 strings */
+ lwc_string *str1, *str2;
+ bool result = true;
- lwc_context_ref(ctx); /* make the weak ref strong */
+ fail_unless(lwc_initialise(enomem_allocator, &permitted, 0) == lwc_error_ok,
+ "Unable to initialise library");
+ fail_unless(lwc_intern_string("Hello", 5, &str1) == lwc_error_ok,
+ "Unable to allocate string.");
+ fail_unless(lwc_intern_string("World", 5, &str2) == lwc_error_ok,
+ "Unable to allocate string.");
+ fail_unless(lwc_string_caseless_isequal(str1, str2, &result) == lwc_error_oom,
+ "Able to caselessly compare despite no memory");
- lwc_context_unref(ctx);
}
END_TEST
/**** The next set of tests need a fixture set ****/
-static lwc_context *shared_ctx;
-
static void
with_simple_context_setup(void)
{
- fail_unless(lwc_create_context(trivial_alloc_fn, NULL,
- &shared_ctx) == lwc_error_ok,
- "Unable to create context");
- lwc_context_ref(shared_ctx);
+ fail_unless(lwc_initialise(trivial_alloc_fn, NULL, 0) == lwc_error_ok,
+ "Unable to initialise library");
}
static void
with_simple_context_teardown(void)
{
- lwc_context_unref(shared_ctx);
+ /* Nothing to do to tear down */
}
-START_TEST (test_lwc_context_intern_ok)
+START_TEST (test_lwc_intern_string_ok)
{
lwc_string *str = NULL;
- fail_unless(lwc_context_intern(shared_ctx, "A", 1, &str) == lwc_error_ok,
+ fail_unless(lwc_intern_string("A", 1, &str) == lwc_error_ok,
"Unable to intern a simple string");
fail_unless(str != NULL,
"Returned OK but str was still NULL");
}
END_TEST
-START_TEST (test_lwc_context_intern_twice_ok)
+START_TEST (test_lwc_intern_string_twice_ok)
{
lwc_string *str1 = NULL, *str2 = NULL;
- fail_unless(lwc_context_intern(shared_ctx, "A", 1, &str1) == lwc_error_ok,
+ fail_unless(lwc_intern_string("A", 1, &str1) == lwc_error_ok,
"Unable to intern a simple string");
fail_unless(str1 != NULL,
"Returned OK but str was still NULL");
- fail_unless(lwc_context_intern(shared_ctx, "B", 1, &str2) == lwc_error_ok,
+ fail_unless(lwc_intern_string("B", 1, &str2) == lwc_error_ok,
"Unable to intern a simple string");
fail_unless(str2 != NULL,
"Returned OK but str was still NULL");
}
END_TEST
-START_TEST (test_lwc_context_intern_twice_same_ok)
+START_TEST (test_lwc_intern_string_twice_same_ok)
{
lwc_string *str1 = NULL, *str2 = NULL;
- fail_unless(lwc_context_intern(shared_ctx, "A", 1, &str1) == lwc_error_ok,
+ fail_unless(lwc_intern_string("A", 1, &str1) == lwc_error_ok,
"Unable to intern a simple string");
fail_unless(str1 != NULL,
"Returned OK but str was still NULL");
- fail_unless(lwc_context_intern(shared_ctx, "A", 1, &str2) == lwc_error_ok,
+ fail_unless(lwc_intern_string("A", 1, &str2) == lwc_error_ok,
"Unable to intern a simple string");
fail_unless(str2 != NULL,
"Returned OK but str was still NULL");
}
END_TEST
-START_TEST (test_lwc_context_size_non_zero)
-{
- fail_unless(lwc_context_size(shared_ctx) > 0,
- "Size of empty context is zero");
-}
-END_TEST
-
-START_TEST (test_lwc_context_size_updated_on_string_intern)
-{
- size_t empty_size = lwc_context_size(shared_ctx);
- lwc_string *str;
-
- fail_unless(empty_size > 0,
- "Size of empty context is zero");
-
- fail_unless(lwc_context_intern(shared_ctx, "one", 3, &str) == lwc_error_ok,
- "Unable to intern a simple string");
-
- fail_unless(lwc_context_size(shared_ctx) > empty_size,
- "Post-intern context size is same or smaller than empty size");
-}
-END_TEST
-
-START_TEST (test_lwc_context_size_updated_on_string_unref)
-{
- size_t empty_size = lwc_context_size(shared_ctx);
- lwc_string *str;
-
- fail_unless(empty_size > 0,
- "Size of empty context is zero");
-
- fail_unless(lwc_context_intern(shared_ctx, "one", 3, &str) == lwc_error_ok,
- "Unable to intern a simple string");
-
- fail_unless(lwc_context_size(shared_ctx) > empty_size,
- "Post-intern context size is same or smaller than empty size");
-
- lwc_context_string_unref(shared_ctx, str);
-
- fail_unless(lwc_context_size(shared_ctx) == empty_size,
- "Post-unref context size is not the same as empty size");
-}
-END_TEST
-
-START_TEST (test_lwc_context_size_updated_on_substring_intern)
-{
- size_t empty_size = lwc_context_size(shared_ctx);
- size_t post_intern_size = 0;
- lwc_string *str, *str2;
-
- fail_unless(empty_size > 0,
- "Size of empty context is zero");
-
- fail_unless(lwc_context_intern(shared_ctx, "one", 3, &str) == lwc_error_ok,
- "Unable to intern a simple string");
-
- post_intern_size = lwc_context_size(shared_ctx);
-
- fail_unless(post_intern_size > empty_size,
- "Post-intern context size is same or smaller than empty size");
-
- fail_unless(lwc_context_intern_substring(shared_ctx, str, 0, 1, &str2) == lwc_error_ok,
- "Failed to intern substring");
-
- fail_unless(lwc_context_size(shared_ctx) > post_intern_size,
- "Post-substring-intern context size is same or smaller than pre-substring-intern size");
-}
-END_TEST
-
-START_TEST (test_lwc_context_size_updated_on_substring_unref)
-{
- size_t empty_size = lwc_context_size(shared_ctx);
- size_t post_intern_size = 0;
- lwc_string *str, *str2;
-
- fail_unless(empty_size > 0,
- "Size of empty context is zero");
-
- fail_unless(lwc_context_intern(shared_ctx, "one", 3, &str) == lwc_error_ok,
- "Unable to intern a simple string");
-
- post_intern_size = lwc_context_size(shared_ctx);
-
- fail_unless(post_intern_size > empty_size,
- "Post-intern context size is same or smaller than empty size");
-
- fail_unless(lwc_context_intern_substring(shared_ctx, str, 0, 1, &str2) == lwc_error_ok,
- "Failed to intern substring");
-
- fail_unless(lwc_context_size(shared_ctx) > post_intern_size,
- "Post-substring-intern context size is same or smaller than pre-substring-intern size");
-
- lwc_context_string_unref(shared_ctx, str2);
-
- fail_unless(lwc_context_size(shared_ctx) == post_intern_size,
- "Post-substring-unref size is not the same as pre-substring-intern size");
-}
-END_TEST
-
/**** The next set of tests need a fixture set with some strings ****/
-static lwc_string *intern_one = NULL, *intern_two = NULL, *intern_three = NULL;
+static lwc_string *intern_one = NULL, *intern_two = NULL, *intern_three = NULL, *intern_YAY = NULL;
static void
with_filled_context_setup(void)
{
- fail_unless(lwc_create_context(trivial_alloc_fn, NULL,
- &shared_ctx) == lwc_error_ok,
- "Unable to create context");
- lwc_context_ref(shared_ctx);
+ fail_unless(lwc_initialise(trivial_alloc_fn, NULL, 2) == lwc_error_ok,
+ "Unable to initialise library");
- fail_unless(lwc_context_intern(shared_ctx, "one", 3, &intern_one) == lwc_error_ok,
- "Unable to intern 'one'");
- fail_unless(lwc_context_intern(shared_ctx, "two", 3, &intern_two) == lwc_error_ok,
- "Unable to intern 'one'");
- fail_unless(lwc_context_intern(shared_ctx, "three", 5, &intern_three) == lwc_error_ok,
+ fail_unless(lwc_intern_string("one", 3, &intern_one) == lwc_error_ok,
"Unable to intern 'one'");
+ fail_unless(lwc_intern_string("two", 3, &intern_two) == lwc_error_ok,
+ "Unable to intern 'two'");
+ fail_unless(lwc_intern_string("three", 5, &intern_three) == lwc_error_ok,
+ "Unable to intern 'three'");
+ fail_unless(lwc_intern_string("YAY", 3, &intern_YAY) == lwc_error_ok,
+ "Unable to intern 'YAY'");
fail_unless(intern_one != intern_two, "'one' == 'two'");
fail_unless(intern_one != intern_three, "'one' == 'three'");
@@ -408,14 +254,17 @@ with_filled_context_setup(void)
static void
with_filled_context_teardown(void)
{
- lwc_context_unref(shared_ctx);
+ lwc_string_unref(intern_one);
+ lwc_string_unref(intern_two);
+ lwc_string_unref(intern_three);
+ lwc_string_unref(intern_YAY);
}
START_TEST (test_lwc_interning_works)
{
lwc_string *new_one = NULL;
- fail_unless(lwc_context_intern(shared_ctx, "one", 3, &new_one) == lwc_error_ok,
+ fail_unless(lwc_intern_string("one", 3, &new_one) == lwc_error_ok,
"Unable to re-intern 'one'");
fail_unless(new_one == intern_one,
@@ -427,62 +276,113 @@ START_TEST (test_lwc_intern_substring)
{
lwc_string *new_hre = NULL, *sub_hre = NULL;
- fail_unless(lwc_context_intern(shared_ctx, "hre", 3,
- &new_hre) == lwc_error_ok,
+ fail_unless(lwc_intern_string("hre", 3, &new_hre) == lwc_error_ok,
"Unable to intern 'hre'");
- fail_unless(lwc_context_intern_substring(shared_ctx, intern_three,
- 1, 3, &sub_hre) == lwc_error_ok,
+ fail_unless(lwc_intern_substring(intern_three,
+ 1, 3, &sub_hre) == lwc_error_ok,
"Unable to re-intern 'hre' by substring");
fail_unless(new_hre == sub_hre,
"'hre' != 'hre' -- wow!");
}
END_TEST
-START_TEST (test_lwc_context_string_ref_ok)
+START_TEST (test_lwc_intern_substring_bad_offset)
{
- fail_unless(lwc_context_string_ref(shared_ctx, intern_one) == intern_one,
+ lwc_string *str;
+
+ fail_unless(lwc_intern_substring(intern_three, 100, 1, &str) == lwc_error_range,
+ "Able to intern substring starting out of range");
+}
+END_TEST
+
+START_TEST (test_lwc_intern_substring_bad_size)
+{
+ lwc_string *str;
+
+ fail_unless(lwc_intern_substring(intern_three, 1, 100, &str) == lwc_error_range,
+ "Able to intern substring ending out of range");
+}
+END_TEST
+
+START_TEST (test_lwc_string_ref_ok)
+{
+ fail_unless(lwc_string_ref(intern_one) == intern_one,
"Oddly, reffing a string didn't return it");
}
END_TEST
-START_TEST (test_lwc_context_string_unref_ok)
+START_TEST (test_lwc_string_unref_ok)
+{
+ lwc_string_unref(intern_one);
+}
+END_TEST
+
+START_TEST (test_lwc_string_ref_unref_ok)
{
- lwc_context_string_unref(shared_ctx, intern_one);
+ lwc_string_ref(intern_one);
+ lwc_string_unref(intern_one);
}
END_TEST
-START_TEST (test_lwc_context_string_isequal_ok)
+START_TEST (test_lwc_string_isequal_ok)
{
bool result = true;
- fail_unless((lwc_context_string_isequal(shared_ctx, intern_one,
- intern_two, &result)) == lwc_error_ok,
+ fail_unless((lwc_string_isequal(intern_one, intern_two, &result)) == lwc_error_ok,
"Failure comparing 'one' and 'two'");
fail_unless(result == false,
"'one' == 'two' ?!");
}
END_TEST
-START_TEST (test_lwc_context_string_caseless_isequal_ok)
+START_TEST (test_lwc_string_caseless_isequal_ok1)
{
bool result = true;
lwc_string *new_ONE;
- fail_unless(lwc_context_intern(shared_ctx, "ONE", 3, &new_ONE) == lwc_error_ok,
+ fail_unless(lwc_intern_string("ONE", 3, &new_ONE) == lwc_error_ok,
"Failure interning 'ONE'");
- fail_unless((lwc_context_string_isequal(shared_ctx, intern_one, new_ONE,
- &result)) == lwc_error_ok);
+ fail_unless((lwc_string_isequal(intern_one, new_ONE, &result)) == lwc_error_ok);
fail_unless(result == false,
"'one' == 'ONE' ?!");
- fail_unless((lwc_context_string_caseless_isequal(shared_ctx, intern_one,
- new_ONE, &result)) == lwc_error_ok,
- "Failure comparing 'one' and 'two'");
+ fail_unless((lwc_string_caseless_isequal(intern_one, new_ONE, &result)) == lwc_error_ok,
+ "Failure comparing 'one' and 'ONE' caselessly");
fail_unless(result == true,
"'one' !~= 'ONE' ?!");
}
END_TEST
+START_TEST (test_lwc_string_caseless_isequal_ok2)
+{
+ bool result = true;
+ lwc_string *new_yay;
+
+ fail_unless(lwc_intern_string("yay", 3, &new_yay) == lwc_error_ok,
+ "Failure interning 'yay'");
+
+ fail_unless((lwc_string_isequal(intern_YAY, new_yay, &result)) == lwc_error_ok);
+ fail_unless(result == false,
+ "'yay' == 'YAY' ?!");
+
+ fail_unless((lwc_string_caseless_isequal(intern_YAY, new_yay, &result)) == lwc_error_ok,
+ "Failure comparing 'yay' and 'YAY' caselessly");
+ fail_unless(result == true,
+ "'yay' !~= 'YAY' ?!");
+}
+END_TEST
+
+START_TEST (test_lwc_string_caseless_isequal_bad)
+{
+ bool result = true;
+
+ fail_unless(lwc_string_caseless_isequal(intern_YAY, intern_one, &result) == lwc_error_ok,
+ "Failure comparing 'YAY' and 'one' caselessly");
+ fail_unless(result == false,
+ "'YAY' ~= 'one' ?!");
+}
+END_TEST
+
START_TEST (test_lwc_extract_data_ok)
{
fail_unless(memcmp("one",
@@ -502,7 +402,7 @@ START_TEST (test_lwc_string_is_nul_terminated)
{
lwc_string *new_ONE;
- fail_unless(lwc_context_intern(shared_ctx, "ONE", 3, &new_ONE) == lwc_error_ok,
+ fail_unless(lwc_intern_string("ONE", 3, &new_ONE) == lwc_error_ok,
"Failure interning 'ONE'");
fail_unless(lwc_string_data(new_ONE)[lwc_string_length(new_ONE)] == '\0',
@@ -515,10 +415,10 @@ START_TEST (test_lwc_substring_is_nul_terminated)
lwc_string *new_ONE;
lwc_string *new_O;
- fail_unless(lwc_context_intern(shared_ctx, "ONE", 3, &new_ONE) == lwc_error_ok,
+ fail_unless(lwc_intern_string("ONE", 3, &new_ONE) == lwc_error_ok,
"Failure interning 'ONE'");
- fail_unless(lwc_context_intern_substring(shared_ctx, new_ONE, 0, 1, &new_O) == lwc_error_ok,
+ fail_unless(lwc_intern_substring(new_ONE, 0, 1, &new_O) == lwc_error_ok,
"Failure interning substring 'O'");
fail_unless(lwc_string_data(new_O)[lwc_string_length(new_O)] == '\0',
@@ -536,52 +436,22 @@ lwc_basic_suite(SRunner *sr)
#ifndef NDEBUG
tcase_add_test_raise_signal(tc_basic,
- test_lwc_context_creation_bad_alloc_aborts,
- SIGABRT);
- tcase_add_test_raise_signal(tc_basic,
- test_lwc_context_destruction_aborts,
+ test_lwc_intern_string_aborts1,
SIGABRT);
tcase_add_test_raise_signal(tc_basic,
- test_lwc_context_ref_aborts,
+ test_lwc_intern_string_aborts2,
SIGABRT);
tcase_add_test_raise_signal(tc_basic,
- test_lwc_context_unref_aborts,
+ test_lwc_intern_substring_aborts1,
SIGABRT);
tcase_add_test_raise_signal(tc_basic,
- test_lwc_context_intern_aborts1,
+ test_lwc_intern_substring_aborts2,
SIGABRT);
tcase_add_test_raise_signal(tc_basic,
- test_lwc_context_intern_aborts2,
+ test_lwc_string_ref_aborts,
SIGABRT);
tcase_add_test_raise_signal(tc_basic,
- test_lwc_context_intern_aborts3,
- SIGABRT);
- tcase_add_test_raise_signal(tc_basic,
- test_lwc_context_intern_substring_aborts1,
- SIGABRT);
- tcase_add_test_raise_signal(tc_basic,
- test_lwc_context_intern_substring_aborts2,
- SIGABRT);
- tcase_add_test_raise_signal(tc_basic,
- test_lwc_context_intern_substring_aborts3,
- SIGABRT);
- tcase_add_test_raise_signal(tc_basic,
- test_lwc_context_intern_substring_aborts4,
- SIGABRT);
- tcase_add_test_raise_signal(tc_basic,
- test_lwc_context_intern_substring_aborts5,
- SIGABRT);
- tcase_add_test_raise_signal(tc_basic,
- test_lwc_context_string_ref_aborts1,
- SIGABRT);
- tcase_add_test_raise_signal(tc_basic,
- test_lwc_context_string_ref_aborts2,
- SIGABRT);
- tcase_add_test_raise_signal(tc_basic,
- test_lwc_context_string_unref_aborts1,
- SIGABRT);
- tcase_add_test_raise_signal(tc_basic,
- test_lwc_context_string_unref_aborts2,
+ test_lwc_string_unref_aborts,
SIGABRT);
tcase_add_test_raise_signal(tc_basic,
test_lwc_string_data_aborts,
@@ -592,31 +462,24 @@ lwc_basic_suite(SRunner *sr)
tcase_add_test_raise_signal(tc_basic,
test_lwc_string_hash_value_aborts,
SIGABRT);
- tcase_add_test_raise_signal(tc_basic,
- test_lwc_context_size_aborts,
- SIGABRT);
#endif
- tcase_add_test(tc_basic, test_lwc_context_creation_ok);
- tcase_add_test(tc_basic, test_lwc_context_destruction_ok);
- tcase_add_test(tc_basic, test_lwc_reffed_context_destruction_ok);
+ tcase_add_test(tc_basic, test_lwc_double_initialise_fails);
+ tcase_add_test(tc_basic, test_lwc_initialise_fails_with_no_memory);
+ tcase_add_test(tc_basic, test_lwc_initialise_fails_with_low_memory);
+ tcase_add_test(tc_basic, test_lwc_intern_fails_with_no_memory);
+ tcase_add_test(tc_basic, test_lwc_caseless_compare_fails_with_no_memory1);
+ tcase_add_test(tc_basic, test_lwc_caseless_compare_fails_with_no_memory2);
+
suite_add_tcase(s, tc_basic);
tc_basic = tcase_create("Ops with a context");
tcase_add_checked_fixture(tc_basic, with_simple_context_setup,
with_simple_context_teardown);
- tcase_add_test(tc_basic, test_lwc_context_intern_ok);
- tcase_add_test(tc_basic, test_lwc_context_intern_twice_ok);
- tcase_add_test(tc_basic, test_lwc_context_intern_twice_same_ok);
- tcase_add_test(tc_basic, test_lwc_context_size_non_zero);
- tcase_add_test(tc_basic,
- test_lwc_context_size_updated_on_string_intern);
- tcase_add_test(tc_basic, test_lwc_context_size_updated_on_string_unref);
- tcase_add_test(tc_basic,
- test_lwc_context_size_updated_on_substring_intern);
- tcase_add_test(tc_basic,
- test_lwc_context_size_updated_on_substring_unref);
+ tcase_add_test(tc_basic, test_lwc_intern_string_ok);
+ tcase_add_test(tc_basic, test_lwc_intern_string_twice_ok);
+ tcase_add_test(tc_basic, test_lwc_intern_string_twice_same_ok);
suite_add_tcase(s, tc_basic);
tc_basic = tcase_create("Ops with a filled context");
@@ -625,14 +488,19 @@ lwc_basic_suite(SRunner *sr)
with_filled_context_teardown);
tcase_add_test(tc_basic, test_lwc_interning_works);
tcase_add_test(tc_basic, test_lwc_intern_substring);
- tcase_add_test(tc_basic, test_lwc_context_string_ref_ok);
- tcase_add_test(tc_basic, test_lwc_context_string_unref_ok);
- tcase_add_test(tc_basic, test_lwc_context_string_isequal_ok);
- tcase_add_test(tc_basic, test_lwc_context_string_caseless_isequal_ok);
+ tcase_add_test(tc_basic, test_lwc_string_ref_ok);
+ tcase_add_test(tc_basic, test_lwc_string_ref_unref_ok);
+ tcase_add_test(tc_basic, test_lwc_string_unref_ok);
+ tcase_add_test(tc_basic, test_lwc_string_isequal_ok);
+ tcase_add_test(tc_basic, test_lwc_string_caseless_isequal_ok1);
+ tcase_add_test(tc_basic, test_lwc_string_caseless_isequal_ok2);
+ tcase_add_test(tc_basic, test_lwc_string_caseless_isequal_bad);
tcase_add_test(tc_basic, test_lwc_extract_data_ok);
tcase_add_test(tc_basic, test_lwc_string_hash_value_ok);
tcase_add_test(tc_basic, test_lwc_string_is_nul_terminated);
tcase_add_test(tc_basic, test_lwc_substring_is_nul_terminated);
+ tcase_add_test(tc_basic, test_lwc_intern_substring_bad_size);
+ tcase_add_test(tc_basic, test_lwc_intern_substring_bad_offset);
suite_add_tcase(s, tc_basic);
srunner_add_suite(sr, s);
diff --git a/test/memorytests.c b/test/memorytests.c
deleted file mode 100644
index 7c55cce..0000000
--- a/test/memorytests.c
+++ b/dev/null
@@ -1,246 +0,0 @@
-/* test/basictests.c
- *
- * Basic tests for the test suite for libwapcaplet
- *
- * Copyright 2009 The NetSurf Browser Project
- * Daniel Silverstone <dsilvers@netsurf-browser.org>
- */
-
-#include <check.h>
-#include <stdlib.h>
-
-#include "tests.h"
-
-/**** Simple tracking allocator ****/
-
-typedef enum {
- NONE, ALLOC, FREE
-} alloc_op;
-
-static unsigned long bytes = 0;
-static unsigned long allocs = 0;
-static void *last_pw = NULL;
-static alloc_op last_op = NONE;
-
-static void *
-tracking_allocator(void *ptr, size_t len, void *pw)
-{
- void *ret;
- last_pw = pw;
- if (ptr == NULL) {
- last_op = ALLOC;
- bytes += len;
- allocs++;
- ret = malloc(len + sizeof(size_t));
- *(size_t *)ret = len;
- return ((char *) ret) + sizeof(size_t);
- }
- last_op = FREE;
- allocs--;
- bytes -= *(((size_t *)ptr) - 1);
- free((((size_t *)ptr) - 1));
- return NULL;
-}
-
-static lwc_context *ctx = NULL;
-
-static void
-with_tracked_alloc_setup(void)
-{
- fail_unless(lwc_create_context(tracking_allocator, NULL, &ctx) == lwc_error_ok,
- "Unable to create context");
- fail_unless(allocs == 1,
- "Creating a context used more than one alloc?");
- fail_unless(lwc_context_ref(ctx) == ctx,
- "Reffing the context failed to return the context.");
-}
-
-static void
-with_tracked_alloc_teardown(void)
-{
- lwc_context_unref(ctx);
- fail_unless(allocs == 0,
- "Unreffing the context failed to free everything left.");
-}
-
-START_TEST (test_tracking_one_intern)
-{
- lwc_string *str;
- fail_unless(lwc_context_intern(ctx, "one", 3, &str) == lwc_error_ok,
- "Unable to intern 'one'");
- fail_unless(allocs == 2,
- "Interning a string into a fresh context didn't.");
-}
-END_TEST
-
-START_TEST (test_tracking_one_intern_twice)
-{
- lwc_string *str;
- fail_unless(lwc_context_intern(ctx, "one", 3, &str) == lwc_error_ok,
- "Unable to intern 'one'");
- fail_unless(allocs == 2,
- "Interning a string into a fresh context didn't.");
- fail_unless(lwc_context_intern(ctx, "one", 3, &str) == lwc_error_ok,
- "Unable to intern 'one' again");
- fail_unless(allocs == 2,
- "Interning a string again still did.");
-}
-END_TEST
-
-START_TEST (test_tracking_two_interns)
-{
- lwc_string *one, *ONE;
- fail_unless(lwc_context_intern(ctx, "one", 3, &one) == lwc_error_ok,
- "Unable to intern 'one'");
- fail_unless(allocs == 2,
- "Interning a string into a fresh context didn't.");
- fail_unless(lwc_context_intern(ctx, "ONE", 3, &ONE) == lwc_error_ok,
- "Unable to intern 'one' again");
- fail_unless(allocs == 3,
- "Interning a new string didn't.");
-}
-END_TEST
-
-START_TEST (test_tracking_two_interns_caseless1)
-{
- lwc_string *one, *ONE;
- bool comp = false;
- fail_unless(lwc_context_intern(ctx, "one", 3, &one) == lwc_error_ok,
- "Unable to intern 'one'");
- fail_unless(allocs == 2,
- "Interning a string into a fresh context didn't.");
- fail_unless(lwc_context_intern(ctx, "ONE", 3, &ONE) == lwc_error_ok,
- "Unable to intern 'ONE'");
- fail_unless(allocs == 3,
- "Interning a new string didn't.");
- fail_unless(lwc_context_string_caseless_isequal(ctx, one, ONE, &comp) == lwc_error_ok,
- "Unable to caseless compare");
- fail_unless(allocs == 3,
- "Caseless compare created worthless new values");
- fail_unless(comp == true,
- "Caseless compare failed to spot that 'one' and 'ONE' are the same");
-}
-END_TEST
-
-START_TEST (test_tracking_two_interns_caseless2)
-{
- lwc_string *one, *ONE;
- bool comp = false;
- fail_unless(lwc_context_intern(ctx, "oNe", 3, &one) == lwc_error_ok,
- "Unable to intern 'oNe'");
- fail_unless(allocs == 2,
- "Interning a string into a fresh context didn't.");
- fail_unless(lwc_context_intern(ctx, "ONE", 3, &ONE) == lwc_error_ok,
- "Unable to intern 'ONE'");
- fail_unless(allocs == 3,
- "Interning a new string didn't.");
- fail_unless(lwc_context_string_caseless_isequal(ctx, one, ONE, &comp) == lwc_error_ok,
- "Unable to caseless compare");
- fail_unless(allocs == 4,
- "Caseless compare didn't make one caseless 'one'");
- fail_unless(comp == true,
- "Caseless compare failed to spot that 'oNe' and 'ONE' are the same");
-}
-END_TEST
-
-START_TEST (test_tracking_caseless_unref1)
-{
- lwc_string *one, *ONE;
- bool comp = false;
- fail_unless(lwc_context_intern(ctx, "one", 3, &one) == lwc_error_ok,
- "Unable to intern 'one'");
- fail_unless(allocs == 2,
- "Interning a string into a fresh context didn't.");
- fail_unless(lwc_context_intern(ctx, "ONE", 3, &ONE) == lwc_error_ok,
- "Unable to intern 'ONE'");
- fail_unless(allocs == 3,
- "Interning a new string didn't.");
- fail_unless(lwc_context_string_caseless_isequal(ctx, one, ONE, &comp) == lwc_error_ok,
- "Unable to caseless compare");
- fail_unless(allocs == 3,
- "Caseless compare made pointless additional 'one'");
- fail_unless(comp == true,
- "Caseless compare failed to spot that 'oNe' and 'ONE' are the same");
-
- lwc_context_string_unref(ctx, ONE);
- fail_unless(allocs == 2, "Unreffing 'ONE' failed to free something");
-}
-END_TEST
-
-START_TEST (test_tracking_caseless_unref2)
-{
- lwc_string *one, *ONE;
- bool comp = false;
- fail_unless(lwc_context_intern(ctx, "one", 3, &one) == lwc_error_ok,
- "Unable to intern 'one'");
- fail_unless(allocs == 2,
- "Interning a string into a fresh context didn't.");
- fail_unless(lwc_context_intern(ctx, "ONE", 3, &ONE) == lwc_error_ok,
- "Unable to intern 'ONE'");
- fail_unless(allocs == 3,
- "Interning a new string didn't.");
- fail_unless(lwc_context_string_caseless_isequal(ctx, one, ONE, &comp) == lwc_error_ok,
- "Unable to caseless compare");
- fail_unless(allocs == 3,
- "Caseless compare made pointless additional 'one'");
- fail_unless(comp == true,
- "Caseless compare failed to spot that 'oNe' and 'ONE' are the same");
-
- lwc_context_string_unref(ctx, ONE);
- fail_unless(allocs == 2, "Unreffing 'ONE' failed to free something");
-
- lwc_context_string_unref(ctx, one);
- fail_unless(allocs == 1, "Unreffing 'one' failed to free something");
-}
-END_TEST
-
-START_TEST (test_tracking_caseless_unref3)
-{
- lwc_string *one, *ONE;
- bool comp = false;
- fail_unless(lwc_context_intern(ctx, "one", 3, &one) == lwc_error_ok,
- "Unable to intern 'one'");
- fail_unless(allocs == 2,
- "Interning a string into a fresh context didn't.");
- fail_unless(lwc_context_intern(ctx, "ONE", 3, &ONE) == lwc_error_ok,
- "Unable to intern 'ONE'");
- fail_unless(allocs == 3,
- "Interning a new string didn't.");
- fail_unless(lwc_context_string_caseless_isequal(ctx, one, ONE, &comp) == lwc_error_ok,
- "Unable to caseless compare");
- fail_unless(allocs == 3,
- "Caseless compare made pointless additional 'one'");
- fail_unless(comp == true,
- "Caseless compare failed to spot that 'oNe' and 'ONE' are the same");
-
- lwc_context_string_unref(ctx, one);
- fail_unless(allocs == 3, "Unreffing 'one' freed something");
-
- lwc_context_string_unref(ctx, ONE);
- fail_unless(allocs == 1, "Unreffing 'ONE' failed to free both things");
-}
-END_TEST
-
-/**** And the suites are set up here ****/
-
-void
-lwc_memory_suite(SRunner *sr)
-{
- Suite *s = suite_create("libwapcaplet: Memory allocation tests");
- TCase *tc_mem = tcase_create("memory");
-
- tcase_add_checked_fixture(tc_mem, with_tracked_alloc_setup,
- with_tracked_alloc_teardown);
-
- tcase_add_test(tc_mem, test_tracking_one_intern);
- tcase_add_test(tc_mem, test_tracking_one_intern_twice);
- tcase_add_test(tc_mem, test_tracking_two_interns);
- tcase_add_test(tc_mem, test_tracking_two_interns_caseless1);
- tcase_add_test(tc_mem, test_tracking_two_interns_caseless2);
- tcase_add_test(tc_mem, test_tracking_caseless_unref1);
- tcase_add_test(tc_mem, test_tracking_caseless_unref2);
- tcase_add_test(tc_mem, test_tracking_caseless_unref3);
-
- suite_add_tcase(s, tc_mem);
- srunner_add_suite(sr, s);
-}
diff --git a/test/testmain.c b/test/testmain.c
index 7c5aee9..95fd6d2 100644
--- a/test/testmain.c
+++ b/test/testmain.c
@@ -31,7 +31,7 @@ main(int argc, char **argv)
sr = srunner_create(suite_create("Test suite for libwapcaplet"));
lwc_basic_suite(sr);
- lwc_memory_suite(sr);
+// lwc_memory_suite(sr);
srunner_set_fork_status(sr, CK_FORK);
srunner_run_all(sr, CK_ENV);