Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#1682: fix help tests #1734

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
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
2 changes: 1 addition & 1 deletion cmd/crates/soroban-test/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ impl TestEnv {
let cmd = self.cmd_with_config::<I, invoke::Cmd>(command_str, None);
self.run_cmd_with(cmd, source)
.await
.map(|r| r.into_result().unwrap())
.map(|tx| tx.into_result().unwrap())
}

/// A convenience method for using the invoke command.
Expand Down
9 changes: 8 additions & 1 deletion cmd/crates/soroban-test/tests/it/help.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
use soroban_cli::commands::contract::arg_parsing::Error::HelpMessage;
use soroban_cli::commands::contract::invoke::Error::ArgParsing;
use soroban_cli::commands::contract::{self, arg_parsing};
use soroban_test::TestEnv;

use crate::util::{invoke_custom as invoke, CUSTOM_TYPES, DEFAULT_CONTRACT_ID};

async fn invoke_custom(func: &str, args: &str) -> Result<String, contract::invoke::Error> {
let e = &TestEnv::default();
invoke(e, DEFAULT_CONTRACT_ID, func, args, &CUSTOM_TYPES.path()).await
let r = invoke(e, DEFAULT_CONTRACT_ID, func, args, &CUSTOM_TYPES.path()).await;
if let Err(ArgParsing(HelpMessage(e))) = r {
return Ok(e);
}
r
}

#[tokio::test]
Expand Down Expand Up @@ -35,6 +41,7 @@ async fn tuple_help() {
#[tokio::test]
async fn strukt_help() {
let output = invoke_custom("strukt", "--help").await.unwrap();
println!("{output}");
assert!(output.contains("--strukt '{ \"a\": 1, \"b\": true, \"c\": \"hello\" }'",));
assert!(output.contains("This is from the rust doc above the struct Test",));
}
Expand Down
9 changes: 3 additions & 6 deletions cmd/crates/soroban-test/tests/it/util.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
use std::path::Path;

use soroban_cli::{
commands::contract,
config::{locator::KeyType, secret::Secret},
};
use soroban_test::{TestEnv, Wasm, TEST_ACCOUNT};
use std::path::Path;

pub const CUSTOM_TYPES: &Wasm = &Wasm::Custom("test-wasms", "test_custom_types");

Expand Down Expand Up @@ -54,10 +53,8 @@ pub async fn invoke_custom(
let mut i: contract::invoke::Cmd =
sandbox.cmd_with_config(&["--id", id, "--", func, arg], None);
i.wasm = Some(wasm.to_path_buf());
sandbox
.run_cmd_with(i, TEST_ACCOUNT)
.await
.map(|r| r.into_result().unwrap())
let s = sandbox.run_cmd_with(i, TEST_ACCOUNT).await;
s.map(|tx| tx.into_result().unwrap())
}

pub const DEFAULT_CONTRACT_ID: &str = "CDR6QKTWZQYW6YUJ7UP7XXZRLWQPFRV6SWBLQS4ZQOSAF4BOUD77OO5Z";
Expand Down
51 changes: 31 additions & 20 deletions cmd/soroban-cli/src/commands/contract/arg_parsing.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
use std::collections::HashMap;
use std::convert::TryInto;
use std::ffi::OsString;
use std::fmt::Debug;
use std::path::PathBuf;

use clap::value_parser;
use ed25519_dalek::SigningKey;
use heck::ToKebabCase;

use crate::commands::contract::arg_parsing::Error::HelpMessage;
use crate::commands::txn_result::TxnResult;
use crate::config::{self};
use crate::xdr::{
self, Hash, InvokeContractArgs, ScAddress, ScSpecEntry, ScSpecFunctionV0, ScSpecTypeDef, ScVal,
ScVec,
};

use crate::commands::txn_result::TxnResult;
use crate::config::{self};
use clap::error::ErrorKind::DisplayHelp;
use clap::value_parser;
use ed25519_dalek::SigningKey;
use heck::ToKebabCase;
use soroban_spec_tools::Spec;
use std::collections::HashMap;
use std::convert::TryInto;
use std::ffi::OsString;
use std::fmt::Debug;
use std::path::PathBuf;

#[derive(thiserror::Error, Debug)]
pub enum Error {
Expand Down Expand Up @@ -43,14 +42,18 @@ pub enum Error {
MissingArgument(String),
#[error("")]
MissingFileArg(PathBuf),
#[error("")]
HelpMessage(String),
}

pub type HostFunctionParameters = (String, Spec, InvokeContractArgs, Vec<SigningKey>);

pub fn build_host_function_parameters(
contract_id: &stellar_strkey::Contract,
slop: &[OsString],
spec_entries: &[ScSpecEntry],
config: &config::Args,
) -> Result<(String, Spec, InvokeContractArgs, Vec<SigningKey>), Error> {
) -> Result<HostFunctionParameters, Error> {
let spec = Spec(Some(spec_entries.to_vec()));
let mut cmd = clap::Command::new(contract_id.to_string())
.no_binary_name(true)
Expand All @@ -63,12 +66,20 @@ pub fn build_host_function_parameters(
cmd.build();
let long_help = cmd.render_long_help();

// get_matches_from exits the process if `help`, `--help` or `-h`are passed in the slop
// see clap documentation for more info: https://github.com/clap-rs/clap/blob/v4.1.8/src/builder/command.rs#L631
let mut matches_ = cmd.get_matches_from(slop);
let Some((function, matches_)) = &matches_.remove_subcommand() else {
println!("{long_help}");
std::process::exit(1);
// try_get_matches_from returns an error if `help`, `--help` or `-h`are passed in the slop
// see clap documentation for more info: https://github.com/clap-rs/clap/blob/v4.1.8/src/builder/command.rs#L586
let maybe_matches = cmd.try_get_matches_from(slop);
let Some((function, matches_)) = (match maybe_matches {
Ok(mut matches) => &matches.remove_subcommand(),
Err(e) => {
// to not exit immediately (to be able to fetch help message in tests), check for an error
if e.kind() == DisplayHelp {
return Err(HelpMessage(e.to_string()));
}
e.exit();
}
}) else {
return Err(HelpMessage(format!("{long_help}")));
};

let func = spec.find_function(function)?;
Expand Down
66 changes: 35 additions & 31 deletions cmd/soroban-cli/src/commands/contract/deploy/wasm.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
use std::array::TryFromSliceError;
use std::ffi::OsString;
use std::fmt::Debug;
use std::num::ParseIntError;

use crate::xdr::{
AccountId, ContractExecutable, ContractIdPreimage, ContractIdPreimageFromAddress,
CreateContractArgs, CreateContractArgsV2, Error as XdrError, Hash, HostFunction,
Expand All @@ -13,9 +8,14 @@ use crate::xdr::{
use clap::{arg, command, Parser};
use rand::Rng;
use regex::Regex;

use soroban_spec_tools::contract as contract_spec;
use std::array::TryFromSliceError;
use std::ffi::OsString;
use std::fmt::Debug;
use std::num::ParseIntError;

use crate::commands::contract::arg_parsing::Error::HelpMessage;
use crate::commands::contract::deploy::wasm::Error::ArgParse;
use crate::{
assembled::simulate_and_assemble_transaction,
commands::{
Expand Down Expand Up @@ -128,26 +128,32 @@ pub enum Error {

impl Cmd {
pub async fn run(&self, global_args: &global::Args) -> Result<(), Error> {
let res = self
.run_against_rpc_server(Some(global_args), None)
.await?
.to_envelope();
let res = self.run_against_rpc_server(Some(global_args), None).await;
match res {
TxnEnvelopeResult::TxnEnvelope(tx) => println!("{}", tx.to_xdr_base64(Limits::none())?),
TxnEnvelopeResult::Res(contract) => {
let network = self.config.get_network()?;

if let Some(alias) = self.alias.clone() {
self.config.locator.save_contract_id(
&network.network_passphrase,
&contract,
&alias,
)?;
Ok(res) => match res.to_envelope() {
TxnEnvelopeResult::TxnEnvelope(tx) => {
println!("{}", tx.to_xdr_base64(Limits::none())?);
}

println!("{contract}");
TxnEnvelopeResult::Res(contract) => {
let network = self.config.get_network()?;

if let Some(alias) = self.alias.clone() {
self.config.locator.save_contract_id(
&network.network_passphrase,
&contract,
&alias,
)?;
}

println!("{contract}");
}
},
Err(ArgParse(HelpMessage(help))) => {
println!("{help}");
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to do this at the top level, rather than inside the arg parsing, otherwise the exit codes will be incorrect when generating the help when no --help is passed. It's a small thing, but also I believe a small fix to keep passing the error as is up the chain, and at the top level doing as you do here.

Err(e) => return Err(e),
}

Ok(())
}
}
Expand Down Expand Up @@ -248,15 +254,13 @@ impl NetworkRunnable for Cmd {
} else {
let mut slop = vec![OsString::from(CONSTRUCTOR_FUNCTION_NAME)];
slop.extend_from_slice(&self.slop);
Some(
arg_parsing::build_host_function_parameters(
&stellar_strkey::Contract(contract_id.0),
&slop,
&entries,
config,
)?
.2,
)
let params = arg_parsing::build_host_function_parameters(
&stellar_strkey::Contract(contract_id.0),
&slop,
&entries,
config,
)?;
Some(params.2)
}
} else {
None
Expand Down
25 changes: 18 additions & 7 deletions cmd/soroban-cli/src/commands/contract/invoke.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ use std::str::FromStr;
use std::{fmt::Debug, fs, io};

use clap::{arg, command, Parser, ValueEnum};

use soroban_rpc::{Client, SimulateHostFunctionResult, SimulateTransactionResponse};
use soroban_spec::read::FromWasmError;

use super::super::events;
use super::arg_parsing;
use crate::commands::contract::arg_parsing::Error::HelpMessage;
use crate::commands::contract::invoke::Error::ArgParsing;
use crate::{
assembled::simulate_and_assemble_transaction,
commands::{
Expand Down Expand Up @@ -131,12 +132,20 @@ impl From<Infallible> for Error {

impl Cmd {
pub async fn run(&self, global_args: &global::Args) -> Result<(), Error> {
let res = self.invoke(global_args).await?.to_envelope();
let res = self.invoke(global_args).await;
match res {
TxnEnvelopeResult::TxnEnvelope(tx) => println!("{}", tx.to_xdr_base64(Limits::none())?),
TxnEnvelopeResult::Res(output) => {
println!("{output}");
Ok(res) => match res.to_envelope() {
TxnEnvelopeResult::TxnEnvelope(tx) => {
println!("{}", tx.to_xdr_base64(Limits::none())?);
}
TxnEnvelopeResult::Res(output) => {
println!("{output}");
}
},
Err(ArgParsing(HelpMessage(help))) => {
println!("{help}");
}
Comment on lines +145 to 147
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment about doing this at the top level.

Err(e) => return Err(e),
}
Ok(())
}
Expand Down Expand Up @@ -221,7 +230,7 @@ impl NetworkRunnable for Cmd {
let spec_entries = self.spec_entries()?;
if let Some(spec_entries) = &spec_entries {
// For testing wasm arg parsing
let _ = build_host_function_parameters(&contract_id, &self.slop, spec_entries, config)?;
build_host_function_parameters(&contract_id, &self.slop, spec_entries, config)?;
}
let client = network.rpc_client()?;

Expand All @@ -235,9 +244,11 @@ impl NetworkRunnable for Cmd {
.await
.map_err(Error::from)?;

let (function, spec, host_function_params, signers) =
let params =
build_host_function_parameters(&contract_id, &self.slop, &spec_entries, config)?;

let (function, spec, host_function_params, signers) = params;

let should_send_tx = self
.should_send_after_sim(host_function_params.clone(), client.clone())
.await?;
Expand Down
Loading