AbstractScheduledEventExecutor.schedule(...) must accept delay <= 0.
Motivation: As the javadoc of ScheduledExecutorService state: Zero and negative delays (but not periods) are also allowed in schedule methods,and are treated as requests for immediate execution. Modifications: - Correctly handle delay <= 0. - Add unit tests. Result: Fixes [#6627].
This commit is contained in:
parent
119383873d
commit
1b0b8f80cd
@ -131,12 +131,11 @@ public abstract class AbstractScheduledEventExecutor extends AbstractEventExecut
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) {
|
public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) {
|
||||||
ObjectUtil.checkNotNull(command, "command");
|
ObjectUtil.checkNotNull(command, "command");
|
||||||
ObjectUtil.checkNotNull(unit, "unit");
|
ObjectUtil.checkNotNull(unit, "unit");
|
||||||
if (delay < 0) {
|
if (delay < 0) {
|
||||||
throw new IllegalArgumentException(
|
delay = 0;
|
||||||
String.format("delay: %d (expected: >= 0)", delay));
|
|
||||||
}
|
}
|
||||||
return schedule(new ScheduledFutureTask<Void>(
|
return schedule(new ScheduledFutureTask<Void>(
|
||||||
this, command, null, ScheduledFutureTask.deadlineNanos(unit.toNanos(delay))));
|
this, command, null, ScheduledFutureTask.deadlineNanos(unit.toNanos(delay))));
|
||||||
@ -147,8 +146,7 @@ public abstract class AbstractScheduledEventExecutor extends AbstractEventExecut
|
|||||||
ObjectUtil.checkNotNull(callable, "callable");
|
ObjectUtil.checkNotNull(callable, "callable");
|
||||||
ObjectUtil.checkNotNull(unit, "unit");
|
ObjectUtil.checkNotNull(unit, "unit");
|
||||||
if (delay < 0) {
|
if (delay < 0) {
|
||||||
throw new IllegalArgumentException(
|
delay = 0;
|
||||||
String.format("delay: %d (expected: >= 0)", delay));
|
|
||||||
}
|
}
|
||||||
return schedule(new ScheduledFutureTask<V>(
|
return schedule(new ScheduledFutureTask<V>(
|
||||||
this, callable, ScheduledFutureTask.deadlineNanos(unit.toNanos(delay))));
|
this, callable, ScheduledFutureTask.deadlineNanos(unit.toNanos(delay))));
|
||||||
|
@ -0,0 +1,144 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2017 The Netty Project
|
||||||
|
*
|
||||||
|
* The Netty Project licenses this file to you 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 io.netty.util.concurrent;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
|
||||||
|
public class AbstractScheduledEventExecutorTest {
|
||||||
|
private static final Runnable TEST_RUNNABLE = new Runnable() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final Callable<?> TEST_CALLABLE = Executors.callable(TEST_RUNNABLE);
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testScheduleRunnableZero() {
|
||||||
|
TestScheduledEventExecutor executor = new TestScheduledEventExecutor();
|
||||||
|
ScheduledFuture<?> future = executor.schedule(TEST_RUNNABLE, 0, TimeUnit.NANOSECONDS);
|
||||||
|
assertEquals(0, future.getDelay(TimeUnit.NANOSECONDS));
|
||||||
|
assertNotNull(executor.pollScheduledTask());
|
||||||
|
assertNull(executor.pollScheduledTask());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testScheduleRunnableNegative() {
|
||||||
|
TestScheduledEventExecutor executor = new TestScheduledEventExecutor();
|
||||||
|
ScheduledFuture<?> future = executor.schedule(TEST_RUNNABLE, -1, TimeUnit.NANOSECONDS);
|
||||||
|
assertEquals(0, future.getDelay(TimeUnit.NANOSECONDS));
|
||||||
|
assertNotNull(executor.pollScheduledTask());
|
||||||
|
assertNull(executor.pollScheduledTask());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testScheduleCallableZero() {
|
||||||
|
TestScheduledEventExecutor executor = new TestScheduledEventExecutor();
|
||||||
|
ScheduledFuture<?> future = executor.schedule(TEST_CALLABLE, 0, TimeUnit.NANOSECONDS);
|
||||||
|
assertEquals(0, future.getDelay(TimeUnit.NANOSECONDS));
|
||||||
|
assertNotNull(executor.pollScheduledTask());
|
||||||
|
assertNull(executor.pollScheduledTask());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testScheduleCallableNegative() {
|
||||||
|
TestScheduledEventExecutor executor = new TestScheduledEventExecutor();
|
||||||
|
ScheduledFuture<?> future = executor.schedule(TEST_CALLABLE, -1, TimeUnit.NANOSECONDS);
|
||||||
|
assertEquals(0, future.getDelay(TimeUnit.NANOSECONDS));
|
||||||
|
assertNotNull(executor.pollScheduledTask());
|
||||||
|
assertNull(executor.pollScheduledTask());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalArgumentException.class)
|
||||||
|
public void testScheduleAtFixedRateRunnableZero() {
|
||||||
|
TestScheduledEventExecutor executor = new TestScheduledEventExecutor();
|
||||||
|
executor.scheduleAtFixedRate(TEST_RUNNABLE, 0, 0, TimeUnit.DAYS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalArgumentException.class)
|
||||||
|
public void testScheduleAtFixedRateRunnableNegative() {
|
||||||
|
TestScheduledEventExecutor executor = new TestScheduledEventExecutor();
|
||||||
|
executor.scheduleAtFixedRate(TEST_RUNNABLE, 0, -1, TimeUnit.DAYS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalArgumentException.class)
|
||||||
|
public void testScheduleWithFixedDelayZero() {
|
||||||
|
TestScheduledEventExecutor executor = new TestScheduledEventExecutor();
|
||||||
|
executor.scheduleWithFixedDelay(TEST_RUNNABLE, 0, -1, TimeUnit.DAYS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalArgumentException.class)
|
||||||
|
public void testScheduleWithFixedDelayNegative() {
|
||||||
|
TestScheduledEventExecutor executor = new TestScheduledEventExecutor();
|
||||||
|
executor.scheduleWithFixedDelay(TEST_RUNNABLE, 0, -1, TimeUnit.DAYS);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class TestScheduledEventExecutor extends AbstractScheduledEventExecutor {
|
||||||
|
@Override
|
||||||
|
public boolean isShuttingDown() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean inEventLoop(Thread thread) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void shutdown() {
|
||||||
|
// NOOP
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Future<?> shutdownGracefully(long quietPeriod, long timeout, TimeUnit unit) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Future<?> terminationFuture() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isShutdown() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isTerminated() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean awaitTermination(long timeout, TimeUnit unit) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(Runnable command) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user