Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 41 additions & 1 deletion src/hyperlight_guest_capi/src/flatbuffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ limitations under the License.
*/

use alloc::boxed::Box;
use alloc::ffi::CString;
use alloc::string::String;
use alloc::vec::Vec;
use core::ffi::{CStr, c_char};

use hyperlight_common::flatbuffer_wrappers::util::get_flatbuffer_result;
Expand Down Expand Up @@ -92,6 +95,13 @@ pub extern "C" fn hl_flatbuffer_result_from_Bytes(data: *const u8, len: usize) -
Box::new(unsafe { FfiVec::from_vec(vec) })
}

#[unsafe(no_mangle)]
pub extern "C" fn hl_flatbuffer_result_from_Bool(value: bool) -> Box<FfiVec> {
let vec = get_flatbuffer_result(value);

Box::new(unsafe { FfiVec::from_vec(vec) })
}

//--- Functions for getting values returned by host functions calls

#[unsafe(no_mangle)]
Expand All @@ -115,4 +125,34 @@ pub extern "C" fn hl_get_host_return_value_as_ULong() -> u64 {
get_host_return_value().expect("Unable to get host return value as ulong")
}

// TODO add bool, float, double, string, vecbytes
#[unsafe(no_mangle)]
pub extern "C" fn hl_get_host_return_value_as_Bool() -> bool {
get_host_return_value().expect("Unable to get host return value as bool")
}

#[unsafe(no_mangle)]
pub extern "C" fn hl_get_host_return_value_as_Float() -> f32 {
get_host_return_value().expect("Unable to get host return value as f32")
}

#[unsafe(no_mangle)]
pub extern "C" fn hl_get_host_return_value_as_Double() -> f64 {
get_host_return_value().expect("Unable to get host return value as f64")
}

#[unsafe(no_mangle)]
pub extern "C" fn hl_get_host_return_value_as_String() -> *const c_char {
let string_value: String =
get_host_return_value().expect("Unable to get host return value as string");

let c_string = CString::new(string_value).expect("Failed to create CString");
c_string.into_raw()
}

#[unsafe(no_mangle)]
pub extern "C" fn hl_get_host_return_value_as_VecBytes() -> Box<FfiVec> {
let vec_value: Vec<u8> =
get_host_return_value().expect("Unable to get host return value as vec bytes");

Box::new(unsafe { FfiVec::from_vec(vec_value) })
}
8 changes: 8 additions & 0 deletions src/hyperlight_host/tests/common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@ pub fn new_uninit_rust() -> Result<UninitializedSandbox> {
)
}

/// Returns a c-language simpleguest.
pub fn new_uninit_c() -> Result<UninitializedSandbox> {
UninitializedSandbox::new(
GuestBinary::FilePath(c_simple_guest_as_string().unwrap()),
None,
)
}

pub fn get_simpleguest_sandboxes(
writer: Option<HostFunction<i32, (String,)>>, // An optional writer to make sure correct info is passed to the host printer
) -> Vec<MultiUseSandbox> {
Expand Down
94 changes: 93 additions & 1 deletion src/hyperlight_host/tests/integration_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ use hyperlight_testing::{c_simple_guest_as_string, simple_guest_as_string};
use log::LevelFilter;

pub mod common; // pub to disable dead_code warning
use crate::common::{new_uninit, new_uninit_rust};
use crate::common::{new_uninit, new_uninit_c, new_uninit_rust};

// A host function cannot be interrupted, but we can at least make sure after requesting to interrupt a host call,
// we don't re-enter the guest again once the host call is done
Expand Down Expand Up @@ -765,3 +765,95 @@ fn log_test_messages(levelfilter: Option<log::LevelFilter>) {
.unwrap();
}
}

/// Tests whether host is able to return Bool as return type
/// or not
#[test]
fn test_if_guest_is_able_to_get_bool_return_values_from_host() {
let mut sbox1 = new_uninit_c().unwrap();

sbox1
.register("HostBool", |a: i32, b: i32| a + b > 10)
.unwrap();
let mut sbox3 = sbox1.evolve().unwrap();

for i in 1..10 {
if i < 6 {
let res = sbox3
.call::<bool>("GuestRetrievesBoolValue", (i, i))
.unwrap();
println!("{:?}", res);
assert!(!res);
} else {
let res = sbox3
.call::<bool>("GuestRetrievesBoolValue", (i, i))
.unwrap();
println!("{:?}", res);
assert!(res);
}
}
}

/// Tests whether host is able to return Float/f32 as return type
/// or not
/// Adding Ignore attribute, due known issues with float and double
/// calculations - see Github issue #179. Once it is fixed we can
/// remove ignore attribute
#[ignore]
#[test]
fn test_if_guest_is_able_to_get_float_return_values_from_host() {
let mut sbox1 = new_uninit_c().unwrap();

sbox1
.register("HostAddFloat", |a: f32, b: f32| a + b)
.unwrap();
let mut sbox3 = sbox1.evolve().unwrap();
let res = sbox3
.call::<f32>("GuestRetrievesFloatValue", (1.34_f32, 1.34_f32))
.unwrap();
println!("{:?}", res);
assert_eq!(res, 2.68_f32);
}

