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

Init Template Option #124

Merged
merged 4 commits into from
Feb 23, 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
2 changes: 1 addition & 1 deletion crates/cli/src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ mod explorer;
pub use explorer::{explorer, ExplorerCommand};

mod init;
pub use init::init;
pub use init::{init, TestsType};

mod clean;
pub use clean::clean;
29 changes: 22 additions & 7 deletions crates/cli/src/command/build.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,27 @@
use anyhow::Error;
use anyhow::{bail, Error};
use fehler::throws;
use trdelnik_client::*;

use crate::_discover;

use super::fuzz::TRDELNIK_TOML;

#[throws]
pub async fn build(root: String) {
let commander = Commander::with_root(root);
commander.create_program_client_crate().await?;
commander.build_programs().await?;
commander.generate_program_client_deps().await?;
commander.generate_program_client_lib_rs(None).await?;
pub async fn build(root: Option<String>) {
// if the root is present from the command line we will use it
// if the root is not present we will look for the Cargo.toml file
// Trdelnik does not have to be already defined to actually create/build
// program client
let root = match root {
Some(r) => r,
_ => {
if let Some(r) = _discover(TRDELNIK_TOML)? {
r
} else {
bail!("It does not seem that Trdelnik is initialized because the Trdelnik.toml file was not found in any parent directory!");
}
}
};
let mut generator: TestGenerator = TestGenerator::new_with_root(root);
generator.build().await?;
}
39 changes: 9 additions & 30 deletions crates/cli/src/command/fuzz.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
use anyhow::{bail, Context, Error, Result};
use anyhow::{bail, Error};

use clap::Subcommand;
use fehler::throws;
use trdelnik_client::{Commander, TestGenerator};

use crate::_discover;

pub const TRDELNIK_TOML: &str = "Trdelnik.toml";

#[derive(Subcommand)]
#[allow(non_camel_case_types)]
pub enum FuzzCommand {
Expand Down Expand Up @@ -31,7 +35,7 @@ pub async fn fuzz(root: Option<String>, subcmd: FuzzCommand) {
let root = match root {
Some(r) => r,
_ => {
let root = _discover()?;
let root = _discover(TRDELNIK_TOML)?;
if let Some(r) = root {
r
} else {
Expand Down Expand Up @@ -61,35 +65,10 @@ pub async fn fuzz(root: Option<String>, subcmd: FuzzCommand) {
}

FuzzCommand::Add => {
let generator = TestGenerator::new();
// generate generator with root so that we do not need to again
// look for root within the generator
let mut generator = TestGenerator::new_with_root(root);
generator.add_new_fuzz_test().await?;
}
};
}

// Climbs each parent directory until we find Trdelnik.toml.
fn _discover() -> Result<Option<String>> {
let _cwd = std::env::current_dir()?;
let mut cwd_opt = Some(_cwd.as_path());

while let Some(cwd) = cwd_opt {
for f in std::fs::read_dir(cwd)
.with_context(|| format!("Error reading the directory with path: {}", cwd.display()))?
{
let p = f
.with_context(|| {
format!("Error reading the directory with path: {}", cwd.display())
})?
.path();
if let Some(filename) = p.file_name() {
if filename.to_str() == Some("Trdelnik.toml") {
return Ok(Some(cwd.to_string_lossy().to_string()));
}
}
}

cwd_opt = cwd.parent();
}

Ok(None)
}
38 changes: 34 additions & 4 deletions crates/cli/src/command/init.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,39 @@
use anyhow::Error;
use anyhow::{bail, Error};
use clap::ValueEnum;
use fehler::throws;
use trdelnik_client::TestGenerator;

use crate::_discover;

pub const ANCHOR_TOML: &str = "Anchor.toml";

#[derive(ValueEnum, Clone)]
pub enum TestsType {
Both,
Fuzz,
Poc,
}

#[throws]
pub async fn init(skip_fuzzer: bool) {
let generator = TestGenerator::new();
generator.generate(skip_fuzzer).await?;
pub async fn init(tests_type: TestsType) {
// look for Anchor.toml
let root = if let Some(r) = _discover(ANCHOR_TOML)? {
r
} else {
bail!("It does not seem that Anchor is initialized because the Anchor.toml file was not found in any parent directory!");
};

let mut generator: TestGenerator = TestGenerator::new_with_root(root);

match tests_type {
TestsType::Poc => {
generator.generate_poc().await?;
}
TestsType::Both => {
generator.generate_both().await?;
}
TestsType::Fuzz => {
generator.generate_fuzz().await?;
}
};
}
20 changes: 18 additions & 2 deletions crates/cli/src/command/test.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,25 @@
use anyhow::Error;
use anyhow::{bail, Error};
use fehler::throws;
use trdelnik_client::*;

use crate::_discover;

use super::fuzz::TRDELNIK_TOML;

#[throws]
pub async fn test(root: String) {
pub async fn test(root: Option<String>) {
// if the root is present from the command line we will use it
// if the root is not present we will look for the Trdelnik.toml file
let root = match root {
Some(r) => r,
_ => {
if let Some(r) = _discover(TRDELNIK_TOML)? {
r
} else {
bail!("It does not seem that Trdelnik is initialized because the Cargo.toml file was not found in any parent directory!");
}
}
};
let commander = Commander::with_root(root);
commander.run_tests().await?;
}
47 changes: 38 additions & 9 deletions crates/cli/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use anyhow::Error;
use anyhow::{Context, Result};
use clap::{Parser, Subcommand};
use command::TestsType;
use fehler::throws;

// subcommand functions to call and nested subcommands
Expand All @@ -19,11 +21,11 @@ struct Cli {

#[derive(Subcommand)]
enum Command {
/// Create a `program_client` crate
/// Create or update a `program_client` crate
Build {
/// Anchor project root
#[clap(short, long, default_value = "./")]
root: String,
#[clap(short, long)]
root: Option<String>,
},
/// Get information about a keypair
KeyPair {
Expand All @@ -33,8 +35,8 @@ enum Command {
/// Run program Integration tests
Test {
/// Anchor project root
#[clap(short, long, default_value = "./")]
root: String,
#[clap(short, long)]
root: Option<String>,
},
/// Run and debug Fuzz tests
Fuzz {
Expand All @@ -53,9 +55,9 @@ enum Command {
},
/// Initialize test environment
Init {
/// Flag to skip generating template for fuzzing and activating the fuzzing feature.
#[arg(short, long)]
skip_fuzzer: bool,
/// Specifies the types of tests for which the frameworks should be initialized.
#[clap(default_value = "both")]
tests_type: TestsType,
},
/// Removes target contents except for KeyPair and removes hfuzz_target folder
Clean,
Expand All @@ -72,7 +74,34 @@ pub async fn start() {
Command::Fuzz { root, subcmd } => command::fuzz(root, subcmd).await?,
Command::Localnet => command::localnet().await?,
Command::Explorer { subcmd } => command::explorer(subcmd).await?,
Command::Init { skip_fuzzer } => command::init(skip_fuzzer).await?,
Command::Init { tests_type } => command::init(tests_type).await?,
Command::Clean => command::clean().await?,
}
}

// Climbs each parent directory until we find target.
fn _discover(target: &str) -> Result<Option<String>> {
let _cwd = std::env::current_dir()?;
let mut cwd_opt = Some(_cwd.as_path());

while let Some(cwd) = cwd_opt {
for f in std::fs::read_dir(cwd)
.with_context(|| format!("Error reading the directory with path: {}", cwd.display()))?
{
let p = f
.with_context(|| {
format!("Error reading the directory with path: {}", cwd.display())
})?
.path();
if let Some(filename) = p.file_name() {
if filename.to_str() == Some(target) {
return Ok(Some(cwd.to_string_lossy().to_string()));
}
}
}

cwd_opt = cwd.parent();
}

Ok(None)
}
Loading
Loading