mirror of
https://github.com/pezkuwichain/revive-differential-tests.git
synced 2026-04-28 09:38:00 +00:00
Use tracing for logging. (#29)
This commit updates how logging is done in the differential testing harness to use `tracing` instead of using the `log` crate. This allows us to be able to better associate logs with the cases being executed which makes it easier to debug and understand what the harness is doing.
This commit is contained in:
Generated
+21
-70
@@ -2071,29 +2071,6 @@ dependencies = [
|
||||
"syn 2.0.101",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "env_filter"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0"
|
||||
dependencies = [
|
||||
"log",
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "env_logger"
|
||||
version = "0.11.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
"env_filter",
|
||||
"jiff",
|
||||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "environmental"
|
||||
version = "1.1.4"
|
||||
@@ -2962,30 +2939,6 @@ version = "1.0.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
|
||||
|
||||
[[package]]
|
||||
name = "jiff"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a194df1107f33c79f4f93d02c80798520551949d59dfad22b6157048a88cca93"
|
||||
dependencies = [
|
||||
"jiff-static",
|
||||
"log",
|
||||
"portable-atomic",
|
||||
"portable-atomic-util",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jiff-static"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c6e1db7ed32c6c71b759497fae34bf7933636f75a251b9e736555da426f6442"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.101",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.77"
|
||||
@@ -3597,21 +3550,6 @@ dependencies = [
|
||||
"syn 2.0.101",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "portable-atomic"
|
||||
version = "1.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e"
|
||||
|
||||
[[package]]
|
||||
name = "portable-atomic-util"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507"
|
||||
dependencies = [
|
||||
"portable-atomic",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "potential_utf"
|
||||
version = "0.1.2"
|
||||
@@ -3997,13 +3935,13 @@ name = "revive-dt-compiler"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"log",
|
||||
"revive-common",
|
||||
"revive-dt-config",
|
||||
"revive-dt-solc-binaries",
|
||||
"revive-solc-json-interface",
|
||||
"semver 1.0.26",
|
||||
"serde_json",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4024,8 +3962,6 @@ dependencies = [
|
||||
"alloy",
|
||||
"anyhow",
|
||||
"clap",
|
||||
"env_logger",
|
||||
"log",
|
||||
"rayon",
|
||||
"revive-dt-compiler",
|
||||
"revive-dt-config",
|
||||
@@ -4036,6 +3972,8 @@ dependencies = [
|
||||
"revive-solc-json-interface",
|
||||
"serde_json",
|
||||
"temp-dir",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4046,10 +3984,10 @@ dependencies = [
|
||||
"alloy-primitives",
|
||||
"alloy-sol-types",
|
||||
"anyhow",
|
||||
"log",
|
||||
"semver 1.0.26",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4058,13 +3996,13 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"alloy",
|
||||
"anyhow",
|
||||
"log",
|
||||
"revive-dt-config",
|
||||
"revive-dt-node-interaction",
|
||||
"serde_json",
|
||||
"sp-core",
|
||||
"sp-runtime",
|
||||
"temp-dir",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4073,9 +4011,9 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"alloy",
|
||||
"anyhow",
|
||||
"log",
|
||||
"once_cell",
|
||||
"tokio",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4083,12 +4021,12 @@ name = "revive-dt-report"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"log",
|
||||
"revive-dt-config",
|
||||
"revive-dt-format",
|
||||
"revive-solc-json-interface",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4097,11 +4035,11 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"hex",
|
||||
"log",
|
||||
"reqwest",
|
||||
"semver 1.0.26",
|
||||
"serde",
|
||||
"sha2 0.10.9",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5569,6 +5507,16 @@ dependencies = [
|
||||
"tracing-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-serde"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "704b1aeb7be0d0a84fc9828cae51dab5970fee5088f83d1dd7ee6f6246fc6ff1"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"tracing-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-subscriber"
|
||||
version = "0.3.19"
|
||||
@@ -5579,6 +5527,8 @@ dependencies = [
|
||||
"nu-ansi-term",
|
||||
"once_cell",
|
||||
"regex",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sharded-slab",
|
||||
"smallvec",
|
||||
"thread_local",
|
||||
@@ -5586,6 +5536,7 @@ dependencies = [
|
||||
"tracing",
|
||||
"tracing-core",
|
||||
"tracing-log",
|
||||
"tracing-serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
+14
-7
@@ -4,9 +4,7 @@ members = ["crates/*"]
|
||||
|
||||
[workspace.package]
|
||||
version = "0.1.0"
|
||||
authors = [
|
||||
"Parity Technologies <admin@parity.io>",
|
||||
]
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
license = "MIT/Apache-2.0"
|
||||
edition = "2024"
|
||||
repository = "https://github.com/paritytech/revive-differential-testing.git"
|
||||
@@ -27,22 +25,31 @@ alloy-primitives = "1.2.1"
|
||||
alloy-sol-types = "1.2.1"
|
||||
anyhow = "1.0"
|
||||
clap = { version = "4", features = ["derive"] }
|
||||
env_logger = "0.11.8"
|
||||
hex = "0.4.3"
|
||||
reqwest = { version = "0.12.15", features = ["blocking", "json"] }
|
||||
log = "0.4.27"
|
||||
once_cell = "1.21"
|
||||
rayon = { version = "1.10" }
|
||||
semver = { version = "1.0", features = ["serde"] }
|
||||
serde = { version = "1.0", default-features = false, features = ["derive"] }
|
||||
serde_json = { version = "1.0", default-features = false, features = ["arbitrary_precision", "std"] }
|
||||
serde_json = { version = "1.0", default-features = false, features = [
|
||||
"arbitrary_precision",
|
||||
"std",
|
||||
] }
|
||||
sha2 = { version = "0.10.9" }
|
||||
sp-core = "36.1.0"
|
||||
sp-runtime = "41.1.0"
|
||||
temp-dir = { version = "0.1.16" }
|
||||
tempfile = "3.3"
|
||||
tokio = { version = "1", default-features = false, features = ["rt-multi-thread"] }
|
||||
tokio = { version = "1", default-features = false, features = [
|
||||
"rt-multi-thread",
|
||||
] }
|
||||
uuid = { version = "1.8", features = ["v4"] }
|
||||
tracing = "0.1.41"
|
||||
tracing-subscriber = { version = "0.3.19", default-features = false, features = [
|
||||
"fmt",
|
||||
"json",
|
||||
"env-filter",
|
||||
] }
|
||||
|
||||
# revive compiler
|
||||
revive-solc-json-interface = { git = "https://github.com/paritytech/revive", rev = "3389865af7c3ff6f29a586d82157e8bc573c1a8e" }
|
||||
|
||||
@@ -16,4 +16,4 @@ revive-dt-solc-binaries = { workspace = true }
|
||||
revive-common = { workspace = true }
|
||||
semver = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
log = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
|
||||
@@ -42,7 +42,7 @@ impl SolidityCompiler for Resolc {
|
||||
|
||||
if !output.status.success() {
|
||||
let message = String::from_utf8_lossy(&stderr);
|
||||
log::error!(
|
||||
tracing::error!(
|
||||
"resolc failed exit={} stderr={} JSON-in={} ",
|
||||
output.status,
|
||||
&message,
|
||||
|
||||
@@ -34,7 +34,7 @@ impl SolidityCompiler for Solc {
|
||||
|
||||
if !output.status.success() {
|
||||
let message = String::from_utf8_lossy(&output.stderr);
|
||||
log::error!("solc failed exit={} stderr={}", output.status, &message);
|
||||
tracing::error!("solc failed exit={} stderr={}", output.status, &message);
|
||||
return Ok(CompilerOutput {
|
||||
input,
|
||||
output: Default::default(),
|
||||
|
||||
@@ -23,8 +23,8 @@ revive-dt-report = { workspace = true }
|
||||
alloy = { workspace = true }
|
||||
anyhow = { workspace = true }
|
||||
clap = { workspace = true }
|
||||
log = { workspace = true }
|
||||
env_logger = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
tracing-subscriber = { workspace = true }
|
||||
rayon = { workspace = true }
|
||||
revive-solc-json-interface = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
|
||||
@@ -19,6 +19,7 @@ use revive_dt_report::reporter::{CompilationTask, Report, Span};
|
||||
use revive_solc_json_interface::SolcStandardJsonOutput;
|
||||
use serde_json::Value;
|
||||
use std::collections::HashMap as StdHashMap;
|
||||
use tracing::Level;
|
||||
|
||||
use crate::Platform;
|
||||
|
||||
@@ -73,7 +74,7 @@ where
|
||||
.solc_optimizer(mode.solc_optimize());
|
||||
|
||||
for (file, _contract) in metadata.contract_sources()?.values() {
|
||||
log::debug!("contract source {}", file.display());
|
||||
tracing::debug!("contract source {}", file.display());
|
||||
compiler = compiler.with_source(file)?;
|
||||
}
|
||||
|
||||
@@ -96,11 +97,13 @@ where
|
||||
if let Some(contracts) = &last_output.contracts {
|
||||
for (file, contracts_map) in contracts {
|
||||
for contract_name in contracts_map.keys() {
|
||||
log::debug!("Compiled contract: {contract_name} from file: {file}");
|
||||
tracing::debug!(
|
||||
"Compiled contract: {contract_name} from file: {file}"
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log::warn!("Compiled contracts field is None");
|
||||
tracing::warn!("Compiled contracts field is None");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,7 +111,7 @@ where
|
||||
Ok(())
|
||||
}
|
||||
Err(error) => {
|
||||
log::error!("Failed to compile contract: {:?}", error.to_string());
|
||||
tracing::error!("Failed to compile contract: {:?}", error.to_string());
|
||||
task.error = Some(error.to_string());
|
||||
Err(error)
|
||||
}
|
||||
@@ -120,11 +123,11 @@ where
|
||||
input: &Input,
|
||||
node: &T::Blockchain,
|
||||
) -> anyhow::Result<(TransactionReceipt, GethTrace, DiffMode)> {
|
||||
log::trace!("Calling execute_input for input: {input:?}");
|
||||
tracing::trace!("Calling execute_input for input: {input:?}");
|
||||
|
||||
let nonce = node.fetch_add_nonce(input.caller)?;
|
||||
|
||||
log::debug!(
|
||||
tracing::debug!(
|
||||
"Nonce calculated on the execute contract, calculated nonce {}, for contract {}, having address {} on node: {}",
|
||||
&nonce,
|
||||
&input.instance,
|
||||
@@ -139,21 +142,21 @@ where
|
||||
&self.deployed_abis,
|
||||
) {
|
||||
Ok(tx) => {
|
||||
log::debug!("Legacy transaction data: {tx:#?}");
|
||||
tracing::debug!("Legacy transaction data: {tx:#?}");
|
||||
tx
|
||||
}
|
||||
Err(err) => {
|
||||
log::error!("Failed to construct legacy transaction: {err:?}");
|
||||
tracing::error!("Failed to construct legacy transaction: {err:?}");
|
||||
return Err(err);
|
||||
}
|
||||
};
|
||||
|
||||
log::trace!("Executing transaction for input: {input:?}");
|
||||
tracing::trace!("Executing transaction for input: {input:?}");
|
||||
|
||||
let receipt = match node.execute_transaction(tx) {
|
||||
Ok(receipt) => receipt,
|
||||
Err(err) => {
|
||||
log::error!(
|
||||
tracing::error!(
|
||||
"Failed to execute transaction when executing the contract: {}, {:?}",
|
||||
&input.instance,
|
||||
err
|
||||
@@ -162,14 +165,14 @@ where
|
||||
}
|
||||
};
|
||||
|
||||
log::trace!(
|
||||
tracing::trace!(
|
||||
"Transaction receipt for executed contract: {} - {:?}",
|
||||
&input.instance,
|
||||
receipt,
|
||||
);
|
||||
|
||||
let trace = node.trace_transaction(receipt.clone())?;
|
||||
log::trace!(
|
||||
tracing::trace!(
|
||||
"Trace result for contract: {} - {:?}",
|
||||
&input.instance,
|
||||
trace
|
||||
@@ -181,7 +184,7 @@ where
|
||||
}
|
||||
|
||||
pub fn deploy_contracts(&mut self, input: &Input, node: &T::Blockchain) -> anyhow::Result<()> {
|
||||
log::debug!(
|
||||
tracing::debug!(
|
||||
"Deploying contracts {}, having address {} on node: {}",
|
||||
&input.instance,
|
||||
&input.caller,
|
||||
@@ -189,7 +192,7 @@ where
|
||||
);
|
||||
for output in self.contracts.values() {
|
||||
let Some(contract_map) = &output.contracts else {
|
||||
log::debug!(
|
||||
tracing::debug!(
|
||||
"No contracts in output — skipping deployment for this input {}",
|
||||
&input.instance
|
||||
);
|
||||
@@ -198,7 +201,7 @@ where
|
||||
|
||||
for contracts in contract_map.values() {
|
||||
for (contract_name, contract) in contracts {
|
||||
log::debug!(
|
||||
tracing::debug!(
|
||||
"Contract name is: {:?} and the input name is: {:?}",
|
||||
&contract_name,
|
||||
&input.instance
|
||||
@@ -211,13 +214,13 @@ where
|
||||
.map(|b| b.object.clone());
|
||||
|
||||
let Some(code) = bytecode else {
|
||||
log::error!("no bytecode for contract {contract_name}");
|
||||
tracing::error!("no bytecode for contract {contract_name}");
|
||||
continue;
|
||||
};
|
||||
|
||||
let nonce = node.fetch_add_nonce(input.caller)?;
|
||||
|
||||
log::debug!(
|
||||
tracing::debug!(
|
||||
"Calculated nonce {}, for contract {}, having address {} on node: {}",
|
||||
&nonce,
|
||||
&input.instance,
|
||||
@@ -239,7 +242,7 @@ where
|
||||
let receipt = match node.execute_transaction(tx) {
|
||||
Ok(receipt) => receipt,
|
||||
Err(err) => {
|
||||
log::error!(
|
||||
tracing::error!(
|
||||
"Failed to execute transaction when deploying the contract on node : {:?}, {:?}, {:?}",
|
||||
std::any::type_name::<T>(),
|
||||
&contract_name,
|
||||
@@ -249,7 +252,7 @@ where
|
||||
}
|
||||
};
|
||||
|
||||
log::debug!(
|
||||
tracing::debug!(
|
||||
"Deployment tx sent for {} with nonce {} → tx hash: {:?}, on node: {:?}",
|
||||
contract_name,
|
||||
nonce,
|
||||
@@ -257,7 +260,7 @@ where
|
||||
std::any::type_name::<T>(),
|
||||
);
|
||||
|
||||
log::trace!(
|
||||
tracing::trace!(
|
||||
"Deployed transaction receipt for contract: {} - {:?}, on node: {:?}",
|
||||
&contract_name,
|
||||
receipt,
|
||||
@@ -265,7 +268,7 @@ where
|
||||
);
|
||||
|
||||
let Some(address) = receipt.contract_address else {
|
||||
log::error!(
|
||||
tracing::error!(
|
||||
"contract {contract_name} deployment did not return an address"
|
||||
);
|
||||
continue;
|
||||
@@ -273,7 +276,7 @@ where
|
||||
|
||||
self.deployed_contracts
|
||||
.insert(contract_name.clone(), address);
|
||||
log::trace!(
|
||||
tracing::trace!(
|
||||
"deployed contract `{}` at {:?}, on node {:?}",
|
||||
contract_name,
|
||||
address,
|
||||
@@ -281,7 +284,7 @@ where
|
||||
);
|
||||
|
||||
if let Some(Value::String(metadata_json_str)) = &contract.metadata {
|
||||
log::trace!(
|
||||
tracing::trace!(
|
||||
"metadata found for contract {contract_name}, {metadata_json_str}"
|
||||
);
|
||||
|
||||
@@ -292,7 +295,7 @@ where
|
||||
{
|
||||
match serde_json::from_value::<JsonAbi>(abi_value.clone()) {
|
||||
Ok(parsed_abi) => {
|
||||
log::trace!(
|
||||
tracing::trace!(
|
||||
"ABI found in metadata for contract {}",
|
||||
&contract_name
|
||||
);
|
||||
@@ -329,7 +332,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
log::debug!("Available contracts: {:?}", self.deployed_contracts.keys());
|
||||
tracing::debug!("Available contracts: {:?}", self.deployed_contracts.keys());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -362,28 +365,28 @@ where
|
||||
}
|
||||
|
||||
pub fn trace_diff_mode(label: &str, diff: &DiffMode) {
|
||||
log::trace!("{label} - PRE STATE:");
|
||||
tracing::trace!("{label} - PRE STATE:");
|
||||
for (addr, state) in &diff.pre {
|
||||
Self::trace_account_state(" [pre]", addr, state);
|
||||
}
|
||||
|
||||
log::trace!("{label} - POST STATE:");
|
||||
tracing::trace!("{label} - POST STATE:");
|
||||
for (addr, state) in &diff.post {
|
||||
Self::trace_account_state(" [post]", addr, state);
|
||||
}
|
||||
}
|
||||
|
||||
fn trace_account_state(prefix: &str, addr: &Address, state: &AccountState) {
|
||||
log::trace!("{prefix} 0x{addr:x}");
|
||||
tracing::trace!("{prefix} 0x{addr:x}");
|
||||
|
||||
if let Some(balance) = &state.balance {
|
||||
log::trace!("{prefix} balance: {balance}");
|
||||
tracing::trace!("{prefix} balance: {balance}");
|
||||
}
|
||||
if let Some(nonce) = &state.nonce {
|
||||
log::trace!("{prefix} nonce: {nonce}");
|
||||
tracing::trace!("{prefix} nonce: {nonce}");
|
||||
}
|
||||
if let Some(code) = &state.code {
|
||||
log::trace!("{prefix} code: {code}");
|
||||
tracing::trace!("{prefix} code: {code}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -395,61 +398,75 @@ where
|
||||
let mut follower_state = State::<F>::new(self.config, span);
|
||||
follower_state.build_contracts(&mode, self.metadata)?;
|
||||
|
||||
for case in &self.metadata.cases {
|
||||
for (case_idx, case) in self.metadata.cases.iter().enumerate() {
|
||||
// Creating a tracing span to know which case within the metadata is being executed
|
||||
// and which one we're getting logs for.
|
||||
let tracing_span = tracing::span!(
|
||||
Level::INFO,
|
||||
"Executing case",
|
||||
case = case.name,
|
||||
case_idx = case_idx
|
||||
);
|
||||
let _guard = tracing_span.enter();
|
||||
|
||||
for input in &case.inputs {
|
||||
log::debug!("Starting deploying contract {}", &input.instance);
|
||||
tracing::debug!("Starting deploying contract {}", &input.instance);
|
||||
if let Err(err) = leader_state.deploy_contracts(input, self.leader_node) {
|
||||
log::error!("Leader deployment failed for {}: {err}", input.instance);
|
||||
tracing::error!("Leader deployment failed for {}: {err}", input.instance);
|
||||
continue;
|
||||
} else {
|
||||
log::debug!("Leader deployment succeeded for {}", &input.instance);
|
||||
tracing::debug!("Leader deployment succeeded for {}", &input.instance);
|
||||
}
|
||||
|
||||
if let Err(err) = follower_state.deploy_contracts(input, self.follower_node) {
|
||||
log::error!("Follower deployment failed for {}: {err}", input.instance);
|
||||
tracing::error!("Follower deployment failed for {}: {err}", input.instance);
|
||||
continue;
|
||||
} else {
|
||||
log::debug!("Follower deployment succeeded for {}", &input.instance);
|
||||
tracing::debug!("Follower deployment succeeded for {}", &input.instance);
|
||||
}
|
||||
|
||||
log::debug!("Starting executing contract {}", &input.instance);
|
||||
tracing::debug!("Starting executing contract {}", &input.instance);
|
||||
|
||||
let (leader_receipt, _, leader_diff) = match leader_state
|
||||
.execute_input(input, self.leader_node)
|
||||
{
|
||||
Ok(result) => result,
|
||||
Err(err) => {
|
||||
log::error!("Leader execution failed for {}: {err}", input.instance);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
let (leader_receipt, _, leader_diff) =
|
||||
match leader_state.execute_input(input, self.leader_node) {
|
||||
Ok(result) => result,
|
||||
Err(err) => {
|
||||
tracing::error!(
|
||||
"Leader execution failed for {}: {err}",
|
||||
input.instance
|
||||
);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
let (follower_receipt, _, follower_diff) = match follower_state
|
||||
.execute_input(input, self.follower_node)
|
||||
{
|
||||
Ok(result) => result,
|
||||
Err(err) => {
|
||||
log::error!("Follower execution failed for {}: {err}", input.instance);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
let (follower_receipt, _, follower_diff) =
|
||||
match follower_state.execute_input(input, self.follower_node) {
|
||||
Ok(result) => result,
|
||||
Err(err) => {
|
||||
tracing::error!(
|
||||
"Follower execution failed for {}: {err}",
|
||||
input.instance
|
||||
);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
if leader_diff == follower_diff {
|
||||
log::debug!("State diffs match between leader and follower.");
|
||||
tracing::debug!("State diffs match between leader and follower.");
|
||||
} else {
|
||||
log::debug!("State diffs mismatch between leader and follower.");
|
||||
tracing::debug!("State diffs mismatch between leader and follower.");
|
||||
Self::trace_diff_mode("Leader", &leader_diff);
|
||||
Self::trace_diff_mode("Follower", &follower_diff);
|
||||
}
|
||||
|
||||
if leader_receipt.logs() != follower_receipt.logs() {
|
||||
log::debug!("Log/event mismatch between leader and follower.");
|
||||
log::trace!("Leader logs: {:?}", leader_receipt.logs());
|
||||
log::trace!("Follower logs: {:?}", follower_receipt.logs());
|
||||
tracing::debug!("Log/event mismatch between leader and follower.");
|
||||
tracing::trace!("Leader logs: {:?}", leader_receipt.logs());
|
||||
tracing::trace!("Follower logs: {:?}", follower_receipt.logs());
|
||||
}
|
||||
|
||||
if leader_receipt.status() != follower_receipt.status() {
|
||||
log::debug!(
|
||||
tracing::debug!(
|
||||
"Mismatch in status: leader = {}, follower = {}",
|
||||
leader_receipt.status(),
|
||||
follower_receipt.status()
|
||||
|
||||
+60
-30
@@ -8,10 +8,12 @@ use revive_dt_core::{
|
||||
Geth, Kitchensink, Platform,
|
||||
driver::{Driver, State},
|
||||
};
|
||||
use revive_dt_format::{corpus::Corpus, metadata::Metadata};
|
||||
use revive_dt_format::{corpus::Corpus, metadata::MetadataFile};
|
||||
use revive_dt_node::pool::NodePool;
|
||||
use revive_dt_report::reporter::{Report, Span};
|
||||
use temp_dir::TempDir;
|
||||
use tracing::Level;
|
||||
use tracing_subscriber::{EnvFilter, FmtSubscriber, fmt::format::FmtSpan};
|
||||
|
||||
static TEMP_DIR: LazyLock<TempDir> = LazyLock::new(|| TempDir::new().unwrap());
|
||||
|
||||
@@ -33,7 +35,14 @@ fn main() -> anyhow::Result<()> {
|
||||
}
|
||||
|
||||
fn init_cli() -> anyhow::Result<Arguments> {
|
||||
env_logger::init();
|
||||
let subscriber = FmtSubscriber::builder()
|
||||
.with_thread_ids(true)
|
||||
.with_thread_names(true)
|
||||
.with_env_filter(EnvFilter::from_default_env())
|
||||
.with_span_events(FmtSpan::ENTER | FmtSpan::CLOSE)
|
||||
.pretty()
|
||||
.finish();
|
||||
tracing::subscriber::set_global_default(subscriber)?;
|
||||
|
||||
let mut args = Arguments::parse();
|
||||
|
||||
@@ -51,7 +60,7 @@ fn init_cli() -> anyhow::Result<Arguments> {
|
||||
args.temp_dir = Some(&TEMP_DIR);
|
||||
}
|
||||
}
|
||||
log::info!("workdir: {}", args.directory().display());
|
||||
tracing::info!("workdir: {}", args.directory().display());
|
||||
|
||||
ThreadPoolBuilder::new()
|
||||
.num_threads(args.workers)
|
||||
@@ -60,21 +69,21 @@ fn init_cli() -> anyhow::Result<Arguments> {
|
||||
Ok(args)
|
||||
}
|
||||
|
||||
fn collect_corpora(args: &Arguments) -> anyhow::Result<HashMap<Corpus, Vec<Metadata>>> {
|
||||
fn collect_corpora(args: &Arguments) -> anyhow::Result<HashMap<Corpus, Vec<MetadataFile>>> {
|
||||
let mut corpora = HashMap::new();
|
||||
|
||||
for path in &args.corpus {
|
||||
let corpus = Corpus::try_from_path(path)?;
|
||||
log::info!("found corpus: {}", path.display());
|
||||
tracing::info!("found corpus: {}", path.display());
|
||||
let tests = corpus.enumerate_tests();
|
||||
log::info!("corpus '{}' contains {} tests", &corpus.name, tests.len());
|
||||
tracing::info!("corpus '{}' contains {} tests", &corpus.name, tests.len());
|
||||
corpora.insert(corpus, tests);
|
||||
}
|
||||
|
||||
Ok(corpora)
|
||||
}
|
||||
|
||||
fn run_driver<L, F>(args: &Arguments, tests: &[Metadata], span: Span) -> anyhow::Result<()>
|
||||
fn run_driver<L, F>(args: &Arguments, tests: &[MetadataFile], span: Span) -> anyhow::Result<()>
|
||||
where
|
||||
L: Platform,
|
||||
F: Platform,
|
||||
@@ -84,34 +93,50 @@ where
|
||||
let leader_nodes = NodePool::<L::Blockchain>::new(args)?;
|
||||
let follower_nodes = NodePool::<F::Blockchain>::new(args)?;
|
||||
|
||||
tests.par_iter().for_each(|metadata| {
|
||||
let mut driver = Driver::<L, F>::new(
|
||||
metadata,
|
||||
args,
|
||||
leader_nodes.round_robbin(),
|
||||
follower_nodes.round_robbin(),
|
||||
);
|
||||
tests.par_iter().for_each(
|
||||
|MetadataFile {
|
||||
content: metadata,
|
||||
path: metadata_file_path,
|
||||
}| {
|
||||
// Starting a new tracing span for this metadata file. This allows our logs to be clear
|
||||
// about which metadata file the logs belong to. We can add other information into this
|
||||
// as well to be able to associate the logs with the correct metadata file and case
|
||||
// that's being executed.
|
||||
let tracing_span = tracing::span!(
|
||||
Level::INFO,
|
||||
"Running driver",
|
||||
metadata_file_path = metadata_file_path.display().to_string(),
|
||||
);
|
||||
let _guard = tracing_span.enter();
|
||||
|
||||
match driver.execute(span) {
|
||||
Ok(_) => {
|
||||
log::info!(
|
||||
"metadata {} success",
|
||||
metadata.directory().as_ref().unwrap().display()
|
||||
);
|
||||
let mut driver = Driver::<L, F>::new(
|
||||
metadata,
|
||||
args,
|
||||
leader_nodes.round_robbin(),
|
||||
follower_nodes.round_robbin(),
|
||||
);
|
||||
|
||||
match driver.execute(span) {
|
||||
Ok(_) => {
|
||||
tracing::info!(
|
||||
"metadata {} success",
|
||||
metadata.directory().as_ref().unwrap().display()
|
||||
);
|
||||
}
|
||||
Err(error) => {
|
||||
tracing::warn!(
|
||||
"metadata {} failure: {error:?}",
|
||||
metadata.file_path.as_ref().unwrap().display()
|
||||
);
|
||||
}
|
||||
}
|
||||
Err(error) => {
|
||||
log::warn!(
|
||||
"metadata {} failure: {error:?}",
|
||||
metadata.file_path.as_ref().unwrap().display()
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_corpus(args: &Arguments, tests: &[Metadata], span: Span) -> anyhow::Result<()> {
|
||||
fn execute_corpus(args: &Arguments, tests: &[MetadataFile], span: Span) -> anyhow::Result<()> {
|
||||
match (&args.leader, &args.follower) {
|
||||
(TestingPlatform::Geth, TestingPlatform::Kitchensink) => {
|
||||
run_driver::<Geth, Kitchensink>(args, tests, span)?
|
||||
@@ -125,7 +150,12 @@ fn execute_corpus(args: &Arguments, tests: &[Metadata], span: Span) -> anyhow::R
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn compile_corpus(config: &Arguments, tests: &[Metadata], platform: &TestingPlatform, span: Span) {
|
||||
fn compile_corpus(
|
||||
config: &Arguments,
|
||||
tests: &[MetadataFile],
|
||||
platform: &TestingPlatform,
|
||||
span: Span,
|
||||
) {
|
||||
tests.par_iter().for_each(|metadata| {
|
||||
for mode in &metadata.solc_modes() {
|
||||
match platform {
|
||||
|
||||
@@ -13,7 +13,7 @@ alloy = { workspace = true }
|
||||
alloy-primitives = { workspace = true }
|
||||
alloy-sol-types = { workspace = true }
|
||||
anyhow = { workspace = true }
|
||||
log = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
semver = { workspace = true }
|
||||
serde = { workspace = true, features = [ "derive" ] }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
serde_json = { workspace = true }
|
||||
|
||||
@@ -5,7 +5,7 @@ use std::{
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::metadata::Metadata;
|
||||
use crate::metadata::MetadataFile;
|
||||
|
||||
#[derive(Clone, Debug, Default, Serialize, Deserialize, Eq, PartialEq, Hash)]
|
||||
pub struct Corpus {
|
||||
@@ -21,7 +21,7 @@ impl Corpus {
|
||||
}
|
||||
|
||||
/// Scan the corpus base directory and return all tests found.
|
||||
pub fn enumerate_tests(&self) -> Vec<Metadata> {
|
||||
pub fn enumerate_tests(&self) -> Vec<MetadataFile> {
|
||||
let mut tests = Vec::new();
|
||||
collect_metadata(&self.path, &mut tests);
|
||||
tests
|
||||
@@ -34,11 +34,11 @@ impl Corpus {
|
||||
/// Found tests are inserted into `tests`.
|
||||
///
|
||||
/// `path` is expected to be a directory.
|
||||
pub fn collect_metadata(path: &Path, tests: &mut Vec<Metadata>) {
|
||||
pub fn collect_metadata(path: &Path, tests: &mut Vec<MetadataFile>) {
|
||||
let dir_entry = match std::fs::read_dir(path) {
|
||||
Ok(dir_entry) => dir_entry,
|
||||
Err(error) => {
|
||||
log::error!("failed to read dir '{}': {error}", path.display());
|
||||
tracing::error!("failed to read dir '{}': {error}", path.display());
|
||||
return;
|
||||
}
|
||||
};
|
||||
@@ -47,7 +47,7 @@ pub fn collect_metadata(path: &Path, tests: &mut Vec<Metadata>) {
|
||||
let entry = match entry {
|
||||
Ok(entry) => entry,
|
||||
Err(error) => {
|
||||
log::error!("error reading dir entry: {error}");
|
||||
tracing::error!("error reading dir entry: {error}");
|
||||
continue;
|
||||
}
|
||||
};
|
||||
@@ -59,7 +59,7 @@ pub fn collect_metadata(path: &Path, tests: &mut Vec<Metadata>) {
|
||||
}
|
||||
|
||||
if path.is_file() {
|
||||
if let Some(metadata) = Metadata::try_from_file(&path) {
|
||||
if let Some(metadata) = MetadataFile::try_from_file(&path) {
|
||||
tests.push(metadata)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,7 +126,7 @@ impl Input {
|
||||
.get(&self.instance)
|
||||
.ok_or_else(|| anyhow::anyhow!("ABI for instance '{}' not found", &self.instance))?;
|
||||
|
||||
log::trace!("ABI found for instance: {}", &self.instance);
|
||||
tracing::trace!("ABI found for instance: {}", &self.instance);
|
||||
|
||||
// Find function by selector
|
||||
let function = abi
|
||||
@@ -140,7 +140,7 @@ impl Input {
|
||||
)
|
||||
})?;
|
||||
|
||||
log::trace!("Functions found for instance: {}", &self.instance);
|
||||
tracing::trace!("Functions found for instance: {}", &self.instance);
|
||||
|
||||
let calldata_args = match &self.calldata {
|
||||
Some(Calldata::Compound(args)) => args,
|
||||
@@ -155,7 +155,7 @@ impl Input {
|
||||
);
|
||||
}
|
||||
|
||||
log::trace!(
|
||||
tracing::trace!(
|
||||
"Starting encoding ABI's parameters for instance: {}",
|
||||
&self.instance
|
||||
);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use std::{
|
||||
collections::BTreeMap,
|
||||
fs::{File, read_to_string},
|
||||
ops::Deref,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
@@ -15,6 +16,29 @@ pub const METADATA_FILE_EXTENSION: &str = "json";
|
||||
pub const SOLIDITY_CASE_FILE_EXTENSION: &str = "sol";
|
||||
pub const SOLIDITY_CASE_COMMENT_MARKER: &str = "//!";
|
||||
|
||||
#[derive(Debug, Default, Deserialize, Clone, Eq, PartialEq)]
|
||||
pub struct MetadataFile {
|
||||
pub path: PathBuf,
|
||||
pub content: Metadata,
|
||||
}
|
||||
|
||||
impl MetadataFile {
|
||||
pub fn try_from_file(path: &Path) -> Option<Self> {
|
||||
Metadata::try_from_file(path).map(|metadata| Self {
|
||||
path: path.to_owned(),
|
||||
content: metadata,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for MetadataFile {
|
||||
type Target = Metadata;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.content
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Deserialize, Clone, Eq, PartialEq)]
|
||||
pub struct Metadata {
|
||||
pub cases: Vec<Case>,
|
||||
@@ -35,7 +59,7 @@ impl Metadata {
|
||||
.filter_map(|mode| match mode {
|
||||
Mode::Solidity(solc_mode) => Some(solc_mode),
|
||||
Mode::Unknown(mode) => {
|
||||
log::debug!("compiler: ignoring unknown mode '{mode}'");
|
||||
tracing::debug!("compiler: ignoring unknown mode '{mode}'");
|
||||
None
|
||||
}
|
||||
})
|
||||
@@ -90,7 +114,7 @@ impl Metadata {
|
||||
assert!(path.is_file(), "not a file: {}", path.display());
|
||||
|
||||
let Some(file_extension) = path.extension() else {
|
||||
log::debug!("skipping corpus file: {}", path.display());
|
||||
tracing::debug!("skipping corpus file: {}", path.display());
|
||||
return None;
|
||||
};
|
||||
|
||||
@@ -102,14 +126,14 @@ impl Metadata {
|
||||
return Self::try_from_solidity(path);
|
||||
}
|
||||
|
||||
log::debug!("ignoring invalid corpus file: {}", path.display());
|
||||
tracing::debug!("ignoring invalid corpus file: {}", path.display());
|
||||
None
|
||||
}
|
||||
|
||||
fn try_from_json(path: &Path) -> Option<Self> {
|
||||
let file = File::open(path)
|
||||
.inspect_err(|error| {
|
||||
log::error!(
|
||||
tracing::error!(
|
||||
"opening JSON test metadata file '{}' error: {error}",
|
||||
path.display()
|
||||
);
|
||||
@@ -122,7 +146,7 @@ impl Metadata {
|
||||
Some(metadata)
|
||||
}
|
||||
Err(error) => {
|
||||
log::error!(
|
||||
tracing::error!(
|
||||
"parsing JSON test metadata file '{}' error: {error}",
|
||||
path.display()
|
||||
);
|
||||
@@ -134,7 +158,7 @@ impl Metadata {
|
||||
fn try_from_solidity(path: &Path) -> Option<Self> {
|
||||
let spec = read_to_string(path)
|
||||
.inspect_err(|error| {
|
||||
log::error!(
|
||||
tracing::error!(
|
||||
"opening JSON test metadata file '{}' error: {error}",
|
||||
path.display()
|
||||
);
|
||||
@@ -163,7 +187,7 @@ impl Metadata {
|
||||
Some(metadata)
|
||||
}
|
||||
Err(error) => {
|
||||
log::error!(
|
||||
tracing::error!(
|
||||
"parsing Solidity test metadata file '{}' error: '{error}' from data: {spec}",
|
||||
path.display()
|
||||
);
|
||||
|
||||
@@ -11,6 +11,6 @@ rust-version.workspace = true
|
||||
[dependencies]
|
||||
alloy = { workspace = true }
|
||||
anyhow = { workspace = true }
|
||||
log = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
once_cell = { workspace = true }
|
||||
tokio = { workspace = true }
|
||||
|
||||
@@ -51,13 +51,13 @@ impl TokioRuntime {
|
||||
let nonce_task = spawn(interaction::<Nonce>(nonce_receiver));
|
||||
|
||||
if let Err(error) = transaction_task.await {
|
||||
log::error!("tokio transaction task failed: {error}");
|
||||
tracing::error!("tokio transaction task failed: {error}");
|
||||
}
|
||||
if let Err(error) = trace_task.await {
|
||||
log::error!("tokio trace transaction task failed: {error}");
|
||||
tracing::error!("tokio trace transaction task failed: {error}");
|
||||
}
|
||||
if let Err(error) = nonce_task.await {
|
||||
log::error!("tokio nonce task failed: {error}");
|
||||
tracing::error!("tokio nonce task failed: {error}");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -11,15 +11,15 @@ rust-version.workspace = true
|
||||
[dependencies]
|
||||
anyhow = { workspace = true }
|
||||
alloy = { workspace = true }
|
||||
log = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
|
||||
revive-dt-node-interaction = { workspace = true }
|
||||
revive-dt-config = { workspace = true }
|
||||
|
||||
serde_json = { workspace = true }
|
||||
|
||||
|
||||
sp-core = { workspace = true }
|
||||
sp-runtime = { workspace = true }
|
||||
|
||||
[dev-dependencies]
|
||||
temp-dir = { workspace = true }
|
||||
temp-dir = { workspace = true }
|
||||
|
||||
@@ -159,7 +159,7 @@ impl EthereumNode for Instance {
|
||||
let connection_string = self.connection_string();
|
||||
let wallet = self.wallet.clone();
|
||||
|
||||
log::debug!("Submitting transaction: {transaction:#?}");
|
||||
tracing::debug!("Submitting transaction: {transaction:#?}");
|
||||
|
||||
execute_transaction(Box::pin(async move {
|
||||
Ok(ProviderBuilder::new()
|
||||
|
||||
@@ -252,7 +252,7 @@ impl EthereumNode for KitchensinkNode {
|
||||
let url = self.rpc_url.clone();
|
||||
let wallet = self.wallet.clone();
|
||||
|
||||
log::debug!("Submitting transaction: {transaction:#?}");
|
||||
tracing::debug!("Submitting transaction: {transaction:#?}");
|
||||
|
||||
execute_transaction(Box::pin(async move {
|
||||
Ok(ProviderBuilder::new()
|
||||
|
||||
@@ -62,7 +62,7 @@ where
|
||||
|
||||
fn spawn_node<T: Node + Send>(args: &Arguments, genesis: String) -> anyhow::Result<T> {
|
||||
let mut node = T::new(args);
|
||||
log::info!("starting node: {}", node.connection_string());
|
||||
tracing::info!("starting node: {}", node.connection_string());
|
||||
node.spawn(genesis)?;
|
||||
Ok(node)
|
||||
}
|
||||
|
||||
@@ -12,8 +12,7 @@ revive-dt-config = { workspace = true }
|
||||
revive-dt-format = { workspace = true }
|
||||
|
||||
anyhow = { workspace = true }
|
||||
log = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
revive-solc-json-interface = { workspace = true }
|
||||
|
||||
|
||||
@@ -192,7 +192,7 @@ impl Report {
|
||||
let file = File::create(&path).context(path.display().to_string())?;
|
||||
serde_json::to_writer_pretty(file, &self)?;
|
||||
|
||||
log::info!("report written to: {}", path.display());
|
||||
tracing::info!("report written to: {}", path.display());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ rust-version.workspace = true
|
||||
[dependencies]
|
||||
anyhow = { workspace = true }
|
||||
hex = { workspace = true }
|
||||
log = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
reqwest = { workspace = true }
|
||||
semver = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
|
||||
@@ -25,7 +25,7 @@ pub(crate) fn get_or_download(
|
||||
|
||||
let mut cache = SOLC_CACHER.lock().unwrap();
|
||||
if cache.contains(&target_file) {
|
||||
log::debug!("using cached solc: {}", target_file.display());
|
||||
tracing::debug!("using cached solc: {}", target_file.display());
|
||||
return Ok(target_file);
|
||||
}
|
||||
|
||||
@@ -37,10 +37,10 @@ pub(crate) fn get_or_download(
|
||||
}
|
||||
|
||||
fn download_to_file(path: &Path, downloader: &GHDownloader) -> anyhow::Result<()> {
|
||||
log::info!("caching file: {}", path.display());
|
||||
tracing::info!("caching file: {}", path.display());
|
||||
|
||||
let Ok(file) = File::create_new(path) else {
|
||||
log::debug!("cache file already exists: {}", path.display());
|
||||
tracing::debug!("cache file already exists: {}", path.display());
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
|
||||
@@ -86,7 +86,7 @@ impl GHDownloader {
|
||||
/// Errors out if the download fails or the digest of the downloaded file
|
||||
/// mismatches the expected digest from the release [List].
|
||||
pub fn download(&self) -> anyhow::Result<Vec<u8>> {
|
||||
log::info!("downloading solc: {self:?}");
|
||||
tracing::info!("downloading solc: {self:?}");
|
||||
let expected_digest = List::download(self.list)?
|
||||
.builds
|
||||
.iter()
|
||||
|
||||
Reference in New Issue
Block a user