Skip to content

Commit

Permalink
refactor(blockifier): split FC to groups base on their tags
Browse files Browse the repository at this point in the history
  • Loading branch information
meship-starkware committed Dec 1, 2024
1 parent 6f268c8 commit 06c9560
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 23 deletions.
16 changes: 12 additions & 4 deletions crates/blockifier/src/test_utils/cairo_compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ pub fn starknet_compile(
cargo_nightly_arg: Option<String>,
base_compile_args: &mut Vec<String>,
) -> Vec<u8> {
prepare_cairo1_compiler_deps(git_tag_override);
verify_cairo1_compiler_deps(git_tag_override);

let cairo1_compiler_path = local_cairo1_compiler_repo_path();

Expand Down Expand Up @@ -204,10 +204,9 @@ fn verify_cairo0_compiler_deps() {
);
}

fn prepare_cairo1_compiler_deps(git_tag_override: Option<String>) {
let cairo_repo_path = local_cairo1_compiler_repo_path();
fn get_tag_and_repo_file_path(git_tag_override: Option<String>) -> (String, PathBuf) {
let tag = git_tag_override.unwrap_or(cairo1_compiler_tag());

let cairo_repo_path = local_cairo1_compiler_repo_path();
// Check if the path is a directory.
assert!(
cairo_repo_path.is_dir(),
Expand All @@ -216,13 +215,22 @@ fn prepare_cairo1_compiler_deps(git_tag_override: Option<String>) {
cairo_repo_path.to_string_lossy(),
);

(tag, cairo_repo_path)
}

pub fn prepare_group_tag_compiler_deps(git_tag_override: Option<String>) {
let (tag, cairo_repo_path) = get_tag_and_repo_file_path(git_tag_override);
// Checkout the required version in the compiler repo.
run_and_verify_output(Command::new("git").args([
"-C",
cairo_repo_path.to_str().unwrap(),
"checkout",
&tag,
]));
}

fn verify_cairo1_compiler_deps(git_tag_override: Option<String>) {
let (tag, cairo_repo_path) = get_tag_and_repo_file_path(git_tag_override);

// Verify that the checked out tag is as expected.
run_and_verify_output(Command::new("git").args([
Expand Down
17 changes: 16 additions & 1 deletion crates/blockifier/src/test_utils/contracts.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use std::collections::HashMap;

use cairo_lang_starknet_classes::casm_contract_class::CasmContractClass;
use itertools::Itertools;
use starknet_api::abi::abi_utils::selector_from_name;
use starknet_api::abi::constants::CONSTRUCTOR_ENTRY_POINT_NAME;
use starknet_api::contract_class::{ContractClass, EntryPointType};
Expand Down Expand Up @@ -86,6 +89,9 @@ const LEGACY_CONTRACT_RUST_TOOLCHAIN: &str = "2023-07-05";
const CAIRO_STEPS_TEST_CONTRACT_COMPILER_TAG: &str = "v2.7.0";
const CAIRO_STEPS_TEST_CONTRACT_RUST_TOOLCHAIN: &str = "2024-04-29";

pub type TagAndToolchain = (Option<String>, Option<String>);
pub type TagToContractsMapping = HashMap<TagAndToolchain, Vec<FeatureContract>>;

/// Enum representing all feature contracts.
/// The contracts that are implemented in both Cairo versions include a version field.
#[derive(Clone, Copy, Debug, EnumIter, Hash, PartialEq, Eq)]
Expand Down Expand Up @@ -212,7 +218,7 @@ impl FeatureContract {
/// Some contracts are designed to test behavior of code compiled with a
/// specific (old) compiler tag. To run the (old) compiler, older rust
/// version is required.
pub fn fixed_tag_and_rust_toolchain(&self) -> (Option<String>, Option<String>) {
pub fn fixed_tag_and_rust_toolchain(&self) -> TagAndToolchain {
match self {
Self::LegacyTestContract => (
Some(LEGACY_CONTRACT_COMPILER_TAG.into()),
Expand Down Expand Up @@ -427,4 +433,13 @@ impl FeatureContract {
// ERC20 is a special case - not in the feature_contracts directory.
Self::all_contracts().filter(|contract| !matches!(contract, Self::ERC20(_)))
}

pub fn cairo1_feature_contracts_by_tag() -> TagToContractsMapping {
// EnumIter iterates over all variants with Default::default() as the cairo
// version.
Self::all_feature_contracts()
.filter(|contract| contract.cairo_version() != CairoVersion::Cairo0)
.map(|contract| (contract.fixed_tag_and_rust_toolchain(), contract))
.into_group_map()
}
}
59 changes: 41 additions & 18 deletions crates/blockifier/tests/feature_contracts_compatibility_test.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::fs;

use blockifier::test_utils::cairo_compile::prepare_group_tag_compiler_deps;
use blockifier::test_utils::contracts::FeatureContract;
use blockifier::test_utils::CairoVersion;
use pretty_assertions::assert_eq;
Expand Down Expand Up @@ -36,29 +37,51 @@ const FIX_COMMAND: &str = "FIX_FEATURE_TEST=1 cargo test -p blockifier --test \
// `COMPILED_CONTRACTS_SUBDIR` which equals `starknet-compile-deprecated X.cairo --no_debug_info`.
fn verify_feature_contracts_compatibility(fix: bool, cairo_version: CairoVersion) {
// TODO(Dori, 1/10/2024): Parallelize this test.
for contract in FeatureContract::all_feature_contracts()
.filter(|contract| contract.cairo_version() == cairo_version)
{
// Compare output of cairo-file on file with existing compiled file.
let expected_compiled_output = contract.compile();
let existing_compiled_path = contract.get_compiled_path();

if fix {
fs::write(&existing_compiled_path, &expected_compiled_output).unwrap();
match cairo_version {
CairoVersion::Cairo0 => {
for contract in FeatureContract::all_feature_contracts()
.filter(|contract| contract.cairo_version() == cairo_version)
{
verify_feature_contracts_compatibility_logic(&contract, fix);
}
}
let existing_compiled_contents = fs::read_to_string(&existing_compiled_path)
.unwrap_or_else(|_| panic!("Cannot read {existing_compiled_path}."));

if String::from_utf8(expected_compiled_output).unwrap() != existing_compiled_contents {
panic!(
"{} does not compile to {existing_compiled_path}.\nRun `{FIX_COMMAND}` to fix the \
existing file according to locally installed `starknet-compile-deprecated`.\n",
contract.get_source_path()
);
_ => {
for (tag_and_tool_chain, feature_contracts) in
FeatureContract::cairo1_feature_contracts_by_tag()
{
prepare_group_tag_compiler_deps(tag_and_tool_chain.0.clone());
// TODO(Meshi 01/01/2025) Make this loop concurrent
for contract in feature_contracts
.into_iter()
.filter(|contract| contract.cairo_version() == cairo_version)
{
verify_feature_contracts_compatibility_logic(&contract, fix);
}
}
}
}
}

fn verify_feature_contracts_compatibility_logic(contract: &FeatureContract, fix: bool) {
// Compare output of cairo-file on file with existing compiled file.
let expected_compiled_output = contract.compile();
let existing_compiled_path = contract.get_compiled_path();

if fix {
fs::write(&existing_compiled_path, &expected_compiled_output).unwrap();
}
let existing_compiled_contents = fs::read_to_string(&existing_compiled_path)
.unwrap_or_else(|_| panic!("Cannot read {existing_compiled_path}."));

if String::from_utf8(expected_compiled_output).unwrap() != existing_compiled_contents {
panic!(
"{} does not compile to {existing_compiled_path}.\nRun `{FIX_COMMAND}` to fix the \
existing file according to locally installed `starknet-compile-deprecated`.\n",
contract.get_source_path()
);
}
}

/// Verifies that the feature contracts directory contains the expected contents, and returns a list
/// of pairs (source_path, base_filename, compiled_path) for each contract.
fn verify_and_get_files(cairo_version: CairoVersion) -> Vec<(String, String, String)> {
Expand Down

0 comments on commit 06c9560

Please sign in to comment.