1e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller/* 2e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * Copyright (C) 2014 Square, Inc. 3e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * 4e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * Licensed under the Apache License, Version 2.0 (the "License"); 5e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * you may not use this file except in compliance with the License. 6e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * You may obtain a copy of the License at 7e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * 8e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * http://www.apache.org/licenses/LICENSE-2.0 9e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * 10e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * Unless required by applicable law or agreed to in writing, software 11e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * distributed under the License is distributed on an "AS IS" BASIS, 12e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * See the License for the specific language governing permissions and 14e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * limitations under the License. 15e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller */ 16e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerpackage okio; 17e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 187aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fullerimport java.io.EOFException; 19e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport org.junit.Test; 20e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 21e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport static org.junit.Assert.assertEquals; 227aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fullerimport static org.junit.Assert.assertFalse; 237aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fullerimport static org.junit.Assert.assertTrue; 247aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fullerimport static org.junit.Assert.fail; 25e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 26e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerpublic final class Utf8Test { 27e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void oneByteCharacters() throws Exception { 28e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEncoded("00", 0x00); // Smallest 1-byte character. 29e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEncoded("20", ' '); 30e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEncoded("7e", '~'); 31e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEncoded("7f", 0x7f); // Largest 1-byte character. 32e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 33e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 34e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void twoByteCharacters() throws Exception { 35e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEncoded("c280", 0x0080); // Smallest 2-byte character. 36e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEncoded("c3bf", 0x00ff); 37e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEncoded("c480", 0x0100); 38e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEncoded("dfbf", 0x07ff); // Largest 2-byte character. 39e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 40e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 41e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void threeByteCharacters() throws Exception { 42e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEncoded("e0a080", 0x0800); // Smallest 3-byte character. 43e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEncoded("e0bfbf", 0x0fff); 44e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEncoded("e18080", 0x1000); 45e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEncoded("e1bfbf", 0x1fff); 46e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEncoded("ed8080", 0xd000); 47e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEncoded("ed9fbf", 0xd7ff); // Largest character lower than the min surrogate. 48e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEncoded("ee8080", 0xe000); // Smallest character greater than the max surrogate. 49e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEncoded("eebfbf", 0xefff); 50e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEncoded("ef8080", 0xf000); 51e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEncoded("efbfbf", 0xffff); // Largest 3-byte character. 52e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 53e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 54e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void fourByteCharacters() throws Exception { 55e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEncoded("f0908080", 0x010000); // Smallest surrogate pair. 56e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEncoded("f48fbfbf", 0x10ffff); // Largest code point expressible by UTF-16. 57e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 58e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 59e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void danglingHighSurrogate() throws Exception { 607aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller assertStringEncoded("3f", "\ud800"); // "?" 61e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 62e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 63e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void lowSurrogateWithoutHighSurrogate() throws Exception { 647aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller assertStringEncoded("3f", "\udc00"); // "?" 65e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 66e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 67e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void highSurrogateFollowedByNonSurrogate() throws Exception { 687aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller assertStringEncoded("3f61", "\ud800\u0061"); // "?a": Following character is too low. 697aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller assertStringEncoded("3fee8080", "\ud800\ue000"); // "?\ue000": Following character is too high. 70e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 71e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 72e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void multipleSegmentString() throws Exception { 73e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller String a = TestUtil.repeat('a', Segment.SIZE + Segment.SIZE + 1); 74e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Buffer encoded = new Buffer().writeUtf8(a); 75e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Buffer expected = new Buffer().write(a.getBytes(Util.UTF_8)); 76e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(expected, encoded); 77e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 78e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 79e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller @Test public void stringSpansSegments() throws Exception { 80e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller Buffer buffer = new Buffer(); 81e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller String a = TestUtil.repeat('a', Segment.SIZE - 1); 82e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller String b = "bb"; 83e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller String c = TestUtil.repeat('c', Segment.SIZE - 1); 84e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller buffer.writeUtf8(a); 85e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller buffer.writeUtf8(b); 86e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller buffer.writeUtf8(c); 87e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(a + b + c, buffer.readUtf8()); 88e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 89e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 907aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller @Test public void readEmptyBufferThrowsEofException() throws Exception { 917aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller Buffer buffer = new Buffer(); 927aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller try { 937aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller buffer.readUtf8CodePoint(); 947aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller fail(); 957aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller } catch (EOFException expected) { 967aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller } 977aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller } 987aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller 997aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller @Test public void readLeadingContinuationByteReturnsReplacementCharacter() throws Exception { 1007aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller Buffer buffer = new Buffer(); 1017aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller buffer.writeByte(0xbf); 1027aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller assertEquals(Buffer.REPLACEMENT_CHARACTER, buffer.readUtf8CodePoint()); 1037aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller assertTrue(buffer.exhausted()); 1047aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller } 1057aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller 1067aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller @Test public void readMissingContinuationBytesThrowsEofException() throws Exception { 1077aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller Buffer buffer = new Buffer(); 1087aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller buffer.writeByte(0xdf); 1097aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller try { 1107aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller buffer.readUtf8CodePoint(); 1117aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller fail(); 1127aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller } catch (EOFException expected) { 1137aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller } 1147aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller assertFalse(buffer.exhausted()); // Prefix byte wasn't consumed. 1157aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller } 1167aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller 1177aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller @Test public void readTooLargeCodepointReturnsReplacementCharacter() throws Exception { 1187aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller // 5-byte and 6-byte code points are not supported. 1197aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller Buffer buffer = new Buffer(); 1207aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller buffer.write(ByteString.decodeHex("f888808080")); 1217aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller assertEquals(Buffer.REPLACEMENT_CHARACTER, buffer.readUtf8CodePoint()); 1227aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller assertEquals(Buffer.REPLACEMENT_CHARACTER, buffer.readUtf8CodePoint()); 1237aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller assertEquals(Buffer.REPLACEMENT_CHARACTER, buffer.readUtf8CodePoint()); 1247aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller assertEquals(Buffer.REPLACEMENT_CHARACTER, buffer.readUtf8CodePoint()); 1257aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller assertEquals(Buffer.REPLACEMENT_CHARACTER, buffer.readUtf8CodePoint()); 1267aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller assertTrue(buffer.exhausted()); 1277aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller } 1287aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller 1297aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller @Test public void readNonContinuationBytesReturnsReplacementCharacter() throws Exception { 1307aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller // Use a non-continuation byte where a continuation byte is expected. 1317aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller Buffer buffer = new Buffer(); 1327aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller buffer.write(ByteString.decodeHex("df20")); 1337aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller assertEquals(Buffer.REPLACEMENT_CHARACTER, buffer.readUtf8CodePoint()); 1347aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller assertEquals(0x20, buffer.readUtf8CodePoint()); // Non-continuation character not consumed. 1357aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller assertTrue(buffer.exhausted()); 1367aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller } 1377aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller 1387aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller @Test public void readCodePointBeyondUnicodeMaximum() throws Exception { 1397aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller // A 4-byte encoding with data above the U+10ffff Unicode maximum. 1407aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller Buffer buffer = new Buffer(); 1417aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller buffer.write(ByteString.decodeHex("f4908080")); 1427aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller assertEquals(Buffer.REPLACEMENT_CHARACTER, buffer.readUtf8CodePoint()); 1437aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller assertTrue(buffer.exhausted()); 1447aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller } 1457aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller 1467aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller @Test public void readSurrogateCodePoint() throws Exception { 1477aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller Buffer buffer = new Buffer(); 1487aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller buffer.write(ByteString.decodeHex("eda080")); 1497aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller assertEquals(Buffer.REPLACEMENT_CHARACTER, buffer.readUtf8CodePoint()); 1507aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller assertTrue(buffer.exhausted()); 1517aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller buffer.write(ByteString.decodeHex("edbfbf")); 1527aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller assertEquals(Buffer.REPLACEMENT_CHARACTER, buffer.readUtf8CodePoint()); 1537aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller assertTrue(buffer.exhausted()); 1547aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller } 1557aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller 1567aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller @Test public void readOverlongCodePoint() throws Exception { 1577aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller // Use 2 bytes to encode data that only needs 1 byte. 1587aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller Buffer buffer = new Buffer(); 1597aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller buffer.write(ByteString.decodeHex("c080")); 1607aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller assertEquals(Buffer.REPLACEMENT_CHARACTER, buffer.readUtf8CodePoint()); 1617aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller assertTrue(buffer.exhausted()); 1627aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller } 1637aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller 1647aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller @Test public void writeSurrogateCodePoint() throws Exception { 1657aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller Buffer buffer = new Buffer(); 1667aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller buffer.writeUtf8CodePoint(0xd7ff); // Below lowest surrogate is okay. 1677aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller try { 1687aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller buffer.writeUtf8CodePoint(0xd800); // Lowest surrogate throws. 1697aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller fail(); 1707aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller } catch (IllegalArgumentException expected) { 1717aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller } 1727aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller try { 1737aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller buffer.writeUtf8CodePoint(0xdfff); // Highest surrogate throws. 1747aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller fail(); 1757aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller } catch (IllegalArgumentException expected) { 1767aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller } 1777aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller buffer.writeUtf8CodePoint(0xe000); // Above highest surrogate is okay. 1787aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller } 1797aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller 1807aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller @Test public void writeCodePointBeyondUnicodeMaximum() throws Exception { 1817aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller Buffer buffer = new Buffer(); 1827aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller try { 1837aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller buffer.writeUtf8CodePoint(0x110000); 1847aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller fail(); 1857aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller } catch (IllegalArgumentException expected) { 1867aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller } 1877aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller } 1887aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller 189e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller private void assertEncoded(String hex, int... codePoints) throws Exception { 1907aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller assertCodePointEncoded(hex, codePoints); 1917aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller assertCodePointDecoded(hex, codePoints); 1927aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller assertStringEncoded(hex, new String(codePoints, 0, codePoints.length)); 1937aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller } 1947aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller 1957aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller private void assertCodePointEncoded(String hex, int... codePoints) throws Exception { 1967aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller Buffer buffer = new Buffer(); 1977aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller for (int codePoint : codePoints) { 1987aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller buffer.writeUtf8CodePoint(codePoint); 1997aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller } 2007aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller assertEquals(buffer.readByteString(), ByteString.decodeHex(hex)); 2017aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller } 2027aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller 2037aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller private void assertCodePointDecoded(String hex, int... codePoints) throws Exception { 2047aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller Buffer buffer = new Buffer().write(ByteString.decodeHex(hex)); 2057aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller for (int codePoint : codePoints) { 2067aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller assertEquals(codePoint, buffer.readUtf8CodePoint()); 2077aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller } 2087aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller assertTrue(buffer.exhausted()); 209e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 210e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 2117aeaaefc891f6221f4b2cce536b1c1e816e09794Neil Fuller private void assertStringEncoded(String hex, String string) throws Exception { 212e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller ByteString expectedUtf8 = ByteString.decodeHex(hex); 213e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 214e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // Confirm our expectations are consistent with the platform. 215e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller ByteString platformUtf8 = ByteString.of(string.getBytes("UTF-8")); 216e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(expectedUtf8, platformUtf8); 217e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller 218e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller // Confirm our implementation matches those expectations. 219e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller ByteString actualUtf8 = new Buffer().writeUtf8(string).readByteString(); 220e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller assertEquals(expectedUtf8, actualUtf8); 221e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller } 222e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller} 223