From 8daa93a8e48af7eda045895ec4e4c1ddd5830691 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Fri, 8 Nov 2019 15:35:37 +0700 Subject: [PATCH] fix(android): Start refactoring to add unit tests --- .../java/com/tavultesoft/kmea/KMManager.java | 45 +++++++++--- .../kmmanager/CountSurrogatePairsTest.java | 69 +++++++++++++++++++ 2 files changed, 103 insertions(+), 11 deletions(-) create mode 100644 android/KMEA/app/src/test/java/com/tavultesoft/kmea/kmmanager/CountSurrogatePairsTest.java diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMManager.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMManager.java index 0421df7555..6df2f1dd43 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMManager.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMManager.java @@ -308,6 +308,39 @@ public final class KMManager { } } + /** + * Count the number of surrogate pairs starting from the end of a character sequence + * until we reach dn codepoints. + * Doing this the hard way because we can't foreach charSequence in reverse. + * @param sequence - the character sequence to analyze + * @param dn - the number of code points to count up to + * @return int + */ + public static int countSurrogatePairs(CharSequence sequence, int dn) { + if ((sequence == null) || (sequence.length() == 0) || (dn <= 0)) { + return 0; + } + + int numPairs = 0, counter = 0; + int lastIndex = sequence.length()-1; + try { + do { + if ((lastIndex - counter > 0) && Character.isLowSurrogate(sequence.charAt(lastIndex - counter))) { + numPairs++; + } + counter++; + } while (counter < dn && numPairs < dn); + + return numPairs; + } catch (Exception e) { + Log.e(TAG, "Error in countSurrogatePairs: " + e); + if (counter >= dn) { + return numPairs; + } + return 0; + } + } + /* // TODO: Chromium has a bug where deleteSurroundingText deletes an entire grapheme cluster // instead of one code-point. @@ -325,18 +358,8 @@ public final class KMManager { return; } - // Count the number of surrogate pairs in this buffer, backwards from the end - // until we reach dn codepoints. - // Unfortunately, can't foreach charSequence in reverse - int numPairs = 0; - int counter=0; try { - do { - if ((lastIndex - counter > 0) && Character.isLowSurrogate(charsBackup.charAt(lastIndex - counter))) { - numPairs++; - } - counter++; - } while (counter < dn && numPairs < dn); + int numPairs = countSurrogatePairs(charsBackup, dn); // Chop dn+numPairs code points from the end of charsBackup // subSequence indices are start(inclusive) to end(exclusive) diff --git a/android/KMEA/app/src/test/java/com/tavultesoft/kmea/kmmanager/CountSurrogatePairsTest.java b/android/KMEA/app/src/test/java/com/tavultesoft/kmea/kmmanager/CountSurrogatePairsTest.java new file mode 100644 index 0000000000..818783f641 --- /dev/null +++ b/android/KMEA/app/src/test/java/com/tavultesoft/kmea/kmmanager/CountSurrogatePairsTest.java @@ -0,0 +1,69 @@ +package com.tavultesoft.kmea.kmmanager; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; + +import com.tavultesoft.kmea.KMManager; + +@RunWith(RobolectricTestRunner.class) +public class CountSurrogatePairsTest { + // Smiley emoji U+1F600 = D800 DC3D + private final String SMILEY = "\uD800\uDC3D"; + + // Winking emoji U+1F609 = D800 DC3C + private final String WINK = "\uD800\uDC3C"; + + + @Test + public void test_invalid_input() { + + // Test invalid input doesn't throw exception + CharSequence sequence = null; + int numPairs = KMManager.countSurrogatePairs(sequence, 1); + Assert.assertEquals(0, numPairs); + + sequence = "test"; + numPairs = KMManager.countSurrogatePairs(sequence, -1); + Assert.assertEquals(0, numPairs); + + numPairs = KMManager.countSurrogatePairs(sequence, sequence.length()+5); + Assert.assertEquals(0, numPairs); + } + + @Test + public void test_zero_pair() { + CharSequence sequence = "Zero emojis"; + int numPairs = KMManager.countSurrogatePairs(sequence, sequence.length()); + Assert.assertEquals(0, numPairs); + } + + @Test + public void test_one_pair() { + + // Test for scenarios that expect 1 surrogate pair + CharSequence sequence = "HaveA" + SMILEY + "Day"; + int numPairs = KMManager.countSurrogatePairs(sequence, 4); + Assert.assertEquals(1, numPairs); + + sequence = "HaveA" + SMILEY + WINK; + numPairs = KMManager.countSurrogatePairs(sequence, 1); + Assert.assertEquals(1, numPairs); + + numPairs = KMManager.countSurrogatePairs(sequence, 2); + Assert.assertEquals(1, numPairs); + } + + @Test + public void test_two_pairs() { + + // Test for scenarios that expect 2 surrogate pairs + CharSequence sequence = "HaveA" + SMILEY + WINK; + int numPairs = KMManager.countSurrogatePairs(sequence, 3); + Assert.assertEquals(2, numPairs); + + numPairs = KMManager.countSurrogatePairs(sequence, 4); + Assert.assertEquals(2, numPairs); + } +}