Add unit tests, some fixes to Deque.

This commit is contained in:
Stephen Seo 2019-01-27 15:09:38 +09:00
parent dd984b85a6
commit 599ac8a23e
5 changed files with 260 additions and 23 deletions

View file

@ -3,7 +3,7 @@ project(UDPConnection)
set(UDPConnection_SOURCES
src/UDPConnection.c
src/Deque.c
src/UDPC_Deque.c
)
set(CMAKE_C_FLAGS "-Wall -Wno-missing-braces")
@ -19,3 +19,12 @@ endif()
add_library(UDPConnection ${UDPConnection_SOURCES})
target_compile_features(UDPConnection PUBLIC c_std_11)
target_link_libraries(UDPConnection PUBLIC pthread)
if(CMAKE_BUILD_TYPE MATCHES "Debug")
set(UDPC_UnitTest_SOURCES
src/test/UDPC_UnitTest.c)
add_executable(UnitTest ${UDPC_UnitTest_SOURCES})
target_link_libraries(UnitTest PUBLIC UDPConnection)
target_include_directories(UnitTest PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src)
endif()

View file

@ -1,4 +1,4 @@
#include "Deque.h"
#include "UDPC_Deque.h"
#include <stdlib.h>
#include <string.h>
@ -41,6 +41,12 @@ int UDPC_Deque_realloc(UDPC_Deque *deque, uint32_t new_size)
free(deque->buf);
deque->buf = buf;
deque->alloc_size = new_size;
deque->head = 0;
deque->tail = deque->size;
if(deque->tail == deque->alloc_size)
{
deque->tail = 0;
}
return 1;
}
else
@ -59,7 +65,7 @@ int UDPC_Deque_realloc(UDPC_Deque *deque, uint32_t new_size)
}
}
int UDPC_Deque_push_back(UDPC_Deque *deque, const char *data, uint32_t size)
int UDPC_Deque_push_back(UDPC_Deque *deque, const void *data, uint32_t size)
{
if(deque->size + size > deque->alloc_size)
{
@ -90,14 +96,14 @@ int UDPC_Deque_push_back(UDPC_Deque *deque, const char *data, uint32_t size)
}
if(size > 0)
{
memcpy(&deque->buf[deque->tail], &data[temp], size);
memcpy(&deque->buf[deque->tail], &((const char*)data)[temp], size);
deque->tail += size;
deque->size += size;
}
return 1;
}
int UDPC_Deque_push_front(UDPC_Deque *deque, const char *data, uint32_t size)
int UDPC_Deque_push_front(UDPC_Deque *deque, const void *data, uint32_t size)
{
if(deque->size + size > deque->alloc_size)
{
@ -114,7 +120,7 @@ int UDPC_Deque_push_front(UDPC_Deque *deque, const char *data, uint32_t size)
if(deque->head > 0)
{
memcpy(deque->buf, &data[size - deque->head], deque->head);
memcpy(deque->buf, &((const char*)data)[size - deque->head], deque->head);
deque->size += deque->head;
size -= deque->head;
deque->head = 0;
@ -138,7 +144,7 @@ uint32_t UDPC_Deque_get_used(UDPC_Deque *deque)
return deque->size;
}
int UDPC_Deque_get_back(UDPC_Deque *deque, char **data, uint32_t *size)
int UDPC_Deque_get_back(UDPC_Deque *deque, void **data, uint32_t *size)
{
int returnValue = 1;
if(deque->size == 0)
@ -169,7 +175,7 @@ int UDPC_Deque_get_back(UDPC_Deque *deque, char **data, uint32_t *size)
return returnValue;
}
int UDPC_Deque_get_front(UDPC_Deque *deque, char **data, uint32_t *size)
int UDPC_Deque_get_front(UDPC_Deque *deque, void **data, uint32_t *size)
{
int returnValue = 1;
if(deque->size == 0)
@ -252,11 +258,11 @@ void UDPC_Deque_pop_front(UDPC_Deque *deque, uint32_t size)
}
}
int UDPC_Deque_index(UDPC_Deque *deque, uint32_t unitSize, uint32_t index, char **out)
int UDPC_Deque_index(UDPC_Deque *deque, uint32_t unitSize, uint32_t index, void **out)
{
uint32_t pos = unitSize * index;
uint32_t abspos;
if(pos >= deque->alloc_size)
if(pos >= deque->size)
{
*out = NULL;
return 0;
@ -286,11 +292,11 @@ int UDPC_Deque_index(UDPC_Deque *deque, uint32_t unitSize, uint32_t index, char
return 1;
}
int UDPC_Deque_index_rev(UDPC_Deque *deque, uint32_t unitSize, uint32_t index, char **out)
int UDPC_Deque_index_rev(UDPC_Deque *deque, uint32_t unitSize, uint32_t index, void **out)
{
uint32_t pos = unitSize * (index + 1);
uint32_t abspos;
if(pos >= deque->alloc_size)
if(pos >= deque->size + unitSize)
{
*out = NULL;
return 0;

View file

@ -33,13 +33,13 @@ int UDPC_Deque_realloc(UDPC_Deque *deque, uint32_t new_size);
* If there was not enough space in the Deque, then no data is inserted at all.
* \return non-zero on success (there was enough size to insert data)
*/
int UDPC_Deque_push_back(UDPC_Deque *deque, const char *data, uint32_t size);
int UDPC_Deque_push_back(UDPC_Deque *deque, const void *data, uint32_t size);
/*!
* If there was not enough space in the Deque, then no data is inserted at all.
* \return non-zero on success (there was enough size to insert data)
*/
int UDPC_Deque_push_front(UDPC_Deque *deque, const char *data, uint32_t size);
int UDPC_Deque_push_front(UDPC_Deque *deque, const void *data, uint32_t size);
/*!
* \return size in bytes of available data
@ -58,7 +58,7 @@ uint32_t UDPC_Deque_get_used(UDPC_Deque *deque);
* updated to allocated amount. If deque is empty, no data is allocated.
* \return non-zero if full requested size was returned
*/
int UDPC_Deque_get_back(UDPC_Deque *deque, char **data, uint32_t *size);
int UDPC_Deque_get_back(UDPC_Deque *deque, void **data, uint32_t *size);
/*!
* \brief Get data from front of deque
@ -67,7 +67,7 @@ int UDPC_Deque_get_back(UDPC_Deque *deque, char **data, uint32_t *size);
* updated to allocated amount. If deque is empty, no data is allocated.
* \return non-zero if full requested size was returned
*/
int UDPC_Deque_get_front(UDPC_Deque *deque, char **data, uint32_t *size);
int UDPC_Deque_get_front(UDPC_Deque *deque, void **data, uint32_t *size);
/*!
* \brief "free" data from the back of the deque
@ -92,22 +92,22 @@ void UDPC_Deque_pop_front(UDPC_Deque *deque, uint32_t size);
* The data will be indexed relative to the head of the Deque.
* The out pointer will be malloc'd with size unitSize and will have a copy of
* the data at the specified unitSize * index.
* Note that the out data must be free'd, but nothing will be malloc'd on fail
* Note that the out data must be free'd, but on fail nothing will be malloc'd
* and *out will be set to NULL.
* \return non-zero if unitSize * index < allocated_size_of_Deque
* \return non-zero if unitSize * index < size
*/
int UDPC_Deque_index(UDPC_Deque *deque, uint32_t unitSize, uint32_t index, char **out);
int UDPC_Deque_index(UDPC_Deque *deque, uint32_t unitSize, uint32_t index, void **out);
/*!
* \brief Get a unitSize sized chunk of data at position relative to tail
* The out pointer will be malloc'd with size unitSize and will have a copy of
* the data at the specified unitSize * (index + 1) relative to tail in reverse
* the data at the specified unitSize * index relative to tail in reverse
* direction.
* Note that the out data must be free'd, but nothing will be malloc'd on fail
* Note that the out data must be free'd, but on fail nothing will be malloc'd
* and *out will be set to NULL.
* \return non-zero if unitSize * (index + 1) < allocated_size_of_Deque
* \return non-zero if unitSize * index < size
*/
int UDPC_Deque_index_rev(UDPC_Deque *deque, uint32_t unitSize, uint32_t index, char **out);
int UDPC_Deque_index_rev(UDPC_Deque *deque, uint32_t unitSize, uint32_t index, void **out);
void UDPC_Deque_clear(UDPC_Deque *deque);

176
src/test/UDPC_UnitTest.c Normal file
View file

@ -0,0 +1,176 @@
#include "UDPC_UnitTest.h"
#include <stdlib.h>
#include <UDPC_Deque.h>
static UnitTestState UDPC_uts = {0, 0};
int main()
{
int arr[32];
char *temp = NULL;
uint32_t size;
for(int x = 0; x < 32; ++x)
{
arr[x] = x;
}
UDPC_Deque deque;
// init
ASSERT_TRUE(UDPC_Deque_init(&deque, sizeof(int) * 32));
ASSERT_TRUE(deque.buf);
ASSERT_EQ(deque.head, 0);
ASSERT_EQ(deque.tail, 0);
ASSERT_EQ(deque.size, 0);
ASSERT_EQ(deque.alloc_size, sizeof(int) * 32);
// realloc smaller success
ASSERT_TRUE(UDPC_Deque_realloc(&deque, sizeof(int) * 16));
ASSERT_TRUE(deque.buf);
ASSERT_EQ(deque.head, 0);
ASSERT_EQ(deque.tail, 0);
ASSERT_EQ(deque.size, 0);
ASSERT_EQ(deque.alloc_size, sizeof(int) * 16);
// push back success
ASSERT_TRUE(UDPC_Deque_push_back(&deque, arr, sizeof(int) * 4));
ASSERT_EQ_MEM(arr, deque.buf, sizeof(int) * 4);
ASSERT_EQ(deque.size, sizeof(int) * 4);
// push front success
ASSERT_TRUE(UDPC_Deque_push_front(&deque, &arr[4], sizeof(int) * 4));
ASSERT_EQ_MEM(&arr[4], &deque.buf[sizeof(int) * 12], sizeof(int) * 4);
ASSERT_EQ(deque.size, sizeof(int) * 8);
// realloc bigger success
ASSERT_TRUE(UDPC_Deque_realloc(&deque, sizeof(int) * 32));
ASSERT_EQ_MEM(&arr[4], deque.buf, sizeof(int) * 4);
ASSERT_EQ_MEM(arr, &deque.buf[sizeof(int) * 4], sizeof(int) * 4);
ASSERT_EQ(deque.alloc_size, sizeof(int) * 32);
// pop front success
UDPC_Deque_pop_front(&deque, sizeof(int) * 4);
ASSERT_EQ(deque.size, sizeof(int) * 4);
// get front success
size = sizeof(int) * 4;
ASSERT_TRUE(UDPC_Deque_get_front(&deque, (void**)&temp, &size));
ASSERT_EQ(size, sizeof(int) * 4);
ASSERT_EQ_MEM(arr, temp, size);
free(temp);
// pop back success
UDPC_Deque_pop_back(&deque, sizeof(int) * 4);
ASSERT_EQ(deque.size, 0);
// push front success
ASSERT_TRUE(UDPC_Deque_push_front(&deque, arr, sizeof(int) * 16));
ASSERT_EQ(deque.size, sizeof(int) * 16);
// get front success
size = sizeof(int) * 16;
ASSERT_TRUE(UDPC_Deque_get_front(&deque, (void**)&temp, &size));
ASSERT_EQ(size, sizeof(int) * 16);
ASSERT_EQ_MEM(arr, temp, size);
free(temp);
// get back success
size = sizeof(int) * 16;
ASSERT_TRUE(UDPC_Deque_get_back(&deque, (void**)&temp, &size));
ASSERT_EQ(size, sizeof(int) * 16);
ASSERT_EQ_MEM(arr, temp, size);
free(temp);
// realloc smaller fail
ASSERT_FALSE(UDPC_Deque_realloc(&deque, sizeof(int) * 8));
ASSERT_EQ(deque.size, sizeof(int) * 16);
ASSERT_EQ(deque.alloc_size, sizeof(int) * 32);
// realloc smaller success
ASSERT_TRUE(UDPC_Deque_realloc(&deque, sizeof(int) * 16));
ASSERT_EQ(deque.size, sizeof(int) * 16);
ASSERT_EQ(deque.alloc_size, sizeof(int) * 16);
ASSERT_EQ_MEM(deque.buf, arr, sizeof(int) * 16);
// push back fail
ASSERT_FALSE(UDPC_Deque_push_back(&deque, arr, sizeof(int) * 16));
ASSERT_EQ(deque.size, sizeof(int) * 16);
ASSERT_EQ(deque.alloc_size, sizeof(int) * 16);
ASSERT_EQ_MEM(deque.buf, arr, sizeof(int) * 16);
// push front fail
ASSERT_FALSE(UDPC_Deque_push_back(&deque, arr, sizeof(int) * 16));
ASSERT_EQ(deque.size, sizeof(int) * 16);
ASSERT_EQ(deque.alloc_size, sizeof(int) * 16);
ASSERT_EQ_MEM(deque.buf, arr, sizeof(int) * 16);
// pop back
UDPC_Deque_pop_back(&deque, sizeof(int) * 8);
// get front success
size = sizeof(int) * 8;
ASSERT_TRUE(UDPC_Deque_get_front(&deque, (void**)&temp, &size));
ASSERT_EQ(size, sizeof(int) * 8);
ASSERT_EQ_MEM(temp, arr, sizeof(int) * 8);
free(temp);
// get front fail
size = sizeof(int) * 16;
ASSERT_FALSE(UDPC_Deque_get_front(&deque, (void**)&temp, &size));
ASSERT_EQ(size, sizeof(int) * 8);
ASSERT_EQ_MEM(temp, arr, sizeof(int) * 8);
free(temp);
// get back success
size = sizeof(int) * 8;
ASSERT_TRUE(UDPC_Deque_get_back(&deque, (void**)&temp, &size));
ASSERT_EQ(size, sizeof(int) * 8);
ASSERT_EQ_MEM(temp, arr, sizeof(int) * 8);
free(temp);
// get back fail
size = sizeof(int) * 16;
ASSERT_FALSE(UDPC_Deque_get_back(&deque, (void**)&temp, &size));
ASSERT_EQ(size, sizeof(int) * 8);
ASSERT_EQ_MEM(temp, arr, sizeof(int) * 8);
free(temp);
// index success
for(int x = 0; x < 8; ++x)
{
ASSERT_TRUE(UDPC_Deque_index(&deque, sizeof(int), x, (void**)&temp));
if(temp)
{
ASSERT_EQ_MEM(temp, &arr[x], sizeof(int));
free(temp);
}
}
// index fail
ASSERT_FALSE(UDPC_Deque_index(&deque, sizeof(int), 8, (void**)&temp));
ASSERT_FALSE(temp);
// index_rev success
for(int x = 0; x < 8; ++x)
{
ASSERT_TRUE(UDPC_Deque_index_rev(&deque, sizeof(int), x, (void**)&temp));
if(temp)
{
ASSERT_EQ_MEM(temp, &arr[7 - x], sizeof(int));
free(temp);
}
}
// index_rev fail
ASSERT_FALSE(UDPC_Deque_index_rev(&deque, sizeof(int), 8, (void**)&temp));
ASSERT_FALSE(temp);
/*
printf("asize %d, size %d, head %d, tail %d\n",
deque.alloc_size, deque.size, deque.head, deque.tail);
*/
UDPC_Deque_destroy(&deque);
UNITTEST_REPORT()
return 0;
}

46
src/test/UDPC_UnitTest.h Normal file
View file

@ -0,0 +1,46 @@
#ifndef UDPC_UNIT_TEST_H
#define UDPC_UNIT_TEST_H
#include <stdio.h>
#include <string.h>
/*
#include <UDPC_Deque.h>
*/
#define ASSERT_TRUE(x) \
if(!x) { printf("%d: ASSERT_TRUE(%s) FAILED\n", __LINE__, #x); \
++UDPC_uts.failed; } ++UDPC_uts.total;
#define ASSERT_FALSE(x) \
if(x) { printf("%d: ASSERT_FALSE(%s) FAILED\n", __LINE__, #x); \
++UDPC_uts.failed; } ++UDPC_uts.total;
#define ASSERT_EQ(x, y) \
if(x != y) { printf("%d: ASSERT_EQ(%s, %s) FAILED\n", __LINE__, #x, #y); \
++UDPC_uts.failed; } ++UDPC_uts.total;
#define ASSERT_NEQ(x, y) \
if(x == y) { printf("%d: ASSERT_NEQ(%s, %s) FAILED\n", __LINE__, #x, #y); \
++UDPC_uts.failed; } ++UDPC_uts.total;
#define ASSERT_EQ_MEM(x, y, size) \
if(memcmp(x, y, size) != 0) { printf("%d: ASSERT_EQ_MEM(%s, %s, %s) FAILED\n", \
__LINE__, #x, #y, #size); ++UDPC_uts.failed; } ++UDPC_uts.total;
#define ASSERT_NEQ_MEM(x, y, size) \
if(memcmp(x, y, size) == 0) { printf("%d: ASSERT_NEQ_MEM(%s, %s, %s) FAILED\n", \
__LINE__, #x, #y, #size); ++UDPC_uts.failed; } ++UDPC_uts.total;
#define UNITTEST_REPORT() printf("%d/%d tests failed\n", UDPC_uts.failed, UDPC_uts.total);
typedef struct
{
int result;
} UnitTest_Test;
typedef struct
{
int failed;
int total;
} UnitTestState;
static UnitTestState UDPC_uts;
#endif