Search in sources :

Example 1 with Subscriber

use of java.util.concurrent.Flow.Subscriber in project helidon by oracle.

the class MultiPartDecoderTest method testPartContentSubscriberThrottling.

@Test
public void testPartContentSubscriberThrottling() {
    String boundary = "boundary";
    final byte[] chunk1 = ("--" + boundary + "\n" + "Content-Id: part1\n" + "\n" + "body 1.aaaa\n").getBytes();
    final byte[] chunk2 = "body 1.bbbb\n".getBytes();
    final byte[] chunk3 = ("body 1.cccc\n" + "--" + boundary + "\n" + "Content-Id: part2\n" + "\n" + "This is the 2nd").getBytes();
    final byte[] chunk4 = ("body.\n" + "--" + boundary + "--").getBytes();
    final CountDownLatch latch = new CountDownLatch(3);
    Consumer<BodyPart> consumer = (part) -> {
        latch.countDown();
        if (latch.getCount() == 2) {
            assertThat(part.headers().values("Content-Id"), hasItems("part1"));
        }
        part.content().subscribe(new Subscriber<DataChunk>() {

            @Override
            public void onSubscribe(Subscription subscription) {
                subscription.request(1);
            }

            @Override
            public void onNext(DataChunk item) {
                latch.countDown();
            }

            @Override
            public void onError(Throwable throwable) {
            }

            @Override
            public void onComplete() {
            }
        });
    };
    BodyPartSubscriber testSubscriber = new BodyPartSubscriber(SUBSCRIBER_TYPE.ONE_BY_ONE, consumer);
    partsPublisher(boundary, List.of(chunk1, chunk2, chunk3, chunk4)).subscribe(testSubscriber);
    waitOnLatchNegative(latch, "the 2nd part should not be processed");
    assertThat(latch.getCount(), is(equalTo(1L)));
    try {
        testSubscriber.complete.orTimeout(200, TimeUnit.MILLISECONDS).join();
        throw new IllegalStateException("Not expecting to make progress, unless the part is consumed");
    } catch (CompletionException e) {
        Throwable error = e.getCause();
        // This is the expected outcome - the testSubcriber is not making progress
        assertThat(error.getClass(), is(equalTo(TimeoutException.class)));
    }
}
Also used : CoreMatchers.is(org.hamcrest.CoreMatchers.is) Assertions.fail(org.junit.jupiter.api.Assertions.fail) CoreMatchers.hasItems(org.hamcrest.CoreMatchers.hasItems) Subscription(java.util.concurrent.Flow.Subscription) DataChunk(io.helidon.common.http.DataChunk) TimeoutException(java.util.concurrent.TimeoutException) CompletableFuture(java.util.concurrent.CompletableFuture) CompletionException(java.util.concurrent.CompletionException) CoreMatchers.notNullValue(org.hamcrest.CoreMatchers.notNullValue) TimeUnit(java.util.concurrent.TimeUnit) Consumer(java.util.function.Consumer) Test(org.junit.jupiter.api.Test) CountDownLatch(java.util.concurrent.CountDownLatch) List(java.util.List) CompletionStage(java.util.concurrent.CompletionStage) Publisher(java.util.concurrent.Flow.Publisher) Subscriber(java.util.concurrent.Flow.Subscriber) Matchers.equalTo(org.hamcrest.Matchers.equalTo) MatcherAssert.assertThat(org.hamcrest.MatcherAssert.assertThat) Multi(io.helidon.common.reactive.Multi) CoreMatchers.nullValue(org.hamcrest.CoreMatchers.nullValue) CountDownLatch(java.util.concurrent.CountDownLatch) Subscriber(java.util.concurrent.Flow.Subscriber) CompletionException(java.util.concurrent.CompletionException) DataChunk(io.helidon.common.http.DataChunk) Subscription(java.util.concurrent.Flow.Subscription) TimeoutException(java.util.concurrent.TimeoutException) Test(org.junit.jupiter.api.Test)

Example 2 with Subscriber

use of java.util.concurrent.Flow.Subscriber in project helidon by oracle.

the class MultiPartDecoderTest method testContentAcrossChunksAsyncRequest.

