Skip to content

Commit

Permalink
feat(asan): Address sanitizer (ASAN) tests and utility
Browse files Browse the repository at this point in the history
build system in test/ to run a utility that uses opencv to do the reading, RGBA conversion and screen play with filters, without applying parameters for now.

using both gcc and clang and ASAN debug

also improved test util to generate metadata of each plugin
  • Loading branch information
jaromil committed Jul 22, 2024
1 parent cdeddc7 commit e2d15f8
Show file tree
Hide file tree
Showing 6 changed files with 221 additions and 3 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ endif (NOT CMAKE_BUILD_TYPE)
set (LIBDIR "${CMAKE_INSTALL_LIBDIR}/frei0r-1")
set (FREI0R_DEF "${CMAKE_SOURCE_DIR}/msvc/frei0r_1_0.def")
set (FREI0R_1_1_DEF "${CMAKE_SOURCE_DIR}/msvc/frei0r_1_1.def")
set (FREI0R_1_2_DEF "${CMAKE_SOURCE_DIR}/msvc/frei0r_1_2.def")

# --- custom targets: ---
INCLUDE( cmake/modules/TargetDistclean.cmake OPTIONAL)
Expand Down
12 changes: 12 additions & 0 deletions GNUmakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@


debug:
mkdir -p build
cd build && cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS_DEBUG='-ggdb -fno-omit-frame-pointer -fsanitize=address' -DCMAKE_C_FLAGS_DEBUG='-ggdb -fno-omit-frame-pointer -fsanitize=address' ..
cd build && make


debug-clang-ninja:
mkdir -p build
cd build && cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS_DEBUG='-ggdb -fno-omit-frame-pointer -fsanitize=address' -DCMAKE_C_FLAGS_DEBUG='-ggdb -fno-omit-frame-pointer -fsanitize=address' -G 'Ninja' ..
cd build && ninja
25 changes: 23 additions & 2 deletions test/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,21 @@ INCLUDES ?= -I ../include

PLUGINDIR ?= ../build/src

all: build scan-plugins
CXX ?= g++
DEBUG_FLAGS ?= -O0 -g -ggdb -Wl,-undefined -Wl,dynamic_lookup -fsanitize=address -fsanitize-recover=address -fno-omit-frame-pointer -fsanitize-address-use-after-scope

all: test-utils
# build scan-plugins

frei0r-test: CVFLAGS := $(shell pkg-config --libs --cflags opencv4)
frei0r-test: frei0r-test.c
${CXX} ${DEBUG_FLAGS} -ggdb -O0 -I../include -o frei0r-test frei0r-test.c ${CVFLAGS} -ldl

test-all-filters: frei0r-test
@$(if $(wildcard ${PLUGINDIR}),,>&2 echo "Scan dir not found: ${PLUGINDIR}" && exit 1)
@find ${PLUGINDIR} -type f -name '*.so' -exec ./frei0r-test -t -v ${HOME}/Downloads/frei0r-all.webm -p {} \;

# @$(if $(wildcard frei0r-test),,make test-utils)

scan-plugins:
@$(if $(wildcard ${PLUGINDIR}),,>&2 echo "Scan dir not found: ${PLUGINDIR}" && exit 1)
Expand All @@ -13,10 +27,17 @@ scan-plugins:
@rm tmp.json
$(info frei0r-plugin-list.json)



generate-metadata: EXTENSION ?= so
generate-metadata:
@$(if $(wildcard ${PLUGINDIR}),,>&2 echo "Scan dir not found: ${PLUGINDIR}" && exit 1)
sh extract-plugin-info.sh ${EXTENSION} ${PLUGINDIR}

build:
@${CC} -o frei0r-info -ggdb frei0r-info.c ${INCLUDES}

clean:
rm -f *.o
rm -f frei0r-info
rm -f frei0r-info frei0r-test
rm -f *.json
14 changes: 14 additions & 0 deletions test/extract-plugin-info.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/bin/sh

[ -r frei0r-info ] || gmake
tmp=`mktemp`
find "${2}" -name "*.$1" |
while read -r line; do
file=`basename $line`
dir=`dirname $line`
name=`echo $file | cut -d. -f1`
./frei0r-info "$line" > $tmp
mv $tmp "$dir/$name.json"
ls "$dir/$name.json"
done
rm -f $tmp
2 changes: 1 addition & 1 deletion test/frei0r-info.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ int main(int argc, char **argv) {
}
fprintf(stdout," ]\n");
}
fprintf(stdout,"\n},\n");
fprintf(stdout,"\n}\n");
fflush(stdout);
f0r_deinit();
dlclose(dl_handle);
Expand Down
170 changes: 170 additions & 0 deletions test/frei0r-test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
#include <unistd.h>
#include <libgen.h>
#include <dlfcn.h>

#include <opencv2/opencv.hpp>

#include <frei0r.h>

// frei0r function prototypes
typedef int (*f0r_init_f)(void);
typedef void (*f0r_deinit_f)(void);
typedef void (*f0r_get_plugin_info_f)(f0r_plugin_info_t *info);
typedef void (*f0r_get_param_info_f)(f0r_param_info_t *info, int param_index);
typedef f0r_instance_t (*f0r_construct_f)(unsigned int width, unsigned int height);
typedef void (*f0r_update_f)(f0r_instance_t instance,
double time, const uint32_t* inframe, uint32_t* outframe);
typedef void (*f0r_destruct_f)(f0r_instance_t instance);


