• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2013 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 "chrome/browser/chromeos/drive/search_metadata.h"
6 
7 #include "base/file_util.h"
8 #include "base/files/scoped_temp_dir.h"
9 #include "base/i18n/string_search.h"
10 #include "base/message_loop/message_loop_proxy.h"
11 #include "base/run_loop.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "chrome/browser/chromeos/drive/fake_free_disk_space_getter.h"
14 #include "chrome/browser/chromeos/drive/file_cache.h"
15 #include "chrome/browser/chromeos/drive/file_system_util.h"
16 #include "chrome/browser/chromeos/drive/test_util.h"
17 #include "content/public/test/test_browser_thread_bundle.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19 
20 namespace drive {
21 namespace internal {
22 
23 namespace {
24 
25 const int kDefaultAtMostNumMatches = 10;
26 
27 // A simple wrapper for testing FindAndHighlightWrapper(). It just converts the
28 // query text parameter to FixedPatternStringSearchIgnoringCaseAndAccents.
FindAndHighlightWrapper(const std::string & text,const std::string & query_text,std::string * highlighted_text)29 bool FindAndHighlightWrapper(
30     const std::string& text,
31     const std::string& query_text,
32     std::string* highlighted_text) {
33   base::i18n::FixedPatternStringSearchIgnoringCaseAndAccents query(
34       base::UTF8ToUTF16(query_text));
35   return FindAndHighlight(text, &query, highlighted_text);
36 }
37 
38 }  // namespace
39 
40 class SearchMetadataTest : public testing::Test {
41  protected:
SetUp()42   virtual void SetUp() OVERRIDE {
43     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
44     fake_free_disk_space_getter_.reset(new FakeFreeDiskSpaceGetter);
45 
46     metadata_storage_.reset(new ResourceMetadataStorage(
47         temp_dir_.path(), base::MessageLoopProxy::current().get()));
48     ASSERT_TRUE(metadata_storage_->Initialize());
49 
50     cache_.reset(new FileCache(metadata_storage_.get(),
51                                temp_dir_.path(),
52                                base::MessageLoopProxy::current().get(),
53                                fake_free_disk_space_getter_.get()));
54     ASSERT_TRUE(cache_->Initialize());
55 
56     resource_metadata_.reset(
57         new ResourceMetadata(metadata_storage_.get(),
58                              cache_.get(),
59                              base::MessageLoopProxy::current()));
60     ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->Initialize());
61 
62     AddEntriesToMetadata();
63   }
64 
AddEntriesToMetadata()65   void AddEntriesToMetadata() {
66     base::FilePath temp_file;
67     EXPECT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(), &temp_file));
68     const std::string temp_file_md5 = "md5";
69 
70     ResourceEntry entry;
71     std::string local_id;
72 
73     // drive/root
74     EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetIdByPath(
75         util::GetDriveMyDriveRootPath(), &local_id));
76     const std::string root_local_id = local_id;
77 
78     // drive/root/Directory 1
79     EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry(GetDirectoryEntry(
80         "Directory 1", "dir1", 1, root_local_id), &local_id));
81     const std::string dir1_local_id = local_id;
82 
83     // drive/root/Directory 1/SubDirectory File 1.txt
84     EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry(GetFileEntry(
85         "SubDirectory File 1.txt", "file1a", 2, dir1_local_id), &local_id));
86     EXPECT_EQ(FILE_ERROR_OK, cache_->Store(
87         local_id, temp_file_md5, temp_file, FileCache::FILE_OPERATION_COPY));
88 
89     // drive/root/Directory 1/Shared To The Account Owner.txt
90     entry = GetFileEntry(
91         "Shared To The Account Owner.txt", "file1b", 3, dir1_local_id);
92     entry.set_shared_with_me(true);
93     EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry(entry, &local_id));
94 
95     // drive/root/Directory 2 excludeDir-test
96     EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry(GetDirectoryEntry(
97         "Directory 2 excludeDir-test", "dir2", 4, root_local_id), &local_id));
98 
99     // drive/root/Slash \xE2\x88\x95 in directory
100     EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry(
101         GetDirectoryEntry("Slash \xE2\x88\x95 in directory", "dir3", 5,
102                           root_local_id), &local_id));
103     const std::string dir3_local_id = local_id;
104 
105     // drive/root/Slash \xE2\x88\x95 in directory/Slash SubDir File.txt
106     EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry(GetFileEntry(
107         "Slash SubDir File.txt", "file3a", 6, dir3_local_id), &local_id));
108 
109     // drive/root/File 2.txt
110     EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry(GetFileEntry(
111         "File 2.txt", "file2", 7, root_local_id), &local_id));
112     EXPECT_EQ(FILE_ERROR_OK, cache_->Store(
113         local_id, temp_file_md5, temp_file, FileCache::FILE_OPERATION_COPY));
114 
115     // drive/root/Document 1 excludeDir-test
116     entry = GetFileEntry(
117         "Document 1 excludeDir-test", "doc1", 8, root_local_id);
118     entry.mutable_file_specific_info()->set_is_hosted_document(true);
119     entry.mutable_file_specific_info()->set_document_extension(".gdoc");
120     EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry(entry, &local_id));
121 
122   }
123 
GetFileEntry(const std::string & name,const std::string & resource_id,int64 last_accessed,const std::string & parent_local_id)124   ResourceEntry GetFileEntry(const std::string& name,
125                              const std::string& resource_id,
126                              int64 last_accessed,
127                              const std::string& parent_local_id) {
128     ResourceEntry entry;
129     entry.set_title(name);
130     entry.set_resource_id(resource_id);
131     entry.set_parent_local_id(parent_local_id);
132     entry.mutable_file_info()->set_last_accessed(last_accessed);
133     return entry;
134   }
135 
GetDirectoryEntry(const std::string & name,const std::string & resource_id,int64 last_accessed,const std::string & parent_local_id)136   ResourceEntry GetDirectoryEntry(const std::string& name,
137                                   const std::string& resource_id,
138                                   int64 last_accessed,
139                                   const std::string& parent_local_id) {
140     ResourceEntry entry;
141     entry.set_title(name);
142     entry.set_resource_id(resource_id);
143     entry.set_parent_local_id(parent_local_id);
144     entry.mutable_file_info()->set_last_accessed(last_accessed);
145     entry.mutable_file_info()->set_is_directory(true);
146     return entry;
147   }
148 
149   content::TestBrowserThreadBundle thread_bundle_;
150   base::ScopedTempDir temp_dir_;
151   scoped_ptr<FakeFreeDiskSpaceGetter> fake_free_disk_space_getter_;
152   scoped_ptr<ResourceMetadataStorage,
153              test_util::DestroyHelperForTests> metadata_storage_;
154   scoped_ptr<ResourceMetadata, test_util::DestroyHelperForTests>
155       resource_metadata_;
156   scoped_ptr<FileCache, test_util::DestroyHelperForTests> cache_;
157 };
158 
TEST_F(SearchMetadataTest,SearchMetadata_ZeroMatches)159 TEST_F(SearchMetadataTest, SearchMetadata_ZeroMatches) {
160   FileError error = FILE_ERROR_FAILED;
161   scoped_ptr<MetadataSearchResultVector> result;
162 
163   SearchMetadata(base::MessageLoopProxy::current(),
164                  resource_metadata_.get(),
165                  "NonExistent",
166                  SEARCH_METADATA_ALL,
167                  kDefaultAtMostNumMatches,
168                  google_apis::test_util::CreateCopyResultCallback(
169                      &error, &result));
170   base::RunLoop().RunUntilIdle();
171   EXPECT_EQ(FILE_ERROR_OK, error);
172   ASSERT_TRUE(result);
173   ASSERT_EQ(0U, result->size());
174 }
175 
TEST_F(SearchMetadataTest,SearchMetadata_RegularFile)176 TEST_F(SearchMetadataTest, SearchMetadata_RegularFile) {
177   FileError error = FILE_ERROR_FAILED;
178   scoped_ptr<MetadataSearchResultVector> result;
179 
180   SearchMetadata(base::MessageLoopProxy::current(),
181                  resource_metadata_.get(),
182                  "SubDirectory File 1.txt",
183                  SEARCH_METADATA_ALL,
184                  kDefaultAtMostNumMatches,
185                  google_apis::test_util::CreateCopyResultCallback(
186                      &error, &result));
187   base::RunLoop().RunUntilIdle();
188   EXPECT_EQ(FILE_ERROR_OK, error);
189   ASSERT_TRUE(result);
190   ASSERT_EQ(1U, result->size());
191   EXPECT_EQ("drive/root/Directory 1/SubDirectory File 1.txt",
192             result->at(0).path.AsUTF8Unsafe());
193 }
194 
195 // This test checks if |FindAndHighlightWrapper| does case-insensitive search.
196 // Tricker test cases for |FindAndHighlightWrapper| can be found below.
TEST_F(SearchMetadataTest,SearchMetadata_CaseInsensitiveSearch)197 TEST_F(SearchMetadataTest, SearchMetadata_CaseInsensitiveSearch) {
198   FileError error = FILE_ERROR_FAILED;
199   scoped_ptr<MetadataSearchResultVector> result;
200 
201   // The query is all in lower case.
202   SearchMetadata(base::MessageLoopProxy::current(),
203                  resource_metadata_.get(),
204                  "subdirectory file 1.txt",
205                  SEARCH_METADATA_ALL,
206                  kDefaultAtMostNumMatches,
207                  google_apis::test_util::CreateCopyResultCallback(
208                      &error, &result));
209   base::RunLoop().RunUntilIdle();
210   EXPECT_EQ(FILE_ERROR_OK, error);
211   ASSERT_TRUE(result);
212   ASSERT_EQ(1U, result->size());
213   EXPECT_EQ("drive/root/Directory 1/SubDirectory File 1.txt",
214             result->at(0).path.AsUTF8Unsafe());
215 }
216 
TEST_F(SearchMetadataTest,SearchMetadata_RegularFiles)217 TEST_F(SearchMetadataTest, SearchMetadata_RegularFiles) {
218   FileError error = FILE_ERROR_FAILED;
219   scoped_ptr<MetadataSearchResultVector> result;
220 
221   SearchMetadata(base::MessageLoopProxy::current(),
222                  resource_metadata_.get(),
223                  "SubDir",
224                  SEARCH_METADATA_ALL,
225                  kDefaultAtMostNumMatches,
226                  google_apis::test_util::CreateCopyResultCallback(
227                      &error, &result));
228   base::RunLoop().RunUntilIdle();
229   EXPECT_EQ(FILE_ERROR_OK, error);
230   ASSERT_TRUE(result);
231   ASSERT_EQ(2U, result->size());
232 
233   // All base names should contain "File". The results should be sorted by the
234   // last accessed time in descending order.
235   EXPECT_EQ("drive/root/Slash \xE2\x88\x95 in directory/Slash SubDir File.txt",
236             result->at(0).path.AsUTF8Unsafe());
237   EXPECT_EQ("drive/root/Directory 1/SubDirectory File 1.txt",
238             result->at(1).path.AsUTF8Unsafe());
239 }
240 
TEST_F(SearchMetadataTest,SearchMetadata_AtMostOneFile)241 TEST_F(SearchMetadataTest, SearchMetadata_AtMostOneFile) {
242   FileError error = FILE_ERROR_FAILED;
243   scoped_ptr<MetadataSearchResultVector> result;
244 
245   // There are two files matching "SubDir" but only one file should be
246   // returned.
247   SearchMetadata(base::MessageLoopProxy::current(),
248                  resource_metadata_.get(),
249                  "SubDir",
250                  SEARCH_METADATA_ALL,
251                  1,  // at_most_num_matches
252                  google_apis::test_util::CreateCopyResultCallback(
253                      &error, &result));
254   base::RunLoop().RunUntilIdle();
255   EXPECT_EQ(FILE_ERROR_OK, error);
256   ASSERT_TRUE(result);
257   ASSERT_EQ(1U, result->size());
258   EXPECT_EQ("drive/root/Slash \xE2\x88\x95 in directory/Slash SubDir File.txt",
259             result->at(0).path.AsUTF8Unsafe());
260 }
261 
TEST_F(SearchMetadataTest,SearchMetadata_Directory)262 TEST_F(SearchMetadataTest, SearchMetadata_Directory) {
263   FileError error = FILE_ERROR_FAILED;
264   scoped_ptr<MetadataSearchResultVector> result;
265 
266   SearchMetadata(base::MessageLoopProxy::current(),
267                  resource_metadata_.get(),
268                  "Directory 1",
269                  SEARCH_METADATA_ALL,
270                  kDefaultAtMostNumMatches,
271                  google_apis::test_util::CreateCopyResultCallback(
272                      &error, &result));
273   base::RunLoop().RunUntilIdle();
274   EXPECT_EQ(FILE_ERROR_OK, error);
275   ASSERT_TRUE(result);
276   ASSERT_EQ(1U, result->size());
277   EXPECT_EQ("drive/root/Directory 1", result->at(0).path.AsUTF8Unsafe());
278 }
279 
TEST_F(SearchMetadataTest,SearchMetadata_HostedDocument)280 TEST_F(SearchMetadataTest, SearchMetadata_HostedDocument) {
281   FileError error = FILE_ERROR_FAILED;
282   scoped_ptr<MetadataSearchResultVector> result;
283 
284   SearchMetadata(base::MessageLoopProxy::current(),
285                  resource_metadata_.get(),
286                  "Document",
287                  SEARCH_METADATA_ALL,
288                  kDefaultAtMostNumMatches,
289                  google_apis::test_util::CreateCopyResultCallback(
290                      &error, &result));
291   base::RunLoop().RunUntilIdle();
292   EXPECT_EQ(FILE_ERROR_OK, error);
293   ASSERT_TRUE(result);
294   ASSERT_EQ(1U, result->size());
295 
296   EXPECT_EQ("drive/root/Document 1 excludeDir-test.gdoc",
297             result->at(0).path.AsUTF8Unsafe());
298 }
299 
TEST_F(SearchMetadataTest,SearchMetadata_ExcludeHostedDocument)300 TEST_F(SearchMetadataTest, SearchMetadata_ExcludeHostedDocument) {
301   FileError error = FILE_ERROR_FAILED;
302   scoped_ptr<MetadataSearchResultVector> result;
303 
304   SearchMetadata(base::MessageLoopProxy::current(),
305                  resource_metadata_.get(),
306                  "Document",
307                  SEARCH_METADATA_EXCLUDE_HOSTED_DOCUMENTS,
308                  kDefaultAtMostNumMatches,
309                  google_apis::test_util::CreateCopyResultCallback(
310                      &error, &result));
311   base::RunLoop().RunUntilIdle();
312   EXPECT_EQ(FILE_ERROR_OK, error);
313   ASSERT_TRUE(result);
314   ASSERT_EQ(0U, result->size());
315 }
316 
TEST_F(SearchMetadataTest,SearchMetadata_SharedWithMe)317 TEST_F(SearchMetadataTest, SearchMetadata_SharedWithMe) {
318   FileError error = FILE_ERROR_FAILED;
319   scoped_ptr<MetadataSearchResultVector> result;
320 
321   SearchMetadata(base::MessageLoopProxy::current(),
322                  resource_metadata_.get(),
323                  "",
324                  SEARCH_METADATA_SHARED_WITH_ME,
325                  kDefaultAtMostNumMatches,
326                  google_apis::test_util::CreateCopyResultCallback(
327                      &error, &result));
328   base::RunLoop().RunUntilIdle();
329   EXPECT_EQ(FILE_ERROR_OK, error);
330   ASSERT_TRUE(result);
331   ASSERT_EQ(1U, result->size());
332   EXPECT_EQ("drive/root/Directory 1/Shared To The Account Owner.txt",
333             result->at(0).path.AsUTF8Unsafe());
334 }
335 
TEST_F(SearchMetadataTest,SearchMetadata_FileAndDirectory)336 TEST_F(SearchMetadataTest, SearchMetadata_FileAndDirectory) {
337   FileError error = FILE_ERROR_FAILED;
338   scoped_ptr<MetadataSearchResultVector> result;
339 
340   SearchMetadata(base::MessageLoopProxy::current(),
341                  resource_metadata_.get(),
342                  "excludeDir-test",
343                  SEARCH_METADATA_ALL,
344                  kDefaultAtMostNumMatches,
345                  google_apis::test_util::CreateCopyResultCallback(
346                      &error, &result));
347 
348   base::RunLoop().RunUntilIdle();
349   EXPECT_EQ(FILE_ERROR_OK, error);
350   ASSERT_TRUE(result);
351   ASSERT_EQ(2U, result->size());
352 
353   EXPECT_EQ("drive/root/Document 1 excludeDir-test.gdoc",
354             result->at(0).path.AsUTF8Unsafe());
355   EXPECT_EQ("drive/root/Directory 2 excludeDir-test",
356             result->at(1).path.AsUTF8Unsafe());
357 }
358 
TEST_F(SearchMetadataTest,SearchMetadata_ExcludeDirectory)359 TEST_F(SearchMetadataTest, SearchMetadata_ExcludeDirectory) {
360   FileError error = FILE_ERROR_FAILED;
361   scoped_ptr<MetadataSearchResultVector> result;
362 
363   SearchMetadata(base::MessageLoopProxy::current(),
364                  resource_metadata_.get(),
365                  "excludeDir-test",
366                  SEARCH_METADATA_EXCLUDE_DIRECTORIES,
367                  kDefaultAtMostNumMatches,
368                  google_apis::test_util::CreateCopyResultCallback(
369                      &error, &result));
370 
371   base::RunLoop().RunUntilIdle();
372   EXPECT_EQ(FILE_ERROR_OK, error);
373   ASSERT_TRUE(result);
374   ASSERT_EQ(1U, result->size());
375 
376   EXPECT_EQ("drive/root/Document 1 excludeDir-test.gdoc",
377             result->at(0).path.AsUTF8Unsafe());
378 }
379 
380 // "drive", "drive/root", "drive/other" should be excluded.
TEST_F(SearchMetadataTest,SearchMetadata_ExcludeSpecialDirectories)381 TEST_F(SearchMetadataTest, SearchMetadata_ExcludeSpecialDirectories) {
382   const char* kQueries[] = { "drive", "root", "other" };
383   for (size_t i = 0; i < arraysize(kQueries); ++i) {
384     FileError error = FILE_ERROR_FAILED;
385     scoped_ptr<MetadataSearchResultVector> result;
386 
387     const std::string query = kQueries[i];
388     SearchMetadata(base::MessageLoopProxy::current(),
389                    resource_metadata_.get(),
390                    query,
391                    SEARCH_METADATA_ALL,
392                    kDefaultAtMostNumMatches,
393                    google_apis::test_util::CreateCopyResultCallback(
394                        &error, &result));
395 
396     base::RunLoop().RunUntilIdle();
397     EXPECT_EQ(FILE_ERROR_OK, error);
398     ASSERT_TRUE(result);
399     ASSERT_TRUE(result->empty()) << ": " << query << " should not match";
400   }
401 }
402 
TEST_F(SearchMetadataTest,SearchMetadata_Offline)403 TEST_F(SearchMetadataTest, SearchMetadata_Offline) {
404   FileError error = FILE_ERROR_FAILED;
405   scoped_ptr<MetadataSearchResultVector> result;
406 
407   SearchMetadata(base::MessageLoopProxy::current(),
408                  resource_metadata_.get(),
409                  "",
410                  SEARCH_METADATA_OFFLINE,
411                  kDefaultAtMostNumMatches,
412                  google_apis::test_util::CreateCopyResultCallback(
413                      &error, &result));
414   base::RunLoop().RunUntilIdle();
415   EXPECT_EQ(FILE_ERROR_OK, error);
416   ASSERT_EQ(3U, result->size());
417 
418   // This is not included in the cache but is a hosted document.
419   EXPECT_EQ("drive/root/Document 1 excludeDir-test.gdoc",
420             result->at(0).path.AsUTF8Unsafe());
421 
422   EXPECT_EQ("drive/root/File 2.txt",
423             result->at(1).path.AsUTF8Unsafe());
424   EXPECT_EQ("drive/root/Directory 1/SubDirectory File 1.txt",
425             result->at(2).path.AsUTF8Unsafe());
426 }
427 
TEST(SearchMetadataSimpleTest,FindAndHighlight_ZeroMatches)428 TEST(SearchMetadataSimpleTest, FindAndHighlight_ZeroMatches) {
429   std::string highlighted_text;
430   EXPECT_FALSE(FindAndHighlightWrapper("text", "query", &highlighted_text));
431 }
432 
TEST(SearchMetadataSimpleTest,FindAndHighlight_EmptyText)433 TEST(SearchMetadataSimpleTest, FindAndHighlight_EmptyText) {
434   std::string highlighted_text;
435   EXPECT_FALSE(FindAndHighlightWrapper("", "query", &highlighted_text));
436 }
437 
TEST(SearchMetadataSimpleTest,FindAndHighlight_FullMatch)438 TEST(SearchMetadataSimpleTest, FindAndHighlight_FullMatch) {
439   std::string highlighted_text;
440   EXPECT_TRUE(FindAndHighlightWrapper("hello", "hello", &highlighted_text));
441   EXPECT_EQ("<b>hello</b>", highlighted_text);
442 }
443 
TEST(SearchMetadataSimpleTest,FindAndHighlight_StartWith)444 TEST(SearchMetadataSimpleTest, FindAndHighlight_StartWith) {
445   std::string highlighted_text;
446   EXPECT_TRUE(FindAndHighlightWrapper("hello, world", "hello",
447                                      &highlighted_text));
448   EXPECT_EQ("<b>hello</b>, world", highlighted_text);
449 }
450 
TEST(SearchMetadataSimpleTest,FindAndHighlight_EndWith)451 TEST(SearchMetadataSimpleTest, FindAndHighlight_EndWith) {
452   std::string highlighted_text;
453   EXPECT_TRUE(FindAndHighlightWrapper("hello, world", "world",
454                                      &highlighted_text));
455   EXPECT_EQ("hello, <b>world</b>", highlighted_text);
456 }
457 
TEST(SearchMetadataSimpleTest,FindAndHighlight_InTheMiddle)458 TEST(SearchMetadataSimpleTest, FindAndHighlight_InTheMiddle) {
459   std::string highlighted_text;
460   EXPECT_TRUE(FindAndHighlightWrapper("yo hello, world", "hello",
461                                      &highlighted_text));
462   EXPECT_EQ("yo <b>hello</b>, world", highlighted_text);
463 }
464 
TEST(SearchMetadataSimpleTest,FindAndHighlight_MultipeMatches)465 TEST(SearchMetadataSimpleTest, FindAndHighlight_MultipeMatches) {
466   std::string highlighted_text;
467   EXPECT_TRUE(FindAndHighlightWrapper("yoyoyoyoy", "yoy", &highlighted_text));
468   // Only the first match is highlighted.
469   EXPECT_EQ("<b>yoy</b>oyoyoy", highlighted_text);
470 }
471 
TEST(SearchMetadataSimpleTest,FindAndHighlight_IgnoreCase)472 TEST(SearchMetadataSimpleTest, FindAndHighlight_IgnoreCase) {
473   std::string highlighted_text;
474   EXPECT_TRUE(FindAndHighlightWrapper("HeLLo", "hello", &highlighted_text));
475   EXPECT_EQ("<b>HeLLo</b>", highlighted_text);
476 }
477 
TEST(SearchMetadataSimpleTest,FindAndHighlight_IgnoreCaseNonASCII)478 TEST(SearchMetadataSimpleTest, FindAndHighlight_IgnoreCaseNonASCII) {
479   std::string highlighted_text;
480 
481   // Case and accent ignorance in Greek. Find "socra" in "Socra'tes".
482   EXPECT_TRUE(FindAndHighlightWrapper(
483       "\xCE\xA3\xCF\x89\xCE\xBA\xCF\x81\xCE\xAC\xCF\x84\xCE\xB7\xCF\x82",
484       "\xCF\x83\xCF\x89\xCE\xBA\xCF\x81\xCE\xB1", &highlighted_text));
485   EXPECT_EQ(
486       "<b>\xCE\xA3\xCF\x89\xCE\xBA\xCF\x81\xCE\xAC</b>\xCF\x84\xCE\xB7\xCF\x82",
487       highlighted_text);
488 
489   // In Japanese characters.
490   // Find Hiragana "pi" + "(small)ya" in Katakana "hi" + semi-voiced-mark + "ya"
491   EXPECT_TRUE(FindAndHighlightWrapper(
492       "\xE3\x81\xB2\xE3\x82\x9A\xE3\x82\x83\xE3\x83\xBC",
493       "\xE3\x83\x94\xE3\x83\xA4",
494       &highlighted_text));
495   EXPECT_EQ(
496       "<b>\xE3\x81\xB2\xE3\x82\x9A\xE3\x82\x83</b>\xE3\x83\xBC",
497       highlighted_text);
498 }
499 
TEST(SearchMetadataSimpleTest,MultiTextBySingleQuery)500 TEST(SearchMetadataSimpleTest, MultiTextBySingleQuery) {
501   base::i18n::FixedPatternStringSearchIgnoringCaseAndAccents query(
502       base::UTF8ToUTF16("hello"));
503 
504   std::string highlighted_text;
505   EXPECT_TRUE(FindAndHighlight("hello", &query, &highlighted_text));
506   EXPECT_EQ("<b>hello</b>", highlighted_text);
507   EXPECT_FALSE(FindAndHighlight("goodbye", &query, &highlighted_text));
508   EXPECT_TRUE(FindAndHighlight("1hello2", &query, &highlighted_text));
509   EXPECT_EQ("1<b>hello</b>2", highlighted_text);
510 }
511 
TEST(SearchMetadataSimpleTest,FindAndHighlight_MetaChars)512 TEST(SearchMetadataSimpleTest, FindAndHighlight_MetaChars) {
513   std::string highlighted_text;
514   EXPECT_TRUE(FindAndHighlightWrapper("<hello>", "hello", &highlighted_text));
515   EXPECT_EQ("&lt;<b>hello</b>&gt;", highlighted_text);
516 }
517 
TEST(SearchMetadataSimpleTest,FindAndHighlight_MoreMetaChars)518 TEST(SearchMetadataSimpleTest, FindAndHighlight_MoreMetaChars) {
519   std::string highlighted_text;
520   EXPECT_TRUE(FindAndHighlightWrapper("a&b&c&d", "b&c", &highlighted_text));
521   EXPECT_EQ("a&amp;<b>b&amp;c</b>&amp;d", highlighted_text);
522 }
523 
524 }  // namespace internal
525 }  // namespace drive
526