/*
* Copyright 2015-2016 Cel Skeggs
*
* This file is part of the CCRE, the Common Chicken Runtime Engine.
*
* The CCRE 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 CCRE 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 CCRE. If not, see <http://www.gnu.org/licenses/>.
*/
package ccre.channel;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import ccre.testing.CountingFloatOutput;
import ccre.util.Utils;
import ccre.util.Values;
@SuppressWarnings("javadoc")
public class FloatFilterTest {
private FloatFilter ff;
@Before
public void setUp() throws Exception {
ff = new FloatFilter() {
@Override
public float filter(float input) {
return input + 1;
}
};
}
@After
public void tearDown() throws Exception {
ff = null;
}
@Test
public void testFilter() {
for (float f : Values.interestingFloats) {
assertEquals(f + 1, ff.filter(f), 0);
}
}
@Test(expected = NullPointerException.class)
public void testWrapFloatInputNull() {
ff.wrap((FloatInput) null);
}
@Test
public void testWrapFloatInput() {
FloatCell fs = new FloatCell();
FloatInput fin = ff.wrap(fs.asInput());
CountingFloatOutput cfo = new CountingFloatOutput();
cfo.valueExpected = ff.filter(0);
cfo.ifExpected = true;
fin.send(cfo);
cfo.check();
for (float f : Values.interestingFloats) {
if (f == 0) { // avoids artificial problem with negative epsilon
// followed by zero... they both add with one to one!
cfo.valueExpected = 2;
cfo.ifExpected = true;
fs.set(1);
cfo.check();
}
cfo.valueExpected = f + 1;
cfo.ifExpected = true;
fs.set(f);
cfo.check();
assertEquals(f + 1, fin.get(), 0);
}
}
@Test(expected = NullPointerException.class)
public void testWrapFloatOutputNull() {
ff.wrap((FloatOutput) null);
}
@Test
public void testWrapFloatOutput() {
CountingFloatOutput cfo = new CountingFloatOutput();
FloatOutput fin = ff.wrap(cfo);
for (float f : Values.interestingFloats) {
cfo.valueExpected = f + 1;
cfo.ifExpected = true;
fin.set(f);
cfo.check();
}
}
@Test
public void testDeadzone() {
for (float zone : Values.interestingFloats) {
if (!Float.isFinite(zone) || zone < 0) {
continue;
}
FloatFilter filter = FloatFilter.deadzone(zone);
for (float value : Values.interestingFloats) {
if (Float.isNaN(value)) {
assertTrue(Float.isNaN(filter.filter(value)));
continue;
}
assertEquals(Utils.deadzone(value, zone), filter.filter(value), 0);
}
}
}
@Test(expected = IllegalArgumentException.class)
public void testDeadzoneNaN() {
FloatFilter.deadzone(Float.NaN);
}
@Test(expected = IllegalArgumentException.class)
public void testDeadzoneNegative() {
FloatFilter.deadzone(-1);
}
@Test(expected = IllegalArgumentException.class)
public void testDeadzoneInfinite() {
FloatFilter.deadzone(Float.POSITIVE_INFINITY);
}
@Test
public void testLimit() {
for (float low : Values.interestingFloats) {
for (float high : Values.interestingFloats) {
FloatFilter limit;
try {
limit = FloatFilter.limit(low, high);
assertFalse("should have thrown exception", high < low);
} catch (IllegalArgumentException ex) {
assertTrue(high < low);
continue;
}
for (float value : Values.interestingFloats) {
float gotten = limit.filter(value);
if (Float.isNaN(value)) {
assertTrue(Float.isNaN(gotten));
continue;
}
assertTrue((gotten >= low || Float.isNaN(low)) && (gotten <= high || Float.isNaN(high)));
if (gotten != value) {
if (gotten == low) {
if (low == high) {
assertTrue(value <= low || value >= high);
} else {
assertTrue(value <= low);
}
} else if (gotten == high) {
assertTrue(value >= high);
} else {
fail("bad roundoff");
}
}
}
}
}
}
@Test
public void testNegate() {
for (float f : Values.interestingFloats) {
assertEquals(-f, FloatFilter.negate.filter(f), 0);
assertEquals(f, FloatFilter.negate.filter(-f), 0);
}
}
@Test
public void testAbsolute() {
for (float f : Values.interestingFloats) {
assertEquals(Math.abs(f), FloatFilter.absolute.filter(f), 0);
assertEquals(Math.abs(f), FloatFilter.absolute.filter(-f), 0);
}
}
}