Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

Add a few tests for the snapshot service #2059

Merged
merged 5 commits into from
Sep 11, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.lock

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

2 changes: 2 additions & 0 deletions ethcore/src/client/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -673,6 +673,8 @@ impl Client {
impl snapshot::DatabaseRestore for Client {
/// Restart the client with a new backend
fn restore_db(&self, new_db: &str) -> Result<(), EthcoreError> {
trace!(target: "snapshot", "Replacing client database with {:?}", new_db);

let _import_lock = self.import_lock.lock();
let mut state_db = self.state_db.write();
let mut chain = self.chain.write();
Expand Down
1 change: 0 additions & 1 deletion ethcore/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@ impl ClientService {
pruning: pruning,
channel: io_service.channel(),
snapshot_root: snapshot_path.into(),
client_db: client_path.into(),
db_restore: client.clone(),
};
let snapshot = Arc::new(try!(SnapshotService::new(snapshot_params)));
Expand Down
15 changes: 1 addition & 14 deletions ethcore/src/snapshot/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,9 +187,6 @@ pub struct ServiceParams {
/// The directory to put snapshots in.
/// Usually "<chain hash>/snapshot"
pub snapshot_root: PathBuf,
/// The client's database directory.
/// Usually "<chain hash>/<pruning>/db".
pub client_db: PathBuf,
/// A handle for database restoration.
pub db_restore: Arc<DatabaseRestore>,
}
Expand All @@ -198,7 +195,6 @@ pub struct ServiceParams {
/// This controls taking snapshots and restoring from them.
pub struct Service {
restoration: Mutex<Option<Restoration>>,
client_db: PathBuf,
snapshot_root: PathBuf,
db_config: DatabaseConfig,
io_channel: Channel,
Expand All @@ -219,7 +215,6 @@ impl Service {
pub fn new(params: ServiceParams) -> Result<Self, Error> {
let mut service = Service {
restoration: Mutex::new(None),
client_db: params.client_db,
snapshot_root: params.snapshot_root,
db_config: params.db_config,
io_channel: params.channel,
Expand Down Expand Up @@ -301,8 +296,7 @@ impl Service {
fn replace_client_db(&self) -> Result<(), Error> {
let our_db = self.restoration_db();

trace!(target: "snapshot", "replacing {:?} with {:?}", self.client_db, our_db);
try!(self.db_restore.restore_db(our_db.to_str().unwrap()));
try!(self.db_restore.restore_db(&*our_db.to_string_lossy()));
Ok(())
}

Expand Down Expand Up @@ -523,12 +517,6 @@ impl SnapshotService for Service {
fn abort_restore(&self) {
*self.restoration.lock() = None;
*self.status.lock() = RestorationStatus::Inactive;
if let Err(e) = fs::remove_dir_all(&self.restoration_dir()) {
match e.kind() {
ErrorKind::NotFound => {},
_ => warn!("encountered error {} while deleting snapshot restoration dir.", e),
}
}
}

fn restore_state_chunk(&self, hash: H256, chunk: Bytes) {
Expand Down Expand Up @@ -585,7 +573,6 @@ mod tests {
pruning: Algorithm::Archive,
channel: service.channel(),
snapshot_root: dir,
client_db: client_db,
db_restore: Arc::new(NoopDBRestore),
};

Expand Down
1 change: 1 addition & 0 deletions ethcore/src/snapshot/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

mod blocks;
mod state;
mod service;

pub mod helpers;

Expand Down
143 changes: 143 additions & 0 deletions ethcore/src/snapshot/tests/service.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
// Copyright 2015, 2016 Ethcore (UK) Ltd.
// This file is part of Parity.

// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.

//! Tests for the snapshot service.

use std::sync::Arc;

use client::{BlockChainClient, Client};
use ids::BlockID;
use snapshot::service::{Service, ServiceParams};
use snapshot::{self, ManifestData, SnapshotService};
use spec::Spec;
use tests::helpers::generate_dummy_client_with_spec_and_data;

use devtools::RandomTempPath;
use io::IoChannel;
use util::kvdb::DatabaseConfig;

struct NoopDBRestore;

impl snapshot::DatabaseRestore for NoopDBRestore {
fn restore_db(&self, _new_db: &str) -> Result<(), ::error::Error> {
Ok(())
}
}

#[test]
fn restored_is_equivalent() {
const NUM_BLOCKS: u32 = 400;
const TX_PER: usize = 5;

let gas_prices = vec![1.into(), 2.into(), 3.into(), 999.into()];

let client = generate_dummy_client_with_spec_and_data(Spec::new_null, NUM_BLOCKS, TX_PER, &gas_prices);

let path = RandomTempPath::create_dir();
let mut path = path.as_path().clone();
let mut client_db = path.clone();

client_db.push("client_db");
path.push("snapshot");

let db_config = DatabaseConfig::with_columns(::db::NUM_COLUMNS);

let spec = Spec::new_null();
let client2 = Client::new(
Default::default(),
&spec,
&client_db,
Arc::new(::miner::Miner::with_spec(&spec)),
IoChannel::disconnected(),
&db_config,
).unwrap();

let service_params = ServiceParams {
engine: spec.engine.clone(),
genesis_block: spec.genesis_block(),
db_config: db_config,
pruning: ::util::journaldb::Algorithm::Archive,
channel: IoChannel::disconnected(),
snapshot_root: path,
db_restore: client2.clone(),
};

let service = Service::new(service_params).unwrap();
service.take_snapshot(&client, NUM_BLOCKS as u64).unwrap();

let manifest = service.manifest().unwrap();

service.init_restore(manifest.clone()).unwrap();
assert!(service.init_restore(manifest.clone()).is_ok());

for hash in manifest.state_hashes {
let chunk = service.chunk(hash).unwrap();
service.feed_state_chunk(hash, &chunk);
}

for hash in manifest.block_hashes {
let chunk = service.chunk(hash).unwrap();
service.feed_block_chunk(hash, &chunk);
}

assert_eq!(service.status(), ::snapshot::RestorationStatus::Inactive);

for x in 0..NUM_BLOCKS {
let block1 = client.block(BlockID::Number(x as u64)).unwrap();
let block2 = client2.block(BlockID::Number(x as u64)).unwrap();

assert_eq!(block1, block2);
}
}

#[test]
fn guards_delete_folders() {
Copy link
Contributor

@NikVolf NikVolf Sep 9, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is the test about btw?
is the name right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's checking if the Guard struct in the snapshot service implementation is properly deleting the restoration folder on snapshot abort or drop.

let spec = Spec::new_null();
let path = RandomTempPath::create_dir();
let mut path = path.as_path().clone();
let service_params = ServiceParams {
engine: spec.engine.clone(),
genesis_block: spec.genesis_block(),
db_config: DatabaseConfig::with_columns(::db::NUM_COLUMNS),
pruning: ::util::journaldb::Algorithm::Archive,
channel: IoChannel::disconnected(),
snapshot_root: path.clone(),
db_restore: Arc::new(NoopDBRestore),
};

let service = Service::new(service_params).unwrap();
path.push("restoration");

let manifest = ManifestData {
state_hashes: vec![],
block_hashes: vec![],
block_number: 0,
block_hash: Default::default(),
state_root: Default::default(),
};

service.init_restore(manifest.clone()).unwrap();
assert!(path.exists());

service.abort_restore();
assert!(!path.exists());

service.init_restore(manifest.clone()).unwrap();
assert!(path.exists());

drop(service);
assert!(!path.exists());
}