Skip to content

Commit

Permalink
feat(macros): add SetOptions { profile } command (#1404)
Browse files Browse the repository at this point in the history
  • Loading branch information
Br1ght0ne authored Jun 6, 2024
1 parent 4515fe4 commit 9f8d74f
Show file tree
Hide file tree
Showing 10 changed files with 121 additions and 10 deletions.
12 changes: 12 additions & 0 deletions docs/src/testing/the-setup-program-test-macro.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,18 @@ of `COMMAND(ARG...)...`

Available `COMMAND`s:

## Options

Example: `Options(profile="debug")`

Description: Sets options from `ARG`s to be used by other `COMMAND`s.

Available options:

- `profile`: sets the `cargo` build profile. Variants: `"release"` (default), `"debug"`

Cardinality: 0 or 1.

## Wallets

Example: `Wallets("a_wallet", "another_wallet"...)`
Expand Down
28 changes: 21 additions & 7 deletions packages/fuels-macros/src/setup_program_test/code_gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,23 @@ use quote::quote;
use syn::LitStr;

use crate::setup_program_test::parsing::{
AbigenCommand, DeployContractCommand, InitializeWalletCommand, LoadScriptCommand,
TestProgramCommands,
AbigenCommand, BuildProfile, DeployContractCommand, InitializeWalletCommand, LoadScriptCommand,
SetOptionsCommand, TestProgramCommands,
};

pub(crate) fn generate_setup_program_test_code(
commands: TestProgramCommands,
) -> syn::Result<TokenStream> {
let TestProgramCommands {
set_options,
initialize_wallets,
generate_bindings,
deploy_contract,
load_scripts,
} = commands;

let project_lookup = generate_project_lookup(&generate_bindings)?;
let SetOptionsCommand { profile } = set_options.unwrap_or_default();
let project_lookup = generate_project_lookup(&generate_bindings, profile)?;
let abigen_code = abigen_code(&project_lookup)?;
let wallet_code = wallet_initialization_code(initialize_wallets);
let deploy_code = contract_deploying_code(&deploy_contract, &project_lookup);
Expand All @@ -37,12 +39,15 @@ pub(crate) fn generate_setup_program_test_code(
})
}

