Commit 7f1f647b authored by Linshizhi's avatar Linshizhi

Init with unittests.

parents
cmake_minimum_required(VERSION 3.16)
enable_testing()
include(ExternalProject)
project(FFmpeg_Protos)
option(DEBUG "Only enable during development" OFF)
option(STATICLIB "Generate Static Library" OFF)
set(SRCs ${CMAKE_SOURCE_DIR}/src)
# Basics
include_directories(${CMAKE_SOURCE_DIR}/src)
set(SRC_FILES
${SRCs}/proto.c
${SRCs}/basic/list/list.c
${SRCs}/MovMem/mm.c)
if (STATICLIB)
add_library(ffmpegprotos STATIC ${SRC_FILES})
else()
add_library(ffmpegprotos SHARED ${SRC_FILES})
target_link_libraries(ffmpegprotos
avformat avcodec avdevice avfilter avutil
swresample swscale postproc z x264 lzma)
endif()
install(TARGETS ffmpegprotos
DESTINATION ${CMAKE_INSTALL_LIBDIR})
if(DEBUG)
ExternalProject_Add(
libav
GIT_REPOSITORY https://github.com/FFmpeg/FFmpeg.git
GIT_TAG n4.3.3
PREFIX ${PROJECT_SOURCE_DIR}/lib/.build/${LIBAV}
CONFIGURE_COMMAND ../${LIBAV}/configure --disable-x86asm --enable-libx264 --enable-debug --extra-cflags=-g
--extra-ldflags=-g --enable-gpl --shlibdir=${PROJECT_SOURCE_DIR}/lib/
--disable-ffmpeg --disable-ffprobe --disable-ffplay --prefix=${PROJECT_SOURCE_DIR}/lib/
--enable-shared
BUILD_COMMAND make -j
INSTALL_COMMAND make install
UPDATE_COMMAND ""
)
# Tests
set(Tests ${CMAKE_SOURCE_DIR}/tests)
set(TestCases
${SRCs}/basic/list/list.c
${Tests}/main.c
${Tests}/listTestCases.c)
add_executable(unittest ${TestCases} ${SRC_Files})
add_dependencies(unittest libav)
add_custom_command(TARGET unittest PRE_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
${CMAKE_SOURCE_DIR}/resources/ $<TARGET_FILE_DIR:unittest>/resources)
add_test(
NAME UNITTEST_DIRECTLY
COMMAND valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --verbose --log-fil=valgrind-log.txt ./unittest)
# Link Google Test
target_link_libraries(unittest
${CMAKE_SOURCE_DIR}/lib/lib/libavformat.a
${CMAKE_SOURCE_DIR}/lib/lib/libavcodec.a
${CMAKE_SOURCE_DIR}/lib/lib/libavdevice.a
${CMAKE_SOURCE_DIR}/lib/lib/libavfilter.a
${CMAKE_SOURCE_DIR}/lib/lib/libavutil.a
${CMAKE_SOURCE_DIR}/lib/lib/libswresample.a
${CMAKE_SOURCE_DIR}/lib/lib/libswscale.a
${CMAKE_SOURCE_DIR}/lib/lib/libpostproc.a
)
target_link_libraries(unittest z)
target_link_libraries(unittest x264)
target_link_libraries(unittest lzma)
endif()
#include "mm.h"
static int mmRead(void *priv, uint8_t *buf, int size) {
return 0;
}
static int mmWrite(void *priv, uint8_t *buf, int size) {
}
MMProto* createMMProto(void) {
MMProto *p = (MMProto*)malloc(sizeof(MMProto));
p->Base = createProto_(mmRead, mmWrite, NULL, p);
return p;
}
#include "../proto.h"
#include <libavformat/avformat.h>
#ifndef MM_H
#define MM_H
typedef struct MMProto {
Proto Base;
} MMProto;
/* Prototypes */
MMProto* createMMProto(void);
#endif /* MM_H */
#include <string.h>
#include <malloc.h>
#include "list.h"
List* createList() {
List *l = (List*)malloc(sizeof(List));
memset(l, 0, sizeof(List));
return l;
}
void destroyList(List **l_) {
List *l = *l_;
Node *n = listTail(l), *next;
while (n) {
next = nodePrev(n);
if (l->destructor) {
destroyNodeVal(l, n);
free(n);
}
n = next;
}
free(l);
*l_ = NULL;
}
void listPush(List *l, void *val) {
Node *n = (Node*)malloc(sizeof(Node));
n->val = val;
n->prev = NULL;
n->next = NULL;
if (listEmpty(l)) {
listSetHead(l, n);
listSetTail(l, n);
} else {
setNodeNext(listTail(l), n);
setNodePrev(n, listTail(l));
listSetTail(l, n);
}
l->size++;
}
void* listPop(List *l) {
Node *n = listHead(l);
if (n == NULL) {
return n;
}
listSetHead(l, n->next);
if (listEmpty(l)) {
listSetTail(l, NULL);
} else {
setNodePrev(listHead(l), NULL);
}
void *v = n->val;
free(n);
l->size--;
return v;
}
#ifndef LIST_H
#define LIST_H
typedef void (*NodeDestructor)(void *val);
typedef void (*NodeDuplicate)(void *val);
typedef struct Node {
struct Node *prev;
struct Node *next;
void *val;
} Node;
typedef struct List {
Node head;
Node *tail;
/* If destructor is NULL then do nothing */
NodeDestructor destructor;
/* Only copyable when duplicate is not NULL */
NodeDuplicate duplicate;
int size;
} List;
/* Member function implement as macros */
#define listSize(L) ((L)->size)
#define listHead(L) ((L)->head.next)
#define listSetHead(L, N) ((L)->head.next = (N))
#define listTail(L) ((L)->tail)
#define listSetTail(L, N) ((L)->tail = (N))
#define listEmpty(L) ((L)->head.next == NULL)
#define listSetDestructor(L, D) ((L)->destructor=(D))
#define listSetDuplicate(L, Dup) ((L)->duplicate=(Dup))
#define nodePrev(N) ((N)->prev)
#define setNodePrev(NL, NR) ((NL)->prev = (NR))
#define nodeNext(N) ((N)->next)
#define setNodeNext(NL, NR) ((NL)->next = (NR))
#define destroyNodeVal(L, N) ((L)->destructor((N)->val))
#define duplicateNodeVal(L, N) ((L)->duplicate((N)->val))
/* Prototypes */
List* createList(void);
void destroyList(List **l);
void listPush(List *l, void *val);
void* listPop(List *l);
#endif /* LIST_H */
#include "proto.h"
Proto* createProto(ReadFunc rf, WriteFunc wf, SeekFunc sf, void *priv) {
Proto *p = (Proto*)malloc(sizeof(Proto));
p->read = rf;
p->write = wf;
p->seek = sf;
p->priv = priv;
p->avioBuffer = NULL;
return p;
}
Proto createProto_(ReadFunc rf, WriteFunc wf, SeekFunc sf, void *priv) {
Proto p = {
.read = rf,
.write = wf,
.seek = sf,
.priv = priv,
.avioBuffer = NULL,
};
return p;
}
AVIOContext* proto2AVIO(Proto *p, size_t bufSize) {
p->avioBuffer = (unsigned char *)av_malloc(bufSize);
AVIOContext *ioctx = avio_alloc_context(
p->avioBuffer, bufSize, 0,
(void *)p,
p->read,
p->write,
p->seek);
return ioctx;
}
#include <stdint.h>
#include <libavformat/avformat.h>
#ifndef PROTO_H
#define PROTO_H
typedef int (*ReadFunc)(void *priv, uint8_t *buf, int size);
typedef int (*WriteFunc)(void *priv, uint8_t *buf, int size);
typedef int64_t (*SeekFunc)(void *opaque, int64_t offset, int whence);
typedef struct Proto {
int (*read)(void *priv, uint8_t *buf, int size);
int (*write)(void *priv, uint8_t *buf, int size);
int64_t (*seek)(void *opaque, int64_t offset, int whence);
void *priv;
unsigned char *avioBuffer;
} Proto;
/* Member function implement as macros */
#define read(P, priv, buf, size) ((P)->read((priv), (buf), (size)))
#define write(P, priv, buf, size) ((P)->write((priv), (buf), (size)))
#define seek(P, opaque, offset, whence) ((P)->seek((opaque), (offset), (whence)))
/* Prototypes */
Proto* createProto(ReadFunc rf, WriteFunc wr, SeekFunc sf, void *priv);
Proto createProto_(ReadFunc rf, WriteFunc wr, SeekFunc sf, void *priv);
AVIOContext* proto2AVIO(Proto *p, size_t bufSize);
#endif /* PROTO_H */
This diff is collapsed.
#include "ctest.h"
#include "basic/list/list.h"
#include <malloc.h>
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);
}
CTEST_DATA(LIST_TEST) {
List *l;
};
CTEST_SETUP(LIST_TEST) {
data->l = createList();
listSetDestructor(data->l, (NodeDestructor)free);
}
CTEST_TEARDOWN(LIST_TEST) {
destroyList(&data->l);
}
CTEST2(LIST_TEST, PUSH) {
int *val = NULL;
for (int i = 0; i < 1000; ++i) {
val = (int*)malloc(sizeof(int));
*val = i;
listPush(data->l, val);
}
ASSERT_EQUAL(listSize(data->l), 1000);
Node *n = data->l->head.next;
for (int i = 0; i < 1000; ++i) {
ASSERT_EQUAL(*(int*)n->val, i);
n = nodeNext(n);
}
}
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);
}
for (int i = 0; i < 1000; ++i) {
val = listPop(data->l);
ASSERT_EQUAL(*(int*)val, i);
free(val);
}
LIST_EMPTY_STATUS_CHECK(data->l);
}
CTEST2(LIST_TEST, POP_FROM_EMPTY_LIST) {
void *v = NULL;
for (int i = 0; i < 1000; ++i) {
v = listPop(data->l);
ASSERT_NULL(v);
}
LIST_EMPTY_STATUS_CHECK(data->l);
}
#include <stdio.h>
#define CTEST_MAIN
// uncomment lines below to enable/disable features. See README.md for details
#define CTEST_SEGFAULT
//#define CTEST_NO_COLORS
//#define CTEST_COLOR_OK
#include "ctest.h"
int main(int argc, const char *argv[])
{
int result = ctest_main(argc, argv);
return result;
}
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