xref: /aosp_15_r20/external/webrtc/video/call_stats2_unittest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker  *  Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker  *
4*d9f75844SAndroid Build Coastguard Worker  *  Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker  *  that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker  *  tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker  *  in the file PATENTS.  All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker  *  be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker  */
10*d9f75844SAndroid Build Coastguard Worker 
11*d9f75844SAndroid Build Coastguard Worker #include "video/call_stats2.h"
12*d9f75844SAndroid Build Coastguard Worker 
13*d9f75844SAndroid Build Coastguard Worker #include <memory>
14*d9f75844SAndroid Build Coastguard Worker 
15*d9f75844SAndroid Build Coastguard Worker #include "api/task_queue/default_task_queue_factory.h"
16*d9f75844SAndroid Build Coastguard Worker #include "api/task_queue/task_queue_base.h"
17*d9f75844SAndroid Build Coastguard Worker #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
18*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/thread.h"
19*d9f75844SAndroid Build Coastguard Worker #include "system_wrappers/include/metrics.h"
20*d9f75844SAndroid Build Coastguard Worker #include "test/gmock.h"
21*d9f75844SAndroid Build Coastguard Worker #include "test/gtest.h"
22*d9f75844SAndroid Build Coastguard Worker #include "test/run_loop.h"
23*d9f75844SAndroid Build Coastguard Worker 
24*d9f75844SAndroid Build Coastguard Worker using ::testing::AnyNumber;
25*d9f75844SAndroid Build Coastguard Worker using ::testing::InvokeWithoutArgs;
26*d9f75844SAndroid Build Coastguard Worker using ::testing::Return;
27*d9f75844SAndroid Build Coastguard Worker 
28*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
29*d9f75844SAndroid Build Coastguard Worker namespace internal {
30*d9f75844SAndroid Build Coastguard Worker 
31*d9f75844SAndroid Build Coastguard Worker class MockStatsObserver : public CallStatsObserver {
32*d9f75844SAndroid Build Coastguard Worker  public:
MockStatsObserver()33*d9f75844SAndroid Build Coastguard Worker   MockStatsObserver() {}
~MockStatsObserver()34*d9f75844SAndroid Build Coastguard Worker   virtual ~MockStatsObserver() {}
35*d9f75844SAndroid Build Coastguard Worker 
36*d9f75844SAndroid Build Coastguard Worker   MOCK_METHOD(void, OnRttUpdate, (int64_t, int64_t), (override));
37*d9f75844SAndroid Build Coastguard Worker };
38*d9f75844SAndroid Build Coastguard Worker 
39*d9f75844SAndroid Build Coastguard Worker class CallStats2Test : public ::testing::Test {
40*d9f75844SAndroid Build Coastguard Worker  public:
CallStats2Test()41*d9f75844SAndroid Build Coastguard Worker   CallStats2Test() { call_stats_.EnsureStarted(); }
42*d9f75844SAndroid Build Coastguard Worker 
43*d9f75844SAndroid Build Coastguard Worker   // Queues an rtt update call on the process thread.
AsyncSimulateRttUpdate(int64_t rtt)44*d9f75844SAndroid Build Coastguard Worker   void AsyncSimulateRttUpdate(int64_t rtt) {
45*d9f75844SAndroid Build Coastguard Worker     RtcpRttStats* rtcp_rtt_stats = call_stats_.AsRtcpRttStats();
46*d9f75844SAndroid Build Coastguard Worker     task_queue_->PostTask(
47*d9f75844SAndroid Build Coastguard Worker         [rtcp_rtt_stats, rtt] { rtcp_rtt_stats->OnRttUpdate(rtt); });
48*d9f75844SAndroid Build Coastguard Worker   }
49*d9f75844SAndroid Build Coastguard Worker 
50*d9f75844SAndroid Build Coastguard Worker  protected:
FlushProcessAndWorker()51*d9f75844SAndroid Build Coastguard Worker   void FlushProcessAndWorker() {
52*d9f75844SAndroid Build Coastguard Worker     task_queue_->PostTask([this] { loop_.PostTask([this] { loop_.Quit(); }); });
53*d9f75844SAndroid Build Coastguard Worker     loop_.Run();
54*d9f75844SAndroid Build Coastguard Worker   }
55*d9f75844SAndroid Build Coastguard Worker 
56*d9f75844SAndroid Build Coastguard Worker   test::RunLoop loop_;
57*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<TaskQueueBase, TaskQueueDeleter> task_queue_ =
58*d9f75844SAndroid Build Coastguard Worker       CreateDefaultTaskQueueFactory()->CreateTaskQueue(
59*d9f75844SAndroid Build Coastguard Worker           "CallStats",
60*d9f75844SAndroid Build Coastguard Worker           TaskQueueFactory::Priority::NORMAL);
61*d9f75844SAndroid Build Coastguard Worker 
62*d9f75844SAndroid Build Coastguard Worker   // Note: Since rtc::Thread doesn't support injecting a Clock, we're going
63*d9f75844SAndroid Build Coastguard Worker   // to be using a mix of the fake clock (used by CallStats) as well as the
64*d9f75844SAndroid Build Coastguard Worker   // system clock (used by rtc::Thread). This isn't ideal and will result in
65*d9f75844SAndroid Build Coastguard Worker   // the tests taking longer to execute in some cases than they need to.
66*d9f75844SAndroid Build Coastguard Worker   SimulatedClock fake_clock_{12345};
67*d9f75844SAndroid Build Coastguard Worker   CallStats call_stats_{&fake_clock_, loop_.task_queue()};
68*d9f75844SAndroid Build Coastguard Worker };
69*d9f75844SAndroid Build Coastguard Worker 
TEST_F(CallStats2Test,AddAndTriggerCallback)70*d9f75844SAndroid Build Coastguard Worker TEST_F(CallStats2Test, AddAndTriggerCallback) {
71*d9f75844SAndroid Build Coastguard Worker   static constexpr const int64_t kRtt = 25;
72*d9f75844SAndroid Build Coastguard Worker 
73*d9f75844SAndroid Build Coastguard Worker   MockStatsObserver stats_observer;
74*d9f75844SAndroid Build Coastguard Worker   EXPECT_CALL(stats_observer, OnRttUpdate(kRtt, kRtt))
75*d9f75844SAndroid Build Coastguard Worker       .Times(1)
76*d9f75844SAndroid Build Coastguard Worker       .WillOnce(InvokeWithoutArgs([this] { loop_.Quit(); }));
77*d9f75844SAndroid Build Coastguard Worker 
78*d9f75844SAndroid Build Coastguard Worker   call_stats_.RegisterStatsObserver(&stats_observer);
79*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(-1, call_stats_.LastProcessedRtt());
80*d9f75844SAndroid Build Coastguard Worker 
81*d9f75844SAndroid Build Coastguard Worker   AsyncSimulateRttUpdate(kRtt);
82*d9f75844SAndroid Build Coastguard Worker   loop_.Run();
83*d9f75844SAndroid Build Coastguard Worker 
84*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(kRtt, call_stats_.LastProcessedRtt());
85*d9f75844SAndroid Build Coastguard Worker 
86*d9f75844SAndroid Build Coastguard Worker   call_stats_.DeregisterStatsObserver(&stats_observer);
87*d9f75844SAndroid Build Coastguard Worker }
88*d9f75844SAndroid Build Coastguard Worker 
TEST_F(CallStats2Test,ProcessTime)89*d9f75844SAndroid Build Coastguard Worker TEST_F(CallStats2Test, ProcessTime) {
90*d9f75844SAndroid Build Coastguard Worker   static constexpr const int64_t kRtt = 100;
91*d9f75844SAndroid Build Coastguard Worker   static constexpr const int64_t kRtt2 = 80;
92*d9f75844SAndroid Build Coastguard Worker 
93*d9f75844SAndroid Build Coastguard Worker   MockStatsObserver stats_observer;
94*d9f75844SAndroid Build Coastguard Worker 
95*d9f75844SAndroid Build Coastguard Worker   EXPECT_CALL(stats_observer, OnRttUpdate(kRtt, kRtt))
96*d9f75844SAndroid Build Coastguard Worker       .Times(2)
97*d9f75844SAndroid Build Coastguard Worker       .WillOnce(InvokeWithoutArgs([this] {
98*d9f75844SAndroid Build Coastguard Worker         // Advance clock and verify we get an update.
99*d9f75844SAndroid Build Coastguard Worker         fake_clock_.AdvanceTimeMilliseconds(CallStats::kUpdateInterval.ms());
100*d9f75844SAndroid Build Coastguard Worker       }))
101*d9f75844SAndroid Build Coastguard Worker       .WillRepeatedly(InvokeWithoutArgs([this] {
102*d9f75844SAndroid Build Coastguard Worker         AsyncSimulateRttUpdate(kRtt2);
103*d9f75844SAndroid Build Coastguard Worker         // Advance clock just too little to get an update.
104*d9f75844SAndroid Build Coastguard Worker         fake_clock_.AdvanceTimeMilliseconds(CallStats::kUpdateInterval.ms() -
105*d9f75844SAndroid Build Coastguard Worker                                             1);
106*d9f75844SAndroid Build Coastguard Worker       }));
107*d9f75844SAndroid Build Coastguard Worker 
108*d9f75844SAndroid Build Coastguard Worker   // In case you're reading this and wondering how this number is arrived at,
109*d9f75844SAndroid Build Coastguard Worker   // please see comments in the ChangeRtt test that go into some detail.
110*d9f75844SAndroid Build Coastguard Worker   static constexpr const int64_t kLastAvg = 94;
111*d9f75844SAndroid Build Coastguard Worker   EXPECT_CALL(stats_observer, OnRttUpdate(kLastAvg, kRtt2))
112*d9f75844SAndroid Build Coastguard Worker       .Times(1)
113*d9f75844SAndroid Build Coastguard Worker       .WillOnce(InvokeWithoutArgs([this] { loop_.Quit(); }));
114*d9f75844SAndroid Build Coastguard Worker 
115*d9f75844SAndroid Build Coastguard Worker   call_stats_.RegisterStatsObserver(&stats_observer);
116*d9f75844SAndroid Build Coastguard Worker 
117*d9f75844SAndroid Build Coastguard Worker   AsyncSimulateRttUpdate(kRtt);
118*d9f75844SAndroid Build Coastguard Worker   loop_.Run();
119*d9f75844SAndroid Build Coastguard Worker 
120*d9f75844SAndroid Build Coastguard Worker   call_stats_.DeregisterStatsObserver(&stats_observer);
121*d9f75844SAndroid Build Coastguard Worker }
122*d9f75844SAndroid Build Coastguard Worker 
123*d9f75844SAndroid Build Coastguard Worker // Verify all observers get correct estimates and observers can be added and
124*d9f75844SAndroid Build Coastguard Worker // removed.
TEST_F(CallStats2Test,MultipleObservers)125*d9f75844SAndroid Build Coastguard Worker TEST_F(CallStats2Test, MultipleObservers) {
126*d9f75844SAndroid Build Coastguard Worker   MockStatsObserver stats_observer_1;
127*d9f75844SAndroid Build Coastguard Worker   call_stats_.RegisterStatsObserver(&stats_observer_1);
128*d9f75844SAndroid Build Coastguard Worker   // Add the second observer twice, there should still be only one report to the
129*d9f75844SAndroid Build Coastguard Worker   // observer.
130*d9f75844SAndroid Build Coastguard Worker   MockStatsObserver stats_observer_2;
131*d9f75844SAndroid Build Coastguard Worker   call_stats_.RegisterStatsObserver(&stats_observer_2);
132*d9f75844SAndroid Build Coastguard Worker   call_stats_.RegisterStatsObserver(&stats_observer_2);
133*d9f75844SAndroid Build Coastguard Worker 
134*d9f75844SAndroid Build Coastguard Worker   static constexpr const int64_t kRtt = 100;
135*d9f75844SAndroid Build Coastguard Worker 
136*d9f75844SAndroid Build Coastguard Worker   // Verify both observers are updated.
137*d9f75844SAndroid Build Coastguard Worker   EXPECT_CALL(stats_observer_1, OnRttUpdate(kRtt, kRtt))
138*d9f75844SAndroid Build Coastguard Worker       .Times(AnyNumber())
139*d9f75844SAndroid Build Coastguard Worker       .WillRepeatedly(Return());
140*d9f75844SAndroid Build Coastguard Worker   EXPECT_CALL(stats_observer_2, OnRttUpdate(kRtt, kRtt))
141*d9f75844SAndroid Build Coastguard Worker       .Times(AnyNumber())
142*d9f75844SAndroid Build Coastguard Worker       .WillOnce(InvokeWithoutArgs([this] { loop_.Quit(); }))
143*d9f75844SAndroid Build Coastguard Worker       .WillRepeatedly(Return());
144*d9f75844SAndroid Build Coastguard Worker   AsyncSimulateRttUpdate(kRtt);
145*d9f75844SAndroid Build Coastguard Worker   loop_.Run();
146*d9f75844SAndroid Build Coastguard Worker 
147*d9f75844SAndroid Build Coastguard Worker   // Deregister the second observer and verify update is only sent to the first
148*d9f75844SAndroid Build Coastguard Worker   // observer.
149*d9f75844SAndroid Build Coastguard Worker   call_stats_.DeregisterStatsObserver(&stats_observer_2);
150*d9f75844SAndroid Build Coastguard Worker 
151*d9f75844SAndroid Build Coastguard Worker   EXPECT_CALL(stats_observer_1, OnRttUpdate(kRtt, kRtt))
152*d9f75844SAndroid Build Coastguard Worker       .Times(AnyNumber())
153*d9f75844SAndroid Build Coastguard Worker       .WillOnce(InvokeWithoutArgs([this] { loop_.Quit(); }))
154*d9f75844SAndroid Build Coastguard Worker       .WillRepeatedly(Return());
155*d9f75844SAndroid Build Coastguard Worker   EXPECT_CALL(stats_observer_2, OnRttUpdate(kRtt, kRtt)).Times(0);
156*d9f75844SAndroid Build Coastguard Worker   AsyncSimulateRttUpdate(kRtt);
157*d9f75844SAndroid Build Coastguard Worker   loop_.Run();
158*d9f75844SAndroid Build Coastguard Worker 
159*d9f75844SAndroid Build Coastguard Worker   // Deregister the first observer.
160*d9f75844SAndroid Build Coastguard Worker   call_stats_.DeregisterStatsObserver(&stats_observer_1);
161*d9f75844SAndroid Build Coastguard Worker 
162*d9f75844SAndroid Build Coastguard Worker   // Now make sure we don't get any callbacks.
163*d9f75844SAndroid Build Coastguard Worker   EXPECT_CALL(stats_observer_1, OnRttUpdate(kRtt, kRtt)).Times(0);
164*d9f75844SAndroid Build Coastguard Worker   EXPECT_CALL(stats_observer_2, OnRttUpdate(kRtt, kRtt)).Times(0);
165*d9f75844SAndroid Build Coastguard Worker   AsyncSimulateRttUpdate(kRtt);
166*d9f75844SAndroid Build Coastguard Worker 
167*d9f75844SAndroid Build Coastguard Worker   // Flush the queue on the process thread to make sure we return after
168*d9f75844SAndroid Build Coastguard Worker   // Process() has been called.
169*d9f75844SAndroid Build Coastguard Worker   FlushProcessAndWorker();
170*d9f75844SAndroid Build Coastguard Worker }
171*d9f75844SAndroid Build Coastguard Worker 
172*d9f75844SAndroid Build Coastguard Worker // Verify increasing and decreasing rtt triggers callbacks with correct values.
TEST_F(CallStats2Test,ChangeRtt)173*d9f75844SAndroid Build Coastguard Worker TEST_F(CallStats2Test, ChangeRtt) {
174*d9f75844SAndroid Build Coastguard Worker   // NOTE: This test assumes things about how old reports are removed
175*d9f75844SAndroid Build Coastguard Worker   // inside of call_stats.cc. The threshold ms value is 1500ms, but it's not
176*d9f75844SAndroid Build Coastguard Worker   // clear here that how the clock is advanced, affects that algorithm and
177*d9f75844SAndroid Build Coastguard Worker   // subsequently the average reported rtt.
178*d9f75844SAndroid Build Coastguard Worker 
179*d9f75844SAndroid Build Coastguard Worker   MockStatsObserver stats_observer;
180*d9f75844SAndroid Build Coastguard Worker   call_stats_.RegisterStatsObserver(&stats_observer);
181*d9f75844SAndroid Build Coastguard Worker 
182*d9f75844SAndroid Build Coastguard Worker   static constexpr const int64_t kFirstRtt = 100;
183*d9f75844SAndroid Build Coastguard Worker   static constexpr const int64_t kLowRtt = kFirstRtt - 20;
184*d9f75844SAndroid Build Coastguard Worker   static constexpr const int64_t kHighRtt = kFirstRtt + 20;
185*d9f75844SAndroid Build Coastguard Worker 
186*d9f75844SAndroid Build Coastguard Worker   EXPECT_CALL(stats_observer, OnRttUpdate(kFirstRtt, kFirstRtt))
187*d9f75844SAndroid Build Coastguard Worker       .Times(1)
188*d9f75844SAndroid Build Coastguard Worker       .WillOnce(InvokeWithoutArgs([this] {
189*d9f75844SAndroid Build Coastguard Worker         fake_clock_.AdvanceTimeMilliseconds(1000);
190*d9f75844SAndroid Build Coastguard Worker         AsyncSimulateRttUpdate(kHighRtt);  // Reported at T1 (1000ms).
191*d9f75844SAndroid Build Coastguard Worker       }));
192*d9f75844SAndroid Build Coastguard Worker 
193*d9f75844SAndroid Build Coastguard Worker   // NOTE: This relies on the internal algorithms of call_stats.cc.
194*d9f75844SAndroid Build Coastguard Worker   // There's a weight factor there (0.3), that weighs the previous average to
195*d9f75844SAndroid Build Coastguard Worker   // the new one by 70%, so the number 103 in this case is arrived at like so:
196*d9f75844SAndroid Build Coastguard Worker   // (100) / 1 * 0.7 + (100+120)/2 * 0.3 = 103
197*d9f75844SAndroid Build Coastguard Worker   static constexpr const int64_t kAvgRtt1 = 103;
198*d9f75844SAndroid Build Coastguard Worker   EXPECT_CALL(stats_observer, OnRttUpdate(kAvgRtt1, kHighRtt))
199*d9f75844SAndroid Build Coastguard Worker       .Times(1)
200*d9f75844SAndroid Build Coastguard Worker       .WillOnce(InvokeWithoutArgs([this] {
201*d9f75844SAndroid Build Coastguard Worker         // This interacts with an internal implementation detail in call_stats
202*d9f75844SAndroid Build Coastguard Worker         // that decays the oldest rtt value. See more below.
203*d9f75844SAndroid Build Coastguard Worker         fake_clock_.AdvanceTimeMilliseconds(1000);
204*d9f75844SAndroid Build Coastguard Worker         AsyncSimulateRttUpdate(kLowRtt);  // Reported at T2 (2000ms).
205*d9f75844SAndroid Build Coastguard Worker       }));
206*d9f75844SAndroid Build Coastguard Worker 
207*d9f75844SAndroid Build Coastguard Worker   // Increase time enough for a new update, but not too much to make the
208*d9f75844SAndroid Build Coastguard Worker   // rtt invalid. Report a lower rtt and verify the old/high value still is sent
209*d9f75844SAndroid Build Coastguard Worker   // in the callback.
210*d9f75844SAndroid Build Coastguard Worker 
211*d9f75844SAndroid Build Coastguard Worker   // Here, enough time must have passed in order to remove exactly the first
212*d9f75844SAndroid Build Coastguard Worker   // report and nothing else (>1500ms has passed since the first rtt).
213*d9f75844SAndroid Build Coastguard Worker   // So, this value is arrived by doing:
214*d9f75844SAndroid Build Coastguard Worker   // (kAvgRtt1)/1 * 0.7 + (kHighRtt+kLowRtt)/2 * 0.3 = 102.1
215*d9f75844SAndroid Build Coastguard Worker   static constexpr const int64_t kAvgRtt2 = 102;
216*d9f75844SAndroid Build Coastguard Worker   EXPECT_CALL(stats_observer, OnRttUpdate(kAvgRtt2, kHighRtt))
217*d9f75844SAndroid Build Coastguard Worker       .Times(1)
218*d9f75844SAndroid Build Coastguard Worker       .WillOnce(InvokeWithoutArgs([this] {
219*d9f75844SAndroid Build Coastguard Worker         // Advance time to make the high report invalid, the lower rtt should
220*d9f75844SAndroid Build Coastguard Worker         // now be in the callback.
221*d9f75844SAndroid Build Coastguard Worker         fake_clock_.AdvanceTimeMilliseconds(1000);
222*d9f75844SAndroid Build Coastguard Worker       }));
223*d9f75844SAndroid Build Coastguard Worker 
224*d9f75844SAndroid Build Coastguard Worker   static constexpr const int64_t kAvgRtt3 = 95;
225*d9f75844SAndroid Build Coastguard Worker   EXPECT_CALL(stats_observer, OnRttUpdate(kAvgRtt3, kLowRtt))
226*d9f75844SAndroid Build Coastguard Worker       .Times(1)
227*d9f75844SAndroid Build Coastguard Worker       .WillOnce(InvokeWithoutArgs([this] { loop_.Quit(); }));
228*d9f75844SAndroid Build Coastguard Worker 
229*d9f75844SAndroid Build Coastguard Worker   // Trigger the first rtt value and set off the chain of callbacks.
230*d9f75844SAndroid Build Coastguard Worker   AsyncSimulateRttUpdate(kFirstRtt);  // Reported at T0 (0ms).
231*d9f75844SAndroid Build Coastguard Worker   loop_.Run();
232*d9f75844SAndroid Build Coastguard Worker 
233*d9f75844SAndroid Build Coastguard Worker   call_stats_.DeregisterStatsObserver(&stats_observer);
234*d9f75844SAndroid Build Coastguard Worker }
235*d9f75844SAndroid Build Coastguard Worker 
TEST_F(CallStats2Test,LastProcessedRtt)236*d9f75844SAndroid Build Coastguard Worker TEST_F(CallStats2Test, LastProcessedRtt) {
237*d9f75844SAndroid Build Coastguard Worker   MockStatsObserver stats_observer;
238*d9f75844SAndroid Build Coastguard Worker   call_stats_.RegisterStatsObserver(&stats_observer);
239*d9f75844SAndroid Build Coastguard Worker 
240*d9f75844SAndroid Build Coastguard Worker   static constexpr const int64_t kRttLow = 10;
241*d9f75844SAndroid Build Coastguard Worker   static constexpr const int64_t kRttHigh = 30;
242*d9f75844SAndroid Build Coastguard Worker   // The following two average numbers dependend on average + weight
243*d9f75844SAndroid Build Coastguard Worker   // calculations in call_stats.cc.
244*d9f75844SAndroid Build Coastguard Worker   static constexpr const int64_t kAvgRtt1 = 13;
245*d9f75844SAndroid Build Coastguard Worker   static constexpr const int64_t kAvgRtt2 = 15;
246*d9f75844SAndroid Build Coastguard Worker 
247*d9f75844SAndroid Build Coastguard Worker   EXPECT_CALL(stats_observer, OnRttUpdate(kRttLow, kRttLow))
248*d9f75844SAndroid Build Coastguard Worker       .Times(1)
249*d9f75844SAndroid Build Coastguard Worker       .WillOnce(InvokeWithoutArgs([this] {
250*d9f75844SAndroid Build Coastguard Worker         EXPECT_EQ(kRttLow, call_stats_.LastProcessedRtt());
251*d9f75844SAndroid Build Coastguard Worker         // Don't advance the clock to make sure that low and high rtt values
252*d9f75844SAndroid Build Coastguard Worker         // are associated with the same time stamp.
253*d9f75844SAndroid Build Coastguard Worker         AsyncSimulateRttUpdate(kRttHigh);
254*d9f75844SAndroid Build Coastguard Worker       }));
255*d9f75844SAndroid Build Coastguard Worker 
256*d9f75844SAndroid Build Coastguard Worker   EXPECT_CALL(stats_observer, OnRttUpdate(kAvgRtt1, kRttHigh))
257*d9f75844SAndroid Build Coastguard Worker       .Times(AnyNumber())
258*d9f75844SAndroid Build Coastguard Worker       .WillOnce(InvokeWithoutArgs([this] {
259*d9f75844SAndroid Build Coastguard Worker         EXPECT_EQ(kAvgRtt1, call_stats_.LastProcessedRtt());
260*d9f75844SAndroid Build Coastguard Worker         fake_clock_.AdvanceTimeMilliseconds(CallStats::kUpdateInterval.ms());
261*d9f75844SAndroid Build Coastguard Worker         AsyncSimulateRttUpdate(kRttLow);
262*d9f75844SAndroid Build Coastguard Worker         AsyncSimulateRttUpdate(kRttHigh);
263*d9f75844SAndroid Build Coastguard Worker       }))
264*d9f75844SAndroid Build Coastguard Worker       .WillRepeatedly(Return());
265*d9f75844SAndroid Build Coastguard Worker 
266*d9f75844SAndroid Build Coastguard Worker   EXPECT_CALL(stats_observer, OnRttUpdate(kAvgRtt2, kRttHigh))
267*d9f75844SAndroid Build Coastguard Worker       .Times(AnyNumber())
268*d9f75844SAndroid Build Coastguard Worker       .WillOnce(InvokeWithoutArgs([this] {
269*d9f75844SAndroid Build Coastguard Worker         EXPECT_EQ(kAvgRtt2, call_stats_.LastProcessedRtt());
270*d9f75844SAndroid Build Coastguard Worker         loop_.Quit();
271*d9f75844SAndroid Build Coastguard Worker       }))
272*d9f75844SAndroid Build Coastguard Worker       .WillRepeatedly(Return());
273*d9f75844SAndroid Build Coastguard Worker 
274*d9f75844SAndroid Build Coastguard Worker   // Set a first values and verify that LastProcessedRtt initially returns the
275*d9f75844SAndroid Build Coastguard Worker   // average rtt.
276*d9f75844SAndroid Build Coastguard Worker   fake_clock_.AdvanceTimeMilliseconds(CallStats::kUpdateInterval.ms());
277*d9f75844SAndroid Build Coastguard Worker   AsyncSimulateRttUpdate(kRttLow);
278*d9f75844SAndroid Build Coastguard Worker   loop_.Run();
279*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(kAvgRtt2, call_stats_.LastProcessedRtt());
280*d9f75844SAndroid Build Coastguard Worker 
281*d9f75844SAndroid Build Coastguard Worker   call_stats_.DeregisterStatsObserver(&stats_observer);
282*d9f75844SAndroid Build Coastguard Worker }
283*d9f75844SAndroid Build Coastguard Worker 
TEST_F(CallStats2Test,ProducesHistogramMetrics)284*d9f75844SAndroid Build Coastguard Worker TEST_F(CallStats2Test, ProducesHistogramMetrics) {
285*d9f75844SAndroid Build Coastguard Worker   metrics::Reset();
286*d9f75844SAndroid Build Coastguard Worker   static constexpr const int64_t kRtt = 123;
287*d9f75844SAndroid Build Coastguard Worker   MockStatsObserver stats_observer;
288*d9f75844SAndroid Build Coastguard Worker   call_stats_.RegisterStatsObserver(&stats_observer);
289*d9f75844SAndroid Build Coastguard Worker   EXPECT_CALL(stats_observer, OnRttUpdate(kRtt, kRtt))
290*d9f75844SAndroid Build Coastguard Worker       .Times(AnyNumber())
291*d9f75844SAndroid Build Coastguard Worker       .WillRepeatedly(InvokeWithoutArgs([this] { loop_.Quit(); }));
292*d9f75844SAndroid Build Coastguard Worker 
293*d9f75844SAndroid Build Coastguard Worker   AsyncSimulateRttUpdate(kRtt);
294*d9f75844SAndroid Build Coastguard Worker   loop_.Run();
295*d9f75844SAndroid Build Coastguard Worker   fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds *
296*d9f75844SAndroid Build Coastguard Worker                                       CallStats::kUpdateInterval.ms());
297*d9f75844SAndroid Build Coastguard Worker   AsyncSimulateRttUpdate(kRtt);
298*d9f75844SAndroid Build Coastguard Worker   loop_.Run();
299*d9f75844SAndroid Build Coastguard Worker 
300*d9f75844SAndroid Build Coastguard Worker   call_stats_.DeregisterStatsObserver(&stats_observer);
301*d9f75844SAndroid Build Coastguard Worker 
302*d9f75844SAndroid Build Coastguard Worker   call_stats_.UpdateHistogramsForTest();
303*d9f75844SAndroid Build Coastguard Worker 
304*d9f75844SAndroid Build Coastguard Worker   EXPECT_METRIC_EQ(1, metrics::NumSamples(
305*d9f75844SAndroid Build Coastguard Worker                           "WebRTC.Video.AverageRoundTripTimeInMilliseconds"));
306*d9f75844SAndroid Build Coastguard Worker   EXPECT_METRIC_EQ(
307*d9f75844SAndroid Build Coastguard Worker       1, metrics::NumEvents("WebRTC.Video.AverageRoundTripTimeInMilliseconds",
308*d9f75844SAndroid Build Coastguard Worker                             kRtt));
309*d9f75844SAndroid Build Coastguard Worker }
310*d9f75844SAndroid Build Coastguard Worker 
311*d9f75844SAndroid Build Coastguard Worker }  // namespace internal
312*d9f75844SAndroid Build Coastguard Worker }  // namespace webrtc
313