-
Notifications
You must be signed in to change notification settings - Fork 7.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Improve performance of NewThreadWorker.tryEnableCancelPolicy().
Disable search for ScheduledExecutorService.setRemoveOnCancelPolicy() on Android API < 21
- Loading branch information
1 parent
3494c00
commit 81b1951
Showing
3 changed files
with
228 additions
and
29 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
118 changes: 118 additions & 0 deletions
118
src/test/java/rx/internal/schedulers/NewThreadWorkerTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
package rx.internal.schedulers; | ||
|
||
import org.junit.Test; | ||
|
||
import java.lang.reflect.Field; | ||
import java.lang.reflect.Method; | ||
import java.util.concurrent.ScheduledExecutorService; | ||
import java.util.concurrent.ScheduledThreadPoolExecutor; | ||
import java.util.concurrent.atomic.AtomicBoolean; | ||
|
||
import static java.lang.reflect.Modifier.FINAL; | ||
import static org.junit.Assert.*; | ||
import static org.mockito.Mockito.*; | ||
|
||
public class NewThreadWorkerTest { | ||
|
||
@Test | ||
public void findSetRemoveOnCancelPolicyMethodShouldFindMethod() { | ||
ScheduledExecutorService executor = spy(new ScheduledThreadPoolExecutor(1)); | ||
Method setRemoveOnCancelPolicyMethod = NewThreadWorker.findSetRemoveOnCancelPolicyMethod(executor); | ||
|
||
assertNotNull(setRemoveOnCancelPolicyMethod); | ||
assertEquals("setRemoveOnCancelPolicy", setRemoveOnCancelPolicyMethod.getName()); | ||
assertEquals(1, setRemoveOnCancelPolicyMethod.getParameterTypes().length); | ||
assertEquals(Boolean.TYPE, setRemoveOnCancelPolicyMethod.getParameterTypes()[0]); | ||
verifyZeroInteractions(executor); | ||
} | ||
|
||
@Test | ||
public void findSetRemoveOnCancelPolicyMethodShouldNotFindMethod() { | ||
ScheduledExecutorService executor = mock(ScheduledExecutorService.class); | ||
|
||
Method setRemoveOnCancelPolicyMethod = NewThreadWorker.findSetRemoveOnCancelPolicyMethod(executor); | ||
assertNull(setRemoveOnCancelPolicyMethod); | ||
verifyZeroInteractions(executor); | ||
} | ||
|
||
@Test | ||
public void tryEnableCancelPolicyShouldInvokeMethodOnExecutor() { | ||
final AtomicBoolean setRemoveOnCancelPolicyWasInvoked = new AtomicBoolean(); | ||
|
||
ScheduledExecutorService executor = new ScheduledThreadPoolExecutor(1) { | ||
// @Override is not used here, to prevent compilation error on JDK 6 | ||
public void setRemoveOnCancelPolicy(boolean value) { | ||
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace(); | ||
|
||
// Check to ensure that this method was called from NewThreadWorker, | ||
// on some versions of JDK ScheduledThreadPoolExecutor may call this method itself and break the test. | ||
for (StackTraceElement stackTraceElement : stackTraceElements) { | ||
if (stackTraceElement.getClassName().equals(NewThreadWorker.class.getCanonicalName())) { | ||
setRemoveOnCancelPolicyWasInvoked.set(true); | ||
break; | ||
} | ||
} | ||
} | ||
}; | ||
|
||
boolean result = NewThreadWorker.tryEnableCancelPolicy(executor); | ||
|
||
assertTrue(result); | ||
assertTrue(setRemoveOnCancelPolicyWasInvoked.get()); | ||
} | ||
|
||
@Test | ||
public void tryEnableCancelPolicyShouldNotInvokeMethodOnExecutor() { | ||
ScheduledExecutorService executor = mock(ScheduledExecutorService.class); | ||
|
||
boolean result = NewThreadWorker.tryEnableCancelPolicy(executor); | ||
|
||
assertFalse(result); | ||
verifyZeroInteractions(executor); | ||
} | ||
|
||
@Test | ||
public void tryEnableCancelPolicyShouldBeSkipped() throws NoSuchFieldException, IllegalAccessException { | ||
Field shouldTryEnableCancelPolicyField = NewThreadWorker | ||
.class | ||
.getDeclaredField("SHOULD_TRY_ENABLE_CANCEL_POLICY"); | ||
|
||
shouldTryEnableCancelPolicyField.setAccessible(true); | ||
|
||
Field modifiersFieldOfField = Field | ||
.class | ||
.getDeclaredField("modifiers"); | ||
|
||
modifiersFieldOfField.setAccessible(true); | ||
|
||
// Removing final flag from the field | ||
modifiersFieldOfField.set( | ||
shouldTryEnableCancelPolicyField, | ||
shouldTryEnableCancelPolicyField.getModifiers() & ~FINAL | ||
); | ||
|
||
final boolean initialValue = shouldTryEnableCancelPolicyField.getBoolean(null); | ||
|
||
try { | ||
// Setting FALSE to the SHOULD_TRY_ENABLE_CANCEL_POLICY | ||
shouldTryEnableCancelPolicyField.setBoolean(null, false); | ||
|
||
// Notice, that this executor has "setRemoveOnCancelPolicy" method | ||
ScheduledThreadPoolExecutor executor = spy(new ScheduledThreadPoolExecutor(1)); | ||
|
||
boolean result = NewThreadWorker.tryEnableCancelPolicy(executor); | ||
assertFalse(result); | ||
|
||
verifyZeroInteractions(executor); | ||
} finally { | ||
// Reverting value back for other tests | ||
shouldTryEnableCancelPolicyField.setBoolean(null, initialValue); | ||
|
||
// Restoring "final" modifier, probably it'll make JIT on VM that runs Tests happier | ||
modifiersFieldOfField.set( | ||
shouldTryEnableCancelPolicyField, | ||
shouldTryEnableCancelPolicyField.getModifiers() & FINAL | ||
); | ||
} | ||
} | ||
} |