blob: cbb44391dd2202a7f18d726e677abb6ac98c5694 [file] [log] [blame]
Stuart Langley80845862018-09-05 00:47:291// Copyright 2018 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <memory>
6
7#include "base/strings/strcat.h"
8#include "base/test/test_mock_time_task_runner.h"
9#include "components/drive/drive_notification_manager.h"
10#include "components/drive/drive_notification_observer.h"
11#include "components/invalidation/impl/fake_invalidation_service.h"
Maksim Moskvitin1817bfa2020-03-03 11:01:1612#include "components/invalidation/public/topic_invalidation_map.h"
Stuart Langley80845862018-09-05 00:47:2913#include "testing/gtest/include/gtest/gtest.h"
14
15namespace drive {
16
17namespace {
18
Maksim Moskvitin1817bfa2020-03-03 11:01:1619const syncer::Topic kDefaultCorpusTopic = "Drive";
Stuart Langley80845862018-09-05 00:47:2920
21struct ShutdownHelper {
22 template <typename T>
23 void operator()(T* object) const {
24 if (object) {
25 object->Shutdown();
26 delete object;
27 }
28 }
29};
30
31class FakeDriveNotificationObserver : public DriveNotificationObserver {
32 public:
33 ~FakeDriveNotificationObserver() override {}
34
35 // DriveNotificationObserver overrides
Sam McNallye4bd01c2018-10-17 23:51:1136 void OnNotificationReceived(
37 const std::map<std::string, int64_t>& ids) override {
Stuart Langley80845862018-09-05 00:47:2938 notification_ids_ = ids;
39 }
40 void OnNotificationTimerFired() override {}
41 void OnPushNotificationEnabled(bool enabled) override {}
42
Sam McNallye4bd01c2018-10-17 23:51:1143 const std::map<std::string, int64_t> GetNotificationIds() const {
Stuart Langley80845862018-09-05 00:47:2944 return notification_ids_;
45 }
46
47 void ClearNotificationIds() { notification_ids_.clear(); }
48
49 private:
Sam McNallye4bd01c2018-10-17 23:51:1150 std::map<std::string, int64_t> notification_ids_;
Stuart Langley80845862018-09-05 00:47:2951};
52
Maksim Moskvitin1817bfa2020-03-03 11:01:1653syncer::Topic CreateTeamDriveInvalidationTopic(
Stuart Langley80845862018-09-05 00:47:2954 const std::string& team_drive_id) {
Maksim Moskvitin1817bfa2020-03-03 11:01:1655 return base::StrCat({"team-drive-", team_drive_id});
Stuart Langley80845862018-09-05 00:47:2956}
57
58} // namespace
59
60class DriveNotificationManagerTest : public testing::Test {
61 protected:
62 void SetUp() override {
63 task_runner_ = base::MakeRefCounted<base::TestMockTimeTaskRunner>(
64 base::TestMockTimeTaskRunner::Type::kBoundToThread);
65 fake_invalidation_service_ =
66 std::make_unique<invalidation::FakeInvalidationService>();
67 drive_notification_observer_ =
68 std::make_unique<FakeDriveNotificationObserver>();
69
70 // Can't use make_unique with a custom deleter.
71 drive_notification_manager_.reset(
72 new DriveNotificationManager(fake_invalidation_service_.get()));
73
74 drive_notification_manager_->AddObserver(
75 drive_notification_observer_.get());
76 }
77
78 void TearDown() override {
79 drive_notification_manager_->RemoveObserver(
80 drive_notification_observer_.get());
81 }
82
83 scoped_refptr<base::TestMockTimeTaskRunner> task_runner_;
84 std::unique_ptr<invalidation::FakeInvalidationService>
85 fake_invalidation_service_;
86 std::unique_ptr<FakeDriveNotificationObserver> drive_notification_observer_;
87 std::unique_ptr<DriveNotificationManager, ShutdownHelper>
88 drive_notification_manager_;
89};
90
91TEST_F(DriveNotificationManagerTest, RegisterTeamDrives) {
92 // By default, we should have registered for default corpus notifications on
93 // initialization.
Maksim Moskvitind705f6a2020-02-18 11:16:5594 auto subscribed_topics = fake_invalidation_service_->invalidator_registrar()
95 .GetAllSubscribedTopics();
Stuart Langley80845862018-09-05 00:47:2996
Maksim Moskvitin1817bfa2020-03-03 11:01:1697 // TODO(crbug.com/1029698): replace syncer::Topics with syncer::TopicSet once
98 // |is_public| become the part of dedicated syncer::Topic struct. This should
99 // simplify this test.
100 syncer::Topics expected_topics;
101 expected_topics.emplace(kDefaultCorpusTopic,
102 syncer::TopicMetadata{/*is_public=*/false});
Maksim Moskvitind705f6a2020-02-18 11:16:55103 EXPECT_EQ(expected_topics, subscribed_topics);
Stuart Langley80845862018-09-05 00:47:29104
105 const std::string team_drive_id_1 = "td_id_1";
Maksim Moskvitin1817bfa2020-03-03 11:01:16106 const auto team_drive_1_topic =
107 CreateTeamDriveInvalidationTopic(team_drive_id_1);
Stuart Langley80845862018-09-05 00:47:29108
109 // Add the team drive
110 drive_notification_manager_->UpdateTeamDriveIds({team_drive_id_1}, {});
Maksim Moskvitind705f6a2020-02-18 11:16:55111 subscribed_topics = fake_invalidation_service_->invalidator_registrar()
112 .GetAllSubscribedTopics();
Stuart Langley80845862018-09-05 00:47:29113
Maksim Moskvitin1817bfa2020-03-03 11:01:16114 expected_topics.emplace(team_drive_1_topic,
115 syncer::TopicMetadata{/*is_public=*/true});
Maksim Moskvitind705f6a2020-02-18 11:16:55116 EXPECT_EQ(expected_topics, subscribed_topics);
Stuart Langley80845862018-09-05 00:47:29117
118 // Remove the team drive.
119 drive_notification_manager_->UpdateTeamDriveIds({}, {team_drive_id_1});
Maksim Moskvitind705f6a2020-02-18 11:16:55120 subscribed_topics = fake_invalidation_service_->invalidator_registrar()
121 .GetAllSubscribedTopics();
Stuart Langley80845862018-09-05 00:47:29122
Maksim Moskvitin1817bfa2020-03-03 11:01:16123 expected_topics.erase(team_drive_1_topic);
Maksim Moskvitind705f6a2020-02-18 11:16:55124 EXPECT_EQ(expected_topics, subscribed_topics);
Stuart Langley80845862018-09-05 00:47:29125
126 const std::string team_drive_id_2 = "td_id_2";
Maksim Moskvitin1817bfa2020-03-03 11:01:16127 const auto team_drive_2_topic =
128 CreateTeamDriveInvalidationTopic(team_drive_id_2);
Stuart Langley80845862018-09-05 00:47:29129
Maksim Moskvitin1817bfa2020-03-03 11:01:16130 // Add two team drives.
Stuart Langley80845862018-09-05 00:47:29131 drive_notification_manager_->UpdateTeamDriveIds(
132 {team_drive_id_1, team_drive_id_2}, {});
Maksim Moskvitind705f6a2020-02-18 11:16:55133 subscribed_topics = fake_invalidation_service_->invalidator_registrar()
134 .GetAllSubscribedTopics();
Stuart Langley80845862018-09-05 00:47:29135
Maksim Moskvitin1817bfa2020-03-03 11:01:16136 expected_topics.emplace(team_drive_1_topic,
137 syncer::TopicMetadata{/*is_public=*/true});
138 expected_topics.emplace(team_drive_2_topic,
139 syncer::TopicMetadata{/*is_public=*/true});
Maksim Moskvitind705f6a2020-02-18 11:16:55140 EXPECT_EQ(expected_topics, subscribed_topics);
Stuart Langley80845862018-09-05 00:47:29141
Maksim Moskvitin1817bfa2020-03-03 11:01:16142 // Remove the first team drive.
Stuart Langley80845862018-09-05 00:47:29143 drive_notification_manager_->UpdateTeamDriveIds({}, {team_drive_id_1});
Maksim Moskvitind705f6a2020-02-18 11:16:55144 subscribed_topics = fake_invalidation_service_->invalidator_registrar()
145 .GetAllSubscribedTopics();
Stuart Langley80845862018-09-05 00:47:29146
Maksim Moskvitin1817bfa2020-03-03 11:01:16147 expected_topics.erase(team_drive_1_topic);
Maksim Moskvitind705f6a2020-02-18 11:16:55148 EXPECT_EQ(expected_topics, subscribed_topics);
Stuart Langley80845862018-09-05 00:47:29149
150 // Remove a team drive that doesn't exists with no changes.
151 const std::string team_drive_id_3 = "td_id_3";
152 drive_notification_manager_->UpdateTeamDriveIds({}, {team_drive_id_3});
Maksim Moskvitind705f6a2020-02-18 11:16:55153 subscribed_topics = fake_invalidation_service_->invalidator_registrar()
154 .GetAllSubscribedTopics();
Stuart Langley80845862018-09-05 00:47:29155
Maksim Moskvitind705f6a2020-02-18 11:16:55156 EXPECT_EQ(expected_topics, subscribed_topics);
Stuart Langley80845862018-09-05 00:47:29157}
158
159TEST_F(DriveNotificationManagerTest, TestBatchInvalidation) {
160 // By default we'll be registered for the default change notification.
161
162 // Emitting an invalidation should not call our observer until the timer
163 // expires.
164 fake_invalidation_service_->EmitInvalidationForTest(
Maksim Moskvitin1817bfa2020-03-03 11:01:16165 syncer::Invalidation::InitUnknownVersion(kDefaultCorpusTopic));
Stuart Langley80845862018-09-05 00:47:29166 EXPECT_TRUE(drive_notification_observer_->GetNotificationIds().empty());
167
Stuart Langley6477fb062018-11-15 03:03:36168 task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(30));
Stuart Langley80845862018-09-05 00:47:29169
170 // Default corpus is has the id "" when sent to observers.
Sam McNally9840fa72018-10-19 01:33:59171 std::map<std::string, int64_t> expected_ids = {{"", -1}};
Stuart Langley80845862018-09-05 00:47:29172 EXPECT_EQ(expected_ids, drive_notification_observer_->GetNotificationIds());
173 drive_notification_observer_->ClearNotificationIds();
174
175 // Register a team drive for notifications
176 const std::string team_drive_id_1 = "td_id_1";
Maksim Moskvitin1817bfa2020-03-03 11:01:16177 const auto team_drive_1_topic =
178 CreateTeamDriveInvalidationTopic(team_drive_id_1);
Stuart Langley80845862018-09-05 00:47:29179 drive_notification_manager_->UpdateTeamDriveIds({team_drive_id_1}, {});
180
181 // Emit invalidation for default corpus, should not emit a team drive
182 // invalidation.
183 fake_invalidation_service_->EmitInvalidationForTest(
Maksim Moskvitin1817bfa2020-03-03 11:01:16184 syncer::Invalidation::Init(kDefaultCorpusTopic, 1, ""));
Stuart Langley80845862018-09-05 00:47:29185 EXPECT_TRUE(drive_notification_observer_->GetNotificationIds().empty());
186
Stuart Langley6477fb062018-11-15 03:03:36187 task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(30));
Stuart Langley80845862018-09-05 00:47:29188
189 // Default corpus is has the id "" when sent to observers.
Sam McNally9438e4b2018-10-30 08:14:01190 expected_ids = {{"", 2}};
Stuart Langley80845862018-09-05 00:47:29191 EXPECT_EQ(expected_ids, drive_notification_observer_->GetNotificationIds());
192 drive_notification_observer_->ClearNotificationIds();
193
194 // Emit team drive invalidation
195 fake_invalidation_service_->EmitInvalidationForTest(
Maksim Moskvitin1817bfa2020-03-03 11:01:16196 syncer::Invalidation::Init(team_drive_1_topic, 2, ""));
Stuart Langley80845862018-09-05 00:47:29197 EXPECT_TRUE(drive_notification_observer_->GetNotificationIds().empty());
198
Stuart Langley6477fb062018-11-15 03:03:36199 task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(30));
Sam McNallye4bd01c2018-10-17 23:51:11200 expected_ids = {{team_drive_id_1, 2}};
Stuart Langley80845862018-09-05 00:47:29201 EXPECT_EQ(expected_ids, drive_notification_observer_->GetNotificationIds());
202 drive_notification_observer_->ClearNotificationIds();
203
204 // Emit both default corpus and team drive.
205 fake_invalidation_service_->EmitInvalidationForTest(
Maksim Moskvitin1817bfa2020-03-03 11:01:16206 syncer::Invalidation::Init(kDefaultCorpusTopic, 1, ""));
Stuart Langley80845862018-09-05 00:47:29207 fake_invalidation_service_->EmitInvalidationForTest(
Maksim Moskvitin1817bfa2020-03-03 11:01:16208 syncer::Invalidation::Init(team_drive_1_topic, 2, ""));
Sam McNally9438e4b2018-10-30 08:14:01209
210 // Emit with an earlier version. This should be ignored.
211 fake_invalidation_service_->EmitInvalidationForTest(
Maksim Moskvitin1817bfa2020-03-03 11:01:16212 syncer::Invalidation::Init(kDefaultCorpusTopic, 0, ""));
Sam McNally9438e4b2018-10-30 08:14:01213
214 // Emit without a version. This should be ignored too.
215 fake_invalidation_service_->EmitInvalidationForTest(
Maksim Moskvitin1817bfa2020-03-03 11:01:16216 syncer::Invalidation::InitUnknownVersion(kDefaultCorpusTopic));
Sam McNally9438e4b2018-10-30 08:14:01217
Stuart Langley80845862018-09-05 00:47:29218 EXPECT_TRUE(drive_notification_observer_->GetNotificationIds().empty());
219
Stuart Langley6477fb062018-11-15 03:03:36220 task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(30));
Sam McNally9438e4b2018-10-30 08:14:01221 expected_ids = {{"", 2}, {team_drive_id_1, 2}};
Stuart Langley80845862018-09-05 00:47:29222 EXPECT_EQ(expected_ids, drive_notification_observer_->GetNotificationIds());
223}
224
Austin Tankiang6f52aa02020-09-30 14:44:36225TEST_F(DriveNotificationManagerTest, UnregisterOnNoObservers) {
226 // By default, we should have registered for default corpus notifications on
227 // initialization.
228 auto subscribed_topics = fake_invalidation_service_->invalidator_registrar()
229 .GetAllSubscribedTopics();
230
231 // TODO(crbug.com/1029698): replace syncer::Topics with syncer::TopicSet once
232 // |is_public| become the part of dedicated syncer::Topic struct.
233 syncer::Topics expected_topics;
234 expected_topics.emplace(kDefaultCorpusTopic,
235 syncer::TopicMetadata{/*is_public=*/false});
236 EXPECT_EQ(expected_topics, subscribed_topics);
237
238 // Stop observing drive notification manager.
239 drive_notification_manager_->RemoveObserver(
240 drive_notification_observer_.get());
241
242 subscribed_topics = fake_invalidation_service_->invalidator_registrar()
243 .GetAllSubscribedTopics();
244 EXPECT_EQ(syncer::Topics(), subscribed_topics);
245
246 // Start observing drive notification manager again. It should subscribe to
247 // the previously subscried topics.
248 drive_notification_manager_->AddObserver(drive_notification_observer_.get());
249 subscribed_topics = fake_invalidation_service_->invalidator_registrar()
250 .GetAllSubscribedTopics();
251 EXPECT_EQ(expected_topics, subscribed_topics);
252}
253
Stuart Langley80845862018-09-05 00:47:29254} // namespace drive