1/* 2 * Copyright 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16package androidx.emoji.text; 17 18import static androidx.emoji.util.EmojiMatcher.hasEmojiAt; 19import static androidx.emoji.util.EmojiMatcher.hasEmojiCount; 20 21import static org.junit.Assert.assertThat; 22import static org.junit.Assert.assertTrue; 23 24import android.content.Context; 25import android.graphics.Paint; 26import android.support.test.InstrumentationRegistry; 27import android.support.test.filters.SdkSuppress; 28import android.support.test.filters.SmallTest; 29import android.text.Spanned; 30 31import androidx.core.graphics.PaintCompat; 32import androidx.emoji.util.TestString; 33 34import org.junit.BeforeClass; 35import org.junit.Test; 36import org.junit.runner.RunWith; 37import org.junit.runners.Parameterized; 38 39import java.io.BufferedReader; 40import java.io.IOException; 41import java.io.InputStream; 42import java.io.InputStreamReader; 43import java.util.ArrayList; 44import java.util.Collection; 45 46/** 47 * Reads raw/allemojis.txt which includes all the emojis known to human kind and tests that 48 * EmojiCompat creates EmojiSpans for each one of them. 49 */ 50@SmallTest 51@RunWith(Parameterized.class) 52@SdkSuppress(minSdkVersion = 19) 53public class AllEmojisTest { 54 55 /** 56 * String representation for a single emoji 57 */ 58 private String mString; 59 60 /** 61 * Codepoints of emoji for better assert error message. 62 */ 63 private String mCodepoints; 64 65 /** 66 * Paint object used to check if Typeface can render the given emoji. 67 */ 68 private Paint mPaint; 69 70 @BeforeClass 71 public static void setup() { 72 EmojiCompat.reset(TestConfigBuilder.config()); 73 } 74 75 @Parameterized.Parameters 76 public static Collection<Object[]> data() throws IOException { 77 final Context context = InstrumentationRegistry.getTargetContext(); 78 final InputStream inputStream = context.getAssets().open("emojis.txt"); 79 try { 80 final BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); 81 final Collection<Object[]> data = new ArrayList<>(); 82 final StringBuilder stringBuilder = new StringBuilder(); 83 final StringBuilder codePointsBuilder = new StringBuilder(); 84 85 String s; 86 while ((s = reader.readLine()) != null) { 87 s = s.trim(); 88 // pass comments 89 if (s.isEmpty() || s.startsWith("#")) continue; 90 91 stringBuilder.setLength(0); 92 codePointsBuilder.setLength(0); 93 94 // emoji codepoints are space separated: i.e. 0x1f1e6 0x1f1e8 95 final String[] split = s.split(" "); 96 97 for (int index = 0; index < split.length; index++) { 98 final String part = split[index].trim(); 99 codePointsBuilder.append(part); 100 codePointsBuilder.append(","); 101 stringBuilder.append(Character.toChars(Integer.parseInt(part, 16))); 102 } 103 data.add(new Object[]{stringBuilder.toString(), codePointsBuilder.toString()}); 104 } 105 106 return data; 107 } finally { 108 inputStream.close(); 109 } 110 111 } 112 113 public AllEmojisTest(String string, String codepoints) { 114 mString = string; 115 mCodepoints = codepoints; 116 mPaint = new Paint(); 117 } 118 119 @Test 120 public void testEmoji() { 121 assertTrue("EmojiCompat should have emoji: " + mCodepoints, 122 EmojiCompat.get().hasEmojiGlyph(mString)); 123 assertEmojiCompatAddsEmoji(mString); 124 assertSpanCanRenderEmoji(mString); 125 } 126 127 private void assertSpanCanRenderEmoji(final String str) { 128 final Spanned spanned = (Spanned) EmojiCompat.get().process(new TestString(str).toString()); 129 final EmojiSpan[] spans = spanned.getSpans(0, spanned.length(), EmojiSpan.class); 130 final EmojiMetadata metadata = spans[0].getMetadata(); 131 mPaint.setTypeface(metadata.getTypeface()); 132 133 final String codepoint = String.valueOf(Character.toChars(metadata.getId())); 134 assertTrue(metadata.toString() + " should be rendered", 135 PaintCompat.hasGlyph(mPaint, codepoint)); 136 } 137 138 private void assertEmojiCompatAddsEmoji(final String str) { 139 TestString string = new TestString(str); 140 CharSequence sequence = EmojiCompat.get().process(string.toString()); 141 assertThat(sequence, hasEmojiCount(1)); 142 assertThat(sequence, hasEmojiAt(string.emojiStartIndex(), string.emojiEndIndex())); 143 144 // case where Emoji is in the middle of string 145 string = new TestString(str).withPrefix().withSuffix(); 146 sequence = EmojiCompat.get().process(string.toString()); 147 assertThat(sequence, hasEmojiCount(1)); 148 assertThat(sequence, hasEmojiAt(string.emojiStartIndex(), string.emojiEndIndex())); 149 150 // case where Emoji is at the end of string 151 string = new TestString(str).withSuffix(); 152 sequence = EmojiCompat.get().process(string.toString()); 153 assertThat(sequence, hasEmojiCount(1)); 154 assertThat(sequence, hasEmojiAt(string.emojiStartIndex(), string.emojiEndIndex())); 155 } 156 157} 158