blob: 1a8dec87abd74201a231ed1f451cad3bed934b8b [file] [log] [blame]
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/strings/string_number_conversions.h"
#include "chrome/browser/sync/test/integration/dictionary_helper.h"
#include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
#include "chrome/browser/sync/test/integration/sync_test.h"
#include "chrome/common/spellcheck_common.h"
using dictionary_helper::AwaitNumDictionaryEntries;
using chrome::spellcheck_common::MAX_SYNCABLE_DICTIONARY_WORDS;
class MultipleClientDictionarySyncTest : public SyncTest {
public:
MultipleClientDictionarySyncTest() : SyncTest(MULTIPLE_CLIENT) {}
~MultipleClientDictionarySyncTest() override {}
bool TestUsesSelfNotifications() override { return false; }
private:
DISALLOW_COPY_AND_ASSIGN(MultipleClientDictionarySyncTest);
};
IN_PROC_BROWSER_TEST_F(MultipleClientDictionarySyncTest, AddToOne) {
ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
dictionary_helper::LoadDictionaries();
ASSERT_TRUE(dictionary_helper::AwaitDictionariesMatch());
ASSERT_TRUE(dictionary_helper::AddWord(0, "foo"));
ASSERT_TRUE(dictionary_helper::AwaitDictionariesMatch());
}
IN_PROC_BROWSER_TEST_F(MultipleClientDictionarySyncTest, AddSameToAll) {
ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
dictionary_helper::LoadDictionaries();
ASSERT_TRUE(dictionary_helper::AwaitDictionariesMatch());
for (int i = 0; i < num_clients(); ++i)
dictionary_helper::AddWord(i, "foo");
ASSERT_TRUE(dictionary_helper::AwaitDictionariesMatch());
ASSERT_EQ(1UL, dictionary_helper::GetDictionarySize(0));
}
IN_PROC_BROWSER_TEST_F(MultipleClientDictionarySyncTest, AddDifferentToAll) {
ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
dictionary_helper::LoadDictionaries();
ASSERT_TRUE(dictionary_helper::AwaitDictionariesMatch());
for (int i = 0; i < num_clients(); ++i)
dictionary_helper::AddWord(i, "foo" + base::IntToString(i));
ASSERT_TRUE(dictionary_helper::AwaitDictionariesMatch());
ASSERT_EQ(num_clients(),
static_cast<int>(dictionary_helper::GetDictionarySize(0)));
}
// Tests the case where the Nth client pushes the server beyond its
// MAX_SYNCABLE_DICTIONARY_WORDS limit.
// Crashes on Windows. crbug.com/431354
#if defined(OS_WIN)
#define MAYBE_Limit DISABLED_Limit
#else
#define MAYBE_Limit Limit
#endif
IN_PROC_BROWSER_TEST_F(MultipleClientDictionarySyncTest, MAYBE_Limit) {
ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
dictionary_helper::LoadDictionaries();
ASSERT_TRUE(dictionary_helper::AwaitDictionariesMatch());
const int n = num_clients();
// Pick a number of initial words per client such that
// (num-clients()-1) * initial_words
// < MAX_SYNCABLE_DICTIONARY_WORDS
// < num_clients() * initial_words
size_t initial_words =
(MAX_SYNCABLE_DICTIONARY_WORDS + n) / n;
// Add |initial_words| words to each of the clients before sync.
for (int i = 0; i < n; ++i) {
GetClient(i)->DisableSyncForAllDatatypes();
for (size_t j = 0; j < initial_words; ++j) {
ASSERT_TRUE(dictionary_helper::AddWord(
i, "foo-" + base::IntToString(i) + "-" + base::Uint64ToString(j)));
}
ASSERT_EQ(initial_words, dictionary_helper::GetDictionarySize(i));
}
// As long as we don't get involved in any race conditions where two clients
// are committing at once, we should be able to guarantee that the server has
// at most MAX_SYNCABLE_DICTIONARY_WORDS words. Every client will be able to
// sync these items. Clients are allowed to have more words if they're
// available locally, but they won't be able to commit any words once the
// server is full.
//
// As we enable clients one-by-one, all but the (N-1)th client should be able
// to commit all of their items. The last one will have some local data left
// over.
// Open the floodgates. Allow N-1 clients to sync their items.
for (int i = 0; i < n-1; ++i) {
SCOPED_TRACE(i);
// Client #i has |initial_words| words before sync.
ASSERT_EQ(initial_words, dictionary_helper::GetDictionarySize(i));
ASSERT_TRUE(GetClient(i)->EnableSyncForAllDatatypes());
}
// Wait for clients to catch up. All should be in sync with the server
// and have exactly (initial_words * (N-1)) words in their dictionaries.
for (int i = 0; i < n-1; ++i) {
SCOPED_TRACE(i);
ASSERT_TRUE(AwaitNumDictionaryEntries(i, initial_words*(n-1)));
}
// Add the client that has engough new words to cause an overflow.
ASSERT_EQ(initial_words, dictionary_helper::GetDictionarySize(n-1));
ASSERT_TRUE(GetClient(n-1)->EnableSyncForAllDatatypes());
// The Nth client will receive the initial_words * (n-1) entries that were on
// the server. It will commit some of the entries it had locally. And it
// will have a few uncommittable items left over.
ASSERT_TRUE(AwaitNumDictionaryEntries(n-1, initial_words*n));
// Everyone else should be at the limit.
for (int i = 0; i < n-1; ++i) {
SCOPED_TRACE(i);
ASSERT_TRUE(AwaitNumDictionaryEntries(i, MAX_SYNCABLE_DICTIONARY_WORDS));
}
}