Move unit tests from integration test suite (#1170)

This commit is contained in:
Austin Shalit
2019-07-16 01:02:52 -04:00
committed by Peter Johnson
parent dffa1a5cba
commit e488861877
12 changed files with 445 additions and 414 deletions

View File

@@ -1,65 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2015-2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
package edu.wpi.first.wpilibj;
import java.util.Random;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class LinearFilterNoiseTest {
public enum TestType {
kSinglePoleIIR, kMovAvg
}
// Filter constants
public static final double kFilterStep = 0.005;
public static final double kFilterTime = 2.0;
public static final double kSinglePoleIIRTimeConstant = 0.015915;
public static final int kMovAvgTaps = 6;
@SuppressWarnings("ParameterName")
public static double getData(double t) {
return 100.0 * Math.sin(2.0 * Math.PI * t);
}
/**
* Test if the filter reduces the noise produced by a signal generator.
*/
@ParameterizedTest
@EnumSource(TestType.class)
public void testNoiseReduce(TestType type) {
final LinearFilter filter;
if (type == TestType.kSinglePoleIIR) {
filter = LinearFilter.singlePoleIIR(kSinglePoleIIRTimeConstant, kFilterStep);
} else {
filter = LinearFilter.movingAverage(kMovAvgTaps);
}
double noiseGenError = 0.0;
double filterError = 0.0;
final Random gen = new Random();
final double kStdDev = 10.0;
for (double t = 0; t < kFilterTime; t += kFilterStep) {
final double theory = getData(t);
final double noise = gen.nextGaussian() * kStdDev;
filterError += Math.abs(filter.calculate(theory + noise) - theory);
noiseGenError += Math.abs(noise - theory);
}
assertTrue(noiseGenError > filterError,
"Filter should have reduced noise accumulation from " + noiseGenError
+ " but failed. The filter error was " + filterError);
}
}

View File

@@ -1,85 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2015-2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
package edu.wpi.first.wpilibj;
import java.util.function.DoubleFunction;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class LinearFilterOutputTest {
public enum TestType {
kSinglePoleIIR,
kHighPass,
kMovAvg,
kPulse
}
// Filter constants
public static final double kFilterStep = 0.005;
public static final double kFilterTime = 2.0;
public static final double kSinglePoleIIRTimeConstant = 0.015915;
public static final double kSinglePoleIIRExpectedOutput = -3.2172003;
public static final double kHighPassTimeConstant = 0.006631;
public static final double kHighPassExpectedOutput = 10.074717;
public static final int kMovAvgTaps = 6;
public static final double kMovAvgExpectedOutput = -10.191644;
@SuppressWarnings("ParameterName")
public static double getData(double t) {
return 100.0 * Math.sin(2.0 * Math.PI * t) + 20.0 * Math.cos(50.0 * Math.PI * t);
}
@SuppressWarnings("ParameterName")
public static double getPulseData(double t) {
if (Math.abs(t - 1.0) < 0.001) {
return 1.0;
} else {
return 0.0;
}
}
/**
* Test if the linear filters produce consistent output for a given data set.
*/
@ParameterizedTest
@EnumSource(TestType.class)
public void testOutput(TestType type) {
final LinearFilter filter;
final DoubleFunction<Double> data;
final double expectedOutput;
if (type == TestType.kSinglePoleIIR) {
filter = LinearFilter.singlePoleIIR(kSinglePoleIIRTimeConstant, kFilterStep);
data = (double t) -> getData(t);
expectedOutput = kSinglePoleIIRExpectedOutput;
} else if (type == TestType.kHighPass) {
filter = LinearFilter.highPass(kHighPassTimeConstant, kFilterStep);
data = (double t) -> getData(t);
expectedOutput = kHighPassExpectedOutput;
} else if (type == TestType.kMovAvg) {
filter = LinearFilter.movingAverage(kMovAvgTaps);
data = (double t) -> getData(t);
expectedOutput = kMovAvgExpectedOutput;
} else {
filter = LinearFilter.movingAverage(kMovAvgTaps);
data = (double t) -> getPulseData(t);
expectedOutput = 0.0;
}
double filterOutput = 0.0;
for (double t = 0.0; t < kFilterTime; t += kFilterStep) {
filterOutput = filter.calculate(data.apply(t));
}
assertEquals(expectedOutput, filterOutput, 0.00005, "Filter output was incorrect.");
}
}

View File

@@ -0,0 +1,116 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2015-2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
package edu.wpi.first.wpilibj;
import java.util.Random;
import java.util.function.DoubleFunction;
import java.util.stream.Stream;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.params.provider.Arguments.arguments;
class LinearFilterTest {
private static final double kFilterStep = 0.005;
private static final double kFilterTime = 2.0;
private static final double kSinglePoleIIRTimeConstant = 0.015915;
private static final double kHighPassTimeConstant = 0.006631;
private static final int kMovAvgTaps = 6;
private static final double kSinglePoleIIRExpectedOutput = -3.2172003;
private static final double kHighPassExpectedOutput = 10.074717;
private static final double kMovAvgExpectedOutput = -10.191644;
@SuppressWarnings("ParameterName")
private static double getData(double t) {
return 100.0 * Math.sin(2.0 * Math.PI * t) + 20.0 * Math.cos(50.0 * Math.PI * t);
}
@SuppressWarnings("ParameterName")
private static double getPulseData(double t) {
if (Math.abs(t - 1.0) < 0.001) {
return 1.0;
} else {
return 0.0;
}
}
@Test
void illegalTapNumberTest() {
assertThrows(IllegalArgumentException.class, () -> LinearFilter.movingAverage(0));
}
/**
* Test if the filter reduces the noise produced by a signal generator.
*/
@ParameterizedTest
@MethodSource("noiseFilterProvider")
void noiseReduceTest(final LinearFilter filter) {
double noiseGenError = 0.0;
double filterError = 0.0;
final Random gen = new Random();
final double kStdDev = 10.0;
for (double t = 0; t < kFilterTime; t += kFilterStep) {
final double theory = getData(t);
final double noise = gen.nextGaussian() * kStdDev;
filterError += Math.abs(filter.calculate(theory + noise) - theory);
noiseGenError += Math.abs(noise - theory);
}
assertTrue(noiseGenError > filterError,
"Filter should have reduced noise accumulation from " + noiseGenError
+ " but failed. The filter error was " + filterError);
}
static Stream<LinearFilter> noiseFilterProvider() {
return Stream.of(
LinearFilter.singlePoleIIR(kSinglePoleIIRTimeConstant, kFilterStep),
LinearFilter.movingAverage(kMovAvgTaps)
);
}
/**
* Test if the linear filters produce consistent output for a given data set.
*/
@ParameterizedTest
@MethodSource("outputFilterProvider")
void outputTest(final LinearFilter filter, final DoubleFunction<Double> data,
final double expectedOutput) {
double filterOutput = 0.0;
for (double t = 0.0; t < kFilterTime; t += kFilterStep) {
filterOutput = filter.calculate(data.apply(t));
}
assertEquals(expectedOutput, filterOutput, 5e-5, "Filter output was incorrect.");
}
static Stream<Arguments> outputFilterProvider() {
return Stream.of(
arguments(LinearFilter.singlePoleIIR(kSinglePoleIIRTimeConstant, kFilterStep),
(DoubleFunction) LinearFilterTest::getData,
kSinglePoleIIRExpectedOutput),
arguments(LinearFilter.highPass(kHighPassTimeConstant, kFilterStep),
(DoubleFunction) LinearFilterTest::getData,
kHighPassExpectedOutput),
arguments(LinearFilter.movingAverage(kMovAvgTaps),
(DoubleFunction) LinearFilterTest::getData,
kMovAvgExpectedOutput),
arguments(LinearFilter.movingAverage(kMovAvgTaps),
(DoubleFunction) LinearFilterTest::getPulseData,
0.0)
);
}
}

View File

@@ -0,0 +1,212 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2008-2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
package edu.wpi.first.wpilibj;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Set;
import java.util.stream.Stream;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import edu.wpi.first.networktables.NetworkTable;
import edu.wpi.first.networktables.NetworkTableInstance;
import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
class PreferencesTest {
private final Preferences m_prefs = Preferences.getInstance();
private final NetworkTable m_table = NetworkTableInstance.getDefault().getTable("Preferences");
private static final String kFilename = "networktables.ini";
@BeforeAll
static void setupAll() {
NetworkTableInstance.getDefault().stopServer();
}
@BeforeEach
void setup(@TempDir Path tempDir) {
m_table.getKeys().forEach(m_table::delete);
Path filepath = tempDir.resolve(kFilename);
try (InputStream is = getClass().getResource("PreferencesTestDefault.ini").openStream()) {
Files.copy(is, filepath);
} catch (IOException ex) {
fail(ex);
}
NetworkTableInstance.getDefault().startServer(filepath.toString());
}
@AfterEach
void cleanup() {
NetworkTableInstance.getDefault().stopServer();
}
@AfterAll
static void cleanupAll() {
NetworkTableInstance.getDefault().startServer();
}
@Test
void removeAllTest() {
m_prefs.removeAll();
Set<String> keys = m_table.getKeys();
keys.remove(".type");
assertTrue(keys.isEmpty(), "Preferences was not empty! Preferences in table: "
+ Arrays.toString(keys.toArray()));
}
@ParameterizedTest
@MethodSource("defaultKeyProvider")
void defaultKeysTest(String key) {
assertTrue(m_prefs.containsKey(key));
}
@ParameterizedTest
@MethodSource("defaultKeyProvider")
void defaultKeysAllTest(String key) {
assertTrue(m_prefs.getKeys().contains(key));
}
@Test
void defaultValueTest() {
assertAll(
() -> assertEquals(172L, m_prefs.getLong("checkedValueLong", 0)),
() -> assertEquals(0.2, m_prefs.getDouble("checkedValueDouble", 0), 1e-6),
() -> assertEquals("Hello. How are you?", m_prefs.getString("checkedValueString", "")),
() -> assertEquals(2, m_prefs.getInt("checkedValueInt", 0)),
() -> assertEquals(3.14, m_prefs.getFloat("checkedValueFloat", 0), 1e-6),
() -> assertFalse(m_prefs.getBoolean("checkedValueBoolean", true))
);
}
@Test
void backupTest() {
m_prefs.removeAll();
assertAll(
() -> assertEquals(0, m_prefs.getLong("checkedValueLong", 0)),
() -> assertEquals(0, m_prefs.getDouble("checkedValueDouble", 0), 1e-6),
() -> assertEquals("", m_prefs.getString("checkedValueString", "")),
() -> assertEquals(0, m_prefs.getInt("checkedValueInt", 0)),
() -> assertEquals(0, m_prefs.getFloat("checkedValueFloat", 0), 1e-6),
() -> assertTrue(m_prefs.getBoolean("checkedValueBoolean", true))
);
}
@Nested
class PutGetTests {
@Test
void intTest() {
final String key = "test";
final int value = 123;
m_prefs.putInt(key, value);
assertAll(
() -> assertEquals(value, m_prefs.getInt(key, -1)),
() -> assertEquals(value, m_table.getEntry(key).getNumber(-1).intValue())
);
}
@Test
void longTest() {
final String key = "test";
final long value = 190L;
m_prefs.putLong(key, value);
assertAll(
() -> assertEquals(value, m_prefs.getLong(key, -1)),
() -> assertEquals(value, m_table.getEntry(key).getNumber(-1).longValue())
);
}
@Test
void floatTest() {
final String key = "test";
final float value = 9.42f;
m_prefs.putFloat(key, value);
assertAll(
() -> assertEquals(value, m_prefs.getFloat(key, -1), 1e-6),
() -> assertEquals(value, m_table.getEntry(key).getNumber(-1).floatValue(), 1e-6)
);
}
@Test
void doubleTest() {
final String key = "test";
final double value = 6.28;
m_prefs.putDouble(key, value);
assertAll(
() -> assertEquals(value, m_prefs.getDouble(key, -1), 1e-6),
() -> assertEquals(value, m_table.getEntry(key).getNumber(-1).doubleValue(), 1e-6)
);
}
@Test
void stringTest() {
final String key = "test";
final String value = "value";
m_prefs.putString(key, value);
assertAll(
() -> assertEquals(value, m_prefs.getString(key, "")),
() -> assertEquals(value, m_table.getEntry(key).getString(""))
);
}
@Test
void booleanTest() {
final String key = "test";
final boolean value = true;
m_prefs.putBoolean(key, value);
assertAll(
() -> assertEquals(value, m_prefs.getBoolean(key, false)),
() -> assertEquals(value, m_table.getEntry(key).getBoolean(false))
);
}
}
static Stream<String> defaultKeyProvider() {
return Stream.of(
"checkedValueLong",
"checkedValueDouble",
"checkedValueString",
"checkedValueInt",
"checkedValueFloat",
"checkedValueBoolean"
);
}
}

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2018 FIRST. All Rights Reserved. */
/* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
@@ -7,10 +7,113 @@
package edu.wpi.first.wpilibj.smartdashboard;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import edu.wpi.first.networktables.NetworkTable;
import edu.wpi.first.networktables.NetworkTableInstance;
import edu.wpi.first.wpilibj.UtilityClassTest;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
class SmartDashboardTest extends UtilityClassTest {
private final NetworkTable m_table = NetworkTableInstance.getDefault().getTable("SmartDashboard");
SmartDashboardTest() {
super(SmartDashboard.class);
}
@BeforeEach
void beforeEach() {
m_table.getKeys().forEach(m_table::delete);
}
@Test
void getBadValueTest() {
assertEquals("Expected", SmartDashboard.getString("KEY_SHOULD_NOT_BE_FOUND", "Expected"));
}
@Test
void putStringTest() {
final String key = "putString";
final String value = "thisIsAValue";
SmartDashboard.putString(key, value);
assertEquals(value, m_table.getEntry(key).getString(""));
}
@Test
void getStringTest() {
final String key = "getString";
final String value = "thisIsAValue";
m_table.getEntry(key).setString(value);
assertEquals(value, SmartDashboard.getString(key, ""));
}
@Test
void putNumberTest() {
final String key = "PutNumber";
final int value = 2147483647;
SmartDashboard.putNumber(key, value);
assertEquals(value, m_table.getEntry(key).getNumber(0).intValue());
}
@Test
void getNumberTest() {
final String key = "GetNumber";
final int value = 2147483647;
m_table.getEntry(key).setNumber(value);
assertEquals(value, SmartDashboard.getNumber(key, 0), 0.01);
}
@Test
void putBooleanTest() {
final String key = "PutBoolean";
final boolean value = true;
SmartDashboard.putBoolean(key, value);
assertEquals(value, m_table.getEntry(key).getBoolean(!value));
}
@Test
void getBooleanTest() {
final String key = "GetBoolean";
final boolean value = true;
m_table.getEntry(key).setBoolean(value);
assertEquals(value, SmartDashboard.getBoolean(key, !value));
}
@Test
void testReplaceString() {
final String key = "testReplaceString";
final String valueNew = "newValue";
m_table.getEntry(key).setString("oldValue");
SmartDashboard.putString(key, valueNew);
assertEquals(valueNew, m_table.getEntry(key).getString(""));
}
@Test
void putStringNullKeyTest() {
assertThrows(NullPointerException.class,
() -> SmartDashboard.putString(null, "This should not work"));
}
@Test
void putStringNullValueTest() {
assertThrows(NullPointerException.class,
() -> SmartDashboard.putString("KEY_SHOULD_NOT_BE_STORED", null));
}
}