Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix jvmnativestest test_EnsureWallClockTime() #13896

Merged
merged 2 commits into from
Nov 10, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
/*[INCLUDE-IF Sidecar19-SE]*/
package com.ibm.oti.jvmtests;

import junit.framework.TestCase;

/*******************************************************************************
* Copyright (c) 2016, 2021 IBM Corp. and others
*
Expand All @@ -24,124 +20,148 @@
*
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
*******************************************************************************/
package com.ibm.oti.jvmtests;

import junit.framework.TestCase;

public class GetNanoTimeAdjustment extends TestCase {

static final long NANO_TIME_DIGITS = 19L;
static final long NANO_SECONDS_IN_SECOND = 1000000000L;
static final long TIME_MAX = 4294967295000000000L;
static final long FAIL_CODE = -1L;



/*
* Basic sanity test, can we invoke the function
*/
public void test_CallGetNanoTimeAdjustment() {
SupportJVM.GetNanoTimeAdjustment(0);
}



/*
* Make getNanoTime returns a value similar to System.currentTimeMillis()
* Make sure getNanoTime() returns a value similar to System.currentTimeMillis().
*/
public void test_EnsureWallClockTime() {
String nanoTime = Long.valueOf(SupportJVM.GetNanoTimeAdjustment(0)).toString();
String milliTime = Long.valueOf(System.currentTimeMillis()).toString();

/* accuracy of 1 second */
milliTime = milliTime.substring(0, milliTime.length() - 3);

assertTrue("nanotime is not similar to millitime", nanoTime.contains(milliTime));

long start = System.currentTimeMillis();
long maxDuration = 1_000; // one second
int equalMillisNeeded = 10;

for (;;) {
/*
* In general, we have no control over the elapsed time between
* the following three method invocations. On the other hand, we
* do expect the return values of GetNanoTimeAdjustment(0) to be
* consistent with the values returned by currentTimeMillis()
* (but scaled by a factor of a million).
*/
long millis1 = System.currentTimeMillis();
long nanoAdjustment = SupportJVM.GetNanoTimeAdjustment(0);
long millis2 = System.currentTimeMillis();

long elapsed = millis2 - start;
long nanosAsMillis = nanoAdjustment / 1_000_000;

if ((nanosAsMillis < millis1) || (millis2 < nanosAsMillis)) {
fail(String.format("nanotime(%d) is not similar to millitime(%d..%d)",
nanoAdjustment, millis1, millis2));
} else if (elapsed > maxDuration) {
break;
} else if (millis1 == millis2) {
equalMillisNeeded -= 1;
if (equalMillisNeeded <= 0) {
break;
}
}
}
}

/*
* Make sure returned value has 19 digits
*/
public void test_EnsureResultIsNanoSecondGranularity() {
long result = SupportJVM.GetNanoTimeAdjustment(0);
assertEquals("GetNanoTimeAdjustment did not return 19 digits", NANO_TIME_DIGITS, Long.toString(result).length());
}

/*
* A positive offset subtracts the amount (in seconds) to the current nano time
*/
public void test_PositiveOffset() {
/* pick an offset difference larger than the amount of time between the two method invocations */
long time1 = SupportJVM.GetNanoTimeAdjustment(0);
long time2 = SupportJVM.GetNanoTimeAdjustment(10);

assertTrue("Nano time offset was incorrectly calculated", time1 > time2);
}

/*
* Test the accuracy of the nano time offset to 1 second
*/
public void test_PositiveOffset2() {
long time1 = SupportJVM.GetNanoTimeAdjustment(0);
long time2 = SupportJVM.GetNanoTimeAdjustment(100);

/* test to an accuracy of 1sec,
* this should take into account the amount it takes to call both methods plus extra
*/
long accuracy = 1 * NANO_SECONDS_IN_SECOND;
long accuracy = 1 * NANO_SECONDS_IN_SECOND;
long offset = 100 * NANO_SECONDS_IN_SECOND;
long interval = time1 - time2;
boolean test = ( interval < (offset + accuracy)) && (interval > (offset - accuracy));
assertTrue("Nano time offset was incorrectly calculated", test);
boolean test = (interval < (offset + accuracy)) && (interval > (offset - accuracy));

assertTrue("Nano time offset was incorrectly calculated", test);
}



/*
* A negative offset adds the amount (in seconds) to the current nano time
*/
public void test_NegativeOffset() {
/* pick an offset difference larger than the amount of time between the two method invocations */
long time1 = SupportJVM.GetNanoTimeAdjustment(0);
long time2 = SupportJVM.GetNanoTimeAdjustment(-10);

assertTrue("Nano time offset was in correctly calculated", time1 < time2);
}

/*
* Test the accuracy of the nano time offset to 1 second
*/
public void test_NegativeOffset2() {
long time1 = SupportJVM.GetNanoTimeAdjustment(0);
long time2 = SupportJVM.GetNanoTimeAdjustment(-100);

/* test to an accuracy of 1sec,
* this should take into account the amount it takes to call both methods plus extra
*/
long accuracy = 1 * NANO_SECONDS_IN_SECOND;
*/
long accuracy = 1 * NANO_SECONDS_IN_SECOND;
long offset = 100 * NANO_SECONDS_IN_SECOND;
long interval = time2 - time1;
boolean test = (interval < (offset + accuracy)) && (interval > (offset - accuracy));
assertTrue("Nano time offset was in correctly calculated", test);

assertTrue("Nano time offset was in correctly calculated", test);
}

/*
* Test bounds. Based on Oracle behaviour a valid result must fall within -4294967295000000000 and
* +4294967295000000000 otherwise -1 is returned.
*/
public void test_UpperBound() {
long time1 = SupportJVM.GetNanoTimeAdjustment(Long.MIN_VALUE);
assertEquals("Failed upper bounds test: allowed an invalid offset", FAIL_CODE, time1);

/* Try with the lowest valid offset + 10 */
time1 = SupportJVM.GetNanoTimeAdjustment(0);
time1 = SupportJVM.GetNanoTimeAdjustment((-(TIME_MAX - time1)/NANO_SECONDS_IN_SECOND) + 10);
time1 = SupportJVM.GetNanoTimeAdjustment((-(TIME_MAX - time1) / NANO_SECONDS_IN_SECOND) + 10);
assertNotSame("Failed upper bounds test: incorrectly rejected a valid offest", FAIL_CODE, time1);
}

public void test_LowerBound() {
long time1 = SupportJVM.GetNanoTimeAdjustment(Long.MAX_VALUE);
assertEquals("Failed lower bounds test: allowed an invalid offset", FAIL_CODE, time1);

/* Try with the highest valid offset - 10 */
time1 = SupportJVM.GetNanoTimeAdjustment(0);
time1 = SupportJVM.GetNanoTimeAdjustment(((TIME_MAX + time1)/NANO_SECONDS_IN_SECOND) - 10);
time1 = SupportJVM.GetNanoTimeAdjustment(((TIME_MAX + time1) / NANO_SECONDS_IN_SECOND) - 10);
assertNotSame("Failed lower bounds test: incorrectly rejected a valid offest", FAIL_CODE, time1);
}
}