/*
Protocol Definition Language
Copyright (C) 2003-2006 Marcus Andersson
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program 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 for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* Created on Dec 18, 2006
*/
package net.sf.nmedit.jpdl;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* JUnit tests for {@link net.sf.nmedit.jpdl.BitStream}
*
* @author Christian Schneider
*/
public class BitStreamTest
{
@Test
public void testZeroBitCase()
{
BitStream bs;
// must not throw an exception
bs = new BitStream();
bs.getInt(0);
bs.append(0, 0);
bs = BitStream.wrap(new byte[10]);
bs.setPosition(bs.getSize());
bs.getInt(0);
bs.append(0, 0);
}
/**
* Test for {@link BitStream#unsignedByte(byte)}.
*/
@Test
public void testUnsignedByte()
{
// for each byte
for (byte b=Byte.MIN_VALUE;;b++)
{
// byte is in two's complement, we calculate
// the expected return value of the tested function
int expected = b>=0 ? (int) b : 256+(int)b;
// test if result of function and expected value are equal
assertTrue(BitStream.unsignedByte(b)==expected);
// all possible values are tested
if (b==Byte.MAX_VALUE)
break;
}
}
/**
* Test for {@link BitStream#b2i(byte, byte, byte, byte)}.
* Tests that <code>signum(b2i(b3,0,0,0))==signum(b3)</code> is always <code>true</code>.
*/
@Test
public void testB2iTestSignumCondition()
{
final byte p = (byte) 0;
for (byte b=Byte.MIN_VALUE;;b++)
{
assertTrue(Integer.signum(BitStream.b2i(b,p,p,p))==Integer.signum(b));
if (b==Byte.MAX_VALUE)
break;
}
}
/**
* Test for {@link BitStream#b2i(byte, byte, byte, byte)}.
*/
@Test
public void testB2i()
{
final byte p = (byte) 0;
byte a = (byte) 0xFF;
assertTrue(BitStream.b2i(p,p,p,p)==0);
assertTrue(BitStream.b2i(a,a,a,a)==0xFFFFFFFF);
}
/**
* Checks valid arguments {@link BitStream#ensureBitRange0to32(int)}
*/
@Test
public void testEnsureBitRange0to32()
{
for (int i=0;i<=32;i++)
BitStream.ensureBitRange0to32(i);
}
/**
* Checks invalid arguments {@link BitStream#ensureBitRange0to32(int)}
*/
@Test(expected=IllegalArgumentException.class)
public void testEnsureBitRange0to32Invalid1()
{
BitStream.ensureBitRange0to32(-1);
}
/**
* Checks invalid arguments {@link BitStream#ensureBitRange0to32(int)}
*/
@Test(expected=IllegalArgumentException.class)
public void testEnsureBitRange0to32Invalid2()
{
BitStream.ensureBitRange0to32(32+1);
}
/**
* Tests {@link BitStream#indexof(int)} and {@link BitStream#bitsof(int)}.
*
* Assures that the for positive or zero values the condition
* <code>p == (BitStream.indexof(p)*32)+BitStream.bitsof(p)</code>
* is <code>true</code>
*/
@Test
public void testIndexOfBitsOfTest()
{
for (int p=0;p<=100;p++)
{
assertTrue(p == (BitStream.indexof(p)*32)+BitStream.bitsof(p));
}
}
/**
* Tests {@link BitStream#bitsof(int)}
* Tests that for values p in [0..32-1] and k in [0..*]
* the condition BitStream.bitsof((32*k)+p)==p is true
*/
@Test
public void testBitsOf()
{
for (int k=0;k<100;k++)
for (int p=0;p<32;p++)
assertTrue(BitStream.bitsof((32*k)+p)==p);
}
/**
* Tests {@link BitStream#indexof(int)}.
* Tests that for values p in [0..32-1] and k in [0..*]
* the condition BitStream.indexof((32*k)+p)==k is true
*/
@Test
public void testIndexOf()
{
for (int k=0;k<100;k++)
for (int p=0;p<32;p++)
assertTrue(BitStream.indexof((32*k)+p)==k);
}
/**
* Tests {@link BitStream#unsetbits(int, int)}
*/
@Test
public void unsetBitsTest()
{
final int allbits = 0xFFFFFFFF;
assertTrue("bitcount: 0",BitStream.unsetbits(allbits,0) == 0);
for (int bitcount=1;bitcount<=32;bitcount++)
{
assertTrue("bitcount: "+bitcount,BitStream.unsetbits(allbits,bitcount) == ((allbits<<(32-bitcount))>>>(32-bitcount)));
}
}
/**
* Test for {@link BitStream#BitStream()}
*/
@Test
public void constructorTest1()
{
new BitStream();
}
/**
* Test for {@link BitStream#BitStream(int)}
*/
@Test
public void constructorTest2()
{
new BitStream(0);
new BitStream(1);
}
/**
* Test for {@link BitStream#BitStream(int)}.
* Tests invalid negative arguments.
*/
@Test(expected=NegativeArraySizeException.class)
public void constructorTest3()
{
new BitStream(-1);
}
/**
* Tests {@link BitStream#getSize()}
*/
@Test
public void getSizeTest()
{
BitStream bs = new BitStream();
// empty bitstream
assertTrue(bs.getSize()==0);
// size after appending
bs.append(0,0);
for (int i=0;i<32;i++)
{
assertTrue(bs.getSize()==i);
bs.append(0,1);
}
assertTrue(bs.getSize()==32);
// size after wrap(byte[])
assertTrue(BitStream.wrap(new byte[10]).getSize()==10*8);
// size after wrap(byte[10], 1, 9)
assertTrue(BitStream.wrap(new byte[10], 1, 9).getSize()==(9-1)*8);
// size after wrap(int[])
assertTrue(BitStream.wrap(new int[10]).getSize()==10*32);
// size after wrap(byte[10], 99)
assertTrue(BitStream.wrap(new int[10], 99).getSize()==99);
// size after clear 1
bs = BitStream.wrap(new byte[10]);
bs.clear();
assertTrue(bs.getSize()==0);
// size after clear 2
bs = new BitStream();
bs.clear();
assertTrue(bs.getSize()==0);
// size after setSize 1
bs = BitStream.wrap(new byte[10]);
bs.setSize(32);
assertTrue(bs.getSize()==32);
// size after setSize 2
bs = new BitStream();
bs.setSize(32);
assertTrue(bs.getSize()==0);
}
/**
* Tests reading and writing
*/
@Test
public void testReadWrite()
{
BitStream bs = new BitStream();
bs.append((byte)0xFF);
assertTrue(bs.getPosition()==0);
assertTrue(bs.getSize()==8);
assertTrue(bs.getInt(bs.getSize())==0xFF);
assertTrue(bs.getPosition()==bs.getSize());
// test getByte()
bs = new BitStream();
bs.append((byte)0xFF);
assertTrue(bs.getPosition()==0);
assertTrue(bs.getSize()==8);
assertTrue(bs.getByte()==(byte)0xFF);
assertTrue(bs.getPosition()==bs.getSize());
final int pattern = 0xAaAaAa;
testRW(pattern); // (1010)+ pattern
testRW(pattern>>>1); // (0101)+ pattern
// writing free number of bits
bs = new BitStream();
int totalbits = 0;
for(int b=0;b<=32;b++)
{
bs.append(0xFfFfFfFf, b);
totalbits+=b;
}
// check number of bits
assertTrue(bs.getSize()==totalbits);
// read all bits and check if they are all set
while (bs.isAvailable(1))
assertTrue(bs.getInt(1)==1);
// test getInt(0)
bs = new BitStream();
assertTrue(bs.getInt(0)==0);
bs = new BitStream();
bs.append(0xFfFfFfFf);
assertTrue(bs.getInt(0)==0);
}
/**
* @see #testReadWrite()
*/
private void testRW(int pattern)
{
BitStream bs = new BitStream();
bs.append(pattern);
bs.append(pattern);
assertTrue(bs.getSize()==32*2);
assertTrue(bs.getPosition()==0);
assertTrue(bs.getInt()==pattern);
assertTrue(bs.getPosition()==32);
assertTrue(bs.getInt()==pattern);
assertTrue(bs.getPosition()==bs.getSize());
}
/**
* Tests invalid argument in {@link BitStream#getInt()}
*/
@Test(expected=IllegalArgumentException.class)
public void testGetIntFails1()
{
BitStream bs = new BitStream();
bs.getInt(-1);
}
/**
* Tests invalid argument in {@link BitStream#getInt()}
*/
@Test(expected=IllegalArgumentException.class)
public void testGetIntFails2()
{
BitStream bs = new BitStream();
bs.getInt(33);
}
/**
* Tests invalid argument in {@link BitStream#getInt()}
*/
@Test(expected=IllegalArgumentException.class)
public void testGetIntFails3()
{
BitStream bs = new BitStream();
bs.append(0);
bs.append(0);
assertTrue(bs.getSize()==64);
bs.getInt(33);
}
/**
* Tests {@link BitStream#clone()}
*/
@Test
public void cloneTest()
{
BitStream bs = new BitStream();
bs.append(0xAaAaAa,32);
bs.getInt(2);
// assert conditions
checkCloneConditions(bs);
// create clone
BitStream cl = bs.clone();
checkCloneConditions(cl);
// check again
assertTrue(bs.getSize()==cl.getSize());
assertTrue(bs.getPosition()==cl.getPosition());
// data check
int remaining = bs.getSize()-bs.getPosition();
assertTrue(bs.getInt(remaining)==cl.getInt(remaining));
}
/**
* @see #cloneTest()
*/
private void checkCloneConditions( BitStream bs )
{
assertTrue(bs.getSize()==32);
assertTrue(bs.getPosition()==2);
}
/**
* Tests {@link BitStream#isAvailable(int)}
*/
@Test
public void availableTest()
{
for (int i=0;i<=32+1;i++)
{
BitStream bs = BitStream.wrap(new int[2], i);
assertTrue(bs.isAvailable(i));
assertFalse(bs.isAvailable(i+1));
}
{
final int start = 1;
for (int i=start;i<=10;i++)
{
BitStream bs = BitStream.wrap(new byte[10], start, i);
assertTrue(bs.isAvailable((i-start)*8));
assertFalse(bs.isAvailable(((i-start)*8)+1));
}
}
{
byte[] data = new byte[10];
BitStream bs = BitStream.wrap(data);
assertTrue(bs.getSize() == data.length*8);
assertTrue(bs.isAvailable(bs.getSize()));
assertTrue(bs.isAvailable(data.length*8));
assertFalse(bs.isAvailable((data.length*8)+1));
}
}
/**
* Tests {@link BitStream#toIntArray()}
*/
@Test
public void toIntArrayTest()
{
// ensure only complete integers are written
int[] tmp = new int[] {0xAaAaAa, 0xAaAaAa};
for (int i=0;i<=tmp.length*32;i++)
{
BitStream bs = BitStream.wrap(tmp, i);
assertTrue(bs.toIntArray().length == i/32);
}
// check data
int[] cpy ;
BitStream bs;
bs = BitStream.wrap(tmp);
cpy = bs.toIntArray();
assertTrue(cpy.length == tmp.length);
assertTrue(cpy[0]==tmp[0]);
assertTrue(cpy[1]==tmp[1]);
bs = BitStream.wrap(tmp, 32*2-1);
cpy = bs.toIntArray();
assertTrue(cpy.length == 1);
assertTrue(cpy[0]==(tmp[0]&~1));
}
/**
* Tests {@link BitStream#toByteArray()}
*/
@Test
public void toByteArrayTest()
{
// ensure only complete integers are written
final byte pattern = (byte) 0xAa;
byte[] tmp = new byte[] {pattern, pattern, pattern, pattern, pattern};
// check data
for (int start=0;start<5;start++)
{
for (int end=start;end<=5;end++)
{
BitStream bs = BitStream.wrap(tmp, start, end);
byte[] cpy = bs.toByteArray();
assertTrue(cpy.length == end-start);
for (int i=0;i<cpy.length;i++)
assertTrue(cpy[i]==tmp[i]);
}
}
}
}