Skip to content

Commit

Permalink
chore: Add e2e test for backup and restore
Browse files Browse the repository at this point in the history
  • Loading branch information
holzeis committed Nov 10, 2023
1 parent 217f763 commit 0a1214b
Show file tree
Hide file tree
Showing 8 changed files with 95 additions and 31 deletions.
33 changes: 25 additions & 8 deletions crates/tests-e2e/src/app.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::test_subscriber::TestSubscriber;
use crate::test_subscriber::ThreadSafeSenders;
use crate::wait_until;
use native::api;
use tempfile::TempDir;

pub struct AppHandle {
Expand All @@ -11,7 +12,13 @@ pub struct AppHandle {
_tx: ThreadSafeSenders,
}

pub async fn run_app() -> AppHandle {
impl AppHandle {
pub fn stop(&self) {
self._handle.abort()
}
}

pub async fn run_app(seed_phrase: Option<Vec<String>>) -> AppHandle {
let app_dir = TempDir::new().expect("Failed to create temporary directory");
let seed_dir = TempDir::new().expect("Failed to create temporary directory");
let _app_handle = {
Expand All @@ -25,13 +32,23 @@ pub async fn run_app() -> AppHandle {
let app_dir = as_string(&app_dir);
let seed_dir = as_string(&seed_dir);

tokio::task::spawn_blocking({
let seed_dir = seed_dir.clone();
move || {
native::api::set_config(test_config(), app_dir, seed_dir)
.expect("Could not configure app")
}
});
native::api::set_config(test_config(), app_dir, seed_dir.clone())
.expect("Could not configure app");

if let Some(seed_phrase) = seed_phrase {
tokio::task::spawn_blocking({
let seed_dir = seed_dir.clone();
move || {
api::restore_from_seed_phrase(
seed_phrase.join(" "),
format!("{seed_dir}/regtest/seed"),
)
.expect("Failed to restore from seed phrase");
}
})
.await
.expect("Failed to finish restore from seed phrase");
}

tokio::task::spawn_blocking(move || {
native::api::run(
Expand Down
2 changes: 1 addition & 1 deletion crates/tests-e2e/src/setup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ impl TestSetup {
.await
.expect("To be able to sync coordinator wallet");

let app = run_app().await;
let app = run_app(None).await;

assert_eq!(
app.rx
Expand Down
2 changes: 1 addition & 1 deletion crates/tests-e2e/tests/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ async fn app_can_be_funded_with_lnd_faucet() -> Result<()> {
bitcoind.mine(1).await.unwrap();
coordinator.sync_wallet().await.unwrap();

let app = run_app().await;
let app = run_app(None).await;

// Unfunded wallet should be empty
assert_eq!(app.rx.wallet_info().unwrap().balances.lightning, 0);
Expand Down
51 changes: 51 additions & 0 deletions crates/tests-e2e/tests/restore_from_backup.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
use anyhow::Result;
use native::api;
use tests_e2e::app::run_app;
use tests_e2e::logger::init_tracing;
use tests_e2e::setup;
use tokio::task::spawn_blocking;

#[tokio::test]
#[ignore = "need to be run with 'just e2e' command"]
async fn app_can_be_restored_from_a_backup() -> Result<()> {
init_tracing();

let test = setup::TestSetup::new_with_open_position().await;

let seed_phrase = api::get_seed_phrase();

let ln_balance = test
.app
.rx
.wallet_info()
.expect("to have wallet info")
.balances
.lightning;

// kill the app
test.app.stop();
tracing::info!("Shutting down app!");

let app = run_app(Some(seed_phrase.0)).await;

assert_eq!(
app.rx
.wallet_info()
.expect("to have wallet info")
.balances
.lightning,
ln_balance
);

let positions = spawn_blocking(|| api::get_positions().expect("Failed to get positions"))
.await
.unwrap();
assert_eq!(1, positions.len());

// Test if full backup is running without errors
spawn_blocking(|| api::full_backup().expect("Failed to run full backup"))
.await
.unwrap();

Ok(())
}
8 changes: 6 additions & 2 deletions mobile/native/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -412,10 +412,14 @@ pub fn get_seed_phrase() -> SyncReturn<Vec<String>> {
SyncReturn(ln_dlc::get_seed_phrase())
}

pub fn restore_from_seed_phrase(seed_phrase: String, target_seed_file_path: String) -> Result<()> {
#[tokio::main(flavor = "current_thread")]
pub async fn restore_from_seed_phrase(
seed_phrase: String,
target_seed_file_path: String,
) -> Result<()> {
let file_path = PathBuf::from(target_seed_file_path);
tracing::info!("Restoring seed from phrase to {:?}", file_path);
ln_dlc::restore_from_mnemonic(&seed_phrase, file_path.as_path())?;
ln_dlc::restore_from_mnemonic(&seed_phrase, file_path.as_path()).await?;
Ok(())
}

Expand Down
15 changes: 3 additions & 12 deletions mobile/native/src/backup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ use crate::event::EventType;
use anyhow::bail;
use anyhow::ensure;
use anyhow::Result;
use bitcoin::hashes::hex::ToHex;
use coordinator_commons::Backup;
use coordinator_commons::DeleteBackup;
use coordinator_commons::Restore;
Expand Down Expand Up @@ -129,7 +128,7 @@ impl RemoteBackupClient {
}

pub fn backup(&self, key: String, value: Vec<u8>) -> RemoteHandle<()> {
tracing::trace!("Creating backup for {key} with value {}", value.to_hex());
tracing::trace!("Creating backup for {key}");
let (fut, remote_handle) = {
let client = self.inner.clone();
let cipher = self.cipher.clone();
Expand Down Expand Up @@ -214,11 +213,7 @@ impl RemoteBackupClient {
let decrypted_value = cipher.decrypt(restore.value)?;
match restore.kind {
RestoreKind::LN => {
tracing::debug!(
"Restoring {} with value {}",
restore.key,
decrypted_value.to_hex()
);
tracing::debug!("Restoring {}", restore.key);
let dest_file = Path::new(&data_dir)
.join(network.to_string())
.join(restore.key.clone());
Expand All @@ -227,11 +222,7 @@ impl RemoteBackupClient {
fs::write(dest_file.as_path(), decrypted_value)?;
}
RestoreKind::DLC => {
tracing::debug!(
"Restoring {} with value {}",
restore.key,
decrypted_value.to_hex()
);
tracing::debug!("Restoring {}", restore.key);
let keys = restore.key.split('/').collect::<Vec<&str>>();
ensure!(keys.len() == 2, "dlc key is too short");

Expand Down
9 changes: 7 additions & 2 deletions mobile/native/src/ln_dlc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -415,12 +415,17 @@ pub fn init_new_mnemonic(target_seed_file: &Path) -> Result<()> {
Ok(())
}

#[tokio::main(flavor = "current_thread")]
pub async fn restore_from_mnemonic(seed_words: &str, target_seed_file: &Path) -> Result<()> {
let seed = Bip39Seed::restore_from_mnemonic(seed_words, target_seed_file)?;
crate::state::set_seed(seed);

let storage = get_storage();
let storage = TenTenOneNodeStorage::new(
config::get_data_dir(),
config::get_network(),
get_node_key(),
);
tracing::info!("Initialized 10101 storage!");
crate::state::set_storage(storage.clone());
storage.client.restore(storage.dlc_storage).await
}

Expand Down
6 changes: 1 addition & 5 deletions mobile/native/src/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,11 +199,7 @@ impl KVStorePersister for TenTenOneNodeStorage {
self.ln_storage.persist(key, value)?;

let value = value.encode();
tracing::trace!(
"Creating a backup of {:?} with value {}",
key,
value.to_hex()
);
tracing::trace!("Creating a backup of {:?}", key);

// Let the backup run asynchronously we don't really care if it is successful or not as the
// next persist will fix the issue. Note, if we want to handle failed backup attempts we
Expand Down

0 comments on commit 0a1214b

Please sign in to comment.