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