/*
* Copyright (c) [2016] [ <ether.camp> ]
* This file is part of the ethereumJ library.
*
* The ethereumJ library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* The ethereumJ library 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the ethereumJ library. If not, see <http://www.gnu.org/licenses/>.
*/
package org.ethereum.util;
import org.junit.Assert;
import org.junit.Test;
import org.spongycastle.util.BigIntegers;
import org.spongycastle.util.encoders.Hex;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.*;
public class ByteUtilTest {
@Test
public void testAppendByte() {
byte[] bytes = "tes".getBytes();
byte b = 0x74;
Assert.assertArrayEquals("test".getBytes(), ByteUtil.appendByte(bytes, b));
}
@Test
public void testBigIntegerToBytes() {
byte[] expecteds = new byte[]{(byte) 0xff, (byte) 0xec, 0x78};
BigInteger b = BigInteger.valueOf(16772216);
byte[] actuals = ByteUtil.bigIntegerToBytes(b);
assertArrayEquals(expecteds, actuals);
}
@Test
public void testBigIntegerToBytesSign() {
{
BigInteger b = BigInteger.valueOf(-2);
byte[] actuals = ByteUtil.bigIntegerToBytesSigned(b, 8);
assertArrayEquals(Hex.decode("fffffffffffffffe"), actuals);
}
{
BigInteger b = BigInteger.valueOf(2);
byte[] actuals = ByteUtil.bigIntegerToBytesSigned(b, 8);
assertArrayEquals(Hex.decode("0000000000000002"), actuals);
}
{
BigInteger b = BigInteger.valueOf(0);
byte[] actuals = ByteUtil.bigIntegerToBytesSigned(b, 8);
assertArrayEquals(Hex.decode("0000000000000000"), actuals);
}
{
BigInteger b = new BigInteger("eeeeeeeeeeeeee", 16);
byte[] actuals = ByteUtil.bigIntegerToBytesSigned(b, 8);
assertArrayEquals(Hex.decode("00eeeeeeeeeeeeee"), actuals);
}
{
BigInteger b = new BigInteger("eeeeeeeeeeeeeeee", 16);
byte[] actuals = ByteUtil.bigIntegerToBytesSigned(b, 8);
assertArrayEquals(Hex.decode("eeeeeeeeeeeeeeee"), actuals);
}
}
@Test
public void testBigIntegerToBytesNegative() {
byte[] expecteds = new byte[]{(byte) 0xff, 0x0, 0x13, (byte) 0x88};
BigInteger b = BigInteger.valueOf(-16772216);
byte[] actuals = ByteUtil.bigIntegerToBytes(b);
assertArrayEquals(expecteds, actuals);
}
@Test
public void testBigIntegerToBytesZero() {
byte[] expecteds = new byte[]{0x00};
BigInteger b = BigInteger.ZERO;
byte[] actuals = ByteUtil.bigIntegerToBytes(b);
assertArrayEquals(expecteds, actuals);
}
@Test
public void testToHexString() {
assertEquals("", ByteUtil.toHexString(null));
}
@Test
public void testCalcPacketLength() {
byte[] test = new byte[]{0x0f, 0x10, 0x43};
byte[] expected = new byte[]{0x00, 0x00, 0x00, 0x03};
assertArrayEquals(expected, ByteUtil.calcPacketLength(test));
}
@Test
public void testByteArrayToInt() {
assertEquals(0, ByteUtil.byteArrayToInt(null));
assertEquals(0, ByteUtil.byteArrayToInt(new byte[0]));
// byte[] x = new byte[] { 5,1,7,0,8 };
// long start = System.currentTimeMillis();
// for (int i = 0; i < 100000000; i++) {
// ByteArray.read32bit(x, 0);
// }
// long end = System.currentTimeMillis();
// System.out.println(end - start + "ms");
//
// long start1 = System.currentTimeMillis();
// for (int i = 0; i < 100000000; i++) {
// new BigInteger(1, x).intValue();
// }
// long end1 = System.currentTimeMillis();
// System.out.println(end1 - start1 + "ms");
}
@Test
public void testNumBytes() {
String test1 = "0";
String test2 = "1";
String test3 = "1000000000"; //3B9ACA00
int expected1 = 1;
int expected2 = 1;
int expected3 = 4;
assertEquals(expected1, ByteUtil.numBytes(test1));
assertEquals(expected2, ByteUtil.numBytes(test2));
assertEquals(expected3, ByteUtil.numBytes(test3));
}
@Test
public void testStripLeadingZeroes() {
byte[] test1 = null;
byte[] test2 = new byte[]{};
byte[] test3 = new byte[]{0x00};
byte[] test4 = new byte[]{0x00, 0x01};
byte[] test5 = new byte[]{0x00, 0x00, 0x01};
byte[] expected1 = null;
byte[] expected2 = new byte[]{0};
byte[] expected3 = new byte[]{0};
byte[] expected4 = new byte[]{0x01};
byte[] expected5 = new byte[]{0x01};
assertArrayEquals(expected1, ByteUtil.stripLeadingZeroes(test1));
assertArrayEquals(expected2, ByteUtil.stripLeadingZeroes(test2));
assertArrayEquals(expected3, ByteUtil.stripLeadingZeroes(test3));
assertArrayEquals(expected4, ByteUtil.stripLeadingZeroes(test4));
assertArrayEquals(expected5, ByteUtil.stripLeadingZeroes(test5));
}
@Test
public void testMatchingNibbleLength1() {
// a larger than b
byte[] a = new byte[]{0x00, 0x01};
byte[] b = new byte[]{0x00};
int result = ByteUtil.matchingNibbleLength(a, b);
assertEquals(1, result);
}
@Test
public void testMatchingNibbleLength2() {
// b larger than a
byte[] a = new byte[]{0x00};
byte[] b = new byte[]{0x00, 0x01};
int result = ByteUtil.matchingNibbleLength(a, b);
assertEquals(1, result);
}
@Test
public void testMatchingNibbleLength3() {
// a and b the same length equal
byte[] a = new byte[]{0x00};
byte[] b = new byte[]{0x00};
int result = ByteUtil.matchingNibbleLength(a, b);
assertEquals(1, result);
}
@Test
public void testMatchingNibbleLength4() {
// a and b the same length not equal
byte[] a = new byte[]{0x01};
byte[] b = new byte[]{0x00};
int result = ByteUtil.matchingNibbleLength(a, b);
assertEquals(0, result);
}
@Test
public void testNiceNiblesOutput_1() {
byte[] test = {7, 0, 7, 5, 7, 0, 7, 0, 7, 9};
String result = "\\x07\\x00\\x07\\x05\\x07\\x00\\x07\\x00\\x07\\x09";
assertEquals(result, ByteUtil.nibblesToPrettyString(test));
}
@Test
public void testNiceNiblesOutput_2() {
byte[] test = {7, 0, 7, 0xf, 7, 0, 0xa, 0, 7, 9};
String result = "\\x07\\x00\\x07\\x0f\\x07\\x00\\x0a\\x00\\x07\\x09";
assertEquals(result, ByteUtil.nibblesToPrettyString(test));
}
@Test(expected = NullPointerException.class)
public void testMatchingNibbleLength5() {
// a == null
byte[] a = null;
byte[] b = new byte[]{0x00};
ByteUtil.matchingNibbleLength(a, b);
}
@Test(expected = NullPointerException.class)
public void testMatchingNibbleLength6() {
// b == null
byte[] a = new byte[]{0x00};
byte[] b = null;
ByteUtil.matchingNibbleLength(a, b);
}
@Test
public void testMatchingNibbleLength7() {
// a or b is empty
byte[] a = new byte[0];
byte[] b = new byte[]{0x00};
int result = ByteUtil.matchingNibbleLength(a, b);
assertEquals(0, result);
}
/**
* This test shows the difference between iterating over,
* and comparing byte[] vs BigInteger value.
*
* Results indicate that the former has ~15x better performance.
* Therefore this is used in the Miner.mine() method.
*/
@Test
public void testIncrementPerformance() {
boolean testEnabled = false;
if (testEnabled) {
byte[] counter1 = new byte[4];
byte[] max = ByteBuffer.allocate(4).putInt(Integer.MAX_VALUE).array();
long start1 = System.currentTimeMillis();
while (ByteUtil.increment(counter1)) {
if (FastByteComparisons.compareTo(counter1, 0, 4, max, 0, 4) == 0) {
break;
}
}
System.out.println(System.currentTimeMillis() - start1 + "ms to reach: " + Hex.toHexString(counter1));
BigInteger counter2 = BigInteger.ZERO;
long start2 = System.currentTimeMillis();
while (true) {
if (counter2.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) == 0) {
break;
}
counter2 = counter2.add(BigInteger.ONE);
}
System.out.println(System.currentTimeMillis() - start2 + "ms to reach: " + Hex.toHexString(BigIntegers.asUnsignedByteArray(4, counter2)));
}
}
@Test
public void firstNonZeroByte_1() {
byte[] data = Hex.decode("0000000000000000000000000000000000000000000000000000000000000000");
int result = ByteUtil.firstNonZeroByte(data);
assertEquals(-1, result);
}
@Test
public void firstNonZeroByte_2() {
byte[] data = Hex.decode("0000000000000000000000000000000000000000000000000000000000332211");
int result = ByteUtil.firstNonZeroByte(data);
assertEquals(29, result);
}
@Test
public void firstNonZeroByte_3() {
byte[] data = Hex.decode("2211009988776655443322110099887766554433221100998877665544332211");
int result = ByteUtil.firstNonZeroByte(data);
assertEquals(0, result);
}
@Test
public void setBitTest() {
/*
Set on
*/
byte[] data = ByteBuffer.allocate(4).putInt(0).array();
int posBit = 24;
int expected = 16777216;
int result = -1;
byte[] ret = ByteUtil.setBit(data, posBit, 1);
result = ByteUtil.byteArrayToInt(ret);
assertTrue(expected == result);
posBit = 25;
expected = 50331648;
ret = ByteUtil.setBit(data, posBit, 1);
result = ByteUtil.byteArrayToInt(ret);
assertTrue(expected == result);
posBit = 2;
expected = 50331652;
ret = ByteUtil.setBit(data, posBit, 1);
result = ByteUtil.byteArrayToInt(ret);
assertTrue(expected == result);
/*
Set off
*/
posBit = 24;
expected = 33554436;
ret = ByteUtil.setBit(data, posBit, 0);
result = ByteUtil.byteArrayToInt(ret);
assertTrue(expected == result);
posBit = 25;
expected = 4;
ret = ByteUtil.setBit(data, posBit, 0);
result = ByteUtil.byteArrayToInt(ret);
assertTrue(expected == result);
posBit = 2;
expected = 0;
ret = ByteUtil.setBit(data, posBit, 0);
result = ByteUtil.byteArrayToInt(ret);
assertTrue(expected == result);
}
@Test
public void getBitTest() {
byte[] data = ByteBuffer.allocate(4).putInt(0).array();
ByteUtil.setBit(data, 24, 1);
ByteUtil.setBit(data, 25, 1);
ByteUtil.setBit(data, 2, 1);
List<Integer> found = new ArrayList<>();
for (int i = 0; i < (data.length * 8); i++) {
int res = ByteUtil.getBit(data, i);
if (res == 1)
if (i != 24 && i != 25 && i != 2)
assertTrue(false);
else
found.add(i);
else {
if (i == 24 || i == 25 || i == 2)
assertTrue(false);
}
}
if (found.size() != 3)
assertTrue(false);
assertTrue(found.get(0) == 2);
assertTrue(found.get(1) == 24);
assertTrue(found.get(2) == 25);
}
@Test
public void numToBytesTest() {
byte[] bytes = ByteUtil.intToBytesNoLeadZeroes(-1);
assertArrayEquals(bytes, Hex.decode("ffffffff"));
bytes = ByteUtil.intToBytesNoLeadZeroes(1);
assertArrayEquals(bytes, Hex.decode("01"));
bytes = ByteUtil.intToBytesNoLeadZeroes(255);
assertArrayEquals(bytes, Hex.decode("ff"));
bytes = ByteUtil.intToBytesNoLeadZeroes(256);
assertArrayEquals(bytes, Hex.decode("0100"));
bytes = ByteUtil.intToBytesNoLeadZeroes(0);
assertArrayEquals(bytes, new byte[0]);
bytes = ByteUtil.intToBytes(-1);
assertArrayEquals(bytes, Hex.decode("ffffffff"));
bytes = ByteUtil.intToBytes(1);
assertArrayEquals(bytes, Hex.decode("00000001"));
bytes = ByteUtil.intToBytes(255);
assertArrayEquals(bytes, Hex.decode("000000ff"));
bytes = ByteUtil.intToBytes(256);
assertArrayEquals(bytes, Hex.decode("00000100"));
bytes = ByteUtil.intToBytes(0);
assertArrayEquals(bytes, Hex.decode("00000000"));
bytes = ByteUtil.longToBytesNoLeadZeroes(-1);
assertArrayEquals(bytes, Hex.decode("ffffffffffffffff"));
bytes = ByteUtil.longToBytesNoLeadZeroes(1);
assertArrayEquals(bytes, Hex.decode("01"));
bytes = ByteUtil.longToBytesNoLeadZeroes(255);
assertArrayEquals(bytes, Hex.decode("ff"));
bytes = ByteUtil.longToBytesNoLeadZeroes(1L << 32);
assertArrayEquals(bytes, Hex.decode("0100000000"));
bytes = ByteUtil.longToBytesNoLeadZeroes(0);
assertArrayEquals(bytes, new byte[0]);
bytes = ByteUtil.longToBytes(-1);
assertArrayEquals(bytes, Hex.decode("ffffffffffffffff"));
bytes = ByteUtil.longToBytes(1);
assertArrayEquals(bytes, Hex.decode("0000000000000001"));
bytes = ByteUtil.longToBytes(255);
assertArrayEquals(bytes, Hex.decode("00000000000000ff"));
bytes = ByteUtil.longToBytes(256);
assertArrayEquals(bytes, Hex.decode("0000000000000100"));
bytes = ByteUtil.longToBytes(0);
assertArrayEquals(bytes, Hex.decode("0000000000000000"));
}
@Test
public void testHexStringToBytes() {
{
String str = "0000";
byte[] actuals = ByteUtil.hexStringToBytes(str);
byte[] expected = new byte[] {0, 0};
assertArrayEquals(expected, actuals);
}
{
String str = "0x0000";
byte[] actuals = ByteUtil.hexStringToBytes(str);
byte[] expected = new byte[] {0, 0};
assertArrayEquals(expected, actuals);
}
{
String str = "0x45a6";
byte[] actuals = ByteUtil.hexStringToBytes(str);
byte[] expected = new byte[] {69, -90};
assertArrayEquals(expected, actuals);
}
{
String str = "1963093cee500c081443e1045c40264b670517af";
byte[] actuals = ByteUtil.hexStringToBytes(str);
byte[] expected = Hex.decode(str);
assertArrayEquals(expected, actuals);
}
{
String str = "0x"; // Empty
byte[] actuals = ByteUtil.hexStringToBytes(str);
byte[] expected = new byte[] {};
assertArrayEquals(expected, actuals);
}
{
String str = "0"; // Same as 0x00
byte[] actuals = ByteUtil.hexStringToBytes(str);
byte[] expected = new byte[] {0};
assertArrayEquals(expected, actuals);
}
{
String str = "0x00"; // This case shouldn't be empty array
byte[] actuals = ByteUtil.hexStringToBytes(str);
byte[] expected = new byte[] {0};
assertArrayEquals(expected, actuals);
}
{
String str = "0xd"; // Should work with odd length, adding leading 0
byte[] actuals = ByteUtil.hexStringToBytes(str);
byte[] expected = new byte[] {13};
assertArrayEquals(expected, actuals);
}
{
String str = "0xd0d"; // Should work with odd length, adding leading 0
byte[] actuals = ByteUtil.hexStringToBytes(str);
byte[] expected = new byte[] {13, 13};
assertArrayEquals(expected, actuals);
}
}
@Test
public void testIpConversion() {
String ip1 = "0.0.0.0";
byte[] ip1Bytes = ByteUtil.hostToBytes(ip1);
assertEquals(ip1, ByteUtil.bytesToIp(ip1Bytes));
String ip2 = "35.36.37.138";
byte[] ip2Bytes = ByteUtil.hostToBytes(ip2);
assertEquals(ip2, ByteUtil.bytesToIp(ip2Bytes));
String ip3 = "255.255.255.255";
byte[] ip3Bytes = ByteUtil.hostToBytes(ip3);
assertEquals(ip3, ByteUtil.bytesToIp(ip3Bytes));
// Fallback case
String ip4 = "255.255.255.256";
byte[] ip4Bytes = ByteUtil.hostToBytes(ip4);
assertEquals("0.0.0.0", ByteUtil.bytesToIp(ip4Bytes));
}
}