/*
* Copyright (C) 2008 Steve Ratcliffe
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 or
* version 2 as published by the Free Software Foundation.
*
* 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.
*/
package uk.me.parabola.imgfmt.app.net;
import java.util.ArrayList;
import java.util.List;
import uk.me.parabola.imgfmt.app.BitReader;
import uk.me.parabola.imgfmt.app.BitWriter;
import func.lib.NumberReader;
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* There are multiple ways of representing the same set of numbers. So these tests will employ a number
* reader to parse the resulting bit stream and create a list of numberings that can be compared with
* the input ones.
*/
public class NumberPreparerTest
{
@Test
public void testNumberConstructor
() {
// A simple test with all numbers increasing.
String spec =
"0,O,1,7,E,2,12";
Numbers n =
new Numbers
(spec
);
assertEquals
(spec, n.
toString());
}
/**
* Just test that the test infrastructure is working with a known byte stream, this
* is testing the tests.
*/
@Test
public void testKnownStream
() {
byte[] buf =
{0x41, 0x13, 0x27, 0x49, 0x60
};
BitReader br =
new BitReader
(buf
);
NumberReader nr =
new NumberReader
(br
);
nr.
setNumberOfNodes(1);
List<Numbers
> numbers = nr.
readNumbers(true);
assertEquals
(1, numbers.
size());
assertEquals
("0,E,24,8,O,23,13", numbers.
get(0).
toString());
}
/**
* Simple test of numbers that increase on both sides.
*/
@Test
public void testIncreasingNumbers
() {
run
("0,O,1,11,E,2,12");
}
@Test
public void testSwappedDefaultStyles
() {
List<Numbers
> numbers = createList
(new String[]{"0,E,2,12,O,1,11"});
List<Numbers
> output = writeAndRead
(numbers
);
assertEquals
(numbers, output
);
}
@Test
public void testIncreasingHighStarts
() {
String[] tests =
{
"0,O,1,5,E,2,6",
"0,O,3,7,E,4,8",
"0,O,91,99,E,92,98",
"0,O,1,15,E,4,8",
};
for (String t : tests
) {
List<Numbers
> numbers = createList
(new String[]{t
});
List<Numbers
> output = writeAndRead
(numbers
);
assertEquals
(numbers, output
);
}
}
@Test
public void testSingleNumbers
() {
runSeparate
("0,O,7,7,E,8,8",
"0,O,7,7,E,6,6");
}
@Test
public void testLargeDifferentStarts
() {
runSeparate
("0,O,91,103,E,2,8",
"0,E,90,102,O,3,9");
}
@Test
public void testMultipleNodes
() {
List<Numbers
> numbers = createList
(new String[]{
"0,O,1,9,E,2,12",
"1,O,11,17,E,14,20",
"2,O,21,31,E,26,36",
});
List<Numbers
> output = writeAndRead
(numbers
);
assertEquals
(numbers, output
);
}
@Test
public void testMultipleNodesWithSkip
() {
List<Numbers
> numbers = createList
(new String[]{
"0,O,1,9,E,2,12",
"2,O,11,17,E,14,20",
"3,O,21,31,E,26,36",
});
List<Numbers
> output = writeAndRead
(numbers
);
assertEquals
(numbers, output
);
}
@Test
public void testMultipleWithReverse
() {
run
("0,E,2,2,O,1,5",
"1,E,2,10,O,5,17");
}
@Test
public void testDecreasing
() {
run
("0,O,25,11,E,24,20");
}
@Test
public void testMixedStyles
() {
run
("0,O,1,9,E,6,12",
"1,E,14,22,O,9,17",
"2,O,17,21,E,26,36");
}
@Test
public void testOneSide
() {
runSeparate
("0,N,-1,-1,O,9,3");
runSeparate
("0,E,2,8,N,-1,-1",
"0,N,-1,-1,O,9,3");
}
@Test
public void testBoth
() {
runSeparate
("0,B,1,10,B,11,20");
}
@Test
public void testLargeRunsAndGaps
() {
run
("0,E,100,200,O,111,211",
"1,E,400,500,O,421,501",
"2,E,600,650,O,601,691");
}
@Test
public void testSkip
() {
run
("0,E,2,20,O,1,9",
"3,O,3,9,E,2,2");
}
@Test
public void testSkipFirst
() {
run
("2,O,1,5,E,2,2");
}
@Test
public void testLargeSkip
() {
run
("0,N,-1,-1,E,2,4",
"100,O,1,9,E,8,16");
}
@Test
public void testRepeatingRun
() {
run
("0,O,1,9,E,2,10",
"1,O,11,19,E,12,20",
"2,O,21,29,E,22,30",
"3,O,31,39,E,32,40"
);
assertThat
(bytesUsed, lessThanOrEqual
(8));
}
/**
* What to do about the number zero.
*/
@Test
public void testZero
() {
// Includes invalid cases where the numbers are the same down both sides.
runSeparate
("0,E,0,10,N,-1,-1",
"1,B,0,4,B,0,8"
);
}
@Test
public void testVeryLargeNumber
() {
String[] numbers =
{"0,E,55892490,55892500,N,-1,-1"};
// Number is way too big, no exception, result just marked invalid.
NumberPreparer preparer =
new NumberPreparer
(createList
(numbers
));
assertFalse
(preparer.
isValid());
numbers =
new String[] {"0,E,10,55892500,N,-1,-1"};
// The difference is too big.
preparer =
new NumberPreparer
(createList
(numbers
));
assertFalse
(preparer.
isValid());
}
@Test
public void testLargeButOK
() {
run
("0,O,1,10001,E,2,12000",
"1,O,10003,10301,E,12002,12060",
"2,E,1047000,1048000,N,-1,-1");
runSeparate
("3,E,131000,2,N,-1,-1");
}
/**
* Range with differences that are too large. The difference between the start and end
* of a range has a lower range than from initial-or-end to start.
*/
@Test
public void testLargeDifferenceError
() {
String[] numbers =
{"3,E,131080,2,N,-1,-1"};
NumberPreparer preparer =
new NumberPreparer
(createList
(numbers
));
assertFalse
(preparer.
isValid());
}
/**
* Tests sequences of number ranges that have previously been discovered to fail using the
* random range generator test.
*/
@Test
public void testRegression
() {
String[][] tests =
{
{"0,E,4,2,E,2,2",
"1,E,10,8,O,3,1",
"2,B,8,6,B,3,3",
"3,E,8,2,E,2,2"},
{"0,O,5,7,O,9,5",
"1,N,-1,-1,O,3,7",
"2,N,-1,-1,O,3,5"},
{"0,N,-1,-1,O,3,5",
"1,O,1,3,N,-1,-1",
"2,E,4,4,E,6,8"},
{"0,N,-1,-1,E,4,4",
"1,E,4,4,O,3,11"},
{"0,B,4,8,O,5,9",
"1,O,5,3,O,7,7",
"2,O,3,3,E,4,20"},
{"0,E,8,6,B,6,2",
"1,O,5,5,E,4,8"},
{"0,B,16,1,B,10,5",
"1,O,3,7,E,2,8"},
{"0,B,10,5,E,22,10",
"1,O,3,1,O,3,5"},
{"0,B,10,10,N,-1,-1",
"1,O,11,9,O,1,11",
"2,O,3,3,E,8,4",
"3,O,7,19,E,6,2",
"4,E,10,6,E,4,4"},
{"0,N,-1,-1,B,6,5",
"1,O,3,11,O,3,3"},
{"0,O,7,1,O,9,5",
"1,O,27,23,O,3,5"},
{"0,B,5,5,E,12,8"},
};
for (String[] sarr : tests
)
run
(sarr
);
}
// Helper routines
private void runSeparate
(String...
numbers) {
for (String s : numbers
)
run
(s
);
}
private void run
(String ...
numbers) {
List<Numbers
> nList = createList
(numbers
);
List<Numbers
> output = writeAndRead
(nList
);
assertEquals
(nList, output
);
}
private int bytesUsed
;
private List<Numbers
> writeAndRead
(List<Numbers
> numbers
) {
NumberPreparer preparer =
new NumberPreparer
(numbers
);
BitWriter bw = preparer.
fetchBitStream();
bytesUsed += bw.
getLength();
assertTrue
("check valid flag", preparer.
isValid());
boolean swapped = preparer.
getSwapped();
// Now read it all back in again
byte[] b1 = bw.
getBytes();
byte[] bytes =
new byte[bw.
getLength()];
System.
arraycopy(b1,
0, bytes,
0, bw.
getLength());
BitReader br =
new BitReader
(bytes
);
NumberReader nr =
new NumberReader
(br
);
nr.
setNumberOfNodes(numbers.
get(numbers.
size()-
1).
getIndex() +
1);
List<Numbers
> list = nr.
readNumbers(swapped
);
for (Numbers n : list
)
n.
setPolishIndex(n.
getIndex());
return list
;
}
private List<Numbers
> createList
(String[] specs
) {
List<Numbers
> numbers =
new ArrayList<>();
for (String s : specs
) {
Numbers n =
new Numbers
(s
);
n.
setIndex(n.
getPolishIndex());
numbers.
add(n
);
}
return numbers
;
}
private Matcher<Integer> lessThanOrEqual
(final int val
) {
return new BaseMatcher
<Integer>() {
public boolean matches
(Object o
) {
return (Integer) o
<= val
;
}
public void describeTo
(Description description
) {
description.
appendText("value is less than ").
appendValue(val
);
}
};
}
}