|
23 | 23 | import com.google.errorprone.annotations.CanIgnoreReturnValue;
|
24 | 24 | import java.lang.reflect.InvocationTargetException;
|
25 | 25 | import java.lang.reflect.Method;
|
| 26 | +import java.time.Duration; |
| 27 | +import java.util.ArrayList; |
26 | 28 | import java.util.Arrays;
|
27 | 29 | import java.util.Comparator;
|
| 30 | +import java.util.List; |
28 | 31 | import java.util.Locale;
|
29 | 32 | import java.util.concurrent.CountDownLatch;
|
30 | 33 | import java.util.concurrent.FutureTask;
|
@@ -57,7 +60,7 @@ public static TestSuite suite() {
|
57 | 60 | }
|
58 | 61 | }
|
59 | 62 |
|
60 |
| - assertEquals(548, suite.testCount()); |
| 63 | + assertEquals(980, suite.testCount()); |
61 | 64 |
|
62 | 65 | return suite;
|
63 | 66 | }
|
@@ -185,14 +188,26 @@ private static boolean isGuarded(Method method) {
|
185 | 188 | return parameterTypes.length >= 1 && parameterTypes[0] == Monitor.Guard.class;
|
186 | 189 | }
|
187 | 190 |
|
188 |
| - /** Determines whether the given method takes a time and unit as its last two parameters. */ |
| 191 | + /** Determines whether the given method is time-based. */ |
189 | 192 | private static boolean isTimed(Method method) {
|
| 193 | + return isLongTimeUnitBased(method) || isDurationBased(method); |
| 194 | + } |
| 195 | + |
| 196 | + /** Determines whether the given method takes a time and unit as its last two parameters. */ |
| 197 | + private static boolean isLongTimeUnitBased(Method method) { |
190 | 198 | Class<?>[] parameterTypes = method.getParameterTypes();
|
191 | 199 | return parameterTypes.length >= 2
|
192 | 200 | && parameterTypes[parameterTypes.length - 2] == long.class
|
193 | 201 | && parameterTypes[parameterTypes.length - 1] == TimeUnit.class;
|
194 | 202 | }
|
195 | 203 |
|
| 204 | + /** Determines whether the given method takes a Duration as its last parameter. */ |
| 205 | + private static boolean isDurationBased(Method method) { |
| 206 | + Class<?>[] parameterTypes = method.getParameterTypes(); |
| 207 | + return parameterTypes.length >= 1 |
| 208 | + && parameterTypes[parameterTypes.length - 1] == Duration.class; |
| 209 | + } |
| 210 | + |
196 | 211 | /** Determines whether the given method returns a boolean value. */
|
197 | 212 | private static boolean isBoolean(Method method) {
|
198 | 213 | return method.getReturnType() == boolean.class;
|
@@ -232,11 +247,21 @@ private static void validateMethod(Method method) {
|
232 | 247 | assertFalse(desc, isTimed(method));
|
233 | 248 | break;
|
234 | 249 | case 1:
|
235 |
| - assertTrue(desc, isGuarded(method)); |
236 |
| - assertFalse(desc, isTimed(method)); |
| 250 | + if (isDurationBased(method)) { |
| 251 | + assertFalse(desc, isGuarded(method)); |
| 252 | + } else { |
| 253 | + assertTrue(desc, isGuarded(method)); |
| 254 | + } |
| 255 | + // we can't make an assumption about isTimed() because now we have single-parameter methods |
| 256 | + // that accept a java.time.Duration |
| 257 | + assertFalse(desc, isLongTimeUnitBased(method)); |
237 | 258 | break;
|
238 | 259 | case 2:
|
239 |
| - assertFalse(desc, isGuarded(method)); |
| 260 | + if (isDurationBased(method)) { |
| 261 | + assertTrue(desc, isGuarded(method)); |
| 262 | + } else { |
| 263 | + assertFalse(desc, isGuarded(method)); |
| 264 | + } |
240 | 265 | assertTrue(desc, isTimed(method));
|
241 | 266 | break;
|
242 | 267 | case 3:
|
@@ -622,21 +647,22 @@ private void doWaitScenarioSetUp() {
|
622 | 647 | }
|
623 | 648 |
|
624 | 649 | private Outcome doCall() {
|
625 |
| - boolean guarded = isGuarded(method); |
626 |
| - boolean timed = isTimed(method); |
627 |
| - Object[] arguments = new Object[(guarded ? 1 : 0) + (timed ? 2 : 0)]; |
628 |
| - if (guarded) { |
629 |
| - arguments[0] = guard; |
| 650 | + List<Object> arguments = new ArrayList<>(); |
| 651 | + if (isGuarded(method)) { |
| 652 | + arguments.add(guard); |
| 653 | + } |
| 654 | + if (isLongTimeUnitBased(method)) { |
| 655 | + arguments.add(timeout.millis); |
| 656 | + arguments.add(TimeUnit.MILLISECONDS); |
630 | 657 | }
|
631 |
| - if (timed) { |
632 |
| - arguments[arguments.length - 2] = timeout.millis; |
633 |
| - arguments[arguments.length - 1] = TimeUnit.MILLISECONDS; |
| 658 | + if (isDurationBased(method)) { |
| 659 | + arguments.add(Duration.ofMillis(timeout.millis)); |
634 | 660 | }
|
635 | 661 | try {
|
636 | 662 | Object result;
|
637 | 663 | doingCallLatch.countDown();
|
638 | 664 | try {
|
639 |
| - result = method.invoke(monitor, arguments); |
| 665 | + result = method.invoke(monitor, arguments.toArray()); |
640 | 666 | } finally {
|
641 | 667 | callCompletedLatch.countDown();
|
642 | 668 | }
|
@@ -721,16 +747,23 @@ protected void runTest() throws Throwable {
|
721 | 747 | Monitor monitor1 = new Monitor(fair1);
|
722 | 748 | Monitor monitor2 = new Monitor(fair2);
|
723 | 749 | FlagGuard guard = new FlagGuard(monitor2);
|
724 |
| - Object[] arguments = |
725 |
| - (timed ? new Object[] {guard, 0L, TimeUnit.MILLISECONDS} : new Object[] {guard}); |
| 750 | + List<Object> arguments = new ArrayList<>(); |
| 751 | + arguments.add(guard); |
| 752 | + if (isDurationBased(method)) { |
| 753 | + arguments.add(Duration.ZERO); |
| 754 | + } |
| 755 | + if (isLongTimeUnitBased(method)) { |
| 756 | + arguments.add(0L); |
| 757 | + arguments.add(TimeUnit.MILLISECONDS); |
| 758 | + } |
726 | 759 | boolean occupyMonitor = isWaitFor(method);
|
727 | 760 | if (occupyMonitor) {
|
728 | 761 | // If we don't already occupy the monitor, we'll get an IMSE regardless of the guard (see
|
729 | 762 | // generateWaitForWhenNotOccupyingTestCase).
|
730 | 763 | monitor1.enter();
|
731 | 764 | }
|
732 | 765 | try {
|
733 |
| - method.invoke(monitor1, arguments); |
| 766 | + method.invoke(monitor1, arguments.toArray()); |
734 | 767 | fail("expected IllegalMonitorStateException");
|
735 | 768 | } catch (InvocationTargetException e) {
|
736 | 769 | assertEquals(IllegalMonitorStateException.class, e.getTargetException().getClass());
|
@@ -760,10 +793,17 @@ private static TestCase generateWaitForWhenNotOccupyingTestCase(
|
760 | 793 | protected void runTest() throws Throwable {
|
761 | 794 | Monitor monitor = new Monitor(fair);
|
762 | 795 | FlagGuard guard = new FlagGuard(monitor);
|
763 |
| - Object[] arguments = |
764 |
| - (timed ? new Object[] {guard, 0L, TimeUnit.MILLISECONDS} : new Object[] {guard}); |
| 796 | + List<Object> arguments = new ArrayList<>(); |
| 797 | + arguments.add(guard); |
| 798 | + if (isDurationBased(method)) { |
| 799 | + arguments.add(Duration.ZERO); |
| 800 | + } |
| 801 | + if (isLongTimeUnitBased(method)) { |
| 802 | + arguments.add(0L); |
| 803 | + arguments.add(TimeUnit.MILLISECONDS); |
| 804 | + } |
765 | 805 | try {
|
766 |
| - method.invoke(monitor, arguments); |
| 806 | + method.invoke(monitor, arguments.toArray()); |
767 | 807 | fail("expected IllegalMonitorStateException");
|
768 | 808 | } catch (InvocationTargetException e) {
|
769 | 809 | assertEquals(IllegalMonitorStateException.class, e.getTargetException().getClass());
|
|
0 commit comments