/** Handles size after put. */ private void onPut() { cnt.incrementAndGet(); int c; while ((c = cnt.get()) > max) { // Decrement count. if (cnt.compareAndSet(c, c - 1)) { try { K key = firstEntry().getKey(); V val; // Make sure that an element is removed. while ((val = super.remove(firstEntry().getKey())) == null) { // No-op. } assert val != null; GridInClosure2<K, V> lsnr = this.lsnr; // Listener notification. if (lsnr != null) lsnr.apply(key, val); } catch (NoSuchElementException e1) { e1.printStackTrace(); // Should never happen. assert false : "Internal error in grid bounded ordered set."; } } } }
@Test(timeout = 10000) public void testOnBackpressureDropSynchronous() { for (int i = 0; i < 100; i++) { int NUM = (int) (RxRingBuffer.SIZE * 1.1); // > 1 so that take doesn't prevent buffer overflow AtomicInteger c = new AtomicInteger(); TestSubscriber<Integer> ts = new TestSubscriber<Integer>(); firehose(c).onBackpressureDrop().map(SLOW_PASS_THRU).take(NUM).subscribe(ts); ts.awaitTerminalEvent(); ts.assertNoErrors(); List<Integer> onNextEvents = ts.getOnNextEvents(); assertEquals(NUM, onNextEvents.size()); Integer lastEvent = onNextEvents.get(NUM - 1); System.out.println( "testOnBackpressureDrop => Received: " + onNextEvents.size() + " Emitted: " + c.get() + " Last value: " + lastEvent); // it drop, so we should get some number far higher than what would have sequentially // incremented assertTrue(NUM - 1 <= lastEvent.intValue()); } }
@Test public void testMergeAsyncThenObserveOnLoop() { for (int i = 0; i < 500; i++) { if (i % 10 == 0) { System.out.println("testMergeAsyncThenObserveOnLoop >> " + i); } // Verify there is no MissingBackpressureException int NUM = (int) (RxRingBuffer.SIZE * 4.1); AtomicInteger c1 = new AtomicInteger(); AtomicInteger c2 = new AtomicInteger(); TestSubscriber<Integer> ts = new TestSubscriber<Integer>(); Observable<Integer> merged = Observable.merge( incrementingIntegers(c1).subscribeOn(Schedulers.computation()), incrementingIntegers(c2).subscribeOn(Schedulers.computation())); merged.observeOn(Schedulers.io()).take(NUM).subscribe(ts); ts.awaitTerminalEvent(); ts.assertNoErrors(); System.out.println( "testMergeAsyncThenObserveOn => Received: " + ts.getOnNextEvents().size() + " Emitted: " + c1.get() + " / " + c2.get()); assertEquals(NUM, ts.getOnNextEvents().size()); } }
@Test public void testTakeWithErrorInObserver() { final AtomicInteger count = new AtomicInteger(); final AtomicReference<Throwable> error = new AtomicReference<>(); Observable.just("1", "2", "three", "4") .take(3) .safeSubscribe( new Observer<String>() { @Override public void onComplete() { System.out.println("completed"); } @Override public void onError(Throwable e) { error.set(e); System.out.println("error"); e.printStackTrace(); } @Override public void onNext(String v) { int num = Integer.parseInt(v); System.out.println(num); // doSomething(num); count.incrementAndGet(); } }); assertEquals(2, count.get()); assertNotNull(error.get()); if (!(error.get() instanceof NumberFormatException)) { fail("It should be a NumberFormatException"); } }
@Test public void testPublishLast() throws InterruptedException { final AtomicInteger count = new AtomicInteger(); ConnectableObservable<String> connectable = Observable.<String>create( observer -> { observer.onSubscribe(EmptySubscription.INSTANCE); count.incrementAndGet(); new Thread( () -> { observer.onNext("first"); observer.onNext("last"); observer.onComplete(); }) .start(); }) .takeLast(1) .publish(); // subscribe once final CountDownLatch latch = new CountDownLatch(1); connectable.subscribe( value -> { assertEquals("last", value); latch.countDown(); }); // subscribe twice connectable.subscribe(); Disposable subscription = connectable.connect(); assertTrue(latch.await(1000, TimeUnit.MILLISECONDS)); assertEquals(1, count.get()); subscription.dispose(); }
@Test public void testOnStartCalledOnceViaUnsafeSubscribe() { final AtomicInteger c = new AtomicInteger(); Observable.just(1, 2, 3, 4) .take(2) .unsafeSubscribe( new Observer<Integer>() { @Override public void onStart() { c.incrementAndGet(); request(1); } @Override public void onComplete() {} @Override public void onError(Throwable e) {} @Override public void onNext(Integer t) { request(1); } }); assertEquals(1, c.get()); }
@Test public void testObserveOnWithSlowConsumer() { int NUM = (int) (RxRingBuffer.SIZE * 0.2); AtomicInteger c = new AtomicInteger(); TestSubscriber<Integer> ts = new TestSubscriber<Integer>(); incrementingIntegers(c) .observeOn(Schedulers.computation()) .map( new Func1<Integer, Integer>() { @Override public Integer call(Integer i) { try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } return i; } }) .take(NUM) .subscribe(ts); ts.awaitTerminalEvent(); ts.assertNoErrors(); System.out.println( "testObserveOnWithSlowConsumer => Received: " + ts.getOnNextEvents().size() + " Emitted: " + c.get()); assertEquals(NUM, ts.getOnNextEvents().size()); assertTrue(c.get() < RxRingBuffer.SIZE * 2); }
/** * The error from the user provided Observable is handled by the subscribe try/catch because this * is synchronous * * <p>Result: Passes */ @Test public void testCustomObservableWithErrorInObservableSynchronous() { final AtomicInteger count = new AtomicInteger(); final AtomicReference<Throwable> error = new AtomicReference<>(); // FIXME custom built??? Observable.just("1", "2") .concatWith(Observable.error(() -> new NumberFormatException())) .subscribe( new Observer<String>() { @Override public void onComplete() { System.out.println("completed"); } @Override public void onError(Throwable e) { error.set(e); System.out.println("error"); e.printStackTrace(); } @Override public void onNext(String v) { System.out.println(v); count.incrementAndGet(); } }); assertEquals(2, count.get()); assertNotNull(error.get()); if (!(error.get() instanceof NumberFormatException)) { fail("It should be a NumberFormatException"); } }
@Test(timeout = 2000) public void testOnBackpressureBuffer() { int NUM = (int) (RxRingBuffer.SIZE * 1.1); // > 1 so that take doesn't prevent buffer overflow AtomicInteger c = new AtomicInteger(); TestSubscriber<Integer> ts = new TestSubscriber<Integer>(); firehose(c) .takeWhile( new Func1<Integer, Boolean>() { @Override public Boolean call(Integer t1) { return t1 < 100000; } }) .onBackpressureBuffer() .observeOn(Schedulers.computation()) .map(SLOW_PASS_THRU) .take(NUM) .subscribe(ts); ts.awaitTerminalEvent(); ts.assertNoErrors(); System.out.println( "testOnBackpressureBuffer => Received: " + ts.getOnNextEvents().size() + " Emitted: " + c.get()); assertEquals(NUM, ts.getOnNextEvents().size()); // it buffers, so we should get the right value sequentially assertEquals(NUM - 1, ts.getOnNextEvents().get(NUM - 1).intValue()); }
@Test public void testObserveOnWithSlowConsumer() { int NUM = (int) (Observable.bufferSize() * 0.2); AtomicInteger c = new AtomicInteger(); TestSubscriber<Integer> ts = new TestSubscriber<>(); incrementingIntegers(c) .observeOn(Schedulers.computation()) .map( i -> { try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } return i; }) .take(NUM) .subscribe(ts); ts.awaitTerminalEvent(); ts.assertNoErrors(); System.out.println( "testObserveOnWithSlowConsumer => Received: " + ts.valueCount() + " Emitted: " + c.get()); assertEquals(NUM, ts.valueCount()); assertTrue(c.get() < Observable.bufferSize() * 2); }
@Test public void testFlatMapSync() { int NUM = (int) (RxRingBuffer.SIZE * 2.1); AtomicInteger c = new AtomicInteger(); TestSubscriber<Integer> ts = new TestSubscriber<Integer>(); incrementingIntegers(c) .flatMap( new Func1<Integer, Observable<Integer>>() { @Override public Observable<Integer> call(Integer i) { return incrementingIntegers(new AtomicInteger()).take(10); } }) .take(NUM) .subscribe(ts); ts.awaitTerminalEvent(); ts.assertNoErrors(); System.out.println( "testFlatMapSync => Received: " + ts.getOnNextEvents().size() + " Emitted: " + c.get()); assertEquals(NUM, ts.getOnNextEvents().size()); // expect less than 1 buffer since the flatMap is emitting 10 each time, so it is NUM/10 that // will be taken. assertTrue(c.get() < RxRingBuffer.SIZE); }
@Test public void testTakeFilterSkipChainAsync() { int NUM = (int) (Observable.bufferSize() * 2.1); AtomicInteger c = new AtomicInteger(); TestSubscriber<Integer> ts = new TestSubscriber<>(); incrementingIntegers(c) .observeOn(Schedulers.computation()) .skip(10000) .filter(i -> i > 11000) .take(NUM) .subscribe(ts); ts.awaitTerminalEvent(); ts.assertNoErrors(); // emit 10000 that are skipped // emit next 1000 that are filtered out // take NUM // so emitted is at least 10000+1000+NUM + extra for buffer size/threshold int expected = 10000 + 1000 + Observable.bufferSize() * 3 + Observable.bufferSize() / 2; System.out.println( "testTakeFilterSkipChain => Received: " + ts.valueCount() + " Emitted: " + c.get() + " Expected: " + expected); assertEquals(NUM, ts.valueCount()); assertTrue(c.get() < expected); }
@Test @Ignore // the test is non-deterministic and can't be made deterministic public void testFlatMapAsync() { int NUM = (int) (Observable.bufferSize() * 2.1); AtomicInteger c = new AtomicInteger(); TestSubscriber<Integer> ts = new TestSubscriber<>(); incrementingIntegers(c) .subscribeOn(Schedulers.computation()) .flatMap( i -> incrementingIntegers(new AtomicInteger()) .take(10) .subscribeOn(Schedulers.computation())) .take(NUM) .subscribe(ts); ts.awaitTerminalEvent(); ts.assertNoErrors(); System.out.println( "testFlatMapAsync => Received: " + ts.valueCount() + " Emitted: " + c.get() + " Size: " + Observable.bufferSize()); assertEquals(NUM, ts.valueCount()); // even though we only need 10, it will request at least Observable.bufferSize(), and then as it // drains keep requesting more // and then it will be non-deterministic when the take() causes the unsubscribe as it is // scheduled on 10 different schedulers (threads) // normally this number is ~250 but can get up to ~1200 when Observable.bufferSize() == 1024 assertTrue(c.get() <= Observable.bufferSize() * 2); }
public void resetScore() { /* * score.set 与char2type.set这两个方法,虽然没有以原子的方式执行完成,但是 却不影响整个类的安全性,因为这两个方法没有相互依赖,只需保证单个方法以原子的方式执行即可, 这个情况与 java并发编程中的因式分解那个例子不同, */ score.set(0); char2type.set(-1); setScore(); }
@Test public void testObserveOn() { int NUM = (int) (Observable.bufferSize() * 2.1); AtomicInteger c = new AtomicInteger(); TestSubscriber<Integer> ts = new TestSubscriber<>(); incrementingIntegers(c).observeOn(Schedulers.computation()).take(NUM).subscribe(ts); ts.awaitTerminalEvent(); ts.assertNoErrors(); System.out.println("testObserveOn => Received: " + ts.valueCount() + " Emitted: " + c.get()); assertEquals(NUM, ts.valueCount()); assertTrue(c.get() < Observable.bufferSize() * 4); }
@Test public void testTakeWhileToList() { final int expectedCount = 3; final AtomicInteger count = new AtomicInteger(); for (int i = 0; i < expectedCount; i++) { Observable.just(Boolean.TRUE, Boolean.FALSE) .takeWhile(v -> v) .toList() .doOnNext(booleans -> count.incrementAndGet()) .subscribe(); } assertEquals(expectedCount, count.get()); }
@Test public void testReplay() throws InterruptedException { final AtomicInteger counter = new AtomicInteger(); ConnectableObservable<String> o = Observable.<String>create( observer -> { observer.onSubscribe(EmptySubscription.INSTANCE); new Thread( new Runnable() { @Override public void run() { counter.incrementAndGet(); observer.onNext("one"); observer.onComplete(); } }) .start(); }) .replay(); // we connect immediately and it will emit the value Disposable s = o.connect(); try { // we then expect the following 2 subscriptions to get that same value final CountDownLatch latch = new CountDownLatch(2); // subscribe once o.subscribe( v -> { assertEquals("one", v); latch.countDown(); }); // subscribe again o.subscribe( v -> { assertEquals("one", v); latch.countDown(); }); if (!latch.await(1000, TimeUnit.MILLISECONDS)) { fail("subscriptions did not receive values"); } assertEquals(1, counter.get()); } finally { s.dispose(); } }
@Test public void testZipAsync() { int NUM = (int) (Observable.bufferSize() * 2.1); AtomicInteger c1 = new AtomicInteger(); AtomicInteger c2 = new AtomicInteger(); TestSubscriber<Integer> ts = new TestSubscriber<>(); Observable<Integer> zipped = Observable.zip( incrementingIntegers(c1).subscribeOn(Schedulers.computation()), incrementingIntegers(c2).subscribeOn(Schedulers.computation()), (t1, t2) -> t1 + t2); zipped.take(NUM).subscribe(ts); ts.awaitTerminalEvent(); ts.assertNoErrors(); System.out.println( "testZipAsync => Received: " + ts.valueCount() + " Emitted: " + c1.get() + " / " + c2.get()); assertEquals(NUM, ts.valueCount()); int max = Observable.bufferSize() * 5; assertTrue("" + c1.get() + " >= " + max, c1.get() < max); assertTrue("" + c2.get() + " >= " + max, c2.get() < max); }
@Test public void testMergeAsync() { int NUM = (int) (Observable.bufferSize() * 4.1); AtomicInteger c1 = new AtomicInteger(); AtomicInteger c2 = new AtomicInteger(); TestSubscriber<Integer> ts = new TestSubscriber<>(); Observable<Integer> merged = Observable.merge( incrementingIntegers(c1).subscribeOn(Schedulers.computation()), incrementingIntegers(c2).subscribeOn(Schedulers.computation())); merged.take(NUM).subscribe(ts); ts.awaitTerminalEvent(); ts.assertNoErrors(); System.out.println( "testMergeAsync => Received: " + ts.valueCount() + " Emitted: " + c1.get() + " / " + c2.get()); assertEquals(NUM, ts.valueCount()); // either one can starve the other, but neither should be capable of doing more than 5 batches // (taking 4.1) // TODO is it possible to make this deterministic rather than one possibly starving the other? // benjchristensen => In general I'd say it's not worth trying to make it so, as "fair" // algoritms generally take a performance hit int max = Observable.bufferSize() * 7; assertTrue("" + c1.get() + " >= " + max, c1.get() < max); assertTrue("" + c2.get() + " >= " + max, c2.get() < max); }
/* * Launches against the agent */ public void testSimpleLauncher() throws Exception { Project project = workspace.getProject("p1"); Run bndrun = new Run(workspace, project.getBase(), project.getFile("one.bndrun")); bndrun.setProperty("-runpath", "biz.aQute.remote.launcher"); bndrun.setProperty("-runbundles", "bsn-1,bsn-2"); bndrun.setProperty("-runremote", "test"); final RemoteProjectLauncherPlugin pl = (RemoteProjectLauncherPlugin) bndrun.getProjectLauncher(); pl.prepare(); final CountDownLatch latch = new CountDownLatch(1); final AtomicInteger exitCode = new AtomicInteger(-1); List<? extends RunSession> sessions = pl.getRunSessions(); assertEquals(1, sessions.size()); final RunSession session = sessions.get(0); Thread t = new Thread("test-launch") { public void run() { try { exitCode.set(session.launch()); } catch (Exception e) { e.printStackTrace(); } finally { latch.countDown(); } } }; t.start(); Thread.sleep(500); for (Bundle b : context.getBundles()) { System.out.println(b.getLocation()); } assertEquals(4, context.getBundles().length); String p1 = t1.getAbsolutePath(); System.out.println(p1); assertNotNull(context.getBundle(p1)); assertNotNull(context.getBundle(t2.getAbsolutePath())); pl.cancel(); latch.await(); assertEquals(-3, exitCode.get()); bndrun.close(); }
@Test(timeout = 2000) public void testFirehoseFailsAsExpected() { AtomicInteger c = new AtomicInteger(); TestSubscriber<Integer> ts = new TestSubscriber<Integer>(); firehose(c).observeOn(Schedulers.computation()).map(SLOW_PASS_THRU).subscribe(ts); ts.awaitTerminalEvent(); System.out.println( "testFirehoseFailsAsExpected => Received: " + ts.getOnNextEvents().size() + " Emitted: " + c.get()); assertEquals(1, ts.getOnErrorEvents().size()); assertTrue(ts.getOnErrorEvents().get(0) instanceof MissingBackpressureException); }
public void run() { done.countDown(); remaining.incrementAndGet(); int n; while (!Thread.interrupted() && (n = remaining.get()) > 0 && done.getCount() > 0) { if (remaining.compareAndSet(n, n - 1)) { try { pool.execute(this); } catch (RuntimeException ex) { System.out.print("*"); while (done.getCount() > 0) done.countDown(); return; } } } }
@Test(timeout = 2000) public void testFirehoseFailsAsExpected() { AtomicInteger c = new AtomicInteger(); TestSubscriber<Integer> ts = new TestSubscriber<>(); firehose(c) .observeOn(Schedulers.computation()) .map( v -> { try { Thread.sleep(10); } catch (Exception e) { e.printStackTrace(); } return v; }) .subscribe(ts); ts.awaitTerminalEvent(); System.out.println( "testFirehoseFailsAsExpected => Received: " + ts.valueCount() + " Emitted: " + c.get()); // FIXME it is possible slow is not slow enough or the main gets delayed and thus more than one // source value is emitted. int vc = ts.valueCount(); assertTrue("10 < " + vc, vc <= 10); ts.assertError(MissingBackpressureException.class); }
@Override public void request(long n) { if (SubscriptionHelper.validateRequest(n)) { return; } if (compareAndSet(false, true)) { int i = 0; final Subscriber<? super Integer> a = s; final AtomicInteger c = counter; while (!cancelled) { a.onNext(i++); c.incrementAndGet(); } System.out.println("unsubscribed after: " + i); } }
public void testAdd() throws Exception { getIdentitiesOfFiles(); fillFilesWithContent(); validateFilesContent(version.byteValue()); version.compareAndSet(1, 2); continuousWrite.compareAndSet(true, false); generateRemainingPagesQueueForAllFiles(); executeConcurrentRandomReadAndWriteOperations(); buffer.flushBuffer(); validateFilesContent(version.byteValue()); }
@Test public void testFlatMapSync() { int NUM = (int) (Observable.bufferSize() * 2.1); AtomicInteger c = new AtomicInteger(); TestSubscriber<Integer> ts = new TestSubscriber<>(); incrementingIntegers(c) .flatMap(i -> incrementingIntegers(new AtomicInteger()).take(10)) .take(NUM) .subscribe(ts); ts.awaitTerminalEvent(); ts.assertNoErrors(); System.out.println("testFlatMapSync => Received: " + ts.valueCount() + " Emitted: " + c.get()); assertEquals(NUM, ts.valueCount()); // expect less than 1 buffer since the flatMap is emitting 10 each time, so it is NUM/10 that // will be taken. assertTrue(c.get() < Observable.bufferSize()); }
/** * The error from the user provided Observer is not handled by the subscribe method try/catch. * * <p>It is handled by the AtomicObserver that wraps the provided Observer. * * <p>Result: Passes (if AtomicObserver functionality exists) */ @Test public void testCustomObservableWithErrorInObserverAsynchronous() throws InterruptedException { final CountDownLatch latch = new CountDownLatch(1); final AtomicInteger count = new AtomicInteger(); final AtomicReference<Throwable> error = new AtomicReference<>(); // FIXME custom built??? Observable.just("1", "2", "three", "4") .subscribeOn(Schedulers.newThread()) .safeSubscribe( new Observer<String>() { @Override public void onComplete() { System.out.println("completed"); latch.countDown(); } @Override public void onError(Throwable e) { error.set(e); System.out.println("error"); e.printStackTrace(); latch.countDown(); } @Override public void onNext(String v) { int num = Integer.parseInt(v); System.out.println(num); // doSomething(num); count.incrementAndGet(); } }); // wait for async sequence to complete latch.await(); assertEquals(2, count.get()); assertNotNull(error.get()); if (!(error.get() instanceof NumberFormatException)) { fail("It should be a NumberFormatException"); } }
@Test public void testUserSubscriberUsingRequestSync() { AtomicInteger c = new AtomicInteger(); final AtomicInteger totalReceived = new AtomicInteger(); final AtomicInteger batches = new AtomicInteger(); final AtomicInteger received = new AtomicInteger(); incrementingIntegers(c) .subscribe( new Subscriber<Integer>() { @Override public void onStart() { request(100); } @Override public void onCompleted() {} @Override public void onError(Throwable e) {} @Override public void onNext(Integer t) { int total = totalReceived.incrementAndGet(); received.incrementAndGet(); if (total >= 2000) { unsubscribe(); } if (received.get() == 100) { batches.incrementAndGet(); request(100); received.set(0); } } }); System.out.println( "testUserSubscriberUsingRequestSync => Received: " + totalReceived.get() + " Emitted: " + c.get() + " Request Batches: " + batches.get()); assertEquals(2000, c.get()); assertEquals(2000, totalReceived.get()); assertEquals(20, batches.get()); }
@Test public void testSubscribeOnScheduling() { // in a loop for repeating the concurrency in this to increase chance of failure for (int i = 0; i < 100; i++) { int NUM = (int) (RxRingBuffer.SIZE * 2.1); AtomicInteger c = new AtomicInteger(); ConcurrentLinkedQueue<Thread> threads = new ConcurrentLinkedQueue<Thread>(); TestSubscriber<Integer> ts = new TestSubscriber<Integer>(); // observeOn is there to make it async and need backpressure incrementingIntegers(c, threads) .subscribeOn(Schedulers.computation()) .observeOn(Schedulers.computation()) .take(NUM) .subscribe(ts); ts.awaitTerminalEvent(); ts.assertNoErrors(); System.out.println( "testSubscribeOnScheduling => Received: " + ts.getOnNextEvents().size() + " Emitted: " + c.get()); assertEquals(NUM, ts.getOnNextEvents().size()); assertTrue(c.get() < RxRingBuffer.SIZE * 4); Thread first = null; for (Thread t : threads) { System.out.println("testSubscribeOnScheduling => thread: " + t); if (first == null) { first = t; } else { if (!first.equals(t)) { fail("Expected to see the same thread"); } } } System.out.println( "testSubscribeOnScheduling => Number of batch requests seen: " + threads.size()); assertTrue(threads.size() > 1); System.out.println( "-------------------------------------------------------------------------------------------"); } }
public ContinuousChangesFeed(String dbName, HttpResponse httpResponse) { this.httpResponse = httpResponse; try { reader = new BufferedReader(new InputStreamReader(httpResponse.getContent(), "UTF-8")); thread.setName( String.format( "ektorp-%s-changes-listening-thread-%s", dbName, THREAD_COUNT.getAndIncrement())); thread.start(); } catch (UnsupportedEncodingException e) { throw Exceptions.propagate(e); } }