Skip to content

Commit e357bbc

Browse files
committed
FW-1087: provide wirefilter.h C header file and add ffi/tests/ctests 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.
1 parent bbc62a7 commit e357bbc

File tree

9 files changed

+514
-2
lines changed

9 files changed

+514
-2
lines changed

Cargo.lock

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

engine/src/types.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ macro_rules! declare_types {
5454
($($(# $attrs:tt)* $name:ident ( $(# $lhs_attrs:tt)* $lhs_ty:ty | $rhs_ty:ty | $multi_rhs_ty:ty ) , )*) => {
5555
/// Enumeration of supported types for field values.
5656
#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)]
57-
#[repr(u8)]
57+
#[repr(C)]
5858
pub enum Type {
5959
$($(# $attrs)* $name,)*
6060
}

ffi/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ publish = false
99
assets = [["target/release/libwirefilter_ffi.so", "usr/local/lib/libwirefilter.so", "644"]]
1010

1111
[lib]
12-
crate-type = ["cdylib"]
12+
crate-type = ["cdylib", "rlib"]
1313
# Avoid duplicate compilation error messages as we don't have doctests anyway
1414
doctest = false
1515
bench = false
@@ -25,3 +25,4 @@ path = "../engine"
2525
[dev-dependencies]
2626
regex = "1.0.1"
2727
indoc = "0.3.0"
28+
wirefilter-ffi-ctests = {path = "tests/ctests"}

ffi/include/wirefilter.h

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
#ifndef _WIREFILTER_H_
2+
#define _WIREFILTER_H_
3+
4+
#include <stdlib.h>
5+
#include <stdint.h>
6+
7+
#ifdef __cplusplus
8+
extern "C" {
9+
#endif
10+
11+
typedef struct wirefilter_scheme wirefilter_scheme_t;
12+
typedef struct wirefilter_execution_context wirefilter_execution_context_t;
13+
typedef struct wirefilter_filter_ast wirefilter_filter_ast_t;
14+
typedef struct wirefilter_filter wirefilter_filter_t;
15+
16+
typedef struct {
17+
const char *data;
18+
size_t length;
19+
} wirefilter_rust_allocated_str_t;
20+
21+
typedef struct {
22+
const char *data;
23+
size_t length;
24+
} wirefilter_static_rust_allocated_str_t;
25+
26+
typedef struct {
27+
const char *data;
28+
size_t length;
29+
} wirefilter_externally_allocated_str_t;
30+
31+
typedef struct {
32+
const unsigned char *data;
33+
size_t length;
34+
} wirefilter_externally_allocated_byte_arr_t;
35+
36+
typedef union {
37+
uint8_t success;
38+
struct {
39+
uint8_t _res1;
40+
wirefilter_rust_allocated_str_t msg;
41+
} err;
42+
struct {
43+
uint8_t _res2;
44+
wirefilter_filter_ast_t *ast;
45+
} ok;
46+
} wirefilter_parsing_result_t;
47+
48+
typedef enum {
49+
WIREFILTER_TYPE_IP,
50+
WIREFILTER_TYPE_BYTES,
51+
WIREFILTER_TYPE_INT,
52+
WIREFILTER_TYPE_BOOL,
53+
} wirefilter_type_t;
54+
55+
wirefilter_scheme_t *wirefilter_create_scheme();
56+
void wirefilter_free_scheme(wirefilter_scheme_t *scheme);
57+
58+
void wirefilter_add_type_field_to_scheme(
59+
wirefilter_scheme_t *scheme,
60+
wirefilter_externally_allocated_str_t name,
61+
wirefilter_type_t type
62+
);
63+
64+
wirefilter_parsing_result_t wirefilter_parse_filter(
65+
wirefilter_scheme_t *scheme,
66+
wirefilter_externally_allocated_str_t input
67+
);
68+
69+
void wirefilter_free_parsing_result(wirefilter_parsing_result_t result);
70+
71+
wirefilter_filter_t *wirefilter_compile_filter(wirefilter_filter_ast_t *ast);
72+
void wirefilter_free_compiled_filter(wirefilter_filter_t *filter);
73+
74+
wirefilter_execution_context_t *wirefilter_create_execution_context(
75+
wirefilter_scheme_t *scheme
76+
);
77+
void wirefilter_free_execution_context(
78+
wirefilter_execution_context_t *exec_ctx
79+
);
80+
81+
void wirefilter_add_int_value_to_execution_context(
82+
wirefilter_execution_context_t *exec_ctx,
83+
wirefilter_externally_allocated_str_t name,
84+
int32_t value
85+
);
86+
87+
void wirefilter_add_bytes_value_to_execution_context(
88+
wirefilter_execution_context_t *exec_ctx,
89+
wirefilter_externally_allocated_str_t name,
90+
wirefilter_externally_allocated_byte_arr_t value
91+
);
92+
93+
void wirefilter_add_ipv6_value_to_execution_context(
94+
wirefilter_execution_context_t *exec_ctx,
95+
wirefilter_externally_allocated_str_t name,
96+
uint8_t value[16]
97+
);
98+
99+
void wirefilter_add_ipv4_value_to_execution_context(
100+
wirefilter_execution_context_t *exec_ctx,
101+
wirefilter_externally_allocated_str_t name,
102+
uint8_t value[4]
103+
);
104+
105+
void wirefilter_add_bool_value_to_execution_context(
106+
wirefilter_execution_context_t *exec_ctx,
107+
wirefilter_externally_allocated_str_t name,
108+
bool value
109+
);
110+
111+
bool wirefilter_match(
112+
wirefilter_filter_t *filter,
113+
wirefilter_execution_context_t *exec_ctx
114+
);
115+
116+
bool wirefilter_filter_uses(
117+
wirefilter_filter_t *filter,
118+
wirefilter_externally_allocated_str_t field_name
119+
);
120+
121+
wirefilter_static_rust_allocated_str_t wirefilter_get_version();
122+
123+
#ifdef __cplusplus
124+
}
125+
#endif
126+
127+
#endif // _WIREFILTER_H_

ffi/src/lib.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,11 @@ pub extern "C" fn wirefilter_parse_filter<'s, 'i>(
9292
}
9393
}
9494

95+
#[no_mangle]
96+
pub extern "C" fn wirefilter_free_parsing_result(r: ParsingResult<'_>) {
97+
drop(r);
98+
}
99+
95100
/// Wrapper for Hasher that allows using Write API (e.g. with serializer).
96101
#[derive(Default)]
97102
struct HasherWrite<H: Hasher>(H);

ffi/tests/ctests/Cargo.toml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[package]
2+
authors = ["Elie ROUDNINSKI <[email protected]>"]
3+
name = "wirefilter-ffi-ctests"
4+
version = "0.1.0"
5+
description = "C based tests for FFI bindings of the Wirefilter engine"
6+
publish = false
7+
8+
[dependencies]
9+
wirefilter-ffi = {path = "../.."}
10+
11+
[build-dependencies]
12+
cc = "1.0"

ffi/tests/ctests/build.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
extern crate cc;
2+
3+
fn main() {
4+
cc::Build::new()
5+
.include("../../include")
6+
.file("src/tests.c")
7+
.warnings(true)
8+
.extra_warnings(true)
9+
.warnings_into_errors(true)
10+
.compile("wirefilter_ffi_ctests");
11+
}

ffi/tests/ctests/src/lib.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#[no_mangle]
2+
unsafe extern "C" fn rust_assert(check: bool, msg: *const std::os::raw::c_char) {
3+
assert!(check, "{}", std::ffi::CStr::from_ptr(msg).to_str().unwrap());
4+
}
5+
6+
macro_rules! ffi_ctest {
7+
(@inner $($name:ident => $link_name:expr,)*) => {
8+
$(
9+
#[test]
10+
pub fn $name() {
11+
#[link(name = "wirefilter_ffi")]
12+
extern "C" {
13+
#[link_name = $link_name]
14+
fn ctest();
15+
}
16+
17+
unsafe { ctest() }
18+
}
19+
)*
20+
};
21+
22+
($($name:ident,)*) => {
23+
ffi_ctest! { @inner
24+
$($name => concat!("wirefilter_ffi_ctest_", stringify!($name)),)*
25+
}
26+
};
27+
}
28+
29+
mod ffi_ctest {
30+
ffi_ctest!(
31+
create_scheme,
32+
add_fields_to_scheme,
33+
parse_good_filter,
34+
parse_bad_filter,
35+
compile_filter,
36+
create_execution_context,
37+
add_values_to_execution_context,
38+
match_filter,
39+
);
40+
}

0 commit comments

Comments
 (0)