Skip to content

Commit

Permalink
FW-1087: provide wirefilter.h C header file and add ffi/tests/ctests …
Browse files Browse the repository at this point in the history
…crate

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/tests/ctests/src/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.a
static library that is later used in the ffi/tests/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 29, 2019
1 parent bbc62a7 commit a92badb
Show file tree
Hide file tree
Showing 9 changed files with 518 additions and 2 deletions.
9 changes: 9 additions & 0 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion engine/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ macro_rules! declare_types {
($($(# $attrs:tt)* $name:ident ( $(# $lhs_attrs:tt)* $lhs_ty:ty | $rhs_ty:ty | $multi_rhs_ty:ty ) , )*) => {
/// Enumeration of supported types for field values.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)]
#[repr(u8)]
#[repr(C)]
pub enum Type {
$($(# $attrs)* $name,)*
}
Expand Down
3 changes: 2 additions & 1 deletion ffi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ publish = false
assets = [["target/release/libwirefilter_ffi.so", "usr/local/lib/libwirefilter.so", "644"]]

[lib]
crate-type = ["cdylib"]
crate-type = ["cdylib", "rlib"]
# Avoid duplicate compilation error messages as we don't have doctests anyway
doctest = false
bench = false
Expand All @@ -25,3 +25,4 @@ path = "../engine"
[dev-dependencies]
regex = "1.0.1"
indoc = "0.3.0"
wirefilter-ffi-ctests = {path = "tests/ctests"}
127 changes: 127 additions & 0 deletions ffi/include/wirefilter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
#ifndef _WIREFILTER_H_
#define _WIREFILTER_H_

#include <stdlib.h>
#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif

typedef struct wirefilter_scheme wirefilter_scheme_t;
typedef struct wirefilter_execution_context wirefilter_execution_context_t;
typedef struct wirefilter_filter_ast wirefilter_filter_ast_t;
typedef struct wirefilter_filter wirefilter_filter_t;

typedef struct {
const char *data;
size_t length;
} wirefilter_rust_allocated_str_t;

typedef struct {
const char *data;
size_t length;
} wirefilter_static_rust_allocated_str_t;

typedef struct {
const char *data;
size_t length;
} wirefilter_externally_allocated_str_t;

typedef struct {
const unsigned char *data;
size_t length;
} wirefilter_externally_allocated_byte_arr_t;

typedef union {
uint8_t success;
struct {
uint8_t _res1;
wirefilter_rust_allocated_str_t msg;
} err;
struct {
uint8_t _res2;
wirefilter_filter_ast_t *ast;
} ok;
} wirefilter_parsing_result_t;

typedef enum {
WIREFILTER_TYPE_IP,
WIREFILTER_TYPE_BYTES,
WIREFILTER_TYPE_INT,
WIREFILTER_TYPE_BOOL,
} wirefilter_type_t;

wirefilter_scheme_t *wirefilter_create_scheme();
void wirefilter_free_scheme(wirefilter_scheme_t *scheme);

void wirefilter_add_type_field_to_scheme(
wirefilter_scheme_t *scheme,
wirefilter_externally_allocated_str_t name,
wirefilter_type_t type
);

wirefilter_parsing_result_t wirefilter_parse_filter(
wirefilter_scheme_t *scheme,
wirefilter_externally_allocated_str_t input
);

void wirefilter_free_parsing_result(wirefilter_parsing_result_t result);

wirefilter_filter_t *wirefilter_compile_filter(wirefilter_filter_ast_t *ast);
void wirefilter_free_compiled_filter(wirefilter_filter_t *filter);

wirefilter_execution_context_t *wirefilter_create_execution_context(
wirefilter_scheme_t *scheme
);
void wirefilter_free_execution_context(
wirefilter_execution_context_t *exec_ctx
);

void wirefilter_add_int_value_to_execution_context(
wirefilter_execution_context_t *exec_ctx,
wirefilter_externally_allocated_str_t name,
int32_t value
);

void wirefilter_add_bytes_value_to_execution_context(
wirefilter_execution_context_t *exec_ctx,
wirefilter_externally_allocated_str_t name,
wirefilter_externally_allocated_byte_arr_t value
);

void wirefilter_add_ipv6_value_to_execution_context(
wirefilter_execution_context_t *exec_ctx,
wirefilter_externally_allocated_str_t name,
uint8_t value[16]
);

void wirefilter_add_ipv4_value_to_execution_context(
wirefilter_execution_context_t *exec_ctx,
wirefilter_externally_allocated_str_t name,
uint8_t value[4]
);

void wirefilter_add_bool_value_to_execution_context(
wirefilter_execution_context_t *exec_ctx,
wirefilter_externally_allocated_str_t name,
bool value
);

bool wirefilter_match(
wirefilter_filter_t *filter,
wirefilter_execution_context_t *exec_ctx
);

bool wirefilter_filter_uses(
wirefilter_filter_t *filter,
wirefilter_externally_allocated_str_t field_name
);

wirefilter_static_rust_allocated_str_t wirefilter_get_version();

#ifdef __cplusplus
}
#endif

#endif // _WIREFILTER_H_
5 changes: 5 additions & 0 deletions ffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,11 @@ pub extern "C" fn wirefilter_parse_filter<'s, 'i>(
}
}

#[no_mangle]
pub extern "C" fn wirefilter_free_parsing_result(r: ParsingResult<'_>) {
drop(r);
}

/// Wrapper for Hasher that allows using Write API (e.g. with serializer).
#[derive(Default)]
struct HasherWrite<H: Hasher>(H);
Expand Down
12 changes: 12 additions & 0 deletions ffi/tests/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]
wirefilter-ffi = {path = "../.."}

[build-dependencies]
cc = "1.0"
11 changes: 11 additions & 0 deletions ffi/tests/ctests/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
extern crate cc;

fn main() {
cc::Build::new()
.include("../../include")
.file("src/tests.c")
.warnings(true)
.extra_warnings(true)
.warnings_into_errors(true)
.compile("wirefilter_ffi_ctests");
}
41 changes: 41 additions & 0 deletions ffi/tests/ctests/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
extern crate wirefilter_ffi as _;

#[no_mangle]
unsafe extern "C" fn rust_assert(check: bool, msg: *const std::os::raw::c_char) {
assert!(check, "{}", std::ffi::CStr::from_ptr(msg).to_str().unwrap());
}

macro_rules! ffi_ctest {
(@inner $($name:ident => $link_name:expr,)*) => {
$(
#[test]
pub fn $name() {
extern "C" {
#[link_name = $link_name]
fn ctest();
}

unsafe { ctest() }
}
)*
};

($($name:ident,)*) => {
ffi_ctest! { @inner
$($name => concat!("wirefilter_ffi_ctest_", stringify!($name)),)*
}
};
}

mod ffi_ctest {
ffi_ctest!(
create_scheme,
add_fields_to_scheme,
parse_good_filter,
parse_bad_filter,
compile_filter,
create_execution_context,
add_values_to_execution_context,
match_filter,
);
}
Loading

0 comments on commit a92badb

Please sign in to comment.