diff --git a/testing-proto/build.gradle b/testing-proto/build.gradle index b1c65bc3e48..144c06d3ac3 100644 --- a/testing-proto/build.gradle +++ b/testing-proto/build.gradle @@ -14,6 +14,7 @@ dependencies { project(':grpc-stub') compileOnly libraries.javax_annotation testCompile libraries.truth + testRuntime libraries.javax_annotation } configureProtoCompilation() diff --git a/testing-proto/src/test/java/io/grpc/testing/protobuf/SimpleServiceTest.java b/testing-proto/src/test/java/io/grpc/testing/protobuf/SimpleServiceTest.java index cce7c98b107..85c39f3c743 100644 --- a/testing-proto/src/test/java/io/grpc/testing/protobuf/SimpleServiceTest.java +++ b/testing-proto/src/test/java/io/grpc/testing/protobuf/SimpleServiceTest.java @@ -24,6 +24,23 @@ import static org.junit.Assert.assertTrue; import io.grpc.MethodDescriptor; +import io.grpc.stub.annotations.RpcMethod; +import java.io.File; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import javax.annotation.processing.AbstractProcessor; +import javax.annotation.processing.RoundEnvironment; +import javax.lang.model.element.Element; +import javax.lang.model.element.TypeElement; +import javax.lang.model.type.MirroredTypeException; +import javax.tools.JavaCompiler; +import javax.tools.JavaCompiler.CompilationTask; +import javax.tools.JavaFileObject; +import javax.tools.StandardJavaFileManager; +import javax.tools.ToolProvider; +import org.junit.Assume; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -57,4 +74,91 @@ public void serviceMethodDescriotrs() { public void generatedMethodsAreSampledToLocalTracing() throws Exception { assertTrue(SimpleServiceGrpc.getUnaryRpcMethod().isSampledToLocalTracing()); } + + public static class AnnotationProcessor extends AbstractProcessor { + + private boolean processedClass = false; + + @Override + public Set getSupportedAnnotationTypes() { + return Collections.singleton(RpcMethod.class.getCanonicalName()); + } + + private void verifyRpcMethodAnnotation( + MethodDescriptor descriptor, RpcMethod annotation) { + assertEquals(descriptor.getFullMethodName(), annotation.fullMethodName()); + assertEquals(descriptor.getType(), annotation.methodType()); + + // Class objects may not be available at runtime, handle MirroredTypeException if it occurs + try { + assertEquals(SimpleRequest.class, annotation.requestType()); + } catch (MirroredTypeException e) { + assertEquals(SimpleRequest.class.getCanonicalName(), e.getTypeMirror().toString()); + } + + try { + assertEquals(SimpleResponse.class, annotation.responseType()); + } catch (MirroredTypeException e) { + assertEquals(SimpleResponse.class.getCanonicalName(), e.getTypeMirror().toString()); + } + } + + @Override + public synchronized boolean process( + Set annotations, RoundEnvironment roundEnv) { + for (Element rootElement : roundEnv.getRootElements()) { + if (!rootElement.asType().toString().equals(SimpleServiceGrpc.class.getCanonicalName())) { + continue; + } + + Map methodToAnnotation = new HashMap(); + for (Element enclosedElement : rootElement.getEnclosedElements()) { + RpcMethod annotation = enclosedElement.getAnnotation(RpcMethod.class); + if (annotation != null) { + methodToAnnotation.put(enclosedElement.getSimpleName().toString(), annotation); + } + } + + verifyRpcMethodAnnotation( + SimpleServiceGrpc.getUnaryRpcMethod(), methodToAnnotation.get("getUnaryRpcMethod")); + verifyRpcMethodAnnotation( + SimpleServiceGrpc.getServerStreamingRpcMethod(), + methodToAnnotation.get("getServerStreamingRpcMethod")); + verifyRpcMethodAnnotation( + SimpleServiceGrpc.getClientStreamingRpcMethod(), + methodToAnnotation.get("getClientStreamingRpcMethod")); + verifyRpcMethodAnnotation( + SimpleServiceGrpc.getBidiStreamingRpcMethod(), + methodToAnnotation.get("getBidiStreamingRpcMethod")); + + processedClass = true; + } + return false; + } + } + + @Test + public void testRpcMethodAnnotations() throws Exception { + File grpcJavaFile = + new File("./src/generated/main/grpc/io/grpc/testing/protobuf/SimpleServiceGrpc.java"); + Assume.assumeTrue(grpcJavaFile.exists()); + + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null); + AnnotationProcessor processor = new AnnotationProcessor(); + Iterable obs = fileManager.getJavaFileObjects(grpcJavaFile); + + CompilationTask task = + compiler.getTask( + null, + fileManager, + null, + Collections.singleton("-proc:only"), + Collections.singleton(SimpleServiceGrpc.class.getCanonicalName()), + obs); + task.setProcessors(Collections.singleton(processor)); + assertTrue(task.call()); + assertTrue(processor.processedClass); + fileManager.close(); + } }