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

Native smoke test for webclient #2112

Merged
merged 3 commits into from
Aug 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions tests/integration/native-image/se-1/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,7 @@ curl -i http://localhost:7076/health

# Should return 200 code and JSON response with metrics
curl -i -H "Accept: application/json" http://localhost:7076/metrics

# Should return ALL TESTS PASSED! after passing all webclient tests
curl -i http://localhost:7076/wc/test
```
16 changes: 16 additions & 0 deletions tests/integration/native-image/se-1/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@
<groupId>io.helidon.media</groupId>
<artifactId>helidon-media-jsonp</artifactId>
</dependency>
<dependency>
<groupId>io.helidon.media</groupId>
<artifactId>helidon-media-jsonb</artifactId>
</dependency>
<dependency>
<groupId>io.helidon.config</groupId>
<artifactId>helidon-config-yaml</artifactId>
Expand All @@ -92,6 +96,18 @@
<groupId>io.helidon.metrics</groupId>
<artifactId>helidon-metrics</artifactId>
</dependency>
<dependency>
<groupId>io.helidon.webclient</groupId>
<artifactId>helidon-webclient</artifactId>
</dependency>
<dependency>
<groupId>io.helidon.webclient</groupId>
<artifactId>helidon-webclient-metrics</artifactId>
</dependency>
<dependency>
<groupId>io.helidon.webclient</groupId>
<artifactId>helidon-webclient-tracing</artifactId>
</dependency>
<dependency>
<groupId>io.helidon.security.integration</groupId>
<artifactId>helidon-security-integration-webserver</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Copyright (c) 2020 Oracle and/or its affiliates.
*
* 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 io.helidon.tests.integration.nativeimage.se1;

import io.helidon.common.Reflected;

@Reflected
public class Animal {
private TYPE type;
private String name;

public Animal() {
}

public Animal(final TYPE type, final String name) {
this.type = type;
this.name = name;
}

public TYPE getType() {
return type;
}

public void setType(final TYPE type) {
this.type = type;
}

public String getName() {
return name;
}

public void setName(final String name) {
this.name = name;
}

public enum TYPE {
BIRD, DOG, CAT
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
/*
* Copyright (c) 2020 Oracle and/or its affiliates.
*
* 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 io.helidon.tests.integration.nativeimage.se1;

import java.io.ByteArrayInputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.StringReader;
import java.nio.ByteBuffer;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.Flow;
import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Logger;
import java.util.zip.GZIPInputStream;

import javax.json.Json;
import javax.json.JsonPointer;
import javax.json.JsonString;
import javax.json.JsonValue;

import io.helidon.common.GenericType;
import io.helidon.common.http.DataChunk;
import io.helidon.common.reactive.Multi;
import io.helidon.common.reactive.Single;
import io.helidon.media.common.MessageBodyReaderContext;
import io.helidon.media.common.MessageBodyStreamReader;
import io.helidon.webserver.Routing;
import io.helidon.webserver.ServerRequest;
import io.helidon.webserver.ServerResponse;
import io.helidon.webserver.Service;

public class MockZipkinService implements Service {

private static final Logger LOGGER = Logger.getLogger(MockZipkinService.class.getName());

final static JsonPointer TAGS_POINTER = Json.createPointer("/tags");
final static JsonPointer COMPONENT_POINTER = Json.createPointer("/tags/component");

private final Set<String> filteredComponents;
private final AtomicReference<CompletableFuture<JsonValue>> next = new AtomicReference<>(new CompletableFuture<>());

/**
* Create mock of the Zipkin listening on /api/v2/spans.
*
* @param filteredComponents listen only for traces with component tag having one of specified values
*/
MockZipkinService(Set<String> filteredComponents) {
this.filteredComponents = filteredComponents;
}

@Override
public void update(final Routing.Rules rules) {
rules.post("/api/v2/spans", this::mockZipkin);
}

/**
* Return completion being completed when next trace call arrives.
*
* @return completion being completed when next trace call arrives
*/
CompletionStage<JsonValue> next() {
return next.get();
}

private void mockZipkin(final ServerRequest request, final ServerResponse response) {
request.queryParams().all("serviceName").forEach(s -> System.out.println(">>>" + s));
request.content()
.registerReader(new MessageBodyStreamReader<JsonValue>() {
@Override
public PredicateResult accept(final GenericType<?> type, final MessageBodyReaderContext context) {
return PredicateResult.COMPATIBLE;
}

@Override
@SuppressWarnings("unchecked")
public <U extends JsonValue> Flow.Publisher<U> read(final Flow.Publisher<DataChunk> publisher, final GenericType<U> type, final MessageBodyReaderContext context) {
return (Flow.Publisher<U>) Multi.create(publisher)
.map(d -> ByteBuffer.wrap(d.bytes()))
.reduce((buf, buf2) ->
ByteBuffer.allocate(buf.capacity() + buf2.capacity())
.put(buf.array())
.put(buf2.array()))
.flatMap(b -> {
try (ByteArrayInputStream bais = new ByteArrayInputStream(b.array());
GZIPInputStream gzipInputStream = new GZIPInputStream(bais)) {
return Single.just(Json.createReader(new StringReader(new String(gzipInputStream.readAllBytes())))
.readArray());
} catch (EOFException e) {
//ignore
return Multi.empty();
} catch (IOException e) {
throw new RuntimeException(e);
}
})
.flatMap(a -> Multi.create(a.stream()));
}
})
.asStream(JsonValue.class)
.map(JsonValue::asJsonObject)
.filter(json ->
TAGS_POINTER.containsValue(json)
&& COMPONENT_POINTER.containsValue(json)
&& filteredComponents.stream()
.anyMatch(s -> s.equals(((JsonString) COMPONENT_POINTER.getValue(json)).getString()))
)
.onError(Throwable::printStackTrace)
.onError(t -> response.status(500).send(t))
.onComplete(response::send)
.peek(json -> LOGGER.info(json.toString()))
.forEach(e -> next.getAndSet(new CompletableFuture<>()).complete(e));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@

import java.io.IOException;
import java.nio.file.Paths;
import java.util.Set;
import java.util.logging.LogManager;

import io.helidon.config.Config;
import io.helidon.config.FileSystemWatcher;
import io.helidon.health.HealthSupport;
import io.helidon.health.checks.HealthChecks;
import io.helidon.media.jsonb.JsonbSupport;
import io.helidon.media.jsonp.JsonpSupport;
import io.helidon.metrics.MetricsSupport;
import io.helidon.security.integration.webserver.WebSecurity;
Expand All @@ -40,6 +42,7 @@
* Main class of this integration test.
*/
public final class Se1Main {

/**
* Cannot be instantiated.
*/
Expand Down Expand Up @@ -75,6 +78,7 @@ static WebServer startServer() throws IOException {
.config(config.get("server"))
.tracer(TracerBuilder.create(config.get("tracing")).build())
.addMediaSupport(JsonpSupport.create())
.addMediaSupport(JsonbSupport.create())
.printFeatureDetails(true)
.build();

Expand Down Expand Up @@ -119,6 +123,8 @@ private static Routing createRouting(Config config) {

MetricsSupport metrics = MetricsSupport.create();
GreetService greetService = new GreetService(config);
MockZipkinService zipkinService = new MockZipkinService(Set.of("helidon-webclient"));
WebClientService webClientService = new WebClientService(config, zipkinService);
HealthSupport health = HealthSupport.builder()
.addLiveness(HealthChecks.healthChecks()) // Adds a convenient set of checks
.addLiveness(() -> HealthCheckResponse.named("custom") // a custom health check
Expand All @@ -135,6 +141,8 @@ private static Routing createRouting(Config config) {
.register(health) // Health at "/health"
.register(metrics) // Metrics at "/metrics"
.register("/greet", greetService)
.register("/wc", webClientService)
.register("/zipkin", zipkinService)
.build();
}

Expand Down
Loading