Skip to content

Commit

Permalink
tests
Browse files Browse the repository at this point in the history
  • Loading branch information
vobradovich committed Dec 11, 2024
1 parent 41d4776 commit fe70c55
Show file tree
Hide file tree
Showing 15 changed files with 407 additions and 2 deletions.
21 changes: 21 additions & 0 deletions rs/macros/core/tests/gservice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -274,3 +274,24 @@ fn works_with_special_lifetimes_and_events() {

insta::assert_snapshot!(result);
}

#[test]
fn works_with_export() {
let input = quote! {
impl SomeService {
#[export(route = "DoSomething", unwrap_result)]
pub async fn do_this(&mut self, p1: u32, p2: String) -> Result<u32, String> {
p1
}

pub fn this(&self, p1: bool) -> bool {
p1
}
}
};

let result = gservice(TokenStream::new(), input).to_string();
let result = prettyplease::unparse(&syn::parse_str(&result).unwrap());

insta::assert_snapshot!(result);
}
193 changes: 193 additions & 0 deletions rs/macros/core/tests/snapshots/gservice__works_with_export.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
---
source: rs/macros/core/tests/gservice.rs
expression: result
---
impl SomeService {
#[export(route = "DoSomething", unwrap_result)]
pub async fn do_this(&mut self, p1: u32, p2: String) -> Result<u32, String> {
p1
}
pub fn this(&self, p1: bool) -> bool {
p1
}
}
pub struct SomeServiceExposure<T> {
message_id: sails_rs::MessageId,
route: &'static [u8],
#[cfg(not(target_arch = "wasm32"))]
inner: Box<T>,
#[cfg(not(target_arch = "wasm32"))]
inner_ptr: *const T,
#[cfg(target_arch = "wasm32")]
inner: T,
}
impl SomeServiceExposure<SomeService> {
pub async fn do_this(&mut self, p1: u32, p2: String) -> Result<u32, String> {
let exposure_scope = sails_rs::gstd::services::ExposureCallScope::new(self);
self.inner.do_this(p1, p2).await
}
pub fn this(&self, p1: bool) -> bool {
let exposure_scope = sails_rs::gstd::services::ExposureCallScope::new(self);
self.inner.this(p1)
}
pub async fn handle(&mut self, input: &[u8]) -> (Vec<u8>, u128) {
self.try_handle(input)
.await
.unwrap_or_else(|| {
{
let mut __input = input;
let input: String = sails_rs::Decode::decode(&mut __input)
.unwrap_or_else(|_| {
if input.len() <= 8 {
format!("0x{}", sails_rs::hex::encode(input))
} else {
format!(
"0x{}..{}", sails_rs::hex::encode(& input[..4]),
sails_rs::hex::encode(& input[input.len() - 4..])
)
}
});
panic!("Unknown request: {}", input)
}
})
}
pub async fn try_handle(&mut self, input: &[u8]) -> Option<(Vec<u8>, u128)> {
if input
.starts_with(
&[
44u8,
68u8,
111u8,
83u8,
111u8,
109u8,
101u8,
116u8,
104u8,
105u8,
110u8,
103u8,
],
)
{
let (output, value) = self.__do_this(&input[12usize..]).await;
static INVOCATION_ROUTE: [u8; 12usize] = [
44u8,
68u8,
111u8,
83u8,
111u8,
109u8,
101u8,
116u8,
104u8,
105u8,
110u8,
103u8,
];
return Some(([INVOCATION_ROUTE.as_ref(), &output].concat(), value));
}
if input.starts_with(&[16u8, 84u8, 104u8, 105u8, 115u8]) {
let (output, value) = self.__this(&input[5usize..]).await;
static INVOCATION_ROUTE: [u8; 5usize] = [16u8, 84u8, 104u8, 105u8, 115u8];
return Some(([INVOCATION_ROUTE.as_ref(), &output].concat(), value));
}
None
}
async fn __do_this(&mut self, mut input: &[u8]) -> (Vec<u8>, u128) {
let request: some_service_meta::__DoThisParams = sails_rs::Decode::decode(
&mut input,
)
.expect("Failed to decode request");
let result = self.do_this(request.p1, request.p2).await.unwrap();
let value = 0u128;
return (sails_rs::Encode::encode(&result), value);
}
async fn __this(&self, mut input: &[u8]) -> (Vec<u8>, u128) {
let request: some_service_meta::__ThisParams = sails_rs::Decode::decode(
&mut input,
)
.expect("Failed to decode request");
let result = self.this(request.p1);
let value = 0u128;
return (sails_rs::Encode::encode(&result), value);
}
}
impl sails_rs::gstd::services::Exposure for SomeServiceExposure<SomeService> {
fn message_id(&self) -> sails_rs::MessageId {
self.message_id
}
fn route(&self) -> &'static [u8] {
self.route
}
}
impl sails_rs::gstd::services::Service for SomeService {
type Exposure = SomeServiceExposure<SomeService>;
fn expose(
self,
message_id: sails_rs::MessageId,
route: &'static [u8],
) -> Self::Exposure {
#[cfg(not(target_arch = "wasm32"))]
let inner_box = Box::new(self);
#[cfg(not(target_arch = "wasm32"))]
let inner = inner_box.as_ref();
#[cfg(target_arch = "wasm32")]
let inner = &self;
Self::Exposure {
message_id,
route,
#[cfg(not(target_arch = "wasm32"))]
inner_ptr: inner_box.as_ref() as *const Self,
#[cfg(not(target_arch = "wasm32"))]
inner: inner_box,
#[cfg(target_arch = "wasm32")]
inner: self,
}
}
}
impl sails_rs::meta::ServiceMeta for SomeService {
fn commands() -> sails_rs::scale_info::MetaType {
sails_rs::scale_info::MetaType::new::<some_service_meta::CommandsMeta>()
}
fn queries() -> sails_rs::scale_info::MetaType {
sails_rs::scale_info::MetaType::new::<some_service_meta::QueriesMeta>()
}
fn events() -> sails_rs::scale_info::MetaType {
sails_rs::scale_info::MetaType::new::<some_service_meta::EventsMeta>()
}
fn base_services() -> impl Iterator<Item = sails_rs::meta::AnyServiceMeta> {
[].into_iter()
}
}
mod some_service_meta {
use super::*;
use sails_rs::{Decode, TypeInfo};
#[derive(Decode, TypeInfo)]
#[codec(crate = sails_rs::scale_codec)]
#[scale_info(crate = sails_rs::scale_info)]
pub struct __DoThisParams {
pub(super) p1: u32,
pub(super) p2: String,
}
#[derive(Decode, TypeInfo)]
#[codec(crate = sails_rs::scale_codec)]
#[scale_info(crate = sails_rs::scale_info)]
pub struct __ThisParams {
pub(super) p1: bool,
}
#[derive(TypeInfo)]
#[scale_info(crate = sails_rs::scale_info)]
pub enum CommandsMeta {
DoSomething(__DoThisParams, u32),
}
#[derive(TypeInfo)]
#[scale_info(crate = sails_rs::scale_info)]
pub enum QueriesMeta {
This(__ThisParams, bool),
}
#[derive(TypeInfo)]
#[scale_info(crate = sails_rs::scale_info)]
pub enum NoEvents {}
pub type EventsMeta = NoEvents;
}
20 changes: 20 additions & 0 deletions rs/macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,26 @@ pub fn route(args: TokenStream, impl_item_fn_tokens: TokenStream) -> TokenStream
sails_macros_core::groute(args.into(), impl_item_fn_tokens.into()).into()
}

