/* * 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 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.setNodeNumber(n.getIndex()); return list; } private List<Numbers> createList(String[] specs) { List<Numbers> numbers = new ArrayList<Numbers>(); for (String s : specs) { Numbers n = new Numbers(s); n.setIndex(n.getNodeNumber()); 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); } }; } }