@Override public void accept(byte[] v) throws Exception { System.out.println("Bounded Replay Leak check: Wait before GC 2"); Thread.sleep(1000); System.out.println("Bounded Replay Leak check: GC 2"); System.gc(); Thread.sleep(500); after.set(memoryMXBean.getHeapMemoryUsage().getUsed()); } });
@Override public void accept(byte[] v) throws Exception { System.out.println("Bounded Replay Leak check: Wait before GC 2"); Thread.sleep(1000); System.out.println("Bounded Replay Leak check: GC 2"); System.gc(); Thread.sleep(500); after.set(memoryMXBean.getHeapMemoryUsage().getUsed()); } });
@Override public void accept(byte[] v) throws Exception { System.out.println("Bounded Replay Leak check: Wait before GC 2"); Thread.sleep(1000); System.out.println("Bounded Replay Leak check: GC 2"); System.gc(); Thread.sleep(500); after.set(memoryMXBean.getHeapMemoryUsage().getUsed()); } });
@Override public void accept(byte[] v) throws Exception { System.out.println("Bounded Replay Leak check: Wait before GC 2"); Thread.sleep(1000); System.out.println("Bounded Replay Leak check: GC 2"); System.gc(); Thread.sleep(500); after.set(memoryMXBean.getHeapMemoryUsage().getUsed()); } });
void tearDown() { // GC before delete() to release files on Windows (https://stackoverflow.com/a/4213208/253468) System.gc(); if (file.exists() && !file.delete()) { throw new IllegalStateException("Failed to delete: " + file); } } }
@After public void tearDown() { // GC before delete() to release files on Windows (https://stackoverflow.com/a/4213208/253468) System.gc(); if (!file.delete()) { throw new IllegalStateException("Failed to delete: " + file); } }
@After public void tearDown() { // GC before delete() to release files on Windows (https://stackoverflow.com/a/4213208/253468) System.gc(); if (file.exists() && !file.delete()) { throw new RuntimeException("Failed to delete file"); } }
@Test public void replayNoLeak() throws Exception { System.gc(); Thread.sleep(100); long start = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getUsed(); source = Observable.fromCallable(new Callable<Object>() { @Override public Object call() throws Exception { return new byte[100 * 1000 * 1000]; } }) .replay(1) .refCount(); source.subscribe(); System.gc(); Thread.sleep(100); long after = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getUsed(); source = null; assertTrue(String.format("%,3d -> %,3d%n", start, after), start + 20 * 1000 * 1000 > after); }
@Test public void replayNoLeak() throws Exception { System.gc(); Thread.sleep(100); long start = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getUsed(); source = Flowable.fromCallable(new Callable<Object>() { @Override public Object call() throws Exception { return new byte[100 * 1000 * 1000]; } }) .replay(1) .refCount(); source.subscribe(); System.gc(); Thread.sleep(100); long after = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getUsed(); source = null; assertTrue(String.format("%,3d -> %,3d%n", start, after), start + 20 * 1000 * 1000 > after); }
@Test public void publishNoLeak() throws Exception { System.gc(); Thread.sleep(100); long start = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getUsed(); source = Flowable.fromCallable(new Callable<Object>() { @Override public Object call() throws Exception { throw new ExceptionData(new byte[100 * 1000 * 1000]); } }) .publish() .refCount(); source.subscribe(Functions.emptyConsumer(), Functions.emptyConsumer()); System.gc(); Thread.sleep(100); long after = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getUsed(); source = null; assertTrue(String.format("%,3d -> %,3d%n", start, after), start + 20 * 1000 * 1000 > after); }
@Test public void justUnsubscribed() throws Exception { o = new Object(); WeakReference<Object> wr = new WeakReference<Object>(o); TestObserver<Long> to = Observable.just(o).count().toObservable().onTerminateDetach().test(); o = null; to.cancel(); System.gc(); Thread.sleep(200); Assert.assertNull("Object retained!", wr.get()); }
@Test public void just() throws Exception { o = new Object(); WeakReference<Object> wr = new WeakReference<Object>(o); TestObserver<Object> to = new TestObserver<Object>(); Observable.just(o).count().toObservable().onTerminateDetach().subscribe(to); to.assertValue(1L); to.assertComplete(); to.assertNoErrors(); o = null; System.gc(); Thread.sleep(200); Assert.assertNull("Object retained!", wr.get()); }
@Test public void justUnsubscribed() throws Exception { o = new Object(); WeakReference<Object> wr = new WeakReference<Object>(o); TestSubscriber<Object> ts = new TestSubscriber<Object>(0); Flowable.just(o).count().toFlowable().onTerminateDetach().subscribe(ts); ts.cancel(); o = null; System.gc(); Thread.sleep(200); Assert.assertNull("Object retained!", wr.get()); }
@Test public void completeDetaches() throws Exception { Disposable d = Disposables.empty(); final WeakReference<Disposable> wr = new WeakReference<Disposable>(d); TestObserver<Void> to = new Completable() { @Override protected void subscribeActual(CompletableObserver observer) { observer.onSubscribe(wr.get()); observer.onComplete(); observer.onComplete(); }; } .onTerminateDetach() .test(); d = null; System.gc(); Thread.sleep(200); to.assertResult(); assertNull(wr.get()); }
@Test public void cancelDetaches() throws Exception { Disposable d = Disposables.empty(); final WeakReference<Disposable> wr = new WeakReference<Disposable>(d); TestObserver<Object> to = new Maybe<Object>() { @Override protected void subscribeActual(MaybeObserver<? super Object> observer) { observer.onSubscribe(wr.get()); }; } .onTerminateDetach() .test(); d = null; to.cancel(); System.gc(); Thread.sleep(200); to.assertEmpty(); assertNull(wr.get()); }
@Test public void cancelDetaches() throws Exception { Disposable d = Disposables.empty(); final WeakReference<Disposable> wr = new WeakReference<Disposable>(d); TestObserver<Object> to = new Single<Object>() { @Override protected void subscribeActual(SingleObserver<? super Object> observer) { observer.onSubscribe(wr.get()); }; } .onTerminateDetach() .test(); d = null; to.cancel(); System.gc(); Thread.sleep(200); to.assertEmpty(); assertNull(wr.get()); }
@Test public void cancelDetaches() throws Exception { Disposable d = Disposables.empty(); final WeakReference<Disposable> wr = new WeakReference<Disposable>(d); TestObserver<Void> to = new Completable() { @Override protected void subscribeActual(CompletableObserver observer) { observer.onSubscribe(wr.get()); }; } .onTerminateDetach() .test(); d = null; to.cancel(); System.gc(); Thread.sleep(200); to.assertEmpty(); assertNull(wr.get()); }
@Test public void errorDetaches() throws Exception { Disposable d = Disposables.empty(); final WeakReference<Disposable> wr = new WeakReference<Disposable>(d); TestObserver<Integer> to = new Maybe<Integer>() { @Override protected void subscribeActual(MaybeObserver<? super Integer> observer) { observer.onSubscribe(wr.get()); observer.onError(new TestException()); observer.onError(new IOException()); }; } .onTerminateDetach() .test(); d = null; System.gc(); Thread.sleep(200); to.assertFailure(TestException.class); assertNull(wr.get()); }
@Test public void just() throws Exception { o = new Object(); WeakReference<Object> wr = new WeakReference<Object>(o); TestSubscriber<Object> ts = new TestSubscriber<Object>(); Flowable.just(o).count().toFlowable().onTerminateDetach().subscribe(ts); ts.assertValue(1L); ts.assertComplete(); ts.assertNoErrors(); o = null; System.gc(); Thread.sleep(200); Assert.assertNull("Object retained!", wr.get()); }
@Test public void backpressured() throws Exception { o = new Object(); WeakReference<Object> wr = new WeakReference<Object>(o); TestSubscriber<Object> ts = new TestSubscriber<Object>(0L); Flowable.just(o).count().toFlowable().onTerminateDetach().subscribe(ts); ts.assertNoValues(); ts.request(1); ts.assertValue(1L); ts.assertComplete(); ts.assertNoErrors(); o = null; System.gc(); Thread.sleep(200); Assert.assertNull("Object retained!", wr.get()); }