/*
* Copyright (c) 2008-2017, Hazelcast, Inc. All Rights Reserved.
*
* 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 com.hazelcast.nio;
import com.hazelcast.test.HazelcastSerialClassRunner;
import com.hazelcast.test.annotation.QuickTest;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.runner.RunWith;
import java.io.IOException;
import java.io.UTFDataFormatException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Random;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@RunWith(HazelcastSerialClassRunner.class)
@Category(QuickTest.class)
public class BitsTest {
private static Random random = new Random();
private static byte[] readBuffer;
@BeforeClass
public static void initBuffer() {
readBuffer = new byte[8];
random.nextBytes(readBuffer);
}
@Test
public void testReadCharBigEndian() {
testReadChar(true);
}
@Test
public void testReadCharLittleEndian() {
testReadChar(false);
}
private void testReadChar(boolean bigEndian) {
char ch1 = Bits.readChar(readBuffer, 0, bigEndian);
ByteBuffer buffer = getByteBuffer(bigEndian);
char ch2 = buffer.getChar();
assertEquals(ch2, ch1);
}
@Test
public void testReadShortBigEndian() {
testReadShort(true);
}
@Test
public void testReadShortLittleEndian() {
testReadShort(false);
}
private void testReadShort(boolean bigEndian) {
short s1 = Bits.readShort(readBuffer, 0, bigEndian);
ByteBuffer buffer = getByteBuffer(bigEndian);
short s2 = buffer.getShort();
assertEquals(s2, s1);
}
@Test
public void testReadIntBigEndian() {
testReadInt(true);
}
@Test
public void testReadIntLittleEndian() {
testReadInt(false);
}
private void testReadInt(boolean bigEndian) {
int i1 = Bits.readInt(readBuffer, 0, bigEndian);
ByteBuffer buffer = getByteBuffer(bigEndian);
int i2 = buffer.getInt();
assertEquals(i2, i1);
}
@Test
public void testReadLongBigEndian() {
testReadLong(true);
}
@Test
public void testReadLongLittleEndian() {
testReadLong(false);
}
private void testReadLong(boolean bigEndian) {
long l1 = Bits.readLong(readBuffer, 0, bigEndian);
ByteBuffer buffer = getByteBuffer(bigEndian);
long l2 = buffer.getLong();
assertEquals(l2, l1);
}
private static ByteBuffer getByteBuffer(boolean bigEndian) {
return ByteBuffer.wrap(BitsTest.readBuffer)
.order(bigEndian ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN);
}
@Test
public void testWriteCharBigEndian() {
testWriteChar(true);
}
@Test
public void testWriteCharLittleEndian() {
testWriteChar(false);
}
private void testWriteChar(boolean bigEndian) {
char c = (char) random.nextInt();
byte[] bb = new byte[2];
Bits.writeChar(bb, 0, c, bigEndian);
ByteBuffer byteBuffer = ByteBuffer.allocate(2);
byteBuffer.order(bigEndian ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN);
byteBuffer.putChar(c);
assertArrayEquals(byteBuffer.array(), bb);
}
@Test
public void testWriteShortBigEndian() {
testWriteShort(true);
}
@Test
public void testWriteShortLittleEndian() {
testWriteShort(false);
}
private void testWriteShort(boolean bigEndian) {
short c = (short) random.nextInt();
byte[] bb = new byte[2];
Bits.writeShort(bb, 0, c, bigEndian);
ByteBuffer byteBuffer = ByteBuffer.allocate(2);
byteBuffer.order(bigEndian ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN);
byteBuffer.putShort(c);
assertArrayEquals(byteBuffer.array(), bb);
}
@Test
public void testWriteIntBigEndian() {
testWriteInt(true);
}
@Test
public void testWriteIntLittleEndian() {
testWriteInt(false);
}
private void testWriteInt(boolean bigEndian) {
int c = random.nextInt();
byte[] bb = new byte[4];
Bits.writeInt(bb, 0, c, bigEndian);
ByteBuffer byteBuffer = ByteBuffer.allocate(4);
byteBuffer.order(bigEndian ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN);
byteBuffer.putInt(c);
assertArrayEquals(byteBuffer.array(), bb);
}
@Test
public void testWriteLongBigEndian() {
testWriteLong(true);
}
@Test
public void testWriteLongLittleEndian() {
testWriteLong(false);
}
private void testWriteLong(boolean bigEndian) {
long c = random.nextLong();
byte[] bb = new byte[8];
Bits.writeLong(bb, 0, c, bigEndian);
ByteBuffer byteBuffer = ByteBuffer.allocate(8);
byteBuffer.order(bigEndian ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN);
byteBuffer.putLong(c);
assertArrayEquals(byteBuffer.array(), bb);
}
@Test
public void testWriteUtf8Char() {
byte[] bytes = new byte[3];
char c1 = 0x0010; //1 byte
char c2 = 0x0080; //2 byte
char c3 = 0x0800; //3 byte
assertEquals(1, Bits.writeUtf8Char(bytes, 0, c1));
assertEquals(2, Bits.writeUtf8Char(bytes, 0, c2));
assertEquals(3, Bits.writeUtf8Char(bytes, 0, c3));
}
@Test
public void testReadUtf8Char() throws IOException {
byte[] bytes = new byte[6];
char c0 = 0x0010; //1 byte
char c1 = 0x0080; //2 byte
char c2 = 0x0800; //3 byte
Bits.writeUtf8Char(bytes, 0, c0);
Bits.writeUtf8Char(bytes, 1, c1);
Bits.writeUtf8Char(bytes, 3, c2);
char[] chars = new char[3];
Bits.readUtf8Char(bytes, 0, chars, 0);
Bits.readUtf8Char(bytes, 1, chars, 1);
Bits.readUtf8Char(bytes, 3, chars, 2);
assertEquals(c0, chars[0]);
assertEquals(c1, chars[1]);
assertEquals(c2, chars[2]);
}
@Test(expected = UTFDataFormatException.class)
public void testReadUtf8CharMalformedBytes() throws IOException {
byte[] bytes = new byte[]{(byte) 0xFF};
char[] chars = new char[1];
Bits.readUtf8Char(bytes, 0, chars, 0);
}
@Test
public void testSetBitByte() throws Exception {
byte b = 110;
b = Bits.setBit(b, 0);
assertEquals(111, b);
b = Bits.setBit(b, 7);
assertTrue(b < 0);
}
@Test
public void testClearBitByte() throws Exception {
byte b = 111;
b = Bits.clearBit(b, 0);
assertEquals(110, b);
b = -111;
b = Bits.clearBit(b, 7);
assertTrue(b > 0);
}
@Test
public void testInvertBitByte() throws Exception {
byte b = -111;
b = Bits.invertBit(b, 7);
assertTrue(b > 0);
}
@Test
public void testSetBitInteger() throws Exception {
int b = 110;
b = Bits.setBit(b, 0);
assertEquals(111, b);
b = Bits.setBit(b, 31);
assertTrue(b < 0);
}
@Test
public void testClearBitInteger() throws Exception {
int b = 111;
b = Bits.clearBit(b, 0);
assertEquals(110, b);
b = -111;
b = Bits.clearBit(b, 31);
assertTrue(b > 0);
}
@Test
public void testInvertBitInteger() throws Exception {
int b = -111111;
b = Bits.invertBit(b, 31);
assertTrue(b > 0);
}
@Test
public void testIsBitSet() throws Exception {
assertFalse(Bits.isBitSet(123, 31));
assertTrue(Bits.isBitSet(-123, 31));
assertFalse(Bits.isBitSet(222, 0));
assertTrue(Bits.isBitSet(221, 0));
}
@Test
public void testCombineToInt() throws Exception {
short x = (short) random.nextInt();
short y = (short) random.nextInt();
int k = Bits.combineToInt(x, y);
assertEquals(x, Bits.extractShort(k, false));
assertEquals(y, Bits.extractShort(k, true));
}
@Test
public void testCombineToLong() throws Exception {
int x = random.nextInt();
int y = random.nextInt();
long k = Bits.combineToLong(x, y);
assertEquals(x, Bits.extractInt(k, false));
assertEquals(y, Bits.extractInt(k, true));
}
}