made data structures immune to call term/destroy twice

This commit is contained in:
tezc 2021-04-13 22:16:30 +03:00
parent 3d11311f90
commit 57e67dc955
24 changed files with 223 additions and 124 deletions

View File

@ -2,9 +2,9 @@
Language: Cpp
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignConsecutiveMacros: true
AlignConsecutiveAssignments: None
AlignConsecutiveDeclarations: None
AlignConsecutiveMacros: None
AlignEscapedNewlines: Right
AlignOperands: Align
AlignTrailingComments: true
@ -100,7 +100,7 @@ PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Right
ReflowComments: true
SortIncludes: true
SortIncludes: CaseSensitive
SortUsingDeclarations: true
SpaceAfterCStyleCast: true
SpaceAfterTemplateKeyword: true

View File

@ -46,6 +46,11 @@ static void test1(void)
{
int *arr, total = 0;
sc_array_create(arr, 10);
assert(arr != NULL);
sc_array_destroy(arr);
assert(arr == NULL);
sc_array_create(arr, 5);
sc_array_add(arr, 3);
sc_array_add(arr, 4);

View File

@ -9,6 +9,24 @@ void test1()
const char *xstr;
struct sc_buf buf, buf2;
sc_buf_init(&buf, 100);
assert(buf.mem != NULL);
sc_buf_term(&buf);
sc_buf_init(&buf2, 0);
assert(buf.mem == buf2.mem);
assert(buf.limit == buf2.limit);
assert(buf.wpos == buf2.wpos);
assert(buf.rpos == buf2.rpos);
assert(buf.ref == buf2.ref);
assert(buf.cap == buf2.cap);
assert(buf.err == buf2.err);
sc_buf_term(&buf2);
sc_buf_put_64(&buf, 100);
assert(sc_buf_get_64(&buf) == 100);
sc_buf_term(&buf);
sc_buf_init(&buf, 100);
sc_buf_set_rpos(&buf, 1);
assert(sc_buf_valid(&buf) == false);

View File

@ -69,6 +69,8 @@ void sc_buf_term(struct sc_buf *b)
if (!b->ref) {
sc_buf_free(b->mem);
}
sc_buf_init(b, 0);
}
void sc_buf_limit(struct sc_buf *b, uint32_t limit)

View File

@ -113,16 +113,17 @@ int sc_thread_start(struct sc_thread *thread, void *(*fn)(void *), void *arg)
int sc_thread_join(struct sc_thread *thread, void **ret)
{
int rc;
void *val;
int rc = 0;
void *val = NULL;
if (thread->id == 0) {
return -1;
goto out;
}
rc = pthread_join(thread->id, &val);
thread->id = 0;
out:
if (ret != NULL) {
*ret = val;
}

View File

@ -4,6 +4,7 @@
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
int example(void)
{
@ -54,6 +55,19 @@ void test1(void)
void *data;
struct sc_heap heap;
sc_heap_init(&heap, 0);
sc_heap_add(&heap, 100, "test");
sc_heap_pop(&heap, &key, &data);
assert(key == 100);
assert(strcmp("test", data) == 0);
sc_heap_term(&heap);
sc_heap_add(&heap, 100, "test");
sc_heap_pop(&heap, &key, &data);
assert(key == 100);
assert(strcmp("test", data) == 0);
sc_heap_term(&heap);
assert(sc_heap_init(&heap, SIZE_MAX / 2) == false);
assert(sc_heap_init(&heap, 3) == true);
@ -67,7 +81,7 @@ void test1(void)
for (int i = 0; i < 10; i++) {
assert(sc_heap_add(&heap, arr[i],
(void *) (uintptr_t)(arr[i] * 2)) == true);
(void *) (uintptr_t) (arr[i] * 2)) == true);
}
for (int i = 0; i < 10; i++) {
@ -97,7 +111,7 @@ void test2(void)
for (int i = 0; i < 10; i++) {
assert(sc_heap_add(&heap, -arr[i],
(void *) (uintptr_t)(arr[i] * 2)) == true);
(void *) (uintptr_t) (arr[i] * 2)) == true);
}
for (int i = 0; i < 10; i++) {

View File

@ -54,6 +54,10 @@ bool sc_heap_init(struct sc_heap *h, size_t cap)
void sc_heap_term(struct sc_heap *h)
{
sc_heap_free(h->elems);
*h = (struct sc_heap){
.elems = NULL,
};
}
size_t sc_heap_size(struct sc_heap *h)

View File

@ -29,7 +29,6 @@
#include "sc_ini.h"
#include <ctype.h>
#include <stdint.h>
#include <string.h>
#if defined(_WIN32) || defined(_WIN64)

View File

@ -186,9 +186,12 @@ int sc_log_term(void)
if (rc != 0) {
rc = -1;
}
sc_log_mutex_term(&sc_log.mtx);
}
sc_log_mutex_term(&sc_log.mtx);
sc_log = (struct sc_log){
.fp = NULL,
};
return rc;
}

