Skip to content

Commit

Permalink
dev mode, fixes #23
Browse files Browse the repository at this point in the history
  • Loading branch information
michalszynkiewicz committed May 4, 2020
1 parent e19c746 commit 03bc10f
Show file tree
Hide file tree
Showing 17 changed files with 608 additions and 27 deletions.
10 changes: 10 additions & 0 deletions deployment/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,16 @@
<artifactId>quarkus-smallrye-health</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
package io.quarkus.grpc.server.devmode;

import com.example.test.MutinyStreamsGrpc;
import com.example.test.StreamsGrpc;
import com.example.test.StreamsOuterClass;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import io.grpc.examples.helloworld.GreeterGrpc;
import io.grpc.examples.helloworld.HelloReply;
import io.grpc.examples.helloworld.HelloRequest;
import io.quarkus.test.QuarkusDevModeTest;
import io.smallrye.mutiny.Multi;
import io.smallrye.mutiny.subscription.Subscribers;
import org.awaitility.Awaitility;
import org.hamcrest.Matchers;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.TimeUnit;

import static io.restassured.RestAssured.when;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.fail;

/**
* @author Michal Szynkiewicz, [email protected]
* <br>
* Date: 4/28/20
*/
public class DevModeTest {
@RegisterExtension
public static final QuarkusDevModeTest test = new QuarkusDevModeTest()
.setArchiveProducer(
() -> ShrinkWrap.create(JavaArchive.class)
.addClasses(DevModeTestService.class, DevModeTestStreamService.class, DevModeTestInterceptor.class, DevModeTestRestResource.class)
.addPackage(GreeterGrpc.class.getPackage()).addPackage(HelloReply.class.getPackage())
.addPackage(StreamsGrpc.class.getPackage()).addPackage(StreamsOuterClass.Item.class.getPackage()));

protected ManagedChannel channel;

@BeforeEach
public void init() {
channel = ManagedChannelBuilder.forAddress("localhost", 9000)
.usePlaintext()
.build();
}

@AfterEach
public void shutdown() throws InterruptedException {
channel.shutdownNow().awaitTermination(2, TimeUnit.SECONDS);
}

@Test
public void testInterceptorReload() {
callHello("Pooh", ".*Pooh");

assertThat(when().get("/test/interceptor-status").asString()).isEqualTo("status");

test.modifySourceFile("DevModeTestInterceptor.java",
text -> text.replace("return \"status\"", "return \"altered-status\"")
);

callHello("Pooh", ".*Pooh");
assertThat(when().get("/test/interceptor-status").asString()).isEqualTo("altered-status");
}

@Test
public void testSingleReload() {
callHello("Pooh", "Hello, Pooh");
test.modifySourceFile("DevModeTestService.java",
text -> text.replaceAll("String greeting = .*;", "String greeting = \"hello, \";")
);
callHello("Pooh", "hello, Pooh");
}

@Test
public void testReloadAfterRest() {
test.modifySourceFile("DevModeTestService.java",
text -> text.replaceAll("String greeting = .*;", "String greeting = \"hell no, \";")
);
test.modifySourceFile("DevModeTestRestResource.java",
text -> text.replace("testresponse", "testresponse2")
);

assertThat(when().get("/test").asString()).isEqualTo("testresponse2");
callHello("Pooh", "hell no, Pooh");
}

@Test
public void testReloadBeforeRest() {
test.modifySourceFile("DevModeTestService.java",
text -> text.replaceAll("String greeting = .*;", "String greeting = \"hell yes, \";")
);
test.modifySourceFile("DevModeTestRestResource.java",
text -> text.replace("testresponse", "testresponse3")
);

callHello("Pooh", "hell yes, Pooh");
assertThat(when().get("/test").asString()).isEqualTo("testresponse3");
}

@Test
public void testEchoStreamReload() {
final CopyOnWriteArrayList<String> results = new CopyOnWriteArrayList<>();
CompletionStage<Boolean> firstStreamFinished = callEcho("foo", results);
Awaitility.await().atMost(1, TimeUnit.SECONDS)
.until(() -> results, Matchers.hasItem("echo::foo"));

test.modifySourceFile("DevModeTestStreamService.java",
text -> text.replace("echo::", "newecho::")
);

final CopyOnWriteArrayList<String> newResults = new CopyOnWriteArrayList<>();
callEcho("foo", newResults);
Awaitility.await().atMost(5, TimeUnit.SECONDS)
.until(() -> newResults, Matchers.hasItem("newecho::foo"));
assertThat(firstStreamFinished).isCompleted();
}


// TODO: implement when we have class from proto generation as a Quarkus build step
public void testProtoFileChangeReload() {
fail("Not implemented.");
}

private CompletionStage<Boolean> callEcho(String name, List<String> output) {
CompletableFuture<Boolean> result = new CompletableFuture<>();
Multi<StreamsOuterClass.Item> request = Multi.createFrom()
.item(name)
.map(StreamsOuterClass.Item.newBuilder()::setName)
.map(StreamsOuterClass.Item.Builder::build);
Multi<StreamsOuterClass.Item> echo = MutinyStreamsGrpc.newMutinyStub(channel)
.echo(request);
echo.subscribe().withSubscriber(Subscribers.<StreamsOuterClass.Item>from(
item -> output.add(item.getName()),
error -> {
error.printStackTrace();
result.completeExceptionally(error);
},
() -> result.complete(true),
s -> s.request(Long.MAX_VALUE)));
return result;
}
private void callHello(String name, String responseMatcher) {
HelloReply reply = GreeterGrpc.newBlockingStub(channel)
.sayHello(HelloRequest.newBuilder().setName(name).build());
assertThat(reply.getMessage()).matches(responseMatcher);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package io.quarkus.grpc.server.devmode;

import io.grpc.ForwardingServerCall;
import io.grpc.Metadata;
import io.grpc.ServerCall;
import io.grpc.ServerCallHandler;
import io.grpc.ServerInterceptor;

import javax.enterprise.context.ApplicationScoped;

@ApplicationScoped
public class DevModeTestInterceptor implements ServerInterceptor {

private volatile String lastStatus = "initial";

@Override
public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(ServerCall<ReqT, RespT> serverCall,
Metadata metadata, ServerCallHandler<ReqT, RespT> serverCallHandler) {
return serverCallHandler
.startCall(new ForwardingServerCall.SimpleForwardingServerCall<ReqT, RespT>(serverCall) {
@Override
protected ServerCall<ReqT, RespT> delegate() {
lastStatus = getStatus();
return super.delegate();
}
}, metadata);
}

public String getLastStatus() {
return lastStatus;
}

private String getStatus() {
return "status";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package io.quarkus.grpc.server.devmode;

import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;

/**
* @author Michal Szynkiewicz, [email protected]
* <br>
* Date: 4/28/20
*/
@Path("/test")
public class DevModeTestRestResource {

@Inject
DevModeTestInterceptor interceptor;

@GET
public String get() {
return "testresponse";
}

@GET
@Path("/interceptor-status")
public String getInterceptorStatus() {
return interceptor.getLastStatus();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package io.quarkus.grpc.server.devmode;

import io.grpc.examples.helloworld.GreeterGrpc;
import io.grpc.examples.helloworld.HelloReply;
import io.grpc.examples.helloworld.HelloRequest;
import io.grpc.stub.StreamObserver;

import javax.inject.Singleton;

/**
* @author Michal Szynkiewicz, [email protected]
* <br>
* Date: 4/28/20
*/
@Singleton
public class DevModeTestService extends GreeterGrpc.GreeterImplBase {

@Override
public void sayHello(HelloRequest request, StreamObserver<HelloReply> responseObserver) {
String greeting = "Hello, ";
responseObserver.onNext(HelloReply.newBuilder().setMessage(greeting + request.getName()).build());
responseObserver.onCompleted();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package io.quarkus.grpc.server.devmode;

import com.example.test.MutinyStreamsGrpc;
import com.example.test.StreamsOuterClass.Item;
import io.smallrye.mutiny.Multi;

import javax.inject.Singleton;
import java.time.Duration;

/**
* @author Michal Szynkiewicz, [email protected]
* <br>
* Date: 4/29/20
*/
@Singleton
public class DevModeTestStreamService extends MutinyStreamsGrpc.StreamsImplBase {

public static final String PREFIX = "echo::";

@Override
public Multi<Item> echo(Multi<Item> request) {
return request.flatMap(value ->
Multi.createFrom().ticks().every(Duration.ofMillis(20))
.map(whatever ->
Item.newBuilder().setName(PREFIX + value.getName()).build()
)
);
}
}
13 changes: 13 additions & 0 deletions deployment/src/test/proto/streams.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
syntax = "proto3";

package com.example;

option java_package = "com.example.test";

service Streams {
rpc Echo (stream Item) returns (stream Item) {}
}

message Item {
string name = 1;
}
7 changes: 7 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
<quarkus.platform.version>${quarkus.version}</quarkus.platform.version>
<compiler-plugin.version>3.8.1</compiler-plugin.version>
<surefire-plugin.version>2.22.1</surefire-plugin.version>
<vertx-grpc.version>3.9.1-SNAPSHOT</vertx-grpc.version>
<grpc.version>1.25.0</grpc.version>
<protoc.version>3.5.1</protoc.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
Expand Down Expand Up @@ -66,6 +67,12 @@
<version>${project.version}</version>
</dependency>

<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-grpc</artifactId>
<version>${vertx-grpc.version}</version>
</dependency>

<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
Expand Down
4 changes: 0 additions & 4 deletions runtime/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@
<version>999-SNAPSHOT</version>
</parent>

<properties>
<vertx.version>3.9.0</vertx.version>
</properties>

<artifactId>quarkus-grpc</artifactId>
<name>Quarkus - gRPC - Runtime</name>
Expand All @@ -20,7 +17,6 @@
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-grpc</artifactId>
<version>${vertx.version}</version>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
Expand Down
Loading

0 comments on commit 03bc10f

Please sign in to comment.