Commit 3caea08b authored by Linshizhi's avatar Linshizhi

Add Property Based Testing.

parent a88100c1
......@@ -20,14 +20,14 @@ function(add_test_with_ffmpeg target)
add_executable(${target} ${CMAKE_CURRENT_SOURCE_DIR}/main.c ${ARGN})
add_dependencies(${target} libav)
link_to_ffmpeg(${target})
target_link_libraries(${target} protos)
target_link_libraries(${target} protos theft)
add_test(NAME ${target}
COMMAND ${target})
endfunction()
function(add_test_raw target)
add_executable(${target} ${CMAKE_CURRENT_SOURCE_DIR}/main.c ${ARGN})
target_link_libraries(${target} protos)
target_link_libraries(${target} protos theft)
add_test(NAME ${target} COMMAND ${target})
endfunction()
......
#include "ctest.h"
#include "theft.h"
#include "basic/container/list.h"
#include <malloc.h>
/*****************************************************************************/
/* Properties */
/*****************************************************************************/
void LIST_EMPTY_STATUS_CHECK(List *l) {
ASSERT_TRUE(listEmpty(l));
ASSERT_TRUE(l->head.next == NULL);
ASSERT_TRUE(l->head.prev == NULL);
ASSERT_TRUE(l->tail == NULL);
ASSERT_TRUE(listSize(l) == 0);
typedef struct ValInfo {
int *vals;
int numOfVals;
} ValInfo;
}
enum theft_alloc_res
random_data_alloc_cb(struct theft *t, void *env, void **instance) {
uint64_t limit = theft_random_choice(t, 1000);
ValInfo *vi = (ValInfo*)malloc(sizeof(ValInfo));
vi->vals = (int*)malloc(limit*sizeof(int));
vi->numOfVals = limit;
CTEST_DATA(LIST_TEST) {
List *l;
};
int *pos = vi->vals;
for (int i = 0; i < limit; ++i) {
*pos = theft_random_choice(t, 1024);
++pos;
}
CTEST_SETUP(LIST_TEST) {
data->l = createList();
listSetDestructor(data->l, (NodeDestructor)free);
}
*instance = vi;
CTEST_TEARDOWN(LIST_TEST) {
destroyList(&data->l);
return THEFT_ALLOC_OK;
}
CTEST2(LIST_TEST, RELEASE_DATAS_REMAIN_IN_LIST) {
int *val = NULL;
for (int i = 0; i < 1000; ++i) {
val = (int*)malloc(sizeof(int));
listPush(data->l, val);
static struct theft_type_info random_data_info = {
.alloc = random_data_alloc_cb,
};
static enum theft_trial_res
prop_list_push_size_match(struct theft *t, void *arg) {
ValInfo *vi = (ValInfo*)arg;
int limit = vi->numOfVals;
List *l = createList();
for (int i = 0; i < limit; ++i) {
listPush(l, &vi->vals[i]);
if (listSize(l) != i+1)
return THEFT_TRIAL_FAIL;
}
return THEFT_TRIAL_PASS;
}
CTEST2(LIST_TEST, PUSH) {
static enum theft_trial_res
prop_list_push_and_pop_equal_in_order(struct theft *t, void *arg) {
ValInfo *vi = (ValInfo*)arg;
int limit = vi->numOfVals;
int *val = NULL;
List *l = createList();
for (int i = 0; i < 1000; ++i) {
val = (int*)malloc(sizeof(int));
*val = i;
listPush(data->l, val);
for (int i = 0; i < limit; ++i) {
listPush(l, &vi->vals[i]);
}
ASSERT_EQUAL(listSize(data->l), 1000);
Node *n = data->l->head.next;
for (int i = 0; i < limit; ++i) {
int *v = (int *)listPop(l);
for (int i = 0; i < 1000; ++i) {
ASSERT_EQUAL(*(int*)n->val, i);
n = nodeNext(n);
if (*v != vi->vals[i])
return THEFT_TRIAL_FAIL;
}
return THEFT_TRIAL_PASS;
}
CTEST2(LIST_TEST, POP) {
int *val = NULL;
for (int i = 0; i < 1000; ++i) {
val = (int*)malloc(sizeof(int));
*val = i;
listPush(data->l, val);
}
/*****************************************************************************/
/* Runner */
/*****************************************************************************/
for (int i = 0; i < 1000; ++i) {
val = listPop(data->l);
ASSERT_EQUAL(*(int*)val, i);
free(val);
}
bool test_list_push_pop_size_match(void) {
theft_seed seed = theft_seed_of_time();
struct theft_run_config config = {
.name = __func__,
.prop1 = prop_list_push_size_match,
.type_info = { &random_data_info },
.seed = seed
};
LIST_EMPTY_STATUS_CHECK(data->l);
enum theft_run_res res = theft_run(&config);
return res == THEFT_RUN_PASS;
}
CTEST2(LIST_TEST, POP_FROM_EMPTY_LIST) {
void *v = NULL;
bool test_list_push_pop_equal_and_in_order(void) {
theft_seed seed = theft_seed_of_time();
for (int i = 0; i < 1000; ++i) {
v = listPop(data->l);
ASSERT_NULL(v);
}
struct theft_run_config config = {
.name = __func__,
.prop1 = prop_list_push_and_pop_equal_in_order,
.type_info = { &random_data_info },
.seed = seed
};
LIST_EMPTY_STATUS_CHECK(data->l);
return theft_run(&config) == THEFT_RUN_PASS;
}
CTEST2(LIST_TEST, RANDOM_ACCESS) {
int *val = NULL;
for (int i = 0; i < 1000; ++i) {
val = (int*)malloc(sizeof(int));
*val = i;
listPush(data->l, val);
}
CTEST_DATA(LIST_TEST) {
List *l;
};
for (int i = 0; i < 1000; ++i) {
val = listGet(data->l, i);
printf("%d\n", *(int*)val);
ASSERT_EQUAL(*(int*)val, i);
}
CTEST_SETUP(LIST_TEST) {
data->l = createList();
listSetDestructor(data->l, (NodeDestructor)free);
}
CTEST2(LIST_TEST, RANDOM_ACCESS_EMPTY) {
int *val = NULL;
for (int i = 0; i < 256; ++i) {
val = listGet(data->l, i);
ASSERT_NULL(val);
}
CTEST_TEARDOWN(LIST_TEST) {
destroyList(&data->l);
}
CTEST2(LIST_TEST, PROP_LIST_SIZE_MATCH) {
ASSERT_TRUE(test_list_push_pop_size_match());
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment