diff --git a/Cargo.lock b/Cargo.lock index 676f2bcf4..c45b0af54 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4563,8 +4563,12 @@ checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" name = "loc" version = "0.1.0" dependencies = [ + "clap 4.5.21", + "clap_complete", + "colored", "serde", "serde_json", + "spinoff", "tokei", ] diff --git a/Makefile b/Makefile index 3973f07ad..fa4138a42 100644 --- a/Makefile +++ b/Makefile @@ -87,16 +87,29 @@ HIVE_REVISION := df7d5103d4ddc772307f9947be4ad1f20ce03ed0 # the whole history by making it shallow since a given date (one day before our # target revision). HIVE_SHALLOW_SINCE := 2024-09-02 +QUIET ?= false hive: - git clone --single-branch --branch master --shallow-since=$(HIVE_SHALLOW_SINCE) https://github.com/lambdaclass/hive - cd hive && git checkout --detach $(HIVE_REVISION) && go build . + if [ "$(QUIET)" = "true" ]; then \ + git clone --quiet --single-branch --branch master --shallow-since=$(HIVE_SHALLOW_SINCE) https://github.com/lambdaclass/hive && \ + cd hive && git checkout --quiet --detach $(HIVE_REVISION) && go build .; \ + else \ + git clone --single-branch --branch master --shallow-since=$(HIVE_SHALLOW_SINCE) https://github.com/lambdaclass/hive && \ + cd hive && git checkout --detach $(HIVE_REVISION) && go build .; \ + fi setup-hive: hive ## ๐Ÿ Set up Hive testing framework if [ "$$(cd hive && git rev-parse HEAD)" != "$(HIVE_REVISION)" ]; then \ - cd hive && \ - git checkout master && \ - git fetch --shallow-since=$(HIVE_SHALLOW_SINCE) && \ - git checkout --detach $(HIVE_REVISION) && go build . ;\ + if [ "$(QUIET)" = "true" ]; then \ + cd hive && \ + git checkout --quiet master && \ + git fetch --quiet --shallow-since=$(HIVE_SHALLOW_SINCE) && \ + git checkout --quiet --detach $(HIVE_REVISION) && go build .;\ + else \ + cd hive && \ + git checkout master && \ + git fetch --shallow-since=$(HIVE_SHALLOW_SINCE) && \ + git checkout --detach $(HIVE_REVISION) && go build .;\ + fi \ fi TEST_PATTERN ?= / @@ -106,7 +119,10 @@ TEST_PATTERN ?= / # For example, to run the rpc-compat suites for eth_chainId & eth_blockNumber you should run: # `make run-hive SIMULATION=ethereum/rpc-compat TEST_PATTERN="/eth_chainId|eth_blockNumber"` run-hive: build-image setup-hive ## ๐Ÿงช Run Hive testing suite - cd hive && ./hive --sim $(SIMULATION) --client ethrex --sim.limit "$(TEST_PATTERN)" + cd hive && ./hive --client ethrex --sim $(SIMULATION) --sim.limit "$(TEST_PATTERN)" + +run-hive-all: build-image setup-hive ## ๐Ÿงช Run all Hive testing suites + cd hive && ./hive --client ethrex --sim $(SIMULATION) --sim.parallelism 4 run-hive-debug: build-image setup-hive ## ๐Ÿž Run Hive testing suite in debug mode cd hive && ./hive --sim $(SIMULATION) --client ethrex --sim.limit "$(TEST_PATTERN)" --docker.output @@ -116,3 +132,27 @@ clean-hive-logs: ## ๐Ÿงน Clean Hive logs loc: cargo run -p loc + +loc-stats: + if [ "$(QUIET)" = "true" ]; then \ + cargo run --quiet -p loc -- --summary;\ + else \ + cargo run -p loc -- --summary;\ + fi + + +hive-stats: + make hive QUIET=true + make setup-hive QUIET=true + rm -rf hive/workspace $(FILE_NAME)_logs + make run-hive-all SIMULATION=ethereum/rpc-compat || exit 0 + make run-hive-all SIMULATION=devp2p || exit 0 + make run-hive-all SIMULATION=ethereum/engine || exit 0 + make run-hive-all SIMULATION=ethereum/sync || exit 0 + +stats: + make loc-stats QUIET=true && echo + cd crates/vm/levm && make download-evm-ef-tests + cd crates/vm/levm && make run-evm-ef-tests QUIET=true && echo + make hive-stats + cargo run --quiet --release -p hive_report diff --git a/cmd/loc/Cargo.toml b/cmd/loc/Cargo.toml index 8c81c97b3..cec31864c 100644 --- a/cmd/loc/Cargo.toml +++ b/cmd/loc/Cargo.toml @@ -7,3 +7,7 @@ edition.workspace = true tokei = "12.1.2" serde = "1.0.215" serde_json = "1.0.133" +clap = { version = "4.3", features = ["derive"] } +clap_complete = "4.5.17" +colored = "2.1.0" +spinoff = "0.8.0" diff --git a/cmd/loc/src/main.rs b/cmd/loc/src/main.rs index 0d8c51839..d3094f6d1 100644 --- a/cmd/loc/src/main.rs +++ b/cmd/loc/src/main.rs @@ -1,18 +1,18 @@ -use serde::{Deserialize, Serialize}; +use clap::Parser; +use report::{shell_summary, LinesOfCodeReport, LinesOfCodeReporterOptions}; +use spinoff::{spinners::Dots, Color, Spinner}; use std::path::PathBuf; use tokei::{Config, LanguageType, Languages}; -const CARGO_MANIFEST_DIR: &str = std::env!("CARGO_MANIFEST_DIR"); +mod report; -#[derive(Default, Serialize, Deserialize, Clone, Copy)] -pub struct LinesOfCodeReport { - ethrex: usize, - ethrex_l1: usize, - ethrex_l2: usize, - levm: usize, -} +const CARGO_MANIFEST_DIR: &str = std::env!("CARGO_MANIFEST_DIR"); fn main() { + let opts = LinesOfCodeReporterOptions::parse(); + + let mut spinner = Spinner::new(Dots, "Counting lines of code...", Color::Cyan); + let ethrex = PathBuf::from(CARGO_MANIFEST_DIR).join("../../"); let levm = PathBuf::from(CARGO_MANIFEST_DIR).join("../../crates/vm"); let ethrex_l2 = PathBuf::from(CARGO_MANIFEST_DIR).join("../../crates/l2"); @@ -31,6 +31,10 @@ fn main() { languages.get_statistics(&[ethrex_l2], &["tests"], &config); let ethrex_l2_loc = &languages.get(&LanguageType::Rust).unwrap(); + spinner.success("Lines of code calculated!"); + + let mut spinner = Spinner::new(Dots, "Generating report...", Color::Cyan); + let new_report = LinesOfCodeReport { ethrex: ethrex_loc.code, ethrex_l1: ethrex_loc.code - ethrex_l2_loc.code - levm_loc.code, @@ -38,121 +42,31 @@ fn main() { levm: levm_loc.code, }; - std::fs::write( - "loc_report.json", - serde_json::to_string(&new_report).unwrap(), - ) - .expect("loc_report.json could not be written"); - - let old_report: LinesOfCodeReport = std::fs::read_to_string("loc_report.json.old") - .map(|s| serde_json::from_str(&s).unwrap()) - .unwrap_or(new_report); - - std::fs::write( - "loc_report_slack.txt", - slack_message(old_report, new_report), - ) - .unwrap(); - std::fs::write( - "loc_report_github.txt", - github_step_summary(old_report, new_report), - ) - .unwrap(); -} + if opts.summary { + spinner.success("Report generated!"); + println!("{}", shell_summary(new_report)); + } else { + std::fs::write( + "loc_report.json", + serde_json::to_string(&new_report).unwrap(), + ) + .expect("loc_report.json could not be written"); -fn slack_message(old_report: LinesOfCodeReport, new_report: LinesOfCodeReport) -> String { - let ethrex_l1_diff = new_report.ethrex_l1.abs_diff(old_report.ethrex_l1); - let ethrex_l2_diff = new_report.ethrex_l2.abs_diff(old_report.ethrex_l2); - let levm_diff = new_report.levm.abs_diff(old_report.levm); - let ethrex_diff_total = ethrex_l1_diff + ethrex_l2_diff + levm_diff; - - format!( - r#"{{ - "blocks": [ - {{ - "type": "header", - "text": {{ - "type": "plain_text", - "text": "Daily Lines of Code Report" - }} - }}, - {{ - "type": "divider" - }}, - {{ - "type": "section", - "text": {{ - "type": "mrkdwn", - "text": "*ethrex L1:* {} {}\n*ethrex L2:* {} {}\n*levm:* {} {}\n*ethrex (total):* {} {}" - }} - }} - ] -}}"#, - new_report.ethrex_l1, - match new_report.ethrex_l1.cmp(&old_report.ethrex_l1) { - std::cmp::Ordering::Greater => format!("(+{ethrex_l1_diff})"), - std::cmp::Ordering::Less => format!("(-{ethrex_l1_diff})"), - std::cmp::Ordering::Equal => "".to_string(), - }, - new_report.ethrex_l2, - match new_report.ethrex_l2.cmp(&old_report.ethrex_l2) { - std::cmp::Ordering::Greater => format!("(+{ethrex_l2_diff})"), - std::cmp::Ordering::Less => format!("(-{ethrex_l2_diff})"), - std::cmp::Ordering::Equal => "".to_string(), - }, - new_report.levm, - match new_report.levm.cmp(&old_report.levm) { - std::cmp::Ordering::Greater => format!("(+{levm_diff})"), - std::cmp::Ordering::Less => format!("(-{levm_diff})"), - std::cmp::Ordering::Equal => "".to_string(), - }, - new_report.ethrex, - match new_report.ethrex.cmp(&old_report.ethrex) { - std::cmp::Ordering::Greater => format!("(+{ethrex_diff_total})"), - std::cmp::Ordering::Less => format!("(-{ethrex_diff_total})"), - std::cmp::Ordering::Equal => "".to_string(), - }, - ) -} + let old_report: LinesOfCodeReport = std::fs::read_to_string("loc_report.json.old") + .map(|s| serde_json::from_str(&s).unwrap()) + .unwrap_or(new_report); + + std::fs::write( + "loc_report_slack.txt", + report::slack_message(old_report, new_report), + ) + .unwrap(); + std::fs::write( + "loc_report_github.txt", + report::github_step_summary(old_report, new_report), + ) + .unwrap(); -fn github_step_summary(old_report: LinesOfCodeReport, new_report: LinesOfCodeReport) -> String { - let ethrex_l1_diff = new_report.ethrex_l1.abs_diff(old_report.ethrex_l1); - let ethrex_l2_diff = new_report.ethrex_l2.abs_diff(old_report.ethrex_l2); - let levm_diff = new_report.levm.abs_diff(old_report.levm); - let ethrex_diff_total = ethrex_l1_diff + ethrex_l2_diff + levm_diff; - - format!( - r#"``` -ethrex loc summary -==================== -ethrex L1: {} {} -ethrex L2: {} {} -levm: {} ({}) -ethrex (total): {} {} -```"#, - new_report.ethrex_l1, - if new_report.ethrex > old_report.ethrex { - format!("(+{ethrex_l1_diff})") - } else { - format!("(-{ethrex_l1_diff})") - }, - new_report.ethrex_l2, - if new_report.ethrex_l2 > old_report.ethrex_l2 { - format!("(+{ethrex_l2_diff})") - } else { - format!("(-{ethrex_l2_diff})") - }, - new_report.levm, - if new_report.levm > old_report.levm { - format!("(+{levm_diff})") - } else { - format!("(-{levm_diff})") - }, - new_report.ethrex, - if new_report.ethrex > old_report.ethrex { - format!("(+{ethrex_diff_total})") - } else { - format!("(-{ethrex_diff_total})") - }, - ) + spinner.success("Report generated!"); + } } diff --git a/cmd/loc/src/report.rs b/cmd/loc/src/report.rs new file mode 100644 index 000000000..9e4470ee4 --- /dev/null +++ b/cmd/loc/src/report.rs @@ -0,0 +1,130 @@ +use clap::Parser; +use colored::Colorize; +use serde::{Deserialize, Serialize}; + +#[derive(Parser)] +pub struct LinesOfCodeReporterOptions { + #[arg(short, long, value_name = "SUMMARY", default_value = "false")] + pub summary: bool, +} + +#[derive(Default, Serialize, Deserialize, Clone, Copy)] +pub struct LinesOfCodeReport { + pub ethrex: usize, + pub ethrex_l1: usize, + pub ethrex_l2: usize, + pub levm: usize, +} + +pub fn slack_message(old_report: LinesOfCodeReport, new_report: LinesOfCodeReport) -> String { + let ethrex_l1_diff = new_report.ethrex_l1.abs_diff(old_report.ethrex_l1); + let ethrex_l2_diff = new_report.ethrex_l2.abs_diff(old_report.ethrex_l2); + let levm_diff = new_report.levm.abs_diff(old_report.levm); + let ethrex_diff_total = ethrex_l1_diff + ethrex_l2_diff + levm_diff; + + format!( + r#"{{ + "blocks": [ + {{ + "type": "header", + "text": {{ + "type": "plain_text", + "text": "Daily Lines of Code Report" + }} + }}, + {{ + "type": "divider" + }}, + {{ + "type": "section", + "text": {{ + "type": "mrkdwn", + "text": "*ethrex L1:* {} {}\n*ethrex L2:* {} {}\n*levm:* {} {}\n*ethrex (total):* {} {}" + }} + }} + ] +}}"#, + new_report.ethrex_l1, + match new_report.ethrex_l1.cmp(&old_report.ethrex_l1) { + std::cmp::Ordering::Greater => format!("(+{ethrex_l1_diff})"), + std::cmp::Ordering::Less => format!("(-{ethrex_l1_diff})"), + std::cmp::Ordering::Equal => "".to_string(), + }, + new_report.ethrex_l2, + match new_report.ethrex_l2.cmp(&old_report.ethrex_l2) { + std::cmp::Ordering::Greater => format!("(+{ethrex_l2_diff})"), + std::cmp::Ordering::Less => format!("(-{ethrex_l2_diff})"), + std::cmp::Ordering::Equal => "".to_string(), + }, + new_report.levm, + match new_report.levm.cmp(&old_report.levm) { + std::cmp::Ordering::Greater => format!("(+{levm_diff})"), + std::cmp::Ordering::Less => format!("(-{levm_diff})"), + std::cmp::Ordering::Equal => "".to_string(), + }, + new_report.ethrex, + match new_report.ethrex.cmp(&old_report.ethrex) { + std::cmp::Ordering::Greater => format!("(+{ethrex_diff_total})"), + std::cmp::Ordering::Less => format!("(-{ethrex_diff_total})"), + std::cmp::Ordering::Equal => "".to_string(), + }, + ) +} + +pub fn github_step_summary(old_report: LinesOfCodeReport, new_report: LinesOfCodeReport) -> String { + let ethrex_l1_diff = new_report.ethrex_l1.abs_diff(old_report.ethrex_l1); + let ethrex_l2_diff = new_report.ethrex_l2.abs_diff(old_report.ethrex_l2); + let levm_diff = new_report.levm.abs_diff(old_report.levm); + let ethrex_diff_total = ethrex_l1_diff + ethrex_l2_diff + levm_diff; + + format!( + r#"``` +ethrex loc summary +==================== +ethrex L1: {} {} +ethrex L2: {} {} +levm: {} ({}) +ethrex (total): {} {} +```"#, + new_report.ethrex_l1, + if new_report.ethrex > old_report.ethrex { + format!("(+{ethrex_l1_diff})") + } else { + format!("(-{ethrex_l1_diff})") + }, + new_report.ethrex_l2, + if new_report.ethrex_l2 > old_report.ethrex_l2 { + format!("(+{ethrex_l2_diff})") + } else { + format!("(-{ethrex_l2_diff})") + }, + new_report.levm, + if new_report.levm > old_report.levm { + format!("(+{levm_diff})") + } else { + format!("(-{levm_diff})") + }, + new_report.ethrex, + if new_report.ethrex > old_report.ethrex { + format!("(+{ethrex_diff_total})") + } else { + format!("(-{ethrex_diff_total})") + }, + ) +} + +pub fn shell_summary(new_report: LinesOfCodeReport) -> String { + format!( + "{}\n{}\n{} {}\n{} {}\n{} {}\n{} {}", + "Lines of Code".bold(), + "=============".bold(), + "ethrex L1:".bold(), + new_report.ethrex_l1, + "ethrex L2:".bold(), + new_report.ethrex_l2, + "levm:".bold(), + new_report.levm, + "ethrex (total):".bold(), + new_report.ethrex, + ) +} diff --git a/crates/vm/levm/Makefile b/crates/vm/levm/Makefile index 011ef9c9b..55234647e 100644 --- a/crates/vm/levm/Makefile +++ b/crates/vm/levm/Makefile @@ -15,7 +15,6 @@ fmt: ## ๐Ÿ“„ Runs rustfmt cargo fmt --all ###### EF Tests ###### - SPECTEST_VERSION := v14.1 SPECTEST_ARTIFACT := tests_$(SPECTEST_VERSION).tar.gz SPECTEST_VECTORS_DIR := ../../../cmd/ef_tests/levm/vectors @@ -32,8 +31,13 @@ $(SPECTEST_VECTORS_DIR): $(SPECTEST_ARTIFACT) download-evm-ef-tests: $(SPECTEST_VECTORS_DIR) ## ๐Ÿ“ฅ Download EF Tests run-evm-ef-tests: ## ๐Ÿƒโ€โ™‚๏ธ Run EF Tests - cd ../../../ && \ - time cargo test -p ef_tests-levm --test ef_tests_levm --release -- $(flags) + if [ "$(QUIET)" = "true" ]; then \ + cd ../../../ && \ + time cargo test --quiet -p ef_tests-levm --test ef_tests_levm --release -- $(flags) --summary;\ + else \ + cd ../../../ && \ + time cargo test -p ef_tests-levm --test ef_tests_levm --release -- $(flags);\ + fi run-evm-ef-tests-ci: ## ๐Ÿƒโ€โ™‚๏ธ Run EF Tests only with LEVM and without spinner, for CI. cd ../../../ && \