/**
* Copyright 2014-2016 Netflix, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.netflix.spectator.impl;
import com.netflix.spectator.api.Counter;
import com.netflix.spectator.api.DefaultRegistry;
import com.netflix.spectator.api.ManualClock;
import com.netflix.spectator.api.Registry;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import java.time.Duration;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
@RunWith(JUnit4.class)
public class SchedulerTest {
@Test
public void updateNextFixedDelay() {
ManualClock clock = new ManualClock();
Registry registry = new DefaultRegistry(clock);
Counter skipped = registry.counter("skipped");
Scheduler.Options options = new Scheduler.Options()
.withFrequency(Scheduler.Policy.FIXED_DELAY, Duration.ofSeconds(10));
clock.setWallTime(5437L);
Scheduler.DelayedTask task = new Scheduler.DelayedTask(clock, options, () -> {});
Assert.assertEquals(5437L, task.getNextExecutionTime());
Assert.assertEquals(0L, skipped.count());
clock.setWallTime(12123L);
task.updateNextExecutionTime(skipped);
Assert.assertEquals(22123L, task.getNextExecutionTime());
Assert.assertEquals(0L, skipped.count());
clock.setWallTime(27000L);
task.updateNextExecutionTime(skipped);
Assert.assertEquals(37000L, task.getNextExecutionTime());
Assert.assertEquals(0L, skipped.count());
}
@Test
public void updateNextFixedRateSkip() {
ManualClock clock = new ManualClock();
Registry registry = new DefaultRegistry(clock);
Counter skipped = registry.counter("skipped");
Scheduler.Options options = new Scheduler.Options()
.withFrequency(Scheduler.Policy.FIXED_RATE_SKIP_IF_LONG, Duration.ofSeconds(10));
clock.setWallTime(5437L);
Scheduler.DelayedTask task = new Scheduler.DelayedTask(clock, options, () -> {});
Assert.assertEquals(5437L, task.getNextExecutionTime());
Assert.assertEquals(0L, skipped.count());
clock.setWallTime(12123L);
task.updateNextExecutionTime(skipped);
Assert.assertEquals(15437L, task.getNextExecutionTime());
Assert.assertEquals(0L, skipped.count());
clock.setWallTime(27000L);
task.updateNextExecutionTime(skipped);
Assert.assertEquals(35437L, task.getNextExecutionTime());
Assert.assertEquals(1L, skipped.count());
clock.setWallTime(57000L);
task.updateNextExecutionTime(skipped);
Assert.assertEquals(65437L, task.getNextExecutionTime());
Assert.assertEquals(3L, skipped.count());
}
@Test
public void stopOnFailureFalse() throws Exception {
Scheduler s = new Scheduler(new DefaultRegistry(), "test", 2);
Scheduler.Options opts = new Scheduler.Options()
.withFrequency(Scheduler.Policy.FIXED_DELAY, Duration.ofMillis(10))
.withStopOnFailure(false);
final CountDownLatch latch = new CountDownLatch(5);
ScheduledFuture<?> f = s.schedule(opts, () -> {
latch.countDown();
throw new RuntimeException("stop");
});
Assert.assertTrue(latch.await(60, TimeUnit.SECONDS));
Assert.assertFalse(f.isDone());
s.shutdown();
}
@Test
public void stopOnFailureTrue() throws Exception {
Scheduler s = new Scheduler(new DefaultRegistry(), "test", 2);
Scheduler.Options opts = new Scheduler.Options()
.withFrequency(Scheduler.Policy.FIXED_DELAY, Duration.ofMillis(10))
.withStopOnFailure(true);
final CountDownLatch latch = new CountDownLatch(1);
ScheduledFuture<?> f = s.schedule(opts, () -> {
latch.countDown();
throw new RuntimeException("stop");
});
Assert.assertTrue(latch.await(60, TimeUnit.SECONDS));
while (!f.isDone()); // This will be an endless loop if broken
s.shutdown();
}
@Test
public void cancel() throws Exception {
Scheduler s = new Scheduler(new DefaultRegistry(), "test", 2);
Scheduler.Options opts = new Scheduler.Options()
.withFrequency(Scheduler.Policy.FIXED_DELAY, Duration.ofMillis(10))
.withStopOnFailure(false);
final CountDownLatch latch = new CountDownLatch(1);
final AtomicReference<ScheduledFuture<?>> ref = new AtomicReference<>();
ref.set(s.schedule(opts, () -> {
try {
while (ref.get() == null);
ref.get().cancel(true);
Thread.sleep(600000L);
} catch (InterruptedException e) {
latch.countDown();
}
}));
Assert.assertTrue(latch.await(60, TimeUnit.SECONDS));
Assert.assertTrue(ref.get().isDone());
s.shutdown();
}
@Test
public void threadsAreReplaced() throws Exception {
Scheduler s = new Scheduler(new DefaultRegistry(), "test", 1);
Scheduler.Options opts = new Scheduler.Options()
.withFrequency(Scheduler.Policy.FIXED_DELAY, Duration.ofMillis(10))
.withStopOnFailure(false);
final CountDownLatch latch = new CountDownLatch(10);
s.schedule(opts, () -> {
latch.countDown();
Thread.currentThread().interrupt();
});
Assert.assertTrue(latch.await(60, TimeUnit.SECONDS));
s.shutdown();
}
}