/* * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" #include "webrtc/system_wrappers/interface/scoped_ptr.h" #include "webrtc/system_wrappers/interface/tick_util.h" #include "webrtc/video_engine/call_stats.h" using ::testing::_; using ::testing::AnyNumber; using ::testing::Return; namespace webrtc { class MockStatsObserver : public CallStatsObserver { public: MockStatsObserver() {} virtual ~MockStatsObserver() {} MOCK_METHOD1(OnRttUpdate, void(uint32_t)); }; class CallStatsTest : public ::testing::Test { protected: virtual void SetUp() { TickTime::UseFakeClock(12345); call_stats_.reset(new CallStats()); } scoped_ptr call_stats_; }; TEST_F(CallStatsTest, AddAndTriggerCallback) { MockStatsObserver stats_observer; RtcpRttStats* rtcp_rtt_stats = call_stats_->rtcp_rtt_stats(); call_stats_->RegisterStatsObserver(&stats_observer); TickTime::AdvanceFakeClock(1000); EXPECT_EQ(0U, rtcp_rtt_stats->LastProcessedRtt()); const uint32_t kRtt = 25; rtcp_rtt_stats->OnRttUpdate(kRtt); EXPECT_CALL(stats_observer, OnRttUpdate(kRtt)) .Times(1); call_stats_->Process(); EXPECT_EQ(kRtt, rtcp_rtt_stats->LastProcessedRtt()); const int kRttTimeOutMs = 1500 + 10; TickTime::AdvanceFakeClock(kRttTimeOutMs); EXPECT_CALL(stats_observer, OnRttUpdate(_)) .Times(0); call_stats_->Process(); EXPECT_EQ(0U, rtcp_rtt_stats->LastProcessedRtt()); call_stats_->DeregisterStatsObserver(&stats_observer); } TEST_F(CallStatsTest, ProcessTime) { MockStatsObserver stats_observer; call_stats_->RegisterStatsObserver(&stats_observer); RtcpRttStats* rtcp_rtt_stats = call_stats_->rtcp_rtt_stats(); rtcp_rtt_stats->OnRttUpdate(100); // Time isn't updated yet. EXPECT_CALL(stats_observer, OnRttUpdate(_)) .Times(0); call_stats_->Process(); // Advance clock and verify we get an update. TickTime::AdvanceFakeClock(1000); EXPECT_CALL(stats_observer, OnRttUpdate(_)) .Times(1); call_stats_->Process(); // Advance clock just too little to get an update. TickTime::AdvanceFakeClock(999); rtcp_rtt_stats->OnRttUpdate(100); EXPECT_CALL(stats_observer, OnRttUpdate(_)) .Times(0); call_stats_->Process(); // Advance enough to trigger a new update. TickTime::AdvanceFakeClock(1); EXPECT_CALL(stats_observer, OnRttUpdate(_)) .Times(1); call_stats_->Process(); call_stats_->DeregisterStatsObserver(&stats_observer); } // Verify all observers get correct estimates and observers can be added and // removed. TEST_F(CallStatsTest, MultipleObservers) { MockStatsObserver stats_observer_1; call_stats_->RegisterStatsObserver(&stats_observer_1); // Add the secondobserver twice, there should still be only one report to the // observer. MockStatsObserver stats_observer_2; call_stats_->RegisterStatsObserver(&stats_observer_2); call_stats_->RegisterStatsObserver(&stats_observer_2); RtcpRttStats* rtcp_rtt_stats = call_stats_->rtcp_rtt_stats(); uint32_t rtt = 100; rtcp_rtt_stats->OnRttUpdate(rtt); // Verify both observers are updated. TickTime::AdvanceFakeClock(1000); EXPECT_CALL(stats_observer_1, OnRttUpdate(rtt)) .Times(1); EXPECT_CALL(stats_observer_2, OnRttUpdate(rtt)) .Times(1); call_stats_->Process(); // Deregister the second observer and verify update is only sent to the first // observer. call_stats_->DeregisterStatsObserver(&stats_observer_2); rtcp_rtt_stats->OnRttUpdate(rtt); TickTime::AdvanceFakeClock(1000); EXPECT_CALL(stats_observer_1, OnRttUpdate(rtt)) .Times(1); EXPECT_CALL(stats_observer_2, OnRttUpdate(rtt)) .Times(0); call_stats_->Process(); // Deregister the first observer. call_stats_->DeregisterStatsObserver(&stats_observer_1); rtcp_rtt_stats->OnRttUpdate(rtt); TickTime::AdvanceFakeClock(1000); EXPECT_CALL(stats_observer_1, OnRttUpdate(rtt)) .Times(0); EXPECT_CALL(stats_observer_2, OnRttUpdate(rtt)) .Times(0); call_stats_->Process(); } // Verify increasing and decreasing rtt triggers callbacks with correct values. TEST_F(CallStatsTest, ChangeRtt) { MockStatsObserver stats_observer; call_stats_->RegisterStatsObserver(&stats_observer); RtcpRttStats* rtcp_rtt_stats = call_stats_->rtcp_rtt_stats(); // Advance clock to be ready for an update. TickTime::AdvanceFakeClock(1000); // Set a first value and verify the callback is triggered. const uint32_t first_rtt = 100; rtcp_rtt_stats->OnRttUpdate(first_rtt); EXPECT_CALL(stats_observer, OnRttUpdate(first_rtt)) .Times(1); call_stats_->Process(); // Increase rtt and verify the new value is reported. TickTime::AdvanceFakeClock(1000); const uint32_t high_rtt = first_rtt + 20; rtcp_rtt_stats->OnRttUpdate(high_rtt); EXPECT_CALL(stats_observer, OnRttUpdate(high_rtt)) .Times(1); call_stats_->Process(); // Increase time enough for a new update, but not too much to make the // rtt invalid. Report a lower rtt and verify the old/high value still is sent // in the callback. TickTime::AdvanceFakeClock(1000); const uint32_t low_rtt = first_rtt - 20; rtcp_rtt_stats->OnRttUpdate(low_rtt); EXPECT_CALL(stats_observer, OnRttUpdate(high_rtt)) .Times(1); call_stats_->Process(); // Advance time to make the high report invalid, the lower rtt should now be // in the callback. TickTime::AdvanceFakeClock(1000); EXPECT_CALL(stats_observer, OnRttUpdate(low_rtt)) .Times(1); call_stats_->Process(); call_stats_->DeregisterStatsObserver(&stats_observer); } } // namespace webrtc