Commit 3caea08b authored by Linshizhi's avatar Linshizhi

Add Property Based Testing.

parent a88100c1
...@@ -20,14 +20,14 @@ function(add_test_with_ffmpeg target) ...@@ -20,14 +20,14 @@ function(add_test_with_ffmpeg target)
add_executable(${target} ${CMAKE_CURRENT_SOURCE_DIR}/main.c ${ARGN}) add_executable(${target} ${CMAKE_CURRENT_SOURCE_DIR}/main.c ${ARGN})
add_dependencies(${target} libav) add_dependencies(${target} libav)
link_to_ffmpeg(${target}) link_to_ffmpeg(${target})
target_link_libraries(${target} protos) target_link_libraries(${target} protos theft)
add_test(NAME ${target} add_test(NAME ${target}
COMMAND ${target}) COMMAND ${target})
endfunction() endfunction()
function(add_test_raw target) function(add_test_raw target)
add_executable(${target} ${CMAKE_CURRENT_SOURCE_DIR}/main.c ${ARGN}) 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}) add_test(NAME ${target} COMMAND ${target})
endfunction() endfunction()
......
#include "ctest.h" #include "ctest.h"
#include "theft.h"
#include "basic/container/list.h" #include "basic/container/list.h"
#include <malloc.h> #include <malloc.h>
/*****************************************************************************/
/* Properties */
/*****************************************************************************/
void LIST_EMPTY_STATUS_CHECK(List *l) { typedef struct ValInfo {
ASSERT_TRUE(listEmpty(l)); int *vals;
ASSERT_TRUE(l->head.next == NULL); int numOfVals;
ASSERT_TRUE(l->head.prev == NULL); } ValInfo;
ASSERT_TRUE(l->tail == NULL);
ASSERT_TRUE(listSize(l) == 0);
} 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) { int *pos = vi->vals;
List *l; for (int i = 0; i < limit; ++i) {
}; *pos = theft_random_choice(t, 1024);
++pos;
}
CTEST_SETUP(LIST_TEST) { *instance = vi;
data->l = createList();
listSetDestructor(data->l, (NodeDestructor)free);
}
CTEST_TEARDOWN(LIST_TEST) { return THEFT_ALLOC_OK;
destroyList(&data->l);
} }
CTEST2(LIST_TEST, RELEASE_DATAS_REMAIN_IN_LIST) { static struct theft_type_info random_data_info = {
int *val = NULL; .alloc = random_data_alloc_cb,
for (int i = 0; i < 1000; ++i) { };
val = (int*)malloc(sizeof(int));
listPush(data->l, val); 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) { for (int i = 0; i < limit; ++i) {
val = (int*)malloc(sizeof(int)); listPush(l, &vi->vals[i]);
*val = i;
listPush(data->l, val);
} }
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) { if (*v != vi->vals[i])
ASSERT_EQUAL(*(int*)n->val, i); return THEFT_TRIAL_FAIL;
n = nodeNext(n);
} }
return THEFT_TRIAL_PASS;
} }
CTEST2(LIST_TEST, POP) {
int *val = NULL;
for (int i = 0; i < 1000; ++i) { /*****************************************************************************/
val = (int*)malloc(sizeof(int)); /* Runner */
*val = i; /*****************************************************************************/
listPush(data->l, val);
}
for (int i = 0; i < 1000; ++i) { bool test_list_push_pop_size_match(void) {
val = listPop(data->l); theft_seed seed = theft_seed_of_time();
ASSERT_EQUAL(*(int*)val, i);
free(val); 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) { bool test_list_push_pop_equal_and_in_order(void) {
void *v = NULL; theft_seed seed = theft_seed_of_time();
for (int i = 0; i < 1000; ++i) { struct theft_run_config config = {
v = listPop(data->l); .name = __func__,
ASSERT_NULL(v); .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) { CTEST_SETUP(LIST_TEST) {
val = listGet(data->l, i); data->l = createList();
printf("%d\n", *(int*)val); listSetDestructor(data->l, (NodeDestructor)free);
ASSERT_EQUAL(*(int*)val, i);
}
} }
CTEST2(LIST_TEST, RANDOM_ACCESS_EMPTY) { CTEST_TEARDOWN(LIST_TEST) {
int *val = NULL; destroyList(&data->l);
for (int i = 0; i < 256; ++i) { }
val = listGet(data->l, i);
ASSERT_NULL(val); 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