182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir/*
282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * Copyright (C) 2017 The Android Open Source Project
382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir *
482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * Licensed under the Apache License, Version 2.0 (the "License");
582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * you may not use this file except in compliance with the License.
682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * You may obtain a copy of the License at
782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir *
882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir *      http://www.apache.org/licenses/LICENSE-2.0
982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir *
1082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * Unless required by applicable law or agreed to in writing, software
1182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * distributed under the License is distributed on an "AS IS" BASIS,
1282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * See the License for the specific language governing permissions and
1482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * limitations under the License.
1582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir */
1682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirpackage android.support.text.emoji;
1782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir
1882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport static android.support.text.emoji.util.EmojiMatcher.hasEmojiAt;
1982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport static android.support.text.emoji.util.EmojiMatcher.hasEmojiCount;
2082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir
2182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport static junit.framework.TestCase.assertTrue;
2282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir
2382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport static org.junit.Assert.assertThat;
2482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir
259546df94e6393de504f7ef8dc1b12a1f550c47a8Siyamed Sinirimport android.annotation.TargetApi;
2682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport android.content.Context;
2782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport android.support.test.InstrumentationRegistry;
289546df94e6393de504f7ef8dc1b12a1f550c47a8Siyamed Sinirimport android.support.test.filters.SdkSuppress;
2982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport android.support.test.filters.SmallTest;
3082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport android.support.text.emoji.util.TestString;
3182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir
3282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport org.junit.BeforeClass;
3382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport org.junit.Test;
3482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport org.junit.runner.RunWith;
3582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport org.junit.runners.Parameterized;
3682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir
3782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport java.io.BufferedReader;
3882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport java.io.IOException;
3982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport java.io.InputStream;
4082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport java.io.InputStreamReader;
4182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport java.util.ArrayList;
4282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport java.util.Collection;
4382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir
4482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir/**
4582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * Reads raw/allemojis.txt which includes all the emojis known to human kind and tests that
4682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * EmojiCompat creates EmojiSpans for each one of them.
4782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir */
4882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir@SmallTest
4982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir@RunWith(Parameterized.class)
509546df94e6393de504f7ef8dc1b12a1f550c47a8Siyamed Sinir@SdkSuppress(minSdkVersion = 19)
519546df94e6393de504f7ef8dc1b12a1f550c47a8Siyamed Sinir@TargetApi(19)
5282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirpublic class AllEmojisTest {
5382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir
5482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    /**
5582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir     * String representation for a single emoji
5682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir     */
5782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    private String mString;
5882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir
5982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    /**
6082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir     * Codepoints of emoji for better assert error message.
6182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir     */
6282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    private String mCodepoints;
6382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir
6482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    @BeforeClass
6582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    public static void setup() {
6682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        EmojiCompat.reset(TestConfigBuilder.config());
6782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    }
6882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir
6982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    @Parameterized.Parameters
70b7b27782ff7589608ed7de38634adc846665cecbSiyamed Sinir    public static Collection<Object[]> data() throws IOException {
7182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        final Context context = InstrumentationRegistry.getTargetContext();
72176b7a517ad28a8cffc8cc3307b6ce2c42a36cc9Siyamed Sinir        final InputStream inputStream = context.getAssets().open("emojis.txt");
7382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        try {
74b7b27782ff7589608ed7de38634adc846665cecbSiyamed Sinir            final BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
75b7b27782ff7589608ed7de38634adc846665cecbSiyamed Sinir            final Collection<Object[]> data = new ArrayList<>();
76b7b27782ff7589608ed7de38634adc846665cecbSiyamed Sinir            final StringBuilder stringBuilder = new StringBuilder();
77b7b27782ff7589608ed7de38634adc846665cecbSiyamed Sinir            final StringBuilder codePointsBuilder = new StringBuilder();
78b7b27782ff7589608ed7de38634adc846665cecbSiyamed Sinir
7982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir            String s;
8082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir            while ((s = reader.readLine()) != null) {
81b7b27782ff7589608ed7de38634adc846665cecbSiyamed Sinir                s = s.trim();
82b7b27782ff7589608ed7de38634adc846665cecbSiyamed Sinir                // pass comments
83b7b27782ff7589608ed7de38634adc846665cecbSiyamed Sinir                if (s.isEmpty() || s.startsWith("#")) continue;
84b7b27782ff7589608ed7de38634adc846665cecbSiyamed Sinir
8582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir                stringBuilder.setLength(0);
8682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir                codePointsBuilder.setLength(0);
8782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir
8882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir                // emoji codepoints are space separated: i.e. 0x1f1e6 0x1f1e8
8982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir                final String[] split = s.split(" ");
9082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir
9182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir                for (int index = 0; index < split.length; index++) {
92b7b27782ff7589608ed7de38634adc846665cecbSiyamed Sinir                    final String part = split[index].trim();
93b7b27782ff7589608ed7de38634adc846665cecbSiyamed Sinir                    codePointsBuilder.append(part);
9482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir                    codePointsBuilder.append(",");
95b7b27782ff7589608ed7de38634adc846665cecbSiyamed Sinir                    stringBuilder.append(Character.toChars(Integer.parseInt(part, 16)));
9682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir                }
9782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir                data.add(new Object[]{stringBuilder.toString(), codePointsBuilder.toString()});
9882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir            }
99b7b27782ff7589608ed7de38634adc846665cecbSiyamed Sinir
100b7b27782ff7589608ed7de38634adc846665cecbSiyamed Sinir            return data;
101b7b27782ff7589608ed7de38634adc846665cecbSiyamed Sinir        } finally {
102b7b27782ff7589608ed7de38634adc846665cecbSiyamed Sinir            inputStream.close();
10382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        }
10482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir
10582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    }
10682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir
10782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    public AllEmojisTest(String string, String codepoints) {
10882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        mString = string;
10982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        mCodepoints = codepoints;
11082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    }
11182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir
11282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    @Test
11382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    public void testEmoji() {
11482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        assertTrue("EmojiCompat should have emoji: " + mCodepoints,
11582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir                EmojiCompat.get().hasEmojiGlyph(mString));
11682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        assertEmojiCompatAddsEmoji(mString);
11782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    }
11882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir
11982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    private void assertEmojiCompatAddsEmoji(final String str) {
12082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        TestString string = new TestString(str);
12182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        CharSequence sequence = EmojiCompat.get().process(string.toString());
12282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        assertThat(sequence, hasEmojiCount(1));
12382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        assertThat(sequence, hasEmojiAt(string.emojiStartIndex(), string.emojiEndIndex()));
12482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir
12582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        // case where Emoji is in the middle of string
12682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        string = new TestString(str).withPrefix().withSuffix();
12782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        sequence = EmojiCompat.get().process(string.toString());
12882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        assertThat(sequence, hasEmojiCount(1));
12982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        assertThat(sequence, hasEmojiAt(string.emojiStartIndex(), string.emojiEndIndex()));
13082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir
13182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        // case where Emoji is at the end of string
13282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        string = new TestString(str).withSuffix();
13382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        sequence = EmojiCompat.get().process(string.toString());
13482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        assertThat(sequence, hasEmojiCount(1));
13582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        assertThat(sequence, hasEmojiAt(string.emojiStartIndex(), string.emojiEndIndex()));
13682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    }
13782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir
13882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir}
139