fn generate_project_lookup(commands: &AbigenCommand) -> syn::Result<HashMap<String, Project>> {
fn generate_project_lookup(
commands: &AbigenCommand,
profile: BuildProfile,
) -> syn::Result<HashMap<String, Project>> {
let pairs = commands
.targets
.iter()
.map(|command| -> syn::Result<_> {
let project = Project::new(command.program_type, &command.project)?;
let project = Project::new(command.program_type, &command.project, profile.clone())?;
Ok((command.name.value(), project))
})
.collect::<Result<Vec<_>, _>>()?;
Expand Down Expand Up @@ -189,10 +194,11 @@ struct Project {
program_type: ProgramType,
path: PathBuf,
path_span: Span,
profile: BuildProfile,
}

impl Project {
fn new(program_type: ProgramType, dir: &LitStr) -> syn::Result<Self> {
fn new(program_type: ProgramType, dir: &LitStr, profile: BuildProfile) -> syn::Result<Self> {
let path = Path::new(&dir.value()).canonicalize().map_err(|_| {
syn::Error::new_spanned(
dir.clone(),
Expand All @@ -204,12 +210,20 @@ impl Project {
program_type,
path,
path_span: dir.span(),
profile,
})
}

fn compile_file_path(&self, suffix: &str, description: &str) -> String {
self.path
.join(["out/release/", self.project_name(), suffix].concat())
.join(
[
format!("out/{}/", &self.profile).as_str(),
self.project_name(),
suffix,
]
.concat(),
)
.to_str()
.unwrap_or_else(|| panic!("could not join path for {description}"))
.to_string()
Expand Down
4 changes: 2 additions & 2 deletions packages/fuels-macros/src/setup_program_test/parsing.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
pub(crate) use commands::{
AbigenCommand, DeployContractCommand, InitializeWalletCommand, LoadScriptCommand,
TestProgramCommands,
AbigenCommand, BuildProfile, DeployContractCommand, InitializeWalletCommand, LoadScriptCommand,
SetOptionsCommand, TestProgramCommands,
};

mod command_parser;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pub(crate) use deploy_contract::DeployContractCommand;
pub(crate) use initialize_wallet::InitializeWalletCommand;
use itertools::Itertools;
pub(crate) use load_script::LoadScriptCommand;
pub(crate) use set_options::{BuildProfile, SetOptionsCommand};
use syn::{
parse::{Parse, ParseStream},
Result,
Expand All @@ -20,18 +21,21 @@ mod abigen;
mod deploy_contract;
mod initialize_wallet;
mod load_script;
mod set_options;

// Contains the result of parsing the input to the `setup_program_test` macro.
// Contents represent the users wishes with regards to wallet initialization,
// bindings generation and contract deployment.
pub(crate) struct TestProgramCommands {
pub(crate) set_options: Option<SetOptionsCommand>,
pub(crate) initialize_wallets: Option<InitializeWalletCommand>,
pub(crate) generate_bindings: AbigenCommand,
pub(crate) deploy_contract: Vec<DeployContractCommand>,
pub(crate) load_scripts: Vec<LoadScriptCommand>,
}

command_parser!(
Options -> SetOptionsCommand,
Wallets -> InitializeWalletCommand,
Abigen -> AbigenCommand,
Deploy -> DeployContractCommand,
Expand All @@ -53,6 +57,7 @@ impl Parse for TestProgramCommands {
validate_zero_or_one_wallet_command_present(&parsed_commands.Wallets)?;

Ok(Self {
set_options: parsed_commands.Options.pop(),
initialize_wallets: parsed_commands.Wallets.pop(),
generate_bindings: abigen_command,
deploy_contract: parsed_commands.Deploy,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
use std::{convert::TryFrom, fmt, str::FromStr};

use syn::Error;

use crate::parse_utils::{Command, UniqueNameValues};

#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub enum BuildProfile {
Debug,
#[default]
Release,
}

impl FromStr for BuildProfile {
type Err = &'static str;

fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"debug" => Ok(Self::Debug),
"release" => Ok(Self::Release),
_ => Err(r#"invalid build profile option: must be "debug" or "release""#),
}
}
}

impl fmt::Display for BuildProfile {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{}",
match self {
BuildProfile::Debug => "debug",
BuildProfile::Release => "release",
}
)
}
}

#[derive(Debug, Clone, Default)]
pub struct SetOptionsCommand {
pub profile: BuildProfile,
}

impl TryFrom<Command> for SetOptionsCommand {
type Error = Error;

fn try_from(command: Command) -> Result<Self, Self::Error> {
let name_values = UniqueNameValues::new(command.contents)?;
name_values.validate_has_no_other_names(&["profile"])?;

let profile = name_values.get_as_lit_str("profile")?;
let profile = profile
.value()
.as_str()
.parse()
.map_err(|msg| Error::new(profile.span(), msg))?;

Ok(Self { profile })
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error: Unrecognized command. Expected one of: 'Wallets', 'Abigen', 'Deploy', 'LoadScript'
error: Unrecognized command. Expected one of: 'Options', 'Wallets', 'Abigen', 'Deploy', 'LoadScript'
--> tests/ui/setup_program_test/unknown_command.rs:10:5
|
10 | UnknownCommand()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
use fuels_macros::setup_program_test;

setup_program_test!(Options(unknown = "debug"));

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
error: attribute 'unknown' not recognized. Expected one of: 'profile'
--> tests/ui/setup_program_test/unknown_options_key.rs:3:29
|
3 | setup_program_test!(Options(unknown = "debug"));
| ^^^^^^^
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
use fuels_macros::setup_program_test;

setup_program_test!(Options(profile = "not_a_profile"));

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
error: invalid build profile option: must be "debug" or "release"
--> tests/ui/setup_program_test/unknown_options_value.rs:3:39
|
3 | setup_program_test!(Options(profile = "not_a_profile"));
| ^^^^^^^^^^^^^^^

0 comments on commit 9f8d74f

Please sign in to comment.