add tests for generated glue code

This commit is contained in:
vms 2021-04-06 13:14:10 +03:00
parent ea5baec462
commit a4fa69e527
43 changed files with 398 additions and 44 deletions

View File

@ -1,6 +1,6 @@
[package]
name = "fluence-sdk-macro"
version = "0.5.0" # remember to update html_root_url
version = "0.6.0" # remember to update html_root_url
edition = "2018"
description = "Definition of the `#[fce]` macro"
documentation = "https://docs.rs/fluence/fluence-sdk-macro"
@ -18,4 +18,4 @@ proc-macro = true
doctest = false
[dependencies]
fluence-sdk-wit = { path = "../wit", version = "=0.5.0" }
fluence-sdk-wit = { path = "../wit", version = "=0.6.0" }

View File

@ -1,6 +1,6 @@
[package]
name = "fluence-sdk-test-macro-impl"
version = "0.5.0" # remember to update html_root_url
version = "0.6.0" # remember to update html_root_url
edition = "2018"
description = "Implementation of the `#[fce_test]` macro"
repository = "https://github.com/fluencelabs/rust-sdk/crates/macro-test"

View File

@ -1,6 +1,6 @@
[package]
name = "fluence-sdk-test-macro"
version = "0.5.0" # remember to update html_root_url
version = "0.6.0" # remember to update html_root_url
edition = "2018"
description = "Definition of the `#[fce_test]` macro"
repository = "https://github.com/fluencelabs/rust-sdk/crates/macro-test"
@ -17,7 +17,7 @@ proc-macro = true
doctest = false
[dependencies]
fluence-sdk-test-macro-impl = { path = "../fce-test-macro-impl", version = "=0.5.0" }
fluence-sdk-test-macro-impl = { path = "../fce-test-macro-impl", version = "=0.6.0" }
quote = "1.0.9"
proc-macro2 = "1.0.24"

View File

@ -1,6 +1,6 @@
[package]
name = "fluence-sdk-main"
version = "0.5.0" # remember to update html_root_url
version = "0.6.0" # remember to update html_root_url
edition = "2018"
description = "Rust SDK for applications for the Fluence network"
documentation = "https://docs.rs/fluence/fluence-sdk-macro"
@ -19,7 +19,7 @@ crate-type = ["rlib"]
doctest = false
[dependencies]
fluence-sdk-macro = { path = "../fce-macro", version = "=0.5.0" }
fluence-sdk-macro = { path = "../fce-macro", version = "=0.6.0" }
log = { version = "0.4.8", features = ["std"] }
serde = "=1.0.118"

View File

@ -1,6 +1,6 @@
[package]
name = "fluence-sdk-wit"
version = "0.5.0" # remember to update html_root_url
version = "0.6.0" # remember to update html_root_url
edition = "2018"
description = "Webassembly interface-types generator"
documentation = "https://docs.rs/fluence/fluence-sdk-macro"
@ -18,5 +18,8 @@ quote = "1.0.9"
proc-macro2 = "1.0.24"
serde = { version = "=1.0.118", features = ["derive"] }
serde_json = "1.0.56"
syn = { version = '1.0.64', features = ['full'] }
syn = { version = '1.0.64', features = ['full', "extra-traits"] }
uuid = { version = "0.8.2", features = ["v4"] }
[dev-dependencies]
pretty_assertions = "0.7.1"

View File

