/* * Copyright (c) 2011-2017 Pivotal Software Inc, All Rights Reserved. * * Licensed 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 reactor.core; import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; import org.junit.Test; import reactor.core.Disposable; import reactor.core.Disposables; import reactor.core.publisher.Hooks; import reactor.core.scheduler.Schedulers; import reactor.test.RaceTestUtils; import static org.assertj.core.api.Assertions.assertThat; public class DisposablesTest { static final AtomicReferenceFieldUpdater<TestDisposable, Disposable> DISPOSABLE_UPDATER = AtomicReferenceFieldUpdater.newUpdater(TestDisposable.class, Disposable.class, "disp"); private static Disposable empty() { return new Disposable() { volatile boolean disposed = false; @Override public void dispose() { this.disposed = true; } @Override public boolean isDisposed() { return disposed; } }; } private static class TestDisposable implements Runnable { volatile Disposable disp; public TestDisposable() { } public TestDisposable(Disposable disp) { this.disp = disp; } @Override public void run() { //NO-OP by default } } @Test public void singletonIsDisposed() { assertThat(Disposables.DISPOSED.isDisposed()).isTrue(); Disposables.DISPOSED.dispose(); assertThat(Disposables.DISPOSED.isDisposed()).isTrue(); } @Test public void validationNull() { Hooks.onErrorDropped(e -> assertThat(e).isInstanceOf(NullPointerException.class) .hasMessage("next is null")); try { assertThat(Disposables.validate(null, null)); } finally { Hooks.resetOnErrorDropped(); } } @Test public void disposeRace() { for (int i = 0; i < 500; i++) { TestDisposable r = new TestDisposable() { @Override public void run() { Disposables.dispose(DISPOSABLE_UPDATER, this); } }; RaceTestUtils.race(r, r, Schedulers.elastic()); } } @Test public void setReplace() { for (int i = 0; i < 500; i++) { TestDisposable r = new TestDisposable() { @Override public void run() { Disposables.replace(DISPOSABLE_UPDATER, this, empty()); } }; RaceTestUtils.race(r, r, Schedulers.elastic()); } } @Test public void setRace() { for (int i = 0; i < 500; i++) { TestDisposable r = new TestDisposable() { @Override public void run() { Disposables.set(DISPOSABLE_UPDATER, this, empty()); } }; RaceTestUtils.race(r, r, Schedulers.elastic()); } } @Test public void setReplaceNull() { TestDisposable r = new TestDisposable(); Disposables.dispose(DISPOSABLE_UPDATER, r); assertThat(Disposables.set(DISPOSABLE_UPDATER, r, null)).isFalse(); assertThat(Disposables.replace(DISPOSABLE_UPDATER, r, null)).isFalse(); } @Test public void dispose() { Disposable u = empty(); TestDisposable r = new TestDisposable(u); Disposables.dispose(DISPOSABLE_UPDATER, r); assertThat(u.isDisposed()).isTrue(); } @Test public void trySet() { TestDisposable r = new TestDisposable(); Disposable d1 = empty(); assertThat(Disposables.trySet(DISPOSABLE_UPDATER, r, d1)).isTrue(); Disposable d2 = empty(); assertThat(Disposables.trySet(DISPOSABLE_UPDATER, r, d2)).isFalse(); assertThat(d1.isDisposed()).isFalse(); assertThat(d2.isDisposed()).isFalse(); Disposables.dispose(DISPOSABLE_UPDATER, r); Disposable d3 = empty(); assertThat(Disposables.trySet(DISPOSABLE_UPDATER, r, d3)).isFalse(); assertThat(d3.isDisposed()).isTrue(); } }