diff options
author | Michael Chen <themichaelchen@google.com> | 2014-07-10 14:44:03 -0700 |
---|---|---|
committer | Andreas Gampe <agampe@google.com> | 2014-07-21 20:01:27 -0700 |
commit | 9d344289a41d19afec915a11b8c44dd2e7638a24 (patch) | |
tree | 42f6f504971c6f641edd9769e2384958a1f3e716 /luni/src/test/java | |
parent | fbf2339d9360d660475ac9909c59ef65512c5f49 (diff) | |
download | libcore-9d344289a41d19afec915a11b8c44dd2e7638a24.zip libcore-9d344289a41d19afec915a11b8c44dd2e7638a24.tar.gz libcore-9d344289a41d19afec915a11b8c44dd2e7638a24.tar.bz2 |
Add math tests in csv format for libcore math functions
The goal here is to have a csv file with math tests that
different parts of Android can all use the same math tests.
This change provides these initial csv files as well as the
corresponding testing framework for libcore.
Change-Id: I56430bd9224d92853aefa5024d6fdd1d10dfb255
Diffstat (limited to 'luni/src/test/java')
3 files changed, 259 insertions, 0 deletions
diff --git a/luni/src/test/java/libcore/java/math/CSVTest.java b/luni/src/test/java/libcore/java/math/CSVTest.java new file mode 100644 index 0000000..9e151c3 --- /dev/null +++ b/luni/src/test/java/libcore/java/math/CSVTest.java @@ -0,0 +1,88 @@ +package libcore.java.math; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +/** + * Standard single-input test framework for csv math tests + */ +public abstract class CSVTest extends junit.framework.TestCase { + /* + * csv file should have the following format: + * function,expected_output,input,extra_info + * e.g. cos,-0x1.0000000000000p+0,0x1.921fb54442d18p+1,cos(pi) + * for two input: function,expected_output,input1,input2,extra + * vogar classpath: obj/JAVA_LIBRARIES/core-tests-support_intermediates/javalib.jar + */ + + /** + * This is a set of functions in java.Math/StrictMath that take two inputs. + * These functions will call run2InputTest; others will call runTest. + */ + protected static final Set<String> twoInputFunctions; + static { + Set<String> twoInFunc = new HashSet<String>(); + twoInFunc.add("atan2"); + twoInFunc.add("copySign"); + twoInFunc.add("hypot"); + twoInFunc.add("IEEEremainder"); + twoInFunc.add("max"); + twoInFunc.add("min"); + twoInFunc.add("nextAfter"); + twoInFunc.add("pow"); + twoInFunc.add("scalb"); + twoInputFunctions = Collections.unmodifiableSet(twoInFunc); + } + + void TestCSVInputs(String[] csvFileNames) throws Exception { + int totalTests = 0; + for (String csvFileName : csvFileNames) { + String line = ""; + BufferedReader br = null; + + try { + br = new BufferedReader(new InputStreamReader( + getClass().getResourceAsStream(csvFileName))); + while ((line = br.readLine()) != null) { + if (line.charAt(0) != '#') { + String[] testCase = line.split(","); + runTest(testCase); + totalTests++; + } + } + } finally { + if (br != null) { + br.close(); + } + } + } + System.out.println("Completed running " + totalTests + " tests"); + } + + protected void runTest(String[] testCase) throws Exception { + String function = testCase[0]; + double expectedOutput = Double.parseDouble(testCase[1]); + double input = Double.parseDouble(testCase[2]); + String extra = ""; + if (twoInputFunctions.contains(function)) { + double input2 = Double.parseDouble(testCase[3]); + if (testCase.length > 4) { + extra = testCase[4]; + } + run2InputTest(function, expectedOutput, input, input2, extra); + } else { + if (testCase.length > 3) { + extra = testCase[3]; + } + runTest(function, expectedOutput, input, extra); + } + } + + abstract void runTest(String func, double expectedOutput, double input, + String extra) throws Exception; + + abstract void run2InputTest(String func, double expectedOutput, double input1, double input2, String extra) throws Exception; +}
\ No newline at end of file diff --git a/luni/src/test/java/libcore/java/math/RunCSVTests.java b/luni/src/test/java/libcore/java/math/RunCSVTests.java new file mode 100644 index 0000000..0c107f1 --- /dev/null +++ b/luni/src/test/java/libcore/java/math/RunCSVTests.java @@ -0,0 +1,109 @@ +package libcore.java.math; + +import java.lang.reflect.Method; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * Tests functions in java.lang.Math + * Looks for the filenames in csvFileNames in tests/resources + * Tests functions and numbers found in those files. + * Run: vogar --classpath out/target/common/obj/JAVA_LIBRARIES/core-tests-support_intermediates/javalib.jar + * libcore/luni/src/test/java/libcore/java/math/RunCSVTests.java + */ +public class RunCSVTests extends CSVTest { + /** Stores ulps of error allowed for each function, if not 1 ulp.*/ + private static final Map<String, Double> UlpMap; + static { + final HashMap<String, Double> funcUlps = new HashMap<String, Double>(); + funcUlps.put("sinh", 2.5); + funcUlps.put("cosh", 2.5); + funcUlps.put("tanh", 2.5); + funcUlps.put("abs", 0.0); + funcUlps.put("signum", 0.0); + funcUlps.put("getExponent", 0.0); + funcUlps.put("toRadians", 0.0); + funcUlps.put("toDegrees", 0.0); + funcUlps.put("sqrt", 0.0); + funcUlps.put("ceil", 0.0); + funcUlps.put("floor", 0.0); + funcUlps.put("rint", 0.0); + funcUlps.put("atan2", 2.0); + funcUlps.put("round", 0.0); + funcUlps.put("max", 0.0); + funcUlps.put("min", 0.0); + funcUlps.put("copySign", 0.0); + funcUlps.put("nextAfter", 0.0); + funcUlps.put("scalb", 0.0); + UlpMap = Collections.unmodifiableMap(funcUlps); + } + + public static final String[] csvFileNames = { "/math_tests.csv", + "/math_important_numbers.csv", "/math_java_only.csv" }; + + public void test_csv() throws Exception { + this.TestCSVInputs(csvFileNames); + } + + /** + * Runs a standard single-input test using assertEquals. + * Allows error based on UlpMap, but defaults to 1 ulp. + */ + @Override + void runTest(String func, double expectedOutput, double input, String extra) + throws Exception { + Class<Math> mathClass = Math.class; + Method m = mathClass.getMethod(func, new Class[] { Double.TYPE }); + Object returnValue = m.invoke(null, input); + + double allowedError; + if (UlpMap.containsKey(func)) { + allowedError = UlpMap.get(func)*Math.ulp(expectedOutput); + } else { + allowedError = Math.ulp(expectedOutput); + } + + try { + assertEquals(extra + ": " + m + ": " + input + ": ", expectedOutput, + (double) returnValue, allowedError); + } catch (ClassCastException e) { + assertEquals(extra + ": " + m + ": " + input + ": ", (int) expectedOutput, + (int) returnValue, allowedError); + } + } + + /** + * Runs a 2-input test using assertEquals. + * Allows error based on UlpMap, but defaults to 1 ulp. + */ + @Override + void run2InputTest(String func, double expectedOutput, double input1, + double input2, String extra) throws Exception { + Class<Math> mathClass = Math.class; + Method m; + Object returnValue; + if (func.equals("scalb")) { + m = mathClass.getMethod(func, new Class[] { Double.TYPE, Integer.TYPE }); + returnValue = m.invoke(null, input1, (int) input2); + } else { + m = mathClass.getMethod(func, new Class[] { Double.TYPE, Double.TYPE }); + returnValue = m.invoke(null, input1, input2); + } + + double allowedError; + if (UlpMap.containsKey(func)) { + allowedError = UlpMap.get(func)*Math.ulp(expectedOutput); + } else { + allowedError = Math.ulp(expectedOutput); + } + + try { + assertEquals(extra + ": " + m + ": ", expectedOutput, (double) returnValue, + allowedError); + } catch (ClassCastException e) { + assertEquals(extra + ": " + m + ": ", (int) expectedOutput, (int) returnValue, + allowedError); + } + } +} diff --git a/luni/src/test/java/libcore/java/math/RunCSVTestsStrict.java b/luni/src/test/java/libcore/java/math/RunCSVTestsStrict.java new file mode 100644 index 0000000..0443eb0 --- /dev/null +++ b/luni/src/test/java/libcore/java/math/RunCSVTestsStrict.java @@ -0,0 +1,62 @@ +package libcore.java.math; + +import java.lang.reflect.Method; + +/** + * Tests java.lang.StrictMath + * Looks for the filenames in csvFileNames in tests/resources + * Tests functions and numbers found in those files. + * Run: vogar --classpath out/target/common/obj/JAVA_LIBRARIES/core-tests-support_intermediates/javalib.jar + * libcore/luni/src/test/java/libcore/java/math/RunCSVTestsStrict.java + */ +public class RunCSVTestsStrict extends CSVTest { + public static final String[] csvFileNames = { "/math_tests.csv", + "/math_important_numbers.csv", "/math_java_only.csv" }; + + public void test_csv() throws Exception { + this.TestCSVInputs(csvFileNames); + } + + /** + * Runs single-input test using assertEquals. + */ + @Override + void runTest(String func, double expectedOutput, double input, String extra) + throws Exception { + Class<StrictMath> mathClass = StrictMath.class; + Method m = mathClass.getMethod(func, new Class[] { Double.TYPE }); + Object returnValue = m.invoke(null, input); + + try { + assertEquals(extra + ": " + m + ": " + input + ": ", expectedOutput, + (double) returnValue, 0D); + } catch (ClassCastException e) { + assertEquals(extra + ": " + m + ": " + input + ": ", (int) expectedOutput, + (int) returnValue, 0D); + } + } + + /** + * Runs 2-input test using assertEquals. + */ + @Override + void run2InputTest(String func, double expectedOutput, double input1, + double input2, String extra) throws Exception { + Class<StrictMath> mathClass = StrictMath.class; + Method m; + Object returnValue; + if (func.equals("scalb")) { + m = mathClass.getMethod(func, new Class[] { Double.TYPE, Integer.TYPE }); + returnValue = m.invoke(null, input1, (int) input2); + } else { + m = mathClass.getMethod(func, new Class[] { Double.TYPE, Double.TYPE }); + returnValue = m.invoke(null, input1, input2); + } + + try { + assertEquals(extra + ": " + m + ": " , expectedOutput, (double) returnValue, 0D); + } catch (ClassCastException e) { + assertEquals(extra + ": " + m + ": ", (int) expectedOutput, (int) returnValue, 0D); + } + } +} |