Skip to content

Commit

Permalink
feat(prover_cli): Add test for status, l1 and config commands. (#2263)
Browse files Browse the repository at this point in the history
Add tests for the CLI of the proover, for the commands `status l1`,
`status batch`, `and config`.

For now, due to how the configuration setup works, it's necessary to run
the tests sequentially. Eventually, the logic for handling environment
variables can be changed to allow running tests in parallel.

## Checklist

- [x] PR title corresponds to the body of PR (we generate changelog
entries from PRs).
- [x] Tests for the changes have been added / updated.
- [x] Documentation comments have been added / updated.
- [x] Code has been formatted via `zk fmt` and `zk lint`.
- [x] Spellcheck has been run via `zk spellcheck`.

---------

Co-authored-by: Joaquin Carletti <[email protected]>
Co-authored-by: Ivan Litteri <[email protected]>
Co-authored-by: Ivan Litteri <[email protected]>
Co-authored-by: ilitteri <[email protected]>
Co-authored-by: EmilLuta <[email protected]>
  • Loading branch information
6 people committed Aug 16, 2024
1 parent 8b4cbf4 commit 6a2e3b0
Show file tree
Hide file tree
Showing 17 changed files with 1,729 additions and 40 deletions.
29 changes: 29 additions & 0 deletions core/lib/db_connection/src/connection_pool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,14 @@ impl TestTemplate {
Ok(Self(db_url.parse()?))
}

pub fn prover_empty() -> anyhow::Result<Self> {
let db_url = env::var("TEST_DATABASE_PROVER_URL").context(
"TEST_DATABASE_PROVER_URL must be set. Normally, this is done by the 'zk' tool. \
Make sure that you are running the tests with 'zk test rust' command or equivalent.",
)?;
Ok(Self(db_url.parse()?))
}

/// Closes the connection pool, disallows connecting to the underlying db,
/// so that the db can be used as a template.
pub async fn freeze<DB: DbMarker>(pool: ConnectionPool<DB>) -> anyhow::Result<Self> {
Expand Down Expand Up @@ -291,6 +299,11 @@ impl<DB: DbMarker> ConnectionPool<DB> {
Self::constrained_test_pool(DEFAULT_CONNECTIONS).await
}

pub async fn prover_test_pool() -> ConnectionPool<DB> {
const DEFAULT_CONNECTIONS: u32 = 100; // Expected to be enough for any unit test.
Self::constrained_prover_test_pool(DEFAULT_CONNECTIONS).await
}

/// Same as [`Self::test_pool()`], but with a configurable number of connections. This is useful to test
/// behavior of components that rely on singleton / constrained pools in production.
pub async fn constrained_test_pool(connections: u32) -> ConnectionPool<DB> {
Expand All @@ -309,6 +322,22 @@ impl<DB: DbMarker> ConnectionPool<DB> {
pool
}

pub async fn constrained_prover_test_pool(connections: u32) -> ConnectionPool<DB> {
assert!(connections > 0, "Number of connections must be positive");
let mut builder = TestTemplate::prover_empty()
.expect("failed creating test template")
.create_db(connections)
.await
.expect("failed creating database for tests");
let mut pool = builder
.set_acquire_timeout(Some(Self::TEST_ACQUIRE_TIMEOUT))
.build()
.await
.expect("cannot build connection pool");
pool.traced_connections = Some(Arc::default());
pool
}

/// Initializes a builder for connection pools.
pub fn builder(database_url: SensitiveUrl, max_pool_size: u32) -> ConnectionPoolBuilder<DB> {
ConnectionPoolBuilder {
Expand Down
28 changes: 25 additions & 3 deletions infrastructure/zk/src/test/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,25 @@ import * as db from '../database';

export { integration };

export async function prover() {
export async function prover(options: string[]) {
await db.resetTest({ core: false, prover: true });
process.chdir(process.env.ZKSYNC_HOME! + '/prover');
await utils.spawn('cargo test --release --workspace --locked');

let result = await utils.exec('cargo install --list');
let test_runner = 'cargo nextest run';

if (!result.stdout.includes('cargo-nextest')) {
console.warn(
chalk.bold.red(
`cargo-nextest is missing, please run "cargo install cargo-nextest". Falling back to "cargo test".`
)
);
test_runner = 'cargo test';
}

let cmd = `${test_runner} --release --locked --${options.join(' ')}`;
console.log(`running prover unit tests with '${cmd}'`);
await utils.spawn(cmd);
}

export async function rust(options: string[]) {
Expand Down Expand Up @@ -38,7 +54,13 @@ export async function l1Contracts() {

export const command = new Command('test').description('run test suites').addCommand(integration.command);

command.command('prover').description('run unit-tests for the prover').action(prover);
command
.command('prover [command...]')
.allowUnknownOption()
.description('run unit-tests for the prover')
.action(async (args: string[]) => {
await prover(args);
});
command.command('l1-contracts').description('run unit-tests for the layer 1 smart contracts').action(l1Contracts);
command
.command('rust [command...]')
Expand Down
73 changes: 72 additions & 1 deletion prover/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion prover/crates/bin/prover_cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,14 @@ zksync_dal.workspace = true
zksync_utils.workspace = true
strum.workspace = true
colored.workspace = true
sqlx.workspace = true
circuit_definitions.workspace = true
serde_json.workspace = true
zkevm_test_harness = { workspace = true, optional = true, features = ["verbose_circuits"] }
chrono.workspace = true

[dev-dependencies]
assert_cmd = "2"

[features]
# enable verbose circuits, if you want to use debug_circuit command (as it is quite heavy dependency).
verbose_circuits = ["zkevm_test_harness"]
42 changes: 22 additions & 20 deletions prover/crates/bin/prover_cli/src/cli.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,37 @@
use clap::{command, Args, Parser, Subcommand};
use zksync_types::url::SensitiveUrl;

use crate::commands::{self, config, debug_proof, delete, get_file_info, requeue, restart, stats};
use crate::commands::{
config, debug_proof, delete, get_file_info, requeue, restart, stats, status::StatusCommand,
};

pub const VERSION_STRING: &str = env!("CARGO_PKG_VERSION");

#[derive(Parser)]
#[command(name = "prover-cli", version = VERSION_STRING, about, long_about = None)]
struct ProverCLI {
pub struct ProverCLI {
#[command(subcommand)]
command: ProverCommand,
#[clap(flatten)]
config: ProverCLIConfig,
}

impl ProverCLI {
pub async fn start(self) -> anyhow::Result<()> {
match self.command {
ProverCommand::FileInfo(args) => get_file_info::run(args).await?,
ProverCommand::Config(cfg) => config::run(cfg).await?,
ProverCommand::Delete(args) => delete::run(args, self.config).await?,
ProverCommand::Status(cmd) => cmd.run(self.config).await?,
ProverCommand::Requeue(args) => requeue::run(args, self.config).await?,
ProverCommand::Restart(args) => restart::run(args).await?,
ProverCommand::DebugProof(args) => debug_proof::run(args).await?,
ProverCommand::Stats(args) => stats::run(args, self.config).await?,
};
Ok(())
}
}

// Note: this is set via the `config` command. Values are taken from the file pointed
// by the env var `PLI__CONFIG` or from `$ZKSYNC_HOME/etc/pliconfig` if unset.
#[derive(Args)]
Expand All @@ -26,31 +44,15 @@ pub struct ProverCLIConfig {
}

#[derive(Subcommand)]
enum ProverCommand {
pub enum ProverCommand {
DebugProof(debug_proof::Args),
FileInfo(get_file_info::Args),
Config(ProverCLIConfig),
Delete(delete::Args),
#[command(subcommand)]
Status(commands::StatusCommand),
Status(StatusCommand),
Requeue(requeue::Args),
Restart(restart::Args),
#[command(about = "Displays L1 Batch proving stats for a given period")]
Stats(stats::Options),
}

pub async fn start() -> anyhow::Result<()> {
let ProverCLI { command, config } = ProverCLI::parse();
match command {
ProverCommand::FileInfo(args) => get_file_info::run(args).await?,
ProverCommand::Config(cfg) => config::run(cfg).await?,
ProverCommand::Delete(args) => delete::run(args, config).await?,
ProverCommand::Status(cmd) => cmd.run(config).await?,
ProverCommand::Requeue(args) => requeue::run(args, config).await?,
ProverCommand::Restart(args) => restart::run(args).await?,
ProverCommand::DebugProof(args) => debug_proof::run(args).await?,
ProverCommand::Stats(args) => stats::run(args, config).await?,
};

Ok(())
}
4 changes: 2 additions & 2 deletions prover/crates/bin/prover_cli/src/commands/debug_proof.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use clap::Args as ClapArgs;

#[derive(ClapArgs)]
pub(crate) struct Args {
pub struct Args {
/// File with the basic proof.
#[clap(short, long)]
file: String,
}

pub(crate) async fn run(_args: Args) -> anyhow::Result<()> {
pub async fn run(_args: Args) -> anyhow::Result<()> {
#[cfg(not(feature = "verbose_circuits"))]
anyhow::bail!("Please compile with verbose_circuits feature");
#[cfg(feature = "verbose_circuits")]
Expand Down
4 changes: 2 additions & 2 deletions prover/crates/bin/prover_cli/src/commands/delete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use zksync_types::L1BatchNumber;
use crate::cli::ProverCLIConfig;

#[derive(ClapArgs)]
pub(crate) struct Args {
pub struct Args {
/// Delete data from all batches
#[clap(
short,
Expand All @@ -22,7 +22,7 @@ pub(crate) struct Args {
batch: L1BatchNumber,
}

pub(crate) async fn run(args: Args, config: ProverCLIConfig) -> anyhow::Result<()> {
pub async fn run(args: Args, config: ProverCLIConfig) -> anyhow::Result<()> {
let confirmation = Input::<String>::with_theme(&ColorfulTheme::default())
.with_prompt("Are you sure you want to delete the data?")
.default("no".to_owned())
Expand Down
2 changes: 1 addition & 1 deletion prover/crates/bin/prover_cli/src/commands/get_file_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use zksync_prover_fri_types::{
use zksync_prover_interface::outputs::L1BatchProofForL1;

#[derive(ClapArgs)]
pub(crate) struct Args {
pub struct Args {
#[clap(short, long)]
file_path: String,
}
Expand Down
3 changes: 1 addition & 2 deletions prover/crates/bin/prover_cli/src/commands/mod.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
pub(crate) use status::StatusCommand;
pub(crate) mod config;
pub(crate) mod debug_proof;
pub(crate) mod delete;
pub(crate) mod get_file_info;
pub(crate) mod requeue;
pub(crate) mod restart;
pub(crate) mod stats;
pub(crate) mod status;
pub mod status;
4 changes: 2 additions & 2 deletions prover/crates/bin/prover_cli/src/commands/restart.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use zksync_prover_dal::{
use zksync_types::{basic_fri_types::AggregationRound, L1BatchNumber};

#[derive(ClapArgs)]
pub(crate) struct Args {
pub struct Args {
/// Batch number to restart
#[clap(
short,
Expand All @@ -22,7 +22,7 @@ pub(crate) struct Args {
prover_job: Option<u32>,
}

pub(crate) async fn run(args: Args) -> anyhow::Result<()> {
pub async fn run(args: Args) -> anyhow::Result<()> {
let config = DatabaseSecrets::from_env()?;
let prover_connection_pool = ConnectionPool::<Prover>::singleton(config.prover_url()?)
.build()
Expand Down
Loading

0 comments on commit 6a2e3b0

Please sign in to comment.