From 5d1e9eee48445016784532877b159b7c9e19c3af Mon Sep 17 00:00:00 2001 From: Ikrk Date: Thu, 14 Sep 2023 16:12:45 +0200 Subject: [PATCH 1/2] =?UTF-8?q?=E2=9C=A8=20Support=20for=20dynamic=20templ?= =?UTF-8?q?ates.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added support for dynamic templates where special variable can be replaced programatically. Added deploy_by_name method to the test template. --- .../templates/trdelnik-tests/fuzz_target.rs | 2 ++ .../src/templates/trdelnik-tests/test.rs | 6 ++++-- crates/client/src/test_generator.rs | 20 ++++++++++++------- examples/escrow/trdelnik-tests/tests/test.rs | 3 ++- 4 files changed, 21 insertions(+), 10 deletions(-) diff --git a/crates/client/src/templates/trdelnik-tests/fuzz_target.rs b/crates/client/src/templates/trdelnik-tests/fuzz_target.rs index a95873c0..7b66c7e7 100644 --- a/crates/client/src/templates/trdelnik-tests/fuzz_target.rs +++ b/crates/client/src/templates/trdelnik-tests/fuzz_target.rs @@ -1,6 +1,8 @@ use assert_matches::*; use trdelnik_client::fuzzing::*; +const PROGRAM_NAME: &str = "###PROGRAM_NAME###"; + #[derive(Arbitrary)] pub struct FuzzData { param1: u8, diff --git a/crates/client/src/templates/trdelnik-tests/test.rs b/crates/client/src/templates/trdelnik-tests/test.rs index 37931717..30038124 100644 --- a/crates/client/src/templates/trdelnik-tests/test.rs +++ b/crates/client/src/templates/trdelnik-tests/test.rs @@ -1,7 +1,6 @@ use fehler::throws; -use program_client; +use program_client::*; use trdelnik_client::{anyhow::Result, *}; -// @todo: do not forget to import your program crate (also in the ../Cargo.toml) // @todo: create and deploy your fixture #[throws] @@ -41,5 +40,8 @@ impl Fixture { self.client .airdrop(self.client.payer().pubkey(), 5_000_000_000) .await?; + self.client + .deploy_by_name(&self.program.clone(), "###PROGRAM_NAME###") + .await?; } } diff --git a/crates/client/src/test_generator.rs b/crates/client/src/test_generator.rs index 5feed758..65859ca0 100644 --- a/crates/client/src/test_generator.rs +++ b/crates/client/src/test_generator.rs @@ -123,7 +123,14 @@ impl TestGenerator { env!("CARGO_MANIFEST_DIR"), "/src/templates/trdelnik-tests/test.rs" )); - self.create_file(&test_path, TESTS_FILE_NAME, test_content) + let program_libs = self.get_program_lib_names(root).await?; + let program_name = if let Some(name) = program_libs.first() { + name + } else { + throw!(Error::CannotParseCargoToml) + }; + let test_content = test_content.replace("###PROGRAM_NAME###", program_name); + self.create_file(&test_path, TESTS_FILE_NAME, &test_content) .await?; let cargo_toml_path = workspace_path.join(CARGO_TOML); @@ -151,7 +158,7 @@ impl TestGenerator { self.create_directory_all(&fuzzer_path, FUZZ_DIRECTORY) .await?; - let libs = self.get_libs(root).await?; + let libs = self.get_program_lib_names(root).await?; let fuzzer_test_path = fuzzer_path.join(FUZZ_TEST_FILE_NAME); let fuzz_test_content = include_str!(concat!( @@ -162,11 +169,11 @@ impl TestGenerator { let fuzz_test_content = if let Some(lib) = libs.first() { let use_entry = format!("use {}::entry;\n", lib); - let prog_name = format!("const PROGRAM_NAME: &str = \"{lib}\";\n"); let use_instructions = format!("use program_client::{}_instruction::*;\n", lib); - format!("{use_entry}{use_instructions}{prog_name}{fuzz_test_content}") + let template = format!("{use_entry}{use_instructions}{fuzz_test_content}"); + template.replace("###PROGRAM_NAME###", lib) } else { - fuzz_test_content + fuzz_test_content.replace("###PROGRAM_NAME###", "") }; self.create_file(&fuzzer_test_path, FUZZ_TEST_FILE_NAME, &fuzz_test_content) @@ -358,7 +365,7 @@ impl TestGenerator { } /// Scans `programs` directory and returns a list of names of libraries - async fn get_libs(&self, root: &Path) -> Result, Error> { + async fn get_program_lib_names(&self, root: &Path) -> Result, Error> { let programs = root.join("programs"); if !programs.exists() { println!("Programs folder does not exist."); @@ -372,7 +379,6 @@ impl TestGenerator { if file.path().is_dir() { let path = file.path().join(CARGO_TOML); if path.exists() { - // let dir = file_name.to_str().unwrap(); let content: Value = fs::read_to_string(&path).await?.parse()?; let name = content .get("lib") diff --git a/examples/escrow/trdelnik-tests/tests/test.rs b/examples/escrow/trdelnik-tests/tests/test.rs index 48790e0a..8a7cb352 100644 --- a/examples/escrow/trdelnik-tests/tests/test.rs +++ b/examples/escrow/trdelnik-tests/tests/test.rs @@ -1,6 +1,7 @@ use anchor_spl::token; use fehler::throws; -use program_client::escrow_instruction; +use program_client::*; +// use program_client::escrow_instruction; use trdelnik_client::{anyhow::Result, *}; #[throws] From 602c4ac3dfd7c035a9827c5277a8759c4b35cb15 Mon Sep 17 00:00:00 2001 From: Ikrk Date: Mon, 18 Sep 2023 10:10:47 +0200 Subject: [PATCH 2/2] =?UTF-8?q?=F0=9F=A5=85=20Consistent=20error=20handlin?= =?UTF-8?q?g=20during=20trdelnik=20and=20fuzz=20test=20templates=20generat?= =?UTF-8?q?ion.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/client/src/test_generator.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/crates/client/src/test_generator.rs b/crates/client/src/test_generator.rs index 65859ca0..82ef3b5f 100644 --- a/crates/client/src/test_generator.rs +++ b/crates/client/src/test_generator.rs @@ -32,6 +32,8 @@ pub enum Error { Commander(#[from] CommanderError), #[error("Cannot find the Anchor.toml file to locate the root folder")] BadWorkspace, + #[error("The Anchor project does not contain any programs")] + NoProgramsFound, } pub struct TestGenerator; @@ -127,7 +129,7 @@ impl TestGenerator { let program_name = if let Some(name) = program_libs.first() { name } else { - throw!(Error::CannotParseCargoToml) + throw!(Error::NoProgramsFound) }; let test_content = test_content.replace("###PROGRAM_NAME###", program_name); self.create_file(&test_path, TESTS_FILE_NAME, &test_content) @@ -173,7 +175,7 @@ impl TestGenerator { let template = format!("{use_entry}{use_instructions}{fuzz_test_content}"); template.replace("###PROGRAM_NAME###", lib) } else { - fuzz_test_content.replace("###PROGRAM_NAME###", "") + throw!(Error::NoProgramsFound) }; self.create_file(&fuzzer_test_path, FUZZ_TEST_FILE_NAME, &fuzz_test_content)