Skip to content

Commit

Permalink
Add new build test for Math.max and Math.min
Browse files Browse the repository at this point in the history
Add functional tests for `Math.max` and `Math.min`:
- to test specific float and double corner cases
- test with NaN, +0, & -0, values to confirm respective omr changes
- test all possible execution paths

Signed-off-by: Matthew Hall <[email protected]>
  • Loading branch information
matthewhall2 committed Oct 28, 2024
1 parent 96ba473 commit 57b4d0e
Show file tree
Hide file tree
Showing 2 changed files with 407 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,28 +23,35 @@
package jit.test.recognizedMethod;
import org.testng.AssertJUnit;
import org.testng.annotations.Test;
import java.util.Random;
import org.testng.asserts.SoftAssert;
import static jit.test.recognizedMethod.TestMathUtils.*;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Listeners;


@Test(singleThreaded=true)
public class TestJavaLangMath {

/**
* Tests the constant corner cases defined by the {@link Math.sqrt} method.
* <p>
* The JIT compiler will transform calls to {@link Math.sqrt} within this test
* into the following tree sequence:
*
* <code>
* dsqrt
* dconst <x>
* </code>
*
* Subsequent tree simplification passes will attempt to reduce this constant
* operation to a <code>dsqrt</code> IL by performing the square root at compile
* time. The transformation will be performed when the function get executed
* twice, therefore, the "invocationCount=2" is needed. However we must ensure the
* result of the square root done by the compiler at compile time will be exactly
* the same as the result had it been done by the Java runtime at runtime. This
* test validates the results are the same.
*/
* Tests the constant corner cases defined by the {@link Math.sqrt} method.
* <p>
* The JIT compiler will transform calls to {@link Math.sqrt} within this test
* into the following tree sequence:
*
* <code>
* dsqrt
* dconst <x>
* </code>
*
* Subsequent tree simplification passes will attempt to reduce this constant
* operation to a <code>dsqrt</code> IL by performing the square root at compile
* time. The transformation will be performed when the function get executed
* twice, therefore, the "invocationCount=2" is needed. However we must ensure the
* result of the square root done by the compiler at compile time will be exactly
* the same as the result had it been done by the Java runtime at runtime. This
* test validates the results are the same.
*/
@Test(groups = {"level.sanity"}, invocationCount=2)
public void test_java_lang_Math_sqrt() {
AssertJUnit.assertTrue(Double.isNaN(Math.sqrt(Double.NEGATIVE_INFINITY)));
Expand All @@ -55,4 +62,86 @@ public void test_java_lang_Math_sqrt() {
AssertJUnit.assertEquals(Double.POSITIVE_INFINITY, Math.sqrt(Double.POSITIVE_INFINITY));
AssertJUnit.assertTrue(Double.isNaN(Math.sqrt(Double.NaN)));
}

@Test(groups = {"level.sanity"}, invocationCount=2, dataProvider="zeroProvider", dataProviderClass=TestMathUtils.class)
public void test_java_lang_Math_min_zeros_FD(Number a, Number b, boolean isFirstArg) {
if (a instanceof Float) {
float f1 = a.floatValue();
float f2 = b.floatValue();
assertEquals(Math.min(f1, f2), isFirstArg ? f1 : f2);
} else {
double f1 = a.doubleValue();
double f2 = b.doubleValue();
assertEquals(Math.min(f1, f2), isFirstArg ? f1 : f2);
}
}

@Test(groups = {"level.sanity"}, invocationCount=2, dataProvider="zeroProvider", dataProviderClass=TestMathUtils.class)
public void test_java_lang_Math_max_zeros_FD(Number a, Number b, boolean isFirstArg) {
if (a instanceof Float) {
float f1 = a.floatValue();
float f2 = b.floatValue();
assertEquals(Math.max(f1, f2), isFirstArg ? f2 : f1);
} else {
double f1 = a.doubleValue();
double f2 = b.doubleValue();
assertEquals(Math.max(f1, f2), isFirstArg ? f2 : f1);
}
}

@Test(groups = {"level.sanity"}, invocationCount=2, dataProvider="nanProvider", dataProviderClass=TestMathUtils.class)
public void test_java_lang_Math_min_nan_FD(Number a, Number b, Number expected) {
if (a instanceof Float) {
float f1 = a.floatValue();
float f2 = b.floatValue();
int exp = expected.intValue();
assertEquals(Math.min(f1, f2), exp);
} else {
double f1 = a.doubleValue();
double f2 = b.doubleValue();
long exp = expected.longValue();
assertEquals(Math.min(f1, f2), exp);
}
}

@Test(groups = {"level.sanity"}, invocationCount=2, dataProvider="nanProvider", dataProviderClass=TestMathUtils.class)
public void test_java_lang_Math_max_nan_FD(Number a, Number b, Number expected) {
if (a instanceof Float) {
float f1 = a.floatValue();
float f2 = b.floatValue();
int exp = expected.intValue();
assertEquals(Math.max(f1, f2), exp);
} else {
double f1 = a.doubleValue();
double f2 = b.doubleValue();
long exp = expected.longValue();
assertEquals(Math.max(f1, f2), exp);
}
}

@Test(groups = {"level.sanity"}, invocationCount=2, dataProvider="normalNumberProvider", dataProviderClass=TestMathUtils.class)
public void test_java_lang_Math_min_normal_FD(Number a, Number b){
if (a instanceof Float) {
float f1 = a.floatValue();
float f2 = b.floatValue();
assertEquals(Math.min(f1, f2), f1 <= f2 ? f1 : f2);
} else {
double f1 = a.doubleValue();
double f2 = b.doubleValue();
assertEquals(Math.min(f1, f2), f1 <= f2 ? f1 : f2);
}
}

@Test(groups = {"level.sanity"}, invocationCount=2, dataProvider="normalNumberProvider", dataProviderClass=TestMathUtils.class)
public void test_java_lang_Math_max_normal_FD(Number a, Number b){
if (a instanceof Float) {
float f1 = a.floatValue();
float f2 = b.floatValue();
assertEquals(Math.max(f1, f2), f1 >= f2 ? f1 : f2);
} else {
double f1 = a.doubleValue();
double f2 = b.doubleValue();
assertEquals(Math.max(f1, f2), f1 >= f2 ? f1 : f2);
}
}
}
Loading

0 comments on commit 57b4d0e

Please sign in to comment.