182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir/* 2ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * Copyright 2018 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 */ 16ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikaspackage androidx.emoji.text; 1782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 18ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport static androidx.emoji.util.EmojiMatcher.hasEmojiAt; 19ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport static androidx.emoji.util.EmojiMatcher.hasEmojiCount; 2082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 2182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport static org.junit.Assert.assertThat; 22fa39e2bca1b284ad7c931d9194287770b7b507faAurimas Liutikasimport static org.junit.Assert.assertTrue; 2382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 2482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport android.content.Context; 25478b4ffdd939482869779da95c45b259771a620bSiyamed Sinirimport android.graphics.Paint; 2682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport android.support.test.InstrumentationRegistry; 279546df94e6393de504f7ef8dc1b12a1f550c47a8Siyamed Sinirimport android.support.test.filters.SdkSuppress; 2882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport android.support.test.filters.SmallTest; 29478b4ffdd939482869779da95c45b259771a620bSiyamed Sinirimport android.text.Spanned; 3082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 3138746a682208c764867ffe4415d0b62fb22b5b9aAurimas Liutikasimport androidx.core.graphics.PaintCompat; 3238746a682208c764867ffe4415d0b62fb22b5b9aAurimas Liutikasimport androidx.emoji.util.TestString; 3338746a682208c764867ffe4415d0b62fb22b5b9aAurimas Liutikas 3482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport org.junit.BeforeClass; 3582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport org.junit.Test; 3682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport org.junit.runner.RunWith; 3782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport org.junit.runners.Parameterized; 3882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 3982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport java.io.BufferedReader; 4082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport java.io.IOException; 4182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport java.io.InputStream; 4282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport java.io.InputStreamReader; 4382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport java.util.ArrayList; 4482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport java.util.Collection; 4582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 4682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir/** 4782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * Reads raw/allemojis.txt which includes all the emojis known to human kind and tests that 4882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * EmojiCompat creates EmojiSpans for each one of them. 4982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir */ 5082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir@SmallTest 5182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir@RunWith(Parameterized.class) 529546df94e6393de504f7ef8dc1b12a1f550c47a8Siyamed Sinir@SdkSuppress(minSdkVersion = 19) 5382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirpublic class AllEmojisTest { 5482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 5582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir /** 5682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * String representation for a single emoji 5782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir */ 5882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir private String mString; 5982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 6082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir /** 6182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * Codepoints of emoji for better assert error message. 6282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir */ 6382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir private String mCodepoints; 6482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 65478b4ffdd939482869779da95c45b259771a620bSiyamed Sinir /** 66478b4ffdd939482869779da95c45b259771a620bSiyamed Sinir * Paint object used to check if Typeface can render the given emoji. 67478b4ffdd939482869779da95c45b259771a620bSiyamed Sinir */ 68478b4ffdd939482869779da95c45b259771a620bSiyamed Sinir private Paint mPaint; 69478b4ffdd939482869779da95c45b259771a620bSiyamed Sinir 7082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir @BeforeClass 7182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir public static void setup() { 7282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir EmojiCompat.reset(TestConfigBuilder.config()); 7382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 7482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 7582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir @Parameterized.Parameters 76b7b27782ff7589608ed7de38634adc846665cecbSiyamed Sinir public static Collection<Object[]> data() throws IOException { 7782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir final Context context = InstrumentationRegistry.getTargetContext(); 78176b7a517ad28a8cffc8cc3307b6ce2c42a36cc9Siyamed Sinir final InputStream inputStream = context.getAssets().open("emojis.txt"); 7982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir try { 80b7b27782ff7589608ed7de38634adc846665cecbSiyamed Sinir final BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); 81b7b27782ff7589608ed7de38634adc846665cecbSiyamed Sinir final Collection<Object[]> data = new ArrayList<>(); 82b7b27782ff7589608ed7de38634adc846665cecbSiyamed Sinir final StringBuilder stringBuilder = new StringBuilder(); 83b7b27782ff7589608ed7de38634adc846665cecbSiyamed Sinir final StringBuilder codePointsBuilder = new StringBuilder(); 84b7b27782ff7589608ed7de38634adc846665cecbSiyamed Sinir 8582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir String s; 8682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir while ((s = reader.readLine()) != null) { 87b7b27782ff7589608ed7de38634adc846665cecbSiyamed Sinir s = s.trim(); 88b7b27782ff7589608ed7de38634adc846665cecbSiyamed Sinir // pass comments 89b7b27782ff7589608ed7de38634adc846665cecbSiyamed Sinir if (s.isEmpty() || s.startsWith("#")) continue; 90b7b27782ff7589608ed7de38634adc846665cecbSiyamed Sinir 9182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir stringBuilder.setLength(0); 9282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir codePointsBuilder.setLength(0); 9382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 9482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir // emoji codepoints are space separated: i.e. 0x1f1e6 0x1f1e8 9582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir final String[] split = s.split(" "); 9682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 9782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir for (int index = 0; index < split.length; index++) { 98b7b27782ff7589608ed7de38634adc846665cecbSiyamed Sinir final String part = split[index].trim(); 99b7b27782ff7589608ed7de38634adc846665cecbSiyamed Sinir codePointsBuilder.append(part); 10082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir codePointsBuilder.append(","); 101b7b27782ff7589608ed7de38634adc846665cecbSiyamed Sinir stringBuilder.append(Character.toChars(Integer.parseInt(part, 16))); 10282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 10382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir data.add(new Object[]{stringBuilder.toString(), codePointsBuilder.toString()}); 10482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 105b7b27782ff7589608ed7de38634adc846665cecbSiyamed Sinir 106b7b27782ff7589608ed7de38634adc846665cecbSiyamed Sinir return data; 107b7b27782ff7589608ed7de38634adc846665cecbSiyamed Sinir } finally { 108b7b27782ff7589608ed7de38634adc846665cecbSiyamed Sinir inputStream.close(); 10982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 11082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 11182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 11282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 11382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir public AllEmojisTest(String string, String codepoints) { 11482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir mString = string; 11582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir mCodepoints = codepoints; 116478b4ffdd939482869779da95c45b259771a620bSiyamed Sinir mPaint = new Paint(); 11782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 11882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 11982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir @Test 12082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir public void testEmoji() { 12182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir assertTrue("EmojiCompat should have emoji: " + mCodepoints, 12282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir EmojiCompat.get().hasEmojiGlyph(mString)); 12382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir assertEmojiCompatAddsEmoji(mString); 124478b4ffdd939482869779da95c45b259771a620bSiyamed Sinir assertSpanCanRenderEmoji(mString); 125478b4ffdd939482869779da95c45b259771a620bSiyamed Sinir } 126478b4ffdd939482869779da95c45b259771a620bSiyamed Sinir 127478b4ffdd939482869779da95c45b259771a620bSiyamed Sinir private void assertSpanCanRenderEmoji(final String str) { 128478b4ffdd939482869779da95c45b259771a620bSiyamed Sinir final Spanned spanned = (Spanned) EmojiCompat.get().process(new TestString(str).toString()); 129478b4ffdd939482869779da95c45b259771a620bSiyamed Sinir final EmojiSpan[] spans = spanned.getSpans(0, spanned.length(), EmojiSpan.class); 130478b4ffdd939482869779da95c45b259771a620bSiyamed Sinir final EmojiMetadata metadata = spans[0].getMetadata(); 131478b4ffdd939482869779da95c45b259771a620bSiyamed Sinir mPaint.setTypeface(metadata.getTypeface()); 132478b4ffdd939482869779da95c45b259771a620bSiyamed Sinir 133478b4ffdd939482869779da95c45b259771a620bSiyamed Sinir final String codepoint = String.valueOf(Character.toChars(metadata.getId())); 134478b4ffdd939482869779da95c45b259771a620bSiyamed Sinir assertTrue(metadata.toString() + " should be rendered", 135478b4ffdd939482869779da95c45b259771a620bSiyamed Sinir PaintCompat.hasGlyph(mPaint, codepoint)); 13682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 13782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 13882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir private void assertEmojiCompatAddsEmoji(final String str) { 13982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir TestString string = new TestString(str); 14082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir CharSequence sequence = EmojiCompat.get().process(string.toString()); 14182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir assertThat(sequence, hasEmojiCount(1)); 14282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir assertThat(sequence, hasEmojiAt(string.emojiStartIndex(), string.emojiEndIndex())); 14382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 14482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir // case where Emoji is in the middle of string 14582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir string = new TestString(str).withPrefix().withSuffix(); 14682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir sequence = EmojiCompat.get().process(string.toString()); 14782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir assertThat(sequence, hasEmojiCount(1)); 14882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir assertThat(sequence, hasEmojiAt(string.emojiStartIndex(), string.emojiEndIndex())); 14982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 15082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir // case where Emoji is at the end of string 15182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir string = new TestString(str).withSuffix(); 15282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir sequence = EmojiCompat.get().process(string.toString()); 15382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir assertThat(sequence, hasEmojiCount(1)); 15482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir assertThat(sequence, hasEmojiAt(string.emojiStartIndex(), string.emojiEndIndex())); 15582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 15682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 15782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir} 158