/// Changes default route to methods exposed by Sails services
/// and specifies that the result should be unwrapped.
///
/// # Examples
///
/// ```rust
/// mod my_service {
/// use sails_rs::{export, service};
///
/// struct MyService;
///
/// #[service]
/// impl MyService {
/// #[export(route = "something", unwrap_result)]
/// pub fn do_something(&mut self) -> Result<u32, String> {
/// Ok(0)
/// }
/// }
/// }
/// ```
#[proc_macro_error]
#[proc_macro_attribute]
pub fn export(args: TokenStream, impl_item_fn_tokens: TokenStream) -> TokenStream {
Expand Down
46 changes: 46 additions & 0 deletions rs/macros/tests/gservice_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use sails_rs::{Decode, Encode, MessageId};

mod gservice_with_basics;
mod gservice_with_events;
mod gservice_with_export_unwrap_result;
mod gservice_with_extends;
mod gservice_with_extends_and_lifetimes;
mod gservice_with_lifecycles_and_generics;
Expand Down Expand Up @@ -369,3 +370,48 @@ async fn gservice_with_multiple_names() {
gservice_works!(gservice_with_multiple_names::MyOtherService);
gservice_works!(gservice_with_multiple_names::yet_another_service::MyService);
}

#[tokio::test]
async fn gservice_with_export_unwrap_result() {
use gservice_with_export_unwrap_result::MyDoThisParams;
use gservice_with_export_unwrap_result::MyService;

const DO_THIS: &str = "DoThis";

let input = [
DO_THIS.encode(),
MyDoThisParams {
p1: 42,
p2: "correct".into(),
}
.encode(),
]
.concat();
let (output, _value) = MyService
.expose(MessageId::from(123), &[1, 2, 3])
.handle(&input)
.await;
let mut output = output.as_slice();

let func_name = String::decode(&mut output).unwrap();
assert_eq!(func_name, DO_THIS);

let result = String::decode(&mut output).unwrap();
assert_eq!(result, "42: correct");

assert_eq!(output.len(), 0);
}

#[tokio::test]
#[should_panic(expected = "failed to parse `not a number`")]
async fn gservice_with_export_unwrap_result_panic() {
use gservice_with_export_unwrap_result::MyService;

const PARSE: &str = "Parse";

let input = (PARSE, "not a number").encode();
_ = MyService
.expose(MessageId::from(123), &[1, 2, 3])
.handle(&input)
.await;
}
28 changes: 28 additions & 0 deletions rs/macros/tests/gservice_with_export_unwrap_result/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
use sails_macros::{export, service};
use sails_rs::Encode;

pub(super) struct MyService;

#[service]
impl MyService {
#[export(unwrap_result)]
pub async fn do_this(&mut self, p1: u32, p2: String) -> Result<String, String> {
Ok(format!("{p1}: ") + &p2)
}

#[export(route = "Parse", unwrap_result)]
pub async fn parse_result(&mut self, s: String) -> Result<u32, String> {
let res = str::parse::<u32>(s.as_str()).map_err(|_| format!("failed to parse `{}`", s))?;
Ok(res)
}

pub fn this(&self, p1: bool) -> bool {
!p1
}
}

#[derive(Encode)]
pub(super) struct MyDoThisParams {
pub(super) p1: u32,
pub(super) p2: String,
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error: `route` attribute conflicts with one assigned to 'service1'
error: `export` or `route` attribute conflicts with one assigned to 'service1'
--> tests/ui/gprogram_fails_for_multiple_services_with_same_route.rs:14:7
|
14 | #[route("svc")]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
use sails_macros::program;

struct MyService;

struct MyProgram;

#[program]
impl MyProgram {
#[route("svc")]
pub fn service1(&self) -> MyService {
MyService
}

#[export(route = "svc")]
pub fn service2(&self) -> MyService {
MyService
}
}

#[tokio::main]
async fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
error: `export` or `route` attribute conflicts with one assigned to 'service1'
--> tests/ui/gprogram_fails_for_multiple_services_with_same_route_and_export.rs:14:14
|
14 | #[export(route = "svc")]
| ^^^^^
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
use sails_macros::{export, service};

struct MyService;

#[service]
impl MyService {
#[export(route = "this")]
#[route("this")]
pub fn this(&self, p1: bool) -> bool {
!p1
}
}

#[tokio::main]
async fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
error: multiple `export` or `route` attributes on the same impl are not allowed
--> tests/ui/gservice_fails_export_and_route_not_allowed_on_one_impl.rs:8:5
|
8 | / #[route("this")]
9 | | pub fn this(&self, p1: bool) -> bool {
10 | | !p1
11 | | }
| |_____^

error[E0599]: no method named `this` found for struct `Box<MyService>` in the current scope
--> tests/ui/gservice_fails_export_and_route_not_allowed_on_one_impl.rs:9:12
|
9 | pub fn this(&self, p1: bool) -> bool {
| ^^^^ method not found in `Box<MyService>`
Loading

0 comments on commit fe70c55

Please sign in to comment.