@Test
public void testContentAcrossChunksAsyncRequest() {
    String boundary = "boundary";
    final byte[] chunk1 = ("--" + boundary + "\n" + "Content-Id: part1\n" + "\n" + "thi").getBytes();
    final byte[] chunk11 = ("s-is-the-1st-slice-of-the-body\n").getBytes();
    final byte[] chunk12 = ("t").getBytes();
    final byte[] chunk2 = ("his-is-the-2nd-slice-of-the-body\n" + "--" + boundary + "--").getBytes();
    final CountDownLatch latch = new CountDownLatch(2);
    Consumer<BodyPart> consumer = (part) -> {
        latch.countDown();
        assertThat(part.headers().values("Content-Id"), hasItems("part1"));
        DataChunkSubscriber subscriber = new DataChunkSubscriber();
        part.content().subscribe(subscriber);
        subscriber.content().thenAccept(body -> {
            assertThat(body, is(equalTo("this-is-the-1st-slice-of-the-body\n" + "this-is-the-2nd-slice-of-the-body")));
        }).exceptionally((ex) -> {
            System.out.println("UH-OH... " + ex);
            return null;
        }).thenAccept((_i) -> {
            latch.countDown();
        });
    };
    BodyPartSubscriber testSubscriber = new BodyPartSubscriber(SUBSCRIBER_TYPE.ONE_BY_ONE, consumer);
    partsPublisher(boundary, List.of(chunk1, chunk11, chunk12, chunk2)).subscribe(testSubscriber);
    try {
        boolean b = testSubscriber.complete.orTimeout(200, TimeUnit.MILLISECONDS).join();
        assertThat(b, is(equalTo(true)));
    } catch (CompletionException error) {
        assertThat(error, is(nullValue()));
    }
    waitOnLatch(latch);
}
Also used : CoreMatchers.is(org.hamcrest.CoreMatchers.is) Assertions.fail(org.junit.jupiter.api.Assertions.fail) CoreMatchers.hasItems(org.hamcrest.CoreMatchers.hasItems) Subscription(java.util.concurrent.Flow.Subscription) DataChunk(io.helidon.common.http.DataChunk) TimeoutException(java.util.concurrent.TimeoutException) CompletableFuture(java.util.concurrent.CompletableFuture) CompletionException(java.util.concurrent.CompletionException) CoreMatchers.notNullValue(org.hamcrest.CoreMatchers.notNullValue) TimeUnit(java.util.concurrent.TimeUnit) Consumer(java.util.function.Consumer) Test(org.junit.jupiter.api.Test) CountDownLatch(java.util.concurrent.CountDownLatch) List(java.util.List) CompletionStage(java.util.concurrent.CompletionStage) Publisher(java.util.concurrent.Flow.Publisher) Subscriber(java.util.concurrent.Flow.Subscriber) Matchers.equalTo(org.hamcrest.Matchers.equalTo) MatcherAssert.assertThat(org.hamcrest.MatcherAssert.assertThat) Multi(io.helidon.common.reactive.Multi) CoreMatchers.nullValue(org.hamcrest.CoreMatchers.nullValue) CompletionException(java.util.concurrent.CompletionException) CountDownLatch(java.util.concurrent.CountDownLatch) Test(org.junit.jupiter.api.Test)

Example 3 with Subscriber

use of java.util.concurrent.Flow.Subscriber in project helidon by oracle.

the class MultiPartDecoderTest method testMultipleChunksBeforeContent.

@Test
public void testMultipleChunksBeforeContent() {
    String boundary = "boundary";
    final byte[] chunk1 = ("--" + boundary + "\n" + "Content-Id: part1\n").getBytes();
    final byte[] chunk2 = "Content-Type: text/plain\n".getBytes();
    final byte[] chunk3 = "Set-Cookie: bob=alice\n".getBytes();
    final byte[] chunk4 = "Set-Cookie: foo=bar\n".getBytes();
    final byte[] chunk5 = ("\n" + "body 1\n" + "--" + boundary + "--").getBytes();
    final CountDownLatch latch = new CountDownLatch(2);
    Consumer<BodyPart> consumer = (part) -> {
        latch.countDown();
        assertThat(part.headers().values("Content-Id"), hasItems("part1"));
        assertThat(part.headers().values("Content-Type"), hasItems("text/plain"));
        assertThat(part.headers().values("Set-Cookie"), hasItems("bob=alice", "foo=bar"));
        DataChunkSubscriber subscriber = new DataChunkSubscriber();
        part.content().subscribe(subscriber);
        subscriber.content().thenAccept(body -> {
            latch.countDown();
            assertThat(body, is(equalTo("body 1")));
        });
    };
    BodyPartSubscriber testSubscriber = new BodyPartSubscriber(SUBSCRIBER_TYPE.INFINITE, consumer);
    partsPublisher(boundary, List.of(chunk1, chunk2, chunk3, chunk4, chunk5)).subscribe(testSubscriber);
    try {
        boolean b = testSubscriber.complete.orTimeout(200, TimeUnit.MILLISECONDS).join();
        assertThat(b, is(equalTo(true)));
    } catch (CompletionException error) {
        assertThat(error, is(nullValue()));
    }
    waitOnLatch(latch);
}
Also used : CoreMatchers.is(org.hamcrest.CoreMatchers.is) Assertions.fail(org.junit.jupiter.api.Assertions.fail) CoreMatchers.hasItems(org.hamcrest.CoreMatchers.hasItems) Subscription(java.util.concurrent.Flow.Subscription) DataChunk(io.helidon.common.http.DataChunk) TimeoutException(java.util.concurrent.TimeoutException) CompletableFuture(java.util.concurrent.CompletableFuture) CompletionException(java.util.concurrent.CompletionException) CoreMatchers.notNullValue(org.hamcrest.CoreMatchers.notNullValue) TimeUnit(java.util.concurrent.TimeUnit) Consumer(java.util.function.Consumer) Test(org.junit.jupiter.api.Test) CountDownLatch(java.util.concurrent.CountDownLatch) List(java.util.List) CompletionStage(java.util.concurrent.CompletionStage) Publisher(java.util.concurrent.Flow.Publisher) Subscriber(java.util.concurrent.Flow.Subscriber) Matchers.equalTo(org.hamcrest.Matchers.equalTo) MatcherAssert.assertThat(org.hamcrest.MatcherAssert.assertThat) Multi(io.helidon.common.reactive.Multi) CoreMatchers.nullValue(org.hamcrest.CoreMatchers.nullValue) CompletionException(java.util.concurrent.CompletionException) CountDownLatch(java.util.concurrent.CountDownLatch) Test(org.junit.jupiter.api.Test)