@ -127,7 +127,7 @@ fn generate_epilog(ty: &Option<ParsedType>) -> proc_macro2::TokenStream {
quote! {
#vector_serializer
let result = #generated_serializer_ident(result);
let result = #generated_serializer_ident(&result);
fluence::internal::set_result_ptr(result.0 as _);
fluence::internal::set_result_size(result.1 as _);
}

View File

@ -21,7 +21,7 @@ use quote::quote;
pub(crate) fn generate_vector_serializer(
value_ty: &ParsedType,
vec_passing_style: PassingStyle,
_vec_passing_style: PassingStyle,
arg_name: &str,
) -> proc_macro2::TokenStream {
let values_serializer = match value_ty {
@ -96,7 +96,7 @@ pub(crate) fn generate_vector_serializer(
let mut result: Vec<u32> = Vec::with_capacity(2 * arg.len());
for value in arg {
let (ptr, size) = #serializer_ident(value);
let (ptr, size) = #serializer_ident(&value);
result.push(ptr as _);
result.push(size as _);
}
@ -121,7 +121,7 @@ pub(crate) fn generate_vector_serializer(
let arg = crate::new_ident!(arg_name);
quote! {
unsafe fn #arg(arg: #vec_passing_style Vec<#value_ty>) -> (u32, u32) {
unsafe fn #arg(arg: &Vec<#value_ty>) -> (u32, u32) {
#values_serializer
}
}

View File

@ -75,7 +75,7 @@ fn generate_serializer_fn(record: &fce_ast_types::AstRecordItem) -> proc_macro2:
#serializer
let raw_record_ptr = raw_record.as_ptr();
fluence::internal::add_object_to_release(Box::new(raw_record));
fluence::internal::add_object_to_release(Box::new(self));
raw_record_ptr as _
}

View File

@ -41,7 +41,6 @@ impl RecordSerializerGlueCodeGenerator for fce_ast_types::AstRecordItem {
quote! {
raw_record.push(#field_ident.as_ptr() as _);
raw_record.push(#field_ident.len() as _);
std::mem::forget(#field_ident);
}
}
ParsedType::Vector(ty, passing_style) => {
@ -61,7 +60,7 @@ impl RecordSerializerGlueCodeGenerator for fce_ast_types::AstRecordItem {
quote::quote! {
#vector_serializer
let #serialized_field_ident = unsafe { #generated_serializer_ident(#field_ident) };
let #serialized_field_ident = unsafe { #generated_serializer_ident(&#field_ident) };
raw_record.push(#serialized_field_ident.0 as _);
raw_record.push(#serialized_field_ident.1 as _);
}

View File

@ -0,0 +1,87 @@
pub fn all_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> {
unimplemented!()
}
#[cfg(target_arch = "wasm32")]
#[export_name = "all_types"]
#[no_mangle]
#[doc(hidden)]
#[allow(clippy::all)]
pub unsafe fn __fce_generated_wrapper_func_all_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: u32,
arg_11: u32,
arg_12: u32,
arg_13: u32
) {
let converted_arg_0 = arg_0 as _;
let converted_arg_1 = arg_1 as _;
let converted_arg_2 = arg_2 as _;
let converted_arg_3 = arg_3 as _;
let converted_arg_4 = arg_4 as _;
let converted_arg_5 = arg_5 as _;
let converted_arg_6 = arg_6 as _;
let converted_arg_7 = arg_7 as _;
let converted_arg_8 = arg_8 as _;
let converted_arg_9 = arg_9 as _;
let converted_arg_10 = String::from_raw_parts(arg_10 as _, arg_11 as _, arg_11 as _);
unsafe fn __fce_generated_vec_deserializer_12(offset: u32, size: u32) -> Vec<u8> {
let size = size / 8;
let mut arg: Vec<u64> = Vec::from_raw_parts(offset as _, size as _, size as _);
let mut result = Vec::with_capacity(arg.len());
for value in arg {
result.push(value as _);
}
result
}
let converted_arg_12 = __fce_generated_vec_deserializer_12(arg_12 as _, arg_13 as _);
let result = all_types(
converted_arg_0,
converted_arg_1,
converted_arg_2,
converted_arg_3,
converted_arg_4,
converted_arg_5,
converted_arg_6,
converted_arg_7,
converted_arg_8,
converted_arg_9,
converted_arg_10,
converted_arg_12
);
unsafe fn __fce_generated_vec_serializer(arg: &Vec<u8>) -> (u32, u32) {
(arg.as_ptr() as _, arg.len() as _)
}
let result = __fce_generated_vec_serializer(&result);
fluence::internal::set_result_ptr(result.0 as _);
fluence::internal::set_result_size(result.1 as _);
fluence::internal::add_object_to_release(Box::new(result));
}
#[cfg(target_arch = "wasm32")]
#[doc(hidden)]
#[allow(clippy::all)]
#[link_section = "__fce_generated_section__all_types"]
pub static __fce_generated_static_global_all_types: [u8; 633usize] = {
* b"{\"ast_type\":\"Function\",\"signature\":{\"name\":\"all_types\",\"arguments\":[{\"name\":\"arg_0\",\"ty\":{\"I8\":\"ByValue\"}},{\"name\":\"arg_1\",\"ty\":{\"I16\":\"ByValue\"}},{\"name\":\"arg_2\",\"ty\":{\"I32\":\"ByValue\"}},{\"name\":\"arg_3\",\"ty\":{\"I64\":\"ByValue\"}},{\"name\":\"arg_4\",\"ty\":{\"U8\":\"ByValue\"}},{\"name\":\"arg_5\",\"ty\":{\"U16\":\"ByValue\"}},{\"name\":\"arg_6\",\"ty\":{\"U32\":\"ByValue\"}},{\"name\":\"arg_7\",\"ty\":{\"U64\":\"ByValue\"}},{\"name\":\"arg_8\",\"ty\":{\"F32\":\"ByValue\"}},{\"name\":\"arg_9\",\"ty\":{\"F64\":\"ByValue\"}},{\"name\":\"arg_10\",\"ty\":{\"Utf8String\":\"ByValue\"}},{\"name\":\"arg_11\",\"ty\":{\"Vector\":[{\"U8\":\"ByValue\"},\"ByValue\"]}}],\"output_type\":{\"Vector\":[{\"U8\":\"ByValue\"},\"ByValue\"]}}}"
};

View File

@ -0,0 +1,16 @@
pub fn all_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> {
unimplemented!()
}

View File

@ -0,0 +1,150 @@
pub struct CallParameters {
/// Peer id of the AIR script initiator.
pub init_peer_id: String,
/// Id of the current service.
pub service_id: String,
/// Id of the service creator.
pub service_creator_peer_id: String,
/// Id of the host which run this service.
pub host_id: String,
/// Id of the particle which execution resulted a call this service.
pub particle_id: String,
/// Security tetraplets which described origin of the arguments.
pub tetraplets: Vec<Vec<SecurityTetraplet>>,
}
#[cfg(target_arch = "wasm32")]
#[doc(hidden)]
#[allow(clippy::all)]
impl CallParameters {
pub fn __fce_generated_serialize(self) -> *const u8 {
let mut raw_record: Vec<u64> = Vec::new();
raw_record.push(self.init_peer_id.as_ptr() as _);
raw_record.push(self.init_peer_id.len() as _);
raw_record.push(self.service_id.as_ptr() as _);
raw_record.push(self.service_id.len() as _);
raw_record.push(self.service_creator_peer_id.as_ptr() as _);
raw_record.push(self.service_creator_peer_id.len() as _);
raw_record.push(self.host_id.as_ptr() as _);
raw_record.push(self.host_id.len() as _);
raw_record.push(self.particle_id.as_ptr() as _);
raw_record.push(self.particle_id.len() as _);
unsafe fn __fce_generated_vec_serializer_tetraplets_5(
arg: &Vec<Vec<SecurityTetraplet>>
) -> (u32, u32) {
unsafe fn __fce_generated_vec_serializer_tetraplets_5_SecurityTetraplet(
arg: &Vec<SecurityTetraplet>
) -> (u32, u32) {
let mut result: Vec<u32> = Vec::with_capacity(arg.len());
for value in arg {
result.push(value.__fce_generated_serialize() as _);
}
(result.as_ptr() as _, (4 * result.len()) as _)
}
let mut result: Vec<u32> = Vec::with_capacity(2 * arg.len());
for value in arg {
let (ptr, size) =
__fce_generated_vec_serializer_tetraplets_5_SecurityTetraplet(&value);
result.push(ptr as _);
result.push(size as _);
}
(result.as_ptr() as _, (4 * result.len()) as _)
}
let serialized_arg_5 =
unsafe { __fce_generated_vec_serializer_tetraplets_5(&self.tetraplets) };
raw_record.push(serialized_arg_5.0 as _);
raw_record.push(serialized_arg_5.1 as _);
let raw_record_ptr = raw_record.as_ptr();
fluence::internal::add_object_to_release(Box::new(self));
raw_record_ptr as _
}
pub unsafe fn __fce_generated_deserialize(record_ptr: *const u8) -> Self {
let raw_record: Vec<u64> = Vec::from_raw_parts(record_ptr as _, 96usize, 96usize);
let field_0 = unsafe {
String::from_raw_parts(
raw_record[0usize] as _,
raw_record[1usize] as _,
raw_record[1usize] as _
)
};
let field_1 = unsafe {
String::from_raw_parts(
raw_record[2usize] as _,
raw_record[3usize] as _,
raw_record[3usize] as _
)
};
let field_2 = unsafe {
String::from_raw_parts(
raw_record[4usize] as _,
raw_record[5usize] as _,
raw_record[5usize] as _
)
};
let field_3 = unsafe {
String::from_raw_parts(
raw_record[6usize] as _,
raw_record[7usize] as _,
raw_record[7usize] as _
)
};
let field_4 = unsafe {
String::from_raw_parts(
raw_record[8usize] as _,
raw_record[9usize] as _,
raw_record[9usize] as _
)
};
unsafe fn __fce_generated_vec_deserializer_10(
offset: u32,
size: u32
) -> Vec<Vec<SecurityTetraplet>> {
let size = size / 8;
unsafe fn __fce_generated_vec_deserializer_10_SecurityTetraplet(
offset: u32,
size: u32
) -> Vec<SecurityTetraplet> {
let size = size / 8;
let mut arg: Vec<u64> = Vec::from_raw_parts(offset as _, size as _, size as _);
let mut result = Vec::with_capacity(arg.len());
for offset in arg {
let value = SecurityTetraplet::__fce_generated_deserialize(offset as _);
result.push(value);
}
result
}
let mut arg: Vec<u64> = Vec::from_raw_parts(offset as _, size as _, size as _);
let mut result = Vec::with_capacity(arg.len());
let mut arg = arg.into_iter();
while let Some(offset) = arg.next() {
let size = arg.next().unwrap();
let value = __fce_generated_vec_deserializer_10_SecurityTetraplet(
offset as _,
size as _
);
result.push(value);
}
result
}
let field_5 = unsafe {
__fce_generated_vec_deserializer_10(
raw_record[10usize] as _,
raw_record[11usize] as _
)
};
Self {
init_peer_id: field_0,
service_id: field_1,
service_creator_peer_id: field_2,
host_id: field_3,
particle_id: field_4,
tetraplets: field_5
}
}
}
#[cfg(target_arch = "wasm32")]
#[doc(hidden)]
#[allow(clippy::all)]
#[link_section = "__fce_generated_section__CallParameters"]
pub static __fce_generated_static_global_CallParameters: [u8; 445usize] = {
* b"{\"ast_type\":\"Record\",\"name\":\"CallParameters\",\"fields\":[{\"name\":\"init_peer_id\",\"ty\":{\"Utf8String\":\"ByValue\"}},{\"name\":\"service_id\",\"ty\":{\"Utf8String\":\"ByValue\"}},{\"name\":\"service_creator_peer_id\",\"ty\":{\"Utf8String\":\"ByValue\"}},{\"name\":\"host_id\",\"ty\":{\"Utf8String\":\"ByValue\"}},{\"name\":\"particle_id\",\"ty\":{\"Utf8String\":\"ByValue\"}},{\"name\":\"tetraplets\",\"ty\":{\"Vector\":[{\"Vector\":[{\"Record\":[\"SecurityTetraplet\",\"ByValue\"]},\"ByValue\"]},\"ByValue\"]}}]}"
};

View File

@ -0,0 +1,19 @@
pub struct CallParameters {
/// Peer id of the AIR script initiator.
pub init_peer_id: String,
/// Id of the current service.
pub service_id: String,
/// Id of the service creator.
pub service_creator_peer_id: String,
/// Id of the host which run this service.
pub host_id: String,
/// Id of the particle which execution resulted a call this service.
pub particle_id: String,
/// Security tetraplets which described origin of the arguments.
pub tetraplets: Vec<Vec<SecurityTetraplet>>,
}

View File

@ -0,0 +1,16 @@
mod utils;
use utils::test_fce_token_streams;
#[test]
fn test() {
test_fce_token_streams(
"tests/generation_tests/export_functions/basic_types/fce.rs",
"tests/generation_tests/export_functions/basic_types/expanded.rs",
);
test_fce_token_streams(
"tests/generation_tests/records/call_parameters/fce.rs",
"tests/generation_tests/records/call_parameters/expanded.rs",
);
}

64
crates/wit/tests/utils.rs Normal file
View File

@ -0,0 +1,64 @@
/*
* 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.
*/
use fluence_sdk_wit::fce;
use pretty_assertions::assert_eq;
use std::io::Read;
use std::path::Path;
pub fn test_fce_token_streams<FP, EP>(fce_path: FP, expanded_path: EP)
where
FP: AsRef<Path>,
EP: AsRef<Path>,
{
let fce_item = stream_from_file(fce_path);
let test_token_stream = quote::quote! { #fce_item };
let fce_token_streams = fce(test_token_stream)
.unwrap_or_else(|e| panic!("failed to apply the fce macro due {}", e));
let expanded_item = items_from_file(expanded_path);
let fce_item = to_syn_item(fce_token_streams);
assert_eq!(fce_item, expanded_item);
}
fn stream_from_file<P>(path: P) -> proc_macro2::TokenStream
where
P: AsRef<Path>,
{
let items = items_from_file(path);
quote::quote! { #(#items)* }
}
fn items_from_file<P>(path: P) -> Vec<syn::Item>
where
P: AsRef<Path>,
{
let mut file = std::fs::File::open(path).expect("Unable to open file");
let mut src = String::new();
file.read_to_string(&mut src).expect("Unable to read file");
let token_file = syn::parse_file(&src).expect("Unable to parse file");
token_file.items
}
fn to_syn_item(token_stream: proc_macro2::TokenStream) -> Vec<syn::Item> {
let file: syn::File = syn::parse2(token_stream).expect("token stream should be parsed");
file.items
}

View File

@ -1,6 +1,6 @@
[package]
name = "fluence-test"
version = "0.5.0" # remember to update html_root_url
version = "0.6.0" # remember to update html_root_url
description = "Fluence backend SDK for testing"
documentation = "https://docs.rs/fluence/"
repository = "https://github.com/fluencelabs/rust-sdk"
@ -19,7 +19,7 @@ path = "src/lib.rs"
doctest = false
[dependencies]
fluence-sdk-test-macro = { path = "../crates/fce-test-macro", version = "=0.5.0" }
fluence-sdk-test-macro = { path = "../crates/fce-test-macro", version = "=0.6.0" }
fluence-app-service = { version = "0.5.2", features = ["raw-module-api"] }
serde = { version = "1.0.118", features = ["derive"] }

View File

@ -1,6 +1,6 @@
[package]
name = "fluence"
version = "0.5.0" # remember to update html_root_url
version = "0.6.0" # remember to update html_root_url
description = "Fluence backend SDK for developing backend applications for the Fluence network"
documentation = "https://docs.rs/fluence/"
repository = "https://github.com/fluencelabs/rust-sdk"
@ -19,8 +19,8 @@ path = "src/lib.rs"
doctest = false
[dependencies]
fluence-sdk-macro = { path = "../crates/fce-macro", version = "=0.5.0" }
fluence-sdk-main = { path = "../crates/main", version = "=0.5.0" }
fluence-sdk-macro = { path = "../crates/fce-macro", version = "=0.6.0" }
fluence-sdk-main = { path = "../crates/main", version = "=0.6.0" }
serde = { version = "1.0.118", features = ["derive"]}

View File

@ -0,0 +1,23 @@
#[test]
fn test() {
let tests = trybuild::TestCases::new();
tests.compile_fail("tests/compilation_tests/export_functions/array_inner_refs.rs");
tests.pass("tests/compilation_tests/export_functions/arrays.rs");
tests.pass("tests/compilation_tests/export_functions/ref_arrays.rs");
tests.pass("tests/compilation_tests/export_functions/basic_types.rs");
tests.pass("tests/compilation_tests/export_functions/ref_basic_types.rs");
tests.compile_fail("tests/compilation_tests/export_functions/improper_types.rs");
tests.compile_fail("tests/compilation_tests/import_functions/arrays_out_inner_refs.rs");
tests.pass("tests/compilation_tests/import_functions/arrays.rs");
tests.pass("tests/compilation_tests/import_functions/ref_arrays.rs");
tests.pass("tests/compilation_tests/import_functions/basic_types.rs");
tests.pass("tests/compilation_tests/import_functions/ref_basic_types.rs");
tests.compile_fail("tests/compilation_tests/import_functions/improper_types.rs");
tests.pass("tests/compilation_tests/records/basic_structs.rs");
tests.pass("tests/compilation_tests/records/empty_struct.rs");
tests.compile_fail("tests/compilation_tests/records/struct_with_improper_types.rs");
tests.compile_fail("tests/compilation_tests/records/struct_with_private_fields.rs");
tests.compile_fail("tests/compilation_tests/records/unnamed_structs.rs");
}

View File

@ -1,23 +0,0 @@
#[test]
fn test() {
let tests = trybuild::TestCases::new();
tests.compile_fail("tests/export_functions/array_inner_refs.rs");
tests.pass("tests/export_functions/arrays.rs");
tests.pass("tests/export_functions/ref_arrays.rs");
tests.pass("tests/export_functions/basic_types.rs");
tests.pass("tests/export_functions/ref_basic_types.rs");
tests.compile_fail("tests/export_functions/improper_types.rs");
tests.compile_fail("tests/import_functions/arrays_out_inner_refs.rs");
tests.pass("tests/import_functions/arrays.rs");
tests.pass("tests/import_functions/ref_arrays.rs");
tests.pass("tests/import_functions/basic_types.rs");
tests.pass("tests/import_functions/ref_basic_types.rs");
tests.compile_fail("tests/import_functions/improper_types.rs");
tests.pass("tests/records/basic_structs.rs");
tests.pass("tests/records/empty_struct.rs");
tests.compile_fail("tests/records/struct_with_improper_types.rs");
tests.compile_fail("tests/records/struct_with_private_fields.rs");
tests.compile_fail("tests/records/unnamed_structs.rs");
}