Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(237)

Side by Side Diff: components/certificate_transparency/log_dns_client_unittest.cc

Issue 2380293002: Adds LogDnsClient::NotifyWhenNotThrottled (Closed)
Patch Set: Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/certificate_transparency/log_dns_client.h" 5 #include "components/certificate_transparency/log_dns_client.h"
6 6
7 #include <memory> 7 #include <memory>
8 #include <string> 8 #include <string>
9 #include <utility> 9 #include <utility>
10 #include <vector> 10 #include <vector>
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
83 // Each node is 32 bytes, with each byte having a different value. 83 // Each node is 32 bytes, with each byte having a different value.
84 for (size_t j = 0; j < crypto::kSHA256Length; ++j) { 84 for (size_t j = 0; j < crypto::kSHA256Length; ++j) {
85 node[j] = static_cast<char>((-127 + i + j) % 128); 85 node[j] = static_cast<char>((-127 + i + j) % 128);
86 } 86 }
87 audit_proof[i].assign(std::move(node)); 87 audit_proof[i].assign(std::move(node));
88 } 88 }
89 89
90 return audit_proof; 90 return audit_proof;
91 } 91 }
92 92
93 // MockAuditProofCallback can be used as an AuditProofCallback. 93 // MockCallback can be used as a base::Callback.
94 // It will record the arguments it is invoked with and provides a helpful 94 // It will record the arguments it is invoked with, which can be examined by
95 // method for pumping the message loop until it is invoked. 95 // calling args() or arg<N>().
96 class MockAuditProofCallback { 96 // It only expects to be called once, but can be reused by calling Reset().
97 // Example:
98 // MockCallback<int> mock;
99 // foo.RegisterCallback(mock.AsCallback());
100 // foo.DoSomething();
101 // mock.WaitUntilRun(TestTimeouts::action_max_timeout());
102 // ASSERT_TRUE(mock.called());
103 // ASSERT_EQ(123, mock.arg<0>());
104 template <typename... Args>
105 class MockCallback {
97 public: 106 public:
98 MockAuditProofCallback() : called_(false) {} 107 MockCallback() : called_(false) {}
99 108
109 // Returns true if the callback has been invoked.
100 bool called() const { return called_; } 110 bool called() const { return called_; }
101 net::Error result() const { return result_; }
102 const net::ct::MerkleAuditProof* proof() const { return proof_.get(); }
103 111
104 // Get this callback as an AuditProofCallback. 112 // The arguments that the callback was called with.
105 LogDnsClient::AuditProofCallback AsCallback() { 113 const std::tuple<Args...>& args() const {
106 return base::Bind(&MockAuditProofCallback::Run, base::Unretained(this)); 114 DCHECK(called_);
115 return args_;
116 }
117
118 // Gets a particular argument that the callback was invoked with.
119 // For example, to get the first argument: mock_callback.arg<0>();
120 template <size_t N>
121 const typename std::tuple_element<N, std::tuple<Args...>>::type& arg() const {
122 DCHECK(called_);
123 return std::get<N>(args_);
124 }
125
126 // Convert to a base::Callback.
127 // TODO(robpercival): Could this reasonably be an implicit conversion?
128 base::Callback<void(Args...)> AsCallback() {
129 return base::Bind(&MockCallback::Run, base::Unretained(this));
107 } 130 }
108 131
109 // Wait until either the callback is invoked or the message loop goes idle 132 // Wait until either the callback is invoked or the message loop goes idle
110 // (after a specified |timeout|). Returns immediately if the callback has 133 // (after a specified |timeout|). Returns immediately if the callback has
111 // already been invoked. 134 // already been invoked.
112 void WaitUntilRun(base::TimeDelta timeout) { 135 void WaitUntilRun(base::TimeDelta timeout) {
113 if (called_) { 136 if (called_) {
114 return; 137 return;
115 } 138 }
116 139
117 // Pump the message loop until the the callback is invoked, which quits the 140 // Pump the message loop until the the callback is invoked, which quits the
118 // RunLoop, or a timeout expires and the message loop goes idle. 141 // RunLoop, or a timeout expires and the message loop goes idle.
119 run_loop_.reset(new base::RunLoop()); 142 run_loop_.reset(new base::RunLoop());
120 base::Closure quit_closure = run_loop_->QuitWhenIdleClosure(); 143 base::Closure quit_closure = run_loop_->QuitWhenIdleClosure();
121 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(FROM_HERE, 144 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(FROM_HERE,
122 quit_closure, timeout); 145 quit_closure, timeout);
123 run_loop_->Run(); 146 run_loop_->Run();
124 run_loop_.reset(); 147 run_loop_.reset();
125 } 148 }
126 149
150 void Reset() {
151 called_ = false;
152 args_ = std::tuple<Args...>();
153 }
154
127 private: 155 private:
128 void Run(net::Error result, 156 void Run(Args... args) {
129 std::unique_ptr<net::ct::MerkleAuditProof> proof) { 157 EXPECT_TRUE(!called_) << "Callback invoked more than once";
130 EXPECT_FALSE(called_) << "Callback invoked more than once";
131 called_ = true; 158 called_ = true;
132 result_ = result; 159 args_ = std::make_tuple(std::forward<Args>(args)...);
133 proof_ = std::move(proof);
134 if (run_loop_) { 160 if (run_loop_) {
135 run_loop_->Quit(); 161 run_loop_->Quit();
136 } 162 }
137 } 163 }
138 164
139 // True if the callback has been invoked. 165 // True if the callback has been invoked.
140 bool called_; 166 bool called_;
141 // The arguments that the callback was invoked with. 167 // The arguments that the callback was invoked with.
142 net::Error result_; 168 std::tuple<Args...> args_;
143 std::unique_ptr<net::ct::MerkleAuditProof> proof_;
144 // The RunLoop currently being used to pump the message loop, as a means to 169 // The RunLoop currently being used to pump the message loop, as a means to
145 // execute this callback. 170 // execute this callback.
146 std::unique_ptr<base::RunLoop> run_loop_; 171 std::unique_ptr<base::RunLoop> run_loop_;
147 }; 172 };
148 173
174 class MockAuditProofCallback
175 : public MockCallback<net::Error,
176 std::unique_ptr<net::ct::MerkleAuditProof>> {
177 public:
178 net::Error result() const { return arg<0>(); }
179 const net::ct::MerkleAuditProof* proof() const { return arg<1>().get(); }
180 };
181
182 class MockNotThrottledCallback
183 : public MockCallback<base::WeakPtr<LogDnsClient>> {
184 public:
185 const base::WeakPtr<LogDnsClient>& log_dns_client() const { return arg<0>(); }
186 };
187
149 class LogDnsClientTest : public ::testing::TestWithParam<net::IoMode> { 188 class LogDnsClientTest : public ::testing::TestWithParam<net::IoMode> {
150 protected: 189 protected:
151 LogDnsClientTest() 190 LogDnsClientTest()
152 : network_change_notifier_(net::NetworkChangeNotifier::CreateMock()) { 191 : network_change_notifier_(net::NetworkChangeNotifier::CreateMock()) {
153 mock_dns_.SetSocketReadMode(GetParam()); 192 mock_dns_.SetSocketReadMode(GetParam());
154 mock_dns_.InitializeDnsConfig(); 193 mock_dns_.InitializeDnsConfig();
155 } 194 }
156 195
157 std::unique_ptr<LogDnsClient> CreateLogDnsClient( 196 std::unique_ptr<LogDnsClient> CreateLogDnsClient(
158 size_t kMaxConcurrentQueries) { 197 size_t kMaxConcurrentQueries) {
(...skipping 644 matching lines...) Expand 10 before | Expand all | Expand 10 after
803 callback3.WaitUntilRun(TestTimeouts::action_max_timeout()); 842 callback3.WaitUntilRun(TestTimeouts::action_max_timeout());
804 ASSERT_TRUE(callback3.called()); 843 ASSERT_TRUE(callback3.called());
805 EXPECT_THAT(callback3.result(), IsOk()); 844 EXPECT_THAT(callback3.result(), IsOk());
806 ASSERT_THAT(callback3.proof(), NotNull()); 845 ASSERT_THAT(callback3.proof(), NotNull());
807 EXPECT_THAT(callback3.proof()->leaf_index, Eq(666u)); 846 EXPECT_THAT(callback3.proof()->leaf_index, Eq(666u));
808 // TODO(robpercival): Enable this once MerkleAuditProof has tree_size. 847 // TODO(robpercival): Enable this once MerkleAuditProof has tree_size.
809 // EXPECT_THAT(callback3.proof()->tree_size, Eq(999999)); 848 // EXPECT_THAT(callback3.proof()->tree_size, Eq(999999));
810 EXPECT_THAT(callback3.proof()->nodes, Eq(audit_proof)); 849 EXPECT_THAT(callback3.proof()->nodes, Eq(audit_proof));
811 } 850 }
812 851
852 TEST_P(LogDnsClientTest, NotifiesWhenNoLongerThrottled) {
853 const std::vector<std::string> audit_proof = GetSampleAuditProof(20);
854
855 mock_dns_.ExpectLeafIndexRequestAndResponse(kLeafIndexQnames[0], "123456");
856 mock_dns_.ExpectAuditProofRequestAndResponse("0.123456.999999.tree.ct.test.",
857 audit_proof.begin(),
858 audit_proof.begin() + 7);
859 mock_dns_.ExpectAuditProofRequestAndResponse("7.123456.999999.tree.ct.test.",
860 audit_proof.begin() + 7,
861 audit_proof.begin() + 14);
862 mock_dns_.ExpectAuditProofRequestAndResponse("14.123456.999999.tree.ct.test.",
863 audit_proof.begin() + 14,
864 audit_proof.end());
865
866 const size_t kMaxConcurrentQueries = 1;
867 std::unique_ptr<LogDnsClient> log_client =
868 CreateLogDnsClient(kMaxConcurrentQueries);
869
870 // Start a query.
871 MockAuditProofCallback proof_callback1;
872 ASSERT_THAT(log_client->QueryAuditProof("ct.test", kLeafHashes[0], 999999,
873 proof_callback1.AsCallback()),
874 IsError(net::ERR_IO_PENDING));
875
876 MockNotThrottledCallback not_throttled_callback;
877 log_client->NotifyWhenNotThrottled(not_throttled_callback.AsCallback());
878
879 proof_callback1.WaitUntilRun(TestTimeouts::action_max_timeout());
880 ASSERT_TRUE(proof_callback1.called());
881
882 // The |not_throttled_callback| should not have fired quite yet, as the query
883 // only just completed. Wait a little longer and check that it does fire.
884 ASSERT_FALSE(not_throttled_callback.called());
885 not_throttled_callback.WaitUntilRun(TestTimeouts::action_max_timeout());
886 ASSERT_TRUE(not_throttled_callback.called());
887
888 // Start another query to check |not_throttled_callback| doesn't fire again.
889 not_throttled_callback.Reset();
890
891 mock_dns_.ExpectLeafIndexRequestAndResponse(kLeafIndexQnames[1], "666");
892 mock_dns_.ExpectAuditProofRequestAndResponse("0.666.999999.tree.ct.test.",
893 audit_proof.begin(),
894 audit_proof.begin() + 7);
895 mock_dns_.ExpectAuditProofRequestAndResponse("7.666.999999.tree.ct.test.",
896 audit_proof.begin() + 7,
897 audit_proof.begin() + 14);
898 mock_dns_.ExpectAuditProofRequestAndResponse("14.666.999999.tree.ct.test.",
899 audit_proof.begin() + 14,
900 audit_proof.end());
901
902 MockAuditProofCallback proof_callback2;
903 ASSERT_THAT(log_client->QueryAuditProof("ct.test", kLeafHashes[1], 999999,
904 proof_callback2.AsCallback()),
905 IsError(net::ERR_IO_PENDING));
906
907 // Give the query a chance to run.
908 proof_callback2.WaitUntilRun(TestTimeouts::action_max_timeout());
909
910 ASSERT_TRUE(proof_callback2.called());
911 ASSERT_FALSE(not_throttled_callback.called());
912 }
913
813 INSTANTIATE_TEST_CASE_P(ReadMode, 914 INSTANTIATE_TEST_CASE_P(ReadMode,
814 LogDnsClientTest, 915 LogDnsClientTest,
815 ::testing::Values(net::IoMode::ASYNC, 916 ::testing::Values(net::IoMode::ASYNC,
816 net::IoMode::SYNCHRONOUS)); 917 net::IoMode::SYNCHRONOUS));
817 918
818 } // namespace 919 } // namespace
819 } // namespace certificate_transparency 920 } // namespace certificate_transparency
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698