Example 4 with Subscriber

use of java.util.concurrent.Flow.Subscriber in project helidon by oracle.

the class ContextLifeCycleTest method testContextReactive.

@Test
void testContextReactive() {
    Handler handler = (req, res) -> {
        String cid = req.context().id();
        req.content().subscribe(new Subscriber<>() {

            @Override
            public void onSubscribe(Subscription subscription) {
                subscription.request(Long.MAX_VALUE);
            }

            @Override
            public void onNext(DataChunk item) {
                item.release();
                if (!cid.equals(contextId())) {
                    throw new IllegalStateException("Context invalid");
                }
            }

            @Override
            public void onError(Throwable throwable) {
                res.send(throwable);
            }

            @Override
            public void onComplete() {
                if (!cid.equals(contextId())) {
                    res.send(new IllegalStateException("Context invalid"));
                } else {
                    res.send();
                }
            }
        });
    };
    WebServer webServer = WebServer.builder(Routing.builder().post(handler)).build().start().await(10, TimeUnit.SECONDS);
    ResponseStatus responseStatus = WebClient.builder().baseUri("http://localhost:" + webServer.port()).build().post().submit("some-payload").map(WebClientResponse::status).onTerminate(webServer::shutdown).await(10, TimeUnit.SECONDS);
    assertThat(responseStatus.code(), is(200));
}
Also used : CoreMatchers.is(org.hamcrest.CoreMatchers.is) WebClient(io.helidon.webclient.WebClient) WebClientResponse(io.helidon.webclient.WebClientResponse) Subscription(java.util.concurrent.Flow.Subscription) DataChunk(io.helidon.common.http.DataChunk) Context(io.helidon.common.context.Context) TimeoutException(java.util.concurrent.TimeoutException) CompletableFuture(java.util.concurrent.CompletableFuture) Contexts(io.helidon.common.context.Contexts) ExecutionException(java.util.concurrent.ExecutionException) TimeUnit(java.util.concurrent.TimeUnit) Test(org.junit.jupiter.api.Test) Subscriber(java.util.concurrent.Flow.Subscriber) ResponseStatus(io.helidon.common.http.Http.ResponseStatus) MatcherAssert.assertThat(org.hamcrest.MatcherAssert.assertThat) WebClientResponse(io.helidon.webclient.WebClientResponse) Subscriber(java.util.concurrent.Flow.Subscriber) ResponseStatus(io.helidon.common.http.Http.ResponseStatus) DataChunk(io.helidon.common.http.DataChunk) Subscription(java.util.concurrent.Flow.Subscription) Test(org.junit.jupiter.api.Test)

Example 5 with Subscriber

use of java.util.concurrent.Flow.Subscriber in project helidon by oracle.

the class RequestContentTest method multiThreadingFilterAndReaderTest.

