Skip to content

Commit

Permalink
FW-1087: provide wirefilter.h C header file and add ffi-ctests crate
Browse files Browse the repository at this point in the history
This new crate is here to provide a set of C based tests that will
serve two purposes:
* Provide some examples how to use the FFI bindings
* Test that those bindings are actually working as intended

Internally, it relies on ffi-ctests/ctests/tests.c file which contains
tests written in C and that is compiled at cargo configuration time
through the use of a build.rs file. This produces a wirefilter_ffi_ctests.so
shared library that is later used in the ffi-ctests/ctests/src/lib.rs file
to call the different tests functions. All of this is done in order to try
to integrate somehow properly with cargo test.
  • Loading branch information
marmeladema committed Mar 27, 2019
1 parent c449e9c commit 671feb5
Show file tree
Hide file tree
Showing 9 changed files with 478 additions and 0 deletions.
17 changes: 17 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
members = [
"engine",
"ffi",
"ffi-ctests",
"wasm",
]

Expand Down
12 changes: 12 additions & 0 deletions ffi-ctests/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[package]
authors = ["Elie ROUDNINSKI <[email protected]>"]
name = "wirefilter-ffi-ctests"
version = "0.1.0"
description = "C based tests for FFI bindings of the Wirefilter engine"
publish = false

[dependencies]

[build-dependencies]
cmake = "0.1"
wirefilter-ffi = {"path"= "../ffi"}
8 changes: 8 additions & 0 deletions ffi-ctests/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
extern crate cmake;

fn main() {
let dst = cmake::build("ctests");

println!("cargo:rustc-link-search=native={}/lib", dst.display());
println!("cargo:rustc-link-lib=dylib=wirefilter_ffi_ctests");
}
13 changes: 13 additions & 0 deletions ffi-ctests/ctests/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
cmake_minimum_required(VERSION 3.2)
project(wirefilter-ffi-ctests)

include_directories($ENV{CARGO_MANIFEST_DIR}/../ffi/include)
link_directories($ENV{OUT_DIR}/../../../deps)

add_library(wirefilter_ffi_ctests SHARED tests.c)
target_link_libraries(wirefilter_ffi_ctests wirefilter_ffi)

install(
TARGETS wirefilter_ffi_ctests
LIBRARY DESTINATION lib
)
270 changes: 270 additions & 0 deletions ffi-ctests/ctests/tests.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,270 @@
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>

#include <wirefilter.h>

#define WIREFILTER_STRING(v, s) {(v).data = (const unsigned char *)(s); (v).length = strlen(s);}

bool test_wirefilter_ffi_01() {
wirefilter_Scheme *scheme = wirefilter_create_scheme();
if(!scheme) {
return false;
}
wirefilter_free_scheme(scheme);
return true;
}

bool test_wirefilter_ffi_02() {
wirefilter_Scheme *scheme = wirefilter_create_scheme();
if(!scheme) {
return false;
}

wirefilter_ExternallyAllocatedStr field;

WIREFILTER_STRING(field, "http.host");
wirefilter_add_type_field_to_scheme(scheme, field, wirefilter_Bytes);
WIREFILTER_STRING(field, "ip.addr");
wirefilter_add_type_field_to_scheme(scheme, field, wirefilter_Ip);
WIREFILTER_STRING(field, "ssl");
wirefilter_add_type_field_to_scheme(scheme, field, wirefilter_Bool);
WIREFILTER_STRING(field, "tcp.port");
wirefilter_add_type_field_to_scheme(scheme, field, wirefilter_Int);

wirefilter_free_scheme(scheme);
return true;
}

bool test_wirefilter_ffi_03() {
wirefilter_Scheme *scheme = wirefilter_create_scheme();
if(!scheme) {
return false;
}

wirefilter_ExternallyAllocatedStr field, filter_str;

WIREFILTER_STRING(field, "http.host");
wirefilter_add_type_field_to_scheme(scheme, field, wirefilter_Bytes);
WIREFILTER_STRING(field, "ip.addr");
wirefilter_add_type_field_to_scheme(scheme, field, wirefilter_Ip);
WIREFILTER_STRING(field, "ssl");
wirefilter_add_type_field_to_scheme(scheme, field, wirefilter_Bool);
WIREFILTER_STRING(field, "tcp.port");
wirefilter_add_type_field_to_scheme(scheme, field, wirefilter_Int);

WIREFILTER_STRING(filter_str, "tcp.port == 80");
wirefilter_ParsingResult result = wirefilter_parse_filter(scheme, filter_str);

if(!result.success) {
return false;
}

if(!result.ok.ast) {
return false;
}

wirefilter_free_parsing_result(result);

wirefilter_free_scheme(scheme);
return true;
}

bool test_wirefilter_ffi_04() {
wirefilter_Scheme *scheme = wirefilter_create_scheme();
if(!scheme) {
return false;
}

wirefilter_ExternallyAllocatedStr field, filter_str;

WIREFILTER_STRING(field, "http.host");
wirefilter_add_type_field_to_scheme(scheme, field, wirefilter_Bytes);
WIREFILTER_STRING(field, "ip.addr");
wirefilter_add_type_field_to_scheme(scheme, field, wirefilter_Ip);
WIREFILTER_STRING(field, "ssl");
wirefilter_add_type_field_to_scheme(scheme, field, wirefilter_Bool);
WIREFILTER_STRING(field, "tcp.port");
wirefilter_add_type_field_to_scheme(scheme, field, wirefilter_Int);

WIREFILTER_STRING(filter_str, "tcp.port == \"wirefilter\"");
wirefilter_ParsingResult result = wirefilter_parse_filter(scheme, filter_str);

if(result.success) {
return false;
}

if(!result.err.msg.data || result.err.msg.length <= 0) {
return false;
}

wirefilter_free_parsing_result(result);

wirefilter_free_scheme(scheme);
return true;
}

bool test_wirefilter_ffi_05() {
wirefilter_Scheme *scheme = wirefilter_create_scheme();
if(!scheme) {
return false;
}

wirefilter_ExternallyAllocatedStr field, filter_str;

WIREFILTER_STRING(field, "http.host");
wirefilter_add_type_field_to_scheme(scheme, field, wirefilter_Bytes);
WIREFILTER_STRING(field, "ip.addr");
wirefilter_add_type_field_to_scheme(scheme, field, wirefilter_Ip);
WIREFILTER_STRING(field, "ssl");
wirefilter_add_type_field_to_scheme(scheme, field, wirefilter_Bool);
WIREFILTER_STRING(field, "tcp.port");
wirefilter_add_type_field_to_scheme(scheme, field, wirefilter_Int);

WIREFILTER_STRING(filter_str, "tcp.port == 80");
wirefilter_ParsingResult result = wirefilter_parse_filter(scheme, filter_str);

if(!result.success) {
return false;
}

if(!result.ok.ast) {
return false;
}

wirefilter_Filter *filter = wirefilter_compile_filter(result.ok.ast);
if(!filter) {
return false;
}

wirefilter_free_compiled_filter(filter);

wirefilter_free_scheme(scheme);
return true;
}

bool test_wirefilter_ffi_06() {
wirefilter_Scheme *scheme = wirefilter_create_scheme();
if(!scheme) {
return false;
}

wirefilter_ExecutionContext *exec_ctx = wirefilter_create_execution_context(scheme);
if(!exec_ctx) {
return false;
}

wirefilter_free_execution_context(exec_ctx);

wirefilter_free_scheme(scheme);
return true;
}

bool test_wirefilter_ffi_07() {
wirefilter_Scheme *scheme = wirefilter_create_scheme();
if(!scheme) {
return false;
}

wirefilter_ExternallyAllocatedStr field;

WIREFILTER_STRING(field, "http.host");
wirefilter_add_type_field_to_scheme(scheme, field, wirefilter_Bytes);
WIREFILTER_STRING(field, "ip.addr");
wirefilter_add_type_field_to_scheme(scheme, field, wirefilter_Ip);
WIREFILTER_STRING(field, "ssl");
wirefilter_add_type_field_to_scheme(scheme, field, wirefilter_Bool);
WIREFILTER_STRING(field, "tcp.port");
wirefilter_add_type_field_to_scheme(scheme, field, wirefilter_Int);

wirefilter_ExecutionContext *exec_ctx = wirefilter_create_execution_context(scheme);
if(!exec_ctx) {
return false;
}

WIREFILTER_STRING(field, "http.host");
wirefilter_ExternallyAllocatedByteArr http_host;
WIREFILTER_STRING(http_host, "www.cloudflare.com")
wirefilter_add_bytes_value_to_execution_context(exec_ctx, field, http_host);

WIREFILTER_STRING(field, "ip.addr");
uint8_t ip_addr[4] = {192, 168, 0, 1};
wirefilter_add_ipv4_value_to_execution_context(exec_ctx, field, ip_addr);

WIREFILTER_STRING(field, "ssl");
wirefilter_add_bool_value_to_execution_context(exec_ctx, field, false);

WIREFILTER_STRING(field, "tcp.port");
wirefilter_add_int_value_to_execution_context(exec_ctx, field, 80);

wirefilter_free_execution_context(exec_ctx);

wirefilter_free_scheme(scheme);
return true;
}