/// Tests whether host is able to return Double/f64 as return type
/// or not
/// Adding Ignore attribute, due known issues with float and double
/// calculations - see Github issue #179. Once it is fixed we can
/// remove ignore attribute
#[ignore]
#[test]
fn test_if_guest_is_able_to_get_double_return_values_from_host() {
let mut sbox1 = new_uninit_c().unwrap();

sbox1
.register("HostAddDouble", |a: f64, b: f64| a + b)
.unwrap();
let mut sbox3 = sbox1.evolve().unwrap();
let res = sbox3
.call::<f64>("GuestRetrievesDoubleValue", (1.34_f64, 1.34_f64))
.unwrap();
println!("{:?}", res);
assert_eq!(res, 2.68_f64);
}

/// Tests whether host is able to return String as return type
/// or not
#[test]
fn test_if_guest_is_able_to_get_string_return_values_from_host() {
let mut sbox1 = new_uninit_c().unwrap();

sbox1
.register("HostAddStrings", |a: String| {
a + ", string added by Host Function"
})
.unwrap();
let mut sbox3 = sbox1.evolve().unwrap();
let res = sbox3
.call::<String>("GuestRetrievesStringValue", ())
.unwrap();
println!("{:?}", res);
assert_eq!(
res,
"Guest Function, string added by Host Function".to_string()
);
}
80 changes: 79 additions & 1 deletion src/tests/c_guests/c_simpleguest/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,80 @@ int guest_function(const char *from_host) {
return 0;
}

bool guest_fn_checks_if_host_returns_bool_value(int32_t a, int32_t b) {
hl_Parameter params[2];

params[0].tag = hl_ParameterType_Int;
params[0].value.Int = a;

params[1].tag = hl_ParameterType_Int;
params[1].value.Int = b;

const hl_FunctionCall host_call = {.function_name = "HostBool",
.parameters = params,
.parameters_len = 2,
.return_type = hl_ReturnType_Bool
};
hl_call_host_function(&host_call);
return hl_get_host_return_value_as_Bool();
}

float guest_fn_checks_if_host_returns_float_value(float a, float b) {
hl_Parameter params[2];

params[0].tag = hl_ParameterType_Float;
params[0].value.Float = a;

params[1].tag = hl_ParameterType_Float;
params[1].value.Float = b;

const hl_FunctionCall host_call = {.function_name = "HostAddFloat",
.parameters = params,
.parameters_len = 2,
.return_type = hl_ReturnType_Float
};
hl_call_host_function(&host_call);
return hl_get_host_return_value_as_Float();
}

double guest_fn_checks_if_host_returns_double_value(double a, double b) {
hl_Parameter params[2];

params[0].tag = hl_ParameterType_Double;
params[0].value.Double = a;

params[1].tag = hl_ParameterType_Double;
params[1].value.Double = b;

const hl_FunctionCall host_call = {.function_name = "HostAddDouble",
.parameters = params,
.parameters_len = 2,
.return_type = hl_ReturnType_Double
};
hl_call_host_function(&host_call);
return hl_get_host_return_value_as_Double();
}

const char* guest_fn_checks_if_host_returns_string_value() {
char guest_message[256] = "Guest Function";
hl_Parameter params;

params.tag = hl_ParameterType_String;
params.value.String = guest_message;

const hl_FunctionCall host_call = {.function_name = "HostAddStrings",
.parameters = &params,
.parameters_len = 1,
.return_type = hl_ReturnType_String
};
hl_call_host_function(&host_call);
return hl_get_host_return_value_as_String();
}

HYPERLIGHT_WRAP_FUNCTION(guest_fn_checks_if_host_returns_float_value, Float, 2, Float, Float)
HYPERLIGHT_WRAP_FUNCTION(guest_fn_checks_if_host_returns_double_value, Double, 2, Double, Double)
HYPERLIGHT_WRAP_FUNCTION(guest_fn_checks_if_host_returns_string_value, String, 0)
HYPERLIGHT_WRAP_FUNCTION(guest_fn_checks_if_host_returns_bool_value, Bool, 2, Int, Int)
HYPERLIGHT_WRAP_FUNCTION(echo, String, 1, String)
// HYPERLIGHT_WRAP_FUNCTION(set_byte_array_to_zero, 1, VecBytes) is not valid for functions that return VecBytes
HYPERLIGHT_WRAP_FUNCTION(guest_function, Int, 1, String)
Expand Down Expand Up @@ -289,6 +363,10 @@ HYPERLIGHT_WRAP_FUNCTION(log_message, Int, 2, String, Long)

void hyperlight_main(void)
{
HYPERLIGHT_REGISTER_FUNCTION("GuestRetrievesFloatValue", guest_fn_checks_if_host_returns_float_value);
HYPERLIGHT_REGISTER_FUNCTION("GuestRetrievesDoubleValue", guest_fn_checks_if_host_returns_double_value);
HYPERLIGHT_REGISTER_FUNCTION("GuestRetrievesStringValue", guest_fn_checks_if_host_returns_string_value);
HYPERLIGHT_REGISTER_FUNCTION("GuestRetrievesBoolValue", guest_fn_checks_if_host_returns_bool_value);
HYPERLIGHT_REGISTER_FUNCTION("Echo", echo);
// HYPERLIGHT_REGISTER_FUNCTION macro does not work for functions that return VecBytes,
// so we use hl_register_function_definition directly
Expand Down Expand Up @@ -338,4 +416,4 @@ hl_Vec *c_guest_dispatch_function(const hl_FunctionCall *function_call) {
}

return NULL;
}
}
Loading