@SuppressWarnings("unchecked")
@Test
public void multiThreadingFilterAndReaderTest() throws Exception {
    CountDownLatch subscribedLatch = new CountDownLatch(1);
    SubmissionPublisher<DataChunk> publisher = new SubmissionPublisher<>(Runnable::run, 10);
    ForkJoinPool.commonPool().submit(() -> {
        try {
            if (!subscribedLatch.await(10, TimeUnit.SECONDS)) {
                fail("Subscriber didn't subscribe in timely manner!");
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new IllegalStateException("Interrupted!", e);
        }
        publisher.submit(DataChunk.create("first".getBytes()));
        publisher.submit(DataChunk.create("second".getBytes()));
        publisher.submit(DataChunk.create("third".getBytes()));
        publisher.close();
    });
    Request request = requestTestStub(Multi.create(publisher));
    request.content().registerFilter(originalPublisher -> subscriberDelegate -> originalPublisher.subscribe(new Subscriber<DataChunk>() {

        @Override
        public void onSubscribe(Subscription subscription) {
            subscriberDelegate.onSubscribe(subscription);
            subscribedLatch.countDown();
        }

        @Override
        public void onNext(DataChunk item) {
            // mapping the on next call only
            subscriberDelegate.onNext(DataChunk.create(requestChunkAsString(item).toUpperCase().getBytes()));
        }

        @Override
        public void onError(Throwable throwable) {
            subscriberDelegate.onError(throwable);
        }

        @Override
        public void onComplete() {
            subscriberDelegate.onComplete();
        }
    }));
    request.content().registerReader(Iterable.class, (publisher1, clazz) -> {
        fail("Iterable reader should have not been used!");
        throw new IllegalStateException("unreachable code");
    });
    request.content().registerReader(ArrayList.class, (publisher1, clazz) -> {
        fail("ArrayList reader should have not been used!");
        throw new IllegalStateException("unreachable code");
    });
    request.content().registerReader(List.class, (publisher1, clazz) -> {
        CompletableFuture<List> future = new CompletableFuture<>();
        List<String> list = new CopyOnWriteArrayList<>();
        publisher1.subscribe(new Subscriber<DataChunk>() {

            @Override
            public void onSubscribe(Subscription subscription) {
                subscription.request(Long.MAX_VALUE);
                subscribedLatch.countDown();
            }

            @Override
            public void onNext(DataChunk item) {
                list.add(TestUtils.requestChunkAsString(item));
            }

            @Override
            public void onError(Throwable throwable) {
                fail("Received an exception: " + throwable.getMessage());
            }

            @Override
            public void onComplete() {
                future.complete(list);
            }
        });
        return future;
    });
    List<String> result = (List<String>) request.content().as(List.class).toCompletableFuture().get(10, TimeUnit.SECONDS);
    assertThat(result, hasItems(is("FIRST"), is("SECOND"), is("THIRD")));
}
Also used : SubmissionPublisher(java.util.concurrent.SubmissionPublisher) TestUtils.requestChunkAsString(io.helidon.webserver.utils.TestUtils.requestChunkAsString) StringContains.containsString(org.hamcrest.core.StringContains.containsString) CountDownLatch(java.util.concurrent.CountDownLatch) CompletableFuture(java.util.concurrent.CompletableFuture) Subscriber(java.util.concurrent.Flow.Subscriber) DataChunk(io.helidon.common.http.DataChunk) ArrayList(java.util.ArrayList) List(java.util.List) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) Subscription(java.util.concurrent.Flow.Subscription) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) Test(org.junit.jupiter.api.Test)

Aggregations

Subscriber (java.util.concurrent.Flow.Subscriber)11 Test (org.junit.jupiter.api.Test)11 DataChunk (io.helidon.common.http.DataChunk)10 Subscription (java.util.concurrent.Flow.Subscription)10 CompletableFuture (java.util.concurrent.CompletableFuture)9 CountDownLatch (java.util.concurrent.CountDownLatch)9 List (java.util.List)8 TimeUnit (java.util.concurrent.TimeUnit)8 TimeoutException (java.util.concurrent.TimeoutException)8 CoreMatchers.is (org.hamcrest.CoreMatchers.is)8 MatcherAssert.assertThat (org.hamcrest.MatcherAssert.assertThat)8 Multi (io.helidon.common.reactive.Multi)7 CompletionException (java.util.concurrent.CompletionException)7 CompletionStage (java.util.concurrent.CompletionStage)7 Publisher (java.util.concurrent.Flow.Publisher)7 Consumer (java.util.function.Consumer)7 CoreMatchers.hasItems (org.hamcrest.CoreMatchers.hasItems)7 CoreMatchers.notNullValue (org.hamcrest.CoreMatchers.notNullValue)7 CoreMatchers.nullValue (org.hamcrest.CoreMatchers.nullValue)7 Matchers.equalTo (org.hamcrest.Matchers.equalTo)7