webrtc/logging/rtc_event_log/rtc_event_log_impl_unittest.cc
Markus Handell f015a12802 RtcEventLogImpl: Add mocked time test.
This change adds mocked time unit tests to RtcEventLogImpl. In
order to simplify test implementation, the Impl ctor was changed
to accept an already created event log encoder. The previous
factory was made public in the Impl interface and relevant
code sites were updated.

Bug: chromium:1288710
Change-Id: Ifbfd899c5a06a3350c7e5fbc3bb7280f67124f2b
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/290382
Reviewed-by: Henrik Andreassson <henrika@webrtc.org>
Commit-Queue: Markus Handell <handellm@webrtc.org>
Reviewed-by: Björn Terelius <terelius@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#38987}
2023-01-03 14:08:16 +00:00

188 lines
6.7 KiB
C++

/*
* Copyright (c) 2023 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 "logging/rtc_event_log/rtc_event_log_impl.h"
#include <utility>
#include <vector>
#include "test/gmock.h"
#include "test/gtest.h"
#include "test/time_controller/simulated_time_controller.h"
namespace webrtc {
namespace {
using ::testing::InSequence;
using ::testing::Mock;
using ::testing::Property;
using ::testing::Ref;
using ::testing::Return;
using ::testing::StrEq;
class MockEventEncoder : public RtcEventLogEncoder {
public:
MOCK_METHOD(std::string,
EncodeLogStart,
(int64_t /*timestamp_us*/, int64_t /*utc_time_us*/),
(override));
MOCK_METHOD(std::string,
EncodeLogEnd,
(int64_t /*timestamp_us*/),
(override));
MOCK_METHOD(std::string, OnEncode, (const RtcEvent&), ());
std::string EncodeBatch(
std::deque<std::unique_ptr<RtcEvent>>::const_iterator a,
std::deque<std::unique_ptr<RtcEvent>>::const_iterator b) override {
std::string result;
while (a != b) {
result += OnEncode(**a);
++a;
}
return result;
}
};
class FakeOutput : public RtcEventLogOutput {
public:
explicit FakeOutput(std::string& written_data)
: written_data_(written_data) {}
bool IsActive() const { return true; }
bool Write(absl::string_view data) override {
written_data_.append(std::string(data));
return true;
}
void Flush() override {}
private:
std::string& written_data_;
};
class FakeEvent : public RtcEvent {
public:
Type GetType() const override { return RtcEvent::Type::FakeEvent; }
bool IsConfigEvent() const override { return false; }
};
class FakeConfigEvent : public RtcEvent {
public:
Type GetType() const override { return RtcEvent::Type::FakeEvent; }
bool IsConfigEvent() const override { return true; }
};
class RtcEventLogImplTest : public ::testing::Test {
public:
static constexpr size_t kMaxEventsInHistory = 2;
static constexpr size_t kMaxEventsInConfigHistory = 3;
static constexpr TimeDelta kOutputPeriod = TimeDelta::Seconds(2);
static constexpr Timestamp kStartTime = Timestamp::Seconds(1);
GlobalSimulatedTimeController time_controller_{kStartTime};
std::unique_ptr<MockEventEncoder> encoder_ =
std::make_unique<MockEventEncoder>();
MockEventEncoder* encoder_ptr_ = encoder_.get();
std::unique_ptr<FakeOutput> output_ =
std::make_unique<FakeOutput>(written_data_);
FakeOutput* output_ptr_ = output_.get();
RtcEventLogImpl event_log_{std::move(encoder_),
time_controller_.GetTaskQueueFactory(),
kMaxEventsInHistory, kMaxEventsInConfigHistory};
std::string written_data_;
};
TEST_F(RtcEventLogImplTest, WritesHeaderAndEventsAndTrailer) {
EXPECT_CALL(*encoder_ptr_, EncodeLogStart(kStartTime.us(), kStartTime.us()))
.WillOnce(Return("start"));
EXPECT_CALL(*encoder_ptr_, EncodeLogEnd(kStartTime.us()))
.WillOnce(Return("stop"));
EXPECT_CALL(*encoder_ptr_, OnEncode(Property(&RtcEvent::IsConfigEvent, true)))
.WillOnce(Return("config"));
EXPECT_CALL(*encoder_ptr_,
OnEncode(Property(&RtcEvent::IsConfigEvent, false)))
.WillOnce(Return("event"));
event_log_.StartLogging(std::move(output_), kOutputPeriod.ms());
event_log_.Log(std::make_unique<FakeEvent>());
event_log_.Log(std::make_unique<FakeConfigEvent>());
event_log_.StopLogging();
Mock::VerifyAndClearExpectations(encoder_ptr_);
EXPECT_TRUE(written_data_ == "startconfigeventstop" ||
written_data_ == "starteventconfigstop");
}
TEST_F(RtcEventLogImplTest, KeepsMostRecentEventsOnStart) {
auto e2 = std::make_unique<FakeEvent>();
RtcEvent* e2_ptr = e2.get();
auto e3 = std::make_unique<FakeEvent>();
RtcEvent* e3_ptr = e3.get();
event_log_.Log(std::make_unique<FakeEvent>());
event_log_.Log(std::move(e2));
event_log_.Log(std::move(e3));
InSequence s;
EXPECT_CALL(*encoder_ptr_, OnEncode(Ref(*e2_ptr)));
EXPECT_CALL(*encoder_ptr_, OnEncode(Ref(*e3_ptr)));
event_log_.StartLogging(std::move(output_), kOutputPeriod.ms());
time_controller_.AdvanceTime(TimeDelta::Zero());
Mock::VerifyAndClearExpectations(encoder_ptr_);
}
TEST_F(RtcEventLogImplTest, EncodesEventsOnHistoryFullPostponesLastEncode) {
auto e1 = std::make_unique<FakeEvent>();
RtcEvent* e1_ptr = e1.get();
auto e2 = std::make_unique<FakeEvent>();
RtcEvent* e2_ptr = e2.get();
auto e3 = std::make_unique<FakeEvent>();
RtcEvent* e3_ptr = e3.get();
event_log_.StartLogging(std::move(output_), kOutputPeriod.ms());
time_controller_.AdvanceTime(TimeDelta::Zero());
event_log_.Log(std::move(e1));
event_log_.Log(std::move(e2));
// Overflows and causes immediate output, and eventual output after the output
// period has passed.
event_log_.Log(std::move(e3));
InSequence s;
EXPECT_CALL(*encoder_ptr_, OnEncode(Ref(*e1_ptr)));
EXPECT_CALL(*encoder_ptr_, OnEncode(Ref(*e2_ptr)));
time_controller_.AdvanceTime(TimeDelta::Zero());
EXPECT_CALL(*encoder_ptr_, OnEncode(Ref(*e3_ptr)));
time_controller_.AdvanceTime(kOutputPeriod);
Mock::VerifyAndClearExpectations(encoder_ptr_);
}
TEST_F(RtcEventLogImplTest, RewritesConfigEventsOnlyOnRestart) {
event_log_.StartLogging(std::make_unique<FakeOutput>(written_data_),
kOutputPeriod.ms());
event_log_.Log(std::make_unique<FakeConfigEvent>());
event_log_.Log(std::make_unique<FakeEvent>());
event_log_.StopLogging();
EXPECT_CALL(*encoder_ptr_,
OnEncode(Property(&RtcEvent::IsConfigEvent, true)));
EXPECT_CALL(*encoder_ptr_,
OnEncode(Property(&RtcEvent::IsConfigEvent, false)))
.Times(0);
event_log_.StartLogging(std::move(output_), kOutputPeriod.ms());
time_controller_.AdvanceTime(TimeDelta::Zero());
Mock::VerifyAndClearExpectations(encoder_ptr_);
}
TEST_F(RtcEventLogImplTest, SchedulesWriteAfterOutputDurationPassed) {
event_log_.StartLogging(std::make_unique<FakeOutput>(written_data_),
kOutputPeriod.ms());
event_log_.Log(std::make_unique<FakeConfigEvent>());
event_log_.Log(std::make_unique<FakeEvent>());
EXPECT_CALL(*encoder_ptr_,
OnEncode(Property(&RtcEvent::IsConfigEvent, true)));
EXPECT_CALL(*encoder_ptr_,
OnEncode(Property(&RtcEvent::IsConfigEvent, false)));
time_controller_.AdvanceTime(kOutputPeriod);
Mock::VerifyAndClearExpectations(encoder_ptr_);
}
} // namespace
} // namespace webrtc