Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2.x: Improve coverage & related cleanup 03/05 #5891

Merged
merged 2 commits into from
Mar 5, 2018

Conversation

akarnokd
Copy link
Member

@akarnokd akarnokd commented Mar 5, 2018

Improve the coverage of various components, fix impossible paths and other fixes. See the comments attached to the code changes.

@akarnokd akarnokd added this to the 2.2 milestone Mar 5, 2018
if (SubscriptionHelper.setOnce(this, s)) {
s.request(batchSize);
}
SubscriptionHelper.setOnce(this, s, batchSize);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When the request call comes directly after setOnce, they can be combined into one and this resolves a lot of partial coverage cases.

}
// otherwise, someone else changed the state (perhaps a concurrent
// request or cancellation) so retry
// add to the current requested and cap it at MAX_VALUE
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was one of the earliest v2 operators where the infrastructure lacked the addCancel method, simplifying this method significantly.

boolean setOther(Subscription o) {
return SubscriptionHelper.setOnce(other, o);
void setOther(Subscription o) {
SubscriptionHelper.setOnce(other, o, Long.MAX_VALUE);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is always Long.MAX_VALUE and moved up from below.

} catch (ExecutionException ex) {
if (!d.isDisposed()) {
observer.onError(ex.getCause());
} catch (Throwable ex) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reduce the code duplication to one catch and extract the actual Throwable if ex was the ExecutionException.

@@ -54,7 +54,7 @@ protected void subscribeActual(SingleObserver<? super T> subscriber) {

@Override
public void onSubscribe(Disposable d) {
if (DisposableHelper.set(this, d)) {
if (DisposableHelper.setOnce(this, d)) {
Copy link
Member Author

@akarnokd akarnokd Mar 5, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should have been setOnce all along.

}
ScheduledExecutorService next = Executors.newScheduledThreadPool(1, new RxThreadFactory("RxSchedulerPurge"));
if (PURGE_THREAD.compareAndSet(curr, next)) {
tryStart(PURGE_ENABLED);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Factored out into a method which takes this parameter to be able to unit test the setup code. In normal code, this start call will usually happen once (class init).

@@ -81,61 +82,77 @@ public static void start() {
* Stops the purge thread.
*/
public static void shutdown() {
ScheduledExecutorService exec = PURGE_THREAD.get();
ScheduledExecutorService exec = PURGE_THREAD.getAndSet(null);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Setting the PURGE_THREAD to null simplifies the start check above.

if (properties.containsKey(PURGE_ENABLED_KEY)) {
purgeEnable = Boolean.getBoolean(PURGE_ENABLED_KEY);
}
PurgeProperties pp = new PurgeProperties();
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Factored out to be able to test parameter loading. This static code block executes once per class init.

/**
* Creates a ScheduledExecutorService with the given factory.
* @param factory the thread factory
* @return the ScheduledExecutorService
*/
public static ScheduledExecutorService create(ThreadFactory factory) {
final ScheduledExecutorService exec = Executors.newScheduledThreadPool(1, factory);
if (PURGE_ENABLED && exec instanceof ScheduledThreadPoolExecutor) {
tryPutIntoPool(PURGE_ENABLED, exec);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Factored out to be able to test with purge not enabled and a non- ScheduledThreadPoolExecutor instance in case Executors.new ScheduledThreadExecutor doesn't return such in some odd JVM.

} else {
e.purge();
}
for (ScheduledThreadPoolExecutor e : new ArrayList<ScheduledThreadPoolExecutor>(POOLS.keySet())) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed the surrounding try-catch as it is practically impossible this loop crashes.

RxJavaPlugins.onError(e);
return;
}
try {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The delay > 0 was always true because execTime > t thus execTime - t == delay is always > 0.

* RxJavaPlugins.
* @param transform the transform to drive an operator
*/
public static void checkDoubleOnSubscribeCompletableToFlowable(Function<Completable, ? extends Publisher<?>> transform) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additional double onSubscribe call checks with operators going from Completable to Flowable|Observable.

* @return true if the operation succeeded, false if the target field was not null.
* @since 2.1.11
*/
public static boolean setOnce(AtomicReference<Subscription> field, Subscription s, long request) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we get rid of the other method that we used before?

Copy link
Member Author

@akarnokd akarnokd Mar 5, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, there are many cases which require some other preparations before issuing the initial request.

this.d = s;
actual.onSubscribe(this);
public void onSubscribe(Disposable d) {
if (DisposableHelper.validate(this.d, d)) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Validation was missing.

@akarnokd
Copy link
Member Author

akarnokd commented Mar 5, 2018

Updated with some additional cleanup and fix to ObservableSkip lacking a validation.

@codecov
Copy link

codecov bot commented Mar 5, 2018

Codecov Report

Merging #5891 into 2.x will increase coverage by 0.33%.
The diff coverage is 98.75%.

Impacted file tree graph

@@             Coverage Diff              @@
##                2.x    #5891      +/-   ##
============================================
+ Coverage     97.61%   97.94%   +0.33%     
- Complexity     5945     5985      +40     
============================================
  Files           655      655              
  Lines         43860    43836      -24     
  Branches       6098     6072      -26     
============================================
+ Hits          42812    42935     +123     
+ Misses          327      277      -50     
+ Partials        721      624      -97
Impacted Files Coverage Δ Complexity Δ
...activex/internal/subscribers/FutureSubscriber.java 100% <100%> (ø) 32 <1> (-1) ⬇️
...ivex/internal/schedulers/SchedulerPoolFactory.java 100% <100%> (+28.26%) 13 <10> (+6) ⬆️
...ternal/operators/single/SingleDelayWithSingle.java 100% <100%> (+5%) 2 <0> (ø) ⬇️
...nternal/operators/parallel/ParallelReduceFull.java 91.08% <100%> (-0.09%) 2 <0> (ø)
...internal/operators/flowable/FlowableTakeUntil.java 100% <100%> (ø) 2 <0> (ø) ⬇️
...rnal/operators/flowable/FlowableCombineLatest.java 92.82% <100%> (+0.36%) 8 <0> (ø) ⬇️
...ivex/internal/operators/maybe/MaybeFromFuture.java 100% <100%> (+13.79%) 8 <0> (+3) ⬆️
.../internal/operators/observable/ObservableSkip.java 100% <100%> (ø) 2 <0> (ø) ⬇️
...l/operators/flowable/BlockingFlowableIterable.java 100% <100%> (+1.47%) 2 <0> (ø) ⬇️
...internal/operators/flowable/FlowableSkipUntil.java 100% <100%> (ø) 2 <0> (ø) ⬇️
... and 91 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 51dd03b...221a01d. Read the comment docs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants