Commit 7ba1e052 authored by Patrick Monette's avatar Patrick Monette Committed by Commit Bot

[PM] Split ContextType from voting::Vote.

Bug: 971272
Change-Id: I9fcde3434c76f8c5529e5be8cca639207cca9eda
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2519765
Commit-Queue: Patrick Monette <pmonette@chromium.org>
Reviewed-by: default avatarChris Hamilton <chrisha@chromium.org>
Cr-Commit-Position: refs/heads/master@{#824980}
parent 894f8f83
......@@ -65,13 +65,13 @@ VotingChannel ExecutionContextPriorityDecorator::GetVotingChannel() {
VoteReceipt ExecutionContextPriorityDecorator::SubmitVote(
util::PassKey<VotingChannel>,
voting::VoterId<Vote> voter_id,
const ExecutionContext* execution_context,
const Vote& vote) {
DCHECK_EQ(voter_id_, voter_id);
const auto* execution_context = vote.context();
auto* accepted_vote =
ExecutionContextPriorityAccess::GetAcceptedVote(execution_context);
DCHECK(!accepted_vote->IsValid());
*accepted_vote = AcceptedVote(this, voter_id, vote);
*accepted_vote = AcceptedVote(this, voter_id, execution_context, vote);
SetPriorityAndReason(execution_context,
PriorityAndReason(vote.value(), vote.reason()));
return accepted_vote->IssueReceipt();
......@@ -80,7 +80,7 @@ VoteReceipt ExecutionContextPriorityDecorator::SubmitVote(
void ExecutionContextPriorityDecorator::ChangeVote(util::PassKey<AcceptedVote>,
AcceptedVote* old_vote,
const Vote& new_vote) {
const auto* execution_context = new_vote.context();
const auto* execution_context = old_vote->context();
auto* accepted_vote =
ExecutionContextPriorityAccess::GetAcceptedVote(execution_context);
DCHECK_EQ(accepted_vote, old_vote);
......@@ -93,7 +93,7 @@ void ExecutionContextPriorityDecorator::ChangeVote(util::PassKey<AcceptedVote>,
void ExecutionContextPriorityDecorator::VoteInvalidated(
util::PassKey<AcceptedVote>,
AcceptedVote* vote) {
const auto* execution_context = vote->vote().context();
const auto* execution_context = vote->context();
auto* accepted_vote =
ExecutionContextPriorityAccess::GetAcceptedVote(execution_context);
DCHECK_EQ(accepted_vote, vote);
......
......@@ -27,6 +27,7 @@ class ExecutionContextPriorityDecorator : public GraphOwnedDefaultImpl,
// VoteConsumer implementation:
VoteReceipt SubmitVote(util::PassKey<VotingChannel>,
voting::VoterId<Vote> voter_id,
const ExecutionContext* execution_context,
const Vote& vote) override;
void ChangeVote(util::PassKey<AcceptedVote>,
AcceptedVote* old_vote,
......
......@@ -192,8 +192,9 @@ void BoostingVoteAggregator::NodeData::DecrementEdgeCount() {
VoteReceipt BoostingVoteAggregator::NodeData::SetIncomingVote(
VoteConsumer* consumer,
voting::VoterId<Vote> voter_id,
const ExecutionContext* execution_context,
const Vote& vote) {
incoming_ = AcceptedVote(consumer, voter_id, vote);
incoming_ = AcceptedVote(consumer, voter_id, execution_context, vote);
return incoming_.IssueReceipt();
}
......@@ -394,17 +395,19 @@ void BoostingVoteAggregator::CancelBoostingVote(
}
}
VoteReceipt BoostingVoteAggregator::SubmitVote(util::PassKey<VotingChannel>,
voting::VoterId<Vote> voter_id,
const Vote& vote) {
VoteReceipt BoostingVoteAggregator::SubmitVote(
util::PassKey<VotingChannel>,
voting::VoterId<Vote> voter_id,
const ExecutionContext* execution_context,
const Vote& vote) {
DCHECK(IsSetup());
DCHECK_EQ(input_voter_id_, voter_id);
DCHECK(vote.IsValid());
// Store the vote.
auto node_data_it = FindOrCreateNodeData(vote.context());
VoteReceipt receipt =
node_data_it->second.SetIncomingVote(this, voter_id, vote);
auto node_data_it = FindOrCreateNodeData(execution_context);
VoteReceipt receipt = node_data_it->second.SetIncomingVote(
this, voter_id, execution_context, vote);
NodeDataPtrSet changes;
......@@ -504,7 +507,7 @@ BoostingVoteAggregator::GetNodeDataByVote(AcceptedVote* vote) {
DCHECK(vote->voter_id() == input_voter_id_);
DCHECK(IsSetup());
auto it = nodes_.find(vote->vote().context());
auto it = nodes_.find(vote->context());
DCHECK(it != nodes_.end());
DCHECK_EQ(vote, &it->second.incoming());
return it;
......@@ -582,7 +585,7 @@ void BoostingVoteAggregator::UpstreamVoteIfNeeded(
// Create an outgoing vote.
node_data->SetOutgoingVoteReceipt(
channel_.SubmitVote(Vote(execution_context, priority, reason)));
channel_.SubmitVote(execution_context, Vote(priority, reason)));
}
void BoostingVoteAggregator::UpstreamChanges(const NodeDataPtrSet& changes) {
......
......@@ -137,7 +137,7 @@ TEST(ExecutionContextPriorityTest, VoteReceiptsWork) {
EXPECT_EQ(1u, consumer.votes_.size());
EXPECT_EQ(1u, consumer.valid_vote_count_);
EXPECT_EQ(voter.voting_channel_.voter_id(), consumer.votes_[0].voter_id());
EXPECT_EQ(kDummyExecutionContext1, consumer.votes_[0].vote().context());
EXPECT_EQ(kDummyExecutionContext1, consumer.votes_[0].context());
EXPECT_TRUE(consumer.votes_[0].IsValid());
ExpectEntangled(voter.receipts_[0], consumer.votes_[0]);
......@@ -165,20 +165,20 @@ TEST(ExecutionContextPriorityTest, VoteReceiptsWork) {
EXPECT_EQ(2u, voter.receipts_.size());
EXPECT_EQ(2u, consumer.votes_.size());
EXPECT_EQ(2u, consumer.valid_vote_count_);
EXPECT_EQ(kDummyExecutionContext1, consumer.votes_[0].vote().context());
EXPECT_EQ(kDummyExecutionContext2, consumer.votes_[1].vote().context());
EXPECT_EQ(kDummyExecutionContext1, consumer.votes_[0].context());
EXPECT_EQ(kDummyExecutionContext2, consumer.votes_[1].context());
ExpectEntangled(voter.receipts_[0], consumer.votes_[0]);
ExpectEntangled(voter.receipts_[1], consumer.votes_[1]);
// Change a vote, but making no change.
ExpectEntangled(voter.receipts_[0], consumer.votes_[0]);
EXPECT_EQ(kDummyExecutionContext1, consumer.votes_[0].vote().context());
EXPECT_EQ(kDummyExecutionContext1, consumer.votes_[0].context());
EXPECT_EQ(base::TaskPriority::LOWEST, consumer.votes_[0].vote().value());
EXPECT_EQ(DummyVoter::kReason, consumer.votes_[0].vote().reason());
voter.receipts_[0].ChangeVote(base::TaskPriority::LOWEST,
DummyVoter::kReason);
ExpectEntangled(voter.receipts_[0], consumer.votes_[0]);
EXPECT_EQ(kDummyExecutionContext1, consumer.votes_[0].vote().context());
EXPECT_EQ(kDummyExecutionContext1, consumer.votes_[0].context());
EXPECT_EQ(base::TaskPriority::LOWEST, consumer.votes_[0].vote().value());
EXPECT_EQ(DummyVoter::kReason, consumer.votes_[0].vote().reason());
......@@ -186,7 +186,7 @@ TEST(ExecutionContextPriorityTest, VoteReceiptsWork) {
static const char kReason[] = "another reason";
voter.receipts_[0].ChangeVote(base::TaskPriority::HIGHEST, kReason);
ExpectEntangled(voter.receipts_[0], consumer.votes_[0]);
EXPECT_EQ(kDummyExecutionContext1, consumer.votes_[0].vote().context());
EXPECT_EQ(kDummyExecutionContext1, consumer.votes_[0].context());
EXPECT_EQ(base::TaskPriority::HIGHEST, consumer.votes_[0].vote().value());
EXPECT_EQ(kReason, consumer.votes_[0].vote().reason());
......@@ -195,8 +195,8 @@ TEST(ExecutionContextPriorityTest, VoteReceiptsWork) {
EXPECT_EQ(2u, voter.receipts_.size());
EXPECT_EQ(2u, consumer.votes_.size());
EXPECT_EQ(1u, consumer.valid_vote_count_);
EXPECT_EQ(kDummyExecutionContext1, consumer.votes_[0].vote().context());
EXPECT_EQ(kDummyExecutionContext2, consumer.votes_[1].vote().context());
EXPECT_EQ(kDummyExecutionContext1, consumer.votes_[0].context());
EXPECT_EQ(kDummyExecutionContext2, consumer.votes_[1].context());
ExpectNotEntangled(voter.receipts_[0], consumer.votes_[0]);
ExpectEntangled(voter.receipts_[1], consumer.votes_[1]);
......@@ -205,7 +205,7 @@ TEST(ExecutionContextPriorityTest, VoteReceiptsWork) {
EXPECT_EQ(2u, voter.receipts_.size());
EXPECT_EQ(1u, consumer.votes_.size());
EXPECT_EQ(1u, consumer.valid_vote_count_);
EXPECT_EQ(kDummyExecutionContext2, consumer.votes_[0].vote().context());
EXPECT_EQ(kDummyExecutionContext2, consumer.votes_[0].context());
EXPECT_FALSE(voter.receipts_[0].HasVote());
ExpectEntangled(voter.receipts_[1], consumer.votes_[0]);
......@@ -214,7 +214,7 @@ TEST(ExecutionContextPriorityTest, VoteReceiptsWork) {
EXPECT_EQ(1u, voter.receipts_.size());
EXPECT_EQ(1u, consumer.votes_.size());
EXPECT_EQ(1u, consumer.valid_vote_count_);
EXPECT_EQ(kDummyExecutionContext2, consumer.votes_[0].vote().context());
EXPECT_EQ(kDummyExecutionContext2, consumer.votes_[0].context());
ExpectEntangled(voter.receipts_[0], consumer.votes_[0]);
// Cancel the remaining vote by deleting the receipt.
......@@ -222,7 +222,7 @@ TEST(ExecutionContextPriorityTest, VoteReceiptsWork) {
EXPECT_EQ(0u, voter.receipts_.size());
EXPECT_EQ(1u, consumer.votes_.size());
EXPECT_EQ(0u, consumer.valid_vote_count_);
EXPECT_EQ(kDummyExecutionContext2, consumer.votes_[0].vote().context());
EXPECT_EQ(kDummyExecutionContext2, consumer.votes_[0].context());
EXPECT_FALSE(consumer.votes_[0].HasReceipt());
EXPECT_FALSE(consumer.votes_[0].IsValid());
}
......@@ -235,9 +235,9 @@ TEST(ExecutionContextPriorityTest, OverwriteVoteReceipt) {
consumer.voting_channel_factory_.BuildVotingChannel();
VoteReceipt receipt = voting_channel.SubmitVote(
Vote(kDummyExecutionContext1, base::TaskPriority::HIGHEST, kReason1));
kDummyExecutionContext1, Vote(base::TaskPriority::HIGHEST, kReason1));
receipt = voting_channel.SubmitVote(
Vote(kDummyExecutionContext2, base::TaskPriority::HIGHEST, kReason1));
kDummyExecutionContext2, Vote(base::TaskPriority::HIGHEST, kReason1));
// The first vote was invalidated because its vote receipt was cleaned up.
consumer.ExpectInvalidVote(0);
......
......@@ -33,9 +33,11 @@ void MaxVoteAggregator::SetUpstreamVotingChannel(VotingChannel&& channel) {
channel_ = std::move(channel);
}
VoteReceipt MaxVoteAggregator::SubmitVote(util::PassKey<VotingChannel>,
voting::VoterId<Vote> voter_id,
const Vote& vote) {
VoteReceipt MaxVoteAggregator::SubmitVote(
util::PassKey<VotingChannel>,
voting::VoterId<Vote> voter_id,
const ExecutionContext* execution_context,
const Vote& vote) {
DCHECK(vote.IsValid());
DCHECK(channel_.IsValid());
......@@ -44,8 +46,8 @@ VoteReceipt MaxVoteAggregator::SubmitVote(util::PassKey<VotingChannel>,
// be added.
// Add the new vote.
VoteData& vote_data = vote_data_map_[vote.context()];
auto accepted_vote = AcceptedVote(this, voter_id, vote);
VoteData& vote_data = vote_data_map_[execution_context];
auto accepted_vote = AcceptedVote(this, voter_id, execution_context, vote);
auto receipt = accepted_vote.IssueReceipt();
if (vote_data.AddVote(std::move(accepted_vote), next_vote_id_++))
vote_data.UpstreamVote(&channel_);
......@@ -100,7 +102,7 @@ MaxVoteAggregator::VoteDataMap::iterator MaxVoteAggregator::GetVoteData(
DCHECK(channel_.IsValid());
// Find the votes associated with this execution context.
auto it = vote_data_map_.find(vote->vote().context());
auto it = vote_data_map_.find(vote->context());
DCHECK(it != vote_data_map_.end());
return it;
}
......@@ -162,13 +164,14 @@ size_t MaxVoteAggregator::VoteData::GetVoteIndex(AcceptedVote* vote) {
void MaxVoteAggregator::VoteData::UpstreamVote(VotingChannel* channel) {
DCHECK_NE(0u, votes_.size());
DCHECK(votes_.top().vote.IsValid());
const ExecutionContext* execution_context = votes_.top().vote.context();
const Vote& vote = votes_.top().vote.vote();
// Change our existing vote, or create a new one as necessary.
if (receipt_.HasVote()) {
receipt_.ChangeVote(vote.value(), vote.reason());
} else {
receipt_ = channel->SubmitVote(vote);
receipt_ = channel->SubmitVote(execution_context, vote);
}
}
......
......@@ -136,8 +136,8 @@ TEST(MaxVoteAggregatorTest, VoteDataHeapStressTest) {
case kInsert: {
auto priority = RandPriority();
auto* reason = RandReason();
vd.AddVote(AcceptedVote(&consumer, voter_id,
Vote(kExecutionContext0, priority, reason)),
vd.AddVote(AcceptedVote(&consumer, voter_id, kExecutionContext0,
Vote(priority, reason)),
next_vote_id++);
} break;
......@@ -154,7 +154,7 @@ TEST(MaxVoteAggregatorTest, VoteDataHeapStressTest) {
}
// Update the vote.
vote.UpdateVote(Vote(vote.vote().context(), priority, reason));
vote.UpdateVote(Vote(priority, reason));
vd.UpdateVote(index, next_vote_id++);
} break;
......
......@@ -42,24 +42,28 @@ bool OverrideVoteAggregator::IsSetup() const {
channel_.IsValid();
}
VoteReceipt OverrideVoteAggregator::SubmitVote(util::PassKey<VotingChannel>,
voting::VoterId<Vote> voter_id,
const Vote& vote) {
VoteReceipt OverrideVoteAggregator::SubmitVote(
util::PassKey<VotingChannel>,
voting::VoterId<Vote> voter_id,
const ExecutionContext* execution_context,
const Vote& vote) {
DCHECK(vote.IsValid());
DCHECK(IsSetup());
VoteData& vote_data = vote_data_map_[vote.context()];
VoteData& vote_data = vote_data_map_[execution_context];
if (voter_id == override_voter_id_) {
DCHECK(!vote_data.override_vote.IsValid());
vote_data.override_vote = AcceptedVote(this, voter_id, vote);
UpstreamVote(vote, &vote_data);
vote_data.override_vote =
AcceptedVote(this, voter_id, execution_context, vote);
UpstreamVote(execution_context, vote, &vote_data);
return vote_data.override_vote.IssueReceipt();
} else {
DCHECK_EQ(default_voter_id_, voter_id);
DCHECK(!vote_data.default_vote.IsValid());
vote_data.default_vote = AcceptedVote(this, voter_id, vote);
vote_data.default_vote =
AcceptedVote(this, voter_id, execution_context, vote);
if (!vote_data.override_vote.IsValid())
UpstreamVote(vote, &vote_data);
UpstreamVote(execution_context, vote, &vote_data);
return vote_data.default_vote.IssueReceipt();
}
}
......@@ -78,7 +82,7 @@ void OverrideVoteAggregator::ChangeVote(util::PassKey<AcceptedVote>,
// (2) There is no override vote.
if (old_vote == &vote_data.override_vote ||
!vote_data.override_vote.IsValid()) {
UpstreamVote(new_vote, &vote_data);
UpstreamVote(old_vote->context(), new_vote, &vote_data);
}
}
......@@ -112,7 +116,7 @@ void OverrideVoteAggregator::VoteInvalidated(util::PassKey<AcceptedVote>,
// being invalidated, and the default is valid. In this case we need to
// upstream a new vote.
if (is_override_vote)
UpstreamVote(other->vote(), &vote_data);
UpstreamVote(other->context(), other->vote(), &vote_data);
}
OverrideVoteAggregator::VoteData::VoteData() = default;
......@@ -129,18 +133,20 @@ OverrideVoteAggregator::GetVoteData(AcceptedVote* vote) {
vote->voter_id() == default_voter_id_);
DCHECK(IsSetup());
auto it = vote_data_map_.find(vote->vote().context());
auto it = vote_data_map_.find(vote->context());
DCHECK(it != vote_data_map_.end());
return it;
}
void OverrideVoteAggregator::UpstreamVote(const Vote& vote,
VoteData* vote_data) {
void OverrideVoteAggregator::UpstreamVote(
const ExecutionContext* execution_context,
const Vote& vote,
VoteData* vote_data) {
// Change our existing vote, or create a new one as necessary.
if (vote_data->receipt.HasVote())
vote_data->receipt.ChangeVote(vote.value(), vote.reason());
else
vote_data->receipt = channel_.SubmitVote(vote);
vote_data->receipt = channel_.SubmitVote(execution_context, vote);
}
} // namespace execution_context_priority
......
......@@ -132,6 +132,7 @@ class BoostingVoteAggregator : public VoteConsumer {
// For modifying |incoming_|.
VoteReceipt SetIncomingVote(VoteConsumer* consumer,
voting::VoterId<Vote> voter_id,
const ExecutionContext* execution_context,
const Vote& vote);
void UpdateIncomingVote(const Vote& vote) { incoming_.UpdateVote(vote); }
......@@ -269,6 +270,7 @@ class BoostingVoteAggregator : public VoteConsumer {
// VoteConsumer implementation:
VoteReceipt SubmitVote(util::PassKey<VotingChannel>,
voting::VoterId<Vote> voter_id,
const ExecutionContext* execution_context,
const Vote& vote) override;
void ChangeVote(util::PassKey<AcceptedVote>,
AcceptedVote* old_vote,
......
......@@ -33,6 +33,7 @@ class MaxVoteAggregator : public VoteConsumer {
// VoteConsumer implementation:
VoteReceipt SubmitVote(util::PassKey<VotingChannel>,
voting::VoterId<Vote> voter_id,
const ExecutionContext* execution_context,
const Vote& vote) override;
void ChangeVote(util::PassKey<AcceptedVote>,
AcceptedVote* old_vote,
......
......@@ -34,6 +34,7 @@ class OverrideVoteAggregator : public VoteConsumer {
// VoteConsumer implementation:
VoteReceipt SubmitVote(util::PassKey<VotingChannel>,
voting::VoterId<Vote> voter_id,
const ExecutionContext* execution_context,
const Vote& vote) override;
void ChangeVote(util::PassKey<AcceptedVote>,
AcceptedVote* old_vote,
......@@ -69,7 +70,9 @@ class OverrideVoteAggregator : public VoteConsumer {
// Rebrands |vote| as belonging to this voter, and then sends it along to our
// |consumer_|. Stores the resulting receipt in |vote_data|.
void UpstreamVote(const Vote& vote, VoteData* vote_data);
void UpstreamVote(const ExecutionContext* execution_context,
const Vote& vote,
VoteData* vote_data);
// Our two input voters. We'll only accept votes from these voters otherwise
// we'll DCHECK.
......
......@@ -82,14 +82,13 @@ class Vote final {
Vote();
// NOTE: |reason| *must* be a static string.
Vote(const ContextType* context, VoteType vote, const char* reason);
Vote(VoteType vote, const char* reason);
Vote(const Vote& rhs);
Vote& operator=(const Vote& rhs);
~Vote();
const ContextType* context() const { return context_; }
VoteType value() const { return vote_; }
const char* reason() const { return reason_; }
......@@ -99,7 +98,6 @@ class Vote final {
bool IsValid() const;
private:
const ContextType* context_ = nullptr;
VoteType vote_ = DefaultVote;
const char* reason_ = nullptr;
};
......@@ -191,11 +189,13 @@ class VoteReceipt final {
template <class VoteImpl>
class AcceptedVote final {
public:
using ContextType = typename VoteImpl::ContextType;
using PassKey = util::PassKey<AcceptedVote<VoteImpl>>;
AcceptedVote();
AcceptedVote(VoteConsumer<VoteImpl>* consumer,
VoterId<VoteImpl> voter_id,
const ContextType* context,
const VoteImpl& vote);
AcceptedVote(const AcceptedVote& rhs) = delete;
AcceptedVote(AcceptedVote&& rhs);
......@@ -214,6 +214,7 @@ class AcceptedVote final {
VoteConsumer<VoteImpl>* consumer() const { return consumer_; }
VoterId<VoteImpl> voter_id() const { return voter_id_; }
const ContextType* context() const { return context_; }
const VoteImpl& vote() const { return vote_; }
// Allows an accepted vote to be updated in place.
......@@ -251,6 +252,8 @@ class AcceptedVote final {
// VoteConsumer.
VoterId<VoteImpl> voter_id_ = kInvalidVoterId<VoteImpl>;
const ContextType* context_ = nullptr;
// The vote that is being wrapped.
VoteImpl vote_;
......@@ -270,6 +273,7 @@ class VotingChannelFactory;
template <class VoteImpl>
class VotingChannel final {
public:
using ContextType = typename VoteImpl::ContextType;
using PassKey = util::PassKey<VotingChannel<VoteImpl>>;
VotingChannel();
......@@ -281,7 +285,8 @@ class VotingChannel final {
// Submits a vote through this voting channel. Can only be called if this
// VotingChannel is valid.
VoteReceipt<VoteImpl> SubmitVote(const VoteImpl& vote);
VoteReceipt<VoteImpl> SubmitVote(const ContextType* context,
const VoteImpl& vote);
// Returns true if this VotingChannel is valid.
bool IsValid() const;
......@@ -356,6 +361,8 @@ class VotingChannelFactory final {
template <class VoteImpl>
class VoteConsumer {
public:
using ContextType = typename VoteImpl::ContextType;
VoteConsumer();
virtual ~VoteConsumer();
VoteConsumer(const VoteConsumer& rhs) = delete;
......@@ -365,6 +372,7 @@ class VoteConsumer {
virtual VoteReceipt<VoteImpl> SubmitVote(
util::PassKey<VotingChannel<VoteImpl>>,
VoterId<VoteImpl> voter_id,
const ContextType* context,
const VoteImpl& vote) = 0;
// Used by an AcceptedVote to notify a consumer that a previously issued vote
......@@ -389,10 +397,9 @@ template <typename ContextType, typename VoteType, VoteType DefaultVote>
Vote<ContextType, VoteType, DefaultVote>::Vote() = default;
template <typename ContextType, typename VoteType, VoteType DefaultVote>
Vote<ContextType, VoteType, DefaultVote>::Vote(const ContextType* context,
VoteType vote,
Vote<ContextType, VoteType, DefaultVote>::Vote(VoteType vote,
const char* reason)
: context_(context), vote_(std::move(vote)), reason_(reason) {}
: vote_(std::move(vote)), reason_(reason) {}
template <typename ContextType, typename VoteType, VoteType DefaultVote>
Vote<ContextType, VoteType, DefaultVote>::Vote(const Vote& rhs) = default;
......@@ -410,8 +417,7 @@ bool Vote<ContextType, VoteType, DefaultVote>::operator==(
const Vote<ContextType, VoteType, DefaultVote>& vote) const {
DCHECK(reason_);
DCHECK(vote.reason_);
return context_ == vote.context_ && vote_ == vote.vote_ &&
::strcmp(reason_, vote.reason_) == 0;
return vote_ == vote.vote_ && ::strcmp(reason_, vote.reason_) == 0;
}
template <typename ContextType, typename VoteType, VoteType DefaultVote>
......@@ -422,7 +428,7 @@ bool Vote<ContextType, VoteType, DefaultVote>::operator!=(
template <typename ContextType, typename VoteType, VoteType DefaultVote>
bool Vote<ContextType, VoteType, DefaultVote>::IsValid() const {
return context_ && reason_;
return reason_;
}
/////////////////////////////////////////////////////////////////////
......@@ -542,14 +548,17 @@ AcceptedVote<VoteImpl>::AcceptedVote() = default;
template <class VoteImpl>
AcceptedVote<VoteImpl>::AcceptedVote(VoteConsumer<VoteImpl>* consumer,
VoterId<VoteImpl> voter_id,
const ContextType* context,
const VoteImpl& vote)
: consumer_(consumer),
voter_id_(voter_id),
context_(context),
vote_(vote),
invalidated_(false) {
DCHECK(consumer);
DCHECK_NE(kInvalidVoterId<VoteImpl>, voter_id_);
DCHECK(vote.IsValid());
DCHECK(consumer_);
DCHECK_NE(voter_id_, kInvalidVoterId<VoteImpl>);
DCHECK(context_);
DCHECK(vote_.IsValid());
}
template <class VoteImpl>
......@@ -596,7 +605,6 @@ VoteReceipt<VoteImpl> AcceptedVote<VoteImpl>::IssueReceipt() {
template <class VoteImpl>
void AcceptedVote<VoteImpl>::UpdateVote(const VoteImpl& vote) {
DCHECK_EQ(vote_.context(), vote.context());
DCHECK(vote_.value() != vote.value() || vote_.reason() != vote.reason());
vote_ = vote;
}
......@@ -635,12 +643,8 @@ void AcceptedVote<VoteImpl>::ChangeVote(util::PassKey<VoteReceipt<VoteImpl>>,
DCHECK(!invalidated_);
DCHECK(vote_.value() != vote || vote_.reason() != reason);
// Explicitly save a copy of |vote_| as the consumer might overwrite it
// directly.
VoteImpl old_vote = vote_;
// Notify the consumer of the new vote.
VoteImpl new_vote = VoteImpl(old_vote.context(), vote, reason);
VoteImpl new_vote = VoteImpl(vote, reason);
consumer_->ChangeVote(PassKey(), this, new_vote);
}
......@@ -667,6 +671,7 @@ void AcceptedVote<VoteImpl>::Take(AcceptedVote<VoteImpl>&& rhs) {
consumer_ = std::exchange(rhs.consumer_, nullptr);
voter_id_ = std::exchange(rhs.voter_id_, kInvalidVoterId<VoteImpl>);
context_ = std::exchange(rhs.context_, nullptr);
vote_ = std::exchange(rhs.vote_, VoteImpl());
receipt_ = std::exchange(rhs.receipt_, nullptr);
invalidated_ = std::exchange(rhs.invalidated_, true);
......@@ -701,10 +706,11 @@ VotingChannel<VoteImpl>::~VotingChannel() {
template <class VoteImpl>
VoteReceipt<VoteImpl> VotingChannel<VoteImpl>::SubmitVote(
const ContextType* context,
const VoteImpl& vote) {
// Pass the vote along to the consumer with the bound |voter_id_|.
return factory_->GetConsumer(PassKey())->SubmitVote(PassKey(), voter_id_,
vote);
context, vote);
}
template <class VoteImpl>
......
......@@ -21,6 +21,7 @@ namespace test {
template <class VoteImpl>
class DummyVoteConsumer : public VoteConsumer<VoteImpl> {
public:
using ContextType = typename VoteImpl::ContextType;
using AcceptedVote = AcceptedVote<VoteImpl>;
using VotingChannel = VotingChannel<VoteImpl>;
......@@ -32,6 +33,7 @@ class DummyVoteConsumer : public VoteConsumer<VoteImpl> {
// VoteConsumer implementation:
VoteReceipt<VoteImpl> SubmitVote(util::PassKey<VotingChannel>,
voting::VoterId<VoteImpl> voter_id,
const ContextType* context,
const VoteImpl& vote) override;
void ChangeVote(util::PassKey<AcceptedVote>,
AcceptedVote* old_vote,
......@@ -91,9 +93,10 @@ template <class VoteImpl>
VoteReceipt<VoteImpl> DummyVoteConsumer<VoteImpl>::SubmitVote(
util::PassKey<VotingChannel>,
voting::VoterId<VoteImpl> voter_id,
const ContextType* context,
const VoteImpl& vote) {
// Accept the vote.
votes_.emplace_back(AcceptedVote(this, voter_id, vote));
votes_.emplace_back(AcceptedVote(this, voter_id, context, vote));
EXPECT_FALSE(votes_.back().HasReceipt());
EXPECT_TRUE(votes_.back().IsValid());
++valid_vote_count_;
......@@ -151,8 +154,8 @@ void DummyVoteConsumer<VoteImpl>::ExpectValidVote(
EXPECT_EQ(this, accepted_vote.consumer());
EXPECT_TRUE(accepted_vote.IsValid());
EXPECT_EQ(voter_id, accepted_vote.voter_id());
EXPECT_EQ(context, accepted_vote.context());
const auto& vote = accepted_vote.vote();
EXPECT_EQ(context, vote.context());
EXPECT_EQ(vote_value, vote.value());
EXPECT_TRUE(vote.reason());
if (reason)
......@@ -180,7 +183,7 @@ void DummyVoter<VoteImpl>::EmitVote(
const char* reason) {
EXPECT_TRUE(voting_channel_.IsValid());
receipts_.emplace_back(
voting_channel_.SubmitVote(VoteImpl(context, vote_value, reason)));
voting_channel_.SubmitVote(context, VoteImpl(vote_value, reason)));
}
} // namespace test
......
......@@ -77,7 +77,7 @@ TEST(VotingTest, VoteReceiptsWork) {
EXPECT_EQ(1u, consumer.votes_.size());
EXPECT_EQ(1u, consumer.valid_vote_count_);
EXPECT_EQ(voter.voting_channel_.voter_id(), consumer.votes_[0].voter_id());
EXPECT_EQ(kDummyContext1, consumer.votes_[0].vote().context());
EXPECT_EQ(kDummyContext1, consumer.votes_[0].context());
EXPECT_TRUE(consumer.votes_[0].IsValid());
EXPECT_TRUE(IsEntangled(voter.receipts_[0], consumer.votes_[0]));
......@@ -105,19 +105,19 @@ TEST(VotingTest, VoteReceiptsWork) {
EXPECT_EQ(2u, voter.receipts_.size());
EXPECT_EQ(2u, consumer.votes_.size());
EXPECT_EQ(2u, consumer.valid_vote_count_);
EXPECT_EQ(kDummyContext1, consumer.votes_[0].vote().context());
EXPECT_EQ(kDummyContext2, consumer.votes_[1].vote().context());
EXPECT_EQ(kDummyContext1, consumer.votes_[0].context());
EXPECT_EQ(kDummyContext2, consumer.votes_[1].context());
EXPECT_TRUE(IsEntangled(voter.receipts_[0], consumer.votes_[0]));
EXPECT_TRUE(IsEntangled(voter.receipts_[1], consumer.votes_[1]));
// Change a vote, but making no change.
EXPECT_TRUE(IsEntangled(voter.receipts_[0], consumer.votes_[0]));
EXPECT_EQ(kDummyContext1, consumer.votes_[0].vote().context());
EXPECT_EQ(kDummyContext1, consumer.votes_[0].context());
EXPECT_EQ(0, consumer.votes_[0].vote().value());
EXPECT_EQ(DummyVoter::kReason, consumer.votes_[0].vote().reason());
voter.receipts_[0].ChangeVote(0, DummyVoter::kReason);
EXPECT_TRUE(IsEntangled(voter.receipts_[0], consumer.votes_[0]));
EXPECT_EQ(kDummyContext1, consumer.votes_[0].vote().context());
EXPECT_EQ(kDummyContext1, consumer.votes_[0].context());
EXPECT_EQ(0, consumer.votes_[0].vote().value());
EXPECT_EQ(DummyVoter::kReason, consumer.votes_[0].vote().reason());
......@@ -125,7 +125,7 @@ TEST(VotingTest, VoteReceiptsWork) {
static const char kReason[] = "another reason";
voter.receipts_[0].ChangeVote(5, kReason);
EXPECT_TRUE(IsEntangled(voter.receipts_[0], consumer.votes_[0]));
EXPECT_EQ(kDummyContext1, consumer.votes_[0].vote().context());
EXPECT_EQ(kDummyContext1, consumer.votes_[0].context());
EXPECT_EQ(5, consumer.votes_[0].vote().value());
EXPECT_EQ(kReason, consumer.votes_[0].vote().reason());
......@@ -134,8 +134,8 @@ TEST(VotingTest, VoteReceiptsWork) {
EXPECT_EQ(2u, voter.receipts_.size());
EXPECT_EQ(2u, consumer.votes_.size());
EXPECT_EQ(1u, consumer.valid_vote_count_);
EXPECT_EQ(kDummyContext1, consumer.votes_[0].vote().context());
EXPECT_EQ(kDummyContext2, consumer.votes_[1].vote().context());
EXPECT_EQ(kDummyContext1, consumer.votes_[0].context());
EXPECT_EQ(kDummyContext2, consumer.votes_[1].context());
EXPECT_TRUE(IsNotEntangled(voter.receipts_[0], consumer.votes_[0]));
EXPECT_TRUE(IsEntangled(voter.receipts_[1], consumer.votes_[1]));
......@@ -144,7 +144,7 @@ TEST(VotingTest, VoteReceiptsWork) {
EXPECT_EQ(2u, voter.receipts_.size());
EXPECT_EQ(1u, consumer.votes_.size());
EXPECT_EQ(1u, consumer.valid_vote_count_);
EXPECT_EQ(kDummyContext2, consumer.votes_[0].vote().context());
EXPECT_EQ(kDummyContext2, consumer.votes_[0].context());
EXPECT_FALSE(voter.receipts_[0].HasVote());
EXPECT_TRUE(IsEntangled(voter.receipts_[1], consumer.votes_[0]));
......@@ -153,7 +153,7 @@ TEST(VotingTest, VoteReceiptsWork) {
EXPECT_EQ(1u, voter.receipts_.size());
EXPECT_EQ(1u, consumer.votes_.size());
EXPECT_EQ(1u, consumer.valid_vote_count_);
EXPECT_EQ(kDummyContext2, consumer.votes_[0].vote().context());
EXPECT_EQ(kDummyContext2, consumer.votes_[0].context());
EXPECT_TRUE(IsEntangled(voter.receipts_[0], consumer.votes_[0]));
// Cancel the remaining vote by deleting the receipt.
......@@ -161,7 +161,7 @@ TEST(VotingTest, VoteReceiptsWork) {
EXPECT_EQ(0u, voter.receipts_.size());
EXPECT_EQ(1u, consumer.votes_.size());
EXPECT_EQ(0u, consumer.valid_vote_count_);
EXPECT_EQ(kDummyContext2, consumer.votes_[0].vote().context());
EXPECT_EQ(kDummyContext2, consumer.votes_[0].context());
EXPECT_FALSE(consumer.votes_[0].HasReceipt());
EXPECT_FALSE(consumer.votes_[0].IsValid());
}
......@@ -174,8 +174,8 @@ TEST(VotingTest, OverwriteVoteReceipt) {
consumer.voting_channel_factory_.BuildVotingChannel();
TestVoteReceipt receipt =
voting_channel.SubmitVote(TestVote(kDummyContext1, 5, kReason));
receipt = voting_channel.SubmitVote(TestVote(kDummyContext2, 5, kReason));
voting_channel.SubmitVote(kDummyContext1, TestVote(5, kReason));
receipt = voting_channel.SubmitVote(kDummyContext2, TestVote(5, kReason));
// The first vote was invalidated because its vote receipt was cleaned up.
consumer.ExpectInvalidVote(0);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment