This repository has been archived by the owner on Apr 17, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 295
Fix consensus VoteOther case #1834
Merged
Merged
Changes from 3 commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
8471db2
Refactor yac gate test with subject
lebdron 15f97c0
Add test case for VoteOther
lebdron 2d50dcd
Fix VoteOther struct and handling
lebdron 82e91ad
Merge branch 'trunk/bft-os-integration' into fix/vote-other-case
lebdron 23abf35
Fix review
lebdron ae93cfe
Replace accumulate with transform
lebdron File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,11 +6,12 @@ | |
#ifndef IROHA_SYNCHRONIZER_IMPL_HPP | ||
#define IROHA_SYNCHRONIZER_IMPL_HPP | ||
|
||
#include "synchronizer/synchronizer.hpp" | ||
|
||
#include "ametsuchi/mutable_factory.hpp" | ||
#include "logger/logger.hpp" | ||
#include "network/block_loader.hpp" | ||
#include "network/consensus_gate.hpp" | ||
#include "synchronizer/synchronizer.hpp" | ||
#include "validation/chain_validator.hpp" | ||
|
||
namespace iroha { | ||
|
@@ -35,15 +36,19 @@ namespace iroha { | |
* apply the missing blocks | ||
*/ | ||
SynchronizationEvent downloadMissingBlocks( | ||
std::shared_ptr<shared_model::interface::Block> commit_message, | ||
const shared_model::interface::types::PublicKeyCollectionType | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe pass VoteOther to avoid specifying all parameters in functions? |
||
&public_keys, | ||
const shared_model::interface::types::HashType &hash, | ||
const consensus::Round &round, | ||
std::unique_ptr<ametsuchi::MutableStorage> storage); | ||
|
||
void processNext( | ||
std::shared_ptr<shared_model::interface::Block> commit_message, | ||
const consensus::Round &round); | ||
void processDifferent( | ||
std::shared_ptr<shared_model::interface::Block> commit_message, | ||
const shared_model::interface::types::PublicKeyCollectionType | ||
&public_keys, | ||
const shared_model::interface::types::HashType &hash, | ||
const consensus::Round &round); | ||
|
||
boost::optional<std::unique_ptr<ametsuchi::MutableStorage>> getStorage(); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,11 +3,12 @@ | |
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#include "consensus/yac/impl/yac_gate_impl.hpp" | ||
|
||
#include <memory> | ||
|
||
#include <rxcpp/rx.hpp> | ||
#include "consensus/consensus_block_cache.hpp" | ||
#include "consensus/yac/impl/yac_gate_impl.hpp" | ||
#include "consensus/yac/storage/yac_proposal_storage.hpp" | ||
#include "cryptography/crypto_provider/crypto_defaults.hpp" | ||
#include "framework/specified_visitor.hpp" | ||
|
@@ -68,18 +69,21 @@ class YacGateTest : public ::testing::Test { | |
message.hash = expected_hash; | ||
message.signature = signature; | ||
commit_message = CommitMessage({message}); | ||
expected_commit = rxcpp::observable<>::just(Answer(commit_message)); | ||
expected_commit = commit_message; | ||
|
||
hash_gate = make_unique<MockHashGate>(); | ||
peer_orderer = make_unique<MockYacPeerOrderer>(); | ||
auto hash_gate_ptr = make_unique<MockHashGate>(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
hash_gate = hash_gate_ptr.get(); | ||
auto peer_orderer_ptr = make_unique<MockYacPeerOrderer>(); | ||
peer_orderer = peer_orderer_ptr.get(); | ||
hash_provider = make_shared<MockYacHashProvider>(); | ||
block_creator = make_shared<MockBlockCreator>(); | ||
block_cache = make_shared<ConsensusResultCache>(); | ||
} | ||
|
||
void init() { | ||
gate = std::make_shared<YacGateImpl>(std::move(hash_gate), | ||
std::move(peer_orderer), | ||
EXPECT_CALL(*block_creator, on_block()) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe use ON_CALL so that we do not set any unnecessary invariants for tests? |
||
.WillOnce(Return(block_notifier.get_observable())); | ||
|
||
gate = std::make_shared<YacGateImpl>(std::move(hash_gate_ptr), | ||
std::move(peer_orderer_ptr), | ||
hash_provider, | ||
block_creator, | ||
block_cache); | ||
|
@@ -92,10 +96,13 @@ class YacGateTest : public ::testing::Test { | |
std::shared_ptr<shared_model::interface::Block> expected_block; | ||
VoteMessage message; | ||
CommitMessage commit_message; | ||
rxcpp::observable<Answer> expected_commit; | ||
Answer expected_commit{commit_message}; | ||
rxcpp::subjects::subject<std::shared_ptr<shared_model::interface::Block>> | ||
block_notifier; | ||
rxcpp::subjects::subject<Answer> outcome_notifier; | ||
|
||
unique_ptr<MockHashGate> hash_gate; | ||
unique_ptr<MockYacPeerOrderer> peer_orderer; | ||
MockHashGate *hash_gate; | ||
MockYacPeerOrderer *peer_orderer; | ||
shared_ptr<MockYacHashProvider> hash_provider; | ||
shared_ptr<MockBlockCreator> block_creator; | ||
shared_ptr<ConsensusResultCache> block_cache; | ||
|
@@ -115,7 +122,8 @@ TEST_F(YacGateTest, YacGateSubscriptionTest) { | |
// yac consensus | ||
EXPECT_CALL(*hash_gate, vote(expected_hash, _)).Times(1); | ||
|
||
EXPECT_CALL(*hash_gate, onOutcome()).WillOnce(Return(expected_commit)); | ||
EXPECT_CALL(*hash_gate, onOutcome()) | ||
.WillOnce(Return(outcome_notifier.get_observable())); | ||
|
||
// generate order of peers | ||
EXPECT_CALL(*peer_orderer, getOrdering(_)) | ||
|
@@ -124,11 +132,7 @@ TEST_F(YacGateTest, YacGateSubscriptionTest) { | |
// make hash from block | ||
EXPECT_CALL(*hash_provider, makeHash(_)).WillOnce(Return(expected_hash)); | ||
|
||
// make blocks | ||
EXPECT_CALL(*block_creator, on_block()) | ||
.WillOnce(Return(rxcpp::observable<>::just(expected_block))); | ||
|
||
init(); | ||
block_notifier.get_subscriber().on_next(expected_block); | ||
|
||
// verify that block we voted for is in the cache | ||
auto cache_block = block_cache->get(); | ||
|
@@ -145,6 +149,8 @@ TEST_F(YacGateTest, YacGateSubscriptionTest) { | |
ASSERT_EQ(block, cache_block); | ||
}); | ||
|
||
outcome_notifier.get_subscriber().on_next(expected_commit); | ||
|
||
ASSERT_TRUE(gate_wrapper.validate()); | ||
} | ||
|
||
|
@@ -165,11 +171,7 @@ TEST_F(YacGateTest, YacGateSubscribtionTestFailCase) { | |
// make hash from block | ||
EXPECT_CALL(*hash_provider, makeHash(_)).WillOnce(Return(expected_hash)); | ||
|
||
// make blocks | ||
EXPECT_CALL(*block_creator, on_block()) | ||
.WillOnce(Return(rxcpp::observable<>::just(expected_block))); | ||
|
||
init(); | ||
block_notifier.get_subscriber().on_next(expected_block); | ||
} | ||
|
||
/** | ||
|
@@ -179,15 +181,74 @@ TEST_F(YacGateTest, YacGateSubscribtionTestFailCase) { | |
*/ | ||
TEST_F(YacGateTest, AgreementOnNone) { | ||
EXPECT_CALL(*hash_gate, vote(_, _)).Times(1); | ||
EXPECT_CALL(*block_creator, on_block()) | ||
.WillOnce(Return(rxcpp::observable<>::empty< | ||
std::shared_ptr<shared_model::interface::Block>>())); | ||
|
||
EXPECT_CALL(*peer_orderer, getOrdering(_)) | ||
.WillOnce(Return(ClusterOrdering::create({mk_peer("fake_node")}))); | ||
|
||
init(); | ||
|
||
ASSERT_EQ(block_cache->get(), nullptr); | ||
|
||
gate->vote(boost::none, boost::none, {}); | ||
|
||
ASSERT_EQ(block_cache->get(), nullptr); | ||
} | ||
|
||
/** | ||
* @given yac gate | ||
* @when voting for one block @and receiving another | ||
* @then yac gate will emit the data of block, for which consensus voted | ||
*/ | ||
TEST_F(YacGateTest, DifferentCommit) { | ||
// make hash from block | ||
EXPECT_CALL(*hash_provider, makeHash(_)).WillOnce(Return(expected_hash)); | ||
|
||
// generate order of peers | ||
EXPECT_CALL(*peer_orderer, getOrdering(_)) | ||
.WillOnce(Return(ClusterOrdering::create({mk_peer("fake_node")}))); | ||
|
||
EXPECT_CALL(*hash_gate, vote(expected_hash, _)).Times(1); | ||
|
||
block_notifier.get_subscriber().on_next(expected_block); | ||
|
||
// create another block, which will be "received", and generate a commit | ||
// message with it | ||
decltype(expected_block) actual_block = std::make_shared<MockBlock>(); | ||
Hash actual_hash("actual_hash"); | ||
PublicKey actual_pubkey("actual_pubkey"); | ||
auto signature = std::make_shared<MockSignature>(); | ||
EXPECT_CALL(*signature, publicKey()) | ||
.WillRepeatedly(ReturnRefOfCopy(actual_pubkey)); | ||
|
||
message.hash = | ||
YacHash(iroha::consensus::Round{1, 1}, "actual_proposal", "actual_block"); | ||
message.signature = signature; | ||
commit_message = CommitMessage({message}); | ||
expected_commit = commit_message; | ||
|
||
// yac | ||
EXPECT_CALL(*hash_gate, onOutcome()) | ||
.WillOnce(Return(outcome_notifier.get_observable())); | ||
|
||
// convert yac hash to model hash | ||
EXPECT_CALL(*hash_provider, toModelHash(message.hash)) | ||
.WillOnce(Return(actual_hash)); | ||
|
||
// verify that block we voted for is in the cache | ||
auto cache_block = block_cache->get(); | ||
ASSERT_EQ(cache_block, expected_block); | ||
|
||
// verify that yac gate emit expected block | ||
auto gate_wrapper = make_test_subscriber<CallExact>(gate->onOutcome(), 1); | ||
gate_wrapper.subscribe([actual_hash, actual_pubkey](auto outcome) { | ||
auto concete_outcome = boost::get<iroha::consensus::VoteOther>(outcome); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. typo in variable name? |
||
auto public_keys = concete_outcome.public_keys; | ||
auto hash = concete_outcome.hash; | ||
|
||
ASSERT_EQ(1, public_keys.size()); | ||
ASSERT_EQ(actual_pubkey, public_keys.front()); | ||
ASSERT_EQ(hash, actual_hash); | ||
}); | ||
|
||
outcome_notifier.get_subscriber().on_next(expected_commit); | ||
|
||
ASSERT_TRUE(gate_wrapper.validate()); | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe use transform instead?