blob: a4296e3086b7b0494821fa34b42867a5048dfdbc [file] [log] [blame]
// 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 "chrome/browser/media/router/providers/cast/cast_session_tracker.h"
#include "base/json/json_reader.h"
#include "chrome/browser/media/router/test/test_helper.h"
#include "chrome/common/media_router/test/test_helper.h"
#include "components/cast_channel/cast_test_util.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using testing::_;
namespace media_router {
namespace {
constexpr char kSessionId[] = "sessionId";
constexpr char kReceiverStatus[] = R"({
"status": {
"applications": [{
"appId": "ABCDEFGH",
"displayName": "App display name",
"namespaces": [
{"name": "urn:x-cast:com.google.cast.media"},
{"name": "urn:x-cast:com.google.foo"}
],
"sessionId": "sessionId",
"statusText":"App status",
"transportId":"transportId"
}]
}
})";
// Receiver status for the backdrop (idle) app.
constexpr char kIdleReceiverStatus[] = R"({
"status": {
"applications": [{
"appId": "E8C28D3C",
"displayName": "Backdrop",
"namespaces": [
{"name": "urn:x-cast:com.google.cast.media"},
{"name": "urn:x-cast:com.google.foo"}
],
"sessionId": "sessionId",
"statusText":"App status",
"transportId":"transportId"
}]
}
})";
} // namespace
class MockCastSessionObserver : public CastSessionTracker::Observer {
public:
MockCastSessionObserver() = default;
~MockCastSessionObserver() override = default;
MOCK_METHOD2(OnSessionAddedOrUpdated,
void(const MediaSinkInternal& sink, const CastSession& session));
MOCK_METHOD1(OnSessionRemoved, void(const MediaSinkInternal& sink));
};
class CastSessionTrackerTest : public testing::Test {
public:
CastSessionTrackerTest()
: socket_service_(base::CreateSingleThreadTaskRunnerWithTraits(
{content::BrowserThread::UI})),
message_handler_(&socket_service_),
session_tracker_(&media_sink_service_,
&message_handler_,
socket_service_.task_runner()) {
base::RunLoop().RunUntilIdle();
}
void SetUp() override { session_tracker_.AddObserver(&observer_); }
void TearDown() override { session_tracker_.RemoveObserver(&observer_); }
void AddSinkAndSendReceiverStatusResponse() {
EXPECT_CALL(message_handler_,
RequestReceiverStatus(sink_.cast_data().cast_channel_id));
media_sink_service_.AddOrUpdateSink(sink_);
auto receiver_status = base::JSONReader::Read(kReceiverStatus);
ASSERT_TRUE(receiver_status);
cast_channel::InternalMessage receiver_status_message(
cast_channel::CastMessageType::kReceiverStatus,
std::move(*receiver_status));
EXPECT_CALL(observer_, OnSessionAddedOrUpdated(sink_, _));
session_tracker_.OnInternalMessage(sink_.cast_data().cast_channel_id,
receiver_status_message);
}
protected:
content::TestBrowserThreadBundle thread_bundle_;
cast_channel::MockCastSocketService socket_service_;
cast_channel::MockCastMessageHandler message_handler_;
TestMediaSinkService media_sink_service_;
CastSessionTracker session_tracker_;
MockCastSessionObserver observer_;
MediaSinkInternal sink_ = CreateCastSink(1);
};
TEST_F(CastSessionTrackerTest, QueryReceiverOnSinkAdded) {
AddSinkAndSendReceiverStatusResponse();
// Receiver status is sent again when sinks is updated.
sink_.cast_data().cast_channel_id = 2;
EXPECT_CALL(message_handler_,
RequestReceiverStatus(sink_.cast_data().cast_channel_id));
media_sink_service_.AddOrUpdateSink(sink_);
}
TEST_F(CastSessionTrackerTest, RemoveSessionOnSinkRemoved) {
AddSinkAndSendReceiverStatusResponse();
EXPECT_CALL(observer_, OnSessionRemoved(sink_));
media_sink_service_.RemoveSink(sink_);
}
TEST_F(CastSessionTrackerTest, RemoveSession) {
AddSinkAndSendReceiverStatusResponse();
auto receiver_status = base::JSONReader::Read(kIdleReceiverStatus);
ASSERT_TRUE(receiver_status);
cast_channel::InternalMessage receiver_status_message(
cast_channel::CastMessageType::kReceiverStatus,
std::move(*receiver_status));
EXPECT_CALL(observer_, OnSessionRemoved(sink_));
session_tracker_.OnInternalMessage(sink_.cast_data().cast_channel_id,
receiver_status_message);
}
TEST_F(CastSessionTrackerTest, sessions_by_sink_id) {
EXPECT_TRUE(session_tracker_.sessions_by_sink_id().empty());
AddSinkAndSendReceiverStatusResponse();
const auto& sessions = session_tracker_.sessions_by_sink_id();
EXPECT_EQ(1u, sessions.size());
auto it = sessions.find(sink_.sink().id());
ASSERT_TRUE(it != sessions.end());
EXPECT_EQ(kSessionId, it->second->session_id());
EXPECT_TRUE(session_tracker_.GetSessionById(kSessionId));
}
} // namespace media_router