multiple_client_dictionary_sync_test.cc revision c5cede9ae108bb15f6b7a8aea21c7e1fefa2834c
1// Copyright (c) 2011 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 "base/strings/string_number_conversions.h"
6#include "chrome/browser/sync/test/integration/dictionary_helper.h"
7#include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
8#include "chrome/browser/sync/test/integration/sync_test.h"
9#include "chrome/common/spellcheck_common.h"
10
11using dictionary_helper::AwaitNumDictionaryEntries;
12using chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS;
13
14class MultipleClientDictionarySyncTest : public SyncTest {
15 public:
16  MultipleClientDictionarySyncTest() : SyncTest(MULTIPLE_CLIENT) {}
17  virtual ~MultipleClientDictionarySyncTest() {}
18
19  virtual bool TestUsesSelfNotifications() OVERRIDE { return false; }
20
21 private:
22  DISALLOW_COPY_AND_ASSIGN(MultipleClientDictionarySyncTest);
23};
24
25IN_PROC_BROWSER_TEST_F(MultipleClientDictionarySyncTest, AddToOne) {
26  ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
27  dictionary_helper::LoadDictionaries();
28  ASSERT_TRUE(dictionary_helper::AwaitDictionariesMatch());
29
30  ASSERT_TRUE(dictionary_helper::AddWord(0, "foo"));
31  ASSERT_TRUE(dictionary_helper::AwaitDictionariesMatch());
32}
33
34IN_PROC_BROWSER_TEST_F(MultipleClientDictionarySyncTest, AddSameToAll) {
35  ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
36  dictionary_helper::LoadDictionaries();
37  ASSERT_TRUE(dictionary_helper::AwaitDictionariesMatch());
38
39  for (int i = 0; i < num_clients(); ++i)
40    dictionary_helper::AddWord(i, "foo");
41  ASSERT_TRUE(dictionary_helper::AwaitDictionariesMatch());
42  ASSERT_EQ(1UL, dictionary_helper::GetDictionarySize(0));
43}
44
45IN_PROC_BROWSER_TEST_F(MultipleClientDictionarySyncTest, AddDifferentToAll) {
46  ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
47  dictionary_helper::LoadDictionaries();
48  ASSERT_TRUE(dictionary_helper::AwaitDictionariesMatch());
49
50  for (int i = 0; i < num_clients(); ++i)
51    dictionary_helper::AddWord(i, "foo" + base::IntToString(i));
52  ASSERT_TRUE(dictionary_helper::AwaitDictionariesMatch());
53  ASSERT_EQ(num_clients(),
54            static_cast<int>(dictionary_helper::GetDictionarySize(0)));
55}
56
57// Tests the case where the Nth client pushes the server beyond its
58// MAX_SYNCABLE_DICTIONARY_WORDS limit.
59IN_PROC_BROWSER_TEST_F(MultipleClientDictionarySyncTest, Limit) {
60  ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
61  dictionary_helper::LoadDictionaries();
62  ASSERT_TRUE(dictionary_helper::AwaitDictionariesMatch());
63
64  const int n = num_clients();
65
66  // Pick a number of initial words per client such that
67  // (num-clients()-1) * initial_words
68  //     < MAX_SYNCABLE_DICTIONARY_WORDS
69  //     < num_clients() * initial_words
70  size_t initial_words =
71      (MAX_SYNCABLE_DICTIONARY_WORDS + n) / n;
72
73  // Add |initial_words| words to each of the clients before sync.
74  for (int i = 0; i < n; ++i) {
75    GetClient(i)->DisableSyncForAllDatatypes();
76    for (size_t j = 0; j < initial_words; ++j) {
77      ASSERT_TRUE(dictionary_helper::AddWord(
78          i, "foo-" + base::IntToString(i) + "-" + base::Uint64ToString(j)));
79    }
80    ASSERT_EQ(initial_words, dictionary_helper::GetDictionarySize(i));
81  }
82
83  // As long as we don't get involved in any race conditions where two clients
84  // are committing at once, we should be able to guarantee that the server has
85  // at most MAX_SYNCABLE_DICTIONARY_WORDS words.  Every client will be able to
86  // sync these items.  Clients are allowed to have more words if they're
87  // available locally, but they won't be able to commit any words once the
88  // server is full.
89  //
90  // As we enable clients one-by-one, all but the (N-1)th client should be able
91  // to commit all of their items.  The last one will have some local data left
92  // over.
93
94  // Open the floodgates.   Allow N-1 clients to sync their items.
95  for (int i = 0; i < n-1; ++i) {
96    SCOPED_TRACE(i);
97
98    // Client #i has |initial_words| words before sync.
99    ASSERT_EQ(initial_words, dictionary_helper::GetDictionarySize(i));
100    ASSERT_TRUE(GetClient(i)->EnableSyncForAllDatatypes());
101  }
102
103  // Wait for clients to catch up.  All should be in sync with the server
104  // and have exactly (initial_words * (N-1)) words in their dictionaries.
105  for (int i = 0; i < n-1; ++i) {
106    SCOPED_TRACE(i);
107    ASSERT_TRUE(AwaitNumDictionaryEntries(i, initial_words*(n-1)));
108  }
109
110  // Add the client that has engough new words to cause an overflow.
111  ASSERT_EQ(initial_words, dictionary_helper::GetDictionarySize(n-1));
112  ASSERT_TRUE(GetClient(n-1)->EnableSyncForAllDatatypes());
113
114  // The Nth client will receive the initial_words * (n-1) entries that were on
115  // the server.  It will commit some of the entries it had locally.  And it
116  // will have a few uncommittable items left over.
117  ASSERT_TRUE(AwaitNumDictionaryEntries(n-1, initial_words*n));
118
119  // Everyone else should be at the limit.
120  for (int i = 0; i < n-1; ++i) {
121    SCOPED_TRACE(i);
122    ASSERT_TRUE(AwaitNumDictionaryEntries(i, MAX_SYNCABLE_DICTIONARY_WORDS));
123  }
124}
125