1 // Copyright 2010-2018, Google Inc.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 //     * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 //     * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
13 // distribution.
14 //     * Neither the name of Google Inc. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 
30 #include "rewriter/variants_rewriter.h"
31 
32 #include <memory>
33 #include <string>
34 
35 #include "base/logging.h"
36 #include "base/util.h"
37 #include "config/character_form_manager.h"
38 #include "converter/segments.h"
39 #include "data_manager/testing/mock_data_manager.h"
40 #include "dictionary/pos_matcher.h"
41 #include "protocol/config.pb.h"
42 #include "request/conversion_request.h"
43 #include "testing/base/public/gunit.h"
44 #include "testing/base/public/mozctest.h"
45 
46 namespace mozc {
47 namespace {
48 
49 using config::CharacterFormManager;
50 using config::Config;
51 using dictionary::POSMatcher;
52 
AppendString(const string & lhs,const string & rhs)53 string AppendString(const string &lhs, const string &rhs) {
54   if (!rhs.empty()) {
55     return lhs + ' ' + rhs;
56   }
57   return lhs;
58 }
59 
60 }  // namespace
61 
62 class VariantsRewriterTest : public ::testing::Test {
63  protected:
64   // Explicitly define constructor to prevent Visual C++ from
65   // considering this class as POD.
VariantsRewriterTest()66   VariantsRewriterTest() {}
67 
SetUp()68   void SetUp() override {
69     Reset();
70     pos_matcher_.Set(mock_data_manager_.GetPOSMatcherData());
71   }
72 
TearDown()73   void TearDown() override {
74     Reset();
75   }
76 
Reset()77   void Reset() {
78     CharacterFormManager::GetCharacterFormManager()->SetDefaultRule();
79     CharacterFormManager::GetCharacterFormManager()->ClearHistory();
80   }
81 
InitSegmentsForAlphabetRewrite(const string & value,Segments * segments) const82   void InitSegmentsForAlphabetRewrite(const string &value,
83                                       Segments *segments) const {
84     Segment *segment = segments->push_back_segment();
85     CHECK(segment);
86     segment->set_key(value);
87     Segment::Candidate *candidate = segment->add_candidate();
88     CHECK(candidate);
89     candidate->Init();
90     candidate->key = value;
91     candidate->content_key = value;
92     candidate->value = value;
93     candidate->content_value = value;
94   }
95 
CreateVariantsRewriter() const96   VariantsRewriter *CreateVariantsRewriter() const {
97     return new VariantsRewriter(pos_matcher_);
98   }
99 
100   POSMatcher pos_matcher_;
101 
102  private:
103   const testing::ScopedTmpUserProfileDirectory tmp_profile_dir_;
104   const testing::MockDataManager mock_data_manager_;
105 };
106 
TEST_F(VariantsRewriterTest,RewriteTest)107 TEST_F(VariantsRewriterTest, RewriteTest) {
108   std::unique_ptr<VariantsRewriter> rewriter(CreateVariantsRewriter());
109   Segments segments;
110   const ConversionRequest request;
111 
112   Segment *seg = segments.push_back_segment();
113 
114   {
115     Segment::Candidate *candidate = seg->add_candidate();
116     candidate->Init();
117     candidate->value = "あいう";
118     candidate->content_value = "あいう";
119     EXPECT_FALSE(rewriter->Rewrite(request, &segments));
120     seg->clear_candidates();
121   }
122 
123   {
124     Segment::Candidate *candidate = seg->add_candidate();
125     candidate->Init();
126     candidate->value = "012";
127     candidate->content_value = "012";
128     CharacterFormManager::GetCharacterFormManager()->SetCharacterForm(
129         "012", Config::FULL_WIDTH);
130 
131     EXPECT_TRUE(rewriter->Rewrite(request, &segments));
132     EXPECT_EQ(2, seg->candidates_size());
133     EXPECT_EQ("012", seg->candidate(0).value);
134     EXPECT_EQ("012", seg->candidate(0).content_value);
135     EXPECT_EQ("012", seg->candidate(1).value);
136     EXPECT_EQ("012", seg->candidate(1).content_value);
137     seg->clear_candidates();
138   }
139 
140   {
141     Segment::Candidate *candidate = seg->add_candidate();
142     candidate->Init();
143     candidate->value = "012";
144     candidate->content_value = "012";
145     candidate->attributes |= Segment::Candidate::NO_VARIANTS_EXPANSION;
146     CharacterFormManager::GetCharacterFormManager()->SetCharacterForm(
147         "012", Config::FULL_WIDTH);
148 
149     EXPECT_FALSE(rewriter->Rewrite(request, &segments));
150     EXPECT_EQ(1, seg->candidates_size());
151     seg->clear_candidates();
152   }
153 
154   {
155     Segment::Candidate *candidate = seg->add_candidate();
156     candidate->Init();
157     candidate->value = "Google";
158     candidate->content_value = "Google";
159     CharacterFormManager::GetCharacterFormManager()->
160       SetCharacterForm("abc", Config::FULL_WIDTH);
161 
162     EXPECT_TRUE(rewriter->Rewrite(request, &segments));
163     EXPECT_EQ(2, seg->candidates_size());
164     EXPECT_EQ("Google", seg->candidate(0).value);
165     EXPECT_EQ("Google", seg->candidate(0).content_value);
166     EXPECT_EQ("Google", seg->candidate(1).value);
167     EXPECT_EQ("Google", seg->candidate(1).content_value);
168     seg->clear_candidates();
169   }
170 
171   {
172     Segment::Candidate *candidate = seg->add_candidate();
173     candidate->Init();
174     candidate->value = "@";
175     candidate->content_value = "@";
176     CharacterFormManager::GetCharacterFormManager()->SetCharacterForm(
177         "@", Config::FULL_WIDTH);
178 
179     EXPECT_TRUE(rewriter->Rewrite(request, &segments));
180     EXPECT_EQ(2, seg->candidates_size());
181     EXPECT_EQ("@", seg->candidate(0).value);
182     EXPECT_EQ("@", seg->candidate(0).content_value);
183     EXPECT_EQ("@", seg->candidate(1).value);
184     EXPECT_EQ("@", seg->candidate(1).content_value);
185     seg->clear_candidates();
186   }
187 
188   {
189     Segment::Candidate *candidate = seg->add_candidate();
190     candidate->Init();
191     candidate->value = "グーグル";
192     candidate->content_value = "グーグル";
193     CharacterFormManager::GetCharacterFormManager()->SetCharacterForm(
194         "アイウ", Config::FULL_WIDTH);
195 
196     EXPECT_FALSE(rewriter->Rewrite(request, &segments));
197     seg->clear_candidates();
198   }
199 
200   {
201     Segment::Candidate *candidate = seg->add_candidate();
202     candidate->Init();
203     candidate->value = "グーグル";
204     candidate->content_value = "グーグル";
205     CharacterFormManager::GetCharacterFormManager()->AddConversionRule(
206         "アイウ", Config::HALF_WIDTH);
207 
208     EXPECT_TRUE(rewriter->Rewrite(request, &segments));
209     EXPECT_EQ(2, seg->candidates_size());
210     EXPECT_EQ("グーグル", seg->candidate(0).value);
211     EXPECT_EQ("グーグル", seg->candidate(0).content_value);
212     EXPECT_EQ("グーグル", seg->candidate(1).value);
213     EXPECT_EQ("グーグル", seg->candidate(1).content_value);
214     seg->clear_candidates();
215   }
216 }
217 
TEST_F(VariantsRewriterTest,RewriteTestManyCandidates)218 TEST_F(VariantsRewriterTest, RewriteTestManyCandidates) {
219   std::unique_ptr<VariantsRewriter> rewriter(CreateVariantsRewriter());
220   Segments segments;
221   const ConversionRequest request;
222   Segment *seg = segments.push_back_segment();
223 
224   {
225     for (int i = 0; i < 10; ++i) {
226       Segment::Candidate *candidate1 = seg->add_candidate();
227       candidate1->Init();
228       candidate1->value = std::to_string(i);
229       candidate1->content_value = std::to_string(i);
230       Segment::Candidate *candidate2 = seg->add_candidate();
231       candidate2->Init();
232       candidate2->content_key = "ぐーぐる";
233       candidate2->key = "ぐーぐる";
234       candidate2->value = "ぐーぐる";
235       candidate2->content_value = "ぐーぐる";
236     }
237 
238     EXPECT_TRUE(rewriter->Rewrite(request, &segments));
239     EXPECT_EQ(30, seg->candidates_size());
240 
241     for (int i = 0; i < 10; ++i) {
242       EXPECT_EQ(std::to_string(i), seg->candidate(3 * i + 1).value);
243       EXPECT_EQ(std::to_string(i), seg->candidate(3 * i + 1).content_value);
244       string full_width;
245       Util::HalfWidthToFullWidth(seg->candidate(3 * i + 1).value, &full_width);
246       EXPECT_EQ(full_width, seg->candidate(3 * i).value);
247       EXPECT_EQ(full_width, seg->candidate(3 * i).content_value);
248       EXPECT_EQ("ぐーぐる", seg->candidate(3 * i + 2).value);
249       EXPECT_EQ("ぐーぐる", seg->candidate(3 * i + 2).content_value);
250     }
251   }
252 
253   {
254     seg->Clear();
255 
256     for (int i = 0; i < 10; ++i) {
257       Segment::Candidate *candidate1 = seg->add_candidate();
258       candidate1->Init();
259       candidate1->content_key = "ぐーぐる";
260       candidate1->key = "ぐーぐる";
261       candidate1->value = "ぐーぐる";
262       candidate1->content_value = "ぐーぐる";
263       Segment::Candidate *candidate2 = seg->add_candidate();
264       candidate2->Init();
265       candidate2->value = std::to_string(i);
266       candidate2->content_value = std::to_string(i);
267     }
268 
269     EXPECT_TRUE(rewriter->Rewrite(request, &segments));
270     EXPECT_EQ(30, seg->candidates_size());
271 
272     for (int i = 0; i < 10; ++i) {
273       EXPECT_EQ(std::to_string(i), seg->candidate(3 * i + 2).value);
274       EXPECT_EQ(std::to_string(i), seg->candidate(3 * i + 2).content_value);
275       string full_width;
276       Util::HalfWidthToFullWidth(seg->candidate(3 * i + 2).value, &full_width);
277       EXPECT_EQ(full_width, seg->candidate(3 * i + 1).value);
278       EXPECT_EQ(full_width, seg->candidate(3 * i + 1).content_value);
279       EXPECT_EQ("ぐーぐる", seg->candidate(3 * i).value);
280       EXPECT_EQ("ぐーぐる", seg->candidate(3 * i).content_value);
281     }
282   }
283 }
284 
TEST_F(VariantsRewriterTest,SetDescriptionForCandidate)285 TEST_F(VariantsRewriterTest, SetDescriptionForCandidate) {
286   {
287     Segment::Candidate candidate;
288     candidate.Init();
289     candidate.value = "HalfASCII";
290     candidate.content_value = candidate.value;
291     candidate.content_key = "halfascii";
292     VariantsRewriter::SetDescriptionForCandidate(pos_matcher_, &candidate);
293     // "[半] アルファベット"
294     EXPECT_EQ(AppendString(VariantsRewriter::kHalfWidth,
295                            VariantsRewriter::kAlphabet),
296               candidate.description);
297   }
298   // containing symbols
299   {
300     Segment::Candidate candidate;
301     candidate.Init();
302     candidate.value = "Half ASCII";
303     candidate.content_value = candidate.value;
304     candidate.content_key = "half ascii";
305     VariantsRewriter::SetDescriptionForCandidate(pos_matcher_, &candidate);
306     // "[半] アルファベット"
307     EXPECT_EQ(AppendString(VariantsRewriter::kHalfWidth,
308                            VariantsRewriter::kAlphabet),
309               candidate.description);
310   }
311   {
312     Segment::Candidate candidate;
313     candidate.Init();
314     candidate.value = "Half!ASCII!";
315     candidate.content_value = candidate.value;
316     candidate.content_key = "half!ascii!";
317     VariantsRewriter::SetDescriptionForCandidate(pos_matcher_, &candidate);
318     // "[半] アルファベット"
319     EXPECT_EQ(AppendString(VariantsRewriter::kHalfWidth,
320                            VariantsRewriter::kAlphabet),
321               candidate.description);
322   }
323   {
324     Segment::Candidate candidate;
325     candidate.Init();
326     candidate.value = "CD-ROM";
327     candidate.content_value = candidate.value;
328     candidate.content_key = "しーでぃーろむ";
329     VariantsRewriter::SetDescriptionForCandidate(pos_matcher_, &candidate);
330     // "[半] アルファベット"
331     EXPECT_EQ(AppendString(VariantsRewriter::kHalfWidth,
332                            VariantsRewriter::kAlphabet),
333               candidate.description);
334   }
335   {
336     Segment::Candidate candidate;
337     candidate.Init();
338     candidate.value = "コギト・エルゴ・スム";
339     candidate.content_value = candidate.value;
340     candidate.content_key = "こぎとえるごすむ";
341     VariantsRewriter::SetDescriptionForCandidate(pos_matcher_, &candidate);
342     // "[全] カタカナ"
343     EXPECT_EQ(AppendString(VariantsRewriter::kFullWidth,
344                            VariantsRewriter::kKatakana),
345         candidate.description);
346   }
347   {
348     Segment::Candidate candidate;
349     candidate.Init();
350     candidate.value = "!@#";
351     candidate.content_value = candidate.value;
352     candidate.content_key = "!@#";
353     VariantsRewriter::SetDescriptionForCandidate(pos_matcher_, &candidate);
354     EXPECT_EQ(VariantsRewriter::kHalfWidth, candidate.description);
355   }
356   {
357     Segment::Candidate candidate;
358     candidate.Init();
359     candidate.value = "「ABC」";
360     candidate.content_value = candidate.value;
361     candidate.content_key = "[ABC]";
362     VariantsRewriter::SetDescriptionForCandidate(pos_matcher_, &candidate);
363     // "[全] アルファベット"
364     EXPECT_EQ(AppendString(VariantsRewriter::kFullWidth,
365                            VariantsRewriter::kAlphabet),
366               candidate.description);
367   }
368   {
369     Segment::Candidate candidate;
370     candidate.Init();
371     candidate.value = "草彅剛";
372     candidate.content_value = candidate.value;
373     candidate.content_key = "くさなぎつよし";
374     VariantsRewriter::SetDescriptionForCandidate(pos_matcher_, &candidate);
375     EXPECT_EQ(VariantsRewriter::kPlatformDependent, candidate.description);
376   }
377   {
378     Segment::Candidate candidate;
379     candidate.Init();
380     candidate.value = "\\";
381     candidate.content_value = candidate.value;
382     candidate.content_key = "えん";
383     VariantsRewriter::SetDescriptionForCandidate(pos_matcher_, &candidate);
384     const char *expected = "[半] バックスラッシュ";
385     EXPECT_EQ(expected, candidate.description);
386   }
387   {
388     Segment::Candidate candidate;
389     candidate.Init();
390     candidate.value = "\";  // Full-width backslash
391     candidate.content_value = candidate.value;
392     candidate.content_key = "えん";
393     VariantsRewriter::SetDescriptionForCandidate(pos_matcher_, &candidate);
394     const char *expected = "[全] バックスラッシュ";
395     EXPECT_EQ(expected, candidate.description);
396   }
397   {
398     Segment::Candidate candidate;
399     candidate.Init();
400     candidate.value = "¥";  // Half-width yen-symbol
401     candidate.content_value = candidate.value;
402     candidate.content_key = "えん";
403     VariantsRewriter::SetDescriptionForCandidate(pos_matcher_, &candidate);
404     // "[半] 円記号 <機種依存文字>" for Desktop,
405     // "[半] 円記号 <機種依存>" for Android
406     string expected = "[半] 円記号 ";
407     expected.append(VariantsRewriter::kPlatformDependent);
408     EXPECT_EQ(expected, candidate.description);
409   }
410   {
411     Segment::Candidate candidate;
412     candidate.Init();
413     candidate.value = "¥";   // Full-width yen-symbol
414     candidate.content_value = candidate.value;
415     candidate.content_key = "えん";
416     VariantsRewriter::SetDescriptionForCandidate(pos_matcher_, &candidate);
417     const char *expected = "[全] 円記号";
418     EXPECT_EQ(expected, candidate.description);
419   }
420   {
421     Segment::Candidate candidate;
422     candidate.Init();
423     // An emoji character of mouse face.
424     candidate.value = "��";
425     candidate.content_value = candidate.value;
426     candidate.content_key = "ねずみ";
427     candidate.description = "絵文字";
428     VariantsRewriter::SetDescriptionForCandidate(pos_matcher_, &candidate);
429     // "絵文字 <機種依存文字>" for Desktop, "絵文字 <機種依存>" for Andorid
430     string expected("絵文字" " ");
431     expected.append(VariantsRewriter::kPlatformDependent);
432     EXPECT_EQ(expected, candidate.description);
433   }
434 }
435 
TEST_F(VariantsRewriterTest,SetDescriptionForTransliteration)436 TEST_F(VariantsRewriterTest, SetDescriptionForTransliteration) {
437   {
438     Segment::Candidate candidate;
439     candidate.Init();
440     candidate.value = "HalfASCII";
441     candidate.content_value = candidate.value;
442     candidate.content_key = "halfascii";
443     VariantsRewriter::SetDescriptionForTransliteration(pos_matcher_,
444                                                        &candidate);
445     // "[半] アルファベット"
446     EXPECT_EQ(AppendString(VariantsRewriter::kHalfWidth,
447                            VariantsRewriter::kAlphabet),
448               candidate.description);
449   }
450   {
451     Segment::Candidate candidate;
452     candidate.Init();
453     candidate.value = "!@#";
454     candidate.content_value = candidate.value;
455     candidate.content_key = "!@#";
456     VariantsRewriter::SetDescriptionForTransliteration(pos_matcher_,
457                                                        &candidate);
458     // "[半]"
459     EXPECT_EQ(VariantsRewriter::kHalfWidth, candidate.description);
460   }
461   {
462     Segment::Candidate candidate;
463     candidate.Init();
464     candidate.value = "「ABC」";
465     candidate.content_value = candidate.value;
466     candidate.content_key = "[ABC]";
467     VariantsRewriter::SetDescriptionForTransliteration(pos_matcher_,
468                                                        &candidate);
469     // "[全] アルファベット"
470     EXPECT_EQ(AppendString(VariantsRewriter::kFullWidth,
471                            VariantsRewriter::kAlphabet),
472               candidate.description);
473   }
474   {
475     Segment::Candidate candidate;
476     candidate.Init();
477     candidate.value = "草彅剛";
478     candidate.content_value = candidate.value;
479     candidate.content_key = "くさなぎつよし";
480     VariantsRewriter::SetDescriptionForTransliteration(pos_matcher_,
481                                                        &candidate);
482     EXPECT_EQ(VariantsRewriter::kPlatformDependent, candidate.description);
483   }
484 }
485 
TEST_F(VariantsRewriterTest,SetDescriptionForPrediction)486 TEST_F(VariantsRewriterTest, SetDescriptionForPrediction) {
487   {
488     Segment::Candidate candidate;
489     candidate.Init();
490     candidate.value = "HalfASCII";
491     candidate.content_value = candidate.value;
492     candidate.content_key = "halfascii";
493     VariantsRewriter::SetDescriptionForPrediction(pos_matcher_, &candidate);
494     EXPECT_EQ("", candidate.description);
495   }
496   // containing symbols
497   {
498     Segment::Candidate candidate;
499     candidate.Init();
500     candidate.value = "Half ASCII";
501     candidate.content_value = candidate.value;
502     candidate.content_key = "half ascii";
503     VariantsRewriter::SetDescriptionForPrediction(pos_matcher_, &candidate);
504     EXPECT_EQ("", candidate.description);
505   }
506   {
507     Segment::Candidate candidate;
508     candidate.Init();
509     candidate.value = "Half!ASCII!";
510     candidate.content_value = candidate.value;
511     candidate.content_key = "half!ascii!";
512     VariantsRewriter::SetDescriptionForPrediction(pos_matcher_, &candidate);
513     EXPECT_EQ("", candidate.description);
514   }
515   {
516     Segment::Candidate candidate;
517     candidate.Init();
518     candidate.value = "CD-ROM";
519     candidate.content_value = candidate.value;
520     candidate.content_key = "しーでぃーろむ";
521     VariantsRewriter::SetDescriptionForPrediction(pos_matcher_, &candidate);
522     EXPECT_EQ("", candidate.description);
523   }
524   {
525     Segment::Candidate candidate;
526     candidate.Init();
527     candidate.value = "!@#";
528     candidate.content_value = candidate.value;
529     candidate.content_key = "!@#";
530     VariantsRewriter::SetDescriptionForPrediction(pos_matcher_, &candidate);
531     EXPECT_EQ("", candidate.description);
532   }
533   {
534     Segment::Candidate candidate;
535     candidate.Init();
536     candidate.value = "「ABC」";
537     candidate.content_value = candidate.value;
538     candidate.content_key = "[ABC]";
539     VariantsRewriter::SetDescriptionForPrediction(pos_matcher_, &candidate);
540     EXPECT_EQ("", candidate.description);
541   }
542   {
543     Segment::Candidate candidate;
544     candidate.Init();
545     candidate.value = "草彅剛";
546     candidate.content_value = candidate.value;
547     candidate.content_key = "くさなぎつよし";
548     VariantsRewriter::SetDescriptionForPrediction(pos_matcher_, &candidate);
549     EXPECT_EQ(VariantsRewriter::kPlatformDependent, candidate.description);
550   }
551 }
552 
TEST_F(VariantsRewriterTest,RewriteForConversion)553 TEST_F(VariantsRewriterTest, RewriteForConversion) {
554   CharacterFormManager *character_form_manager =
555       CharacterFormManager::GetCharacterFormManager();
556   std::unique_ptr<VariantsRewriter> rewriter(CreateVariantsRewriter());
557   const ConversionRequest request;
558   {
559     Segments segments;
560     segments.set_request_type(Segments::CONVERSION);
561     {
562       Segment *segment = segments.push_back_segment();
563       segment->set_key("abc");
564       Segment::Candidate *candidate = segment->add_candidate();
565       candidate->Init();
566       candidate->key = "abc";
567       candidate->content_key = "abc";
568       candidate->value = "abc";
569       candidate->content_value = "abc";
570     }
571     EXPECT_TRUE(rewriter->Rewrite(request, &segments));
572     EXPECT_EQ(1, segments.segments_size());
573     EXPECT_EQ(2, segments.segment(0).candidates_size());
574 
575     EXPECT_EQ(Config::FULL_WIDTH,
576               character_form_manager->GetConversionCharacterForm("abc"));
577 
578     EXPECT_EQ("abc", segments.segment(0).candidate(0).value);
579     EXPECT_EQ("abc", segments.segment(0).candidate(1).value);
580   }
581   {
582     character_form_manager->SetCharacterForm("abc", Config::HALF_WIDTH);
583     Segments segments;
584     segments.set_request_type(Segments::CONVERSION);
585     {
586       Segment *segment = segments.push_back_segment();
587       segment->set_key("abc");
588       Segment::Candidate *candidate = segment->add_candidate();
589       candidate->Init();
590       candidate->key = "abc";
591       candidate->content_key = "abc";
592       candidate->value = "abc";
593       candidate->content_value = "abc";
594     }
595     EXPECT_TRUE(rewriter->Rewrite(request, &segments));
596     EXPECT_EQ(1, segments.segments_size());
597     EXPECT_EQ(2, segments.segment(0).candidates_size());
598 
599     EXPECT_EQ(Config::HALF_WIDTH,
600               character_form_manager->GetConversionCharacterForm("abc"));
601 
602     EXPECT_EQ("abc", segments.segment(0).candidate(0).value);
603     EXPECT_EQ("abc", segments.segment(0).candidate(1).value);
604   }
605 }
606 
TEST_F(VariantsRewriterTest,RewriteForPrediction)607 TEST_F(VariantsRewriterTest, RewriteForPrediction) {
608   CharacterFormManager *character_form_manager =
609       CharacterFormManager::GetCharacterFormManager();
610   std::unique_ptr<VariantsRewriter> rewriter(CreateVariantsRewriter());
611   const ConversionRequest request;
612   {
613     Segments segments;
614     segments.set_request_type(Segments::PREDICTION);
615     InitSegmentsForAlphabetRewrite("abc", &segments);
616     EXPECT_TRUE(rewriter->Rewrite(request, &segments));
617     EXPECT_EQ(1, segments.segments_size());
618     EXPECT_EQ(2, segments.segment(0).candidates_size());
619 
620     EXPECT_EQ(Config::FULL_WIDTH,
621               character_form_manager->GetConversionCharacterForm("abc"));
622 
623     EXPECT_EQ("abc", segments.segment(0).candidate(0).value);
624     EXPECT_EQ("abc", segments.segment(0).candidate(1).value);
625   }
626   {
627     character_form_manager->SetCharacterForm("abc", Config::HALF_WIDTH);
628     Segments segments;
629     segments.set_request_type(Segments::PREDICTION);
630     InitSegmentsForAlphabetRewrite("abc", &segments);
631     EXPECT_TRUE(rewriter->Rewrite(request, &segments));
632     EXPECT_EQ(1, segments.segments_size());
633     EXPECT_EQ(2, segments.segment(0).candidates_size());
634 
635     EXPECT_EQ(Config::HALF_WIDTH,
636               character_form_manager->GetConversionCharacterForm("abc"));
637 
638     EXPECT_EQ("abc", segments.segment(0).candidate(0).value);
639     EXPECT_EQ("abc", segments.segment(0).candidate(1).value);
640   }
641 }
642 
TEST_F(VariantsRewriterTest,RewriteForSuggestion)643 TEST_F(VariantsRewriterTest, RewriteForSuggestion) {
644   CharacterFormManager *character_form_manager =
645       CharacterFormManager::GetCharacterFormManager();
646   std::unique_ptr<VariantsRewriter> rewriter(CreateVariantsRewriter());
647   const ConversionRequest request;
648   {
649     Segments segments;
650     segments.set_request_type(Segments::SUGGESTION);
651     InitSegmentsForAlphabetRewrite("abc", &segments);
652     EXPECT_TRUE(rewriter->Rewrite(request, &segments));
653     EXPECT_EQ(1, segments.segments_size());
654     EXPECT_EQ(1, segments.segment(0).candidates_size());
655 
656     EXPECT_EQ(Config::FULL_WIDTH,
657               character_form_manager->GetConversionCharacterForm("abc"));
658 
659     EXPECT_EQ("abc", segments.segment(0).candidate(0).value);
660   }
661   {
662     character_form_manager->SetCharacterForm("abc", Config::HALF_WIDTH);
663     Segments segments;
664     segments.set_request_type(Segments::SUGGESTION);
665     InitSegmentsForAlphabetRewrite("abc", &segments);
666     EXPECT_TRUE(rewriter->Rewrite(request, &segments));
667     EXPECT_EQ(1, segments.segments_size());
668     EXPECT_EQ(1, segments.segment(0).candidates_size());
669 
670     EXPECT_EQ(Config::HALF_WIDTH,
671               character_form_manager->GetConversionCharacterForm("abc"));
672 
673     EXPECT_EQ("abc", segments.segment(0).candidate(0).value);
674   }
675   {
676     // Test for candidate with inner segment boundary.
677     Segments segments;
678     segments.set_request_type(Segments::SUGGESTION);
679 
680     Segment *segment = segments.push_back_segment();
681     segment->set_key("まじ!");
682 
683     Segment::Candidate *candidate = segment->add_candidate();
684     candidate->Init();
685     candidate->key = "まじ!";
686     candidate->content_key = candidate->key;
687     candidate->value = "マジ!";
688     candidate->content_value = candidate->value;
689     candidate->inner_segment_boundary.push_back(
690         Segment::Candidate::EncodeLengths(6, 6, 6, 6));  // 6 bytes for "まじ"
691     candidate->inner_segment_boundary.push_back(
692         Segment::Candidate::EncodeLengths(1, 1, 1, 1));  // 1 byte for "!"
693 
694     EXPECT_TRUE(rewriter->Rewrite(request, &segments));
695     ASSERT_EQ(1, segments.segments_size());
696     ASSERT_EQ(1, segments.segment(0).candidates_size());
697 
698     const Segment::Candidate &rewritten_candidate =
699         segments.segment(0).candidate(0);
700     EXPECT_EQ("マジ!",  // "マジ!" (full-width)
701               rewritten_candidate.value);
702     EXPECT_EQ("マジ!",  // "マジ!" (full-width)
703               rewritten_candidate.content_value);
704     ASSERT_EQ(2, rewritten_candidate.inner_segment_boundary.size());
705 
706     // Boundary information for
707     // key="まじ", value="マジ", ckey="まじ", cvalue="マジ"
708     EXPECT_EQ(Segment::Candidate::EncodeLengths(6, 6, 6, 6),
709               rewritten_candidate.inner_segment_boundary[0]);
710     // Boundary information for
711     // key="!", value="!", ckey="!", cvalue="!".
712     // Values are converted to full-width.
713     EXPECT_EQ(Segment::Candidate::EncodeLengths(1, 3, 1, 3),
714               rewritten_candidate.inner_segment_boundary[1]);
715   }
716 }
717 
TEST_F(VariantsRewriterTest,Capability)718 TEST_F(VariantsRewriterTest, Capability) {
719   std::unique_ptr<VariantsRewriter> rewriter(CreateVariantsRewriter());
720   const ConversionRequest request;
721   EXPECT_EQ(RewriterInterface::ALL, rewriter->capability(request));
722 }
723 
724 }  // namespace mozc
725