// Copyright 2012 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifdef UNSAFE_BUFFERS_BUILD // TODO(crbug.com/40285824): Remove this and convert code to safer constructs. #pragma allow_unsafe_buffers #endif #include "components/spellcheck/renderer/spellcheck.h" #include <stddef.h> #include <memory> #include <utility> #include "base/containers/contains.h" #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/memory/raw_ptr.h" #include "base/path_service.h" #include "base/run_loop.h" #include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" #include "base/test/task_environment.h" #include "build/build_config.h" #include "components/spellcheck/common/spellcheck_common.h" #include "components/spellcheck/common/spellcheck_result.h" #include "components/spellcheck/renderer/empty_local_interface_provider.h" #include "components/spellcheck/renderer/hunspell_engine.h" #include "components/spellcheck/renderer/spellcheck_language.h" #include "components/spellcheck/renderer/spellcheck_provider_test.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/platform/web_vector.h" #include "third_party/blink/public/web/web_text_checking_completion.h" #include "third_party/blink/public/web/web_text_checking_result.h" namespace { base::FilePath GetHunspellDirectory() { … } } // namespace // TODO(groby): This needs to be a BrowserTest for OSX. class SpellCheckTest : public testing::Test { … }; struct MockTextCheckingResult { … }; // A fake completion object for verification. class MockTextCheckingCompletion : public blink::WebTextCheckingCompletion { … }; // Operates unit tests for the content::SpellCheck::SpellCheckWord() function // with the US English dictionary. // The unit tests in this function consist of: // * Tests for the function with empty strings; // * Tests for the function with a valid English word; // * Tests for the function with a valid non-English word; // * Tests for the function with a valid English word with a preceding // space character; // * Tests for the function with a valid English word with a preceding // non-English word; // * Tests for the function with a valid English word with a following // space character; // * Tests for the function with a valid English word with a following // non-English word; // * Tests for the function with two valid English words concatenated // with space characters or non-English words; // * Tests for the function with an invalid English word; // * Tests for the function with an invalid English word with a preceding // space character; // * Tests for the function with an invalid English word with a preceding // non-English word; // * Tests for the function with an invalid English word with a following // space character; // * Tests for the function with an invalid English word with a following // non-English word, and; // * Tests for the function with two invalid English words concatenated // with space characters or non-English words. // A test with a "[ROBUSTNESS]" mark shows it is a robustness test and it uses // grammatically incorrect string. // TODO(groby): Please feel free to add more tests. TEST_F(SpellCheckTest, SpellCheckStrings_EN_US) { … } TEST_F(SpellCheckTest, SpellCheckSuggestions_EN_US) { … } // This test verifies our spellchecker can split a text into words and check // the spelling of each word in the text. TEST_F(SpellCheckTest, SpellCheckText) { … } // Verify that our SpellCheck::SpellCheckWord() returns false when it checks // misspelled words. TEST_F(SpellCheckTest, MisspelledWords) { … } // Since SpellCheck::SpellCheckParagraph is not implemented on Mac, // we skip these SpellCheckParagraph tests on Mac. #if !BUILDFLAG(IS_APPLE) // Make sure SpellCheckParagraph does not crash if the input is empty. TEST_F(SpellCheckTest, SpellCheckParagraphEmptyParagraph) { … } // A simple test case having no misspellings. TEST_F(SpellCheckTest, SpellCheckParagraphNoMisspellings) { … } // A simple test case having one misspelling. TEST_F(SpellCheckTest, SpellCheckParagraphSingleMisspellings) { … } // A simple test case having multiple misspellings. TEST_F(SpellCheckTest, SpellCheckParagraphMultipleMisspellings) { … } // Make sure a relatively long (correct) sentence can be spellchecked. TEST_F(SpellCheckTest, SpellCheckParagraphLongSentence) { … } // Make sure all misspellings can be found in a relatively long sentence. TEST_F(SpellCheckTest, SpellCheckParagraphLongSentenceMultipleMisspellings) { … } // We also skip RequestSpellCheck tests on Mac, because a system spellchecker // is used on Mac instead of SpellCheck::RequestTextChecking. // Make sure RequestTextChecking does not crash if input is empty. TEST_F(SpellCheckTest, RequestSpellCheckWithEmptyString) { … } // A simple test case having no misspellings. TEST_F(SpellCheckTest, RequestSpellCheckWithoutMisspelling) { … } // A simple test case having one misspelling. TEST_F(SpellCheckTest, RequestSpellCheckWithSingleMisspelling) { … } // A simple test case having a few misspellings. TEST_F(SpellCheckTest, RequestSpellCheckWithMisspellings) { … } // A test case that multiple requests comes at once. Make sure all // requests are processed. TEST_F(SpellCheckTest, RequestSpellCheckWithMultipleRequests) { … } // A test case that spellchecking is requested before initializing. // In this case, we postpone to post a request. TEST_F(SpellCheckTest, RequestSpellCheckWithoutInitialization) { … } // Requests several spellchecking before initializing. Except the last one, // posting requests is cancelled and text is rendered as correct one. TEST_F(SpellCheckTest, RequestSpellCheckMultipleTimesWithoutInitialization) { … } #endif // Verify that the SpellCheck class keeps the spelling marker added to a // misspelled word "zz". TEST_F(SpellCheckTest, CreateTextCheckingResultsKeepsMarkers) { … } // Verify that the SpellCheck class replaces the spelling marker added to a // contextually-misspelled word "bean" with a grammar marker. TEST_F(SpellCheckTest, CreateTextCheckingResultsAddsGrammarMarkers) { … } // Verify that the SpellCheck preserves the original apostrophe type in the // checked text, regardless of the type of apostrophe the browser returns. TEST_F(SpellCheckTest, CreateTextCheckingResultsKeepsTypographicalApostrophe) { … } // Checks some words that should be present in all English dictionaries. TEST_F(SpellCheckTest, EnglishWords) { … } // Checks that NOSUGGEST works in English dictionaries. TEST_F(SpellCheckTest, NoSuggest) { … } // Check that the correct dictionary files are checked in. TEST_F(SpellCheckTest, DictionaryFiles) { … } // TODO(groby): Add a test for hunspell itself, when MAXWORDLEN is exceeded. TEST_F(SpellCheckTest, SpellingEngine_CheckSpelling) { … } // Chrome should not suggest "Othello" for "hellllo" or "identically" for // "accidently". TEST_F(SpellCheckTest, LogicalSuggestions) { … } // Words with apostrophes should be valid contractions. TEST_F(SpellCheckTest, IsValidContraction) { … } TEST_F(SpellCheckTest, FillSuggestions_OneLanguageNoSuggestions) { … } TEST_F(SpellCheckTest, FillSuggestions_OneLanguageFewSuggestions) { … } TEST_F(SpellCheckTest, FillSuggestions_OneLanguageManySuggestions) { … } TEST_F(SpellCheckTest, FillSuggestions_RemoveDuplicates) { … } TEST_F(SpellCheckTest, FillSuggestions_TwoLanguages) { … } TEST_F(SpellCheckTest, FillSuggestions_ThreeLanguages) { … }