freezing_vote_aggregator_unittest.cc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. // Copyright 2020 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "components/performance_manager/freezing/freezing_vote_aggregator.h"
  5. #include "base/rand_util.h"
  6. #include "components/performance_manager/test_support/voting.h"
  7. #include "testing/gtest/include/gtest/gtest.h"
  8. namespace performance_manager {
  9. namespace freezing {
  10. // Expose the FreezingVoteData type for testing.
  11. class FreezingVoteAggregatorTestAccess {
  12. public:
  13. using FreezingVoteData = FreezingVoteAggregator::FreezingVoteData;
  14. static const FreezingVoteData::VotesDeque& GetAllVotes(
  15. FreezingVoteAggregator* agg,
  16. const PageNode* node) {
  17. return agg->GetVoteData(node)->second.GetVotesForTesting();
  18. }
  19. };
  20. using VoteData = FreezingVoteAggregatorTestAccess::FreezingVoteData;
  21. namespace {
  22. using DummyFreezingVoteObserver = voting::test::DummyVoteObserver<FreezingVote>;
  23. // Some dummy page nodes.
  24. const PageNode* kPageNode0 = reinterpret_cast<const PageNode*>(0xDEADBEEF);
  25. const PageNode* kPageNode1 = reinterpret_cast<const PageNode*>(0xBAADF00D);
  26. static const FreezingVote kCannotFreezeVote0(FreezingVoteValue::kCannotFreeze,
  27. "cannot freeze 0");
  28. static const FreezingVote kCannotFreezeVote1(FreezingVoteValue::kCannotFreeze,
  29. "cannot freeze 1");
  30. static const FreezingVote kCannotFreezeVote2(FreezingVoteValue::kCannotFreeze,
  31. "cannot freeze 2");
  32. static const FreezingVote kCanFreezeVote0(FreezingVoteValue::kCanFreeze,
  33. "can freeze 0");
  34. static const FreezingVote kCanFreezeVote1(FreezingVoteValue::kCanFreeze,
  35. "can freeze 1");
  36. static const FreezingVote kCanFreezeVote2(FreezingVoteValue::kCanFreeze,
  37. "can freeze 2");
  38. static const FreezingVote kCanFreezeVote3(FreezingVoteValue::kCanFreeze,
  39. "can freeze 3");
  40. } // namespace
  41. class FreezingVoteAggregatorTest : public testing::Test {
  42. public:
  43. FreezingVoteAggregatorTest() = default;
  44. ~FreezingVoteAggregatorTest() override = default;
  45. void SetUp() override {
  46. FreezingVotingChannel channel = observer_.BuildVotingChannel();
  47. aggregator_voter_id_ = channel.voter_id();
  48. aggregator_.SetUpstreamVotingChannel(std::move(channel));
  49. }
  50. void TearDown() override {}
  51. FreezingVoterId aggregator_voter_id() const { return aggregator_voter_id_; }
  52. const DummyFreezingVoteObserver& observer() const { return observer_; }
  53. FreezingVoteAggregator* aggregator() { return &aggregator_; }
  54. private:
  55. DummyFreezingVoteObserver observer_;
  56. FreezingVoteAggregator aggregator_;
  57. FreezingVoterId aggregator_voter_id_;
  58. };
  59. TEST_F(FreezingVoteAggregatorTest, EndToEnd) {
  60. FreezingVotingChannel voter0 = aggregator()->GetVotingChannel();
  61. FreezingVotingChannel voter1 = aggregator()->GetVotingChannel();
  62. FreezingVotingChannel voter2 = aggregator()->GetVotingChannel();
  63. // Create some dummy votes for each PageNode and immediately expect
  64. // them to propagate upwards.
  65. voter0.SubmitVote(kPageNode0, kCannotFreezeVote0);
  66. voter0.SubmitVote(kPageNode1, kCanFreezeVote0);
  67. // Current state and expectations:
  68. // - kPageNode0: 1 x kCannotFreeze => kCannotFreeze
  69. // - kPageNode1: 1 x kCanFreeze => kCanFreeze
  70. EXPECT_EQ(2u, observer().GetVoteCount());
  71. EXPECT_TRUE(observer().HasVote(aggregator_voter_id(), kPageNode0,
  72. kCannotFreezeVote0));
  73. EXPECT_TRUE(
  74. observer().HasVote(aggregator_voter_id(), kPageNode1, kCanFreezeVote0));
  75. // Change an existing vote, and expect it to propagate upwards.
  76. voter0.ChangeVote(kPageNode0, kCanFreezeVote1);
  77. // Current state and expectations:
  78. // - kPageNode0: 1 x kCanFreeze => kCanFreeze
  79. // - kPageNode1: 1 x kCanFreeze => kCanFreeze
  80. EXPECT_EQ(2u, observer().GetVoteCount());
  81. EXPECT_TRUE(
  82. observer().HasVote(aggregator_voter_id(), kPageNode0, kCanFreezeVote1));
  83. EXPECT_TRUE(
  84. observer().HasVote(aggregator_voter_id(), kPageNode1, kCanFreezeVote0));
  85. // Submit a new kCanFreeze vote for page 1 and expect no change.
  86. voter1.SubmitVote(kPageNode1, kCanFreezeVote2);
  87. // Current state and expectations:
  88. // - kPageNode0: 1 x kCanFreeze => kCanFreeze
  89. // - kPageNode1: 2 x kCanFreeze => kCanFreeze
  90. EXPECT_EQ(2u, observer().GetVoteCount());
  91. EXPECT_TRUE(
  92. observer().HasVote(aggregator_voter_id(), kPageNode0, kCanFreezeVote1));
  93. EXPECT_TRUE(
  94. observer().HasVote(aggregator_voter_id(), kPageNode1, kCanFreezeVote0));
  95. // Submit a new vote with a different value and expect it to propagate
  96. // upwards.
  97. voter2.SubmitVote(kPageNode1, kCannotFreezeVote0);
  98. // Current state and expectations:
  99. // - kPageNode0: 1 x kCanFreeze => kCanFreeze
  100. // - kPageNode1: 2 x kCanFreeze + 1 x kCannotFreeze => kCannotFreeze
  101. EXPECT_EQ(2u, observer().GetVoteCount());
  102. EXPECT_TRUE(
  103. observer().HasVote(aggregator_voter_id(), kPageNode0, kCanFreezeVote1));
  104. EXPECT_TRUE(observer().HasVote(aggregator_voter_id(), kPageNode1,
  105. kCannotFreezeVote0));
  106. // Invalidate the only kCannotFreeze vote for a given PageNode and expect it
  107. // to propagate upwards.
  108. voter2.InvalidateVote(kPageNode1);
  109. // Current state and expectations:
  110. // - kPageNode0: 1 x kCanFreeze => kCanFreeze
  111. // - kPageNode1: 2 x kCanFreeze => kCanFreeze
  112. EXPECT_EQ(2u, observer().GetVoteCount());
  113. EXPECT_TRUE(
  114. observer().HasVote(aggregator_voter_id(), kPageNode0, kCanFreezeVote1));
  115. EXPECT_TRUE(
  116. observer().HasVote(aggregator_voter_id(), kPageNode1, kCanFreezeVote0));
  117. // Invalidate the remaining vote for kPageNode1.
  118. voter0.InvalidateVote(kPageNode1);
  119. voter1.InvalidateVote(kPageNode1);
  120. // Current state and expectations:
  121. // - kPageNode0: 1 x kCanFreeze => kCanFreeze
  122. // - kPageNode1: No vote => Invalidated
  123. EXPECT_EQ(1u, observer().GetVoteCount());
  124. EXPECT_TRUE(
  125. observer().HasVote(aggregator_voter_id(), kPageNode0, kCanFreezeVote1));
  126. EXPECT_FALSE(observer().HasVote(aggregator_voter_id(), kPageNode1));
  127. // Emit a new vote for the PageNode that had no remaining vote
  128. voter0.SubmitVote(kPageNode1, kCannotFreezeVote1);
  129. // Current state and expectations:
  130. // - kPageNode0: 1 x kCanFreeze => kCanFreeze
  131. // - kPageNode1: 1 x kCanFreeze => kCannotFreeze
  132. EXPECT_EQ(2u, observer().GetVoteCount());
  133. EXPECT_TRUE(
  134. observer().HasVote(aggregator_voter_id(), kPageNode0, kCanFreezeVote1));
  135. EXPECT_TRUE(observer().HasVote(aggregator_voter_id(), kPageNode1,
  136. kCannotFreezeVote1));
  137. // Clear the votes.
  138. voter0.InvalidateVote(kPageNode0);
  139. voter0.InvalidateVote(kPageNode1);
  140. }
  141. TEST_F(FreezingVoteAggregatorTest, VoteIntegrity) {
  142. FreezingVotingChannel voter0 = aggregator()->GetVotingChannel();
  143. FreezingVotingChannel voter1 = aggregator()->GetVotingChannel();
  144. // Submit a first vote, this should be the only vote tracked by the
  145. // aggregator.
  146. voter0.SubmitVote(kPageNode0, kCanFreezeVote0);
  147. EXPECT_EQ(1u, FreezingVoteAggregatorTestAccess::GetAllVotes(aggregator(),
  148. kPageNode0)
  149. .size());
  150. EXPECT_EQ(kCanFreezeVote0, FreezingVoteAggregatorTestAccess::GetAllVotes(
  151. aggregator(), kPageNode0)
  152. .front()
  153. .second);
  154. EXPECT_TRUE(
  155. observer().HasVote(aggregator_voter_id(), kPageNode0, kCanFreezeVote0));
  156. // Emit a second vote that should be ordered before the previous one, ensure
  157. // that this is the case.
  158. voter1.SubmitVote(kPageNode0, kCannotFreezeVote0);
  159. EXPECT_EQ(2u, FreezingVoteAggregatorTestAccess::GetAllVotes(aggregator(),
  160. kPageNode0)
  161. .size());
  162. EXPECT_EQ(kCannotFreezeVote0, FreezingVoteAggregatorTestAccess::GetAllVotes(
  163. aggregator(), kPageNode0)
  164. .front()
  165. .second);
  166. EXPECT_EQ(kCanFreezeVote0, FreezingVoteAggregatorTestAccess::GetAllVotes(
  167. aggregator(), kPageNode0)
  168. .back()
  169. .second);
  170. EXPECT_TRUE(observer().HasVote(aggregator_voter_id(), kPageNode0,
  171. kCannotFreezeVote0));
  172. // Removing the second vote should restore things back to the state they were
  173. // before casting it.
  174. voter1.InvalidateVote(kPageNode0);
  175. EXPECT_EQ(1u, FreezingVoteAggregatorTestAccess::GetAllVotes(aggregator(),
  176. kPageNode0)
  177. .size());
  178. EXPECT_EQ(kCanFreezeVote0, FreezingVoteAggregatorTestAccess::GetAllVotes(
  179. aggregator(), kPageNode0)
  180. .front()
  181. .second);
  182. EXPECT_TRUE(
  183. observer().HasVote(aggregator_voter_id(), kPageNode0, kCanFreezeVote0));
  184. // Removing the last vote should cause the upstreamed vote to be invalidated.
  185. voter0.InvalidateVote(kPageNode0);
  186. EXPECT_FALSE(observer().HasVote(aggregator_voter_id(), kPageNode0));
  187. }
  188. // Tests that submitting a second vote with the same value as the first one does
  189. // not change the upstreamed vote.
  190. TEST_F(FreezingVoteAggregatorTest, VoteConsistency) {
  191. FreezingVotingChannel voter0 = aggregator()->GetVotingChannel();
  192. FreezingVotingChannel voter1 = aggregator()->GetVotingChannel();
  193. // Submit a first vote.
  194. voter0.SubmitVote(kPageNode0, kCanFreezeVote0);
  195. EXPECT_TRUE(
  196. observer().HasVote(aggregator_voter_id(), kPageNode0, kCanFreezeVote0));
  197. // Emit a second vote with the same value but a different reason so that they
  198. // can be differentiated. The upstreamed vote should be the same.
  199. voter1.SubmitVote(kPageNode0, kCanFreezeVote1);
  200. EXPECT_TRUE(
  201. observer().HasVote(aggregator_voter_id(), kPageNode0, kCanFreezeVote0));
  202. // Clear the votes.
  203. voter0.InvalidateVote(kPageNode0);
  204. voter1.InvalidateVote(kPageNode0);
  205. // Do the same with kCannotFreeze votes.
  206. // Submit a first vote.
  207. voter0.SubmitVote(kPageNode0, kCannotFreezeVote0);
  208. EXPECT_TRUE(observer().HasVote(aggregator_voter_id(), kPageNode0,
  209. kCannotFreezeVote0));
  210. // Emit a second vote with the same value but a different reason so that they
  211. // can be differentiated. The upstreamed vote should be the same.
  212. voter1.SubmitVote(kPageNode0, kCannotFreezeVote1);
  213. EXPECT_TRUE(observer().HasVote(aggregator_voter_id(), kPageNode0,
  214. kCannotFreezeVote0));
  215. // Clear the votes.
  216. voter0.InvalidateVote(kPageNode0);
  217. voter1.InvalidateVote(kPageNode0);
  218. }
  219. } // namespace freezing
  220. } // namespace performance_manager