Skip to content

Commit

Permalink
tests: refactor and add new tests (starkware-libs#1405)
Browse files Browse the repository at this point in the history
* tests: refactor and add new tests

* tests: add tests for options/account

* fix: typo

* refactor(sozo): AccountOptions doesn't require `account_address` while specifying `private_key` to be consistent with `keystore`

* fix: formatting

* fix: remove unnecessary TODO

* fix: formatting
  • Loading branch information
lambda-0x authored Jan 10, 2024
1 parent 136a67a commit 18182a0
Show file tree
Hide file tree
Showing 4 changed files with 238 additions and 12 deletions.
1 change: 0 additions & 1 deletion crates/dojo-world/src/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,6 @@ impl Environment {
self.private_key.as_deref()
}

#[allow(dead_code)]
pub fn keystore_path(&self) -> Option<&str> {
self.keystore_path.as_deref()
}
Expand Down
224 changes: 221 additions & 3 deletions crates/sozo/src/commands/options/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,16 @@ use super::{

#[derive(Debug, Args)]
#[command(next_help_heading = "Account options")]
// INVARIANT:
// - For commandline: we can either specify `private_key` or `keystore_path` along with
// `keystore_password`. This is enforced by Clap.
// - For `Scarb.toml`: if both private_key and keystore are specified in `Scarb.toml` private_key
// will take priority
pub struct AccountOptions {
#[arg(long, env = DOJO_ACCOUNT_ADDRESS_ENV_VAR)]
pub account_address: Option<FieldElement>,

#[arg(long, env = DOJO_PRIVATE_KEY_ENV_VAR)]
#[arg(requires = "account_address")]
#[arg(conflicts_with = "keystore_path")]
#[arg(help_heading = "Signer options - RAW")]
#[arg(help = "The raw private key associated with the account contract.")]
Expand All @@ -33,7 +37,6 @@ pub struct AccountOptions {

#[arg(long = "password", env = DOJO_KEYSTORE_PASSWORD_ENV_VAR)]
#[arg(value_name = "PASSWORD")]
#[arg(requires = "keystore_path")]
#[arg(help_heading = "Signer options - KEYSTORE")]
#[arg(help = "The keystore password. Used with --keystore.")]
pub keystore_password: Option<String>,
Expand Down Expand Up @@ -72,7 +75,11 @@ impl AccountOptions {
)));
}

if let Some(path) = &self.keystore_path {
if let Some(path) = &self
.keystore_path
.as_deref()
.or_else(|| env_metadata.and_then(|env| env.keystore_path()))
{
if let Some(password) = self
.keystore_password
.as_deref()
Expand Down Expand Up @@ -105,3 +112,214 @@ impl AccountOptions {
}
}
}

#[cfg(test)]
mod tests {
use std::str::FromStr;

use clap::Parser;
use starknet::signers::{LocalWallet, Signer, SigningKey};
use starknet_crypto::FieldElement;

use super::{
AccountOptions, DOJO_ACCOUNT_ADDRESS_ENV_VAR, DOJO_KEYSTORE_PASSWORD_ENV_VAR,
DOJO_PRIVATE_KEY_ENV_VAR,
};

#[derive(clap::Parser, Debug)]
struct Command {
#[clap(flatten)]
pub account: AccountOptions,
}

#[test]
fn account_address_read_from_env_variable() {
std::env::set_var(DOJO_ACCOUNT_ADDRESS_ENV_VAR, "0x0");

let cmd = Command::parse_from([""]);
assert_eq!(cmd.account.account_address, Some(FieldElement::from_hex_be("0x0").unwrap()));
}

#[test]
fn private_key_read_from_env_variable() {
std::env::set_var(DOJO_PRIVATE_KEY_ENV_VAR, "private_key");

let cmd = Command::parse_from(["sozo", "--account-address", "0x0"]);
assert_eq!(cmd.account.private_key, Some("private_key".to_owned()));
}

#[test]
fn keystore_path_read_from_env_variable() {
std::env::set_var(DOJO_KEYSTORE_PASSWORD_ENV_VAR, "keystore_password");

let cmd = Command::parse_from(["sozo", "--keystore", "./some/path"]);
assert_eq!(cmd.account.keystore_password, Some("keystore_password".to_owned()));
}

#[test]
fn account_address_from_args() {
let env_metadata = dojo_world::metadata::Environment::default();

let cmd = Command::parse_from(["sozo", "--account-address", "0x0"]);
assert_eq!(
cmd.account.account_address(Some(&env_metadata)).unwrap(),
FieldElement::from_hex_be("0x0").unwrap()
);
}

#[test]
fn account_address_from_env_metadata() {
let env_metadata = dojo_world::metadata::Environment {
account_address: Some("0x0".to_owned()),
..Default::default()
};

let cmd = Command::parse_from([""]);
assert_eq!(
cmd.account.account_address(Some(&env_metadata)).unwrap(),
FieldElement::from_hex_be("0x0").unwrap()
);
}

#[test]
fn account_address_from_both() {
let env_metadata = dojo_world::metadata::Environment {
account_address: Some("0x0".to_owned()),
..Default::default()
};

let cmd = Command::parse_from(["sozo", "--account-address", "0x1"]);
assert_eq!(
cmd.account.account_address(Some(&env_metadata)).unwrap(),
FieldElement::from_hex_be("0x1").unwrap()
);
}

#[test]
fn account_address_from_neither() {
let env_metadata = dojo_world::metadata::Environment::default();

let cmd = Command::parse_from([""]);
assert!(cmd.account.account_address(Some(&env_metadata)).is_err());
}

#[tokio::test]
async fn private_key_from_args() {
let env_metadata = dojo_world::metadata::Environment::default();
let private_key = "0x1";

let cmd =
Command::parse_from(["sozo", "--account-address", "0x0", "--private-key", private_key]);
let result_wallet = cmd.account.signer(Some(&env_metadata)).unwrap();
let expected_wallet = LocalWallet::from_signing_key(SigningKey::from_secret_scalar(
FieldElement::from_str(private_key).unwrap(),
));

let result_public_key = result_wallet.get_public_key().await.unwrap();
let expected_public_key = expected_wallet.get_public_key().await.unwrap();
assert!(result_public_key.scalar() == expected_public_key.scalar());
}

#[tokio::test]
async fn private_key_from_env_metadata() {
let private_key = "0x1";
let env_metadata = dojo_world::metadata::Environment {
private_key: Some(private_key.to_owned()),
..Default::default()
};

let cmd = Command::parse_from(["sozo", "--account-address", "0x0"]);
let result_wallet = cmd.account.signer(Some(&env_metadata)).unwrap();
let expected_wallet = LocalWallet::from_signing_key(SigningKey::from_secret_scalar(
FieldElement::from_str(private_key).unwrap(),
));

let result_public_key = result_wallet.get_public_key().await.unwrap();
let expected_public_key = expected_wallet.get_public_key().await.unwrap();
assert!(result_public_key.scalar() == expected_public_key.scalar());
}

#[tokio::test]
async fn keystore_path_and_keystore_password_from_args() {
let keystore_path = "./tests/test_data/keystore/test.json";
let keystore_password = "dojoftw";
let private_key = "0x1";
let env_metadata = dojo_world::metadata::Environment::default();

let cmd = Command::parse_from([
"sozo",
"--keystore",
keystore_path,
"--password",
keystore_password,
]);
let result_wallet = cmd.account.signer(Some(&env_metadata)).unwrap();
let expected_wallet = LocalWallet::from_signing_key(SigningKey::from_secret_scalar(
FieldElement::from_str(private_key).unwrap(),
));

let result_public_key = result_wallet.get_public_key().await.unwrap();
let expected_public_key = expected_wallet.get_public_key().await.unwrap();
assert!(result_public_key.scalar() == expected_public_key.scalar());
}

#[tokio::test]
async fn keystore_path_from_env_metadata() {
let keystore_path = "./tests/test_data/keystore/test.json";
let keystore_password = "dojoftw";

let private_key = "0x1";
let env_metadata = dojo_world::metadata::Environment {
keystore_path: Some(keystore_path.to_owned()),
..Default::default()
};

let cmd = Command::parse_from(["sozo", "--password", keystore_password]);
let result_wallet = cmd.account.signer(Some(&env_metadata)).unwrap();
let expected_wallet = LocalWallet::from_signing_key(SigningKey::from_secret_scalar(
FieldElement::from_str(private_key).unwrap(),
));

let result_public_key = result_wallet.get_public_key().await.unwrap();
let expected_public_key = expected_wallet.get_public_key().await.unwrap();
assert!(result_public_key.scalar() == expected_public_key.scalar());
}

#[tokio::test]
async fn keystore_password_from_env_metadata() {
let keystore_path = "./tests/test_data/keystore/test.json";
let keystore_password = "dojoftw";
let private_key = "0x1";

let env_metadata = dojo_world::metadata::Environment {
keystore_password: Some(keystore_password.to_owned()),
..Default::default()
};

let cmd = Command::parse_from(["sozo", "--keystore", keystore_path]);
let result_wallet = cmd.account.signer(Some(&env_metadata)).unwrap();
let expected_wallet = LocalWallet::from_signing_key(SigningKey::from_secret_scalar(
FieldElement::from_str(private_key).unwrap(),
));

let result_public_key = result_wallet.get_public_key().await.unwrap();
let expected_public_key = expected_wallet.get_public_key().await.unwrap();
assert!(result_public_key.scalar() == expected_public_key.scalar());
}

#[test]
fn dont_allow_both_private_key_and_keystore() {
let keystore_path = "./tests/test_data/keystore/test.json";
let private_key = "0x1";
assert!(
Command::try_parse_from([
"sozo",
"--keystore",
keystore_path,
"--private_key",
private_key,
])
.is_err()
);
}
}
24 changes: 16 additions & 8 deletions crates/sozo/src/commands/options/starknet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,15 @@ mod tests {
}

#[test]
fn url_exist_in_env_metadata_but_env_doesnt() {
fn url_read_from_env_variable() {
std::env::set_var(STARKNET_RPC_URL_ENV_VAR, ENV_RPC);

let cmd = Command::parse_from([""]);
assert_eq!(cmd.options.url(None).unwrap().as_str(), ENV_RPC);
}

#[test]
fn url_exist_in_env_but_not_in_args() {
let env_metadata = dojo_world::metadata::Environment {
rpc_url: Some(METADATA_RPC.into()),
..Default::default()
Expand All @@ -65,26 +73,26 @@ mod tests {
}

#[test]
fn url_doesnt_exist_in_env_metadata_but_env_does() {
std::env::set_var(STARKNET_RPC_URL_ENV_VAR, ENV_RPC);
fn url_doesnt_exist_in_env_but_exist_in_args() {
let env_metadata = dojo_world::metadata::Environment::default();
let cmd = Command::parse_from([""]);
let cmd = Command::parse_from(["sozo", "--rpc-url", ENV_RPC]);

assert_eq!(cmd.options.url(Some(&env_metadata)).unwrap().as_str(), ENV_RPC);
}

#[test]
fn exists_in_both() {
std::env::set_var(STARKNET_RPC_URL_ENV_VAR, ENV_RPC);
fn url_exists_in_both() {
let env_metadata = dojo_world::metadata::Environment {
rpc_url: Some(METADATA_RPC.into()),
..Default::default()
};
let cmd = Command::parse_from([""]);

let cmd = Command::parse_from(["sozo", "--rpc-url", ENV_RPC]);
assert_eq!(cmd.options.url(Some(&env_metadata)).unwrap().as_str(), ENV_RPC);
}

#[test]
fn exists_in_neither() {
fn url_exists_in_neither() {
let env_metadata = dojo_world::metadata::Environment::default();
let cmd = Command::parse_from([""]);
assert_eq!(cmd.options.url(Some(&env_metadata)).unwrap().as_str(), DEFAULT_RPC);
Expand Down
1 change: 1 addition & 0 deletions crates/sozo/tests/test_data/keystore/test.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"crypto":{"cipher":"aes-128-ctr","cipherparams":{"iv":"86dcdc44db46801dd2df660e2242926c"},"ciphertext":"75c93de54b0d29c9d5ecce255478cfb52ce6c82752af0f4f1e353be91ab93f2a","kdf":"scrypt","kdfparams":{"dklen":32,"n":8192,"p":1,"r":8,"salt":"e9342c34144d65f40c5ecee338cea267f96049e9795fa52d1d9cb96923fce998"},"mac":"35252658d371ead5aa890b15a6a4cdfde427561208d2c1e84978d107217faa0b"},"id":"f10cdaf9-0f8f-44df-a906-4285f2ba798d","version":3}

0 comments on commit 18182a0

Please sign in to comment.