Skip to content

Commit

Permalink
Extract Network and Interface from utils (#127)
Browse files Browse the repository at this point in the history
* Extract Network and Interface from utils

* Use a component

* fmt

* Remove unnecessary dev-dep

* fmt

* extract setup_for_test

Signed-off-by: Ana Hobden <operator@hoverbear.org>

* Fmt

Signed-off-by: Ana Hobden <operator@hoverbear.org>

* Fixup failpoint test

Signed-off-by: Ana Hobden <operator@hoverbear.org>

* Fmt

Signed-off-by: Ana Hobden <operator@hoverbear.org>
  • Loading branch information
Hoverbear committed Feb 21, 2019
1 parent 4ceb6fa commit a726ccc
Show file tree
Hide file tree
Showing 22 changed files with 415 additions and 244 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ target
tmp
/bin

harness/target

Cargo.lock
*.rs.bk
*.rs.fmt
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@ categories = ["algorithms", "database-implementations"]

[features]
default = []
# Enable failpoints
failpoint = ["fail"]

# Make sure to synchronize updates with Harness.
[dependencies]
log = ">0.2"
protobuf = "~2.0-2.2"
Expand All @@ -28,6 +30,7 @@ getset = "0.0.6"
env_logger = "0.5"
criterion = ">0.2.4"
lazy_static = "1.0"
harness = { path = "harness" }
regex = "1.1"

[[bench]]
Expand Down
17 changes: 17 additions & 0 deletions harness/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[package]
name = "harness"
version = "0.1.0"
authors = ["The TiKV Project Developers"]
license = "Apache-2.0"
keywords = []
repository = "https://github.com/pingcap/raft-rs/harness"
readme = "README.md"
homepage = "https://github.com/pingcap/raft-rs/harness"
description = "A testing harness for Raft."
categories = []

# Make sure to synchronize updates with Raft.
[dependencies]
raft = { path = ".." }
rand = "0.5.4"
env_logger = "0.5"
115 changes: 115 additions & 0 deletions harness/src/interface.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
// Copyright 2018 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

// Copyright 2015 CoreOS, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use raft::{eraftpb::Message, storage::MemStorage, Progress, ProgressSet, Raft, Result};
use std::ops::{Deref, DerefMut};

/// A simulated Raft façade for testing.
///
/// If the contained value is a `Some` operations happen. If they are a `None` operations are
/// a no-op.
///
// Compare to upstream, we use struct instead of trait here.
// Because to be able to cast Interface later, we have to make
// Raft derive Any, which will require a lot of dependencies to derive Any.
// That's not worthy for just testing purpose.
pub struct Interface {
/// The raft peer.
pub raft: Option<Raft<MemStorage>>,
}

impl Interface {
/// Create a new interface to a new raft.
pub fn new(r: Raft<MemStorage>) -> Interface {
Interface { raft: Some(r) }
}

/// Step the raft, if it exists.
pub fn step(&mut self, m: Message) -> Result<()> {
match self.raft {
Some(_) => Raft::step(self, m),
None => Ok(()),
}
}

/// Read messages out of the raft.
pub fn read_messages(&mut self) -> Vec<Message> {
match self.raft {
Some(_) => self.msgs.drain(..).collect(),
None => vec![],
}
}

/// Initialize a raft with the given ID and peer set.
pub fn initial(&mut self, id: u64, ids: &[u64]) {
if self.raft.is_some() {
self.id = id;
let prs = self.take_prs();
self.set_prs(ProgressSet::with_capacity(
ids.len(),
prs.learner_ids().len(),
));
for id in ids {
let progress = Progress::new(0, 256);
if prs.learner_ids().contains(id) {
if let Err(e) = self.mut_prs().insert_learner(*id, progress) {
panic!("{}", e);
}
} else if let Err(e) = self.mut_prs().insert_voter(*id, progress) {
panic!("{}", e);
}
}
let term = self.term;
self.reset(term);
}
}
}

impl From<Option<Raft<MemStorage>>> for Interface {
fn from(raft: Option<Raft<MemStorage>>) -> Self {
Self { raft }
}
}

impl From<Raft<MemStorage>> for Interface {
fn from(raft: Raft<MemStorage>) -> Self {
Self { raft: Some(raft) }
}
}

impl Deref for Interface {
type Target = Raft<MemStorage>;
fn deref(&self) -> &Raft<MemStorage> {
self.raft.as_ref().unwrap()
}
}

impl DerefMut for Interface {
fn deref_mut(&mut self) -> &mut Raft<MemStorage> {
self.raft.as_mut().unwrap()
}
}
49 changes: 49 additions & 0 deletions harness/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright 2018 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

// Copyright 2015 The etcd Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/*!
This module contains various testing harness utilities for Raft.
> If you want to build Raft without this, disable the `harness` feature.
*/

extern crate env_logger;
extern crate raft;
extern crate rand;

mod interface;
mod network;

pub use self::{interface::Interface, network::Network};

/// Do any common test initialization. Eg set up logging.
#[doc(hidden)]
pub fn setup_for_test() {
let _ = env_logger::try_init();
}
Loading

0 comments on commit a726ccc

Please sign in to comment.