8243010: Test support: Customizable Hex Printer

Reviewed-by: lancea, dfuchs, weijun
This commit is contained in:
Roger Riggs 2020-04-16 15:45:37 -04:00
parent d2e0d0e06a
commit bdf672659c
16 changed files with 1657 additions and 60 deletions

View File

@ -163,9 +163,6 @@ public class Base64Test {
*/
private static void deserialize(byte[] bytes) throws Exception {
//System.out.println("\nSerialized RefAddr object: ");
//System.out.println(new sun.security.util.HexDumpEncoder().encode(bytes));
ObjectInputStream objectStream =
new ObjectInputStream(new ByteArrayInputStream(bytes));
Object object = objectStream.readObject();

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2010, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -24,6 +24,7 @@
/*
* @test
* @bug 6911951 7150092
* @library /test/lib
* @summary NTLM should be a supported Java SASL mechanism
* @modules java.base/sun.security.util
* java.security.sasl
@ -32,7 +33,7 @@ import java.io.IOException;
import javax.security.sasl.*;
import javax.security.auth.callback.*;
import java.util.*;
import sun.security.util.HexDumpEncoder;
import jdk.test.lib.hexdump.HexPrinter;
public class NTLMTest {
@ -312,7 +313,7 @@ public class NTLMTest {
byte[] response = (clnt.hasInitialResponse()
? clnt.evaluateChallenge(EMPTY) : EMPTY);
System.out.println("Initial:");
new HexDumpEncoder().encodeBuffer(response, System.out);
HexPrinter.simple().format(response);
byte[] challenge;
while (!clnt.isComplete() || !srv.isComplete()) {
@ -320,12 +321,12 @@ public class NTLMTest {
response = null;
if (challenge != null) {
System.out.println("Challenge:");
new HexDumpEncoder().encodeBuffer(challenge, System.out);
HexPrinter.simple().format(challenge);
response = clnt.evaluateChallenge(challenge);
}
if (response != null) {
System.out.println("Response:");
new HexDumpEncoder().encodeBuffer(response, System.out);
HexPrinter.simple().format(response);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -43,7 +43,7 @@ import jdk.test.lib.security.SSLContextBuilder;
import java.util.concurrent.*;
import sun.security.util.HexDumpEncoder;
import jdk.test.lib.hexdump.HexPrinter;
/**
* An example to show the way to use SSLEngine in datagram connections.
@ -688,12 +688,11 @@ public class DTLSOverDatagram {
}
final static void printHex(String prefix, ByteBuffer bb) {
HexDumpEncoder dump = new HexDumpEncoder();
synchronized (System.out) {
System.out.println(prefix);
try {
dump.encodeBuffer(bb.slice(), System.out);
HexPrinter.simple().format(bb.slice());
} catch (Exception e) {
// ignore
}
@ -704,13 +703,10 @@ public class DTLSOverDatagram {
final static void printHex(String prefix,
byte[] bytes, int offset, int length) {
HexDumpEncoder dump = new HexDumpEncoder();
synchronized (System.out) {
System.out.println(prefix);
try {
ByteBuffer bb = ByteBuffer.wrap(bytes, offset, length);
dump.encodeBuffer(bb, System.out);
HexPrinter.simple().format(bytes, offset, length);
} catch (Exception e) {
// ignore
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -30,13 +30,15 @@
* @test
* @bug 8215790 8219389
* @summary Verify exception
* @library /test/lib
* @modules java.base/sun.security.util
* @run main/othervm ClientHelloBufferUnderflowException
*/
import sun.security.util.HexDumpEncoder;
import javax.net.ssl.SSLHandshakeException;
import jdk.test.lib.hexdump.HexPrinter;
public class ClientHelloBufferUnderflowException extends ClientHelloInterOp {
/*
* Main entry point for this test.
@ -75,7 +77,7 @@ public class ClientHelloBufferUnderflowException extends ClientHelloInterOp {
System.out.println("The ClientHello message used");
try {
(new HexDumpEncoder()).encodeBuffer(bytes, System.out);
HexPrinter.simple().format(bytes);
} catch (Exception e) {
// ignore
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -30,13 +30,15 @@
* @test
* @bug 8169362
* @summary Interop automated testing with Chrome
* @library /test/lib
* @modules jdk.crypto.ec
* java.base/sun.security.util
* @run main/othervm ClientHelloChromeInterOp
*/
import java.util.Base64;
import sun.security.util.HexDumpEncoder;
import jdk.test.lib.hexdump.HexPrinter;
public class ClientHelloChromeInterOp extends ClientHelloInterOp {
// The ClientHello message.
@ -63,10 +65,9 @@ public class ClientHelloChromeInterOp extends ClientHelloInterOp {
// Dump the hex codes of the ClientHello message so that developers
// can easily check whether the message is captured correct or not.
HexDumpEncoder dump = new HexDumpEncoder();
System.out.println("The ClientHello message used");
try {
dump.encodeBuffer(bytes, System.out);
HexPrinter.simple().format(bytes);
} catch (Exception e) {
// ignore
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -32,7 +32,7 @@
*/
import sun.security.jgss.GSSUtil;
import sun.security.util.HexDumpEncoder;
import jdk.test.lib.hexdump.HexPrinter;
// The basic krb5 test skeleton you can copy from
public class MSOID2 {
@ -72,7 +72,7 @@ public class MSOID2 {
nt[pos] = (byte)newLen;
}
t = nt;
new HexDumpEncoder().encodeBuffer(t, System.out);
HexPrinter.simple().format(t);
}
if (t != null || !s.x().isEstablished()) t = s.take(t);
if (c.x().isEstablished() && s.x().isEstablished()) break;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -23,6 +23,7 @@
/*
* @test
* @bug 8014628
* @library /test/lib
* @modules java.base/sun.security.util
* java.security.jgss/sun.security.krb5.internal.crypto.dk:+open
* @summary https://tools.ietf.org/html/rfc8009 Test Vectors
@ -33,7 +34,7 @@ import java.lang.reflect.Method;
import java.util.Arrays;
import sun.security.krb5.internal.crypto.dk.AesSha2DkCrypto;
import sun.security.util.HexDumpEncoder;
import jdk.test.lib.hexdump.HexPrinter;
public class KerberosAesSha2 {
@ -204,6 +205,6 @@ public class KerberosAesSha2 {
}
private static void dump(byte[] data) throws Exception {
new HexDumpEncoder().encodeBuffer(data, System.err);
HexPrinter.simple().dest(System.err).format(data);
}
}

View File

@ -35,7 +35,7 @@ import java.util.*;
import javax.crypto.*;
import jdk.test.lib.SecurityTools;
import sun.security.util.HexDumpEncoder;
import jdk.test.lib.hexdump.HexPrinter;
/*
* Confirm interoperability of RSA public keys between SunMSCAPI and SunJCE
@ -84,29 +84,29 @@ public class PublicKeyInterop {
System.out.println();
byte[] plain = new byte[] {0x01, 0x02, 0x03, 0x04, 0x05};
HexDumpEncoder hde = new HexDumpEncoder();
System.out.println("Plaintext:\n" + hde.encode(plain) + "\n");
HexPrinter hp = HexPrinter.simple();
System.out.println("Plaintext:\n" + hp.toString(plain) + "\n");
Cipher rsa = Cipher.getInstance("RSA/ECB/PKCS1Padding");
rsa.init(Cipher.ENCRYPT_MODE, myPuKey);
byte[] encrypted = rsa.doFinal(plain);
System.out.println("Encrypted plaintext using RSA Cipher from " +
rsa.getProvider().getName() + " JCE provider\n");
System.out.println(hde.encode(encrypted) + "\n");
System.out.println(hp.toString(encrypted) + "\n");
Cipher rsa2 = Cipher.getInstance("RSA/ECB/PKCS1Padding", "SunMSCAPI");
rsa2.init(Cipher.ENCRYPT_MODE, myPuKey);
byte[] encrypted2 = rsa2.doFinal(plain);
System.out.println("Encrypted plaintext using RSA Cipher from " +
rsa2.getProvider().getName() + " JCE provider\n");
System.out.println(hde.encode(encrypted2) + "\n");
System.out.println(hp.toString(encrypted2) + "\n");
Cipher rsa3 = Cipher.getInstance("RSA/ECB/PKCS1Padding", "SunMSCAPI");
rsa3.init(Cipher.DECRYPT_MODE, myPrKey);
byte[] decrypted = rsa3.doFinal(encrypted);
System.out.println("Decrypted first ciphertext using RSA Cipher from " +
rsa3.getProvider().getName() + " JCE provider\n");
System.out.println(hde.encode(decrypted) + "\n");
System.out.println(hp.toString(decrypted) + "\n");
if (! Arrays.equals(plain, decrypted)) {
throw new Exception("First decrypted ciphertext does not match " +
"original plaintext");
@ -115,7 +115,7 @@ public class PublicKeyInterop {
decrypted = rsa3.doFinal(encrypted2);
System.out.println("Decrypted second ciphertext using RSA Cipher from "
+ rsa3.getProvider().getName() + " JCE provider\n");
System.out.println(hde.encode(decrypted) + "\n");
System.out.println(hp.toString(decrypted) + "\n");
if (! Arrays.equals(plain, decrypted)) {
throw new Exception("Second decrypted ciphertext does not match " +
"original plaintext");

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,6 +25,7 @@
* @test
* @bug 8048357
* @summary test PKCS7 data signing, encoding and verification
* @library /test/lib
* @modules java.base/sun.security.pkcs
* java.base/sun.security.util
* java.base/sun.security.x509
@ -40,7 +41,6 @@ import java.security.Signature;
import java.security.SignatureException;
import java.security.cert.X509Certificate;
import java.util.Date;
import sun.security.util.HexDumpEncoder;
import sun.security.pkcs.ContentInfo;
import sun.security.pkcs.PKCS7;
import sun.security.pkcs.SignerInfo;
@ -55,11 +55,10 @@ import sun.security.x509.X500Name;
import sun.security.x509.X509CertImpl;
import sun.security.x509.X509CertInfo;
import sun.security.x509.X509Key;
import jdk.test.lib.hexdump.HexPrinter;
public class SignerOrder {
static final HexDumpEncoder hexDump = new HexDumpEncoder();
//signer infos
static final byte[] data1 = "12345".getBytes();
static final byte[] data2 = "abcde".getBytes();
@ -120,7 +119,7 @@ public class SignerOrder {
signerInfo.derEncode(strm);
System.out.println("SignerInfo, length: "
+ strm.toByteArray().length);
System.out.println(hexDump.encode(strm.toByteArray()));
HexPrinter.simple().format(strm.toByteArray());
System.out.println("\n");
strm.reset();
}
@ -131,7 +130,7 @@ public class SignerOrder {
signerInfos[i].derEncode(strm);
System.out.println("SignerInfo[" + i + "], length: "
+ strm.toByteArray().length);
System.out.println(hexDump.encode(strm.toByteArray()));
HexPrinter.simple().format(strm.toByteArray());
System.out.println("\n");
strm.reset();
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,6 +25,7 @@
* @test
* @bug 8048357
* @summary PKCS8 Standards Conformance Tests
* @library /test/lib
* @requires (os.family != "solaris")
* @modules java.base/sun.security.pkcs
* java.base/sun.security.util
@ -42,18 +43,16 @@ import java.io.IOException;
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.util.Arrays;
import sun.security.util.HexDumpEncoder;
import sun.security.pkcs.PKCS8Key;
import sun.security.provider.DSAPrivateKey;
import sun.security.util.DerOutputStream;
import sun.security.util.DerValue;
import sun.security.x509.AlgorithmId;
import jdk.test.lib.hexdump.HexPrinter;
import static java.lang.System.out;
public class PKCS8Test {
static final HexDumpEncoder hexDump = new HexDumpEncoder();
static final DerOutputStream derOutput = new DerOutputStream();
static final String FORMAT = "PKCS#8";
@ -281,6 +280,6 @@ public class PKCS8Test {
static void dumpByteArray(String nm, byte[] bytes) throws IOException {
out.println(nm + " length: " + bytes.length);
hexDump.encodeBuffer(bytes, out);
HexPrinter.simple().dest(out).format(bytes);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,6 +25,7 @@
* @test
* @bug 8011867
* @summary Accept unknown PKCS #9 attributes
* @library /test/lib
* @modules java.base/sun.security.pkcs
* java.base/sun.security.util
*/
@ -32,10 +33,10 @@
import java.io.*;
import java.util.Arrays;
import sun.security.util.HexDumpEncoder;
import sun.security.pkcs.PKCS9Attribute;
import sun.security.util.DerValue;
import sun.security.util.ObjectIdentifier;
import jdk.test.lib.hexdump.HexPrinter;
public class UnknownAttribute {
@ -58,7 +59,7 @@ public class UnknownAttribute {
}
ByteArrayOutputStream bout = new ByteArrayOutputStream();
p2.derEncode(bout);
new HexDumpEncoder().encodeBuffer(bout.toByteArray(), System.err);
HexPrinter.simple().dest(System.err).format(bout.toByteArray());
if (!Arrays.equals(data, bout.toByteArray())) {
throw new Exception();
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -59,7 +59,7 @@ import java.util.Arrays;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;
import jdk.test.lib.Utils;
import sun.security.util.HexDumpEncoder;
import jdk.test.lib.hexdump.HexPrinter;
public class SSLSocketKeyLimit {
SSLSocket socket;
@ -212,7 +212,7 @@ public class SSLSocketKeyLimit {
if (b == 0x0A || b == 0x0D) {
continue;
}
System.out.println("\nData invalid: " + new HexDumpEncoder().encode(buf));
System.out.println("\nData invalid: " + HexPrinter.minimal().toString(buf));
break;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -24,6 +24,7 @@
/* @test
* @bug 4118818
* @summary allow null X.500 Names
* @library /test/lib
* @modules java.base/sun.security.util
* java.base/sun.security.x509
*/
@ -31,7 +32,7 @@
import java.util.Arrays;
import sun.security.util.DerOutputStream;
import sun.security.x509.*;
import sun.security.util.HexDumpEncoder;
import jdk.test.lib.hexdump.HexPrinter;
public class NullX500Name {
@ -63,16 +64,16 @@ public class NullX500Name {
subject.encode(dos);
byte[] out = dos.toByteArray();
byte[] enc = subject.getEncoded();
HexDumpEncoder e = new HexDumpEncoder();
HexPrinter e = HexPrinter.simple();
if (Arrays.equals(out, enc))
System.out.println("Sucess: out:" + e.encodeBuffer(out));
System.out.println("Success: out:" + e.toString(out));
else {
System.out.println("Failed: encode:" + e.encodeBuffer(out));
System.out.println("getEncoded:" + e.encodeBuffer(enc));
System.out.println("Failed: encode:" + e.toString(out));
System.out.println("getEncoded:" + e.toString(enc));
}
X500Name x = new X500Name(enc);
if (x.equals(subject))
System.out.println("Sucess: X500Name(byte[]):" + x.toString());
System.out.println("Success: X500Name(byte[]):" + x.toString());
else
System.out.println("Failed: X500Name(byte[]):" + x.toString());
}

9
test/lib-test/TEST.ROOT Normal file
View File

@ -0,0 +1,9 @@
# This file identifies the root of the test-suite hierarchy.
# It also contains test-suite configuration information.
# Minimum jtreg version
requiredVersion=5.0 b1
# Path to libraries in the topmost test directory. This is needed so @library
# does not need ../../ notation to reach them
external.lib.roots = ../../

View File

@ -0,0 +1,409 @@
/*
* Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.test.lib.hexdump;
import jdk.test.lib.hexdump.HexPrinter;
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
/*
* @test
* @summary Check HexPrinter formatting
* @library /test/lib
* @compile HexPrinterTest.java
* @run testng jdk.test.lib.hexdump.HexPrinterTest
*/
public class HexPrinterTest {
@Test
static void testMinimalToStringByteArray() {
int len = 16;
byte[] bytes = genData(len);
StringBuilder expected = new StringBuilder(bytes.length * 2);
for (int i = 0; i < len; i++)
expected.append(String.format("%02x", bytes[i]));
String actual = HexPrinter.minimal().toString(bytes);
System.out.println(actual);
Assert.assertEquals(actual, expected.toString(), "Minimal format incorrect");
}
@DataProvider(name = "ColumnParams")
Object[][] columnParams() {
return new Object[][]{
{"%4d: ", "%d ", 10, " ; ", 50, HexPrinter.Formatters.PRINTABLE, "\n"},
{"%03o: ", "%d ", 16, " ; ", 50, HexPrinter.Formatters.ofPrimitive(byte.class, ""), "\n"},
{"%5d: ", "%02x:", 16, " ; ", 50, HexPrinter.Formatters.ofPrimitive(byte.class, ""), "\n"},
{"%5d: ", "%3d", 16, " ; ", 50, HexPrinter.Formatters.ofPrimitive(byte.class, ""), "\n"},
{"%05o: ", "%3o", 8, " ; ", 50, HexPrinter.Formatters.ofPrimitive(byte.class, ""), "\n"},
{"%6x: ", "%02x", 8, " | ", 50, HexPrinter.Formatters.ofPrimitive(byte.class, "%d "), "\n"},
{"%2x: ", "%02x", 8, " | ", 50, HexPrinter.Formatters.PRINTABLE, "\n"},
{"%5d: ", "%02x", 16, " | ", 50, HexPrinter.Formatters.ofPrimitive(short.class, "%d "), "\n"},
};
}
@DataProvider(name = "BuiltinParams")
Object[][] builtinParams() {
return new Object[][]{
{"minimal", "", "%02x", 16, "", 64, HexPrinter.Formatters.NONE, ""},
{"canonical", "%08x ", "%02x ", 16, "|", 31, HexPrinter.Formatters.ASCII, "|\n"},
{"simple", "%5d: ", "%02x ", 16, " // ", 64, HexPrinter.Formatters.PRINTABLE, "\n"},
{"source", " ", "(byte)%3d, ", 8, " // ", 64, HexPrinter.Formatters.PRINTABLE,
"\n"},
};
}
@Test(dataProvider = "BuiltinParams")
public void testBuiltins(String name, String offsetFormat, String binFormat, int colWidth,
String annoDelim, int annoWidth,
HexPrinter.Formatter mapper, String lineSep) {
HexPrinter f = switch (name) {
case "minimal" -> HexPrinter.minimal();
case "simple" -> HexPrinter.simple();
case "canonical" -> HexPrinter.canonical();
case "source" -> HexPrinter.source();
default -> throw new IllegalStateException("Unexpected value: " + name);
};
testParams(f, offsetFormat, binFormat, colWidth, annoDelim, annoWidth, mapper, lineSep);
String actual = f.toString();
HexPrinter f2 = HexPrinter.simple()
.withOffsetFormat(offsetFormat)
.withBytesFormat(binFormat, colWidth)
.formatter(mapper, annoDelim, annoWidth)
.withLineSeparator(lineSep);
String expected = f2.toString();
Assert.assertEquals(actual, expected, "toString of " + name + " does not match");
}
@Test(dataProvider = "ColumnParams")
public void testToStringTwoLines(String offsetFormat, String binFormat, int colWidth,
String annoDelim, int annoWidth,
HexPrinter.Formatter mapper, String lineSep) {
HexPrinter f = HexPrinter.simple()
.withOffsetFormat(offsetFormat)
.withBytesFormat(binFormat, colWidth)
.formatter(mapper, annoDelim, annoWidth)
.withLineSeparator(lineSep);
testParams(f, offsetFormat, binFormat, colWidth, annoDelim, annoWidth, mapper, lineSep);
}
public static void testParams(HexPrinter printer, String offsetFormat, String binFormat, int colWidth,
String annoDelim, int annoWidth,
HexPrinter.Formatter mapper, String lineSep) {
byte[] bytes = genData(colWidth * 2);
System.out.println("Params: " + printer.toString());
String out = printer.toString(bytes);
System.out.println(out);
// Compare the actual output with the expected output of each formatting element
int padToWidth = colWidth * String.format(binFormat, 0xff).length();
int ndx = 0;
int valuesStart = 0;
int l;
for (int i = 0; i < bytes.length; i++) {
if (i % colWidth == 0) {
String offset = String.format(offsetFormat, i);
l = offset.length();
Assert.assertEquals(out.substring(ndx, ndx + l), offset,
"offset format mismatch: " + ndx);
ndx += l;
valuesStart = ndx;
}
String value = String.format(binFormat, (0xff & bytes[i]));
l = value.length();
Assert.assertEquals(out.substring(ndx, ndx + l), value,
"value format mismatch: " + ndx + ", i: " + i);
ndx += l;
if (((i + 1) % colWidth) == 0) {
// Rest of line is for padding, delimiter, formatter
String padding = " ".repeat(padToWidth - (ndx - valuesStart));
Assert.assertEquals(out.substring(ndx, ndx + padding.length()), padding, "padding");
ndx += padding.length();
Assert.assertEquals(out.substring(ndx, ndx + annoDelim.length()), annoDelim,
"delimiter mismatch");
ndx += annoDelim.length();
// Formatter output is tested separately
ndx = out.indexOf(lineSep, ndx) + lineSep.length();
}
}
}
@DataProvider(name = "PrimitiveFormatters")
Object[][] formatterParams() {
return new Object[][]{
{byte.class, ""},
{byte.class, "%02x: "},
{short.class, "%d "},
{int.class, "%08x, "},
{long.class, "%16x "},
{float.class, "%3.4f "},
{double.class, "%6.3g "},
{boolean.class, "%b "},
};
}
@Test(dataProvider = "PrimitiveFormatters")
public void testFormatter(Class<?> primClass, String fmtString) {
HexPrinter.Formatter formatter = HexPrinter.Formatters.ofPrimitive(primClass, fmtString);
// Create a byte array with data for two lines
int colWidth = 8;
byte[] bytes = genData(colWidth);
StringBuilder sb = new StringBuilder();
DataInputStream in = new DataInputStream(new ByteArrayInputStream(bytes));
DataInputStream in2 = new DataInputStream(new ByteArrayInputStream(bytes));
try {
while (true) {
formatter.annotate(in, sb);
Object n = readPrimitive(primClass, in2);
String expected = String.format(fmtString, n);
Assert.assertEquals(sb.toString(), expected, "mismatch");
sb.setLength(0);
}
} catch (IOException ioe) {
// EOF is done
}
try {
Assert.assertEquals(in.available(), 0, "not all input consumed");
Assert.assertEquals(in2.available(), 0, "not all 2nd stream input consumed");
} catch (IOException ioe) {
//
}
}
@Test(dataProvider = "PrimitiveFormatters")
static void testHexPrinterPrimFormatter(Class<?> primClass, String fmtString) {
// Create a byte array with data for two lines
int colWidth = 8;
byte[] bytes = genData(colWidth);
HexPrinter p = HexPrinter.simple()
.formatter(primClass, fmtString);
String actual = p.toString(bytes);
System.out.println(actual);
// The formatter should produce the same output as using the formatter method
// with an explicit formatter for the primitive
String expected = HexPrinter.simple()
.formatter(HexPrinter.Formatters.ofPrimitive(primClass, fmtString))
.toString(bytes);
Assert.assertEquals(actual, expected, "mismatch");
}
private static Object readPrimitive(Class<?> primClass, DataInputStream in) throws IOException {
if (int.class.equals(primClass)) {
return in.readInt();
} else if (byte.class.equals(primClass)) {
return (int) in.readByte();
} else if (short.class.equals(primClass)) {
return in.readShort();
} else if (char.class.equals(primClass)) {
return in.readChar();
} else if (long.class.equals(primClass)) {
return in.readLong();
} else if (float.class.equals(primClass)) {
return in.readFloat();
} else if (double.class.equals(primClass)) {
return in.readDouble();
} else if (boolean.class.equals(primClass)) {
return in.readBoolean();
} else {
throw new RuntimeException("unknown primitive class: " + primClass);
}
}
@DataProvider(name = "sources")
Object[][] sources() {
return new Object[][]{
{genBytes(21), 0, -1},
{genBytes(21), 5, 12},
};
}
public static byte[] genData(int len) {
// Create a byte array with data for two lines
byte[] bytes = new byte[len];
for (int i = 0; i < len / 2; i++) {
bytes[i] = (byte) (i + 'A');
bytes[i + len / 2] = (byte) (i + 'A' + 128);
}
return bytes;
}
public static byte[] genFloat(int len) {
byte[] bytes = null;
try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream out = new DataOutputStream(baos)) {
for (int i = 0; i < len; i++) {
out.writeFloat(i);
}
bytes = baos.toByteArray();
} catch (IOException unused) {
}
return bytes;
}
public static byte[] genDouble(int len) {
byte[] bytes = null;
try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream out = new DataOutputStream(baos)) {
for (int i = 0; i < len; i++) {
out.writeDouble(i);
}
bytes = baos.toByteArray();
} catch (IOException unused) {
}
return bytes;
}
public static byte[] genBytes(int len) {
byte[] bytes = new byte[len];
for (int i = 0; i < len; i++)
bytes[i] = (byte) ('A' + i);
return bytes;
}
public ByteBuffer genByteBuffer(int len) {
return ByteBuffer.wrap(genBytes(len));
}
public InputStream genInputStream(int len) {
return new ByteArrayInputStream(genBytes(len));
}
@Test
public void testNilPrinterBigBuffer() {
byte[] bytes = new byte[1024];
HexPrinter p = HexPrinter.minimal();
String r = p.toString(bytes);
Assert.assertEquals(r.length(), bytes.length * 2, "encoded byte wrong size");
Assert.assertEquals(r.replace("00", "").length(), 0, "contents not all zeros");
}
@Test(dataProvider = "sources")
public void testToStringByteBuffer(byte[] bytes, int offset, int length) {
if (length < 0)
length = bytes.length - offset;
ByteBuffer bb = ByteBuffer.wrap(bytes, 0, bytes.length);
System.out.printf("Source: %s, off: %d, len: %d%n",
bytes.getClass().getName(), offset, length);
String actual;
if (offset == 0 && length < 0) {
bb.position(offset);
bb.limit(length);
actual = HexPrinter.simple().toString(bb);
} else
actual = HexPrinter.simple().toString(bb, offset, length);
System.out.println(actual);
String expected = HexPrinter.simple().toString(bytes, offset, length);
Assert.assertEquals(actual, expected, "mismatch in format()");
}
@Test(dataProvider = "sources")
public void testFormatBytes(byte[] bytes, int offset, int length) {
int len = length >= 0 ? length : bytes.length;
System.out.printf("Source: %s, off: %d, len: %d%n",
"bytes", offset, len);
StringBuilder sb = new StringBuilder();
if (offset == 0 && length < 0)
HexPrinter.simple().dest(sb).format(bytes);
else
HexPrinter.simple().dest(sb).format(bytes, offset, len);
String actual = sb.toString();
System.out.println(actual);
String expected = HexPrinter.simple().toString(bytes, offset, len);
Assert.assertEquals(actual, expected, "mismatch in format()");
}
@Test(dataProvider = "sources")
public void testFormatByteBuffer(byte[] bytes, int offset, int length) {
if (length < 0)
length = bytes.length - offset;
ByteBuffer bb = ByteBuffer.wrap(bytes, 0, bytes.length);
System.out.printf("Source: %s, off: %d, len: %d%n",
bytes.getClass().getName(), offset, length);
StringBuilder sb = new StringBuilder();
if (offset == 0 && length < 0) {
bb.position(offset);
bb.limit(length);
HexPrinter.simple().dest(sb).format(bb);
} else
HexPrinter.simple().dest(sb).format(bb, offset, length);
String actual = sb.toString();
System.out.println(actual);
String expected = HexPrinter.simple().toString(bytes, offset, length);
Assert.assertEquals(actual, expected, "mismatch in format()");
}
@Test(dataProvider = "sources")
public void testFormatInputStream(byte[] bytes, int offset, int length) {
// Offset is ignored
InputStream is = new ByteArrayInputStream(bytes, 0, length);
StringBuilder sb = new StringBuilder();
System.out.printf("Source: %s, off: %d, len: %d%n",
bytes.getClass().getName(), offset, length);
HexPrinter.simple().dest(sb).format(is);
String actual = sb.toString();
System.out.println(actual);
String expected = HexPrinter.simple().toString(bytes, 0, length);
Assert.assertEquals(actual, expected, "mismatch in format()");
}
@Test(expectedExceptions = NullPointerException.class)
public void testNullByteArray() {
HexPrinter.simple().dest(System.out).format((byte[]) null);
}
@Test(expectedExceptions = NullPointerException.class)
public void testNullByteArrayOff() {
HexPrinter.simple().dest(System.out).format((byte[]) null, 0, 1);
}
@Test(expectedExceptions = NullPointerException.class)
public void testNullByteBuffer() {
HexPrinter.simple().dest(System.out).format((ByteBuffer) null);
}
@Test(expectedExceptions = NullPointerException.class)
public void testNullByteBufferOff() {
HexPrinter.simple().dest(System.out).format((ByteBuffer) null, 0, 1);
}
@Test(expectedExceptions = NullPointerException.class)
public void testNullInputStream() {
HexPrinter.simple().dest(System.out).format((InputStream) null);
}
}

File diff suppressed because it is too large Load Diff