initial test to ensure auxiliary data is generated correctly

This commit is contained in:
Robert Habermeier
2018-10-31 12:39:27 +01:00
parent fe6dd131f0
commit c64ff78776
3 changed files with 186 additions and 22 deletions
@@ -39,11 +39,7 @@ impl<H, N> SharedAuthoritySet<H, N> {
/// The genesis authority set.
pub(crate) fn genesis(initial: Vec<(AuthorityId, u64)>) -> Self {
SharedAuthoritySet {
inner: Arc::new(RwLock::new(AuthoritySet {
current_authorities: initial,
set_id: 0,
pending_changes: Vec::new(),
}))
inner: Arc::new(RwLock::new(AuthoritySet::genesis(initial)))
}
}
@@ -91,6 +87,15 @@ pub(crate) struct AuthoritySet<H, N> {
}
impl<H, N> AuthoritySet<H, N> {
/// Get a genesis set with given authorities.
pub(crate) fn genesis(initial: Vec<(AuthorityId, u64)>) -> Self {
AuthoritySet {
current_authorities: initial,
set_id: 0,
pending_changes: Vec::new(),
}
}
/// Get the current set id and a reference to the current authority set.
pub(crate) fn current(&self) -> (u64, &[(AuthorityId, u64)]) {
(self.set_id, &self.current_authorities[..])
@@ -113,6 +118,12 @@ impl<H: Eq, N> AuthoritySet<H, N>
self.pending_changes.insert(idx, pending);
}
/// Inspect pending changes.
pub(crate) fn pending_changes(&self) -> &[PendingChange<H, N>] {
&self.pending_changes
}
/// Get the earliest limit-block number, if any.
pub(crate) fn current_limit(&self) -> Option<N> {
self.pending_changes.get(0).map(|change| change.effective_number().clone())
+164 -11
View File
@@ -1,3 +1,21 @@
// Copyright 2018 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate 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.
// Substrate 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 Substrate. If not, see <http://www.gnu.org/licenses/>.
//! Tests and test helpers for GRANDPA.
use super::*;
use network::test::{Block, Hash, TestNetFactory, Peer, PeersClient};
use network::import_queue::{PassThroughVerifier};
@@ -7,6 +25,10 @@ use tokio::runtime::current_thread;
use keyring::Keyring;
use client::BlockchainEvents;
use test_client::{self, runtime::BlockNumber};
use codec::Decode;
use consensus_common::BlockOrigin;
use authorities::AuthoritySet;
type PeerData = Mutex<Option<LinkHalf<test_client::Backend, test_client::Executor, Block>>>;
type GrandpaPeer = Peer<PassThroughVerifier, PeerData>;
@@ -135,14 +157,14 @@ impl Network for MessageRouting {
#[derive(Default, Clone)]
struct TestApi {
genesis_authorities: Vec<(AuthorityId, u64)>,
scheduled_changes: HashMap<BlockNumber, ScheduledChange<BlockNumber>>,
scheduled_changes: Arc<Mutex<HashMap<Hash, ScheduledChange<BlockNumber>>>>,
}
impl TestApi {
fn new(genesis_authorities: Vec<(AuthorityId, u64)>) -> Self {
TestApi {
genesis_authorities,
scheduled_changes: HashMap::new(),
scheduled_changes: Arc::new(Mutex::new(HashMap::new())),
}
}
}
@@ -157,20 +179,29 @@ impl ApiClient<Block> for TestApi {
{
// we take only scheduled changes at given block number where there are no
// extrinsics.
Ok(self.scheduled_changes.get(header.number()).map(|c| c.clone()))
let change = self.scheduled_changes.lock().get(&header.hash()).map(|c| c.clone());
if change.is_some() {
println!("Found transition for {:?}", header.hash());
}
Ok(change)
}
}
const TEST_GOSSIP_DURATION: Duration = Duration::from_millis(500);
const TEST_ROUTING_INTERVAL: Duration = Duration::from_millis(50);
fn make_ids(keys: &[Keyring]) -> Vec<(AuthorityId, u64)> {
keys.iter()
.map(|key| AuthorityId(key.to_raw_public()))
.map(|id| (id, 1))
.collect()
}
#[test]
fn finalize_3_voters_no_observers() {
let peers = &[Keyring::Alice, Keyring::Bob, Keyring::Charlie];
let voters: Vec<_> = peers.iter()
.map(|key| AuthorityId(key.to_raw_public()))
.map(|id| (id, 1))
.collect();
let voters = make_ids(peers);
let mut net = GrandpaTestNet::new(TestApi::new(voters), 3);
net.peer(0).push_blocks(20, false);
@@ -229,10 +260,7 @@ fn finalize_3_voters_no_observers() {
#[test]
fn finalize_3_voters_1_observer() {
let peers = &[Keyring::Alice, Keyring::Bob, Keyring::Charlie];
let voters: Vec<_> = peers.iter()
.map(|key| AuthorityId(key.to_raw_public()))
.map(|id| (id, 1))
.collect();
let voters = make_ids(peers);
let mut net = GrandpaTestNet::new(TestApi::new(voters), 4);
net.peer(0).push_blocks(20, false);
@@ -285,3 +313,128 @@ fn finalize_3_voters_1_observer() {
runtime.block_on(wait_for.select(drive_to_completion).map_err(|_| ())).unwrap();
}
#[test]
fn transition_3_voters_twice_1_observer() {
let peers_a = &[
Keyring::Alice,
Keyring::Bob,
Keyring::Charlie,
];
let peers_b = &[
Keyring::Dave,
Keyring::Eve,
Keyring::Ferdie,
];
let peers_c = &[
Keyring::Alice,
Keyring::Eve,
Keyring::Two,
];
let observer = &[Keyring::One];
let genesis_voters = make_ids(peers_a);
let api = TestApi::new(genesis_voters);
let transitions = api.scheduled_changes.clone();
let add_transition = move |hash, change| {
transitions.lock().insert(hash, change);
};
let mut net = GrandpaTestNet::new(api, 8);
// first 20 blocks: transition at 15, applied at 20.
{
net.peer(0).push_blocks(14, false);
net.peer(0).generate_blocks(1, BlockOrigin::File, |builder| {
let block = builder.bake().unwrap();
println!("Adding transition for {:?}", block.header.hash());
add_transition(block.header.hash(), ScheduledChange {
next_authorities: make_ids(peers_b),
delay: 4,
});
block
});
net.peer(0).push_blocks(5, false);
}
// at block 21 we do another transition, but this time instant.
// add more until we have 30.
{
net.peer(0).generate_blocks(1, BlockOrigin::File, |builder| {
let block = builder.bake().unwrap();
println!("Adding transition for {:?}", block.header.hash());
add_transition(block.header.hash(), ScheduledChange {
next_authorities: make_ids(peers_c),
delay: 0,
});
block
});
net.peer(0).push_blocks(9, false);
}
net.sync();
for (i, peer) in net.peers().iter().enumerate() {
assert_eq!(peer.client().info().unwrap().chain.best_number, 30,
"Peer #{} failed to sync", i);
let set_raw = peer.client().backend().get_aux(::AUTHORITY_SET_KEY).unwrap().unwrap();
let set = AuthoritySet::<Hash, BlockNumber>::decode(&mut &set_raw[..]).unwrap();
assert_eq!(set.current(), (0, make_ids(peers_a).as_slice()));
assert_eq!(set.pending_changes().len(), 2);
}
// let net = Arc::new(Mutex::new(net));
// let mut finality_notifications = Vec::new();
// let mut runtime = current_thread::Runtime::new().unwrap();
// let all_peers = peers.iter()
// .cloned()
// .map(|key| Some(Arc::new(key.into())))
// .chain(::std::iter::once(None));
// for (peer_id, local_key) in all_peers.enumerate() {
// let (client, link) = {
// let mut net = net.lock();
// let link = net.peers[peer_id].data.lock().take().expect("link initialized at startup; qed");
// (
// net.peers[peer_id].client().clone(),
// link,
// )
// };
// finality_notifications.push(
// client.finality_notification_stream()
// .take_while(|n| Ok(n.header.number() < &20))
// .for_each(move |_| Ok(()))
// );
// let voter = run_grandpa(
// Config {
// gossip_duration: TEST_GOSSIP_DURATION,
// local_key,
// },
// link,
// MessageRouting::new(net.clone(), peer_id),
// ).expect("all in order with client and network");
// runtime.spawn(voter);
// }
// // wait for all finalized on each.
// let wait_for = ::futures::future::join_all(finality_notifications)
// .map(|_| ())
// .map_err(|_| ());
// let drive_to_completion = ::tokio::timer::Interval::new_interval(TEST_ROUTING_INTERVAL)
// .for_each(move |_| { net.lock().route_until_complete(); Ok(()) })
// .map(|_| ())
// .map_err(|_| ());
// runtime.block_on(wait_for.select(drive_to_completion).map_err(|_| ())).unwrap();
}