Committed by
Gerrit Code Review
Adds manually advancing timer.
Change-Id: I83936f4fff577b0f23404560c6ecfbc0c9f18e2e
Showing
4 changed files
with
298 additions
and
28 deletions
| ... | @@ -66,24 +66,37 @@ public final class TestUtils { | ... | @@ -66,24 +66,37 @@ public final class TestUtils { |
| 66 | * | 66 | * |
| 67 | * @param subject Object where the field belongs | 67 | * @param subject Object where the field belongs |
| 68 | * @param fieldName name of the field to get | 68 | * @param fieldName name of the field to get |
| 69 | - * @return value of the field. | ||
| 70 | * @param <T> subject type | 69 | * @param <T> subject type |
| 71 | - * @param <U> field value type | 70 | + * @param <U> fieldO value type |
| 71 | + * @return value of the field. | ||
| 72 | * @throws TestUtilsException if there are reflection errors while getting | 72 | * @throws TestUtilsException if there are reflection errors while getting |
| 73 | * the field | 73 | * the field |
| 74 | */ | 74 | */ |
| 75 | public static <T, U> U getField(T subject, String fieldName) | 75 | public static <T, U> U getField(T subject, String fieldName) |
| 76 | throws TestUtilsException { | 76 | throws TestUtilsException { |
| 77 | try { | 77 | try { |
| 78 | + NoSuchFieldException exception = null; | ||
| 78 | @SuppressWarnings("unchecked") | 79 | @SuppressWarnings("unchecked") |
| 79 | - Class<T> clazz = (Class<T>) subject.getClass(); | 80 | + Class clazz = subject.getClass(); |
| 81 | + while (clazz != null) { | ||
| 82 | + try { | ||
| 80 | Field field = clazz.getDeclaredField(fieldName); | 83 | Field field = clazz.getDeclaredField(fieldName); |
| 81 | field.setAccessible(true); | 84 | field.setAccessible(true); |
| 82 | 85 | ||
| 83 | @SuppressWarnings("unchecked") | 86 | @SuppressWarnings("unchecked") |
| 84 | U result = (U) field.get(subject); | 87 | U result = (U) field.get(subject); |
| 85 | return result; | 88 | return result; |
| 86 | - } catch (NoSuchFieldException | SecurityException | | 89 | + } catch (NoSuchFieldException e) { |
| 90 | + exception = e; | ||
| 91 | + if (clazz == clazz.getSuperclass()) { | ||
| 92 | + break; | ||
| 93 | + } | ||
| 94 | + clazz = clazz.getSuperclass(); | ||
| 95 | + } | ||
| 96 | + } | ||
| 97 | + throw new TestUtilsException("Field not found. " + fieldName, exception); | ||
| 98 | + | ||
| 99 | + } catch (SecurityException | | ||
| 87 | IllegalArgumentException | IllegalAccessException e) { | 100 | IllegalArgumentException | IllegalAccessException e) { |
| 88 | throw new TestUtilsException("getField failed", e); | 101 | throw new TestUtilsException("getField failed", e); |
| 89 | } | 102 | } | ... | ... |
| ... | @@ -15,23 +15,24 @@ | ... | @@ -15,23 +15,24 @@ |
| 15 | */ | 15 | */ |
| 16 | package org.onlab.util; | 16 | package org.onlab.util; |
| 17 | 17 | ||
| 18 | -import org.junit.Ignore; | ||
| 19 | import org.junit.Test; | 18 | import org.junit.Test; |
| 20 | 19 | ||
| 21 | import java.util.List; | 20 | import java.util.List; |
| 22 | -import java.util.Timer; | ||
| 23 | import java.util.stream.IntStream; | 21 | import java.util.stream.IntStream; |
| 24 | 22 | ||
| 25 | -import static org.junit.Assert.*; | 23 | +import static org.junit.Assert.assertEquals; |
| 24 | +import static org.junit.Assert.assertFalse; | ||
| 25 | +import static org.junit.Assert.assertTrue; | ||
| 26 | import static org.onlab.junit.TestTools.assertAfter; | 26 | import static org.onlab.junit.TestTools.assertAfter; |
| 27 | -import static org.onlab.junit.TestTools.delay; | ||
| 28 | 27 | ||
| 29 | /** | 28 | /** |
| 30 | * Tests the operation of the accumulator. | 29 | * Tests the operation of the accumulator. |
| 31 | */ | 30 | */ |
| 32 | public class AbstractAccumulatorTest { | 31 | public class AbstractAccumulatorTest { |
| 33 | 32 | ||
| 34 | - private final Timer timer = new Timer(); | 33 | + |
| 34 | + private final ManuallyAdvancingTimer timer = new ManuallyAdvancingTimer(); | ||
| 35 | + | ||
| 35 | 36 | ||
| 36 | @Test | 37 | @Test |
| 37 | public void basics() throws Exception { | 38 | public void basics() throws Exception { |
| ... | @@ -42,7 +43,6 @@ public class AbstractAccumulatorTest { | ... | @@ -42,7 +43,6 @@ public class AbstractAccumulatorTest { |
| 42 | assertEquals("incorrect idle ms", 70, accumulator.maxIdleMillis()); | 43 | assertEquals("incorrect idle ms", 70, accumulator.maxIdleMillis()); |
| 43 | } | 44 | } |
| 44 | 45 | ||
| 45 | - @Ignore("FIXME: timing sensitive test failing randomly.") | ||
| 46 | @Test | 46 | @Test |
| 47 | public void eventTrigger() { | 47 | public void eventTrigger() { |
| 48 | TestAccumulator accumulator = new TestAccumulator(); | 48 | TestAccumulator accumulator = new TestAccumulator(); |
| ... | @@ -52,43 +52,40 @@ public class AbstractAccumulatorTest { | ... | @@ -52,43 +52,40 @@ public class AbstractAccumulatorTest { |
| 52 | accumulator.add(new TestItem("d")); | 52 | accumulator.add(new TestItem("d")); |
| 53 | assertTrue("should not have fired yet", accumulator.batch.isEmpty()); | 53 | assertTrue("should not have fired yet", accumulator.batch.isEmpty()); |
| 54 | accumulator.add(new TestItem("e")); | 54 | accumulator.add(new TestItem("e")); |
| 55 | - delay(20); | 55 | + timer.advanceTimeMillis(20, 10); |
| 56 | assertFalse("should have fired", accumulator.batch.isEmpty()); | 56 | assertFalse("should have fired", accumulator.batch.isEmpty()); |
| 57 | assertEquals("incorrect batch", "abcde", accumulator.batch); | 57 | assertEquals("incorrect batch", "abcde", accumulator.batch); |
| 58 | } | 58 | } |
| 59 | 59 | ||
| 60 | - @Ignore("FIXME: timing sensitive test failing randomly.") | ||
| 61 | @Test | 60 | @Test |
| 62 | public void timeTrigger() { | 61 | public void timeTrigger() { |
| 63 | TestAccumulator accumulator = new TestAccumulator(); | 62 | TestAccumulator accumulator = new TestAccumulator(); |
| 64 | accumulator.add(new TestItem("a")); | 63 | accumulator.add(new TestItem("a")); |
| 65 | - delay(30); | 64 | + timer.advanceTimeMillis(30, 1); |
| 66 | assertTrue("should not have fired yet", accumulator.batch.isEmpty()); | 65 | assertTrue("should not have fired yet", accumulator.batch.isEmpty()); |
| 67 | accumulator.add(new TestItem("b")); | 66 | accumulator.add(new TestItem("b")); |
| 68 | - delay(30); | 67 | + timer.advanceTimeMillis(30, 1); |
| 69 | assertTrue("should not have fired yet", accumulator.batch.isEmpty()); | 68 | assertTrue("should not have fired yet", accumulator.batch.isEmpty()); |
| 70 | accumulator.add(new TestItem("c")); | 69 | accumulator.add(new TestItem("c")); |
| 71 | - delay(30); | 70 | + timer.advanceTimeMillis(30, 1); |
| 72 | assertTrue("should not have fired yet", accumulator.batch.isEmpty()); | 71 | assertTrue("should not have fired yet", accumulator.batch.isEmpty()); |
| 73 | accumulator.add(new TestItem("d")); | 72 | accumulator.add(new TestItem("d")); |
| 74 | - delay(60); | 73 | + timer.advanceTimeMillis(10, 10); |
| 75 | assertFalse("should have fired", accumulator.batch.isEmpty()); | 74 | assertFalse("should have fired", accumulator.batch.isEmpty()); |
| 76 | assertEquals("incorrect batch", "abcd", accumulator.batch); | 75 | assertEquals("incorrect batch", "abcd", accumulator.batch); |
| 77 | } | 76 | } |
| 78 | 77 | ||
| 79 | - @Ignore("FIXME: timing sensitive test failing randomly.") | ||
| 80 | @Test | 78 | @Test |
| 81 | public void idleTrigger() { | 79 | public void idleTrigger() { |
| 82 | TestAccumulator accumulator = new TestAccumulator(); | 80 | TestAccumulator accumulator = new TestAccumulator(); |
| 83 | accumulator.add(new TestItem("a")); | 81 | accumulator.add(new TestItem("a")); |
| 84 | assertTrue("should not have fired yet", accumulator.batch.isEmpty()); | 82 | assertTrue("should not have fired yet", accumulator.batch.isEmpty()); |
| 85 | accumulator.add(new TestItem("b")); | 83 | accumulator.add(new TestItem("b")); |
| 86 | - delay(80); | 84 | + timer.advanceTimeMillis(70, 10); |
| 87 | assertFalse("should have fired", accumulator.batch.isEmpty()); | 85 | assertFalse("should have fired", accumulator.batch.isEmpty()); |
| 88 | assertEquals("incorrect batch", "ab", accumulator.batch); | 86 | assertEquals("incorrect batch", "ab", accumulator.batch); |
| 89 | } | 87 | } |
| 90 | 88 | ||
| 91 | - @Ignore("FIXME: timing sensitive test failing randomly.") | ||
| 92 | @Test | 89 | @Test |
| 93 | public void readyIdleTrigger() { | 90 | public void readyIdleTrigger() { |
| 94 | TestAccumulator accumulator = new TestAccumulator(); | 91 | TestAccumulator accumulator = new TestAccumulator(); |
| ... | @@ -96,30 +93,28 @@ public class AbstractAccumulatorTest { | ... | @@ -96,30 +93,28 @@ public class AbstractAccumulatorTest { |
| 96 | accumulator.add(new TestItem("a")); | 93 | accumulator.add(new TestItem("a")); |
| 97 | assertTrue("should not have fired yet", accumulator.batch.isEmpty()); | 94 | assertTrue("should not have fired yet", accumulator.batch.isEmpty()); |
| 98 | accumulator.add(new TestItem("b")); | 95 | accumulator.add(new TestItem("b")); |
| 99 | - delay(80); | 96 | + timer.advanceTimeMillis(80, 1); |
| 100 | assertTrue("should not have fired yet", accumulator.batch.isEmpty()); | 97 | assertTrue("should not have fired yet", accumulator.batch.isEmpty()); |
| 101 | accumulator.ready = true; | 98 | accumulator.ready = true; |
| 102 | - delay(80); | 99 | + timer.advanceTimeMillis(80, 10); |
| 103 | assertFalse("should have fired", accumulator.batch.isEmpty()); | 100 | assertFalse("should have fired", accumulator.batch.isEmpty()); |
| 104 | assertEquals("incorrect batch", "ab", accumulator.batch); | 101 | assertEquals("incorrect batch", "ab", accumulator.batch); |
| 105 | } | 102 | } |
| 106 | 103 | ||
| 107 | - @Ignore("FIXME: timing sensitive test failing randomly.") | ||
| 108 | @Test | 104 | @Test |
| 109 | public void readyLongTrigger() { | 105 | public void readyLongTrigger() { |
| 110 | TestAccumulator accumulator = new TestAccumulator(); | 106 | TestAccumulator accumulator = new TestAccumulator(); |
| 111 | accumulator.ready = false; | 107 | accumulator.ready = false; |
| 112 | - delay(120); | 108 | + timer.advanceTimeMillis(120, 1); |
| 113 | assertTrue("should not have fired yet", accumulator.batch.isEmpty()); | 109 | assertTrue("should not have fired yet", accumulator.batch.isEmpty()); |
| 114 | accumulator.add(new TestItem("a")); | 110 | accumulator.add(new TestItem("a")); |
| 115 | assertTrue("should not have fired yet", accumulator.batch.isEmpty()); | 111 | assertTrue("should not have fired yet", accumulator.batch.isEmpty()); |
| 116 | accumulator.ready = true; | 112 | accumulator.ready = true; |
| 117 | - delay(80); | 113 | + timer.advanceTimeMillis(120, 10); |
| 118 | assertFalse("should have fired", accumulator.batch.isEmpty()); | 114 | assertFalse("should have fired", accumulator.batch.isEmpty()); |
| 119 | assertEquals("incorrect batch", "a", accumulator.batch); | 115 | assertEquals("incorrect batch", "a", accumulator.batch); |
| 120 | } | 116 | } |
| 121 | 117 | ||
| 122 | - @Ignore("FIXME: timing sensitive test failing randomly.") | ||
| 123 | @Test | 118 | @Test |
| 124 | public void readyMaxTrigger() { | 119 | public void readyMaxTrigger() { |
| 125 | TestAccumulator accumulator = new TestAccumulator(); | 120 | TestAccumulator accumulator = new TestAccumulator(); |
| ... | @@ -133,16 +128,16 @@ public class AbstractAccumulatorTest { | ... | @@ -133,16 +128,16 @@ public class AbstractAccumulatorTest { |
| 133 | assertTrue("should not have fired yet", accumulator.batch.isEmpty()); | 128 | assertTrue("should not have fired yet", accumulator.batch.isEmpty()); |
| 134 | accumulator.ready = true; | 129 | accumulator.ready = true; |
| 135 | accumulator.add(new TestItem("g")); | 130 | accumulator.add(new TestItem("g")); |
| 136 | - delay(5); | 131 | + timer.advanceTimeMillis(10, 10); |
| 137 | assertFalse("should have fired", accumulator.batch.isEmpty()); | 132 | assertFalse("should have fired", accumulator.batch.isEmpty()); |
| 138 | assertEquals("incorrect batch", "abcdefg", accumulator.batch); | 133 | assertEquals("incorrect batch", "abcdefg", accumulator.batch); |
| 139 | } | 134 | } |
| 140 | 135 | ||
| 141 | - @Ignore("FIXME: timing sensitive test failing randomly.") | ||
| 142 | @Test | 136 | @Test |
| 143 | public void stormTest() { | 137 | public void stormTest() { |
| 144 | TestAccumulator accumulator = new TestAccumulator(); | 138 | TestAccumulator accumulator = new TestAccumulator(); |
| 145 | IntStream.range(0, 1000).forEach(i -> accumulator.add(new TestItem("#" + i))); | 139 | IntStream.range(0, 1000).forEach(i -> accumulator.add(new TestItem("#" + i))); |
| 140 | + timer.advanceTimeMillis(1); | ||
| 146 | assertAfter(100, () -> assertEquals("wrong item count", 1000, accumulator.itemCount)); | 141 | assertAfter(100, () -> assertEquals("wrong item count", 1000, accumulator.itemCount)); |
| 147 | assertEquals("wrong batch count", 200, accumulator.batchCount); | 142 | assertEquals("wrong batch count", 200, accumulator.batchCount); |
| 148 | } | 143 | } |
| ... | @@ -180,5 +175,4 @@ public class AbstractAccumulatorTest { | ... | @@ -180,5 +175,4 @@ public class AbstractAccumulatorTest { |
| 180 | return ready; | 175 | return ready; |
| 181 | } | 176 | } |
| 182 | } | 177 | } |
| 183 | - | ||
| 184 | } | 178 | } | ... | ... |
This diff is collapsed. Click to expand it.
| 1 | +/* | ||
| 2 | + * Copyright 2015 Open Networking Laboratory | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | + | ||
| 17 | +package org.onlab.util; | ||
| 18 | + | ||
| 19 | +import com.google.common.collect.Lists; | ||
| 20 | +import org.junit.Before; | ||
| 21 | +import org.junit.Test; | ||
| 22 | + | ||
| 23 | +import java.util.ArrayList; | ||
| 24 | +import java.util.Date; | ||
| 25 | +import java.util.TimerTask; | ||
| 26 | +import java.util.concurrent.atomic.AtomicInteger; | ||
| 27 | + | ||
| 28 | +import static org.junit.Assert.assertEquals; | ||
| 29 | +import static org.junit.Assert.assertFalse; | ||
| 30 | +import static org.junit.Assert.assertTrue; | ||
| 31 | +import static org.onlab.junit.TestTools.delay; | ||
| 32 | + | ||
| 33 | +/** | ||
| 34 | + * Testing class for manually advancing timer. | ||
| 35 | + */ | ||
| 36 | +public class ManuallyAdvancingTimerTest { | ||
| 37 | + | ||
| 38 | + private ManuallyAdvancingTimer timer; | ||
| 39 | + | ||
| 40 | + /* Generates unique id's for TestTasks */ | ||
| 41 | + private AtomicInteger idGenerator; | ||
| 42 | + | ||
| 43 | + /* Tracks TestTasks in order of creation, tasks are automatically added at creation. */ | ||
| 44 | + private ArrayList<TestTask> taskList; | ||
| 45 | + | ||
| 46 | + /* Total number of tasks run */ | ||
| 47 | + private AtomicInteger tasksRunCount; | ||
| 48 | + | ||
| 49 | + // FIXME if this class fails first try increasing the real time delay to account for heavy system load. | ||
| 50 | + private static final int REAL_TIME_DELAY = 1; | ||
| 51 | + | ||
| 52 | + /** | ||
| 53 | + * Sets up the testing environment. | ||
| 54 | + */ | ||
| 55 | + @Before | ||
| 56 | + public void setup() { | ||
| 57 | + timer = new ManuallyAdvancingTimer(); | ||
| 58 | + idGenerator = new AtomicInteger(1); | ||
| 59 | + tasksRunCount = new AtomicInteger(0); | ||
| 60 | + taskList = Lists.newArrayList(); | ||
| 61 | + } | ||
| 62 | + | ||
| 63 | + /** | ||
| 64 | + * Tests the one time schedule with delay. | ||
| 65 | + * | ||
| 66 | + * @throws Exception throws an exception if the test fails | ||
| 67 | + */ | ||
| 68 | + @Test | ||
| 69 | + public void testScheduleByDelay() throws Exception { | ||
| 70 | + /* Test scheduling in the future as normal. */ | ||
| 71 | + timer.schedule(new TestTask(), 10); | ||
| 72 | + timer.advanceTimeMillis(5); | ||
| 73 | + assertFalse(taskList.get(0).hasRun()); | ||
| 74 | + timer.advanceTimeMillis(10, REAL_TIME_DELAY); | ||
| 75 | + assertTrue(taskList.get(0).hasRun()); | ||
| 76 | + | ||
| 77 | + /* Test scheduling with negative numbers */ | ||
| 78 | + timer.schedule(new TestTask(), -10); | ||
| 79 | + timer.advanceTimeMillis(5); | ||
| 80 | + assertFalse(taskList.get(1).hasRun()); | ||
| 81 | + timer.advanceTimeMillis(10, REAL_TIME_DELAY); | ||
| 82 | + assertTrue(taskList.get(1).hasRun()); | ||
| 83 | + | ||
| 84 | + /* Reset list, counter and timer for next test */ | ||
| 85 | + taskList.clear(); | ||
| 86 | + idGenerator.set(1); | ||
| 87 | + tasksRunCount.set(0); | ||
| 88 | + | ||
| 89 | + for (int i = 0; i < 50; i++) { | ||
| 90 | + timer.schedule(new TestTask(), i); | ||
| 91 | + } | ||
| 92 | + /* Test that a task scheduled for present is run and not placed in the queue */ | ||
| 93 | + assertEquals("Only the first task should have run.", 1, tasksRunCount.get()); | ||
| 94 | + | ||
| 95 | + for (int i = 2; i <= 50; i++) { | ||
| 96 | + timer.advanceTimeMillis(1, REAL_TIME_DELAY); | ||
| 97 | + assertEquals("One task should be executed per loop", i, tasksRunCount.get()); | ||
| 98 | + } | ||
| 99 | + /* Below tests ordered insertion, this will only be done once, it is the same for all schedule methods. */ | ||
| 100 | + | ||
| 101 | + tasksRunCount.set(0); | ||
| 102 | + | ||
| 103 | + for (int i = 0; i < 10; i++) { | ||
| 104 | + timer.schedule(new TestTask(), 500); | ||
| 105 | + } | ||
| 106 | + | ||
| 107 | + assertEquals("No new tasks should have been run since run count reset.", 0, tasksRunCount.get()); | ||
| 108 | + timer.schedule(new TestTask(), 10); | ||
| 109 | + assertEquals("No new tasks should have been run since run count reset.", 0, tasksRunCount.get()); | ||
| 110 | + timer.advanceTimeMillis(10, REAL_TIME_DELAY); | ||
| 111 | + assertEquals("One new tasks should have been run since run count reset.", 1, tasksRunCount.get()); | ||
| 112 | + timer.advanceTimeMillis(510, REAL_TIME_DELAY); | ||
| 113 | + assertEquals("Eleven new tasks should have been run since run count reset.", 11, tasksRunCount.get()); | ||
| 114 | + } | ||
| 115 | + | ||
| 116 | + /** | ||
| 117 | + * Tests scheduling for a particular date or time which may be in the past. | ||
| 118 | + * | ||
| 119 | + * @throws Exception throws an exception if the test fails | ||
| 120 | + */ | ||
| 121 | + @Test | ||
| 122 | + public void testScheduleByDate() throws Exception { | ||
| 123 | + /* Tests basic scheduling for future times. */ | ||
| 124 | + timer.schedule(new TestTask(), new Date(10)); | ||
| 125 | + timer.advanceTimeMillis(5); | ||
| 126 | + assertFalse(taskList.get(0).hasRun()); | ||
| 127 | + timer.advanceTimeMillis(10, REAL_TIME_DELAY); | ||
| 128 | + assertTrue(taskList.get(0).hasRun()); | ||
| 129 | + | ||
| 130 | + /* Test scheduling with past times numbers */ | ||
| 131 | + timer.schedule(new TestTask(), new Date(0)); | ||
| 132 | + delay(REAL_TIME_DELAY); | ||
| 133 | + assertTrue(taskList.get(1).hasRun()); | ||
| 134 | + | ||
| 135 | + /* Tests cancellation on non-periodic events */ | ||
| 136 | + TestTask task = new TestTask(); | ||
| 137 | + timer.schedule(task, new Date(timer.currentTimeInMillis() + 10)); | ||
| 138 | + task.cancel(); | ||
| 139 | + timer.advanceTimeMillis(12, REAL_TIME_DELAY); | ||
| 140 | + assertFalse(task.hasRun()); | ||
| 141 | + | ||
| 142 | + } | ||
| 143 | + | ||
| 144 | + /** | ||
| 145 | + * Test scheduling beginning after a delay and recurring periodically. | ||
| 146 | + * | ||
| 147 | + * @throws Exception throws an exception if the test fails | ||
| 148 | + */ | ||
| 149 | + @Test | ||
| 150 | + public void testScheduleByDelayPeriodic() throws Exception { | ||
| 151 | + /* Test straightforward periodic execution */ | ||
| 152 | + timer.schedule(new TestTask(), 0, 10); | ||
| 153 | + delay(REAL_TIME_DELAY); | ||
| 154 | + assertEquals("Task should have run once when added.", 1, taskList.get(0).timesRun()); | ||
| 155 | + | ||
| 156 | + /* Tests whether things that are not added to the queue are scheduled for future executions (ones which execute | ||
| 157 | + immediately on add). */ | ||
| 158 | + timer.advanceTimeMillis(10, REAL_TIME_DELAY); | ||
| 159 | + assertEquals("Task should have run once when added.", 2, taskList.get(0).timesRun()); | ||
| 160 | + | ||
| 161 | + /* Tests whether cancellation works on periodic events. */ | ||
| 162 | + taskList.get(0).cancel(); | ||
| 163 | + | ||
| 164 | + timer.advanceTimeMillis(10, REAL_TIME_DELAY); | ||
| 165 | + assertEquals("The task should not have run another time.", 2, taskList.get(0).timesRun()); | ||
| 166 | + | ||
| 167 | + TestTask task = new TestTask(); | ||
| 168 | + timer.schedule(task, 0, 10); | ||
| 169 | + timer.advanceTimeMillis(100, REAL_TIME_DELAY); | ||
| 170 | + assertEquals("Should have run immeditaley and subsequently once during the larger skip", task.timesRun(), 2); | ||
| 171 | + | ||
| 172 | + } | ||
| 173 | + | ||
| 174 | + /** | ||
| 175 | + * Test scheduling beginning at a specified date and recurring periodically. | ||
| 176 | + * | ||
| 177 | + * @throws Exception throws an exception if the test fails | ||
| 178 | + */ | ||
| 179 | + @Test | ||
| 180 | + public void testScheduleByDatePeriodic() throws Exception { | ||
| 181 | + /* Test straightforward periodic execution */ | ||
| 182 | + timer.schedule(new TestTask(), new Date(timer.currentTimeInMillis()), 10); | ||
| 183 | + delay(REAL_TIME_DELAY); | ||
| 184 | + assertEquals("Task should have run once when added.", 1, taskList.get(0).timesRun()); | ||
| 185 | + | ||
| 186 | + /* Tests whether things that are not added to the queue are scheduled for future executions (ones which execute | ||
| 187 | + immediately on add). */ | ||
| 188 | + timer.advanceTimeMillis(10, REAL_TIME_DELAY); | ||
| 189 | + assertEquals("Task should have run once when added.", 2, taskList.get(0).timesRun()); | ||
| 190 | + | ||
| 191 | + /* Tests whether cancellation works on periodic events. */ | ||
| 192 | + taskList.get(0).cancel(); | ||
| 193 | + | ||
| 194 | + timer.advanceTimeMillis(10, REAL_TIME_DELAY); | ||
| 195 | + assertEquals("The task should not have run another time.", 2, taskList.get(0).timesRun()); | ||
| 196 | + | ||
| 197 | + TestTask task = new TestTask(); | ||
| 198 | + timer.schedule(task, new Date(timer.currentTimeInMillis()), 10); | ||
| 199 | + timer.advanceTimeMillis(100, REAL_TIME_DELAY); | ||
| 200 | + assertEquals("Should have run immediately and subsequently once during the larger skip", task.timesRun(), 2); | ||
| 201 | + } | ||
| 202 | + | ||
| 203 | + /* Schedule at fixed rate runs exactly like the two scheduling methods just tested so tests are not included */ | ||
| 204 | + | ||
| 205 | + /** | ||
| 206 | + * Timer task with added functions to make it better for testing. | ||
| 207 | + */ | ||
| 208 | + private class TestTask extends TimerTask { | ||
| 209 | + | ||
| 210 | + /* Remains true once the task has been run at least once */ | ||
| 211 | + private boolean hasRun; | ||
| 212 | + | ||
| 213 | + /* Unique id per event. */ | ||
| 214 | + private int id; | ||
| 215 | + | ||
| 216 | + /* Specifies the number of times an event has run */ | ||
| 217 | + private int timesRun; | ||
| 218 | + | ||
| 219 | + /** | ||
| 220 | + * Constructor initializes id, timesRun, and id fields. | ||
| 221 | + */ | ||
| 222 | + public TestTask() { | ||
| 223 | + id = idGenerator.getAndIncrement(); | ||
| 224 | + timesRun = 0; | ||
| 225 | + hasRun = false; | ||
| 226 | + taskList.add(this); | ||
| 227 | + } | ||
| 228 | + | ||
| 229 | + @Override | ||
| 230 | + public void run() { | ||
| 231 | + this.hasRun = true; | ||
| 232 | + tasksRunCount.incrementAndGet(); | ||
| 233 | + timesRun++; | ||
| 234 | + } | ||
| 235 | + | ||
| 236 | + /** | ||
| 237 | + * Returns whether this event has run. | ||
| 238 | + * | ||
| 239 | + * @return true if the event has run, false otherwise. | ||
| 240 | + */ | ||
| 241 | + public boolean hasRun() { | ||
| 242 | + return hasRun; | ||
| 243 | + } | ||
| 244 | + | ||
| 245 | + /** | ||
| 246 | + * Returns the number of times this task has run. | ||
| 247 | + * | ||
| 248 | + * @return an int representing the number of times this task has been run | ||
| 249 | + */ | ||
| 250 | + public int timesRun() { | ||
| 251 | + return timesRun; | ||
| 252 | + } | ||
| 253 | + | ||
| 254 | + /** | ||
| 255 | + * Returns the unique identifier of this task. | ||
| 256 | + * | ||
| 257 | + * @return a unique integer identifier | ||
| 258 | + */ | ||
| 259 | + public int getId() { | ||
| 260 | + return id; | ||
| 261 | + } | ||
| 262 | + } | ||
| 263 | +} | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
-
Please register or login to post a comment