Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(848)

Unified Diff: chrome/browser/spellchecker/feedback_sender_unittest.cc

Issue 1006953003: Revert "Remove spellcheck feedback." (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/spellchecker/feedback_sender.cc ('k') | chrome/browser/spellchecker/feedback_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/spellchecker/feedback_sender_unittest.cc
diff --git a/chrome/browser/spellchecker/feedback_sender_unittest.cc b/chrome/browser/spellchecker/feedback_sender_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..5f6963d6aa00bc47a5c4e50afdad5b812e789854
--- /dev/null
+++ b/chrome/browser/spellchecker/feedback_sender_unittest.cc
@@ -0,0 +1,624 @@
+// Copyright (c) 2013 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.
+//
+// Unit tests for |FeedbackSender| object.
+
+#include "chrome/browser/spellchecker/feedback_sender.h"
+
+#include "base/bind.h"
+#include "base/command_line.h"
+#include "base/json/json_reader.h"
+#include "base/message_loop/message_loop.h"
+#include "base/metrics/field_trial.h"
+#include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/values.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/spellcheck_common.h"
+#include "chrome/common/spellcheck_marker.h"
+#include "chrome/common/spellcheck_result.h"
+#include "chrome/test/base/testing_profile.h"
+#include "components/variations/entropy_provider.h"
+#include "content/public/test/test_browser_thread.h"
+#include "net/url_request/test_url_fetcher_factory.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace spellcheck {
+
+namespace {
+
+const char kCountry[] = "USA";
+const char kLanguage[] = "en";
+const char kText[] = "Helllo world.";
+const int kMisspellingLength = 6;
+const int kMisspellingStart = 0;
+const int kRendererProcessId = 0;
+const int kUrlFetcherId = 0;
+
+// Builds a simple spellcheck result.
+SpellCheckResult BuildSpellCheckResult() {
+ return SpellCheckResult(SpellCheckResult::SPELLING,
+ kMisspellingStart,
+ kMisspellingLength,
+ base::UTF8ToUTF16("Hello"));
+}
+
+// Returns the number of times that |needle| appears in |haystack| without
+// overlaps. For example, CountOccurences("bananana", "nana") returns 1.
+int CountOccurences(const std::string& haystack, const std::string& needle) {
+ int number_of_occurrences = 0;
+ for (size_t pos = haystack.find(needle);
+ pos != std::string::npos;
+ pos = haystack.find(needle, pos + needle.length())) {
+ ++number_of_occurrences;
+ }
+ return number_of_occurrences;
+}
+
+} // namespace
+
+// A test fixture to help keep tests simple.
+class FeedbackSenderTest : public testing::Test {
+ public:
+ FeedbackSenderTest() : ui_thread_(content::BrowserThread::UI, &loop_) {
+ feedback_.reset(new FeedbackSender(NULL, kLanguage, kCountry));
+ feedback_->StartFeedbackCollection();
+ }
+
+ ~FeedbackSenderTest() override {}
+
+ protected:
+ // Appends the "--enable-spelling-service-feedback" switch to the
+ // command-line.
+ void AppendCommandLineSwitch() {
+ // The command-line switch is temporary.
+ // TODO(rouslan): Remove the command-line switch. http://crbug.com/247726
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kEnableSpellingFeedbackFieldTrial);
+ feedback_.reset(new FeedbackSender(NULL, kLanguage, kCountry));
+ feedback_->StartFeedbackCollection();
+ }
+
+ // Enables the "SpellingServiceFeedback.Enabled" field trial.
+ void EnableFieldTrial() {
+ // The field trial is temporary.
+ // TODO(rouslan): Remove the field trial. http://crbug.com/247726
+ field_trial_list_.reset(
+ new base::FieldTrialList(new metrics::SHA1EntropyProvider("foo")));
+ field_trial_ = base::FieldTrialList::CreateFieldTrial(
+ kFeedbackFieldTrialName, kFeedbackFieldTrialEnabledGroupName);
+ field_trial_->group();
+ feedback_.reset(new FeedbackSender(NULL, kLanguage, kCountry));
+ feedback_->StartFeedbackCollection();
+ }
+
+ uint32 AddPendingFeedback() {
+ std::vector<SpellCheckResult> results(1, BuildSpellCheckResult());
+ feedback_->OnSpellcheckResults(kRendererProcessId,
+ base::UTF8ToUTF16(kText),
+ std::vector<SpellCheckMarker>(),
+ &results);
+ return results[0].hash;
+ }
+
+ void ExpireSession() {
+ feedback_->session_start_ =
+ base::Time::Now() -
+ base::TimeDelta::FromHours(chrome::spellcheck_common::kSessionHours);
+ }
+
+ bool UploadDataContains(const std::string& data) const {
+ const net::TestURLFetcher* fetcher =
+ fetchers_.GetFetcherByID(kUrlFetcherId);
+ return fetcher && CountOccurences(fetcher->upload_data(), data) > 0;
+ }
+
+ bool UploadDataContains(const std::string& data,
+ int number_of_occurrences) const {
+ const net::TestURLFetcher* fetcher =
+ fetchers_.GetFetcherByID(kUrlFetcherId);
+ return fetcher && CountOccurences(fetcher->upload_data(), data) ==
+ number_of_occurrences;
+ }
+
+ // Returns true if the feedback sender would be uploading data now. The test
+ // does not open network connections.
+ bool IsUploadingData() const {
+ return !!fetchers_.GetFetcherByID(kUrlFetcherId);
+ }
+
+ void ClearUploadData() {
+ fetchers_.RemoveFetcherFromMap(kUrlFetcherId);
+ }
+
+ std::string GetUploadData() const {
+ const net::TestURLFetcher* fetcher =
+ fetchers_.GetFetcherByID(kUrlFetcherId);
+ return fetcher ? fetcher->upload_data() : std::string();
+ }
+
+ scoped_ptr<spellcheck::FeedbackSender> feedback_;
+
+ private:
+ TestingProfile profile_;
+ base::MessageLoop loop_;
+ content::TestBrowserThread ui_thread_;
+ scoped_ptr<base::FieldTrialList> field_trial_list_;
+ scoped_refptr<base::FieldTrial> field_trial_;
+ net::TestURLFetcherFactory fetchers_;
+};
+
+// Do not send data if there's no feedback.
+TEST_F(FeedbackSenderTest, NoFeedback) {
+ EXPECT_FALSE(IsUploadingData());
+ feedback_->OnReceiveDocumentMarkers(kRendererProcessId,
+ std::vector<uint32>());
+ EXPECT_FALSE(IsUploadingData());
+}
+
+// Do not send data if not aware of which markers are still in the document.
+TEST_F(FeedbackSenderTest, NoDocumentMarkersReceived) {
+ EXPECT_FALSE(IsUploadingData());
+ uint32 hash = AddPendingFeedback();
+ EXPECT_FALSE(IsUploadingData());
+ static const int kSuggestionIndex = 1;
+ feedback_->SelectedSuggestion(hash, kSuggestionIndex);
+ EXPECT_FALSE(IsUploadingData());
+}
+
+// Send PENDING feedback message if the marker is still in the document, and the
+// user has not performed any action on it.
+TEST_F(FeedbackSenderTest, PendingFeedback) {
+ uint32 hash = AddPendingFeedback();
+ feedback_->OnReceiveDocumentMarkers(kRendererProcessId,
+ std::vector<uint32>(1, hash));
+ EXPECT_TRUE(UploadDataContains("\"actionType\":\"PENDING\""));
+}
+
+// Send NO_ACTION feedback message if the marker has been removed from the
+// document.
+TEST_F(FeedbackSenderTest, NoActionFeedback) {
+ AddPendingFeedback();
+ feedback_->OnReceiveDocumentMarkers(kRendererProcessId,
+ std::vector<uint32>());
+ EXPECT_TRUE(UploadDataContains("\"actionType\":\"NO_ACTION\""));
+}
+
+// Send SELECT feedback message if the user has selected a spelling suggestion.
+TEST_F(FeedbackSenderTest, SelectFeedback) {
+ uint32 hash = AddPendingFeedback();
+ static const int kSuggestionIndex = 0;
+ feedback_->SelectedSuggestion(hash, kSuggestionIndex);
+ feedback_->OnReceiveDocumentMarkers(kRendererProcessId,
+ std::vector<uint32>());
+ EXPECT_TRUE(UploadDataContains("\"actionType\":\"SELECT\""));
+ EXPECT_TRUE(UploadDataContains("\"actionTargetIndex\":" + kSuggestionIndex));
+}
+
+// Send ADD_TO_DICT feedback message if the user has added the misspelled word
+// to the custom dictionary.
+TEST_F(FeedbackSenderTest, AddToDictFeedback) {
+ uint32 hash = AddPendingFeedback();
+ feedback_->AddedToDictionary(hash);
+ feedback_->OnReceiveDocumentMarkers(kRendererProcessId,
+ std::vector<uint32>());
+ EXPECT_TRUE(UploadDataContains("\"actionType\":\"ADD_TO_DICT\""));
+}
+
+// Send IN_DICTIONARY feedback message if the user has the misspelled word in
+// the custom dictionary.
+TEST_F(FeedbackSenderTest, InDictionaryFeedback) {
+ uint32 hash = AddPendingFeedback();
+ feedback_->RecordInDictionary(hash);
+ feedback_->OnReceiveDocumentMarkers(kRendererProcessId,
+ std::vector<uint32>());
+ EXPECT_TRUE(UploadDataContains("\"actionType\":\"IN_DICTIONARY\""));
+}
+
+// Send PENDING feedback message if the user saw the spelling suggestion, but
+// decided to not select it, and the marker is still in the document.
+TEST_F(FeedbackSenderTest, IgnoreFeedbackMarkerInDocument) {
+ uint32 hash = AddPendingFeedback();
+ feedback_->IgnoredSuggestions(hash);
+ feedback_->OnReceiveDocumentMarkers(kRendererProcessId,
+ std::vector<uint32>(1, hash));
+ EXPECT_TRUE(UploadDataContains("\"actionType\":\"PENDING\""));
+}
+
+// Send IGNORE feedback message if the user saw the spelling suggestion, but
+// decided to not select it, and the marker is no longer in the document.
+TEST_F(FeedbackSenderTest, IgnoreFeedbackMarkerNotInDocument) {
+ uint32 hash = AddPendingFeedback();
+ feedback_->IgnoredSuggestions(hash);
+ feedback_->OnReceiveDocumentMarkers(kRendererProcessId,
+ std::vector<uint32>());
+ EXPECT_TRUE(UploadDataContains("\"actionType\":\"IGNORE\""));
+}
+
+// Send MANUALLY_CORRECTED feedback message if the user manually corrected the
+// misspelled word.
+TEST_F(FeedbackSenderTest, ManuallyCorrectedFeedback) {
+ uint32 hash = AddPendingFeedback();
+ static const std::string kManualCorrection = "Howdy";
+ feedback_->ManuallyCorrected(hash, base::ASCIIToUTF16(kManualCorrection));
+ feedback_->OnReceiveDocumentMarkers(kRendererProcessId,
+ std::vector<uint32>());
+ EXPECT_TRUE(UploadDataContains("\"actionType\":\"MANUALLY_CORRECTED\""));
+ EXPECT_TRUE(UploadDataContains("\"actionTargetValue\":\"" +
+ kManualCorrection + "\""));
+}
+
+// Send feedback messages in batch.
+TEST_F(FeedbackSenderTest, BatchFeedback) {
+ std::vector<SpellCheckResult> results;
+ results.push_back(SpellCheckResult(SpellCheckResult::SPELLING,
+ kMisspellingStart,
+ kMisspellingLength,
+ base::ASCIIToUTF16("Hello")));
+ static const int kSecondMisspellingStart = 7;
+ static const int kSecondMisspellingLength = 5;
+ results.push_back(SpellCheckResult(SpellCheckResult::SPELLING,
+ kSecondMisspellingStart,
+ kSecondMisspellingLength,
+ base::ASCIIToUTF16("world")));
+ feedback_->OnSpellcheckResults(kRendererProcessId,
+ base::UTF8ToUTF16(kText),
+ std::vector<SpellCheckMarker>(),
+ &results);
+ feedback_->OnReceiveDocumentMarkers(kRendererProcessId,
+ std::vector<uint32>());
+ EXPECT_TRUE(UploadDataContains("\"actionType\":\"NO_ACTION\"", 2));
+}
+
+// Send a series of PENDING feedback messages and one final NO_ACTION feedback
+// message with the same hash identifier for a single misspelling.
+TEST_F(FeedbackSenderTest, SameHashFeedback) {
+ uint32 hash = AddPendingFeedback();
+ std::vector<uint32> remaining_markers(1, hash);
+
+ feedback_->OnReceiveDocumentMarkers(kRendererProcessId, remaining_markers);
+ EXPECT_TRUE(UploadDataContains("\"actionType\":\"PENDING\""));
+ std::string hash_string = base::StringPrintf("\"suggestionId\":\"%u\"", hash);
+ EXPECT_TRUE(UploadDataContains(hash_string));
+ ClearUploadData();
+
+ feedback_->OnReceiveDocumentMarkers(kRendererProcessId, remaining_markers);
+ EXPECT_TRUE(UploadDataContains("\"actionType\":\"PENDING\""));
+ EXPECT_TRUE(UploadDataContains(hash_string));
+ ClearUploadData();
+
+ feedback_->OnReceiveDocumentMarkers(kRendererProcessId,
+ std::vector<uint32>());
+ EXPECT_TRUE(UploadDataContains("\"actionType\":\"NO_ACTION\""));
+ EXPECT_TRUE(UploadDataContains(hash_string));
+ ClearUploadData();
+
+ feedback_->OnReceiveDocumentMarkers(kRendererProcessId,
+ std::vector<uint32>());
+ EXPECT_FALSE(IsUploadingData());
+}
+
+// When a session expires:
+// 1) Pending feedback is finalized and sent to the server in the last message
+// batch in the session.
+// 2) No feedback is sent until a spellcheck request happens.
+// 3) Existing markers get new hash identifiers.
+TEST_F(FeedbackSenderTest, SessionExpirationFeedback) {
+ std::vector<SpellCheckResult> results(
+ 1,
+ SpellCheckResult(SpellCheckResult::SPELLING,
+ kMisspellingStart,
+ kMisspellingLength,
+ base::ASCIIToUTF16("Hello")));
+ feedback_->OnSpellcheckResults(kRendererProcessId,
+ base::UTF8ToUTF16(kText),
+ std::vector<SpellCheckMarker>(),
+ &results);
+ uint32 original_hash = results[0].hash;
+ std::vector<uint32> remaining_markers(1, original_hash);
+
+ feedback_->OnReceiveDocumentMarkers(kRendererProcessId, remaining_markers);
+ EXPECT_FALSE(UploadDataContains("\"actionType\":\"NO_ACTION\""));
+ EXPECT_TRUE(UploadDataContains("\"actionType\":\"PENDING\""));
+ std::string original_hash_string =
+ base::StringPrintf("\"suggestionId\":\"%u\"", original_hash);
+ EXPECT_TRUE(UploadDataContains(original_hash_string));
+ ClearUploadData();
+
+ ExpireSession();
+
+ // Last message batch in the current session has only finalized messages.
+ feedback_->OnReceiveDocumentMarkers(kRendererProcessId, remaining_markers);
+ EXPECT_TRUE(UploadDataContains("\"actionType\":\"NO_ACTION\""));
+ EXPECT_FALSE(UploadDataContains("\"actionType\":\"PENDING\""));
+ EXPECT_TRUE(UploadDataContains(original_hash_string));
+ ClearUploadData();
+
+ // The next session starts on the next spellchecker request. Until then,
+ // there's no more feedback sent.
+ feedback_->OnReceiveDocumentMarkers(kRendererProcessId, remaining_markers);
+ EXPECT_FALSE(IsUploadingData());
+
+ // The first spellcheck request after session expiration creates different
+ // document marker hash identifiers.
+ std::vector<SpellCheckMarker> original_markers(
+ 1, SpellCheckMarker(results[0].hash, results[0].location));
+ results[0] = SpellCheckResult(SpellCheckResult::SPELLING,
+ kMisspellingStart,
+ kMisspellingLength,
+ base::ASCIIToUTF16("Hello"));
+ feedback_->OnSpellcheckResults(
+ kRendererProcessId, base::UTF8ToUTF16(kText), original_markers, &results);
+ uint32 updated_hash = results[0].hash;
+ EXPECT_NE(updated_hash, original_hash);
+ remaining_markers[0] = updated_hash;
+
+ // The first feedback message batch in session |i + 1| has the new document
+ // marker hash identifiers.
+ feedback_->OnReceiveDocumentMarkers(kRendererProcessId, remaining_markers);
+ EXPECT_FALSE(UploadDataContains("\"actionType\":\"NO_ACTION\""));
+ EXPECT_TRUE(UploadDataContains("\"actionType\":\"PENDING\""));
+ EXPECT_FALSE(UploadDataContains(original_hash_string));
+ std::string updated_hash_string =
+ base::StringPrintf("\"suggestionId\":\"%u\"", updated_hash);
+ EXPECT_TRUE(UploadDataContains(updated_hash_string));
+}
+
+// First message in session has an indicator.
+TEST_F(FeedbackSenderTest, FirstMessageInSessionIndicator) {
+ // Session 1, message 1
+ AddPendingFeedback();
+ feedback_->OnReceiveDocumentMarkers(kRendererProcessId,
+ std::vector<uint32>());
+ EXPECT_TRUE(UploadDataContains("\"isFirstInSession\":true"));
+
+ // Session 1, message 2
+ AddPendingFeedback();
+ feedback_->OnReceiveDocumentMarkers(kRendererProcessId,
+ std::vector<uint32>());
+ EXPECT_TRUE(UploadDataContains("\"isFirstInSession\":false"));
+
+ ExpireSession();
+
+ // Session 1, message 3 (last)
+ AddPendingFeedback();
+ feedback_->OnReceiveDocumentMarkers(kRendererProcessId,
+ std::vector<uint32>());
+ EXPECT_TRUE(UploadDataContains("\"isFirstInSession\":false"));
+
+ // Session 2, message 1
+ AddPendingFeedback();
+ feedback_->OnReceiveDocumentMarkers(kRendererProcessId,
+ std::vector<uint32>());
+ EXPECT_TRUE(UploadDataContains("\"isFirstInSession\":true"));
+
+ // Session 2, message 2
+ AddPendingFeedback();
+ feedback_->OnReceiveDocumentMarkers(kRendererProcessId,
+ std::vector<uint32>());
+ EXPECT_TRUE(UploadDataContains("\"isFirstInSession\":false"));
+}
+
+// Flush all feedback when the spellcheck language and country change.
+TEST_F(FeedbackSenderTest, OnLanguageCountryChange) {
+ AddPendingFeedback();
+ feedback_->OnLanguageCountryChange("pt", "BR");
+ EXPECT_TRUE(UploadDataContains("\"language\":\"en\""));
+ AddPendingFeedback();
+ feedback_->OnLanguageCountryChange("en", "US");
+ EXPECT_TRUE(UploadDataContains("\"language\":\"pt\""));
+}
+
+// The field names and types should correspond to the API.
+TEST_F(FeedbackSenderTest, FeedbackAPI) {
+ AddPendingFeedback();
+ feedback_->OnReceiveDocumentMarkers(kRendererProcessId,
+ std::vector<uint32>());
+ std::string actual_data = GetUploadData();
+ scoped_ptr<base::DictionaryValue> actual(
+ static_cast<base::DictionaryValue*>(base::JSONReader::Read(actual_data)));
+ actual->SetString("params.key", "TestDummyKey");
+ base::ListValue* suggestions = NULL;
+ actual->GetList("params.suggestionInfo", &suggestions);
+ base::DictionaryValue* suggestion = NULL;
+ suggestions->GetDictionary(0, &suggestion);
+ suggestion->SetString("suggestionId", "42");
+ suggestion->SetString("timestamp", "9001");
+ static const std::string expected_data =
+ "{\"apiVersion\":\"v2\","
+ "\"method\":\"spelling.feedback\","
+ "\"params\":"
+ "{\"clientName\":\"Chrome\","
+ "\"originCountry\":\"USA\","
+ "\"key\":\"TestDummyKey\","
+ "\"language\":\"en\","
+ "\"suggestionInfo\":[{"
+ "\"isAutoCorrection\":false,"
+ "\"isFirstInSession\":true,"
+ "\"misspelledLength\":6,"
+ "\"misspelledStart\":0,"
+ "\"originalText\":\"Helllo world\","
+ "\"suggestionId\":\"42\","
+ "\"suggestions\":[\"Hello\"],"
+ "\"timestamp\":\"9001\","
+ "\"userActions\":[{\"actionType\":\"NO_ACTION\"}]}]}}";
+ scoped_ptr<base::Value> expected(base::JSONReader::Read(expected_data));
+ EXPECT_TRUE(expected->Equals(actual.get()))
+ << "Expected data: " << expected_data
+ << "\nActual data: " << actual_data;
+}
+
+// The default API version is "v2".
+TEST_F(FeedbackSenderTest, DefaultApiVersion) {
+ AddPendingFeedback();
+ feedback_->OnReceiveDocumentMarkers(kRendererProcessId,
+ std::vector<uint32>());
+ EXPECT_TRUE(UploadDataContains("\"apiVersion\":\"v2\""));
+ EXPECT_FALSE(UploadDataContains("\"apiVersion\":\"v2-internal\""));
+}
+
+// The API version should not change for field-trial participants that do not
+// append the command-line switch.
+TEST_F(FeedbackSenderTest, FieldTrialAloneHasSameApiVersion) {
+ EnableFieldTrial();
+
+ AddPendingFeedback();
+ feedback_->OnReceiveDocumentMarkers(kRendererProcessId,
+ std::vector<uint32>());
+
+ EXPECT_TRUE(UploadDataContains("\"apiVersion\":\"v2\""));
+ EXPECT_FALSE(UploadDataContains("\"apiVersion\":\"v2-internal\""));
+}
+
+// The API version should not change if the command-line switch is appended, but
+// the user is not participating in the field-trial.
+TEST_F(FeedbackSenderTest, CommandLineSwitchAloneHasSameApiVersion) {
+ AppendCommandLineSwitch();
+
+ AddPendingFeedback();
+ feedback_->OnReceiveDocumentMarkers(kRendererProcessId,
+ std::vector<uint32>());
+
+ EXPECT_TRUE(UploadDataContains("\"apiVersion\":\"v2\""));
+ EXPECT_FALSE(UploadDataContains("\"apiVersion\":\"v2-internal\""));
+}
+
+// The API version should be different for field-trial participants that also
+// append the command-line switch.
+TEST_F(FeedbackSenderTest, InternalApiVersion) {
+ AppendCommandLineSwitch();
+ EnableFieldTrial();
+
+ AddPendingFeedback();
+ feedback_->OnReceiveDocumentMarkers(kRendererProcessId,
+ std::vector<uint32>());
+
+ EXPECT_FALSE(UploadDataContains("\"apiVersion\":\"v2\""));
+ EXPECT_TRUE(UploadDataContains("\"apiVersion\":\"v2-internal\""));
+}
+
+// Duplicate spellcheck results should be matched to the existing markers.
+TEST_F(FeedbackSenderTest, MatchDupliateResultsWithExistingMarkers) {
+ uint32 hash = AddPendingFeedback();
+ std::vector<SpellCheckResult> results(
+ 1,
+ SpellCheckResult(SpellCheckResult::SPELLING,
+ kMisspellingStart,
+ kMisspellingLength,
+ base::ASCIIToUTF16("Hello")));
+ std::vector<SpellCheckMarker> markers(
+ 1, SpellCheckMarker(hash, results[0].location));
+ EXPECT_EQ(static_cast<uint32>(0), results[0].hash);
+ feedback_->OnSpellcheckResults(
+ kRendererProcessId, base::UTF8ToUTF16(kText), markers, &results);
+ EXPECT_EQ(hash, results[0].hash);
+}
+
+// Adding a word to dictionary should trigger ADD_TO_DICT feedback for every
+// occurrence of that word.
+TEST_F(FeedbackSenderTest, MultipleAddToDictFeedback) {
+ std::vector<SpellCheckResult> results;
+ static const int kSentenceLength = 14;
+ static const int kNumberOfSentences = 2;
+ static const base::string16 kTextWithDuplicates =
+ base::ASCIIToUTF16("Helllo world. Helllo world.");
+ for (int i = 0; i < kNumberOfSentences; ++i) {
+ results.push_back(SpellCheckResult(SpellCheckResult::SPELLING,
+ kMisspellingStart + i * kSentenceLength,
+ kMisspellingLength,
+ base::ASCIIToUTF16("Hello")));
+ }
+ static const int kNumberOfRenderers = 2;
+ int last_renderer_process_id = -1;
+ for (int i = 0; i < kNumberOfRenderers; ++i) {
+ feedback_->OnSpellcheckResults(kRendererProcessId + i,
+ kTextWithDuplicates,
+ std::vector<SpellCheckMarker>(),
+ &results);
+ last_renderer_process_id = kRendererProcessId + i;
+ }
+ std::vector<uint32> remaining_markers;
+ for (size_t i = 0; i < results.size(); ++i)
+ remaining_markers.push_back(results[i].hash);
+ feedback_->OnReceiveDocumentMarkers(last_renderer_process_id,
+ remaining_markers);
+ EXPECT_TRUE(UploadDataContains("PENDING", 2));
+ EXPECT_FALSE(UploadDataContains("ADD_TO_DICT"));
+
+ feedback_->AddedToDictionary(results[0].hash);
+ feedback_->OnReceiveDocumentMarkers(last_renderer_process_id,
+ remaining_markers);
+ EXPECT_FALSE(UploadDataContains("PENDING"));
+ EXPECT_TRUE(UploadDataContains("ADD_TO_DICT", 2));
+}
+
+// ADD_TO_DICT feedback for multiple occurrences of a word should trigger only
+// for pending feedback.
+TEST_F(FeedbackSenderTest, AddToDictOnlyPending) {
+ AddPendingFeedback();
+ uint32 add_to_dict_hash = AddPendingFeedback();
+ uint32 select_hash = AddPendingFeedback();
+ feedback_->SelectedSuggestion(select_hash, 0);
+ feedback_->AddedToDictionary(add_to_dict_hash);
+ feedback_->OnReceiveDocumentMarkers(kRendererProcessId,
+ std::vector<uint32>());
+ EXPECT_TRUE(UploadDataContains("SELECT", 1));
+ EXPECT_TRUE(UploadDataContains("ADD_TO_DICT", 2));
+}
+
+// Spellcheck results that are out-of-bounds are not added to feedback.
+TEST_F(FeedbackSenderTest, IgnoreOutOfBounds) {
+ std::vector<SpellCheckResult> results;
+ results.push_back(SpellCheckResult(
+ SpellCheckResult::SPELLING, 0, 100, base::UTF8ToUTF16("Hello")));
+ results.push_back(SpellCheckResult(
+ SpellCheckResult::SPELLING, 100, 3, base::UTF8ToUTF16("world")));
+ results.push_back(SpellCheckResult(
+ SpellCheckResult::SPELLING, -1, 3, base::UTF8ToUTF16("how")));
+ results.push_back(SpellCheckResult(
+ SpellCheckResult::SPELLING, 0, 0, base::UTF8ToUTF16("are")));
+ results.push_back(SpellCheckResult(
+ SpellCheckResult::SPELLING, 2, -1, base::UTF8ToUTF16("you")));
+ feedback_->OnSpellcheckResults(kRendererProcessId,
+ base::UTF8ToUTF16(kText),
+ std::vector<SpellCheckMarker>(),
+ &results);
+ feedback_->OnReceiveDocumentMarkers(kRendererProcessId,
+ std::vector<uint32>());
+ EXPECT_FALSE(IsUploadingData());
+}
+
+// FeedbackSender does not collect and upload feedback when instructed to stop.
+TEST_F(FeedbackSenderTest, CanStopFeedbackCollection) {
+ feedback_->StopFeedbackCollection();
+ AddPendingFeedback();
+ feedback_->OnReceiveDocumentMarkers(kRendererProcessId,
+ std::vector<uint32>());
+ EXPECT_FALSE(IsUploadingData());
+}
+
+// FeedbackSender resumes collecting and uploading feedback when instructed to
+// start after stopping.
+TEST_F(FeedbackSenderTest, CanResumeFeedbackCollection) {
+ feedback_->StopFeedbackCollection();
+ feedback_->StartFeedbackCollection();
+ AddPendingFeedback();
+ feedback_->OnReceiveDocumentMarkers(kRendererProcessId,
+ std::vector<uint32>());
+ EXPECT_TRUE(IsUploadingData());
+}
+
+// FeedbackSender does not collect data while being stopped and upload it later.
+TEST_F(FeedbackSenderTest, NoFeedbackCollectionWhenStopped) {
+ feedback_->StopFeedbackCollection();
+ AddPendingFeedback();
+ feedback_->OnReceiveDocumentMarkers(kRendererProcessId,
+ std::vector<uint32>());
+ feedback_->StartFeedbackCollection();
+ feedback_->OnReceiveDocumentMarkers(kRendererProcessId,
+ std::vector<uint32>());
+ EXPECT_FALSE(IsUploadingData());
+}
+
+} // namespace spellcheck
« no previous file with comments | « chrome/browser/spellchecker/feedback_sender.cc ('k') | chrome/browser/spellchecker/feedback_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698