/* * JBoss, Home of Professional Open Source. * Copyright 2015 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.wildfly.security.util; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import org.junit.Test; /** * Tests for Hex encoding and decoding. The expected results for these test cases have been * taken from the examples in <a href="https://tools.ietf.org/html/rfc4648">RFC 4648</a>. * * @author <a href="mailto:fjuma@redhat.com">Farah Juma</a> */ public class HexTest { @Test public void testEncodeEmpty() { CodePointIterator ci = CodePointIterator.ofString("").asLatin1().hexEncode(); String encoded = ci.drainToString(); assertEquals("", encoded); verifyBackwardIterationOfEncodedCharacters(ci, encoded); } @Test public void testEncodeRfcExample1() { CodePointIterator ci = CodePointIterator.ofString("f").asLatin1().hexEncode(); String encoded = ci.drainToString(); assertEquals("66", encoded); verifyBackwardIterationOfEncodedCharacters(ci, encoded); } @Test public void testEncodeRfcExample2() { CodePointIterator ci = CodePointIterator.ofString("fo").asLatin1().hexEncode(); String encoded = ci.drainToString(); assertEquals("666f", encoded); verifyBackwardIterationOfEncodedCharacters(ci, encoded); } @Test public void testEncodeRfcExample3() { CodePointIterator ci = CodePointIterator.ofString("foo").asLatin1().hexEncode(); String encoded = ci.drainToString(); assertEquals("666f6f", encoded); verifyBackwardIterationOfEncodedCharacters(ci, encoded); } @Test public void testEncodeRfcExample4() { CodePointIterator ci = CodePointIterator.ofString("foob").asLatin1().hexEncode(); String encoded = ci.drainToString(); assertEquals("666f6f62", encoded); verifyBackwardIterationOfEncodedCharacters(ci, encoded); } @Test public void testEncodeRfcExample5() { CodePointIterator ci = CodePointIterator.ofString("fooba").asLatin1().hexEncode(); String encoded = ci.drainToString(); assertEquals("666f6f6261", encoded); verifyBackwardIterationOfEncodedCharacters(ci, encoded); } @Test public void testEncodeRfcExample6() { CodePointIterator ci = CodePointIterator.ofString("foobar").asLatin1().hexEncode(); String encoded = ci.drainToString(); assertEquals("666f6f626172", encoded); verifyBackwardIterationOfEncodedCharacters(ci, encoded); } @Test public void testEncodeUpperCase() { CodePointIterator ci = ByteIterator.ofBytes(new byte[]{(byte) 0x1d, (byte) 0x34, (byte) 0xaf, (byte) 0xbc, (byte) 0x9e, (byte) 0x89}).hexEncode(true); String encoded = ci.drainToString(); assertEquals("1D34AFBC9E89", encoded); verifyBackwardIterationOfEncodedCharacters(ci, encoded); } @Test public void testEncodeWithFormatting() { assertEquals("66:6F:6F:62:61:72", CodePointIterator.ofString("foobar").asLatin1().hexEncode(true).drainToString(':', 2)); assertEquals("0x66 0x6F 0x6F 0x62 0x61 0x72", CodePointIterator.ofString("foobar").asLatin1().hexEncode(true).drainToString("0x", ' ', 2)); assertEquals("666F6F6261\n72666F6F62\n6172666F6F\n626172", CodePointIterator.ofString("foobarfoobarfoobar").asLatin1().hexEncode(true).drainToString('\n', 10)); } private void verifyBackwardIterationOfEncodedCharacters(CodePointIterator ci, String encoded) { int encodedSize = encoded.length(); for (int i = encodedSize - 1; i >= 0; i--) { assertTrue(ci.hasPrev()); assertEquals(encoded.charAt(i), ci.prev()); } } @Test public void testDecodeEmpty() throws Exception { ByteIterator bi = CodePointIterator.ofString("").hexDecode(); String decoded = bi.asUtf8String().drainToString(); assertEquals("", decoded); verifyBackwardIterationOfDecodedBytes(bi, decoded); } @Test public void testDecodeRfcExample1() throws Exception { ByteIterator bi = CodePointIterator.ofString("66").hexDecode(); String decoded = bi.asUtf8String().drainToString(); assertEquals("f", decoded); verifyBackwardIterationOfDecodedBytes(bi, decoded); } @Test public void testDecodeRfcExample2() throws Exception { ByteIterator bi = CodePointIterator.ofString("666f").hexDecode(); String decoded = bi.asUtf8String().drainToString(); assertEquals("fo", decoded); verifyBackwardIterationOfDecodedBytes(bi, decoded); } @Test public void testDecodeRfcExample3() throws Exception { ByteIterator bi = CodePointIterator.ofString("666f6f").hexDecode(); String decoded = bi.asUtf8String().drainToString(); assertEquals("foo", decoded); verifyBackwardIterationOfDecodedBytes(bi, decoded); } @Test public void testDecodeRfcExample4() throws Exception { ByteIterator bi = CodePointIterator.ofString("666f6f62").hexDecode(); String decoded = bi.asUtf8String().drainToString(); assertEquals("foob", decoded); verifyBackwardIterationOfDecodedBytes(bi, decoded); } @Test public void testDecodeRfcExample5() throws Exception { ByteIterator bi = CodePointIterator.ofString("666f6f6261").hexDecode(); String decoded = bi.asUtf8String().drainToString(); assertEquals("fooba", decoded); verifyBackwardIterationOfDecodedBytes(bi, decoded); } @Test public void testDecodeRfcExample6() throws Exception { ByteIterator bi = CodePointIterator.ofString("666f6f626172").hexDecode(); String decoded = bi.asUtf8String().drainToString(); assertEquals("foobar", decoded); verifyBackwardIterationOfDecodedBytes(bi, decoded); } @Test public void testDecodeUpperCase() throws Exception { ByteIterator bi = CodePointIterator.ofString("1D34AFBC9E89").hexDecode(); byte[] decoded = bi.drain(); assertArrayEquals(new byte[]{(byte) 0x1d, (byte) 0x34, (byte) 0xaf, (byte) 0xbc, (byte) 0x9e, (byte) 0x89}, decoded); verifyBackwardIterationOfDecodedBytes(bi, decoded); } @Test(expected=DecodeException.class) public void testDecodeInvalidCharacter() throws Exception { CodePointIterator.ofString("6h666f6f626172g").hexDecode().drain(); } @Test(expected=DecodeException.class) public void testDecodeInvalidLength() throws Exception { CodePointIterator.ofChars(new char[]{'1', 'F', 'A'}).hexDecode().drain(); } private void verifyBackwardIterationOfDecodedBytes(ByteIterator bi, String decoded) { int decodedSize = decoded.length(); for (int i = decodedSize - 1; i >= 0; i--) { assertTrue(bi.hasPrev()); assertEquals(decoded.charAt(i), bi.prev()); } } private void verifyBackwardIterationOfDecodedBytes(ByteIterator bi, byte[] decoded) { int decodedSize = decoded.length; for (int i = decodedSize - 1; i >= 0; i--) { assertTrue(bi.hasPrev()); assertEquals(decoded[i], (byte) bi.prev()); } } }