1 // Copyright 2017 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/nqe/socket_watcher.h"
6
7 #include "base/functional/bind.h"
8 #include "base/run_loop.h"
9 #include "base/task/single_thread_task_runner.h"
10 #include "base/test/simple_test_tick_clock.h"
11 #include "base/time/time.h"
12 #include "build/build_config.h"
13 #include "net/base/ip_address.h"
14 #include "net/socket/socket_performance_watcher_factory.h"
15 #include "net/test/test_with_task_environment.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17
18 namespace net::nqe::internal {
19
20 namespace {
21
22 class NetworkQualitySocketWatcherTest : public TestWithTaskEnvironment {
23 public:
24 NetworkQualitySocketWatcherTest(const NetworkQualitySocketWatcherTest&) =
25 delete;
26 NetworkQualitySocketWatcherTest& operator=(
27 const NetworkQualitySocketWatcherTest&) = delete;
28
29 protected:
NetworkQualitySocketWatcherTest()30 NetworkQualitySocketWatcherTest() { ResetExpectedCallbackParams(); }
~NetworkQualitySocketWatcherTest()31 ~NetworkQualitySocketWatcherTest() override { ResetExpectedCallbackParams(); }
32
OnUpdatedRTTAvailableStoreParams(SocketPerformanceWatcherFactory::Protocol protocol,const base::TimeDelta & rtt,const std::optional<IPHash> & host)33 static void OnUpdatedRTTAvailableStoreParams(
34 SocketPerformanceWatcherFactory::Protocol protocol,
35 const base::TimeDelta& rtt,
36 const std::optional<IPHash>& host) {
37 // Need to verify before another callback is executed, or explicitly call
38 // |ResetCallbackParams()|.
39 ASSERT_FALSE(callback_executed_);
40 callback_rtt_ = rtt;
41 callback_host_ = host;
42 callback_executed_ = true;
43 }
44
OnUpdatedRTTAvailable(SocketPerformanceWatcherFactory::Protocol protocol,const base::TimeDelta & rtt,const std::optional<IPHash> & host)45 static void OnUpdatedRTTAvailable(
46 SocketPerformanceWatcherFactory::Protocol protocol,
47 const base::TimeDelta& rtt,
48 const std::optional<IPHash>& host) {
49 // Need to verify before another callback is executed, or explicitly call
50 // |ResetCallbackParams()|.
51 ASSERT_FALSE(callback_executed_);
52 callback_executed_ = true;
53 }
54
SetShouldNotifyRTTCallback(bool value)55 static void SetShouldNotifyRTTCallback(bool value) {
56 should_notify_rtt_callback_ = value;
57 }
58
ShouldNotifyRTTCallback(base::TimeTicks now)59 static bool ShouldNotifyRTTCallback(base::TimeTicks now) {
60 return should_notify_rtt_callback_;
61 }
62
VerifyCallbackParams(const base::TimeDelta & rtt,const std::optional<IPHash> & host)63 static void VerifyCallbackParams(const base::TimeDelta& rtt,
64 const std::optional<IPHash>& host) {
65 ASSERT_TRUE(callback_executed_);
66 EXPECT_EQ(rtt, callback_rtt_);
67 if (host)
68 EXPECT_EQ(host, callback_host_);
69 else
70 EXPECT_FALSE(callback_host_.has_value());
71 ResetExpectedCallbackParams();
72 }
73
ResetExpectedCallbackParams()74 static void ResetExpectedCallbackParams() {
75 callback_rtt_ = base::Milliseconds(0);
76 callback_host_ = std::nullopt;
77 callback_executed_ = false;
78 should_notify_rtt_callback_ = false;
79 }
80
callback_rtt()81 static base::TimeDelta callback_rtt() { return callback_rtt_; }
82
83 private:
84 static base::TimeDelta callback_rtt_;
85 static std::optional<IPHash> callback_host_;
86 static bool callback_executed_;
87 static bool should_notify_rtt_callback_;
88 };
89
90 base::TimeDelta NetworkQualitySocketWatcherTest::callback_rtt_ =
91 base::Milliseconds(0);
92
93 std::optional<IPHash> NetworkQualitySocketWatcherTest::callback_host_ =
94 std::nullopt;
95
96 bool NetworkQualitySocketWatcherTest::callback_executed_ = false;
97
98 bool NetworkQualitySocketWatcherTest::should_notify_rtt_callback_ = false;
99
100 // Verify that the buffer size is never exceeded.
TEST_F(NetworkQualitySocketWatcherTest,NotificationsThrottled)101 TEST_F(NetworkQualitySocketWatcherTest, NotificationsThrottled) {
102 base::SimpleTestTickClock tick_clock;
103 tick_clock.SetNowTicks(base::TimeTicks::Now());
104
105 // Use a public IP address so that the socket watcher runs the RTT callback.
106 IPAddress ip_address;
107 ASSERT_TRUE(ip_address.AssignFromIPLiteral("157.0.0.1"));
108
109 SocketWatcher socket_watcher(
110 SocketPerformanceWatcherFactory::PROTOCOL_TCP, ip_address,
111 base::Milliseconds(2000), false,
112 base::SingleThreadTaskRunner::GetCurrentDefault(),
113 base::BindRepeating(OnUpdatedRTTAvailable),
114 base::BindRepeating(ShouldNotifyRTTCallback), &tick_clock);
115
116 EXPECT_TRUE(socket_watcher.ShouldNotifyUpdatedRTT());
117 socket_watcher.OnUpdatedRTTAvailable(base::Seconds(10));
118 base::RunLoop().RunUntilIdle();
119 ResetExpectedCallbackParams();
120
121 EXPECT_FALSE(socket_watcher.ShouldNotifyUpdatedRTT());
122
123 tick_clock.Advance(base::Milliseconds(1000));
124 // Minimum interval between consecutive notifications is 2000 msec.
125 EXPECT_FALSE(socket_watcher.ShouldNotifyUpdatedRTT());
126
127 // Advance the clock by 1000 msec more so that the current time is at least
128 // 2000 msec more than the last time |socket_watcher| received a notification.
129 tick_clock.Advance(base::Milliseconds(1000));
130 EXPECT_TRUE(socket_watcher.ShouldNotifyUpdatedRTT());
131 ResetExpectedCallbackParams();
132 socket_watcher.OnUpdatedRTTAvailable(base::Seconds(10));
133
134 EXPECT_FALSE(socket_watcher.ShouldNotifyUpdatedRTT());
135
136 // RTT notification is allowed by the global check.
137 SetShouldNotifyRTTCallback(true);
138 EXPECT_TRUE(socket_watcher.ShouldNotifyUpdatedRTT());
139 }
140
TEST_F(NetworkQualitySocketWatcherTest,QuicFirstNotificationDropped)141 TEST_F(NetworkQualitySocketWatcherTest, QuicFirstNotificationDropped) {
142 base::SimpleTestTickClock tick_clock;
143 tick_clock.SetNowTicks(base::TimeTicks::Now());
144
145 // Use a public IP address so that the socket watcher runs the RTT callback.
146 IPAddress ip_address;
147 ASSERT_TRUE(ip_address.AssignFromIPLiteral("157.0.0.1"));
148
149 SocketWatcher socket_watcher(
150 SocketPerformanceWatcherFactory::PROTOCOL_QUIC, ip_address,
151 base::Milliseconds(2000), false,
152 base::SingleThreadTaskRunner::GetCurrentDefault(),
153 base::BindRepeating(OnUpdatedRTTAvailableStoreParams),
154 base::BindRepeating(ShouldNotifyRTTCallback), &tick_clock);
155
156 EXPECT_TRUE(socket_watcher.ShouldNotifyUpdatedRTT());
157 socket_watcher.OnUpdatedRTTAvailable(base::Seconds(10));
158 base::RunLoop().RunUntilIdle();
159 // First notification from a QUIC connection should be dropped, and it should
160 // be possible to notify the |socket_watcher| again.
161 EXPECT_TRUE(NetworkQualitySocketWatcherTest::callback_rtt().is_zero());
162 EXPECT_TRUE(socket_watcher.ShouldNotifyUpdatedRTT());
163 ResetExpectedCallbackParams();
164
165 socket_watcher.OnUpdatedRTTAvailable(base::Seconds(2));
166 base::RunLoop().RunUntilIdle();
167 EXPECT_EQ(base::Seconds(2), NetworkQualitySocketWatcherTest::callback_rtt());
168 ResetExpectedCallbackParams();
169
170 EXPECT_FALSE(socket_watcher.ShouldNotifyUpdatedRTT());
171
172 tick_clock.Advance(base::Milliseconds(1000));
173 // Minimum interval between consecutive notifications is 2000 msec.
174 EXPECT_FALSE(socket_watcher.ShouldNotifyUpdatedRTT());
175
176 // Advance the clock by 1000 msec more so that the current time is at least
177 // 2000 msec more than the last time |socket_watcher| received a notification.
178 tick_clock.Advance(base::Milliseconds(1000));
179 EXPECT_TRUE(socket_watcher.ShouldNotifyUpdatedRTT());
180 }
181
182 #if BUILDFLAG(IS_IOS)
183 // Flaky on iOS: crbug.com/672917.
184 #define MAYBE_PrivateAddressRTTNotNotified DISABLED_PrivateAddressRTTNotNotified
185 #else
186 #define MAYBE_PrivateAddressRTTNotNotified PrivateAddressRTTNotNotified
187 #endif
TEST_F(NetworkQualitySocketWatcherTest,MAYBE_PrivateAddressRTTNotNotified)188 TEST_F(NetworkQualitySocketWatcherTest, MAYBE_PrivateAddressRTTNotNotified) {
189 base::SimpleTestTickClock tick_clock;
190 tick_clock.SetNowTicks(base::TimeTicks::Now());
191
192 const struct {
193 std::string ip_address;
194 bool expect_should_notify_rtt;
195 } tests[] = {
196 {"157.0.0.1", true}, {"127.0.0.1", false},
197 {"192.168.0.1", false}, {"::1", false},
198 {"0.0.0.0", false}, {"2607:f8b0:4006:819::200e", true},
199 };
200
201 for (const auto& test : tests) {
202 IPAddress ip_address;
203 ASSERT_TRUE(ip_address.AssignFromIPLiteral(test.ip_address));
204
205 SocketWatcher socket_watcher(
206 SocketPerformanceWatcherFactory::PROTOCOL_TCP, ip_address,
207 base::Milliseconds(2000), false,
208 base::SingleThreadTaskRunner::GetCurrentDefault(),
209 base::BindRepeating(OnUpdatedRTTAvailable),
210 base::BindRepeating(ShouldNotifyRTTCallback), &tick_clock);
211
212 EXPECT_EQ(test.expect_should_notify_rtt,
213 socket_watcher.ShouldNotifyUpdatedRTT());
214 socket_watcher.OnUpdatedRTTAvailable(base::Seconds(10));
215 base::RunLoop().RunUntilIdle();
216 ResetExpectedCallbackParams();
217
218 EXPECT_FALSE(socket_watcher.ShouldNotifyUpdatedRTT());
219 }
220 }
221
TEST_F(NetworkQualitySocketWatcherTest,RemoteHostIPHashComputedCorrectly)222 TEST_F(NetworkQualitySocketWatcherTest, RemoteHostIPHashComputedCorrectly) {
223 base::SimpleTestTickClock tick_clock;
224 tick_clock.SetNowTicks(base::TimeTicks::Now());
225 const struct {
226 std::string ip_address;
227 uint64_t host;
228 } tests[] = {
229 {"112.112.112.100", 0x0000000070707064UL}, // IPv4.
230 {"112.112.112.250", 0x00000000707070faUL},
231 {"2001:0db8:85a3:0000:0000:8a2e:0370:7334",
232 0x20010db885a30000UL}, // IPv6.
233 {"2001:db8:85a3::8a2e:370:7334", 0x20010db885a30000UL} // Shortened IPv6.
234 };
235
236 for (const auto& test : tests) {
237 IPAddress ip_address;
238 ASSERT_TRUE(ip_address.AssignFromIPLiteral(test.ip_address));
239
240 SocketWatcher socket_watcher(
241 SocketPerformanceWatcherFactory::PROTOCOL_TCP, ip_address,
242 base::Milliseconds(2000), false,
243 base::SingleThreadTaskRunner::GetCurrentDefault(),
244 base::BindRepeating(OnUpdatedRTTAvailableStoreParams),
245 base::BindRepeating(ShouldNotifyRTTCallback), &tick_clock);
246 EXPECT_TRUE(socket_watcher.ShouldNotifyUpdatedRTT());
247 socket_watcher.OnUpdatedRTTAvailable(base::Seconds(10));
248 base::RunLoop().RunUntilIdle();
249 VerifyCallbackParams(base::Seconds(10), test.host);
250 EXPECT_FALSE(socket_watcher.ShouldNotifyUpdatedRTT());
251 }
252 }
253
254 } // namespace
255
256 } // namespace net::nqe::internal
257