diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2018-08-24 12:15:48 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2018-08-28 13:30:04 +0000 |
commit | b014812705fc80bff0a5c120dfcef88f349816dc (patch) | |
tree | 25a2e2d9fa285f1add86aa333389a839f81a39ae /chromium/components/mirroring/service/session_monitor_unittest.cc | |
parent | 9f4560b1027ae06fdb497023cdcaf91b8511fa74 (diff) | |
download | qtwebengine-chromium-b014812705fc80bff0a5c120dfcef88f349816dc.tar.gz |
BASELINE: Update Chromium to 68.0.3440.125
Change-Id: I23f19369e01f688e496f5bf179abb521ad73874f
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/components/mirroring/service/session_monitor_unittest.cc')
-rw-r--r-- | chromium/components/mirroring/service/session_monitor_unittest.cc | 397 |
1 files changed, 397 insertions, 0 deletions
diff --git a/chromium/components/mirroring/service/session_monitor_unittest.cc b/chromium/components/mirroring/service/session_monitor_unittest.cc new file mode 100644 index 00000000000..c887eaa0a9f --- /dev/null +++ b/chromium/components/mirroring/service/session_monitor_unittest.cc @@ -0,0 +1,397 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/mirroring/service/session_monitor.h" + +#include "base/bind.h" +#include "base/callback.h" +#include "base/json/json_reader.h" +#include "base/json/json_writer.h" +#include "base/macros.h" +#include "base/test/mock_callback.h" +#include "base/test/scoped_task_environment.h" +#include "base/time/default_tick_clock.h" +#include "components/mirroring/service/message_dispatcher.h" +#include "components/mirroring/service/mirror_settings.h" +#include "components/mirroring/service/value_util.h" +#include "components/mirroring/service/wifi_status_monitor.h" +#include "media/cast/cast_environment.h" +#include "media/cast/test/utility/net_utility.h" +#include "mojo/public/cpp/bindings/strong_binding.h" +#include "net/base/ip_endpoint.h" +#include "services/network/test/test_url_loader_factory.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace mirroring { + +namespace { + +constexpr int kRetentionBytes = 512 * 1024; // 512k. + +void VerifyStringValue(const base::Value& raw_value, + const std::string& key, + const std::string& expected_value) { + std::string data; + EXPECT_TRUE(GetString(raw_value, key, &data)); + EXPECT_EQ(expected_value, data); +} + +void VerifyBoolValue(const base::Value& raw_value, + const std::string& key, + bool expected_value) { + bool data; + EXPECT_TRUE(GetBool(raw_value, key, &data)); + EXPECT_EQ(expected_value, data); +} + +void VerifyIntValue(const base::Value& raw_value, + const std::string& key, + int32_t expected_value) { + int32_t data; + EXPECT_TRUE(GetInt(raw_value, key, &data)); + EXPECT_EQ(expected_value, data); +} + +void VerifyWifiStatus(const base::Value& raw_value, + double starting_snr, + int starting_speed, + int num_of_status) { + EXPECT_TRUE(raw_value.is_dict()); + auto* found = raw_value.FindKey("tags"); + EXPECT_TRUE(found && found->is_dict()); + auto* wifi_status = found->FindKey("receiverWifiStatus"); + EXPECT_TRUE(wifi_status && wifi_status->is_list()); + const base::Value::ListStorage& status_list = wifi_status->GetList(); + EXPECT_EQ(num_of_status, static_cast<int>(status_list.size())); + for (int i = 0; i < num_of_status; ++i) { + double snr = -1; + int32_t speed = -1; + int32_t timestamp = 0; + EXPECT_TRUE(GetDouble(status_list[i], "wifiSnr", &snr)); + EXPECT_EQ(starting_snr + i, snr); + EXPECT_TRUE(GetInt(status_list[i], "wifiSpeed", &speed)); + EXPECT_EQ(starting_speed + i, speed); + EXPECT_TRUE(GetInt(status_list[i], "timestamp", ×tamp)); + } +} + +} // namespace + +class SessionMonitorTest : public CastMessageChannel, public ::testing::Test { + public: + SessionMonitorTest() + : receiver_address_(media::cast::test::GetFreeLocalPort().address()), + message_dispatcher_(this, error_callback_.Get()) {} + ~SessionMonitorTest() override {} + + protected: + // CastMessageChannel implementation. + MOCK_METHOD1(Send, void(const CastMessage&)); + + void CreateSessionMonitor(int max_bytes, std::string* expected_settings) { + EXPECT_CALL(*this, Send(::testing::_)).Times(::testing::AtLeast(1)); + auto wifi_status_monitor = + std::make_unique<WifiStatusMonitor>(123, &message_dispatcher_); + network::mojom::URLLoaderFactoryPtr url_loader_factory; + auto test_url_loader_factory = + std::make_unique<network::TestURLLoaderFactory>(); + url_loader_factory_ = test_url_loader_factory.get(); + mojo::MakeStrongBinding(std::move(test_url_loader_factory), + mojo::MakeRequest(&url_loader_factory)); + MirrorSettings mirror_settings; + base::Value session_tags(base::Value::Type::DICTIONARY); + base::Value settings = mirror_settings.ToDictionaryValue(); + if (expected_settings) + EXPECT_TRUE(base::JSONWriter::Write(settings, expected_settings)); + session_tags.SetKey("mirrorSettings", std::move(settings)); + session_tags.SetKey("receiverProductName", base::Value("ChromeCast")); + session_tags.SetKey("shouldCaptureAudio", base::Value(true)); + session_tags.SetKey("shouldCaptureVideo", base::Value(true)); + session_monitor_ = std::make_unique<SessionMonitor>( + max_bytes, receiver_address_, std::move(session_tags), + std::move(url_loader_factory), std::move(wifi_status_monitor)); + } + + // Generates and sends |num_of_responses| WiFi status. + void SendWifiStatus(double starting_snr, + int starting_speed, + int num_of_responses) { + for (int i = 0; i < num_of_responses; ++i) { + CastMessage message; + message.message_namespace = kWebRtcNamespace; + message.json_format_data = + "{\"seqNum\":" + + std::to_string(message_dispatcher_.GetNextSeqNumber()) + + "," + "\"type\": \"STATUS_RESPONSE\"," + "\"result\": \"ok\"," + "\"status\": {" + "\"wifiSnr\":" + + std::to_string(starting_snr + i) + + "," + "\"wifiSpeed\": [1234, 5678, 3000, " + + std::to_string(starting_speed + i) + + "]," + "\"wifiFcsError\": [12, 13, 12, 12]}" // This will be ignored. + "}"; + static_cast<CastMessageChannel*>(&message_dispatcher_)->Send(message); + scoped_task_environment_.RunUntilIdle(); + } + } + + void StartStreamingSession() { + cast_environment_ = new media::cast::CastEnvironment( + base::DefaultTickClock::GetInstance(), + scoped_task_environment_.GetMainThreadTaskRunner(), + scoped_task_environment_.GetMainThreadTaskRunner(), + scoped_task_environment_.GetMainThreadTaskRunner()); + EXPECT_TRUE(session_monitor_); + session_monitor_->StartStreamingSession(cast_environment_, + SessionMonitor::AUDIO_AND_VIDEO, + false /* is_remoting */); + scoped_task_environment_.RunUntilIdle(); + } + + void StopStreamingSession() { + EXPECT_TRUE(session_monitor_); + session_monitor_->StopStreamingSession(); + cast_environment_ = nullptr; + scoped_task_environment_.RunUntilIdle(); + } + + std::vector<SessionMonitor::EventsAndStats> AssembleBundleAndVerify( + const std::vector<int32_t>& bundle_sizes) { + std::vector<SessionMonitor::EventsAndStats> bundles = + session_monitor_->AssembleBundlesAndClear(bundle_sizes); + scoped_task_environment_.RunUntilIdle(); + EXPECT_EQ(bundle_sizes.size(), bundles.size()); + for (size_t i = 0; i < bundles.size(); ++i) { + EXPECT_FALSE(bundles[i].first.empty()); + EXPECT_FALSE(bundles[i].second.empty()); + EXPECT_LE( + static_cast<int>(bundles[i].first.size() + bundles[i].second.size()), + bundle_sizes[i]); + } + return bundles; + } + + base::Value ReadStats(const std::string& stats_string) { + std::unique_ptr<base::Value> stats_ptr = + base::JSONReader::Read(stats_string); + EXPECT_TRUE(stats_ptr); + base::Value stats = base::Value::FromUniquePtrValue(std::move(stats_ptr)); + EXPECT_TRUE(stats.is_list()); + return stats; + } + + void SendReceiverSetupInfo(const std::string& setup_info) { + url_loader_factory_->AddResponse( + "http://" + receiver_address_.ToString() + ":8008/setup/eureka_info", + setup_info); + scoped_task_environment_.RunUntilIdle(); + } + + void TakeSnapshot() { + ASSERT_TRUE(session_monitor_); + session_monitor_->TakeSnapshot(); + scoped_task_environment_.RunUntilIdle(); + } + + void ReportError(SessionError error) { + ASSERT_TRUE(session_monitor_); + session_monitor_->OnStreamingError(error); + scoped_task_environment_.RunUntilIdle(); + } + + private: + base::test::ScopedTaskEnvironment scoped_task_environment_; + const net::IPAddress receiver_address_; + base::MockCallback<MessageDispatcher::ErrorCallback> error_callback_; + MessageDispatcher message_dispatcher_; + network::TestURLLoaderFactory* url_loader_factory_ = nullptr; + std::unique_ptr<SessionMonitor> session_monitor_; + scoped_refptr<media::cast::CastEnvironment> cast_environment_ = nullptr; + + DISALLOW_COPY_AND_ASSIGN(SessionMonitorTest); +}; + +TEST_F(SessionMonitorTest, ProvidesExpectedTags) { + std::string expected_settings; + CreateSessionMonitor(kRetentionBytes, &expected_settings); + SendWifiStatus(34, 2000, 5); + StartStreamingSession(); + std::vector<int32_t> bundle_sizes({kRetentionBytes}); + std::vector<SessionMonitor::EventsAndStats> bundles = + AssembleBundleAndVerify(bundle_sizes); + + base::Value stats = ReadStats(bundles[0].second); + const base::Value::ListStorage& stats_list = stats.GetList(); + ASSERT_EQ(1u, stats_list.size()); + // Verify tags. + EXPECT_TRUE(stats_list[0].is_dict()); + auto* found = stats_list[0].FindKey("video"); + EXPECT_TRUE(found && found->is_dict()); + found = stats_list[0].FindKey("audio"); + EXPECT_TRUE(found && found->is_dict()); + found = stats_list[0].FindKey("tags"); + EXPECT_TRUE(found && found->is_dict()); + // Verify session tags. + VerifyStringValue(*found, "activity", "audio+video streaming"); + VerifyStringValue(*found, "receiverProductName", "ChromeCast"); + VerifyBoolValue(*found, "shouldCaptureAudio", true); + VerifyBoolValue(*found, "shouldCaptureVideo", true); + auto* settings = found->FindKey("mirrorSettings"); + EXPECT_TRUE(settings && settings->is_dict()); + std::string settings_string; + EXPECT_TRUE(base::JSONWriter::Write(*settings, &settings_string)); + EXPECT_EQ(expected_settings, settings_string); + VerifyWifiStatus(stats_list[0], 34, 2000, 5); +} + +// Test for multiple streaming sessions. +TEST_F(SessionMonitorTest, MultipleSessions) { + CreateSessionMonitor(kRetentionBytes, nullptr); + StartStreamingSession(); + StopStreamingSession(); + // Starts the second streaming session. + StartStreamingSession(); + StopStreamingSession(); + std::vector<int32_t> bundle_sizes({kRetentionBytes}); + std::vector<SessionMonitor::EventsAndStats> bundles = + AssembleBundleAndVerify(bundle_sizes); + base::Value stats = ReadStats(bundles[0].second); + const base::Value::ListStorage& stats_list = stats.GetList(); + // There should be two sessions in the recorded stats. + EXPECT_EQ(2u, stats_list.size()); +} + +TEST_F(SessionMonitorTest, ConfigureMaxRetentionBytes) { + // 2500 is an estimate number of bytes for a snapshot that includes tags and + // five WiFi status records. + CreateSessionMonitor(2500, nullptr); + SendWifiStatus(34, 2000, 5); + StartStreamingSession(); + StopStreamingSession(); + SendWifiStatus(54, 3000, 5); + StartStreamingSession(); + StopStreamingSession(); + std::vector<int32_t> bundle_sizes({kRetentionBytes}); + std::vector<SessionMonitor::EventsAndStats> bundles = + AssembleBundleAndVerify(bundle_sizes); + base::Value stats = ReadStats(bundles[0].second); + const base::Value::ListStorage& stats_list = stats.GetList(); + // Expect to only record the second session. + ASSERT_EQ(1u, stats_list.size()); + VerifyWifiStatus(stats_list[0], 54, 3000, 5); +} + +TEST_F(SessionMonitorTest, AssembleBundlesWithVaryingSizes) { + CreateSessionMonitor(kRetentionBytes, nullptr); + SendWifiStatus(34, 2000, 5); + StartStreamingSession(); + StopStreamingSession(); + SendWifiStatus(54, 3000, 5); + StartStreamingSession(); + StopStreamingSession(); + std::vector<int32_t> bundle_sizes({2500, kRetentionBytes}); + std::vector<SessionMonitor::EventsAndStats> bundles = + AssembleBundleAndVerify(bundle_sizes); + + // Expect the first bundle has only one session. + base::Value stats = ReadStats(bundles[0].second); + const base::Value::ListStorage& stats_list = stats.GetList(); + // Expect to only record the second session. + ASSERT_EQ(1u, stats_list.size()); + VerifyWifiStatus(stats_list[0], 54, 3000, 5); + + // Expect the second bundle has both sessions. + stats = ReadStats(bundles[1].second); + const base::Value::ListStorage& stats_list2 = stats.GetList(); + ASSERT_EQ(2u, stats_list2.size()); + VerifyWifiStatus(stats_list2[0], 34, 2000, 5); + VerifyWifiStatus(stats_list2[1], 54, 3000, 5); +} + +TEST_F(SessionMonitorTest, ErrorTags) { + CreateSessionMonitor(kRetentionBytes, nullptr); + StartStreamingSession(); + TakeSnapshot(); // Take the first snapshot. + ReportError(VIDEO_CAPTURE_ERROR); + ReportError(RTP_STREAM_ERROR); + TakeSnapshot(); // Take the second snapshot. + StopStreamingSession(); // Take the third snapshot. + + std::vector<int32_t> bundle_sizes({kRetentionBytes}); + std::vector<SessionMonitor::EventsAndStats> bundles = + AssembleBundleAndVerify(bundle_sizes); + base::Value stats = ReadStats(bundles[0].second); + const base::Value::ListStorage& stats_list = stats.GetList(); + // There should be three snapshots in the bundle. + ASSERT_EQ(3u, stats_list.size()); + + // The first and the third snapshots should have no error tags. + auto* tags = stats_list[0].FindKey("tags"); + ASSERT_TRUE(tags); + EXPECT_FALSE(tags->FindKey("streamingErrorTime")); + EXPECT_FALSE(tags->FindKey("streamingErrorMessage")); + tags = stats_list[2].FindKey("tags"); + ASSERT_TRUE(tags); + EXPECT_FALSE(tags->FindKey("streamingErrorTime")); + EXPECT_FALSE(tags->FindKey("streamingErrorMessage")); + + // The second snapshot should have the error tags. Only the first error is + // recorded. + tags = stats_list[1].FindKey("tags"); + ASSERT_TRUE(tags && tags->FindKey("streamingErrorTime")); + VerifyStringValue(*tags, "streamingErrorMessage", "Video capture error"); +} + +TEST_F(SessionMonitorTest, ReceiverSetupInfo) { + CreateSessionMonitor(kRetentionBytes, nullptr); + StartStreamingSession(); + // This snapshot should have no receiver setup info tags. + TakeSnapshot(); + + const std::string receiver_setup_info = + "{" + "\"cast_build_revision\": \"1.26.0.1\"," + "\"connected\": true," + "\"ethernet_connected\": false," + "\"has_update\": false," + "\"uptime\": 132536 }"; + + SendReceiverSetupInfo(receiver_setup_info); + + // A final snapshot is taken and should have receiver setup info tags. + StopStreamingSession(); + + std::vector<int32_t> bundle_sizes({kRetentionBytes}); + std::vector<SessionMonitor::EventsAndStats> bundles = + AssembleBundleAndVerify(bundle_sizes); + base::Value stats = ReadStats(bundles[0].second); + const base::Value::ListStorage& stats_list = stats.GetList(); + // There should be two snapshots in the bundle. + EXPECT_EQ(2u, stats_list.size()); + + // The first snapshot should have no receiver setup info tags. + auto* tags = stats_list[0].FindKey("tags"); + ASSERT_TRUE(tags); + EXPECT_FALSE(tags->FindKey("receiverVersion")); + EXPECT_FALSE(tags->FindKey("receiverConnected")); + EXPECT_FALSE(tags->FindKey("receiverOnEthernet")); + EXPECT_FALSE(tags->FindKey("receiverHasUpdatePending")); + EXPECT_FALSE(tags->FindKey("receiverUptimeSeconds")); + + // The second snapshot should have the receiver setup info tags. + tags = stats_list[1].FindKey("tags"); + ASSERT_TRUE(tags); + VerifyStringValue(*tags, "receiverVersion", "1.26.0.1"); + VerifyBoolValue(*tags, "receiverConnected", true); + VerifyBoolValue(*tags, "receiverOnEthernet", false); + VerifyBoolValue(*tags, "receiverHasUpdatePending", false); + VerifyIntValue(*tags, "receiverUptimeSeconds", 132536); +} + +} // namespace mirroring |