diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_type/src/lib.rs b/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_type/src/lib.rs index 0b3ce9c27..938d95796 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_type/src/lib.rs +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_type/src/lib.rs @@ -1,7 +1,7 @@ #![no_std] use soroban_sdk::{ - contractimpl, contracttype, vec, Address, Bytes, BytesN, Env, Map, Set, String, Symbol, Vec, - I256, U256, + contracterror, contractimpl, contracttype, vec, Address, Bytes, BytesN, Env, Map, RawVal, Set, + String, Symbol, Vec, I256, U256, }; pub struct Contract; @@ -43,12 +43,35 @@ pub enum ComplexEnum { Void, } +#[contracterror] +#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] +#[repr(u32)] +pub enum Error { + OhNo = 1, +} + #[contractimpl] impl Contract { pub fn hello(_env: Env, hello: Symbol) -> Symbol { hello } + pub fn void(_env: Env) { + // do nothing + } + + pub fn raw_val(_env: Env) -> RawVal { + RawVal::default() + } + + pub fn u32_fail_on_even(_env: Env, u32_: u32) -> Result { + if u32_ % 2 == 1 { + Ok(u32_) + } else { + Err(Error::OhNo) + } + } + pub fn u32_(_env: Env, u32_: u32) -> u32 { u32_ } diff --git a/cmd/crates/soroban-test/tests/it/custom_types.rs b/cmd/crates/soroban-test/tests/it/custom_types.rs index 80013d932..60185cb27 100644 --- a/cmd/crates/soroban-test/tests/it/custom_types.rs +++ b/cmd/crates/soroban-test/tests/it/custom_types.rs @@ -174,6 +174,44 @@ fn number_arg() { invoke_with_roundtrip("u32_", 42); } +#[test] +fn number_arg_return_ok() { + invoke(&TestEnv::default(), "u32_fail_on_even") + .arg("--u32_") + .arg("1") + .assert() + .success() + .stdout("1\n"); +} + +#[test] +fn number_arg_return_err() { + invoke(&TestEnv::default(), "u32_fail_on_even") + .arg("--u32_") + .arg("2") + .assert() + .success() + .stderr(predicates::str::contains("Status(ContractError(1))")); +} + +#[test] +fn void() { + invoke(&TestEnv::default(), "void") + .assert() + .success() + .stdout("\n") + .stderr(""); +} + +#[test] +fn raw_val() { + invoke(&TestEnv::default(), "raw_val") + .assert() + .success() + .stdout("null\n") + .stderr(""); +} + #[test] fn i32() { invoke_with_roundtrip("i32_", 42); diff --git a/cmd/soroban-cli/src/strval.rs b/cmd/soroban-cli/src/strval.rs index 573333c35..2162481a8 100644 --- a/cmd/soroban-cli/src/strval.rs +++ b/cmd/soroban-cli/src/strval.rs @@ -438,7 +438,8 @@ impl Spec { /// May panic pub fn xdr_to_json(&self, val: &ScVal, output: &ScType) -> Result { Ok(match (val, output) { - (ScVal::Map(None) | ScVal::Vec(None), ScType::Option(_)) => Value::Null, + (ScVal::Void, ScType::Val) + | (ScVal::Map(None) | ScVal::Vec(None), ScType::Option(_)) => Value::Null, (ScVal::Bool(_), ScType::Bool) | (ScVal::Void, ScType::Void) | (ScVal::String(_), ScType::String) @@ -650,6 +651,11 @@ impl Spec { (ScVal::Address(v), ScType::Address) => sc_address_to_json(v), + (ok_val, ScType::Result(result_type)) => { + let ScSpecTypeResult { ok_type, .. } = result_type.as_ref(); + self.xdr_to_json(ok_val, ok_type)? + } + (x, y) => return Err(Error::InvalidPair(x.clone(), y.clone())), }) }