use crate::runner::{Backend, Database, HealthCheck, Mode, Phase, Settings, Verbosity};
use hegel_c::hegel_result_t;
use std::ffi::{CStr, CString};
use std::os::raw::c_char;
use std::ptr;
struct Context {
raw: *mut hegel_c::HegelContext,
}
impl Context {
fn new() -> Self {
Context {
raw: hegel_c::hegel_context_new(),
}
}
fn as_ptr(&self) -> *mut hegel_c::HegelContext {
self.raw
}
fn last_error(&self) -> String {
let p = unsafe { hegel_c::hegel_context_last_error(self.raw) };
if p.is_null() {
return String::new(); }
unsafe { CStr::from_ptr(p) }.to_string_lossy().into_owned()
}
}
impl Drop for Context {
fn drop(&mut self) {
require_ok(unsafe { hegel_c::hegel_context_free(self.raw) });
}
}
thread_local! {
static CONTEXT: Context = Context::new();
}
fn with_context<R>(f: impl FnOnce(*mut hegel_c::HegelContext) -> R) -> R {
CONTEXT.with(|c| f(c.as_ptr()))
}
fn free_on_drop(f: impl FnOnce(*mut hegel_c::HegelContext) -> hegel_c::hegel_result_t) {
let _ = CONTEXT.try_with(|c| require_ok(f(c.as_ptr())));
}
pub(crate) fn last_error_string() -> String {
CONTEXT.with(|c| c.last_error())
}
fn cstring_lossy(s: &str) -> CString {
CString::new(s).unwrap_or_else(|_| CString::new(s.replace('\0', "\u{FFFD}")).unwrap())
}
fn string_from_engine_bytes(bytes: Vec<u8>) -> String {
String::from_utf8(bytes).unwrap_or_else(|e| {
crate::control::hegel_internal_error!("libhegel returned invalid UTF-8: {e}")
})
}
pub(crate) struct SettingsHandle {
raw: *mut hegel_c::HegelSettings,
}
impl SettingsHandle {
pub(crate) fn build(settings: &Settings, database_key: Option<&str>) -> Self {
with_context(|ctx| {
let mut raw: *mut hegel_c::HegelSettings = ptr::null_mut();
unsafe {
require_ok(hegel_c::hegel_settings_new(ctx, &mut raw));
require_ok(hegel_c::hegel_settings_set_mode(
ctx,
raw,
map_mode(settings.mode),
));
require_ok(hegel_c::hegel_settings_set_test_cases(
ctx,
raw,
settings.test_cases,
));
require_ok(hegel_c::hegel_settings_set_verbosity(
ctx,
raw,
map_verbosity(settings.verbosity),
));
require_ok(match settings.seed {
Some(seed) => hegel_c::hegel_settings_set_seed(ctx, raw, seed, true),
None => hegel_c::hegel_settings_set_seed(ctx, raw, 0, false),
});
require_ok(hegel_c::hegel_settings_set_derandomize(
ctx,
raw,
settings.derandomize,
));
require_ok(hegel_c::hegel_settings_set_report_multiple_failures(
ctx,
raw,
settings.report_multiple_failures,
));
match &settings.database {
Database::Disabled => {
let empty = CString::new("").unwrap();
require_ok(hegel_c::hegel_settings_set_database(
ctx,
raw,
empty.as_ptr(),
));
}
Database::Path(path) => {
let c = cstring_lossy(path);
require_ok(hegel_c::hegel_settings_set_database(ctx, raw, c.as_ptr()));
}
Database::Unset => {}
}
if let Some(key) = database_key {
let c = cstring_lossy(key);
require_ok(hegel_c::hegel_settings_set_database_key(
ctx,
raw,
c.as_ptr(),
));
}
require_ok(hegel_c::hegel_settings_set_phases(
ctx,
raw,
phases_bitmask(&settings.phases),
));
require_ok(hegel_c::hegel_settings_set_suppress_health_check(
ctx,
raw,
health_check_bitmask(&settings.suppress_health_check),
));
require_ok(hegel_c::hegel_settings_set_backend(
ctx,
raw,
map_backend(settings.backend),
));
}
SettingsHandle { raw }
})
}
pub(crate) fn as_ptr(&self) -> *const hegel_c::HegelSettings {
self.raw
}
}
impl Drop for SettingsHandle {
fn drop(&mut self) {
free_on_drop(|ctx| unsafe { hegel_c::hegel_settings_free(ctx, self.raw) });
}
}
pub(crate) struct RunHandle {
raw: *mut hegel_c::HegelRun,
}
impl RunHandle {
pub(crate) fn start(settings: &SettingsHandle) -> Result<Self, String> {
let mut raw: *mut hegel_c::HegelRun = ptr::null_mut();
let rc = with_context(|ctx| unsafe {
hegel_c::hegel_run_start(ctx, settings.as_ptr(), &mut raw)
});
if rc != hegel_result_t::HEGEL_OK {
return Err(last_error_string()); }
Ok(RunHandle { raw })
}
pub(crate) fn next_test_case(&self) -> Option<CTestCase> {
let mut raw: *mut hegel_c::HegelTestCase = ptr::null_mut();
let rc =
with_context(|ctx| unsafe { hegel_c::hegel_next_test_case(ctx, self.raw, &mut raw) });
require_ok(rc);
if raw.is_null() {
None
} else {
Some(CTestCase { raw })
}
}
pub(crate) fn result(&self) -> RunResult {
let mut raw: *mut hegel_c::HegelRunResult = ptr::null_mut();
require_ok(with_context(|ctx| unsafe {
hegel_c::hegel_run_result(ctx, self.raw, &mut raw)
}));
RunResult { raw }
}
}
impl Drop for RunHandle {
fn drop(&mut self) {
free_on_drop(|ctx| unsafe { hegel_c::hegel_run_free(ctx, self.raw) });
}
}
pub(crate) struct CTestCase {
raw: *mut hegel_c::HegelTestCase,
}
unsafe impl Send for CTestCase {}
unsafe impl Sync for CTestCase {}
impl CTestCase {
pub(crate) fn from_blob(settings: &SettingsHandle, blob: &str) -> Result<Self, String> {
let c_blob = cstring_lossy(blob);
let mut raw: *mut hegel_c::HegelTestCase = ptr::null_mut();
let rc = with_context(|ctx| unsafe {
hegel_c::hegel_test_case_from_blob(ctx, settings.as_ptr(), c_blob.as_ptr(), &mut raw)
});
if rc != hegel_result_t::HEGEL_OK {
return Err(last_error_string());
}
Ok(CTestCase { raw })
}
pub(crate) fn clone_handle(&self) -> CTestCase {
let mut raw: *mut hegel_c::HegelTestCase = ptr::null_mut();
require_ok(with_context(|ctx| unsafe {
hegel_c::hegel_test_case_clone(ctx, self.raw, &mut raw)
}));
CTestCase { raw }
}
pub(crate) fn generate_integer(
&self,
min_value: i64,
max_value: i64,
) -> Result<i64, hegel_result_t> {
let mut out: i64 = 0;
let rc = with_context(|ctx| unsafe {
hegel_c::hegel_generate_integer(ctx, self.raw, min_value, max_value, &mut out)
});
rc_to_value(rc, out)
}
pub(crate) fn generate_integer_big(
&self,
min_value: &[u8],
max_value: &[u8],
) -> Result<[u8; 17], hegel_result_t> {
let mut out = [0u8; 17];
let mut out_len: usize = 0;
let rc = with_context(|ctx| unsafe {
hegel_c::hegel_generate_integer_big(
ctx,
self.raw,
min_value.as_ptr(),
min_value.len(),
max_value.as_ptr(),
max_value.len(),
out.as_mut_ptr(),
out.len(),
&mut out_len,
)
});
if rc != hegel_result_t::HEGEL_OK {
return Err(rc);
}
Ok(out)
}
#[allow(clippy::too_many_arguments)]
pub(crate) fn generate_float(
&self,
width: u32,
min_value: f64,
max_value: f64,
allow_nan: bool,
allow_infinity: bool,
exclude_min: bool,
exclude_max: bool,
smallest_nonzero_magnitude: f64,
) -> Result<f64, hegel_result_t> {
let mut out: f64 = 0.0;
let rc = with_context(|ctx| unsafe {
hegel_c::hegel_generate_float(
ctx,
self.raw,
width,
min_value,
max_value,
allow_nan,
allow_infinity,
exclude_min,
exclude_max,
smallest_nonzero_magnitude,
&mut out,
)
});
rc_to_value(rc, out)
}
pub(crate) fn generate_boolean(&self, p: f64) -> Result<bool, hegel_result_t> {
let mut out = false;
let rc = with_context(|ctx| unsafe {
hegel_c::hegel_generate_boolean(ctx, self.raw, p, false, false, &mut out)
});
rc_to_value(rc, out)
}
pub(crate) fn generate_bytes(
&self,
min_size: u64,
max_size: u64,
) -> Result<Vec<u8>, hegel_result_t> {
let mut result = hegel_c::hegel_generate_bytes_result_t {
data: ptr::null_mut(),
len: 0,
};
let rc = with_context(|ctx| unsafe {
hegel_c::hegel_generate_bytes(ctx, self.raw, min_size, max_size, &mut result)
});
if rc != hegel_result_t::HEGEL_OK {
return Err(rc);
}
let bytes = unsafe { std::slice::from_raw_parts(result.data, result.len) }.to_vec();
require_ok(with_context(|ctx| unsafe {
hegel_c::hegel_generate_bytes_result_free(ctx, &mut result)
}));
Ok(bytes)
}
pub(crate) fn generate_string(
&self,
generator: &StringGenerator,
) -> Result<String, hegel_result_t> {
let mut result = hegel_c::hegel_generate_string_result_t {
data: ptr::null_mut(),
len: 0,
};
let rc = with_context(|ctx| unsafe {
hegel_c::hegel_generate_string(ctx, self.raw, generator.raw, &mut result)
});
if rc != hegel_result_t::HEGEL_OK {
return Err(rc);
}
let bytes =
unsafe { std::slice::from_raw_parts(result.data.cast::<u8>(), result.len) }.to_vec();
require_ok(with_context(|ctx| unsafe {
hegel_c::hegel_generate_string_result_free(ctx, &mut result)
}));
Ok(string_from_engine_bytes(bytes))
}
pub(crate) fn generate_date(
&self,
min: hegel_c::hegel_date_t,
max: hegel_c::hegel_date_t,
) -> Result<hegel_c::hegel_date_t, hegel_result_t> {
let mut out = min;
let rc = with_context(|ctx| unsafe {
hegel_c::hegel_generate_date(ctx, self.raw, min, max, &mut out)
});
rc_to_value(rc, out)
}
pub(crate) fn generate_time(
&self,
min: hegel_c::hegel_time_t,
max: hegel_c::hegel_time_t,
) -> Result<hegel_c::hegel_time_t, hegel_result_t> {
let mut out = min;
let rc = with_context(|ctx| unsafe {
hegel_c::hegel_generate_time(ctx, self.raw, min, max, &mut out)
});
rc_to_value(rc, out)
}
pub(crate) fn generate_datetime(
&self,
min: hegel_c::hegel_datetime_t,
max: hegel_c::hegel_datetime_t,
) -> Result<hegel_c::hegel_datetime_t, hegel_result_t> {
let mut out = min;
let rc = with_context(|ctx| unsafe {
hegel_c::hegel_generate_datetime(ctx, self.raw, min, max, &mut out)
});
rc_to_value(rc, out)
}
pub(crate) fn generate_uuid(&self, version: Option<u8>) -> Result<[u8; 16], hegel_result_t> {
let mut out = [0u8; 16];
let rc = with_context(|ctx| unsafe {
hegel_c::hegel_generate_uuid(
ctx,
self.raw,
version.unwrap_or(0),
version.is_some(),
out.as_mut_ptr(),
)
});
rc_to_value(rc, out)
}
pub(crate) fn generate_ipv4(&self) -> Result<std::net::Ipv4Addr, hegel_result_t> {
let mut out = [0u8; 4];
let rc = with_context(|ctx| unsafe {
hegel_c::hegel_generate_ipv4(ctx, self.raw, out.as_mut_ptr())
});
rc_to_value(rc, std::net::Ipv4Addr::from(out))
}
pub(crate) fn generate_ipv6(&self) -> Result<std::net::Ipv6Addr, hegel_result_t> {
let mut out = [0u8; 16];
let rc = with_context(|ctx| unsafe {
hegel_c::hegel_generate_ipv6(ctx, self.raw, out.as_mut_ptr())
});
rc_to_value(rc, std::net::Ipv6Addr::from(out))
}
pub(crate) fn start_span(&self, label: u64) -> Result<(), hegel_result_t> {
rc_to_unit(with_context(|ctx| unsafe {
hegel_c::hegel_start_span(ctx, self.raw, label)
}))
}
pub(crate) fn stop_span(&self, discard: bool) -> Result<(), hegel_result_t> {
rc_to_unit(with_context(|ctx| unsafe {
hegel_c::hegel_stop_span(ctx, self.raw, discard)
}))
}
pub(crate) fn new_collection(
&self,
min_size: u64,
max_size: Option<u64>,
) -> Result<i64, hegel_result_t> {
let mut id: i64 = 0;
let rc = with_context(|ctx| unsafe {
hegel_c::hegel_new_collection(
ctx,
self.raw,
min_size,
max_size.unwrap_or(u64::MAX),
&mut id,
)
});
rc_to_value(rc, id)
}
pub(crate) fn collection_more(&self, collection_id: i64) -> Result<bool, hegel_result_t> {
let mut more = false;
let rc = with_context(|ctx| unsafe {
hegel_c::hegel_collection_more(ctx, self.raw, collection_id, &mut more)
});
rc_to_value(rc, more)
}
pub(crate) fn collection_reject(
&self,
collection_id: i64,
why: Option<&str>,
) -> Result<(), hegel_result_t> {
let c_why = why.map(cstring_lossy);
let why_ptr = c_why.as_ref().map_or(ptr::null(), |c| c.as_ptr());
rc_to_unit(with_context(|ctx| unsafe {
hegel_c::hegel_collection_reject(ctx, self.raw, collection_id, why_ptr)
}))
}
pub(crate) fn new_pool(&self) -> Result<i64, hegel_result_t> {
let mut id: i64 = 0;
let rc = with_context(|ctx| unsafe { hegel_c::hegel_new_pool(ctx, self.raw, &mut id) });
rc_to_value(rc, id)
}
pub(crate) fn pool_add(&self, pool_id: i64) -> Result<i64, hegel_result_t> {
let mut id: i64 = 0;
let rc =
with_context(|ctx| unsafe { hegel_c::hegel_pool_add(ctx, self.raw, pool_id, &mut id) });
rc_to_value(rc, id)
}
pub(crate) fn pool_generate(&self, pool_id: i64, consume: bool) -> Result<i64, hegel_result_t> {
let mut id: i64 = 0;
let rc = with_context(|ctx| unsafe {
hegel_c::hegel_pool_generate(ctx, self.raw, pool_id, consume, &mut id)
});
rc_to_value(rc, id)
}
pub(crate) fn new_state_machine(
&self,
rule_names: &[&str],
invariant_names: &[&str],
) -> Result<i64, hegel_result_t> {
let rule_cstrings: Vec<CString> = rule_names.iter().map(|s| cstring_lossy(s)).collect();
let invariant_cstrings: Vec<CString> =
invariant_names.iter().map(|s| cstring_lossy(s)).collect();
let rule_ptrs: Vec<*const c_char> = rule_cstrings.iter().map(|c| c.as_ptr()).collect();
let invariant_ptrs: Vec<*const c_char> =
invariant_cstrings.iter().map(|c| c.as_ptr()).collect();
let mut id: i64 = 0;
let rc = with_context(|ctx| unsafe {
hegel_c::hegel_new_state_machine(
ctx,
self.raw,
rule_ptrs.as_ptr(),
rule_ptrs.len(),
invariant_ptrs.as_ptr(),
invariant_ptrs.len(),
&mut id,
)
});
rc_to_value(rc, id)
}
pub(crate) fn state_machine_next_rule(
&self,
state_machine_id: i64,
) -> Result<i64, hegel_result_t> {
let mut out: i64 = 0;
let rc = with_context(|ctx| unsafe {
hegel_c::hegel_state_machine_next_rule(ctx, self.raw, state_machine_id, &mut out)
});
rc_to_value(rc, out)
}
pub(crate) fn target(&self, score: f64, label: &str) -> Result<(), hegel_result_t> {
let c_label = cstring_lossy(label);
rc_to_unit(with_context(|ctx| unsafe {
hegel_c::hegel_target(ctx, self.raw, score, c_label.as_ptr())
}))
}
pub(crate) fn mark_complete(
&self,
status: hegel_c::hegel_status_t,
origin: Option<&str>,
) -> Result<(), hegel_result_t> {
let c_origin = origin.map(cstring_lossy);
let origin_ptr = c_origin.as_ref().map_or(ptr::null(), |c| c.as_ptr());
rc_to_unit(with_context(|ctx| unsafe {
hegel_c::hegel_mark_complete(ctx, self.raw, status, origin_ptr)
}))
}
}
impl Drop for CTestCase {
fn drop(&mut self) {
free_on_drop(|ctx| unsafe { hegel_c::hegel_test_case_free(ctx, self.raw) });
}
}
pub(crate) struct StringGenerator {
raw: *mut hegel_c::HegelStringGenerator,
}
unsafe impl Send for StringGenerator {}
unsafe impl Sync for StringGenerator {}
impl std::fmt::Debug for StringGenerator {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("StringGenerator").finish_non_exhaustive()
}
}
impl StringGenerator {
#[allow(clippy::too_many_arguments)]
pub(crate) fn text(
min_size: u64,
max_size: u64,
codec: Option<&str>,
min_codepoint: u32,
max_codepoint: Option<u32>,
categories: Option<&[String]>,
exclude_categories: Option<&[String]>,
include_characters: Option<&str>,
exclude_characters: Option<&str>,
) -> Result<Self, String> {
let c_codec = codec.map(cstring_lossy);
let c_categories: Option<Vec<CString>> =
categories.map(|cats| cats.iter().map(|c| cstring_lossy(c)).collect());
let c_exclude_categories: Option<Vec<CString>> =
exclude_categories.map(|cats| cats.iter().map(|c| cstring_lossy(c)).collect());
let category_ptrs: Option<Vec<*const c_char>> = c_categories
.as_ref()
.map(|cats| cats.iter().map(|c| c.as_ptr()).collect());
let exclude_category_ptrs: Option<Vec<*const c_char>> = c_exclude_categories
.as_ref()
.map(|cats| cats.iter().map(|c| c.as_ptr()).collect());
let mut raw: *mut hegel_c::HegelStringGenerator = ptr::null_mut();
let rc = with_context(|ctx| unsafe {
hegel_c::hegel_string_generator_text(
ctx,
min_size,
max_size,
c_codec.as_ref().map_or(ptr::null(), |c| c.as_ptr()),
min_codepoint,
max_codepoint.unwrap_or(u32::MAX),
category_ptrs.as_ref().map_or(ptr::null(), |p| p.as_ptr()),
category_ptrs.as_ref().map_or(0, |p| p.len()),
exclude_category_ptrs
.as_ref()
.map_or(ptr::null(), |p| p.as_ptr()),
exclude_category_ptrs.as_ref().map_or(0, |p| p.len()),
include_characters.map_or(ptr::null(), |s| s.as_ptr()),
include_characters.map_or(0, |s| s.len()),
exclude_characters.map_or(ptr::null(), |s| s.as_ptr()),
exclude_characters.map_or(0, |s| s.len()),
&mut raw,
)
});
Self::from_construction(rc, raw)
}
pub(crate) fn regex(
pattern: &str,
fullmatch: bool,
alphabet: Option<&StringGenerator>,
) -> Result<Self, String> {
let c_pattern = cstring_lossy(pattern);
let mut raw: *mut hegel_c::HegelStringGenerator = ptr::null_mut();
let rc = with_context(|ctx| unsafe {
hegel_c::hegel_string_generator_regex(
ctx,
c_pattern.as_ptr(),
fullmatch,
alphabet.map_or(ptr::null(), |a| a.raw),
&mut raw,
)
});
Self::from_construction(rc, raw)
}
pub(crate) fn email() -> Result<Self, String> {
let mut raw: *mut hegel_c::HegelStringGenerator = ptr::null_mut();
let rc =
with_context(|ctx| unsafe { hegel_c::hegel_string_generator_email(ctx, &mut raw) });
Self::from_construction(rc, raw)
}
pub(crate) fn url() -> Result<Self, String> {
let mut raw: *mut hegel_c::HegelStringGenerator = ptr::null_mut();
let rc = with_context(|ctx| unsafe { hegel_c::hegel_string_generator_url(ctx, &mut raw) });
Self::from_construction(rc, raw)
}
pub(crate) fn domain(max_length: u64) -> Result<Self, String> {
let mut raw: *mut hegel_c::HegelStringGenerator = ptr::null_mut();
let rc = with_context(|ctx| unsafe {
hegel_c::hegel_string_generator_domain(ctx, max_length, &mut raw)
});
Self::from_construction(rc, raw)
}
fn from_construction(
rc: hegel_result_t,
raw: *mut hegel_c::HegelStringGenerator,
) -> Result<Self, String> {
if rc != hegel_result_t::HEGEL_OK {
return Err(last_error_string());
}
Ok(StringGenerator { raw })
}
}
impl Drop for StringGenerator {
fn drop(&mut self) {
free_on_drop(|ctx| unsafe { hegel_c::hegel_string_generator_free(ctx, self.raw) });
}
}
pub(crate) struct RunResult {
raw: *mut hegel_c::HegelRunResult,
}
impl RunResult {
pub(crate) fn status(&self) -> hegel_c::hegel_run_status_t {
let mut status = hegel_c::hegel_run_status_t::HEGEL_RUN_STATUS_ERROR;
require_ok(with_context(|ctx| unsafe {
hegel_c::hegel_run_result_status(ctx, self.raw, &mut status)
}));
status
}
pub(crate) fn error(&self) -> Option<String> {
let mut p: *const c_char = ptr::null();
require_ok(with_context(|ctx| unsafe {
hegel_c::hegel_run_result_error(ctx, self.raw, &mut p)
}));
cstr_opt(p)
}
pub(crate) fn failure_count(&self) -> usize {
let mut count = 0;
require_ok(with_context(|ctx| unsafe {
hegel_c::hegel_run_result_failure_count(ctx, self.raw, &mut count)
}));
count
}
pub(crate) fn failure(&self, index: usize) -> Failure {
let mut f: *mut hegel_c::HegelFailure = ptr::null_mut();
require_ok(with_context(|ctx| unsafe {
hegel_c::hegel_run_result_failure(ctx, self.raw, index, &mut f)
}));
let mut blob: *const c_char = ptr::null();
let reproduce_blob = with_context(|ctx| unsafe {
require_ok(hegel_c::hegel_failure_reproduction_blob(ctx, f, &mut blob));
let reproduce_blob = cstr_opt(blob);
require_ok(hegel_c::hegel_failure_free(ctx, f));
reproduce_blob
});
Failure { reproduce_blob }
}
}
impl Drop for RunResult {
fn drop(&mut self) {
free_on_drop(|ctx| unsafe { hegel_c::hegel_run_result_free(ctx, self.raw) });
}
}
pub(crate) struct Failure {
pub(crate) reproduce_blob: Option<String>,
}
fn rc_to_unit(rc: hegel_result_t) -> Result<(), hegel_result_t> {
if rc == hegel_result_t::HEGEL_OK {
Ok(())
} else {
Err(rc)
}
}
fn require_ok(rc: hegel_result_t) {
rc_to_unit(rc).unwrap_or_else(|rc| crate::test_case::raise_for_rc(rc));
}
fn rc_to_value<T>(rc: hegel_result_t, value: T) -> Result<T, hegel_result_t> {
if rc == hegel_result_t::HEGEL_OK {
Ok(value)
} else {
Err(rc)
}
}
fn cstr_opt(p: *const c_char) -> Option<String> {
if p.is_null() {
None
} else {
Some(unsafe { CStr::from_ptr(p) }.to_string_lossy().into_owned())
}
}
fn map_mode(mode: Mode) -> hegel_c::hegel_mode_t {
match mode {
Mode::TestRun => hegel_c::hegel_mode_t::HEGEL_MODE_TEST_RUN,
Mode::SingleTestCase => hegel_c::hegel_mode_t::HEGEL_MODE_SINGLE_TEST_CASE,
}
}
fn map_verbosity(v: Verbosity) -> hegel_c::hegel_verbosity_t {
match v {
Verbosity::Quiet => hegel_c::hegel_verbosity_t::HEGEL_VERBOSITY_QUIET,
Verbosity::Normal => hegel_c::hegel_verbosity_t::HEGEL_VERBOSITY_NORMAL,
Verbosity::Verbose => hegel_c::hegel_verbosity_t::HEGEL_VERBOSITY_VERBOSE,
Verbosity::Debug => hegel_c::hegel_verbosity_t::HEGEL_VERBOSITY_DEBUG,
}
}
fn map_backend(backend: Option<Backend>) -> hegel_c::hegel_backend_t {
match backend {
None => hegel_c::hegel_backend_t::HEGEL_BACKEND_AUTO,
Some(Backend::Default) => hegel_c::hegel_backend_t::HEGEL_BACKEND_DEFAULT,
Some(Backend::Urandom) => hegel_c::hegel_backend_t::HEGEL_BACKEND_URANDOM,
}
}
fn phases_bitmask(phases: &[Phase]) -> u32 {
let mut mask = 0;
for phase in phases {
mask |= match phase {
Phase::Explicit => hegel_c::hegel_phase_t::HEGEL_PHASE_EXPLICIT as u32,
Phase::Reuse => hegel_c::hegel_phase_t::HEGEL_PHASE_REUSE as u32,
Phase::Generate => hegel_c::hegel_phase_t::HEGEL_PHASE_GENERATE as u32,
Phase::Target => hegel_c::hegel_phase_t::HEGEL_PHASE_TARGET as u32,
Phase::Shrink => hegel_c::hegel_phase_t::HEGEL_PHASE_SHRINK as u32,
};
}
mask
}
fn health_check_bitmask(checks: &[HealthCheck]) -> u32 {
let mut mask = 0;
for check in checks {
mask |= match check {
HealthCheck::FilterTooMuch => {
hegel_c::hegel_health_check_t::HEGEL_HC_FILTER_TOO_MUCH as u32
}
HealthCheck::TooSlow => hegel_c::hegel_health_check_t::HEGEL_HC_TOO_SLOW as u32,
HealthCheck::TestCasesTooLarge => {
hegel_c::hegel_health_check_t::HEGEL_HC_TEST_CASES_TOO_LARGE as u32
}
HealthCheck::LargeInitialTestCase => {
hegel_c::hegel_health_check_t::HEGEL_HC_LARGE_INITIAL_TEST_CASE as u32
}
};
}
mask
}
#[cfg(test)]
#[path = "../tests/embedded/ffi_tests.rs"]
mod tests;