int main(int argc, char* argv[]) {
// instance frei0r pointers
static void *dl_handle;
static f0r_init_f f0r_init;
static f0r_deinit_f f0r_deinit;
static f0r_plugin_info_t pi;
static f0r_get_plugin_info_f f0r_get_plugin_info;
static f0r_get_param_info_f f0r_get_param_info;
static f0r_param_info_t param;
static f0r_instance_t instance;
static f0r_construct_f f0r_construct;
static f0r_update_f f0r_update;
static f0r_destruct_f f0r_destruct;

const char *usage = "Usage: frei0r-test [-td] <video_file> <frei0r_plugin_file>";
if (argc <3) {
fprintf(stderr,"%s\n",usage);
return -1;
}

int opt;
int headless = 0;
int debug = 0;
char video_file[512];
char plugin_file[512];
while((opt = getopt(argc, argv, "tdv:p:")) != -1) {
switch(opt) {
case 't':
headless = 1;
break;
case 'd':
debug = 1;
break;
case 'p':
snprintf(plugin_file, 511, "%s", optarg);
break;
case 'v':
snprintf(video_file, 511, "%s", optarg);
break;
}
}

// Open the image file using OpenCV
cv::VideoCapture cap(video_file);
if (!cap.isOpened()) {
printf("Error opening image file\n");
return -1;
}
// Get video properties
int frame_width = (int) cap.get(cv::CAP_PROP_FRAME_WIDTH);
int frame_height = (int) cap.get(cv::CAP_PROP_FRAME_HEIGHT);
int fps = (int) cap.get(cv::CAP_PROP_FPS);

const char *file = basename(plugin_file);
const char *dir = dirname(plugin_file);
char path[256];;
snprintf(path, 255,"%s/%s",dir,file);
// fprintf(stderr,"%s %s\n",argv[0], file);
// load shared library
dl_handle = dlopen(path, RTLD_NOW|RTLD_LOCAL|RTLD_NODELETE);
if(!dl_handle) {
fprintf(stderr,"error: %s\n",dlerror());
exit(1);
}
// get plugin function calls
f0r_init = (f0r_init_f) dlsym(dl_handle,"f0r_init");
f0r_deinit = (f0r_deinit_f) dlsym(dl_handle,"f0r_deinit");
f0r_get_plugin_info = (f0r_get_plugin_info_f) dlsym(dl_handle,"f0r_get_plugin_info");
f0r_get_param_info = (f0r_get_param_info_f) dlsym(dl_handle,"f0r_get_param_info");
f0r_construct = (f0r_construct_f) dlsym(dl_handle,"f0r_construct");
f0r_update = (f0r_update_f) dlsym(dl_handle,"f0r_update");
f0r_destruct = (f0r_destruct_f) dlsym(dl_handle,"f0r_destruct");

// always initialize plugin first
f0r_init();
// get info about plugin
f0r_get_plugin_info(&pi);
const char *frei0r_color_model = (pi.color_model == F0R_COLOR_MODEL_BGRA8888 ? "bgra8888" :
pi.color_model == F0R_COLOR_MODEL_RGBA8888 ? "rgba8888" :
pi.color_model == F0R_COLOR_MODEL_PACKED32 ? "packed32" : "unknown");

fprintf(stderr,"{\n \"name\":\"%s\",\n \"type\":\"%s\",\n \"color_model\":\"%s\",\n \"num_params\":\"%d\"\n}",
pi.name,
pi.plugin_type == F0R_PLUGIN_TYPE_FILTER ? "filter" :
pi.plugin_type == F0R_PLUGIN_TYPE_SOURCE ? "source" :
pi.plugin_type == F0R_PLUGIN_TYPE_MIXER2 ? "mixer2" :
pi.plugin_type == F0R_PLUGIN_TYPE_MIXER3 ? "mixer3" : "unknown",
frei0r_color_model,
pi.num_params);

// TODO: just filters for now
if( pi.plugin_type != F0R_PLUGIN_TYPE_FILTER ) {
fprintf(stderr,"Plugin is not of filter type, skip for now\n");
cap.release();
f0r_deinit();
dlclose(dl_handle);
exit(0);
}
if( pi.color_model != F0R_COLOR_MODEL_RGBA8888 ) {
fprintf(stderr,"Filter color model not supported: %s\n",frei0r_color_model);
cap.release();
f0r_deinit();
dlclose(dl_handle);
exit(1);
}

instance = f0r_construct(frame_width, frame_height);

// Create a window to display the video
if(!headless) {
cv::namedWindow("frei0r", cv::WINDOW_NORMAL);
cv::resizeWindow("frei0r", frame_width, frame_height);
cv::namedWindow("source", cv::WINDOW_NORMAL);
cv::resizeWindow("source", frame_width, frame_height);
}

uint32_t *buffer;
/* //posix_memalign( (void**) &outframe, 16, frame_width * frame_height * 4 ); */
buffer = (uint32_t*)calloc(4, frame_width * frame_height );

// Read the image file frame by frame
cv::Mat frame;
while (cap.read(frame)) {
// Convert the OpenCV image to an RGBA pixel buffer
cv::Mat frame_rgba;
cv::cvtColor(frame, frame_rgba, cv::COLOR_RGB2RGBA);

// Create an SDL2 surface from the RGBA pixel buffer
f0r_update(instance, 0.0, (const uint32_t*)frame_rgba.data, buffer);

// Display the frames
if(!headless) {
cv::imshow("source", frame);
memcpy(frame_rgba.data, buffer, frame_width * frame_height * 4);
cv::imshow("frei0r", frame_rgba);
// Wait for a key press
if(cv::waitKey(1000/fps) >= 0) break;
}
}

free(buffer);

cap.release(); // Release the video capture object

f0r_destruct(instance);
f0r_deinit();

dlclose(dl_handle);

return 0;
}

0 comments on commit e2d15f8

Please sign in to comment.