1 // Copyright (c) 2012 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/macros.h"
8 #include "base/run_loop.h"
9 #include "base/strings/string_util.h"
10 #include "base/test/bind.h"
11 #include "base/test/metrics/histogram_tester.h"
12 #include "base/values.h"
13 #include "build/build_config.h"
14 #include "chrome/browser/sync/test/integration/bookmarks_helper.h"
15 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
16 #include "chrome/browser/sync/test/integration/sync_test.h"
17 #include "chrome/browser/sync/test/integration/updated_progress_marker_checker.h"
18 #include "components/bookmarks/browser/bookmark_model.h"
19 #include "components/sync/base/model_type.h"
20 #include "components/sync/base/user_selectable_type.h"
21 #include "components/sync/driver/profile_sync_service.h"
22 #include "components/sync/driver/sync_user_settings_impl.h"
23 #include "components/sync/test/fake_server/bookmark_entity_builder.h"
24 #include "components/sync/test/fake_server/entity_builder_factory.h"
25 #include "content/public/test/browser_test.h"
26
27 namespace {
28
29 using syncer::ModelType;
30 using syncer::ModelTypeFromString;
31 using syncer::ModelTypeSet;
32 using syncer::ModelTypeToString;
33 using syncer::ProxyTypes;
34 using syncer::SyncPrefs;
35 using syncer::SyncUserSettings;
36 using syncer::UserSelectableType;
37 using syncer::UserSelectableTypeSet;
38
39 const char kSyncedBookmarkURL[] = "http://www.mybookmark.com";
40 // Non-utf8 string to make sure it gets handled well.
41 const char kTestServerChips[] = "\xed\xa0\x80\xed\xbf\xbf";
42
43 // Some types show up in multiple groups. This means that there are at least two
44 // user selectable groups that will cause these types to become enabled. This
45 // affects our tests because we cannot assume that before enabling a multi type
46 // it will be disabled, because the other selectable type(s) could already be
47 // enabling it. And vice versa for disabling.
MultiGroupTypes(const ModelTypeSet & registered_types)48 ModelTypeSet MultiGroupTypes(const ModelTypeSet& registered_types) {
49 ModelTypeSet seen;
50 ModelTypeSet multi;
51 for (UserSelectableType type : UserSelectableTypeSet::All()) {
52 const ModelTypeSet grouped_types =
53 syncer::SyncUserSettingsImpl::ResolvePreferredTypesForTesting({type});
54 for (ModelType grouped_type : grouped_types) {
55 if (seen.Has(grouped_type)) {
56 multi.Put(grouped_type);
57 } else {
58 seen.Put(grouped_type);
59 }
60 }
61 }
62 multi.RetainAll(registered_types);
63 return multi;
64 }
65
66 // This test enables and disables types and verifies the type is sufficiently
67 // affected by checking for existence of a root node.
68 class EnableDisableSingleClientTest : public SyncTest {
69 public:
EnableDisableSingleClientTest()70 EnableDisableSingleClientTest() : SyncTest(SINGLE_CLIENT) {}
71 ~EnableDisableSingleClientTest() override = default;
72
73 // Don't use self-notifications as they can trigger additional sync cycles.
TestUsesSelfNotifications()74 bool TestUsesSelfNotifications() override { return false; }
75
ModelTypeExists(ModelType type)76 bool ModelTypeExists(ModelType type) {
77 base::RunLoop loop;
78 std::unique_ptr<base::ListValue> all_nodes;
79 GetSyncService(0)->GetAllNodesForDebugging(
80 base::BindLambdaForTesting([&](std::unique_ptr<base::ListValue> nodes) {
81 all_nodes = std::move(nodes);
82 loop.Quit();
83 }));
84 loop.Run();
85 // Look for the root node corresponding to |type|.
86 for (const base::Value& value : all_nodes->GetList()) {
87 DCHECK(value.is_dict());
88 const base::Value* nodes = value.FindKey("nodes");
89 DCHECK(nodes);
90 DCHECK(nodes->is_list());
91 // Ignore types that are empty, because we expect the root node.
92 if (nodes->GetList().empty()) {
93 continue;
94 }
95 const base::Value* model_type = value.FindKey("type");
96 DCHECK(model_type);
97 DCHECK(model_type->is_string());
98 if (type == ModelTypeFromString(model_type->GetString())) {
99 return true;
100 }
101 }
102 return false;
103 }
104
InjectSyncedBookmark()105 void InjectSyncedBookmark() {
106 fake_server::BookmarkEntityBuilder bookmark_builder =
107 entity_builder_factory_.NewBookmarkEntityBuilder("My Bookmark");
108 GetFakeServer()->InjectEntity(
109 bookmark_builder.BuildBookmark(GURL(kSyncedBookmarkURL)));
110 }
111
GetNumUpdatesDownloadedInLastCycle()112 int GetNumUpdatesDownloadedInLastCycle() {
113 return GetSyncService(0)
114 ->GetLastCycleSnapshotForDebugging()
115 .model_neutral_state()
116 .num_updates_downloaded_total;
117 }
118
119 protected:
SetupTest(bool all_types_enabled)120 void SetupTest(bool all_types_enabled) {
121 ASSERT_TRUE(SetupClients());
122 if (all_types_enabled) {
123 ASSERT_TRUE(GetClient(0)->SetupSync());
124 } else {
125 ASSERT_TRUE(
126 GetClient(0)->SetupSyncNoWaitForCompletion(UserSelectableTypeSet()));
127 ASSERT_TRUE(GetClient(0)->AwaitSyncSetupCompletion());
128 }
129
130 registered_data_types_ = GetSyncService(0)->GetRegisteredDataTypesForTest();
131 multi_grouped_types_ = MultiGroupTypes(registered_data_types_);
132 registered_selectable_types_ = GetRegisteredSelectableTypes(0);
133 }
134
ResolveGroup(UserSelectableType type)135 ModelTypeSet ResolveGroup(UserSelectableType type) {
136 ModelTypeSet grouped_types =
137 syncer::SyncUserSettingsImpl::ResolvePreferredTypesForTesting({type});
138 grouped_types.RetainAll(registered_data_types_);
139 grouped_types.RemoveAll(ProxyTypes());
140 return grouped_types;
141 }
142
WithoutMultiTypes(const ModelTypeSet & input)143 ModelTypeSet WithoutMultiTypes(const ModelTypeSet& input) {
144 return Difference(input, multi_grouped_types_);
145 }
146
147 ModelTypeSet registered_data_types_;
148 ModelTypeSet multi_grouped_types_;
149 UserSelectableTypeSet registered_selectable_types_;
150
151 private:
152 fake_server::EntityBuilderFactory entity_builder_factory_;
153
154 DISALLOW_COPY_AND_ASSIGN(EnableDisableSingleClientTest);
155 };
156
IN_PROC_BROWSER_TEST_F(EnableDisableSingleClientTest,EnableOneAtATime)157 IN_PROC_BROWSER_TEST_F(EnableDisableSingleClientTest, EnableOneAtATime) {
158 // Setup sync with no enabled types.
159 SetupTest(/*all_types_enabled=*/false);
160
161 for (UserSelectableType type : registered_selectable_types_) {
162 const ModelTypeSet grouped_types = ResolveGroup(type);
163 for (ModelType single_grouped_type : WithoutMultiTypes(grouped_types)) {
164 ASSERT_FALSE(ModelTypeExists(single_grouped_type))
165 << " for " << GetUserSelectableTypeName(type);
166 }
167
168 base::HistogramTester histogram_tester;
169 EXPECT_TRUE(GetClient(0)->EnableSyncForType(type));
170
171 for (ModelType grouped_type : grouped_types) {
172 EXPECT_TRUE(ModelTypeExists(grouped_type))
173 << " for " << GetUserSelectableTypeName(type);
174
175 if (syncer::CommitOnlyTypes().Has(grouped_type)) {
176 EXPECT_EQ(0,
177 histogram_tester.GetBucketCount(
178 "Sync.PostedDataTypeGetUpdatesRequest",
179 static_cast<int>(ModelTypeHistogramValue(grouped_type))))
180 << " for " << ModelTypeToString(grouped_type);
181 } else {
182 EXPECT_NE(0,
183 histogram_tester.GetBucketCount(
184 "Sync.PostedDataTypeGetUpdatesRequest",
185 static_cast<int>(ModelTypeHistogramValue(grouped_type))))
186 << " for " << ModelTypeToString(grouped_type);
187 }
188 }
189 }
190 }
191
IN_PROC_BROWSER_TEST_F(EnableDisableSingleClientTest,DisableOneAtATime)192 IN_PROC_BROWSER_TEST_F(EnableDisableSingleClientTest, DisableOneAtATime) {
193 // Setup sync with no disabled types.
194 SetupTest(/*all_types_enabled=*/true);
195
196 for (UserSelectableType type : registered_selectable_types_) {
197 const ModelTypeSet grouped_types = ResolveGroup(type);
198 for (ModelType grouped_type : grouped_types) {
199 ASSERT_TRUE(ModelTypeExists(grouped_type))
200 << " for " << GetUserSelectableTypeName(type);
201 }
202
203 EXPECT_TRUE(GetClient(0)->DisableSyncForType(type));
204
205 for (ModelType single_grouped_type : WithoutMultiTypes(grouped_types)) {
206 EXPECT_FALSE(ModelTypeExists(single_grouped_type))
207 << " for " << GetUserSelectableTypeName(type);
208 }
209 }
210
211 // Lastly make sure that all the multi grouped times are all gone, since we
212 // did not check these after disabling inside the above loop.
213 for (ModelType multi_grouped_type : multi_grouped_types_) {
214 EXPECT_FALSE(ModelTypeExists(multi_grouped_type))
215 << " for " << ModelTypeToString(multi_grouped_type);
216 }
217 }
218
IN_PROC_BROWSER_TEST_F(EnableDisableSingleClientTest,FastEnableDisableOneAtATime)219 IN_PROC_BROWSER_TEST_F(EnableDisableSingleClientTest,
220 FastEnableDisableOneAtATime) {
221 // Setup sync with no enabled types.
222 SetupTest(/*all_types_enabled=*/false);
223
224 for (UserSelectableType type : registered_selectable_types_) {
225 const ModelTypeSet grouped_types = ResolveGroup(type);
226 const ModelTypeSet single_grouped_types = WithoutMultiTypes(grouped_types);
227 for (ModelType single_grouped_type : single_grouped_types) {
228 ASSERT_FALSE(ModelTypeExists(single_grouped_type))
229 << " for " << GetUserSelectableTypeName(type);
230 }
231
232 // Enable and then disable immediately afterwards, before the datatype has
233 // had the chance to finish startup (which usually involves task posting).
234 EXPECT_TRUE(GetClient(0)->EnableSyncForType(type));
235 EXPECT_TRUE(GetClient(0)->DisableSyncForType(type));
236
237 for (ModelType single_grouped_type : single_grouped_types) {
238 EXPECT_FALSE(ModelTypeExists(single_grouped_type))
239 << " for " << GetUserSelectableTypeName(type);
240 }
241 }
242
243 // Lastly make sure that all the multi grouped times are all gone, since we
244 // did not check these after disabling inside the above loop.
245 for (ModelType multi_grouped_type : multi_grouped_types_) {
246 EXPECT_FALSE(ModelTypeExists(multi_grouped_type))
247 << " for " << ModelTypeToString(multi_grouped_type);
248 }
249 }
250
IN_PROC_BROWSER_TEST_F(EnableDisableSingleClientTest,FastDisableEnableOneAtATime)251 IN_PROC_BROWSER_TEST_F(EnableDisableSingleClientTest,
252 FastDisableEnableOneAtATime) {
253 // Setup sync with no disabled types.
254 SetupTest(/*all_types_enabled=*/true);
255
256 for (UserSelectableType type : registered_selectable_types_) {
257 const ModelTypeSet grouped_types = ResolveGroup(type);
258 for (ModelType grouped_type : grouped_types) {
259 ASSERT_TRUE(ModelTypeExists(grouped_type))
260 << " for " << GetUserSelectableTypeName(type);
261 }
262
263 // Disable and then reenable immediately afterwards, before the datatype has
264 // had the chance to stop fully (which usually involves task posting).
265 EXPECT_TRUE(GetClient(0)->DisableSyncForType(type));
266 EXPECT_TRUE(GetClient(0)->EnableSyncForType(type));
267
268 for (ModelType grouped_type : grouped_types) {
269 EXPECT_TRUE(ModelTypeExists(grouped_type))
270 << " for " << GetUserSelectableTypeName(type);
271 }
272 }
273 }
274
IN_PROC_BROWSER_TEST_F(EnableDisableSingleClientTest,FastEnableDisableEnableOneAtATime)275 IN_PROC_BROWSER_TEST_F(EnableDisableSingleClientTest,
276 FastEnableDisableEnableOneAtATime) {
277 // Setup sync with no enabled types.
278 SetupTest(/*all_types_enabled=*/false);
279
280 for (UserSelectableType type : registered_selectable_types_) {
281 const ModelTypeSet single_grouped_types =
282 WithoutMultiTypes(ResolveGroup(type));
283 for (ModelType single_grouped_type : single_grouped_types) {
284 ASSERT_FALSE(ModelTypeExists(single_grouped_type))
285 << " for " << GetUserSelectableTypeName(type);
286 }
287
288 // Fast enable-disable-enable sequence, before the datatype has had the
289 // chance to transition fully across states (usually involves task posting).
290 EXPECT_TRUE(GetClient(0)->EnableSyncForType(type));
291 EXPECT_TRUE(GetClient(0)->DisableSyncForType(type));
292 EXPECT_TRUE(GetClient(0)->EnableSyncForType(type));
293
294 for (ModelType single_grouped_type : single_grouped_types) {
295 EXPECT_TRUE(ModelTypeExists(single_grouped_type))
296 << " for " << GetUserSelectableTypeName(type);
297 }
298 }
299 }
300
IN_PROC_BROWSER_TEST_F(EnableDisableSingleClientTest,EnableDisable)301 IN_PROC_BROWSER_TEST_F(EnableDisableSingleClientTest, EnableDisable) {
302 SetupTest(/*all_types_enabled=*/false);
303
304 // Enable all, and then disable immediately afterwards, before datatypes
305 // have had the chance to finish startup (which usually involves task
306 // posting).
307 GetClient(0)->EnableSyncForRegisteredDatatypes();
308 GetClient(0)->DisableSyncForAllDatatypes();
309
310 for (UserSelectableType type : UserSelectableTypeSet::All()) {
311 for (ModelType grouped_type : ResolveGroup(type)) {
312 EXPECT_FALSE(ModelTypeExists(grouped_type))
313 << " for " << GetUserSelectableTypeName(type);
314 }
315 }
316 }
317
IN_PROC_BROWSER_TEST_F(EnableDisableSingleClientTest,PRE_EnableAndRestart)318 IN_PROC_BROWSER_TEST_F(EnableDisableSingleClientTest, PRE_EnableAndRestart) {
319 SetupTest(/*all_types_enabled=*/true);
320 }
321
IN_PROC_BROWSER_TEST_F(EnableDisableSingleClientTest,EnableAndRestart)322 IN_PROC_BROWSER_TEST_F(EnableDisableSingleClientTest, EnableAndRestart) {
323 ASSERT_TRUE(SetupClients());
324
325 EXPECT_TRUE(GetClient(0)->AwaitEngineInitialization());
326
327 for (UserSelectableType type : UserSelectableTypeSet::All()) {
328 for (ModelType model_type : ResolveGroup(type)) {
329 EXPECT_TRUE(ModelTypeExists(model_type))
330 << " for " << ModelTypeToString(model_type);
331 }
332 }
333 }
334
IN_PROC_BROWSER_TEST_F(EnableDisableSingleClientTest,FastEnableDisableEnable)335 IN_PROC_BROWSER_TEST_F(EnableDisableSingleClientTest, FastEnableDisableEnable) {
336 SetupTest(/*all_types_enabled=*/false);
337
338 // Enable all, and then disable+reenable immediately afterwards, before
339 // datatypes have had the chance to finish startup (which usually involves
340 // task posting).
341 GetClient(0)->EnableSyncForRegisteredDatatypes();
342 GetClient(0)->DisableSyncForAllDatatypes();
343 GetClient(0)->EnableSyncForRegisteredDatatypes();
344
345 for (UserSelectableType type : UserSelectableTypeSet::All()) {
346 for (ModelType model_type : ResolveGroup(type)) {
347 EXPECT_TRUE(ModelTypeExists(model_type))
348 << " for " << ModelTypeToString(model_type);
349 }
350 }
351 }
352
353 // This test makes sure that after a StopAndClear(), Sync data gets redownloaded
354 // when Sync is started again. This does not actually verify that the data is
355 // gone from disk (which seems infeasible); it's mostly here as a baseline for
356 // the following tests.
IN_PROC_BROWSER_TEST_F(EnableDisableSingleClientTest,RedownloadsAfterClearData)357 IN_PROC_BROWSER_TEST_F(EnableDisableSingleClientTest,
358 RedownloadsAfterClearData) {
359 ASSERT_TRUE(SetupClients());
360 ASSERT_FALSE(bookmarks_helper::GetBookmarkModel(0)->IsBookmarked(
361 GURL(kSyncedBookmarkURL)));
362
363 // Create a bookmark on the server, then turn on Sync on the client.
364 InjectSyncedBookmark();
365 ASSERT_TRUE(GetClient(0)->SetupSync());
366 ASSERT_TRUE(GetSyncService(0)->IsSyncFeatureActive());
367
368 // Make sure the bookmark got synced down.
369 ASSERT_TRUE(bookmarks_helper::GetBookmarkModel(0)->IsBookmarked(
370 GURL(kSyncedBookmarkURL)));
371 // Note: The response may also contain permanent nodes, so we can't check the
372 // exact count.
373 const int initial_updates_downloaded = GetNumUpdatesDownloadedInLastCycle();
374 ASSERT_GT(initial_updates_downloaded, 0);
375
376 // Stop and restart Sync.
377 GetClient(0)->StopSyncServiceAndClearData();
378 GetClient(0)->StartSyncService();
379 ASSERT_TRUE(GetSyncService(0)->IsSyncFeatureActive());
380
381 // Everything should have been redownloaded.
382 ASSERT_TRUE(bookmarks_helper::GetBookmarkModel(0)->IsBookmarked(
383 GURL(kSyncedBookmarkURL)));
384 EXPECT_EQ(GetNumUpdatesDownloadedInLastCycle(), initial_updates_downloaded);
385 }
386
IN_PROC_BROWSER_TEST_F(EnableDisableSingleClientTest,DoesNotRedownloadAfterKeepData)387 IN_PROC_BROWSER_TEST_F(EnableDisableSingleClientTest,
388 DoesNotRedownloadAfterKeepData) {
389 ASSERT_TRUE(SetupClients());
390 ASSERT_FALSE(bookmarks_helper::GetBookmarkModel(0)->IsBookmarked(
391 GURL(kSyncedBookmarkURL)));
392
393 // Create a bookmark on the server, then turn on Sync on the client.
394 InjectSyncedBookmark();
395 ASSERT_TRUE(GetClient(0)->SetupSync());
396 ASSERT_TRUE(GetSyncService(0)->IsSyncFeatureActive());
397
398 // Make sure the bookmark got synced down.
399 ASSERT_TRUE(bookmarks_helper::GetBookmarkModel(0)->IsBookmarked(
400 GURL(kSyncedBookmarkURL)));
401 // Note: The response may also contain permanent nodes, so we can't check the
402 // exact count.
403 ASSERT_GT(GetNumUpdatesDownloadedInLastCycle(), 0);
404
405 // Stop Sync and let it start up again in standalone transport mode.
406 GetClient(0)->StopSyncServiceWithoutClearingData();
407 ASSERT_TRUE(GetClient(0)->AwaitSyncTransportActive());
408 ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE,
409 GetSyncService(0)->GetTransportState());
410 ASSERT_FALSE(GetSyncService(0)->IsSyncFeatureActive());
411
412 // Now start full Sync again.
413 base::HistogramTester histogram_tester;
414 GetClient(0)->StartSyncService();
415 ASSERT_TRUE(GetSyncService(0)->IsSyncFeatureActive());
416
417 // The bookmark should still be there, *without* having been redownloaded.
418 ASSERT_TRUE(SetupSync());
419 ASSERT_TRUE(bookmarks_helper::GetBookmarkModel(0)->IsBookmarked(
420 GURL(kSyncedBookmarkURL)));
421 EXPECT_EQ(
422 0, histogram_tester.GetBucketCount("Sync.ModelTypeEntityChange3.BOOKMARK",
423 /*REMOTE_NON_INITIAL_UPDATE=*/4));
424 EXPECT_EQ(
425 0, histogram_tester.GetBucketCount("Sync.ModelTypeEntityChange3.BOOKMARK",
426 /*REMOTE_INITIAL_UPDATE=*/5));
427 }
428
IN_PROC_BROWSER_TEST_F(EnableDisableSingleClientTest,ClearsPrefsIfClearData)429 IN_PROC_BROWSER_TEST_F(EnableDisableSingleClientTest, ClearsPrefsIfClearData) {
430 SetupTest(/*all_types_enabled=*/true);
431
432 SyncPrefs prefs(GetProfile(0)->GetPrefs());
433 ASSERT_NE("", prefs.GetCacheGuid());
434
435 GetClient(0)->StopSyncServiceAndClearData();
436 EXPECT_EQ("", prefs.GetCacheGuid());
437 }
438
IN_PROC_BROWSER_TEST_F(EnableDisableSingleClientTest,DoesNotClearPrefsWithKeepData)439 IN_PROC_BROWSER_TEST_F(EnableDisableSingleClientTest,
440 DoesNotClearPrefsWithKeepData) {
441 SetupTest(/*all_types_enabled=*/true);
442
443 SyncPrefs prefs(GetProfile(0)->GetPrefs());
444 const std::string cache_guid = prefs.GetCacheGuid();
445 ASSERT_NE("", cache_guid);
446
447 GetClient(0)->StopSyncServiceWithoutClearingData();
448 EXPECT_EQ(cache_guid, prefs.GetCacheGuid());
449 }
450
451 class EnableDisableSingleClientSelfNotifyTest
452 : public EnableDisableSingleClientTest {
453 public:
454 // UpdatedProgressMarkerChecker relies on the 'self-notify' feature.
TestUsesSelfNotifications()455 bool TestUsesSelfNotifications() override { return true; }
456
TriggerGetUpdatesCycleAndWait()457 sync_pb::ClientToServerMessage TriggerGetUpdatesCycleAndWait() {
458 TriggerSyncForModelTypes(0, {syncer::BOOKMARKS});
459 EXPECT_TRUE(UpdatedProgressMarkerChecker(GetSyncService(0)).Wait());
460
461 sync_pb::ClientToServerMessage message;
462 EXPECT_TRUE(GetFakeServer()->GetLastGetUpdatesMessage(&message));
463 return message;
464 }
465 };
466
IN_PROC_BROWSER_TEST_F(EnableDisableSingleClientSelfNotifyTest,PRE_ResendsBagOfChips)467 IN_PROC_BROWSER_TEST_F(EnableDisableSingleClientSelfNotifyTest,
468 PRE_ResendsBagOfChips) {
469 sync_pb::ChipBag bag_of_chips;
470 bag_of_chips.set_server_chips(kTestServerChips);
471 ASSERT_FALSE(base::IsStringUTF8(bag_of_chips.SerializeAsString()));
472 GetFakeServer()->SetBagOfChips(bag_of_chips);
473
474 SetupTest(/*all_types_enabled=*/true);
475
476 SyncPrefs prefs(GetProfile(0)->GetPrefs());
477 EXPECT_EQ(bag_of_chips.SerializeAsString(), prefs.GetBagOfChips());
478
479 sync_pb::ClientToServerMessage message = TriggerGetUpdatesCycleAndWait();
480 EXPECT_TRUE(message.has_bag_of_chips());
481 EXPECT_EQ(kTestServerChips, message.bag_of_chips().server_chips());
482 }
483
IN_PROC_BROWSER_TEST_F(EnableDisableSingleClientSelfNotifyTest,ResendsBagOfChips)484 IN_PROC_BROWSER_TEST_F(EnableDisableSingleClientSelfNotifyTest,
485 ResendsBagOfChips) {
486 ASSERT_TRUE(SetupClients());
487 SyncPrefs prefs(GetProfile(0)->GetPrefs());
488 ASSERT_NE("", prefs.GetBagOfChips());
489 ASSERT_TRUE(GetClient(0)->AwaitSyncSetupCompletion());
490
491 sync_pb::ClientToServerMessage message = TriggerGetUpdatesCycleAndWait();
492 EXPECT_TRUE(message.has_bag_of_chips());
493 EXPECT_EQ(kTestServerChips, message.bag_of_chips().server_chips());
494 }
495
496 } // namespace
497