View File

@ -518,6 +518,17 @@ void test1()
values[i] = str_random((rand() % 64) + 32);
}
sc_map_init_str(&map, 0, 0);
sc_map_put_str(&map, "100", "200");
sc_map_get_str(&map, "100", &value);
assert(strcmp(value, "200") == 0);
sc_map_term_str(&map);
sc_map_put_str(&map, "100", "200");
sc_map_get_str(&map, "100", &value);
assert(strcmp(value, "200") == 0);
sc_map_term_str(&map);
assert(!sc_map_init_str(&map, 0, -1));
assert(!sc_map_init_str(&map, 0, 24));
assert(!sc_map_init_str(&map, 0, 96));

View File

@ -131,7 +131,7 @@
m->used = false; \
m->cap = cap; \
m->load_fac = f; \
m->remap = (uint32_t)(m->cap * ((double) m->load_fac / 100)); \
m->remap = (uint32_t) (m->cap * ((double) m->load_fac / 100)); \
\
return true; \
} \
@ -140,6 +140,7 @@
{ \
if (m->mem != sc_map_empty_##name.mem) { \
sc_map_free(&m->mem[-1]); \
*m = sc_map_empty_##name; \
} \
} \
\
@ -199,7 +200,7 @@
\
m->mem = new; \
m->cap = cap; \
m->remap = (uint32_t)(m->cap * ((double) m->load_fac / 100)); \
m->remap = (uint32_t) (m->cap * ((double) m->load_fac / 100)); \
\
return true; \
} \
@ -330,7 +331,7 @@ static uint32_t sc_map_hash_32(uint32_t a)
static uint32_t sc_map_hash_64(uint64_t a)
{
return ((uint32_t) a) ^ (uint32_t)(a >> 32u);
return ((uint32_t) a) ^ (uint32_t) (a >> 32u);
}
// clang-format off

View File

@ -21,6 +21,8 @@ void test1()
assert(rc == 0);
rc = sc_mmap_term(&mmap);
assert(rc == 0);
rc = sc_mmap_term(&mmap);
assert(rc == 0);
rc = sc_mmap_init(&mmap, "x.txt", O_RDWR | O_CREAT | O_TRUNC,
PROT_READ | PROT_WRITE, MAP_SHARED, 0, 8192);

View File

@ -261,6 +261,10 @@ int sc_mmap_term(struct sc_mmap *m)
{
int rc;
if (m->fd == -1) {
return 0;
}
close(m->fd);
rc = munmap(m->ptr, m->len);
@ -268,6 +272,12 @@ int sc_mmap_term(struct sc_mmap *m)
strncpy(m->err, strerror(errno), sizeof(m->err) - 1);
}
*m = (struct sc_mmap) {
.ptr = NULL,
.fd = -1,
.len = 0,
};
return rc;
}

View File

@ -135,13 +135,14 @@ char *sc_str_create_fmt(const char *fmt, ...)
return str;
}
void sc_str_destroy(char *str)
void sc_str_destroy(char **str)
{
if (str == NULL) {
if (str == NULL || *str == NULL) {
return;
}
sc_str_free(sc_str_meta(str));
sc_str_free(sc_str_meta(*str));
*str = NULL;
}
int64_t sc_str_len(const char *str)
@ -174,7 +175,7 @@ bool sc_str_set(char **str, const char *param)
return false;
}
sc_str_destroy(*str);
sc_str_destroy(str);
*str = c;
return true;
@ -190,7 +191,7 @@ bool sc_str_set_fmt(char **str, const char *fmt, ...)
va_end(args);
if (ret != NULL) {
sc_str_destroy(*str);
sc_str_destroy(str);
*str = ret;
}
@ -310,7 +311,7 @@ bool sc_str_trim(char **str, const char *list)
return false;
}
sc_str_destroy(*str);
sc_str_destroy(str);
*str = head;
}
@ -336,7 +337,7 @@ bool sc_str_substring(char **str, uint32_t start, uint32_t end)
return false;
}
sc_str_destroy(*str);
sc_str_destroy(str);
*str = c;
return true;
@ -416,7 +417,7 @@ bool sc_str_replace(char **str, const char *replace, const char *with)
memcpy(tmp, orig, orig_end - orig + 1);
sc_str_destroy(*str);
sc_str_destroy(str);
*str = dest->buf;
return true;

