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

feat(macros): add SetOptions { profile } command #1404

Merged
merged 7 commits into from
Jun 6, 2024
Merged
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
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"));
| ^^^^^^^^^^^^^^^
Loading