blob: c37c21be966834e2f5019ad67056868225c1ac03 [file] [log] [blame]
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/mirroring/service/openscreen_stats_client.h"
#include "base/logging.h"
#include "media/cast/logging/stats_event_subscriber.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/openscreen/src/cast/streaming/public/sender_session.h"
#include "third_party/openscreen/src/cast/streaming/public/statistics.h"
namespace mirroring {
using openscreen::cast::SenderStats;
using openscreen::cast::StatisticType;
using HistogramsList = openscreen::cast::SenderStats::HistogramsList;
using StatisticsList = openscreen::cast::SenderStats::StatisticsList;
using SimpleHistogram = openscreen::cast::SimpleHistogram;
using CastStat = media::cast::StatsEventSubscriber::CastStat;
class OpenscreenStatsClientTest : public ::testing::Test {
public:
OpenscreenStatsClientTest()
: test_statistics_list_(ConstructTestStatisticsList()),
test_histogram_(ConstructTestHistogram()),
test_histograms_list_(ConstructTestHistogramsList()),
test_sender_stats_(ConstructTestSenderStats()),
openscreen_stats_client_(std::make_unique<OpenscreenStatsClient>()) {}
OpenscreenStatsClientTest(const OpenscreenStatsClientTest&) = delete;
OpenscreenStatsClientTest& operator=(const OpenscreenStatsClientTest&) =
delete;
~OpenscreenStatsClientTest() override = default;
StatisticsList ConstructTestStatisticsList() {
StatisticsList ret;
for (std::size_t i = 0; i < ret.size(); ++i) {
ret[i] = static_cast<double>(i);
}
return ret;
}
HistogramsList ConstructTestHistogramsList() {
HistogramsList ret;
for (auto& histogram : ret) {
histogram = ConstructTestHistogram();
}
return ret;
}
SimpleHistogram ConstructTestHistogram() {
SimpleHistogram ret = SimpleHistogram(0, 10, 2);
ret.Add(1);
ret.Add(4);
ret.Add(7);
return ret;
}
SenderStats ConstructTestSenderStats() {
return SenderStats{.audio_statistics = ConstructTestStatisticsList(),
.audio_histograms = ConstructTestHistogramsList(),
.video_statistics = ConstructTestStatisticsList(),
.video_histograms = ConstructTestHistogramsList()};
}
SenderStats ConstructDefaultSenderStats() {
return SenderStats{.audio_statistics = StatisticsList(),
.audio_histograms = HistogramsList(),
.video_statistics = StatisticsList(),
.video_histograms = HistogramsList()};
}
protected:
StatisticsList test_statistics_list_;
SimpleHistogram test_histogram_;
HistogramsList test_histograms_list_;
SenderStats test_sender_stats_;
std::unique_ptr<OpenscreenStatsClient> openscreen_stats_client_;
};
TEST_F(OpenscreenStatsClientTest, OnStatisticsUpdatedValidValues) {
// Test to verify that statistics are parsed and verified into both stats
// and histograms.
openscreen_stats_client_->OnStatisticsUpdated(test_sender_stats_);
auto stats_dict = openscreen_stats_client_->GetStats();
// Check that the GetStats() dict has been populated with audio stats and
// histograms.
const base::Value::Dict* audio_dict = stats_dict.FindDict(
media::cast::StatsEventSubscriber::kAudioStatsDictKey);
EXPECT_TRUE(audio_dict);
EXPECT_TRUE(audio_dict->contains("NUM_FRAMES_CAPTURED"));
EXPECT_TRUE(audio_dict->FindDouble("NUM_FRAMES_CAPTURED").has_value());
EXPECT_TRUE(audio_dict->contains("NUM_FRAMES_DROPPED_BY_ENCODER"));
EXPECT_TRUE(
audio_dict->FindDouble("NUM_FRAMES_DROPPED_BY_ENCODER").has_value());
EXPECT_TRUE(audio_dict->contains("AVG_CAPTURE_LATENCY_MS"));
EXPECT_TRUE(audio_dict->FindDouble("AVG_CAPTURE_LATENCY_MS").has_value());
// Check for some histograms.
EXPECT_TRUE(audio_dict->contains("E2E_LATENCY_MS_HISTO"));
EXPECT_TRUE(audio_dict->FindList("E2E_LATENCY_MS_HISTO")->size());
EXPECT_TRUE(audio_dict->contains("NETWORK_LATENCY_MS_HISTO"));
EXPECT_TRUE(audio_dict->FindList("NETWORK_LATENCY_MS_HISTO")->size());
// Check that the GetStats() dict has been populated with video stats and
// histograms.
const base::Value::Dict* video_dict = stats_dict.FindDict(
media::cast::StatsEventSubscriber::kVideoStatsDictKey);
EXPECT_TRUE(video_dict);
EXPECT_TRUE(video_dict->contains("NUM_FRAMES_CAPTURED"));
EXPECT_TRUE(video_dict->FindDouble("NUM_FRAMES_CAPTURED").has_value());
EXPECT_TRUE(video_dict->contains("NUM_FRAMES_DROPPED_BY_ENCODER"));
EXPECT_TRUE(
video_dict->FindDouble("NUM_FRAMES_DROPPED_BY_ENCODER").has_value());
EXPECT_TRUE(video_dict->contains("AVG_CAPTURE_LATENCY_MS"));
EXPECT_TRUE(video_dict->FindDouble("AVG_CAPTURE_LATENCY_MS").has_value());
// Check for some histograms.
EXPECT_TRUE(video_dict->contains("E2E_LATENCY_MS_HISTO"));
EXPECT_TRUE(video_dict->FindList("E2E_LATENCY_MS_HISTO")->size());
EXPECT_TRUE(video_dict->contains("NETWORK_LATENCY_MS_HISTO"));
EXPECT_TRUE(video_dict->FindList("NETWORK_LATENCY_MS_HISTO")->size());
}
TEST_F(OpenscreenStatsClientTest, OnStatisticsUpdatedEmptyValues) {
// Test to verify that statistics are parsed into both stats
// and histograms even if they are empty.
openscreen_stats_client_->OnStatisticsUpdated(ConstructDefaultSenderStats());
auto stats_dict = openscreen_stats_client_->GetStats();
// Check that the GetStats() dict has been populated with audio stats and
// histograms.
const base::Value::Dict* audio_dict = stats_dict.FindDict(
media::cast::StatsEventSubscriber::kAudioStatsDictKey);
EXPECT_TRUE(audio_dict);
EXPECT_TRUE(audio_dict->contains("NUM_FRAMES_CAPTURED"));
EXPECT_TRUE(audio_dict->FindDouble("NUM_FRAMES_CAPTURED").has_value());
// Check for some histograms. They should have no size since they are empty.
EXPECT_TRUE(audio_dict->contains("E2E_LATENCY_MS_HISTO"));
EXPECT_FALSE(audio_dict->FindList("E2E_LATENCY_MS_HISTO")->size());
EXPECT_TRUE(audio_dict->contains("NETWORK_LATENCY_MS_HISTO"));
EXPECT_FALSE(audio_dict->FindList("NETWORK_LATENCY_MS_HISTO")->size());
// Check that the GetStats() dict has been populated with video stats and
// histograms.
const base::Value::Dict* video_dict = stats_dict.FindDict(
media::cast::StatsEventSubscriber::kVideoStatsDictKey);
EXPECT_TRUE(video_dict);
EXPECT_TRUE(video_dict->contains("NUM_FRAMES_CAPTURED"));
EXPECT_TRUE(video_dict->FindDouble("NUM_FRAMES_CAPTURED").has_value());
// Check for some histograms. They should have no size since they are empty.
EXPECT_TRUE(video_dict->contains("E2E_LATENCY_MS_HISTO"));
EXPECT_FALSE(video_dict->FindList("E2E_LATENCY_MS_HISTO")->size());
EXPECT_TRUE(video_dict->contains("NETWORK_LATENCY_MS_HISTO"));
EXPECT_FALSE(video_dict->FindList("NETWORK_LATENCY_MS_HISTO")->size());
}
} // namespace mirroring