bool test_wirefilter_ffi_08() {
wirefilter_Scheme *scheme = wirefilter_create_scheme();
if(!scheme) {
return false;
}

wirefilter_ExternallyAllocatedStr field;

WIREFILTER_STRING(field, "http.host");
wirefilter_add_type_field_to_scheme(scheme, field, wirefilter_Bytes);
WIREFILTER_STRING(field, "ip.addr");
wirefilter_add_type_field_to_scheme(scheme, field, wirefilter_Ip);
WIREFILTER_STRING(field, "ssl");
wirefilter_add_type_field_to_scheme(scheme, field, wirefilter_Bool);
WIREFILTER_STRING(field, "tcp.port");
wirefilter_add_type_field_to_scheme(scheme, field, wirefilter_Int);

wirefilter_ExternallyAllocatedStr filter_str;
WIREFILTER_STRING(filter_str, "tcp.port == 80");
wirefilter_ParsingResult result = wirefilter_parse_filter(scheme, filter_str);

if(!result.success) {
return false;
}

if(!result.ok.ast) {
return false;
}

wirefilter_Filter *filter = wirefilter_compile_filter(result.ok.ast);
if(!filter) {
return false;
}

wirefilter_ExecutionContext *exec_ctx = wirefilter_create_execution_context(scheme);
if(!exec_ctx) {
return false;
}

WIREFILTER_STRING(field, "http.host");
wirefilter_ExternallyAllocatedByteArr http_host;
WIREFILTER_STRING(http_host, "www.cloudflare.com")
wirefilter_add_bytes_value_to_execution_context(exec_ctx, field, http_host);

WIREFILTER_STRING(field, "ip.addr");
uint8_t ip_addr[4] = {192, 168, 0, 1};
wirefilter_add_ipv4_value_to_execution_context(exec_ctx, field, ip_addr);

WIREFILTER_STRING(field, "ssl");
wirefilter_add_bool_value_to_execution_context(exec_ctx, field, false);

WIREFILTER_STRING(field, "tcp.port");
wirefilter_add_int_value_to_execution_context(exec_ctx, field, 80);

if(!wirefilter_match(filter, exec_ctx)) {
return false;
}

wirefilter_free_execution_context(exec_ctx);

wirefilter_free_compiled_filter(filter);

wirefilter_free_scheme(scheme);
return true;
}
30 changes: 30 additions & 0 deletions ffi-ctests/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#[test]
fn test() {
#[link(name = "wirefilter_ffi_ctests")]
extern "C" {
fn test_wirefilter_ffi_01() -> bool;
fn test_wirefilter_ffi_02() -> bool;
fn test_wirefilter_ffi_03() -> bool;
fn test_wirefilter_ffi_04() -> bool;
fn test_wirefilter_ffi_05() -> bool;
fn test_wirefilter_ffi_06() -> bool;
fn test_wirefilter_ffi_07() -> bool;
fn test_wirefilter_ffi_08() -> bool;
}

assert!(unsafe { test_wirefilter_ffi_01() });

assert!(unsafe { test_wirefilter_ffi_02() });

assert!(unsafe { test_wirefilter_ffi_03() });

assert!(unsafe { test_wirefilter_ffi_04() });

assert!(unsafe { test_wirefilter_ffi_05() });

assert!(unsafe { test_wirefilter_ffi_06() });

assert!(unsafe { test_wirefilter_ffi_07() });

assert!(unsafe { test_wirefilter_ffi_08() });
}
Loading

0 comments on commit 671feb5

Please sign in to comment.