Home | History | Annotate | Download | only in integration
      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 
     11 using dictionary_helper::AwaitNumDictionaryEntries;
     12 using chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS;
     13 
     14 class 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 
     25 IN_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 
     34 IN_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 
     45 IN_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.
     59 IN_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