Additional tests for BWU (#74)

This commit is contained in:
vms
2021-04-13 12:36:14 +03:00
committed by GitHub
parent ab14b987ea
commit 820e292f15
24 changed files with 701 additions and 257 deletions

View File

@ -11,7 +11,7 @@ jobs:
- checkout
- restore_cache:
keys:
- fce04-{{ checksum "Cargo.lock" }}
- fce05-{{ checksum "Cargo.lock" }}
- run: |
rustup toolchain install nightly-2021-02-27
rustup default nightly-2021-02-27
@ -36,7 +36,7 @@ jobs:
paths:
- ~/.cargo
- ~/.rustup
key: fce04-{{ checksum "Cargo.lock" }}
key: fce05-{{ checksum "Cargo.lock" }}
workflows:
version: 2.1

2
.gitignore vendored
View File

@ -23,4 +23,4 @@ target/
# Allowed Wasm files for test
!/fluence-faas/tests/wasm_tests/arguments_passing/artifacts/*.wasm
!/fluence-faas/tests/wasm_tests/arrays_passing/artifacts/*.wasm
!/fluence-faas/tests/wasm_tests/inner_records/artifacts/inner_records_pure.wasm
!/fluence-faas/tests/wasm_tests/records_passing/artifacts/*.wasm

54
Cargo.lock generated
View File

@ -245,7 +245,7 @@ checksum = "52785868311163c46203e5be682d01623fc550949e24b7943eb8e4b80c9ca937"
dependencies = [
"anyhow",
"chrono",
"reqwest 0.11.2",
"reqwest 0.11.3",
"semver 0.11.0",
"serde",
]
@ -730,7 +730,7 @@ dependencies = [
[[package]]
name = "fce-timestamp-macro"
version = "0.6.0"
source = "git+https://github.com/fluencelabs/rust-sdk#e2a1e66e170abd992ee5b1a1bd21347494fcf91c"
source = "git+https://github.com/fluencelabs/rust-sdk#339dd4d58a9e7481ad4cc9e73e19a8ebe96b46fe"
dependencies = [
"chrono",
"quote",
@ -807,7 +807,7 @@ dependencies = [
[[package]]
name = "fluence"
version = "0.6.0"
source = "git+https://github.com/fluencelabs/rust-sdk#e2a1e66e170abd992ee5b1a1bd21347494fcf91c"
source = "git+https://github.com/fluencelabs/rust-sdk#339dd4d58a9e7481ad4cc9e73e19a8ebe96b46fe"
dependencies = [
"fce-timestamp-macro",
"fluence-sdk-macro 0.6.0",
@ -879,7 +879,7 @@ dependencies = [
[[package]]
name = "fluence-sdk-macro"
version = "0.6.0"
source = "git+https://github.com/fluencelabs/rust-sdk#e2a1e66e170abd992ee5b1a1bd21347494fcf91c"
source = "git+https://github.com/fluencelabs/rust-sdk#339dd4d58a9e7481ad4cc9e73e19a8ebe96b46fe"
dependencies = [
"fluence-sdk-wit 0.6.0",
]
@ -898,7 +898,7 @@ dependencies = [
[[package]]
name = "fluence-sdk-main"
version = "0.6.0"
source = "git+https://github.com/fluencelabs/rust-sdk#e2a1e66e170abd992ee5b1a1bd21347494fcf91c"
source = "git+https://github.com/fluencelabs/rust-sdk#339dd4d58a9e7481ad4cc9e73e19a8ebe96b46fe"
dependencies = [
"fluence-sdk-macro 0.6.0",
"log",
@ -922,7 +922,7 @@ dependencies = [
[[package]]
name = "fluence-sdk-wit"
version = "0.6.0"
source = "git+https://github.com/fluencelabs/rust-sdk#e2a1e66e170abd992ee5b1a1bd21347494fcf91c"
source = "git+https://github.com/fluencelabs/rust-sdk#339dd4d58a9e7481ad4cc9e73e19a8ebe96b46fe"
dependencies = [
"proc-macro2",
"quote",
@ -1175,8 +1175,8 @@ dependencies = [
"http",
"indexmap",
"slab",
"tokio 1.4.0",
"tokio-util 0.6.5",
"tokio 1.5.0",
"tokio-util 0.6.6",
"tracing",
]
@ -1305,7 +1305,7 @@ dependencies = [
"itoa",
"pin-project",
"socket2 0.4.0",
"tokio 1.4.0",
"tokio 1.5.0",
"tower-service",
"tracing",
"want",
@ -1333,7 +1333,7 @@ dependencies = [
"bytes 1.0.1",
"hyper 0.14.5",
"native-tls",
"tokio 1.4.0",
"tokio 1.5.0",
"tokio-native-tls",
]
@ -1371,14 +1371,6 @@ dependencies = [
"serde",
]
[[package]]
name = "inner-records-test"
version = "0.1.0"
dependencies = [
"fluence 0.6.0",
"safe-transmute",
]
[[package]]
name = "instant"
version = "0.1.9"
@ -2117,6 +2109,14 @@ dependencies = [
"test-record",
]
[[package]]
name = "records-passing-test"
version = "0.1.0"
dependencies = [
"fluence 0.6.0",
"safe-transmute",
]
[[package]]
name = "redox_syscall"
version = "0.1.57"
@ -2225,9 +2225,9 @@ dependencies = [
[[package]]
name = "reqwest"
version = "0.11.2"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf12057f289428dbf5c591c74bf10392e4a8003f993405a902f20117019022d4"
checksum = "2296f2fac53979e8ccbc4a1136b25dcefd37be9ed7e4a1f6b05a6029c84ff124"
dependencies = [
"base64",
"bytes 1.0.1",
@ -2249,7 +2249,7 @@ dependencies = [
"serde",
"serde_json",
"serde_urlencoded",
"tokio 1.4.0",
"tokio 1.5.0",
"tokio-native-tls",
"url",
"wasm-bindgen",
@ -2731,9 +2731,9 @@ dependencies = [
[[package]]
name = "tokio"
version = "1.4.0"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "134af885d758d645f0f0505c9a8b3f9bf8a348fd822e112ab5248138348f1722"
checksum = "83f0c8e7c0addab50b663055baf787d0af7f413a46e6e7fb9559a4e4db7137a5"
dependencies = [
"autocfg",
"bytes 1.0.1",
@ -2762,7 +2762,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b"
dependencies = [
"native-tls",
"tokio 1.4.0",
"tokio 1.5.0",
]
[[package]]
@ -2791,16 +2791,16 @@ dependencies = [
[[package]]
name = "tokio-util"
version = "0.6.5"
version = "0.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5143d049e85af7fbc36f5454d990e62c2df705b3589f123b71f441b6b59f443f"
checksum = "940a12c99365c31ea8dd9ba04ec1be183ffe4920102bb7122c2f515437601e8e"
dependencies = [
"bytes 1.0.1",
"futures-core",
"futures-sink",
"log",
"pin-project-lite 0.2.6",
"tokio 1.4.0",
"tokio 1.5.0",
]
[[package]]

View File

@ -22,7 +22,7 @@ members = [
"fluence-faas",
"fluence-faas/tests/wasm_tests/arguments_passing",
"fluence-faas/tests/wasm_tests/arrays_passing",
"fluence-faas/tests/wasm_tests/inner_records",
"fluence-faas/tests/wasm_tests/records_passing",
"tools/cli",
"tools/repl",
]

View File

@ -52,12 +52,7 @@ impl FCE {
arguments: &[IValue],
) -> FCEResult<Vec<IValue>> {
self.modules.get_mut(module_name.as_ref()).map_or_else(
|| {
Err(FCEError::NoSuchModule(format!(
"trying to call module with name {} that is not loaded",
module_name.as_ref()
)))
},
|| Err(FCEError::NoSuchModule(module_name.as_ref().to_string())),
|module| module.call(module_name.as_ref(), func_name.as_ref(), arguments),
)
}
@ -97,12 +92,7 @@ impl FCE {
self.modules
.remove(name.as_ref())
.map(|_| ())
.ok_or_else(|| {
FCEError::NoSuchModule(format!(
"trying to unload module with name {} that is not loaded",
name.as_ref()
))
})
.ok_or_else(|| FCEError::NoSuchModule(name.as_ref().to_string()))
}
pub fn module_wasi_state<S: AsRef<str>>(

View File

@ -131,10 +131,7 @@ impl WITInstance {
Ok((start_index + idx as usize, func))
}
None => Err(FCEError::NoSuchModule(format!(
"trying to get imports from module with name {} that is not loaded",
import.namespace
))),
None => Err(FCEError::NoSuchModule(import.namespace.to_string())),
})
.collect::<FCEResult<HashMap<_, _>>>()
}

View File

@ -56,10 +56,28 @@ pub fn get_interfaces() {
let string_type_sign = fluence_faas::FaaSFunctionSignature {
name: Rc::new(String::from("string_type")),
arguments: Rc::new(string_type_arguments.clone()),
outputs: Rc::new(string_type_outputs.clone()),
};
let string_ref_type_sign = fluence_faas::FaaSFunctionSignature {
name: Rc::new(String::from("string_ref_type")),
arguments: Rc::new(string_type_arguments),
outputs: Rc::new(string_type_outputs),
};
let str_type_arguments = vec![fluence_faas::IFunctionArg {
name: String::from("arg"),
ty: IType::String,
}];
let str_type_outputs = vec![IType::String];
let str_type_sign = fluence_faas::FaaSFunctionSignature {
name: Rc::new(String::from("str_type")),
arguments: Rc::new(str_type_arguments),
outputs: Rc::new(str_type_outputs),
};
let bytearray_type_arguments = vec![fluence_faas::IFunctionArg {
name: String::from("arg"),
ty: IType::Array(Box::new(IType::U8)),
@ -68,6 +86,12 @@ pub fn get_interfaces() {
let bytearray_type_sign = fluence_faas::FaaSFunctionSignature {
name: Rc::new(String::from("bytearray_type")),
arguments: Rc::new(bytearray_type_arguments.clone()),
outputs: Rc::new(bytearray_type_outputs.clone()),
};
let bytearray_ref_type_sign = fluence_faas::FaaSFunctionSignature {
name: Rc::new(String::from("bytearray_ref_type")),
arguments: Rc::new(bytearray_type_arguments),
outputs: Rc::new(bytearray_type_outputs),
};
@ -80,6 +104,12 @@ pub fn get_interfaces() {
let i32_type_sign = fluence_faas::FaaSFunctionSignature {
name: Rc::new(String::from("i32_type")),
arguments: Rc::new(i32_type_arguments.clone()),
outputs: Rc::new(i32_type_outputs.clone()),
};
let i32_ref_type_sign = fluence_faas::FaaSFunctionSignature {
name: Rc::new(String::from("i32_ref_type")),
arguments: Rc::new(i32_type_arguments),
outputs: Rc::new(i32_type_outputs),
};
@ -93,6 +123,12 @@ pub fn get_interfaces() {
let i64_type_sign = fluence_faas::FaaSFunctionSignature {
name: Rc::new(String::from("i64_type")),
arguments: Rc::new(i64_type_arguments.clone()),
outputs: Rc::new(i64_type_outputs.clone()),
};
let i64_ref_type_sign = fluence_faas::FaaSFunctionSignature {
name: Rc::new(String::from("i64_ref_type")),
arguments: Rc::new(i64_type_arguments),
outputs: Rc::new(i64_type_outputs),
};
@ -105,6 +141,12 @@ pub fn get_interfaces() {
let u32_type_sign = fluence_faas::FaaSFunctionSignature {
name: Rc::new(String::from("u32_type")),
arguments: Rc::new(u32_type_arguments.clone()),
outputs: Rc::new(u32_type_outputs.clone()),
};
let u32_ref_type_sign = fluence_faas::FaaSFunctionSignature {
name: Rc::new(String::from("u32_ref_type")),
arguments: Rc::new(u32_type_arguments),
outputs: Rc::new(u32_type_outputs),
};
@ -117,6 +159,12 @@ pub fn get_interfaces() {
let u64_type_sign = fluence_faas::FaaSFunctionSignature {
name: Rc::new(String::from("u64_type")),
arguments: Rc::new(u64_type_arguments.clone()),
outputs: Rc::new(u64_type_outputs.clone()),
};
let u64_ref_type_sign = fluence_faas::FaaSFunctionSignature {
name: Rc::new(String::from("u64_ref_type")),
arguments: Rc::new(u64_type_arguments),
outputs: Rc::new(u64_type_outputs),
};
@ -129,6 +177,12 @@ pub fn get_interfaces() {
let f32_type_sign = fluence_faas::FaaSFunctionSignature {
name: Rc::new(String::from("f32_type")),
arguments: Rc::new(f32_type_arguments.clone()),
outputs: Rc::new(f32_type_outputs.clone()),
};
let f32_ref_type_sign = fluence_faas::FaaSFunctionSignature {
name: Rc::new(String::from("f32_ref_type")),
arguments: Rc::new(f32_type_arguments),
outputs: Rc::new(f32_type_outputs),
};
@ -141,6 +195,12 @@ pub fn get_interfaces() {
let f64_type_sign = fluence_faas::FaaSFunctionSignature {
name: Rc::new(String::from("f64_type")),
arguments: Rc::new(f64_type_arguments.clone()),
outputs: Rc::new(f64_type_outputs.clone()),
};
let f64_ref_type_sign = fluence_faas::FaaSFunctionSignature {
name: Rc::new(String::from("f64_ref_type")),
arguments: Rc::new(f64_type_arguments),
outputs: Rc::new(f64_type_outputs),
};
@ -162,6 +222,12 @@ pub fn get_interfaces() {
let bool_type_sign = fluence_faas::FaaSFunctionSignature {
name: Rc::new(String::from("bool_type")),
arguments: Rc::new(bool_type_arguments.clone()),
outputs: Rc::new(bool_type_outputs.clone()),
};
let bool_ref_type_sign = fluence_faas::FaaSFunctionSignature {
name: Rc::new(String::from("bool_ref_type")),
arguments: Rc::new(bool_type_arguments),
outputs: Rc::new(bool_type_outputs),
};
@ -220,22 +286,39 @@ pub fn get_interfaces() {
let all_types_sign = fluence_faas::FaaSFunctionSignature {
name: Rc::new(String::from("all_types")),
arguments: Rc::new(all_types_arguments.clone()),
outputs: Rc::new(all_types_outputs.clone()),
};
let all_ref_types_sign = fluence_faas::FaaSFunctionSignature {
name: Rc::new(String::from("all_ref_types")),
arguments: Rc::new(all_types_arguments),
outputs: Rc::new(all_types_outputs),
};
let functions = vec![
string_type_sign,
string_ref_type_sign,
str_type_sign,
bytearray_type_sign,
bytearray_ref_type_sign,
i32_type_sign,
i32_ref_type_sign,
i64_type_sign,
i64_ref_type_sign,
u32_type_sign,
u32_ref_type_sign,
u64_type_sign,
u64_ref_type_sign,
f32_type_sign,
f32_ref_type_sign,
f64_type_sign,
f64_ref_type_sign,
empty_type_sign,
bool_type_sign,
bool_ref_type_sign,
all_types_sign,
all_ref_types_sign,
];
let pure_module_name = "arguments_passing_pure";
@ -268,22 +351,22 @@ pub fn get_interfaces() {
#[test]
pub fn all_types() {
const FUNC_NAME: &'static str = "all_types";
let mut faas = FluenceFaaS::with_raw_config(ARG_CONFIG.clone())
.unwrap_or_else(|e| panic!("can't create Fluence FaaS instance: {}", e));
let result1 = faas.call_with_json(MODULE_NAME, FUNC_NAME, json!({}), <_>::default());
let mut test = |func_name: &str| {
let result1 = faas.call_with_json(MODULE_NAME, func_name, json!({}), <_>::default());
assert!(result1.is_err());
let result2 = faas.call_with_json(MODULE_NAME, FUNC_NAME, json!([]), <_>::default());
let result2 = faas.call_with_json(MODULE_NAME, func_name, json!([]), <_>::default());
assert!(result2.is_err());
let expected_result = json!([
0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4, 5, 0, 6, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0,
65, 1, 153, 154, 64, 34, 51, 51, 51, 51, 51, 51, 102, 108, 117, 101, 110, 99, 101, 19, 55,
0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4, 5, 0, 6, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0,
65, 1, 153, 154, 64, 34, 51, 51, 51, 51, 51, 51, 102, 108, 117, 101, 110, 99, 101, 19, 55
0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4, 5, 0, 6, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0,
0, 65, 1, 153, 154, 64, 34, 51, 51, 51, 51, 51, 51, 102, 108, 117, 101, 110, 99, 101,
19, 55, 0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4, 5, 0, 6, 0, 0, 0, 7, 0, 0, 0,
0, 0, 0, 0, 65, 1, 153, 154, 64, 34, 51, 51, 51, 51, 51, 51, 102, 108, 117, 101, 110,
99, 101, 19, 55
]);
let faas_arg = json!({
@ -300,7 +383,7 @@ pub fn all_types() {
"arg_10": "fluence",
"arg_11": vec! [0x13, 0x37],
});
let result3 = call_faas!(faas, MODULE_NAME, FUNC_NAME, faas_arg);
let result3 = call_faas!(faas, MODULE_NAME, func_name, faas_arg);
assert_eq!(result3, expected_result);
let faas_arg = json!([
@ -317,177 +400,223 @@ pub fn all_types() {
"fluence",
vec![0x13, 0x37]
]);
let result4 = call_faas!(faas, MODULE_NAME, FUNC_NAME, faas_arg);
let result4 = call_faas!(faas, MODULE_NAME, func_name, faas_arg);
assert_eq!(result4, expected_result);
};
test("all_types");
test("all_ref_types");
}
#[test]
pub fn i32_type() {
const FUNC_NAME: &'static str = "i32_type";
let test = |func_name: &str| {
let mut faas = FluenceFaaS::with_raw_config(ARG_CONFIG.clone())
.unwrap_or_else(|e| panic!("can't create Fluence FaaS instance: {}", e));
let result1 = faas.call_with_json(MODULE_NAME, FUNC_NAME, json!({}), <_>::default());
let result1 = faas.call_with_json(MODULE_NAME, func_name, json!({}), <_>::default());
assert!(result1.is_err());
let result2 = faas.call_with_json(MODULE_NAME, FUNC_NAME, json!([]), <_>::default());
let result2 = faas.call_with_json(MODULE_NAME, func_name, json!([]), <_>::default());
assert!(result2.is_err());
let expected_result = json!(3);
let result3 = call_faas!(faas, MODULE_NAME, FUNC_NAME, json!({ "arg": 1 }));
let result3 = call_faas!(faas, MODULE_NAME, func_name, json!({ "arg": 1 }));
assert_eq!(result3, expected_result);
let result4 = call_faas!(faas, MODULE_NAME, FUNC_NAME, json!(1));
let result4 = call_faas!(faas, MODULE_NAME, func_name, json!(1));
assert_eq!(result4, expected_result);
let result5 = call_faas!(faas, MODULE_NAME, FUNC_NAME, json!([[1]]));
let result5 = call_faas!(faas, MODULE_NAME, func_name, json!([[1]]));
assert_eq!(result5, expected_result);
let value = std::i32::MAX - 2;
let result6 = call_faas!(faas, MODULE_NAME, FUNC_NAME, json!(value));
let result6 = call_faas!(faas, MODULE_NAME, func_name, json!(value));
assert_eq!(result6, value + 2);
let value = std::i32::MIN;
let result7 = call_faas!(faas, MODULE_NAME, FUNC_NAME, json!(value));
let result7 = call_faas!(faas, MODULE_NAME, func_name, json!(value));
assert_eq!(result7, value + 2);
};
test("i32_type");
test("i32_ref_type");
}
#[test]
pub fn i64_type() {
const FUNC_NAME: &'static str = "i64_type";
let mut faas = FluenceFaaS::with_raw_config(ARG_CONFIG.clone())
.unwrap_or_else(|e| panic!("can't create Fluence FaaS instance: {}", e));
let result1 = faas.call_with_json(MODULE_NAME, FUNC_NAME, json!({}), <_>::default());
let mut test = |func_name: &str| {
let result1 = faas.call_with_json(MODULE_NAME, func_name, json!({}), <_>::default());
assert!(result1.is_err());
let result2 = faas.call_with_json(MODULE_NAME, FUNC_NAME, json!([]), <_>::default());
let result2 = faas.call_with_json(MODULE_NAME, func_name, json!([]), <_>::default());
assert!(result2.is_err());
let expected_result = json!(3);
let result3 = call_faas!(faas, MODULE_NAME, FUNC_NAME, json!({ "arg": 1 }));
let result3 = call_faas!(faas, MODULE_NAME, func_name, json!({ "arg": 1 }));
assert_eq!(result3, expected_result);
let result4 = call_faas!(faas, MODULE_NAME, FUNC_NAME, json!(1));
let result4 = call_faas!(faas, MODULE_NAME, func_name, json!(1));
assert_eq!(result4, expected_result);
let result5 = call_faas!(faas, MODULE_NAME, FUNC_NAME, json!([1]));
let result5 = call_faas!(faas, MODULE_NAME, func_name, json!([1]));
assert_eq!(result5, expected_result);
let value = std::i64::MAX - 2;
let result6 = call_faas!(faas, MODULE_NAME, FUNC_NAME, json!(value));
let result6 = call_faas!(faas, MODULE_NAME, func_name, json!(value));
assert_eq!(result6, value + 2);
let value = std::i64::MIN;
let result7 = call_faas!(faas, MODULE_NAME, FUNC_NAME, json!(value));
let result7 = call_faas!(faas, MODULE_NAME, func_name, json!(value));
assert_eq!(result7, value + 2);
};
test("i64_type");
test("i64_ref_type");
}
#[test]
pub fn u32_type() {
const FUNC_NAME: &'static str = "u32_type";
let mut faas = FluenceFaaS::with_raw_config(ARG_CONFIG.clone())
.unwrap_or_else(|e| panic!("can't create Fluence FaaS instance: {}", e));
let result1 = faas.call_with_json(MODULE_NAME, FUNC_NAME, json!({}), <_>::default());
let mut test = |func_name: &str| {
let result1 = faas.call_with_json(MODULE_NAME, func_name, json!({}), <_>::default());
assert!(result1.is_err());
let result2 = faas.call_with_json(MODULE_NAME, FUNC_NAME, json!([]), <_>::default());
let result2 = faas.call_with_json(MODULE_NAME, func_name, json!([]), <_>::default());
assert!(result2.is_err());
let expected_result = json!(3);
let result3 = call_faas!(faas, MODULE_NAME, FUNC_NAME, json!({ "arg": 1 }));
let result3 = call_faas!(faas, MODULE_NAME, func_name, json!({ "arg": 1 }));
assert_eq!(result3, expected_result);
let result4 = call_faas!(faas, MODULE_NAME, FUNC_NAME, json!(1));
let result4 = call_faas!(faas, MODULE_NAME, func_name, json!(1));
assert_eq!(result4, expected_result);
};
test("u32_type");
test("u32_ref_type");
}
#[test]
pub fn u64_type() {
const FUNC_NAME: &'static str = "u64_type";
let mut faas = FluenceFaaS::with_raw_config(ARG_CONFIG.clone())
.unwrap_or_else(|e| panic!("can't create Fluence FaaS instance: {}", e));
let result1 = faas.call_with_json(MODULE_NAME, FUNC_NAME, json!({}), <_>::default());
let mut test = |func_name: &str| {
let result1 = faas.call_with_json(MODULE_NAME, func_name, json!({}), <_>::default());
assert!(result1.is_err());
let result2 = faas.call_with_json(MODULE_NAME, FUNC_NAME, json!([]), <_>::default());
let result2 = faas.call_with_json(MODULE_NAME, func_name, json!([]), <_>::default());
assert!(result2.is_err());
let expected_result = json!(3);
let result3 = call_faas!(faas, MODULE_NAME, FUNC_NAME, json!({ "arg": 1 }));
let result3 = call_faas!(faas, MODULE_NAME, func_name, json!({ "arg": 1 }));
assert_eq!(result3, expected_result);
let result4 = call_faas!(faas, MODULE_NAME, FUNC_NAME, json!(1));
let result4 = call_faas!(faas, MODULE_NAME, func_name, json!(1));
assert_eq!(result4, expected_result);
};
test("u64_type");
test("u64_ref_type");
}
#[test]
pub fn f32_type() {
const FUNC_NAME: &'static str = "f32_type";
let mut faas = FluenceFaaS::with_raw_config(ARG_CONFIG.clone())
.unwrap_or_else(|e| panic!("can't create Fluence FaaS instance: {}", e));
let result1 = faas.call_with_json(MODULE_NAME, FUNC_NAME, json!({}), <_>::default());
let mut test = |func_name: &str| {
let result1 = faas.call_with_json(MODULE_NAME, func_name, json!({}), <_>::default());
assert!(result1.is_err());
let result2 = faas.call_with_json(MODULE_NAME, FUNC_NAME, json!([]), <_>::default());
let result2 = faas.call_with_json(MODULE_NAME, func_name, json!([]), <_>::default());
assert!(result2.is_err());
let expected_result = json!(3.0);
let result3 = call_faas!(faas, MODULE_NAME, FUNC_NAME, json!({ "arg": 1.0 }));
let result3 = call_faas!(faas, MODULE_NAME, func_name, json!({ "arg": 1.0 }));
assert_eq!(result3, expected_result);
let result4 = call_faas!(faas, MODULE_NAME, FUNC_NAME, json!(1.0));
let result4 = call_faas!(faas, MODULE_NAME, func_name, json!(1.0));
assert_eq!(result4, expected_result);
let value = std::f32::MAX - 2.0;
let result5 = call_faas!(faas, MODULE_NAME, FUNC_NAME, json!(value));
let result5 = call_faas!(faas, MODULE_NAME, func_name, json!(value));
assert_eq!(result5, value + 2.0);
let value = std::f32::MIN;
let result6 = call_faas!(faas, MODULE_NAME, FUNC_NAME, json!(value));
let result6 = call_faas!(faas, MODULE_NAME, func_name, json!(value));
assert_eq!(result6, value + 2.0);
};
test("f32_type");
test("f32_ref_type");
}
#[test]
pub fn f64_type() {
const FUNC_NAME: &'static str = "f64_type";
let mut faas = FluenceFaaS::with_raw_config(ARG_CONFIG.clone())
.unwrap_or_else(|e| panic!("can't create Fluence FaaS instance: {}", e));
let result1 = faas.call_with_json(MODULE_NAME, FUNC_NAME, json!({}), <_>::default());
let mut test = |func_name: &str| {
let result1 = faas.call_with_json(MODULE_NAME, func_name, json!({}), <_>::default());
assert!(result1.is_err());
let result2 = faas.call_with_json(MODULE_NAME, FUNC_NAME, json!([]), <_>::default());
let result2 = faas.call_with_json(MODULE_NAME, func_name, json!([]), <_>::default());
assert!(result2.is_err());
let expected_result = json!(3.0);
let result3 = call_faas!(faas, MODULE_NAME, FUNC_NAME, json!({ "arg": 1.0 }));
let result3 = call_faas!(faas, MODULE_NAME, func_name, json!({ "arg": 1.0 }));
assert_eq!(result3, expected_result);
let result4 = call_faas!(faas, MODULE_NAME, FUNC_NAME, json!(1.0));
let result4 = call_faas!(faas, MODULE_NAME, func_name, json!(1.0));
assert_eq!(result4, expected_result);
let value = std::f64::MAX - 2.0;
let result5 = call_faas!(faas, MODULE_NAME, FUNC_NAME, json!(value));
let result5 = call_faas!(faas, MODULE_NAME, func_name, json!(value));
assert_eq!(result5, value + 2.0);
let value = std::f64::MIN;
let result6 = call_faas!(faas, MODULE_NAME, FUNC_NAME, json!(value));
let result6 = call_faas!(faas, MODULE_NAME, func_name, json!(value));
assert_eq!(result6, value + 2.0);
};
test("f64_type");
test("f64_ref_type");
}
#[test]
pub fn string_type() {
const FUNC_NAME: &'static str = "string_type";
let mut faas = FluenceFaaS::with_raw_config(ARG_CONFIG.clone())
.unwrap_or_else(|e| panic!("can't create Fluence FaaS instance: {}", e));
let mut test = |func_name: &str| {
let result1 = faas.call_with_json(MODULE_NAME, func_name, json!({}), <_>::default());
assert!(result1.is_err());
let result2 = faas.call_with_json(MODULE_NAME, func_name, json!([]), <_>::default());
assert!(result2.is_err());
let expected_result = json!("Fluence_Fluence_Fluence_Fluence");
let result3 = call_faas!(faas, MODULE_NAME, func_name, json!({ "arg": "Fluence" }));
assert_eq!(result3, expected_result);
let result4 = call_faas!(faas, MODULE_NAME, func_name, json!("Fluence"));
assert_eq!(result4, expected_result);
};
test("string_type");
test("string_ref_type");
}
#[test]
pub fn str_type() {
const FUNC_NAME: &'static str = "str_type";
let mut faas = FluenceFaaS::with_raw_config(ARG_CONFIG.clone())
.unwrap_or_else(|e| panic!("can't create Fluence FaaS instance: {}", e));
@ -508,47 +637,53 @@ pub fn string_type() {
#[test]
pub fn bytearray_type() {
const FUNC_NAME: &'static str = "bytearray_type";
let mut faas = FluenceFaaS::with_raw_config(ARG_CONFIG.clone())
.unwrap_or_else(|e| panic!("can't create Fluence FaaS instance: {}", e));
let result1 = faas.call_with_json(MODULE_NAME, FUNC_NAME, json!({}), <_>::default());
let mut test = |func_name: &str| {
let result1 = faas.call_with_json(MODULE_NAME, func_name, json!({}), <_>::default());
assert!(result1.is_err());
let result2 = faas.call_with_json(MODULE_NAME, FUNC_NAME, json!([]), <_>::default());
let result2 = faas.call_with_json(MODULE_NAME, func_name, json!([]), <_>::default());
assert!(result2.is_err());
let expected_result = json!([0x13, 0x37, 1, 1]);
let result3 = call_faas!(faas, MODULE_NAME, FUNC_NAME, json!({ "arg": [0x13, 0x37] }));
let result3 = call_faas!(faas, MODULE_NAME, func_name, json!({ "arg": [0x13, 0x37] }));
assert_eq!(result3, expected_result);
let result4 = call_faas!(faas, MODULE_NAME, FUNC_NAME, json!([[0x13, 0x37]]));
let result4 = call_faas!(faas, MODULE_NAME, func_name, json!([[0x13, 0x37]]));
assert_eq!(result4, expected_result);
let result5 = call_faas!(faas, MODULE_NAME, FUNC_NAME, json!([[0x13]]));
let result5 = call_faas!(faas, MODULE_NAME, func_name, json!([[0x13]]));
assert_eq!(result5, json!([0x13, 1, 1]));
};
test("bytearray_type");
test("bytearray_ref_type");
}
#[test]
pub fn bool_type() {
const FUNC_NAME: &'static str = "bool_type";
let mut faas = FluenceFaaS::with_raw_config(ARG_CONFIG.clone())
.unwrap_or_else(|e| panic!("can't create Fluence FaaS instance: {}", e));
let result1 = faas.call_with_json(MODULE_NAME, FUNC_NAME, json!({}), <_>::default());
let mut test = |func_name: &str| {
let result1 = faas.call_with_json(MODULE_NAME, func_name, json!({}), <_>::default());
assert!(result1.is_err());
let result2 = faas.call_with_json(MODULE_NAME, FUNC_NAME, json!([]), <_>::default());
let result2 = faas.call_with_json(MODULE_NAME, func_name, json!([]), <_>::default());
assert!(result2.is_err());
let expected_result = json!(1);
let result3 = call_faas!(faas, MODULE_NAME, FUNC_NAME, json!({ "arg": 0 }));
let result3 = call_faas!(faas, MODULE_NAME, func_name, json!({ "arg": 0 }));
assert_eq!(result3, expected_result);
let result4 = call_faas!(faas, MODULE_NAME, FUNC_NAME, json!(0));
let result4 = call_faas!(faas, MODULE_NAME, func_name, json!(0));
assert_eq!(result4, expected_result);
};
test("bool_type");
test("bool_ref_type");
}
#[test]

View File

@ -157,24 +157,25 @@ pub fn records() {
}
#[test]
fn inner_records() {
let inner_records_config_raw = std::fs::read("./tests/wasm_tests/inner_records/Config.toml")
.expect("../examples/greeting/artifacts/greeting.wasm should presence");
fn records_passing() {
let inner_records_config_raw = std::fs::read("./tests/wasm_tests/records_passing/Config.toml")
.expect("./tests/wasm_tests/records_passing/Config.toml should presence");
let mut inner_records_config: fluence_faas::TomlFaaSConfig =
let mut records_passing_config: fluence_faas::TomlFaaSConfig =
toml::from_slice(&inner_records_config_raw)
.expect("argument passing test config should be well-formed");
inner_records_config.modules_dir =
Some(String::from("./tests/wasm_tests/inner_records/artifacts"));
records_passing_config.modules_dir =
Some(String::from("./tests/wasm_tests/records_passing/artifacts"));
let mut faas = FluenceFaaS::with_raw_config(inner_records_config)
let mut faas = FluenceFaaS::with_raw_config(records_passing_config)
.unwrap_or_else(|e| panic!("can't create Fluence FaaS instance: {}", e));
let mut test = |func_name: &str| {
let result = faas
.call_with_json(
"inner_records_pure",
"test_record",
"records_passing_pure",
func_name,
json!({
"test_record": {
"test_record_0": {
@ -200,13 +201,17 @@ fn inner_records() {
},
"test_record_1": {
"field_0": 1,
"field_1": "",
"field_2": vec![1],
"field_1": "fluence",
"field_2": vec![0x13, 0x37],
"test_record_0": {
"field_0": 1
"field_0": 5
}
}
});
assert_eq!(result, right_result);
};
test("test_record");
test("test_record_ref");
}

View File

@ -14,6 +14,5 @@ name = "arguments_passing_effector"
path = "src/effector.rs"
[dependencies]
#fluence = { git = "https://github.com/fluencelabs/rust-sdk" }
fluence = { git = "https://github.com/fluencelabs/rust-sdk" }
safe-transmute = "0.11.0"

View File

@ -51,52 +51,136 @@ pub fn all_types(
result
}
#[fce]
pub fn all_ref_types(
arg_0: &i8,
arg_1: &i16,
arg_2: &i32,
arg_3: &i64,
arg_4: &u8,
arg_5: &u16,
arg_6: &u32,
arg_7: &u64,
arg_8: &f32,
arg_9: &f64,
arg_10: &String,
arg_11: &Vec<u8>,
) -> Vec<u8> {
let mut result = Vec::new();
result.push(*arg_0 as u8);
result.extend(safe_transmute::transmute_one_to_bytes(arg_1));
result.extend(safe_transmute::transmute_one_to_bytes(arg_2));
result.extend(safe_transmute::transmute_one_to_bytes(arg_3));
result.extend(safe_transmute::transmute_one_to_bytes(arg_4));
result.extend(safe_transmute::transmute_one_to_bytes(arg_5));
result.extend(safe_transmute::transmute_one_to_bytes(arg_6));
result.extend(safe_transmute::transmute_one_to_bytes(arg_7));
result.extend(&arg_8.to_be_bytes());
result.extend(&arg_9.to_be_bytes());
result.extend(arg_10.as_bytes());
result.extend(arg_11);
result
}
#[fce]
pub fn string_type(arg: String) -> String {
format!("{}_{}", arg, arg)
}
#[fce]
pub fn string_ref_type(arg: &String) -> String {
format!("{}_{}", arg, arg)
}
#[fce]
pub fn str_type(arg: &str) -> String {
format!("{}_{}", arg, arg)
}
#[fce]
pub fn bytearray_type(mut arg: Vec<u8>) -> Vec<u8> {
arg.push(1);
arg
}
#[fce]
pub fn bytearray_ref_type(arg: &mut Vec<u8>) -> Vec<u8> {
arg.push(1);
arg.clone()
}
#[fce]
pub fn bool_type(arg: bool) -> bool {
!arg
}
#[fce]
pub fn bool_ref_type(arg: &bool) -> bool {
!*arg
}
#[fce]
pub fn f32_type(arg: f32) -> f32 {
arg + 1.0
}
#[fce]
pub fn f32_ref_type(arg: &f32) -> f32 {
*arg + 1.0
}
#[fce]
pub fn f64_type(arg: f64) -> f64 {
arg + 1.0
}
#[fce]
pub fn f64_ref_type(arg: &f64) -> f64 {
*arg + 1.0
}
#[fce]
pub fn u32_type(arg: u32) -> u32 {
arg + 1
}
#[fce]
pub fn u32_ref_type(arg: &u32) -> u32 {
*arg + 1
}
#[fce]
pub fn u64_type(arg: u64) -> u64 {
arg + 1
}
#[fce]
pub fn u64_ref_type(arg: &u64) -> u64 {
*arg + 1
}
#[fce]
pub fn i32_type(arg: i32) -> i32 {
arg + 1
}
#[fce]
pub fn i32_ref_type(arg: &i32) -> i32 {
*arg + 1
}
#[fce]
pub fn i64_type(arg: i64) -> i64 {
arg + 1
}
#[fce]
pub fn i64_ref_type(arg: &i64) -> i64 {
*arg + 1
}
#[fce]
pub fn empty_type() -> String {
String::from("success")

View File

@ -68,6 +68,43 @@ pub fn all_types(
result
}
#[fce]
pub fn all_ref_types(
arg_0: &i8,
arg_1: &i16,
arg_2: &i32,
arg_3: &i64,
arg_4: &u8,
arg_5: &u16,
arg_6: &u32,
arg_7: &u64,
arg_8: &f32,
arg_9: &f64,
arg_10: &String,
arg_11: &Vec<u8>,
) -> Vec<u8> {
let mut result = unsafe {
effector::all_ref_types(
arg_0, arg_1, arg_2, arg_3, arg_4, arg_5, arg_6, arg_7, arg_8, arg_9, arg_10, arg_11,
)
};
result.push(*arg_0 as u8);
result.extend(safe_transmute::transmute_one_to_bytes(arg_1));
result.extend(safe_transmute::transmute_one_to_bytes(arg_2));
result.extend(safe_transmute::transmute_one_to_bytes(arg_3));
result.extend(safe_transmute::transmute_one_to_bytes(arg_4));
result.extend(safe_transmute::transmute_one_to_bytes(arg_5));
result.extend(safe_transmute::transmute_one_to_bytes(arg_6));
result.extend(safe_transmute::transmute_one_to_bytes(arg_7));
result.extend(&arg_8.to_be_bytes());
result.extend(&arg_9.to_be_bytes());
result.extend(arg_10.as_bytes());
result.extend(arg_11);
result
}
#[fce]
pub fn string_type(arg: String) -> String {
let arg = unsafe { effector::string_type(arg) };
@ -75,6 +112,20 @@ pub fn string_type(arg: String) -> String {
format!("{}_{}", arg, arg)
}
#[fce]
pub fn string_ref_type(arg: &String) -> String {
let arg = unsafe { effector::string_ref_type(arg) };
format!("{}_{}", arg, arg)
}
#[fce]
pub fn str_type(arg: &str) -> String {
let arg = unsafe { effector::str_type(arg) };
format!("{}_{}", arg, arg)
}
#[fce]
pub fn bytearray_type(arg: Vec<u8>) -> Vec<u8> {
let mut arg = unsafe { effector::bytearray_type(arg) };
@ -83,47 +134,96 @@ pub fn bytearray_type(arg: Vec<u8>) -> Vec<u8> {
arg
}
#[fce]
pub fn bytearray_ref_type(arg: &Vec<u8>) -> Vec<u8> {
let mut arg = unsafe { effector::bytearray_ref_type(arg) };
arg.push(1);
arg
}
#[fce]
pub fn bool_type(arg: bool) -> bool {
unsafe { effector::bool_type(arg) }
}
#[fce]
pub fn bool_ref_type(arg: &bool) -> bool {
unsafe { effector::bool_ref_type(arg) }
}
#[fce]
pub fn f32_type(arg: f32) -> f32 {
let arg = unsafe { effector::f32_type(arg) };
arg + 1.0
}
#[fce]
pub fn f32_ref_type(arg: &f32) -> f32 {
let arg = unsafe { effector::f32_ref_type(arg) };
arg + 1.0
}
#[fce]
pub fn f64_type(arg: f64) -> f64 {
let arg = unsafe { effector::f64_type(arg) };
arg + 1.0
}
#[fce]
pub fn f64_ref_type(arg: &f64) -> f64 {
let arg = unsafe { effector::f64_ref_type(arg) };
arg + 1.0
}
#[fce]
pub fn u32_type(arg: u32) -> u32 {
let arg = unsafe { effector::u32_type(arg) };
arg + 1
}
#[fce]
pub fn u32_ref_type(arg: &u32) -> u32 {
let arg = unsafe { effector::u32_ref_type(arg) };
arg + 1
}
#[fce]
pub fn u64_type(arg: u64) -> u64 {
let arg = unsafe { effector::u64_type(arg) };
arg + 1
}
#[fce]
pub fn u64_ref_type(arg: &u64) -> u64 {
let arg = unsafe { effector::u64_ref_type(arg) };
arg + 1
}
#[fce]
pub fn i32_type(arg: i32) -> i32 {
let arg = unsafe { effector::i32_type(arg) };
arg + 1
}
#[fce]
pub fn i32_ref_type(arg: &i32) -> i32 {
let arg = unsafe { effector::i32_ref_type(arg) };
arg + 1
}
#[fce]
pub fn i64_type(arg: i64) -> i64 {
let arg = unsafe { effector::i64_type(arg) };
arg + 1
}
#[fce]
pub fn i64_ref_type(arg: &i64) -> i64 {
let arg = unsafe { effector::i64_ref_type(arg) };
arg + 1
}
#[fce]
pub fn empty_type() -> String {
unsafe { effector::empty_type() }
@ -150,19 +250,49 @@ mod effector {
arg_11: Vec<u8>,
) -> Vec<u8>;
pub fn all_ref_types(
arg_0: &i8,
arg_1: &i16,
arg_2: &i32,
arg_3: &i64,
arg_4: &u8,
arg_5: &u16,
arg_6: &u32,
arg_7: &u64,
arg_8: &f32,
arg_9: &f64,
arg_10: &String,
arg_11: &Vec<u8>,
) -> Vec<u8>;
pub fn string_type(arg: String) -> String;
pub fn string_ref_type(arg: &String) -> String;
pub fn str_type(arg: &str) -> String;
pub fn bytearray_type(arg: Vec<u8>) -> Vec<u8>;
pub fn bytearray_ref_type(arg: &Vec<u8>) -> Vec<u8>;
pub fn bool_type(arg: bool) -> bool;
pub fn bool_ref_type(arg: &bool) -> bool;
pub fn f32_type(arg: f32) -> f32;
pub fn f32_ref_type(arg: &f32) -> f32;
pub fn f64_type(arg: f64) -> f64;
pub fn f64_ref_type(arg: &f64) -> f64;
pub fn u32_type(arg: u32) -> u32;
pub fn u32_ref_type(arg: &u32) -> u32;
pub fn u64_type(arg: u64) -> u64;
pub fn u64_ref_type(arg: &u64) -> u64;
pub fn i32_type(arg: i32) -> i32;
pub fn i32_ref_type(arg: &i32) -> i32;
pub fn i64_type(arg: i64) -> i64;
pub fn i64_ref_type(arg: &i64) -> i64;
pub fn empty_type() -> String;
}

View File

@ -5,25 +5,26 @@
cd arguments_passing || exit;
cargo update;
fce build --release;
rm artifacts/*;
rm artifacts/* || true;
)
(
cd arrays_passing || exit;
cargo update;
fce build --release;
rm artifacts/*;
rm artifacts/* || true;
)
(
cd inner_records || exit;
cd records_passing || exit;
cargo update;
fce build --release;
rm artifacts/*;
rm artifacts/* || true;
)
cp ../../../target/wasm32-wasi/release/arguments_passing_effector.wasm arguments_passing/artifacts/
cp ../../../target/wasm32-wasi/release/arguments_passing_pure.wasm arguments_passing/artifacts/
cp ../../../target/wasm32-wasi/release/arrays_passing_effector.wasm arrays_passing/artifacts/
cp ../../../target/wasm32-wasi/release/arrays_passing_pure.wasm arrays_passing/artifacts/
cp ../../../target/wasm32-wasi/release/inner_records_pure.wasm inner_records/artifacts/
cp ../../../target/wasm32-wasi/release/records_passing_effector.wasm records_passing/artifacts/
cp ../../../target/wasm32-wasi/release/records_passing_pure.wasm records_passing/artifacts/

View File

@ -1,6 +0,0 @@
modules_dir = "./artifacts/"
[[module]]
name = "inner_records_pure"
mem_pages_count = 1
logger_enabled = true

View File

@ -1,12 +1,16 @@
[package]
name = "inner-records-test"
name = "records-passing-test"
version = "0.1.0"
authors = ["Fluence Labs"]
edition = "2018"
publish = false
[[bin]]
name = "inner_records_pure"
name = "records_passing_effector"
path = "src/effector.rs"
[[bin]]
name = "records_passing_pure"
path = "src/pure.rs"
[dependencies]

View File

@ -0,0 +1,11 @@
modules_dir = "./artifacts/"
[[module]]
name = "records_passing_effector"
mem_pages_count = 1
logger_enabled = true
[[module]]
name = "records_passing_pure"
mem_pages_count = 1
logger_enabled = true

View File

@ -17,11 +17,13 @@
use fluence::fce;
#[fce]
#[derive(Clone, Debug, Default)]
pub struct TestRecord0 {
pub field_0: i32,
}
#[fce]
#[derive(Clone, Debug, Default)]
pub struct TestRecord1 {
pub field_0: i32,
pub field_1: String,
@ -30,6 +32,7 @@ pub struct TestRecord1 {
}
#[fce]
#[derive(Clone, Debug, Default)]
pub struct TestRecord2 {
pub test_record_0: TestRecord0,
pub test_record_1: TestRecord1,
@ -43,3 +46,10 @@ pub fn test_record(mut test_record: TestRecord2) -> TestRecord2 {
test_record
}
#[fce]
pub fn test_record_ref(test_record: &mut TestRecord2) -> TestRecord2 {
test_record.test_record_0 = TestRecord0 { field_0: 1 };
test_record.clone()
}

View File

@ -0,0 +1,84 @@
/*
* Copyright 2020 Fluence Labs Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#![allow(improper_ctypes)]
use fluence::fce;
#[fce]
#[derive(Clone, Debug, Default)]
pub struct TestRecord0 {
pub field_0: i32,
}
#[fce]
#[derive(Clone, Debug, Default)]
pub struct TestRecord1 {
pub field_0: i32,
pub field_1: String,
pub field_2: Vec<u8>,
pub test_record_0: TestRecord0,
}
#[fce]
#[derive(Clone, Debug, Default)]
pub struct TestRecord2 {
pub test_record_0: TestRecord0,
pub test_record_1: TestRecord1,
}
fn main() {}
#[fce]
pub fn test_record(test_record: TestRecord2) -> TestRecord2 {
let mut test_record = unsafe { effector::test_record(test_record) };
test_record.test_record_1 = TestRecord1 {
field_0: 1,
field_1: "fluence".to_string(),
field_2: vec![0x13, 0x37],
test_record_0: TestRecord0 { field_0: 5 },
};
test_record
}
#[fce]
fn test_record_ref(test_record: &TestRecord2) -> TestRecord2 {
let mut test_record = unsafe { effector::test_record_ref(test_record) };
test_record.test_record_1 = TestRecord1 {
field_0: 1,
field_1: "fluence".to_string(),
field_2: vec![0x13, 0x37],
test_record_0: TestRecord0 { field_0: 5 },
};
test_record
}
mod effector {
use fluence::fce;
use super::TestRecord2;
#[fce]
#[link(wasm_import_module = "records_passing_effector")]
extern "C" {
pub fn test_record(test_record: TestRecord2) -> TestRecord2;
pub fn test_record_ref(test_record: &TestRecord2) -> TestRecord2;
}
}