Path: blob/master/test/jdk/java/util/HexFormat/HexFormatTest.java
41149 views
/*1* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223import org.testng.annotations.DataProvider;24import org.testng.annotations.Test;25import org.testng.SkipException;2627import java.io.CharArrayWriter;28import java.io.IOException;29import java.io.UncheckedIOException;30import java.nio.CharBuffer;31import java.util.Arrays;32import java.util.HexFormat;33import java.util.Locale;3435import static org.testng.Assert.assertEquals;36import static org.testng.Assert.assertFalse;37import static org.testng.Assert.assertSame;38import static org.testng.Assert.assertThrows;39import static org.testng.Assert.assertTrue;40import static org.testng.Assert.expectThrows;4142/*43* @test44* @summary Check HexFormat formatting and parsing45* @run testng/othervm HexFormatTest46*/4748@Test49public class HexFormatTest {50static final Class<NullPointerException> NPE = NullPointerException.class;5152@DataProvider(name = "HexFormattersParsers")53Object[][] hexFormattersParsers() {54return new Object[][]{55{"", "", "", true,56HexFormat.of().withUpperCase()},57{", ", "#", "L", false,58HexFormat.ofDelimiter(", ").withPrefix("#").withSuffix("L")},59{"", "", "", false,60HexFormat.of().withPrefix("").withSuffix("")},61{".", "", "", false,62HexFormat.ofDelimiter(".").withPrefix("").withSuffix("")},63{", ", "0x", "", true,64HexFormat.ofDelimiter(", ").withUpperCase().withPrefix("0x")},65{"\u0202", "\u0203", "\u0204", false,66HexFormat.ofDelimiter("\u0202").withPrefix("\u0203").withSuffix("\u0204")},67{"\u0202", "", "", false,68HexFormat.ofDelimiter("\u0202")},6970};71}7273@DataProvider(name = "HexStringsThrowing")74Object[][] HexStringsThrowing() {75return new Object[][]{76{"0", ":", "", ""}, // wrong string length77{"01:", ":", "", ""}, // wrong string length78{"01:0", ":", "", ""}, // wrong string length79{"0", ",", "", ""}, // wrong length and separator80{"01:", ",", "", ""}, // wrong length and separator81{"01:0", ",", "", ""}, // wrong length and separator82{"01:00", ",", "", ""}, // wrong separator83{"00]", ",", "[", "]"}, // missing prefix84{"[00", ",", "[", "]"}, // missing suffix85{"]", ",", "[", "]"}, // missing prefix86{"[", ",", "[", "]"}, // missing suffix87{"00", ",", "abc", ""}, // Prefix longer than string88{"01", ",", "", "def"}, // Suffix longer than string89{"abc00,", ",", "abc", ""}, // Prefix and delim but not another value90{"01def,", ",", "", "def"}, // Suffix and delim but not another value91};92}9394@DataProvider(name = "BadBytesThrowing")95Object[][] badBytesThrowing() {96return new Object[][]{97{new byte[1], 0, 2}, // bad toIndex98{new byte[1], 1, 2}, // bad fromIndex + toIndex99{new byte[1], -1, 2}, // bad fromIndex100{new byte[1], -1, 1}, // bad fromIndex101{new byte[1], 0, -1}, // bad toIndex102{new byte[1], 1, -1}, // bad toIndex103};104}105106@DataProvider(name = "BadParseHexThrowing")107Object[][] badParseHexThrowing() {108return new Object[][]{109{"a", 0, 2, IndexOutOfBoundsException.class}, // bad toIndex110{"b", 1, 2, IndexOutOfBoundsException.class}, // bad toIndex111{"a", -1, 2, IndexOutOfBoundsException.class}, // bad fromIndex112{"b", -1, 1, IndexOutOfBoundsException.class}, // bad fromIndex113{"a", 0, -1, IndexOutOfBoundsException.class}, // bad toIndex114{"b", 1, -1, IndexOutOfBoundsException.class}, // bad fromIndex + toIndex115{"76543210", 0, 7, IllegalArgumentException.class}, // odd number of digits116{"zz00", 0, 4, IllegalArgumentException.class}, // non-hex digits117{"00zz", 0, 4, IllegalArgumentException.class}, // non-hex digits118};119}120121@DataProvider(name = "BadFromHexDigitsThrowing")122Object[][] badHexDigitsThrowing() {123return new Object[][]{124{"a", 0, 2, IndexOutOfBoundsException.class}, // bad toIndex125{"b", 1, 2, IndexOutOfBoundsException.class}, // bad fromIndex + toIndex126{"a", -1, 2, IndexOutOfBoundsException.class}, // bad toIndex127{"b", -1, 1, IndexOutOfBoundsException.class}, // bad fromIndex + toIndex128{"a", 0, -1, IndexOutOfBoundsException.class}, // bad toIndex129{"b", 1, -1, IndexOutOfBoundsException.class}, // bad fromIndex + toIndex130};131}132133static byte[] genBytes(int origin, int len) {134byte[] bytes = new byte[len];135for (int i = 0; i < len; i++)136bytes[i] = (byte) (origin + i);137return bytes;138}139140@Test141static void testToHex() {142HexFormat hex = HexFormat.of();143for (int i = 0; i < 32; i++) {144char c = hex.toLowHexDigit((byte)i);145String expected = Integer.toHexString(i & 0xf);146assertEquals(c, expected.charAt(0), "toHex formatting");147}148}149150@Test151static void testToHexDigits() {152HexFormat hex = HexFormat.of();153for (int i = 0; i < 256; i++) {154String actual = hex.toHexDigits((byte)i);155int expected = HexFormat.fromHexDigits(actual);156assertEquals(expected, i, "fromHexDigits");157assertEquals(actual.charAt(0), hex.toHighHexDigit((byte)i),158"first char mismatch");159assertEquals(actual.charAt(1), hex.toLowHexDigit((byte)i),160"second char mismatch");161}162}163164@Test165static void testIsHexDigit() {166for (int i = 0; i < 0x3ff; i++) {167boolean actual = HexFormat.isHexDigit(i);168boolean expected = Character.digit(i, 16) >= 0;169assertEquals(actual, expected, "isHexDigit: " + i);170}171}172173@Test174static void testFromHexDigit() {175String chars = "0123456789ABCDEF0123456789abcdef";176for (int i = 0; i < chars.length(); i++) {177int v = HexFormat.fromHexDigit(chars.charAt(i));178assertEquals(v, i & 0xf, "fromHex decode");179}180}181182@Test183static void testFromHexInvalid() {184for (int i = 0; i < 65536; i++) {185char ch = (char)i;186if (ch > 0xff || Character.digit(ch, 16) < 0) {187assertFalse(HexFormat.isHexDigit(ch), "isHexDigit incorrect for '" + ch + "' = " + i);188expectThrows(NumberFormatException.class,189() -> HexFormat.fromHexDigit(ch));190191}192}193}194195@Test196static void testAppendHexByteWithStringBuilder() {197HexFormat hex = HexFormat.of();198StringBuilder sb = new StringBuilder();199for (int i = 0; i < 256; i++) {200sb.setLength(0);201StringBuilder sb1 = hex.toHexDigits(sb, (byte)i);202assertSame(sb1, sb, "toHexDigits returned different StringBuilder");203assertEquals(sb.length(), 2, "wrong length after append: " + i);204assertEquals(sb.charAt(0), hex.toHighHexDigit((byte)i), "MSB converted wrong");205assertEquals(sb.charAt(1), hex.toLowHexDigit((byte)i), "LSB converted wrong");206207assertEquals(HexFormat.fromHexDigits(sb), i, "hex.format(sb, byte) wrong");208}209}210211@Test212static void testAppendHexByteWithCharBuffer() {213HexFormat hex = HexFormat.of();214CharBuffer cb = CharBuffer.allocate(256);215for (int i = 1; i <= 128; i++) {216CharBuffer cb1 = hex.toHexDigits(cb, (byte)i);217assertTrue(cb1 == cb);218assertEquals(cb.position(), i * 2);219}220assertEquals(cb.remaining(), 0);221}222223@Test224static void testAppendHexByteWithCharArrayWriter() {225HexFormat hex = HexFormat.of();226CharArrayWriter caw = new CharArrayWriter();227for (int i = 1; i <= 128; i++) {228CharArrayWriter caw1 = hex.toHexDigits(caw, (byte)i);229assertTrue(caw1 == caw);230assertEquals(caw.size(), i * 2);231}232}233234@Test235static void testFromHexPairInvalid() {236HexFormat hex = HexFormat.of();237238// An assortment of invalid characters239String chars = "-0--0-";240for (int i = 0; i < chars.length(); i += 2) {241final int ndx = i;242Throwable ex = expectThrows(NumberFormatException.class,243() -> HexFormat.fromHexDigits(chars.subSequence(ndx, ndx+2)));244System.out.println(ex);245}246}247248@Test(dataProvider = "HexStringsThrowing")249static void testToBytesThrowing(String value, String sep, String prefix, String suffix) {250HexFormat hex = HexFormat.ofDelimiter(sep).withPrefix(prefix).withSuffix(suffix);251Throwable ex = expectThrows(IllegalArgumentException.class,252() -> {253byte[] v = hex.parseHex(value);254System.out.println("str: " + value + ", actual: " + v + ", bytes: " +255Arrays.toString(v));256});257System.out.println("ex: " + ex);258}259260@Test261static void testFactoryNPE() {262assertThrows(NPE, () -> HexFormat.ofDelimiter(null));263assertThrows(NPE, () -> HexFormat.of().withDelimiter(null));264assertThrows(NPE, () -> HexFormat.of().withPrefix(null));265assertThrows(NPE, () -> HexFormat.of().withSuffix(null));266}267268@Test269static void testFormatHexNPE() {270assertThrows(NPE, () -> HexFormat.of().formatHex(null));271assertThrows(NPE, () -> HexFormat.of().formatHex(null, 0, 1));272assertThrows(NPE, () -> HexFormat.of().formatHex(null, null));273assertThrows(NPE, () -> HexFormat.of().formatHex(null, null, 0, 0));274StringBuilder sb = new StringBuilder();275assertThrows(NPE, () -> HexFormat.of().formatHex(sb, null));276assertThrows(NPE, () -> HexFormat.of().formatHex(sb, null, 0, 1));277}278279@Test280static void testParseHexNPE() {281assertThrows(NPE, () -> HexFormat.of().parseHex(null));282assertThrows(NPE, () -> HexFormat.of().parseHex((String)null, 0, 0));283assertThrows(NPE, () -> HexFormat.of().parseHex((char[])null, 0, 0));284}285286@Test287static void testFromHexNPE() {288assertThrows(NPE, () -> HexFormat.fromHexDigits(null));289assertThrows(NPE, () -> HexFormat.fromHexDigits(null, 0, 0));290assertThrows(NPE, () -> HexFormat.fromHexDigitsToLong(null));291assertThrows(NPE, () -> HexFormat.fromHexDigitsToLong(null, 0, 0));292}293294@Test295static void testToHexDigitsNPE() {296assertThrows(NPE, () -> HexFormat.of().toHexDigits(null, (byte)0));297}298299@Test(dataProvider = "BadParseHexThrowing")300static void badParseHex(String string, int offset, int length,301Class<? extends Throwable> exClass) {302assertThrows(exClass,303() -> HexFormat.of().parseHex(string, offset, length));304char[] chars = string.toCharArray();305assertThrows(exClass,306() -> HexFormat.of().parseHex(chars, offset, length));307}308309@Test(dataProvider = "BadFromHexDigitsThrowing")310static void badFromHexDigits(String string, int fromIndex, int toIndex,311Class<? extends Throwable> exClass) {312assertThrows(exClass,313() -> HexFormat.fromHexDigits(string, fromIndex, toIndex));314assertThrows(exClass,315() -> HexFormat.fromHexDigitsToLong(string, fromIndex, toIndex));316}317318// Verify IAE for strings that are too long for the target primitive type319// or the number of requested digits is too large.320@Test321static void wrongNumberDigits() {322assertThrows(IllegalArgumentException.class,323() -> HexFormat.fromHexDigits("9876543210"));324assertThrows(IllegalArgumentException.class,325() -> HexFormat.fromHexDigits("9876543210", 0, 9));326assertThrows(IllegalArgumentException.class,327() -> HexFormat.fromHexDigitsToLong("98765432109876543210"));328assertThrows(IllegalArgumentException.class,329() -> HexFormat.fromHexDigitsToLong("98765432109876543210", 0, 17));330}331332@Test(dataProvider="HexFormattersParsers")333static void testFormatter(String delimiter, String prefix, String suffix,334boolean uppercase,335HexFormat hex) {336byte[] expected = genBytes('A', 15);337String res = hex.formatHex(expected);338assertTrue(res.startsWith(prefix), "Prefix not found");339assertTrue(res.endsWith(suffix), "Suffix not found");340int expectedLen = expected.length * (2 + prefix.length() +341delimiter.length() + suffix.length()) - delimiter.length();342assertEquals(res.length(), expectedLen, "String length");343344if (expected.length > 1) {345// check prefix and suffix is present for each hex pair346for (int i = 0; i < expected.length; i++) {347int valueChars = prefix.length() + 2 + suffix.length();348int offset = i * (valueChars + delimiter.length());349String value = res.substring(offset, offset + valueChars);350assertTrue(value.startsWith(prefix), "wrong prefix");351assertTrue(value.endsWith(suffix), "wrong suffix");352353// Check case of digits354String cc = value.substring(prefix.length(), prefix.length() + 2);355assertEquals(cc,356(uppercase) ? cc.toUpperCase(Locale.ROOT) : cc.toLowerCase(Locale.ROOT),357"Case mismatch");358if (i < expected.length - 1 && !delimiter.isEmpty()) {359// Check the delimiter is present for each pair except the last360assertEquals(res.substring(offset + valueChars,361offset + valueChars + delimiter.length()), delimiter);362}363}364}365}366367@Test(dataProvider="HexFormattersParsers")368static void testFormatHexString(String unused1, String unused2, String unused3,369boolean unused4, HexFormat hex) {370byte[] expected = genBytes('A', 15);371String s = hex.formatHex(expected);372System.out.println(" formatted: " + s);373374byte[] actual = hex.parseHex(s);375System.out.println(" parsed as: " + Arrays.toString(actual));376int mismatch = Arrays.mismatch(expected, actual);377assertEquals(actual, expected, "format/parse cycle failed, mismatch: " + mismatch);378}379380@Test(dataProvider="HexFormattersParsers")381static void testParseHexStringRange(String delimiter, String prefix, String suffix,382boolean unused4, HexFormat hex) {383byte[] expected = genBytes('A', 15);384String s = hex.formatHex(expected);385386// Parse values 2, 3, 4 from the generated string387int low = 2;388int high = 5;389int stride = prefix.length() + 2 + suffix.length() + delimiter.length();390System.out.println(" formatted subrange: " +391s.substring(low * stride, high * stride - delimiter.length()));392byte[] actual = hex.parseHex(s, low * stride,393high * stride - delimiter.length());394System.out.println(" parsed as: " + Arrays.toString(actual));395396assertEquals(actual.length, (high - low), "array length");397int mismatch = Arrays.mismatch(expected, low, high, actual, 0, high - low);398assertEquals(mismatch, -1, "format/parse cycle failed, mismatch: " + mismatch);399}400401@Test(dataProvider="HexFormattersParsers")402static void testParseHexEmptyString(String delimiter, String prefix, String suffix,403boolean unused4, HexFormat hex) {404byte[] actual = hex.parseHex("");405assertEquals(actual.length, 0, "empty string parse");406actual = hex.parseHex("abc", 0, 0);407assertEquals(actual.length, 0, "empty string range parse");408actual = hex.parseHex(new char[1], 0, 0);409assertEquals(actual.length, 0, "empty char array subrange empty parse");410}411412@Test(dataProvider="HexFormattersParsers")413static void testFormatHexRangeString(String unused1, String unused2, String unused3,414boolean unused4, HexFormat hex) {415byte[] expected = genBytes('A', 15);416int low = 1;417int high = expected.length - 2;418String s = hex.formatHex(expected, low, high);419System.out.println(" formatted: " + s);420421byte[] actual = hex.parseHex(s);422System.out.println(" parsed as: " + Arrays.toString(actual));423int mismatch = Arrays.mismatch(expected, low, high, actual, 0, high - low);424assertEquals(mismatch, -1, "format/parse cycle failed, mismatch: " + mismatch);425}426427@Test(dataProvider="HexFormattersParsers")428static void testFormatHexAppendable(String unused1, String unused2, String unused3,429boolean unused4, HexFormat hex) {430byte[] expected = genBytes('A', 15);431StringBuilder sb = new StringBuilder();432StringBuilder s = hex.formatHex(sb, expected);433assertEquals(s, sb, "formatHex returned unknown StringBuilder");434System.out.println(" formatted: " + s);435436byte[] actual = hex.parseHex(s.toString());437System.out.println(" parsed as: " + Arrays.toString(actual));438int mismatch = Arrays.mismatch(expected, actual);439assertEquals(actual, expected, "format/parse cycle failed, mismatch: " + mismatch);440}441442@Test(dataProvider="HexFormattersParsers")443static void testFormatHexRangeAppendable(String unused1, String unused2, String unused3,444boolean unused4, HexFormat hex) {445byte[] expected = genBytes('A', 15);446int low = 1;447int high = expected.length - 2;448StringBuilder sb = new StringBuilder();449StringBuilder s = hex.formatHex(sb, expected, low, high);450assertEquals(s, sb, "formatHex returned unknown StringBuilder");451System.out.println(" formatted: " + s);452453byte[] actual = hex.parseHex(s.toString());454System.out.println(" parsed as: " + Arrays.toString(actual));455byte[] sub = Arrays.copyOfRange(expected, low, high);456System.out.println("actual: " + Arrays.toString(actual));457System.out.println("sub : " + Arrays.toString(sub));458int mismatch = Arrays.mismatch(expected, low, high, actual, 0, high - low);459460assertEquals(actual, sub, "format/parse cycle failed, mismatch: " + mismatch);461assertEquals(mismatch, -1, "format/parse cycle failed, mismatch: " + mismatch);462}463464@Test(dataProvider="HexFormattersParsers")465static void testFormatHexCharArray(String unused1, String unused2, String unused3,466boolean unused4, HexFormat hex) {467byte[] expected = genBytes('A', 15);468String s = hex.formatHex(expected);469System.out.println(" formatted: " + s);470471char[] chars = s.toCharArray();472byte[] actual = hex.parseHex(chars, 0, chars.length);473System.out.println(" parsed as: " + Arrays.toString(actual));474int mismatch = Arrays.mismatch(expected, actual);475assertEquals(actual, expected, "format/parse cycle failed, mismatch: " + mismatch);476}477478@Test(dataProvider="HexFormattersParsers")479static void testFormatHexCharArrayIndexed(String delimiter, String prefix, String suffix,480boolean unused4, HexFormat hex) {481byte[] expected = genBytes('A', 15);482String s = hex.formatHex(expected);483System.out.println(" formatted: " + s);484485486// Parse values 2, 3, 4 from the generated string487int low = 2;488int high = 5;489int stride = prefix.length() + 2 + suffix.length() + delimiter.length();490System.out.println(" formatted subrange: " +491s.substring(low * stride, high * stride - delimiter.length()));492char[] chars = s.toCharArray();493byte[] actual = hex.parseHex(chars, low * stride,494high * stride - delimiter.length());495System.out.println(" parsed as: " + Arrays.toString(actual));496497assertEquals(actual.length, (high - low), "array length");498int mismatch = Arrays.mismatch(expected, low, high, actual, 0, high - low);499assertEquals(mismatch, -1, "format/parse cycle failed, mismatch: " + mismatch);500}501502@Test(dataProvider="HexFormattersParsers")503static void testFormatterToString(String delimiter, String prefix, String suffix,504boolean uppercase,505HexFormat hex) {506String actual = String.format(507"uppercase: %s, delimiter: \"%s\", prefix: \"%s\", suffix: \"%s\"",508uppercase, escapeNL(delimiter), escapeNL(prefix), escapeNL(suffix));509System.out.println(" hex: " + actual);510assertEquals(actual, hex.toString(), "Formatter toString mismatch");511}512513@Test(dataProvider="HexFormattersParsers")514static void testFormatterParameterMethods(String delimiter, String prefix, String suffix,515boolean uppercase,516HexFormat hex) {517assertEquals(hex.delimiter(), delimiter);518assertEquals(hex.prefix(), prefix);519assertEquals(hex.suffix(), suffix);520assertEquals(hex.isUpperCase(), uppercase);521}522523@Test(dataProvider="HexFormattersParsers")524static void testFormatterTestEquals(String delimiter, String prefix, String suffix,525boolean uppercase,526HexFormat expected) {527HexFormat actual = HexFormat.of()528.withDelimiter(delimiter)529.withPrefix(prefix)530.withSuffix(suffix);531actual = uppercase ? actual.withUpperCase() : actual.withLowerCase();532533assertEquals(actual.delimiter(), delimiter, "delimiter");534assertEquals(actual.prefix(), prefix, "prefix");535assertEquals(actual.suffix(), suffix, "suffix");536assertEquals(actual.isUpperCase(), uppercase, "uppercase");537assertTrue(actual.equals(expected), "equals method");538assertEquals(actual.hashCode(), expected.hashCode(), "hashCode");539540assertTrue(actual.equals(actual)); // equals self541assertFalse(actual.equals(null)); // never equals null542}543544@Test(dataProvider="HexFormattersParsers")545static void testZeroLength(String delimiter, String prefix, String suffix, boolean uppercase,546HexFormat hex) {547// Test formatting of zero length byte arrays, should produce no output548StringBuilder sb = new StringBuilder();549assertEquals(hex.formatHex(new byte[0]), "", "Zero length");550assertEquals(hex.formatHex(new byte[0], 0, 0), "", "Zero length");551552hex.formatHex(sb, new byte[0]);553assertEquals(sb.length(), 0, "length should not change");554hex.formatHex(sb, new byte[0], 0, 0);555assertEquals(sb.length(), 0, "length should not change");556557}558private static String escapeNL(String string) {559return string.replace("\n", "\\n")560.replace("\r", "\\r");561}562563@Test564static void testfromHexDigitsToInt() {565HexFormat hex = HexFormat.of();566567String allHex = "76543210";568final int orig = 0x76543210;569for (int digits = 0; digits <= 8; digits++) {570String s = hex.toHexDigits(orig, digits);571long actual = HexFormat.fromHexDigits(s, 0, digits);572System.out.printf(" digits: %2d, formatted: \"%s\", parsed as: 0x%08x%n",573digits, s, actual);574assertEquals(s, allHex.substring(8 - digits, 8));575long expected = (digits < 8) ? orig & ~(0xffffffff << (4 * digits)) : orig;576assertEquals(actual, expected);577}578}579580@Test581static void testfromHexDigitsToLong() {582HexFormat hex = HexFormat.of();583584String allHex = "fedcba9876543210";585final long orig = 0xfedcba9876543210L;586for (int digits = 0; digits <= 16; digits++) {587String s = hex.toHexDigits(orig, digits);588long actual = HexFormat.fromHexDigitsToLong(s, 0, digits);589System.out.printf(" digits: %2d, formatted: \"%s\", parsed as: 0x%016xL%n",590digits, s, actual);591assertEquals(s, allHex.substring(16 - digits, 16));592long expected = (digits < 16) ? orig & ~(0xffffffffffffffffL << (4 * digits)) : orig;593assertEquals(actual, expected);594}595}596597@Test598static void testToHexDigitsLong() {599HexFormat hex = HexFormat.of();600601String allHex = "fedcba9876543210";602final long expected = 0xfedcba9876543210L;603String s = hex.toHexDigits(expected);604long actual = HexFormat.fromHexDigitsToLong(s);605System.out.printf(" formatted: \"%s\", parsed as: 0x%016xL%n", s, actual);606assertEquals(s, allHex);607assertEquals(actual, expected);608}609610@Test(dataProvider="HexFormattersParsers")611static void testIOException(String delimiter, String prefix, String suffix, boolean uppercase,612HexFormat hex) {613Appendable throwingAppendable = new ThrowingAppendable();614assertThrows(UncheckedIOException.class,615() -> hex.formatHex(throwingAppendable, new byte[1]));616assertThrows(UncheckedIOException.class,617() -> hex.formatHex(throwingAppendable, new byte[1], 0, 1));618assertThrows(UncheckedIOException.class,619() -> hex.toHexDigits(throwingAppendable, (byte)1));620}621622@Test(dataProvider="HexFormattersParsers")623static void testOOME(String delimiter, String prefix, String suffix, boolean uppercase,624HexFormat hex) {625// compute the size of byte array that will exceed the buffer626long valueChars = prefix.length() + 2 + suffix.length();627long stride = valueChars + delimiter.length();628long max = Integer.MAX_VALUE & 0xFFFFFFFFL;629long len = max / stride;630long remainder = max - ((len - 1) * stride);631if (remainder > valueChars) {632len++;633remainder -= valueChars;634}635try {636byte[] bytes = new byte[(int) len];637Throwable ex = expectThrows(OutOfMemoryError.class,638() -> hex.formatHex(bytes));639System.out.println("ex: " + ex);640} catch (OutOfMemoryError oome) {641System.out.printf("OOME: total mem: %08x, free mem: %08x, max mem: %08x%n",642Runtime.getRuntime().totalMemory(),643Runtime.getRuntime().freeMemory(),644Runtime.getRuntime().maxMemory());645throw new SkipException("Insufficient Memory to test OOME");646}647648}649650/**651* Example code from the HexFormat javadoc.652* Showing simple usage of the API using "assert" to express the correct results653* when shown in the javadoc.654* The additional TestNG asserts verify the correctness of the same code.655*/656@Test657private static void samples() {658{659// Primitive formatting and parsing.660HexFormat hex = HexFormat.of();661662byte b = 127;663String byteStr = hex.toHexDigits(b);664System.out.println(" " + byteStr);665666byte byteVal = (byte) HexFormat.fromHexDigits(byteStr);667assert(byteStr.equals("7f"));668assert(b == byteVal);669assertTrue(byteStr.equals("7f"));670assertTrue(b == byteVal);671672673char c = 'A';674String charStr = hex.toHexDigits(c);675System.out.println(" " + charStr);676int charVal = HexFormat.fromHexDigits(charStr);677assert(c == charVal);678assertTrue(c == charVal);679680int i = 12345;681String intStr = hex.toHexDigits(i);682System.out.println(" " + intStr);683int intVal = HexFormat.fromHexDigits(intStr);684assert(i == intVal);685assertTrue(i == intVal);686687long l = Long.MAX_VALUE;688String longStr = hex.toHexDigits(l, 16);689long longVal = HexFormat.fromHexDigitsToLong(longStr, 0, 16);690System.out.println(" " + longStr + ", " + longVal);691assert(l == longVal);692assertTrue(l == longVal);693}694695{696// RFC 4752 Fingerprint697HexFormat formatFingerprint = HexFormat.ofDelimiter(":").withUpperCase();698byte[] bytes = {0, 1, 2, 3, 124, 125, 126, 127};699String str = formatFingerprint.formatHex(bytes);700System.out.println(" Formatted: " + str);701702byte[] parsed = formatFingerprint.parseHex(str);703System.out.println(" Parsed: " + Arrays.toString(parsed));704assert(Arrays.equals(bytes, parsed));705assertTrue(Arrays.equals(bytes, parsed));706}707708{709// Comma separated formatting710HexFormat commaFormat = HexFormat.ofDelimiter(",");711byte[] bytes = {0, 1, 2, 3, 124, 125, 126, 127};712String str = commaFormat.formatHex(bytes);713System.out.println(" Formatted: " + str);714715byte[] parsed = commaFormat.parseHex(str);716System.out.println(" Parsed: " + Arrays.toString(parsed));717assert(Arrays.equals(bytes, parsed));718assertTrue(Arrays.equals(bytes, parsed));719}720{721// Text formatting722HexFormat commaFormat = HexFormat.ofDelimiter(", ").withPrefix("#");723byte[] bytes = {0, 1, 2, 3, 124, 125, 126, 127};724String str = commaFormat.formatHex(bytes);725System.out.println(" Formatted: " + str);726727byte[] parsed = commaFormat.parseHex(str);728System.out.println(" Parsed: " + Arrays.toString(parsed));729assert(Arrays.equals(bytes, parsed));730assertTrue(Arrays.equals(bytes, parsed));731}732}733734/**735* A test implementation of Appendable that throws IOException on all methods.736*/737static class ThrowingAppendable implements Appendable {738@Override739public Appendable append(CharSequence csq) throws IOException {740throw new IOException(".append(CharSequence) always throws");741}742743@Override744public Appendable append(CharSequence csq, int start, int end) throws IOException {745throw new IOException(".append(CharSequence, start, end) always throws");746}747748@Override749public Appendable append(char c) throws IOException {750throw new IOException(".append(char) always throws");751}752}753}754755756