View File

@ -82,7 +82,7 @@ char *sc_str_create_va(const char *fmt, va_list va);
* Deallocate length prefixed string.
* @param str length prefixed string. str may be NULL.
*/
void sc_str_destroy(char *str);
void sc_str_destroy(char **str);
/**
* @param str length prefixed string. NULL values are accepted.

View File

@ -62,6 +62,13 @@ int __wrap_vsnprintf(char *str, size_t size, const char *format, va_list ap)
void test1()
{
char* m = sc_str_create(NULL);
sc_str_destroy(&m);
sc_str_append(&m, "test");
sc_str_append_fmt(&m, "%d", 3);
assert(strcmp(m, "test3") == 0);
sc_str_destroy(&m);
assert(sc_str_len(NULL) == -1);
sc_str_destroy(NULL);
assert(sc_str_dup(NULL) == NULL);
@ -79,8 +86,8 @@ void test1()
assert(strcmp(s1, "test3") == 0);
fail_malloc = false;
sc_str_destroy(s1);
sc_str_destroy(s2);
sc_str_destroy(&s1);
sc_str_destroy(&s2);
fail_malloc = true;
assert(sc_str_create("test") == NULL);
@ -96,8 +103,8 @@ void test1()
assert(strcmp(s1, "5test5") == 0);
s2 = sc_str_dup(s1);
assert(sc_str_cmp(s1, s2) == true);
sc_str_destroy(s1);
sc_str_destroy(s2);
sc_str_destroy(&s1);
sc_str_destroy(&s2);
fail_malloc = true;
s1 = sc_str_create_fmt("%dtest%d", 5, 5);
@ -152,7 +159,7 @@ void test1()
assert(strcmp(s1, "test") == 0);
fail_vsnprintf_at = -1;
free(s2);
sc_str_destroy(s1);
sc_str_destroy(&s1);
fail_vsnprintf = true;
assert(!sc_str_set_fmt(&s1, "test%d", 3));
@ -201,7 +208,7 @@ void test2()
fail_strlen = 2;
assert(sc_str_replace(&c, "*", "2") == false);
fail_strlen = INT32_MAX;
sc_str_destroy(c);
sc_str_destroy(&c);
c = sc_str_create("n1n1");
assert(sc_str_substring(&c, -1, -3) == false);
@ -218,7 +225,7 @@ void test2()
assert(sc_str_append(&c, "12") == false);
fail_realloc = false;
sc_str_destroy(c);
sc_str_destroy(&c);
fail_vsnprintf_at = 2;
fail_vnsprintf_value = -1;
@ -243,7 +250,7 @@ void test2()
assert(tmp[i] == x1[i]);
}
sc_str_destroy(x1);
sc_str_destroy(&x1);
free(tmp);
x1 = NULL;
@ -255,7 +262,7 @@ void test2()
assert(x1[i] == 'x');
}
assert(sc_str_len(x1) == 4000);
sc_str_destroy(x1);
sc_str_destroy(&x1);
}
#endif
@ -308,7 +315,7 @@ void test3()
while ((token = sc_str_token_begin(str, &save, "-")) != NULL) {
}
sc_str_token_end(str, &save);
sc_str_destroy(str);
sc_str_destroy(&str);
str = sc_str_create(NULL);
save = NULL;
@ -316,12 +323,12 @@ void test3()
assert(strcmp(token, "token") == 0);
}
sc_str_token_end(str, &save);
sc_str_destroy(str);
sc_str_destroy(&str);
str = sc_str_create("x,x");
save = NULL;
sc_str_token_end(str, &save);
sc_str_destroy(str);
sc_str_destroy(&str);
str = sc_str_create("x,x");
save = NULL;
@ -330,7 +337,7 @@ void test3()
break;
}
sc_str_token_end(str, &save);
sc_str_destroy(str);
sc_str_destroy(&str);
str = sc_str_create("x,x");
save = NULL;
@ -340,7 +347,7 @@ void test3()
}
sc_str_token_end(str, &save);
sc_str_token_end(str, &save);
sc_str_destroy(str);
sc_str_destroy(&str);
}
void test4()
@ -405,7 +412,7 @@ void test4()
sc_str_token_end(str, &save);
assert(strcmp(str, "tk1;tk2-tk3 tk4 tk5*tk6") == 0);
sc_str_destroy(str);
sc_str_destroy(&str);
}
void test5()
@ -419,7 +426,7 @@ void test5()
assert(strcmp(s2, "test") == 0);
assert(sc_str_len(s2) == 4);
assert(strcmp(s1, s2) == 0);
sc_str_destroy(s2);
sc_str_destroy(&s2);
sc_str_set(&s1, "test2");
assert(strcmp(s1, "test2") == 0);
@ -452,7 +459,7 @@ void test5()
assert(strcmp(s1, "longeRlongeR") == 0);
assert(sc_str_replace(&s1, "longeR", ""));
assert(strcmp(s1, "") == 0);
sc_str_destroy(s1);
sc_str_destroy(&s1);
s1 = sc_str_create("*test * test*");
sc_str_trim(&s1, "*");
@ -465,29 +472,29 @@ void test5()
sc_str_set(&s1, "testtx");
sc_str_trim(&s1, "a");
sc_str_destroy(s1);
sc_str_destroy(&s1);
s1 = sc_str_create(" elem1,elem2, elem3 ");
sc_str_trim(&s1, " ");
assert(strcmp(s1, "elem1,elem2, elem3") == 0);
sc_str_replace(&s1, " ", "");
assert(strcmp(s1, "elem1,elem2,elem3") == 0);
sc_str_destroy(s1);
sc_str_destroy(&s1);
s1 = sc_str_create("elem1,elem2,elem3");
sc_str_replace(&s1, "elem", "item");
assert(strcmp(s1, "item1,item2,item3") == 0);
sc_str_destroy(s1);
sc_str_destroy(&s1);
s1 = sc_str_create(NULL);
assert(sc_str_append_fmt(&s1, "%s", "string") == true);
assert(strcmp(s1, "string") == 0);
sc_str_destroy(s1);
sc_str_destroy(&s1);
s1 = sc_str_create(NULL);
sc_str_append(&s1, "string");
assert(strcmp(s1, "string") == 0);
sc_str_destroy(s1);
sc_str_destroy(&s1);
s1 = sc_str_create(NULL);
assert(sc_str_trim(&s1, "x") == true);
@ -499,17 +506,17 @@ void test5()
assert(sc_str_dup(s1) == NULL);
assert(sc_str_set(&s1, "string") == true);
assert(strcmp(s1, "string") == 0);
sc_str_destroy(s1);
sc_str_destroy(&s1);
s1 = sc_str_create(NULL);
assert(sc_str_set_fmt(&s1, "%s", "string") == true);
assert(strcmp(s1, "string") == 0);
sc_str_destroy(s1);
sc_str_destroy(&s1);
s1 = sc_str_create(NULL);
assert(sc_str_set(&s1, "string") == true);
assert(strcmp(s1, "string") == 0);
sc_str_destroy(s1);
sc_str_destroy(&s1);
}
void test6()
@ -521,47 +528,47 @@ void test6()
s1 = sc_str_create(NULL);
assert(s1 == NULL);
sc_str_destroy(s1);
sc_str_destroy(&s1);
s1 = sc_str_create_len(NULL, 100);
assert(s1 == NULL);
sc_str_destroy(s1);
sc_str_destroy(&s1);
s1 = NULL;
b = sc_str_set(&s1, "test");
assert(b);
assert(strcmp(s1, "test") == 0);
sc_str_destroy(s1);
sc_str_destroy(&s1);
s1 = NULL;
b = sc_str_set_fmt(&s1, "test");
assert(b);
assert(strcmp(s1, "test") == 0);
sc_str_destroy(s1);
sc_str_destroy(&s1);
s1 = NULL;
b = sc_str_append(&s1, "test");
assert(b);
assert(strcmp(s1, "test") == 0);
sc_str_destroy(s1);
sc_str_destroy(&s1);
s1 = NULL;
b = sc_str_trim(&s1, "*");
assert(b);
assert(s1 == NULL);
sc_str_destroy(s1);
sc_str_destroy(&s1);
s1 = NULL;
b = sc_str_substring(&s1, 0, 0);
assert(!b);
assert(s1 == NULL);
sc_str_destroy(s1);
sc_str_destroy(&s1);
s1 = NULL;
b = sc_str_replace(&s1, "s", "a");
assert(b);
assert(s1 == NULL);
sc_str_destroy(s1);
sc_str_destroy(&s1);
s1 = NULL;
while ((token = sc_str_token_begin(s1, &save, ";")) != NULL) {
@ -570,15 +577,15 @@ void test6()
}
sc_str_token_end(s1, &save);
sc_str_destroy(s1);
sc_str_destroy(&s1);
s1 = sc_str_create("de1");
s2 = sc_str_create("de2");
assert(!sc_str_cmp(s1, s2));
sc_str_set(&s1, "dee2");
assert(!sc_str_cmp(s1, s2));
sc_str_destroy(s1);
sc_str_destroy(s2);
sc_str_destroy(&s1);
sc_str_destroy(&s2);
}
int main()

View File

@ -78,12 +78,12 @@ int sc_thread_start(struct sc_thread *t, void *(*fn)(void *), void *arg)
int sc_thread_join(struct sc_thread *t, void **ret)
{
int rc = 0;
void* val = NULL;
DWORD rv;
BOOL brc;
if (t->id == 0) {
strncpy(t->err, "Already stopped.", sizeof(t->err));
return -1;
goto out;
}
rv = WaitForSingleObject(t->id, INFINITE);
@ -98,7 +98,10 @@ int sc_thread_join(struct sc_thread *t, void **ret)
rc = -1;
}
val = t->ret;
t->id = 0;
out:
if (ret != NULL) {
*ret = t->ret;
}
@ -134,20 +137,17 @@ int sc_thread_start(struct sc_thread *t, void *(*fn)(void *), void *arg)
int sc_thread_join(struct sc_thread *t, void **ret)
{
int rc;
void *val;
int rc = 0;
void *val = NULL;
if (t->id == 0) {
return -1;
goto out;
}
rc = pthread_join(t->id, &val);
if (rc != 0) {
strncpy(t->err, strerror(rc), sizeof(t->err) - 1);
}
t->id = 0;
out:
if (ret != NULL) {
*ret = val;
}

View File

@ -26,7 +26,9 @@ void test1()
assert(strcmp((char *) ret, "first") == 0);
rc = sc_thread_term(&thread);
assert(rc == -1);
assert(rc == 0);
rc = sc_thread_term(&thread);
assert(rc == 0);
sc_thread_init(&thread);
rc = sc_thread_start(&thread, fn, "first");

View File

@ -34,34 +34,20 @@
#define SC_TIMER_MAX (UINT32_MAX / sizeof(struct sc_timer_data)) / WHEEL_COUNT
#endif
bool sc_timer_init(struct sc_timer *t, uint64_t timestamp)
void sc_timer_init(struct sc_timer *t, uint64_t timestamp)
{
const uint32_t wheel_cap = 4;
const uint32_t cap = WHEEL_COUNT * wheel_cap;
const size_t size = cap * sizeof(struct sc_timer_data);
t->count = 0;
t->head = 0;
t->wheel = wheel_cap;
t->timestamp = timestamp;
t->list = sc_timer_malloc(size);
if (t->list == NULL) {
return false;
}
for (uint32_t i = 0; i < cap; i++) {
t->list[i].timeout = UINT64_MAX;
t->list[i].data = NULL;
}
return true;
*t = (struct sc_timer){
.timestamp = timestamp,
};
}
void sc_timer_term(struct sc_timer *t)
{
sc_timer_free(t->list);
*t = (struct sc_timer){
.timestamp = t->timestamp,
};
}
void sc_timer_clear(struct sc_timer *t)
@ -79,7 +65,8 @@ void sc_timer_clear(struct sc_timer *t)
static bool expand(struct sc_timer *t)
{
uint32_t cap = t->wheel * WHEEL_COUNT * 2;
uint32_t wheel = t->wheel != 0 ? t->wheel * 2 : 4;
uint32_t cap = wheel * WHEEL_COUNT * 2;
size_t size = cap * sizeof(struct sc_timer_data);
struct sc_timer_data *alloc;
@ -111,7 +98,7 @@ static bool expand(struct sc_timer *t)
sc_timer_free(t->list);
t->list = alloc;
t->wheel *= 2;
t->wheel = wheel;
return true;
}
@ -119,12 +106,11 @@ static bool expand(struct sc_timer *t)
uint64_t sc_timer_add(struct sc_timer *t, uint64_t timeout, uint64_t type,
void *data)
{
const uint32_t offset = (uint32_t)(timeout / TICK + t->head);
const uint32_t offset = (uint32_t) (timeout / TICK + t->head);
const uint32_t pos = offset & (WHEEL_COUNT - 1);
uint64_t id;
uint32_t seq, index, wheel_pos;
wheel_pos = (pos * t->wheel);
for (seq = 0; seq < t->wheel; seq++) {
index = wheel_pos + seq;
@ -176,7 +162,7 @@ uint64_t sc_timer_timeout(struct sc_timer *t, uint64_t timestamp, void *arg,
const uint64_t time = timestamp - t->timestamp;
uint32_t wheel, base;
uint32_t head = t->head;
uint32_t wheels = (uint32_t)(sc_timer_min(time / TICK, WHEEL_COUNT));
uint32_t wheels = (uint32_t) (sc_timer_min(time / TICK, WHEEL_COUNT));
struct sc_timer_data *item;
if (wheels == 0) {

View File

@ -60,9 +60,8 @@ struct sc_timer {
*
* @param t timer
* @param timestamp current timestamp. Use monotonic timer source.
* @return 'false' on out of memory.
*/
bool sc_timer_init(struct sc_timer *t, uint64_t timestamp);
void sc_timer_init(struct sc_timer *t, uint64_t timestamp);
/**
* Destroy timer.

View File

@ -81,7 +81,8 @@ void test1(void)
{
struct sc_timer timer;
assert(sc_timer_init(&timer, time_ms()));
sc_timer_init(&timer, time_ms());
for (int i = 0; i < 1000; i++) {
ids[i] = sc_timer_add(&timer, rand() % 100, i,
(void *) (uintptr_t) i);
@ -105,13 +106,37 @@ void test1(void)
}
sc_timer_term(&timer);
for (int i = 0; i < 1000; i++) {
ids[i] = sc_timer_add(&timer, rand() % 100, i,
(void *) (uintptr_t) i);
assert(ids[i] != SC_TIMER_INVALID);
}
t = 10000;
while (t > 0) {
n = sc_timer_timeout(&timer, time_ms(),
(void *) (uintptr_t) 333, callback);
if (timer.count == 0) {
break;
}
t -= n;
sleep_ms(n);
}
for (int i = 0; i < 1000; i++) {
assert(ids[i] == SC_TIMER_INVALID);
}
sc_timer_term(&timer);
}
void test2(void)
{
struct sc_timer timer;
assert(sc_timer_init(&timer, time_ms()));
sc_timer_init(&timer, time_ms());
for (int i = 0; i < 1000; i++) {
ids[i] = SC_TIMER_INVALID;
sc_timer_add(&timer, rand() % 100, i, (void *) (uintptr_t) i);
@ -164,7 +189,8 @@ void test3(void)
{
struct sc_timer timer;
assert(sc_timer_init(&timer, time_ms()));
sc_timer_init(&timer, time_ms());
for (int i = 0; i < 1000; i++) {
ids[i] = sc_timer_add(&timer, rand() % 20, i,
(void *) (uintptr_t) i);
@ -202,7 +228,8 @@ void test4(void)
{
struct sc_timer timer;
assert(sc_timer_init(&timer, 0));
sc_timer_init(&timer, 0);
for (int i = 0; i < 1000; i++) {
ids[i] = sc_timer_add(&timer, rand() % 20, i,
(void *) (uintptr_t) i);
@ -256,10 +283,7 @@ void fail_test(void)
size_t max = 50000;
struct sc_timer timer;
fail_malloc = true;
assert(sc_timer_init(&timer, time_ms()) == false);
fail_malloc = false;
assert(sc_timer_init(&timer, time_ms()) == true);
sc_timer_init(&timer, time_ms());
uint64_t id;
for (size_t i = 0; i < max + 100; i++) {

View File

@ -174,7 +174,12 @@ error:
return NULL;
}
void sc_uri_destroy(struct sc_uri *uri)
void sc_uri_destroy(struct sc_uri **uri)
{
sc_uri_free(uri);
if (uri == NULL || *uri == NULL) {
return;
}
sc_uri_free(*uri);
*uri = NULL;
}

View File

@ -100,6 +100,6 @@ struct sc_uri *sc_uri_create(const char *str);
/**
* @param uri uri
*/
void sc_uri_destroy(struct sc_uri *uri);
void sc_uri_destroy(struct sc_uri **uri);
#endif

