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
VirtualTimeScheduler does not advance time if there is nothing on the drain queue #1251
Comments
I had to use a hack in the unit test to actually cause time advancement: vts.advanceTimeBy(Duration.ofMillis(millis)); |
I'm not sure your test makes sense to me. If you create some timed operation, shouldn't you advance the time before you block? At this point, there's a timed operation in the queue and the |
I think this test would demo the issue. IMO there nothing in this test that should fail, but it does. My test cases are more complex, but involve the same issue.
|
I have a similar issue but I don't know if they are connected with the previous comment. The problem is that when using Library is being used: reactor-test-3.2.3.RELEASE.jar public class VirtualSchedulerTest {
private VirtualTimeScheduler underTest;
@Before
public void setUp() throws Exception {
underTest = VirtualTimeScheduler.create();
}
@Test
public void nowDoesNotReflectVirtualTimeInSchedule() {
ZonedDateTime start = ZonedDateTime.of(2019, 3, 10, 8, 0, 0, 0, ZoneOffset.UTC);
underTest.advanceTimeTo(start.toInstant());
// Good: 2019-03-10T08:00Z
printSchedulerTime();
underTest.advanceTimeBy(Duration.ofHours(1));
// Good: 2019-03-10T09:00Z
printSchedulerTime();
// Wrong: 1970-01-01T01:00Z
// Expected : 2019-03-10T10:00Z
underTest.schedule(this::printSchedulerTime, 1, TimeUnit.HOURS);
underTest.advanceTimeBy(Duration.ofHours(1));
// 2019-03-10T10:00Z
printSchedulerTime();
}
private void printSchedulerTime() {
ZonedDateTime now = Instant.ofEpochMilli(underTest.now(TimeUnit.MILLISECONDS)).atZone(ZoneOffset.UTC);
System.out.println(now);
}
} |
A simpler test case based on @lestarcdog 's sample: package pl.allegro.badges.bargains.badgeradmin.domain.campaign;
import org.junit.Test;
import reactor.test.scheduler.VirtualTimeScheduler;
import java.time.Duration;
import java.time.Instant;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static org.junit.Assert.assertEquals;
public class VirtualSchedulerTest {
@Test
public void nowDoesNotReflectVirtualTimeInSchedule() {
VirtualTimeScheduler underTest = VirtualTimeScheduler.create();
underTest.advanceTimeTo(Instant.ofEpochMilli(0));
assertEquals(0, underTest.now(MILLISECONDS));
underTest.advanceTimeBy(Duration.ofSeconds(1));
assertEquals(1_000, underTest.now(MILLISECONDS));
AtomicLong inJob = new AtomicLong();
underTest.schedule(() -> inJob.set(underTest.now(MILLISECONDS)), 1, TimeUnit.SECONDS);
underTest.advanceTimeBy(Duration.ofSeconds(1));
assertEquals(2_000, underTest.now(MILLISECONDS));
assertEquals(2_000, inJob.get());
}
} The last assertion fails on 3.1.7 upwards, test passes on 3.1.6 (before |
Original problem still reproduced as of
The problem is that |
Looks like this issue was introduced intentionally in 4b4f20a
Although the fix does not seem to be ideal. Perhaps just need to document the hack. |
I suspect this behavior would be important for any case that involves using the VTS in a non-trivial |
I would add overload with additional Although need to dig further and look through those invocations first. I can prepare the pull request if you agree. |
@yarosla yeah let's explore how that looks, please prepare that PR 👍
There is probably a bunch of tests that use |
For reference, the idea of putting the parameter at the |
…te()` method
Created pull request #2017 |
|
Expected behavior
VirtualTimeScheduler.advanceTimeBy actually advances the time for the following operations using the scheduler.
Actual behavior
When timedTask is scheduled it uses nanoTime as a starting point.
final TimedRunnable timedTask = new TimedRunnable(this,
nanoTime + unit.toNanos(delayTime),
However now() uses nanoTime + deferredNanoTime.
Also nanoTime is only updated to the sum of nanoTime and deferredNanoTime in the drain method, but only if the queue is not empty.
So advancing time between running timed reactor operations does not work. The following test loop iteration does not take the advanced time into account.
Steps to reproduce
for (int i = 0; i <test.size(); i++) {
Mono mono = createSomeTimedOperation(test.get(i));
assertValue(test.get(i), mono.block());
// at this point there is nothing in the drain queue, so nanoTime is not updated
// next loop iteration will take original nanoTime as base for the timeout.
vts.advanceTimeBy(Duration.ofMillis(delay));
}
Reactor Core version
3.1.7
JVM version (e.g.
java -version
)The text was updated successfully, but these errors were encountered: