blob: 6b485fccda1c9dc753f2b68fbb09203f8ec9d159 [file] [log] [blame]
// Copyright 2015 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/media_router/browser/issue_manager.h"
#include <string>
#include "base/test/task_environment.h"
#include "components/media_router/browser/test/test_helper.h"
#include "content/public/test/browser_task_environment.h"
#include "testing/gmock/include/gmock/gmock.h"
using testing::_;
using testing::SaveArg;
namespace media_router {
namespace {
IssueInfo CreateTestIssue(IssueInfo::Severity severity) {
IssueInfo issue("title", severity, "sinkId1");
issue.message = "message";
return issue;
}
} // namespace
class IssueManagerTest : public ::testing::Test {
protected:
IssueManagerTest()
: task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
~IssueManagerTest() override = default;
content::BrowserTaskEnvironment task_environment_;
IssueManager manager_;
};
TEST_F(IssueManagerTest, AddAndClearIssue) {
IssueInfo issue_info1 = CreateTestIssue(IssueInfo::Severity::WARNING);
// Add initial issue.
manager_.AddIssue(issue_info1);
Issue issue1 = Issue::CreateIssueWithIssueInfo(IssueInfo());
MockIssuesObserver observer(&manager_);
EXPECT_CALL(observer, OnIssue(_)).WillOnce(SaveArg<0>(&issue1));
observer.Init();
ASSERT_TRUE(testing::Mock::VerifyAndClearExpectations(&observer));
EXPECT_EQ(issue_info1, issue1.info());
IssueInfo issue_info2 = CreateTestIssue(IssueInfo::Severity::NOTIFICATION);
Issue issue2 = Issue::CreateIssueWithIssueInfo(IssueInfo());
manager_.AddIssue(issue_info2);
// Clear |issue1|. Observer will be notified with |issue2|.
EXPECT_CALL(observer, OnIssue(_)).WillOnce(SaveArg<0>(&issue2));
manager_.ClearIssue(issue1.id());
ASSERT_TRUE(testing::Mock::VerifyAndClearExpectations(&observer));
EXPECT_EQ(issue_info2, issue2.info());
// All issues cleared. Observer will be notified with |nullptr| that there are
// no more issues.
EXPECT_CALL(observer, OnIssuesCleared());
manager_.ClearIssue(issue2.id());
}
TEST_F(IssueManagerTest, AddPermissionIssue) {
IssueInfo issue_info1 = CreateTestIssue(IssueInfo::Severity::WARNING);
// Add initial issue.
Issue issue1 = Issue::CreateIssueWithIssueInfo(IssueInfo());
MockIssuesObserver observer(&manager_);
EXPECT_CALL(observer, OnIssue(_)).WillOnce(SaveArg<0>(&issue1));
manager_.AddIssue(issue_info1);
observer.Init();
testing::Mock::VerifyAndClearExpectations(&observer);
EXPECT_EQ(issue_info1, issue1.info());
// The permission rejected issue will clear out existing issues and be the top
// issue.
Issue issue2 = Issue::CreateIssueWithIssueInfo(IssueInfo());
EXPECT_CALL(observer, OnIssue(_)).WillOnce(SaveArg<0>(&issue2));
manager_.AddPermissionRejectedIssue();
testing::Mock::VerifyAndClearExpectations(&observer);
EXPECT_TRUE(issue2.is_permission_rejected_issue());
}
TEST_F(IssueManagerTest, IssuesDeletionShouldNotAffectOrder) {
MockIssuesObserver observer(&manager_);
observer.Init();
Issue issue1 = Issue::CreateIssueWithIssueInfo(IssueInfo());
EXPECT_CALL(observer, OnIssue(_)).WillOnce(SaveArg<0>(&issue1));
IssueInfo issue_info1 = CreateTestIssue(IssueInfo::Severity::NOTIFICATION);
manager_.AddIssue(issue_info1);
IssueInfo issue_info2 = CreateTestIssue(IssueInfo::Severity::WARNING);
manager_.AddIssue(issue_info2);
IssueInfo issue_info3 = CreateTestIssue(IssueInfo::Severity::NOTIFICATION);
manager_.AddIssue(issue_info3);
ASSERT_TRUE(testing::Mock::VerifyAndClearExpectations(&observer));
EXPECT_EQ(issue_info1, issue1.info());
Issue issue2 = Issue::CreateIssueWithIssueInfo(IssueInfo());
EXPECT_CALL(observer, OnIssue(_)).WillOnce(SaveArg<0>(&issue2));
manager_.ClearIssue(issue1.id());
EXPECT_EQ(issue_info2, issue2.info());
manager_.ClearAllIssues();
}
TEST_F(IssueManagerTest, AddSameIssueInfoHasNoEffect) {
IssueInfo issue_info = CreateTestIssue(IssueInfo::Severity::WARNING);
MockIssuesObserver observer(&manager_);
observer.Init();
Issue issue = Issue::CreateIssueWithIssueInfo(IssueInfo());
EXPECT_CALL(observer, OnIssue(_)).WillOnce(SaveArg<0>(&issue));
manager_.AddIssue(issue_info);
ASSERT_TRUE(testing::Mock::VerifyAndClearExpectations(&observer));
EXPECT_EQ(issue_info, issue.info());
// Adding the same IssueInfo has no effect.
manager_.AddIssue(issue_info);
EXPECT_CALL(observer, OnIssuesCleared());
manager_.ClearIssue(issue.id());
}
TEST_F(IssueManagerTest, IssuesGetAutoDismissed) {
MockIssuesObserver observer(&manager_);
observer.Init();
EXPECT_CALL(observer, OnIssue(_)).Times(1);
IssueInfo issue_info1 = CreateTestIssue(IssueInfo::Severity::NOTIFICATION);
manager_.AddIssue(issue_info1);
EXPECT_CALL(observer, OnIssuesCleared()).Times(1);
base::TimeDelta timeout = IssueManager::GetAutoDismissTimeout(issue_info1);
EXPECT_FALSE(timeout.is_zero());
EXPECT_TRUE(task_environment_.MainThreadIsIdle());
task_environment_.FastForwardBy(timeout);
EXPECT_CALL(observer, OnIssue(_)).Times(1);
IssueInfo issue_info2 = CreateTestIssue(IssueInfo::Severity::WARNING);
manager_.AddIssue(issue_info2);
EXPECT_CALL(observer, OnIssuesCleared()).Times(1);
timeout = IssueManager::GetAutoDismissTimeout(issue_info2);
EXPECT_FALSE(timeout.is_zero());
EXPECT_GT(task_environment_.GetPendingMainThreadTaskCount(), 0u);
task_environment_.FastForwardBy(timeout);
EXPECT_EQ(task_environment_.GetPendingMainThreadTaskCount(), 0u);
}
TEST_F(IssueManagerTest, IssueAutoDismissNoopsIfAlreadyCleared) {
MockIssuesObserver observer(&manager_);
observer.Init();
Issue issue1 = Issue::CreateIssueWithIssueInfo(IssueInfo());
EXPECT_CALL(observer, OnIssue(_)).Times(1).WillOnce(SaveArg<0>(&issue1));
IssueInfo issue_info1 = CreateTestIssue(IssueInfo::Severity::NOTIFICATION);
manager_.AddIssue(issue_info1);
ASSERT_TRUE(testing::Mock::VerifyAndClearExpectations(&observer));
EXPECT_CALL(observer, OnIssuesCleared()).Times(1);
EXPECT_GT(task_environment_.GetPendingMainThreadTaskCount(), 0u);
manager_.ClearIssue(issue1.id());
EXPECT_CALL(observer, OnIssuesCleared()).Times(0);
base::TimeDelta timeout = IssueManager::GetAutoDismissTimeout(issue_info1);
EXPECT_FALSE(timeout.is_zero());
task_environment_.FastForwardBy(timeout);
}
TEST_F(IssueManagerTest, ClearAllIssues) {
MockIssuesObserver observer(&manager_);
observer.Init();
EXPECT_CALL(observer, OnIssue(_)).Times(1);
manager_.AddIssue(CreateTestIssue(IssueInfo::Severity::NOTIFICATION));
manager_.AddIssue(CreateTestIssue(IssueInfo::Severity::WARNING));
EXPECT_CALL(observer, OnIssuesCleared()).Times(1);
manager_.ClearAllIssues();
}
TEST_F(IssueManagerTest, ClearTopIssueForSink) {
const char sink_id_1[] = "sink_1";
const char sink_id_2[] = "sink_2";
IssueInfo issue_info1("title", IssueInfo::Severity::WARNING, sink_id_1);
IssueInfo issue_info2("title", IssueInfo::Severity::NOTIFICATION, sink_id_2);
manager_.AddIssue(issue_info1);
manager_.AddIssue(issue_info2);
// issue_info1 is the top issue.
MockIssuesObserver observer(&manager_);
EXPECT_CALL(observer, OnIssue)
.WillOnce([&issue_info1](const Issue& received_issue) {
EXPECT_EQ(issue_info1, received_issue.info());
});
observer.Init();
testing::Mock::VerifyAndClearExpectations(&observer);
// No-op since the top issue isn't associated with sink_id_2.
EXPECT_CALL(observer, OnIssue).Times(0);
manager_.ClearTopIssueForSink(sink_id_2);
testing::Mock::VerifyAndClearExpectations(&observer);
// Clear top issue makes issue_info2 the top issue.
EXPECT_CALL(observer, OnIssue)
.WillOnce([&issue_info2](const Issue& received_issue) {
EXPECT_EQ(issue_info2, received_issue.info());
});
manager_.ClearTopIssueForSink(sink_id_1);
testing::Mock::VerifyAndClearExpectations(&observer);
EXPECT_CALL(observer, OnIssuesCleared);
manager_.ClearTopIssueForSink(sink_id_2);
testing::Mock::VerifyAndClearExpectations(&observer);
}
} // namespace media_router