View File

@ -12,6 +12,11 @@ void test1(void)
const char *f = "foo://user:password@example.com:8042/over/"
"there?name=ferret#nose";
uri = sc_uri_create("");
assert(uri == NULL);
sc_uri_destroy(&uri);
sc_uri_destroy(NULL);
uri = sc_uri_create(f);
assert(uri != NULL);
assert(strcmp(uri->str, f) == 0);
@ -23,7 +28,7 @@ void test1(void)
assert(strcmp(uri->query, "name=ferret") == 0);
assert(strcmp(uri->fragment, "nose") == 0);
sc_uri_destroy(uri);
sc_uri_destroy(&uri);
}
void test2(void)
@ -43,7 +48,7 @@ void test2(void)
assert(strcmp(uri->query, "tag=networking&order=newest") == 0);
assert(strcmp(uri->fragment, "top") == 0);
sc_uri_destroy(uri);
sc_uri_destroy(&uri);
}
void test3(void)
@ -62,7 +67,7 @@ void test3(void)
assert(strcmp(uri->query, "objectClass?one") == 0);
assert(strcmp(uri->fragment, "") == 0);
sc_uri_destroy(uri);
sc_uri_destroy(&uri);
}
void test4(void)
@ -81,7 +86,7 @@ void test4(void)
assert(strcmp(uri->query, "") == 0);
assert(strcmp(uri->fragment, "") == 0);
sc_uri_destroy(uri);
sc_uri_destroy(&uri);
}
void test5(void)
@ -100,7 +105,7 @@ void test5(void)
assert(strcmp(uri->query, "") == 0);
assert(strcmp(uri->fragment, "") == 0);
sc_uri_destroy(uri);
sc_uri_destroy(&uri);
}
void test6(void)
@ -119,7 +124,7 @@ void test6(void)
assert(strcmp(uri->query, "") == 0);
assert(strcmp(uri->fragment, "") == 0);
sc_uri_destroy(uri);
sc_uri_destroy(&uri);
}
void test7(void)
@ -138,7 +143,7 @@ void test7(void)
assert(strcmp(uri->query, "") == 0);
assert(strcmp(uri->fragment, "") == 0);
sc_uri_destroy(uri);
sc_uri_destroy(&uri);
}
void test8(void)
@ -158,7 +163,7 @@ void test8(void)
assert(strcmp(uri->query, "") == 0);
assert(strcmp(uri->fragment, "") == 0);
sc_uri_destroy(uri);
sc_uri_destroy(&uri);
}
void test9(void)
@ -177,7 +182,7 @@ void test9(void)
assert(strcmp(uri->query, "fred") == 0);
assert(strcmp(uri->fragment, "") == 0);
sc_uri_destroy(uri);
sc_uri_destroy(&uri);
}
void test10(void)
@ -196,7 +201,7 @@ void test10(void)
assert(strcmp(uri->query, "") == 0);
assert(strcmp(uri->fragment, "") == 0);
sc_uri_destroy(uri);
sc_uri_destroy(&uri);
}
void test11(void)
@ -213,7 +218,7 @@ void test11(void)
NULL);
assert(sc_uri_create("ldap://[2001:db8::7") == NULL);
sc_uri_destroy(uri);
sc_uri_destroy(&uri);
}
void test12(void)
@ -232,7 +237,7 @@ void test12(void)
assert(strcmp(uri->query, "x") == 0);
assert(strcmp(uri->fragment, "3") == 0);
sc_uri_destroy(uri);
sc_uri_destroy(&uri);
}
void test13(void)
@ -321,13 +326,13 @@ void fail_test()
uri = sc_uri_create("tcp://127.0.0.1");
assert(uri != NULL);
sc_uri_destroy(uri);
sc_uri_destroy(&uri);
uri = sc_uri_create("tcp:/127.0.0.1");
assert(uri != NULL);
assert(strcmp(uri->scheme, "tcp") == 0);
assert(strcmp(uri->path, "/127.0.0.1") == 0);
sc_uri_destroy(uri);
sc_uri_destroy(&uri);
fail_snprintf = -1;
assert(sc_uri_create("tcp://127.0.0.1") == NULL);