Skip to content

Commit

Permalink
test(acc-packet): adding automated tests to sn_cli::AccountPacket
Browse files Browse the repository at this point in the history
  • Loading branch information
bochaco committed Mar 7, 2024
1 parent a184d18 commit 19e6e5e
Show file tree
Hide file tree
Showing 7 changed files with 179 additions and 10 deletions.
9 changes: 8 additions & 1 deletion .github/workflows/merge.yml
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ jobs:

- name: Run CLI tests
timeout-minutes: 25
run: cargo test --release --package sn_cli
run: cargo test --release --package sn_cli --bins

- name: Run client tests
timeout-minutes: 25
Expand Down Expand Up @@ -399,6 +399,13 @@ jobs:
SN_LOG: "all"
timeout-minutes: 10

# CLI Acc-Packet files and folders tests against local network
- name: CLI Acc-Packet files and folders tests
run: cargo test --release -p sn_cli test_acc_packet -- --nocapture
env:
SN_LOG: "all"
timeout-minutes: 10

- name: Start a client to create a register writable by the owner only
run: cargo run --bin safe --release -- --log-output-dest=data-dir register create -n baobao
env:
Expand Down
1 change: 1 addition & 0 deletions Cargo.lock

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

158 changes: 157 additions & 1 deletion sn_cli/src/subcommands/acc_packet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ impl AccountPacket {
if let Ok((addr, _)) = read_root_folder_addr(&meta_dir) {
// bail out if there is already a root folder address different from the passed in
if addr == address {
bail!("The download path is already tracking that Folder, you use 'sync' instead.");
bail!("The download path is already tracking that Folder, use 'sync' instead.");
} else {
bail!(
"The download path is already tracking another Folder with address: {}",
Expand Down Expand Up @@ -925,3 +925,159 @@ fn find_by_name_in_parent_folder(name: &str, path: &Path, folders: &Folders) ->
.and_then(|(folder, _)| folder.find_by_name(name))
.map(|(meta_xorname, _)| *meta_xorname)
}

#[cfg(test)]
mod tests {
// All tests require a network running so Clients can be instantiated.

use std::{
fs::{create_dir_all, File},
io::{Read, Write},
path::{Path, PathBuf},
};

use crate::subcommands::files::upload::FilesUploadOptions;

use super::AccountPacket;

use sn_client::{
protocol::storage::{Chunk, RetryStrategy},
registers::RegisterAddress,
test_utils::{get_funded_wallet, get_new_client, random_file_chunk},
BATCH_SIZE,
};

use bls::SecretKey;
use eyre::{eyre, Result};
use xor_name::XorName;

#[tokio::test]
async fn test_acc_packet_basics() -> Result<()> {
let mut rng = rand::thread_rng();
let owner_sk = SecretKey::random();
let owner_pk = owner_sk.public_key();
let root_folder_addr = RegisterAddress::new(XorName::random(&mut rng), owner_pk);
let client = get_new_client(owner_sk).await?;

let tmp_dir = tempfile::tempdir()?;
let wallet_dir = tmp_dir.path();
let _ = get_funded_wallet(&client, wallet_dir).await?;

let src_files_path = tmp_dir.path().join("myaccpacket");
println!("Files source root dir: {src_files_path:?}");

// let's create some random files and dirs
let files = &[
(
Path::new("file0.txt").to_path_buf(),
Some(random_file_chunk()),
),
(
Path::new("dir1").join("file1.txt"),
Some(random_file_chunk()),
),
(Path::new("dir2").to_path_buf(), None),
];
create_files_with_random_content(&src_files_path, files)?;

let mut acc_packet = AccountPacket::init(
client.clone(),
wallet_dir,
&src_files_path,
Some(root_folder_addr),
)?;

let options = FilesUploadOptions {
make_data_public: false,
verify_store: true,
batch_size: BATCH_SIZE,
retry_strategy: RetryStrategy::Quick,
};
acc_packet.sync(options).await?;
println!(
"Account packet sync-ed to address {}\n",
acc_packet.root_folder_addr().to_hex()
);

let download_files_path = tmp_dir.path().join("myaccpacket-downloaded");
println!("Downloading acc-packet to dir: {download_files_path:?}...\n");

let _downloaded_acc_packet = AccountPacket::retrieve_folders(
&client,
wallet_dir,
root_folder_addr,
&download_files_path,
BATCH_SIZE,
RetryStrategy::Quick,
)
.await?;

check_files_and_dirs_match(&src_files_path, files, &download_files_path)?;

Ok(())
}

fn create_files_with_random_content(
base_path: &Path,
files: &[(PathBuf, Option<Chunk>)],
) -> Result<()> {
for (path, chunk) in files {
let full_path = base_path.join(path);
println!(">> CREATING {full_path:?}");
if let Some(chunk) = chunk {
// it's a file, thus we create it and store its chunk bytes
create_dir_all(full_path.parent().expect("invalid path for test file"))?;
let mut file = File::create(full_path)?;
file.write_all(chunk.value())?;
} else {
// it's a dir, and it shall be empty
create_dir_all(full_path)?;
}
}
Ok(())
}

fn check_files_and_dirs_match(
src_path: &Path,
files: &[(PathBuf, Option<Chunk>)],
target_path: &Path,
) -> Result<()> {
for (path, chunk) in files {
let src_file_path = src_path.join(path);
let target_file_path = target_path.join(path);
println!(">> CHECKING {src_file_path:?} with {target_file_path:?}");
if let Some(chunk) = chunk {
// it's a file, let's compare their content
let mut src_file = File::open(&src_file_path)
.map_err(|err| eyre!("couldn't open source file {src_file_path:?}: {err:?}"))?;
let mut target_file = File::open(&target_file_path).map_err(|err| {
eyre!("couldn't open target file {target_file_path:?}: {err:?}")
})?;

let mut src_content = Vec::new();
src_file
.read_to_end(&mut src_content)
.expect("couldn't read source file");
let mut target_content = Vec::new();
target_file
.read_to_end(&mut target_content)
.expect("couldn't read target file");

assert_eq!(
src_content,
chunk.value().slice(..),
"source file content doesn't match with expected"
);
assert_eq!(
target_content,
chunk.value().slice(..),
"target file content doesn't match with expected"
);
} else {
// it's a dir, let's check their exist and both are empty
todo!();
}
}
Ok(())
}
}
9 changes: 5 additions & 4 deletions sn_client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ version = "0.104.29-alpha.0"
default=[]
local-discovery=["sn_networking/local-discovery"]
open-metrics = ["sn_networking/open-metrics", "prometheus-client"]
test-utils=["sn_protocol/test-utils"]
test-utils=["sn_protocol/test-utils", "sn_peers_acquisition", "lazy_static", "eyre"]
# required to pass on flag to node builds
websockets = ["sn_networking/websockets", "sn_protocol/websockets"]

Expand Down Expand Up @@ -46,14 +46,15 @@ tiny-keccak = "~2.0.2"
tokio = { version = "1.35.0", features = ["io-util", "macros", "rt", "sync", "time"] }
tracing = { version = "~0.1.26" }
xor_name = "5.0.0"
sn_peers_acquisition= { path="../sn_peers_acquisition", version = "0.2.6", optional = true }
eyre = { version = "0.6.8", optional = true }
lazy_static = { version = "~1.4.0", optional = true }

[dev-dependencies]
dirs-next = "~2.0.0"
eyre = "0.6.8"
lazy_static = "~1.4.0"
# add rand to libp2p
libp2p-identity = { version="0.2.7", features = ["rand"] }
sn_peers_acquisition= { path="../sn_peers_acquisition", version = "0.2.6" }
sn_client = { path = "../sn_client", features = ["test-utils"]}

[lints]
workspace = true
Expand Down
4 changes: 4 additions & 0 deletions sn_client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ mod folders;
mod register;
mod wallet;

/// Test utils
#[cfg(feature = "test-utils")]
pub mod test_utils;

// re-export used crates to make them available to app builders
// this ensures the version of the crates used by the app builders are the same as the ones used by the client
// so they don't run into issues with incompatible types due to different versions of the same crate
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
// KIND, either express or implied. Please review the Licences for the specific language governing
// permissions and limitations relating to use of the SAFE Network Software.

use sn_client::{send, Client, WalletClient};
use crate::{send, Client, WalletClient};
use sn_peers_acquisition::parse_peer_addr;
use sn_protocol::{storage::Chunk, NetworkAddress};
use sn_transfers::{create_faucet_wallet, HotWallet, NanoTokens};
Expand Down
6 changes: 3 additions & 3 deletions sn_client/tests/folders_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@

// All tests require a network running so Clients can be instantiated.

mod common;

use common::{get_funded_wallet, get_new_client, pay_for_storage, random_file_chunk};
use sn_client::test_utils::{
get_funded_wallet, get_new_client, pay_for_storage, random_file_chunk,
};

use sn_client::{FolderEntry, FoldersApi, Metadata};
use sn_protocol::{storage::ChunkAddress, NetworkAddress};
Expand Down

0 comments on commit 19e6e5e

Please sign in to comment.