Something went wrong. Try again.
This repository has no description
Something went wrong. Try again.
3.3 kB · 98 lines
Kotlin
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899package social.grain
import androidx.test.ext.junit.runners.AndroidJUnit4import org.junit.Assert.assertEqualsimport org.junit.Assert.assertFalseimport org.junit.Assert.assertTrueimport org.junit.Testimport org.junit.runner.RunWithimport social.grain.util.GrainLimitsimport social.grain.util.TextLimitimport social.grain.util.graphemeCountimport social.grain.util.utf8ByteCount
/** * On the device rather than the JVM: grapheme segmentation comes from ICU, and * the JVM's own BreakIterator gives different — wrong — answers for flags and * ZWJ sequences. */@RunWith(AndroidJUnit4::class)class TextLimitsTest {
@Test fun countsPlainTextOnePerCharacter() { assertEquals(5, "hello".graphemeCount()) assertEquals(5, "hello".utf8ByteCount()) }
@Test fun countsAnAccentedCharacterAsOneGraphemeAndTwoBytes() { assertEquals(4, "café".graphemeCount()) assertEquals(5, "café".utf8ByteCount()) }
/** The case String.length gets wrong: one glyph, two UTF-16 code units. */ @Test fun countsAnEmojiAsOneGrapheme() { assertEquals(2, "📷".length) assertEquals(1, "📷".graphemeCount()) assertEquals(4, "📷".utf8ByteCount()) }
/** A flag is two regional indicators; a reader sees one flag. */ @Test fun countsAFlagAsOneGrapheme() { assertEquals(1, "🇬🇧".graphemeCount()) assertEquals(8, "🇬🇧".utf8ByteCount()) }
@Test fun countsAZwjSequenceAsOneGrapheme() { assertEquals(1, "👩👩👧".graphemeCount()) }
@Test fun emptyTextCountsZero() { assertEquals(0, "".graphemeCount()) assertEquals(0, "".utf8ByteCount()) }
@Test fun aGalleryTitleOfPlainTextIsBoundedByItsGraphemeCount() { assertTrue(GrainLimits.GalleryTitle.isWithin("a".repeat(100))) assertFalse(GrainLimits.GalleryTitle.isWithin("a".repeat(101))) }
/** * The reason both units are checked. Twenty-six emoji is well inside the * gallery title's 100, but 104 bytes — over the cap the PDS enforces. */ @Test fun aGalleryTitleWithinItsGraphemeCountCanStillBeOverInBytes() { val emoji = "📷".repeat(26) assertEquals(26, emoji.graphemeCount()) assertEquals(104, emoji.utf8ByteCount()) assertFalse(GrainLimits.GalleryTitle.isWithin(emoji)) }
/** * The profile lexicon gives itself ten bytes per grapheme, so for * displayName the grapheme count is what binds — 64 emoji is 256 bytes, * comfortably inside 640. */ @Test fun aDisplayNameIsBoundedByGraphemesRatherThanBytes() { val emoji = "📷".repeat(64) assertEquals(256, emoji.utf8ByteCount()) assertTrue(GrainLimits.DisplayName.isWithin(emoji)) assertFalse(GrainLimits.DisplayName.isWithin("📷".repeat(65))) }
@Test fun limitsMatchTheLexicons() { assertEquals(TextLimit(graphemes = 100, bytes = 100), GrainLimits.GalleryTitle) assertEquals(TextLimit(graphemes = 1000, bytes = 1000), GrainLimits.GalleryDescription) assertEquals(TextLimit(graphemes = 64, bytes = 640), GrainLimits.DisplayName) assertEquals(TextLimit(graphemes = 256, bytes = 2560), GrainLimits.Bio) }}