1ce6bcdd1a547c9874f05a08074cafdfea16196d6Tadashi G. Takaoka/*
2ce6bcdd1a547c9874f05a08074cafdfea16196d6Tadashi G. Takaoka * Copyright (C) 2013 The Android Open Source Project
3ce6bcdd1a547c9874f05a08074cafdfea16196d6Tadashi G. Takaoka *
4ce6bcdd1a547c9874f05a08074cafdfea16196d6Tadashi G. Takaoka * Licensed under the Apache License, Version 2.0 (the "License");
5ce6bcdd1a547c9874f05a08074cafdfea16196d6Tadashi G. Takaoka * you may not use this file except in compliance with the License.
6ce6bcdd1a547c9874f05a08074cafdfea16196d6Tadashi G. Takaoka * You may obtain a copy of the License at
7ce6bcdd1a547c9874f05a08074cafdfea16196d6Tadashi G. Takaoka *
8ce6bcdd1a547c9874f05a08074cafdfea16196d6Tadashi G. Takaoka *      http://www.apache.org/licenses/LICENSE-2.0
9ce6bcdd1a547c9874f05a08074cafdfea16196d6Tadashi G. Takaoka *
10ce6bcdd1a547c9874f05a08074cafdfea16196d6Tadashi G. Takaoka * Unless required by applicable law or agreed to in writing, software
11ce6bcdd1a547c9874f05a08074cafdfea16196d6Tadashi G. Takaoka * distributed under the License is distributed on an "AS IS" BASIS,
12ce6bcdd1a547c9874f05a08074cafdfea16196d6Tadashi G. Takaoka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ce6bcdd1a547c9874f05a08074cafdfea16196d6Tadashi G. Takaoka * See the License for the specific language governing permissions and
14ce6bcdd1a547c9874f05a08074cafdfea16196d6Tadashi G. Takaoka * limitations under the License.
15ce6bcdd1a547c9874f05a08074cafdfea16196d6Tadashi G. Takaoka */
16ce6bcdd1a547c9874f05a08074cafdfea16196d6Tadashi G. Takaoka
17e28eba5074664d5716b8e58b8d0a235746b261ebKen Wakasapackage com.android.inputmethod.latin.utils;
18ce6bcdd1a547c9874f05a08074cafdfea16196d6Tadashi G. Takaoka
190a75cf51afbdc79ccb2c6eabaf06a0aa26263af5Tadashi G. Takaokaimport android.content.res.Resources;
20ce6bcdd1a547c9874f05a08074cafdfea16196d6Tadashi G. Takaokaimport android.test.AndroidTestCase;
21ce6bcdd1a547c9874f05a08074cafdfea16196d6Tadashi G. Takaokaimport android.test.suitebuilder.annotation.SmallTest;
22ce6bcdd1a547c9874f05a08074cafdfea16196d6Tadashi G. Takaokaimport android.text.TextUtils;
23ce6bcdd1a547c9874f05a08074cafdfea16196d6Tadashi G. Takaoka
245b91b551e5ffaf2c2e691dfbd434f21c82293986Jean Chalardimport com.android.inputmethod.latin.common.LocaleUtils;
250a75cf51afbdc79ccb2c6eabaf06a0aa26263af5Tadashi G. Takaokaimport com.android.inputmethod.latin.settings.SpacingAndPunctuations;
260a75cf51afbdc79ccb2c6eabaf06a0aa26263af5Tadashi G. Takaoka
27ce6bcdd1a547c9874f05a08074cafdfea16196d6Tadashi G. Takaokaimport java.util.Locale;
28ce6bcdd1a547c9874f05a08074cafdfea16196d6Tadashi G. Takaoka
29ce6bcdd1a547c9874f05a08074cafdfea16196d6Tadashi G. Takaoka@SmallTest
30ce6bcdd1a547c9874f05a08074cafdfea16196d6Tadashi G. Takaokapublic class CapsModeUtilsTests extends AndroidTestCase {
31ce6bcdd1a547c9874f05a08074cafdfea16196d6Tadashi G. Takaoka    private static void onePathForCaps(final CharSequence cs, final int expectedResult,
320a75cf51afbdc79ccb2c6eabaf06a0aa26263af5Tadashi G. Takaoka            final int mask, final SpacingAndPunctuations sp, final boolean hasSpaceBefore) {
330a75cf51afbdc79ccb2c6eabaf06a0aa26263af5Tadashi G. Takaoka        final int oneTimeResult = expectedResult & mask;
34ce6bcdd1a547c9874f05a08074cafdfea16196d6Tadashi G. Takaoka        assertEquals("After >" + cs + "<", oneTimeResult,
350a75cf51afbdc79ccb2c6eabaf06a0aa26263af5Tadashi G. Takaoka                CapsModeUtils.getCapsMode(cs, mask, sp, hasSpaceBefore));
36ce6bcdd1a547c9874f05a08074cafdfea16196d6Tadashi G. Takaoka    }
37ce6bcdd1a547c9874f05a08074cafdfea16196d6Tadashi G. Takaoka
38ce6bcdd1a547c9874f05a08074cafdfea16196d6Tadashi G. Takaoka    private static void allPathsForCaps(final CharSequence cs, final int expectedResult,
390a75cf51afbdc79ccb2c6eabaf06a0aa26263af5Tadashi G. Takaoka            final SpacingAndPunctuations sp, final boolean hasSpaceBefore) {
40ce6bcdd1a547c9874f05a08074cafdfea16196d6Tadashi G. Takaoka        final int c = TextUtils.CAP_MODE_CHARACTERS;
41ce6bcdd1a547c9874f05a08074cafdfea16196d6Tadashi G. Takaoka        final int w = TextUtils.CAP_MODE_WORDS;
42ce6bcdd1a547c9874f05a08074cafdfea16196d6Tadashi G. Takaoka        final int s = TextUtils.CAP_MODE_SENTENCES;
430a75cf51afbdc79ccb2c6eabaf06a0aa26263af5Tadashi G. Takaoka        onePathForCaps(cs, expectedResult, c | w | s, sp, hasSpaceBefore);
440a75cf51afbdc79ccb2c6eabaf06a0aa26263af5Tadashi G. Takaoka        onePathForCaps(cs, expectedResult, w | s, sp, hasSpaceBefore);
450a75cf51afbdc79ccb2c6eabaf06a0aa26263af5Tadashi G. Takaoka        onePathForCaps(cs, expectedResult, c | s, sp, hasSpaceBefore);
460a75cf51afbdc79ccb2c6eabaf06a0aa26263af5Tadashi G. Takaoka        onePathForCaps(cs, expectedResult, c | w, sp, hasSpaceBefore);
470a75cf51afbdc79ccb2c6eabaf06a0aa26263af5Tadashi G. Takaoka        onePathForCaps(cs, expectedResult, c, sp, hasSpaceBefore);
480a75cf51afbdc79ccb2c6eabaf06a0aa26263af5Tadashi G. Takaoka        onePathForCaps(cs, expectedResult, w, sp, hasSpaceBefore);
490a75cf51afbdc79ccb2c6eabaf06a0aa26263af5Tadashi G. Takaoka        onePathForCaps(cs, expectedResult, s, sp, hasSpaceBefore);
50ce6bcdd1a547c9874f05a08074cafdfea16196d6Tadashi G. Takaoka    }
51ce6bcdd1a547c9874f05a08074cafdfea16196d6Tadashi G. Takaoka
52ce6bcdd1a547c9874f05a08074cafdfea16196d6Tadashi G. Takaoka    public void testGetCapsMode() {
53ce6bcdd1a547c9874f05a08074cafdfea16196d6Tadashi G. Takaoka        final int c = TextUtils.CAP_MODE_CHARACTERS;
54ce6bcdd1a547c9874f05a08074cafdfea16196d6Tadashi G. Takaoka        final int w = TextUtils.CAP_MODE_WORDS;
55ce6bcdd1a547c9874f05a08074cafdfea16196d6Tadashi G. Takaoka        final int s = TextUtils.CAP_MODE_SENTENCES;
560a75cf51afbdc79ccb2c6eabaf06a0aa26263af5Tadashi G. Takaoka        final RunInLocale<SpacingAndPunctuations> job = new RunInLocale<SpacingAndPunctuations>() {
570a75cf51afbdc79ccb2c6eabaf06a0aa26263af5Tadashi G. Takaoka            @Override
580a75cf51afbdc79ccb2c6eabaf06a0aa26263af5Tadashi G. Takaoka            protected SpacingAndPunctuations job(final Resources res) {
590a75cf51afbdc79ccb2c6eabaf06a0aa26263af5Tadashi G. Takaoka                return new SpacingAndPunctuations(res);
600a75cf51afbdc79ccb2c6eabaf06a0aa26263af5Tadashi G. Takaoka            }
610a75cf51afbdc79ccb2c6eabaf06a0aa26263af5Tadashi G. Takaoka        };
620a75cf51afbdc79ccb2c6eabaf06a0aa26263af5Tadashi G. Takaoka        final Resources res = getContext().getResources();
630a75cf51afbdc79ccb2c6eabaf06a0aa26263af5Tadashi G. Takaoka        SpacingAndPunctuations sp = job.runInLocale(res, Locale.ENGLISH);
640a75cf51afbdc79ccb2c6eabaf06a0aa26263af5Tadashi G. Takaoka        allPathsForCaps("", c | w | s, sp, false);
650a75cf51afbdc79ccb2c6eabaf06a0aa26263af5Tadashi G. Takaoka        allPathsForCaps("Word", c, sp, false);
660a75cf51afbdc79ccb2c6eabaf06a0aa26263af5Tadashi G. Takaoka        allPathsForCaps("Word.", c, sp, false);
670a75cf51afbdc79ccb2c6eabaf06a0aa26263af5Tadashi G. Takaoka        allPathsForCaps("Word ", c | w, sp, false);
680a75cf51afbdc79ccb2c6eabaf06a0aa26263af5Tadashi G. Takaoka        allPathsForCaps("Word. ", c | w | s, sp, false);
690a75cf51afbdc79ccb2c6eabaf06a0aa26263af5Tadashi G. Takaoka        allPathsForCaps("Word..", c, sp, false);
700a75cf51afbdc79ccb2c6eabaf06a0aa26263af5Tadashi G. Takaoka        allPathsForCaps("Word.. ", c | w | s, sp, false);
710a75cf51afbdc79ccb2c6eabaf06a0aa26263af5Tadashi G. Takaoka        allPathsForCaps("Word... ", c | w | s, sp, false);
720a75cf51afbdc79ccb2c6eabaf06a0aa26263af5Tadashi G. Takaoka        allPathsForCaps("Word ... ", c | w | s, sp, false);
730a75cf51afbdc79ccb2c6eabaf06a0aa26263af5Tadashi G. Takaoka        allPathsForCaps("Word . ", c | w, sp, false);
740a75cf51afbdc79ccb2c6eabaf06a0aa26263af5Tadashi G. Takaoka        allPathsForCaps("In the U.S ", c | w, sp, false);
750a75cf51afbdc79ccb2c6eabaf06a0aa26263af5Tadashi G. Takaoka        allPathsForCaps("In the U.S. ", c | w, sp, false);
760a75cf51afbdc79ccb2c6eabaf06a0aa26263af5Tadashi G. Takaoka        allPathsForCaps("Some stuff (e.g. ", c | w, sp, false);
770a75cf51afbdc79ccb2c6eabaf06a0aa26263af5Tadashi G. Takaoka        allPathsForCaps("In the U.S.. ", c | w | s, sp, false);
780a75cf51afbdc79ccb2c6eabaf06a0aa26263af5Tadashi G. Takaoka        allPathsForCaps("\"Word.\" ", c | w | s, sp, false);
790a75cf51afbdc79ccb2c6eabaf06a0aa26263af5Tadashi G. Takaoka        allPathsForCaps("\"Word\". ", c | w | s, sp, false);
800a75cf51afbdc79ccb2c6eabaf06a0aa26263af5Tadashi G. Takaoka        allPathsForCaps("\"Word\" ", c | w, sp, false);
81ce6bcdd1a547c9874f05a08074cafdfea16196d6Tadashi G. Takaoka
82ce6bcdd1a547c9874f05a08074cafdfea16196d6Tadashi G. Takaoka        // Test for phantom space
830a75cf51afbdc79ccb2c6eabaf06a0aa26263af5Tadashi G. Takaoka        allPathsForCaps("Word", c | w, sp, true);
840a75cf51afbdc79ccb2c6eabaf06a0aa26263af5Tadashi G. Takaoka        allPathsForCaps("Word.", c | w | s, sp, true);
85ce6bcdd1a547c9874f05a08074cafdfea16196d6Tadashi G. Takaoka
86ce6bcdd1a547c9874f05a08074cafdfea16196d6Tadashi G. Takaoka        // Tests after some whitespace
870a75cf51afbdc79ccb2c6eabaf06a0aa26263af5Tadashi G. Takaoka        allPathsForCaps("Word\n", c | w | s, sp, false);
880a75cf51afbdc79ccb2c6eabaf06a0aa26263af5Tadashi G. Takaoka        allPathsForCaps("Word\n", c | w | s, sp, true);
890a75cf51afbdc79ccb2c6eabaf06a0aa26263af5Tadashi G. Takaoka        allPathsForCaps("Word\n ", c | w | s, sp, true);
900a75cf51afbdc79ccb2c6eabaf06a0aa26263af5Tadashi G. Takaoka        allPathsForCaps("Word.\n", c | w | s, sp, false);
910a75cf51afbdc79ccb2c6eabaf06a0aa26263af5Tadashi G. Takaoka        allPathsForCaps("Word.\n", c | w | s, sp, true);
920a75cf51afbdc79ccb2c6eabaf06a0aa26263af5Tadashi G. Takaoka        allPathsForCaps("Word.\n ", c | w | s, sp, true);
93ce6bcdd1a547c9874f05a08074cafdfea16196d6Tadashi G. Takaoka
940a75cf51afbdc79ccb2c6eabaf06a0aa26263af5Tadashi G. Takaoka        sp = job.runInLocale(res, Locale.FRENCH);
950a75cf51afbdc79ccb2c6eabaf06a0aa26263af5Tadashi G. Takaoka        allPathsForCaps("\"Word.\" ", c | w, sp, false);
960a75cf51afbdc79ccb2c6eabaf06a0aa26263af5Tadashi G. Takaoka        allPathsForCaps("\"Word\". ", c | w | s, sp, false);
970a75cf51afbdc79ccb2c6eabaf06a0aa26263af5Tadashi G. Takaoka        allPathsForCaps("\"Word\" ", c | w, sp, false);
9860afa7000f14f8f8ca890236f636d45a2b59b61eJean Chalard
9960afa7000f14f8f8ca890236f636d45a2b59b61eJean Chalard        // Test special case for German. German does not capitalize at the start of a
10060afa7000f14f8f8ca890236f636d45a2b59b61eJean Chalard        // line when the previous line starts with a comma. It does in other cases.
10160afa7000f14f8f8ca890236f636d45a2b59b61eJean Chalard        sp = job.runInLocale(res, Locale.GERMAN);
10260afa7000f14f8f8ca890236f636d45a2b59b61eJean Chalard        allPathsForCaps("Liebe Sara,\n", c | w, sp, false);
10360afa7000f14f8f8ca890236f636d45a2b59b61eJean Chalard        allPathsForCaps("Liebe Sara,\n", c | w, sp, true);
10460afa7000f14f8f8ca890236f636d45a2b59b61eJean Chalard        allPathsForCaps("Liebe Sara,  \n  ", c | w, sp, false);
10560afa7000f14f8f8ca890236f636d45a2b59b61eJean Chalard        allPathsForCaps("Liebe Sara  \n  ", c | w | s, sp, false);
10660afa7000f14f8f8ca890236f636d45a2b59b61eJean Chalard        allPathsForCaps("Liebe Sara.\n  ", c | w | s, sp, false);
10760afa7000f14f8f8ca890236f636d45a2b59b61eJean Chalard        sp = job.runInLocale(res, Locale.ENGLISH);
10860afa7000f14f8f8ca890236f636d45a2b59b61eJean Chalard        allPathsForCaps("Liebe Sara,\n", c | w | s, sp, false);
10960afa7000f14f8f8ca890236f636d45a2b59b61eJean Chalard        allPathsForCaps("Liebe Sara,\n", c | w | s, sp, true);
11060afa7000f14f8f8ca890236f636d45a2b59b61eJean Chalard        allPathsForCaps("Liebe Sara,  \n  ", c | w | s, sp, false);
11160afa7000f14f8f8ca890236f636d45a2b59b61eJean Chalard        allPathsForCaps("Liebe Sara  \n  ", c | w | s, sp, false);
11260afa7000f14f8f8ca890236f636d45a2b59b61eJean Chalard        allPathsForCaps("Liebe Sara.\n  ", c | w | s, sp, false);
113bfea7dec1a4260104b6d4b316f2163368478869cJean Chalard
114bfea7dec1a4260104b6d4b316f2163368478869cJean Chalard        // Test armenian period
115bfea7dec1a4260104b6d4b316f2163368478869cJean Chalard        sp = job.runInLocale(res, LocaleUtils.constructLocaleFromString("hy_AM"));
116bfea7dec1a4260104b6d4b316f2163368478869cJean Chalard        assertTrue("Period is not sentence separator in Armenian",
117bfea7dec1a4260104b6d4b316f2163368478869cJean Chalard                !sp.isSentenceSeparator('.'));
118bfea7dec1a4260104b6d4b316f2163368478869cJean Chalard        assertTrue("Sentence separator is Armenian period in Armenian",
119bfea7dec1a4260104b6d4b316f2163368478869cJean Chalard                sp.isSentenceSeparator(0x589));
120bfea7dec1a4260104b6d4b316f2163368478869cJean Chalard        // No space : capitalize only if MODE_CHARACTERS
121bfea7dec1a4260104b6d4b316f2163368478869cJean Chalard        allPathsForCaps("Word", c, sp, false);
122bfea7dec1a4260104b6d4b316f2163368478869cJean Chalard        allPathsForCaps("Word.", c, sp, false);
123bfea7dec1a4260104b6d4b316f2163368478869cJean Chalard        // Space, but no armenian period : capitalize if MODE_WORDS but not SENTENCES
124bfea7dec1a4260104b6d4b316f2163368478869cJean Chalard        allPathsForCaps("Word. ", c | w, sp, false);
125bfea7dec1a4260104b6d4b316f2163368478869cJean Chalard        // Armenian period : capitalize if MODE_SENTENCES
126bfea7dec1a4260104b6d4b316f2163368478869cJean Chalard        allPathsForCaps("Word\u0589 ", c | w | s, sp, false);
12717901db6910317a4266b06035455b92f3a85a2e9Jean Chalard
12817901db6910317a4266b06035455b92f3a85a2e9Jean Chalard        // Test for sentence terminators
12917901db6910317a4266b06035455b92f3a85a2e9Jean Chalard        sp = job.runInLocale(res, Locale.ENGLISH);
13017901db6910317a4266b06035455b92f3a85a2e9Jean Chalard        allPathsForCaps("Word? ", c | w | s, sp, false);
13117901db6910317a4266b06035455b92f3a85a2e9Jean Chalard        allPathsForCaps("Word?", c | w | s, sp, true);
13217901db6910317a4266b06035455b92f3a85a2e9Jean Chalard        allPathsForCaps("Word?", c, sp, false);
13317901db6910317a4266b06035455b92f3a85a2e9Jean Chalard        allPathsForCaps("Word! ", c | w | s, sp, false);
13417901db6910317a4266b06035455b92f3a85a2e9Jean Chalard        allPathsForCaps("Word!", c | w | s, sp, true);
13517901db6910317a4266b06035455b92f3a85a2e9Jean Chalard        allPathsForCaps("Word!", c, sp, false);
13617901db6910317a4266b06035455b92f3a85a2e9Jean Chalard        allPathsForCaps("Word; ", c | w, sp, false);
13717901db6910317a4266b06035455b92f3a85a2e9Jean Chalard        allPathsForCaps("Word;", c | w, sp, true);
13817901db6910317a4266b06035455b92f3a85a2e9Jean Chalard        allPathsForCaps("Word;", c, sp, false);
139b526a894db0f475596abbed56c4b311b5e4904dcJean Chalard        // Test for sentence terminators in Greek
140b526a894db0f475596abbed56c4b311b5e4904dcJean Chalard        sp = job.runInLocale(res, LocaleUtils.constructLocaleFromString("el"));
141b526a894db0f475596abbed56c4b311b5e4904dcJean Chalard        allPathsForCaps("Word? ", c | w | s, sp, false);
142b526a894db0f475596abbed56c4b311b5e4904dcJean Chalard        allPathsForCaps("Word?", c | w | s, sp, true);
143b526a894db0f475596abbed56c4b311b5e4904dcJean Chalard        allPathsForCaps("Word?", c, sp, false);
144b526a894db0f475596abbed56c4b311b5e4904dcJean Chalard        allPathsForCaps("Word! ", c | w | s, sp, false);
145b526a894db0f475596abbed56c4b311b5e4904dcJean Chalard        allPathsForCaps("Word!", c | w | s, sp, true);
146b526a894db0f475596abbed56c4b311b5e4904dcJean Chalard        allPathsForCaps("Word!", c, sp, false);
147b526a894db0f475596abbed56c4b311b5e4904dcJean Chalard        // In Greek ";" is the question mark and it terminates the sentence
148b526a894db0f475596abbed56c4b311b5e4904dcJean Chalard        allPathsForCaps("Word; ", c | w | s, sp, false);
149b526a894db0f475596abbed56c4b311b5e4904dcJean Chalard        allPathsForCaps("Word;", c | w | s, sp, true);
150b526a894db0f475596abbed56c4b311b5e4904dcJean Chalard        allPathsForCaps("Word;", c, sp, false);
151ce6bcdd1a547c9874f05a08074cafdfea16196d6Tadashi G. Takaoka    }
152ce6bcdd1a547c9874f05a08074cafdfea16196d6Tadashi G. Takaoka}
153