1 /* 2 * Copyright 2017 The gRPC Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package io.grpc.testing.protobuf; 18 19 import static io.grpc.MethodDescriptor.MethodType.BIDI_STREAMING; 20 import static io.grpc.MethodDescriptor.MethodType.CLIENT_STREAMING; 21 import static io.grpc.MethodDescriptor.MethodType.SERVER_STREAMING; 22 import static io.grpc.MethodDescriptor.MethodType.UNARY; 23 import static org.junit.Assert.assertEquals; 24 import static org.junit.Assert.assertTrue; 25 26 import io.grpc.MethodDescriptor; 27 import io.grpc.stub.annotations.RpcMethod; 28 import java.io.File; 29 import java.util.Collections; 30 import java.util.HashMap; 31 import java.util.Map; 32 import java.util.Set; 33 import javax.annotation.processing.AbstractProcessor; 34 import javax.annotation.processing.RoundEnvironment; 35 import javax.lang.model.SourceVersion; 36 import javax.lang.model.element.Element; 37 import javax.lang.model.element.TypeElement; 38 import javax.lang.model.type.MirroredTypeException; 39 import javax.tools.JavaCompiler; 40 import javax.tools.JavaCompiler.CompilationTask; 41 import javax.tools.JavaFileObject; 42 import javax.tools.StandardJavaFileManager; 43 import javax.tools.ToolProvider; 44 import org.junit.Assume; 45 import org.junit.Test; 46 import org.junit.runner.RunWith; 47 import org.junit.runners.JUnit4; 48 49 /** Test to verify that the proto file simpleservice.proto generates the expected service. */ 50 @RunWith(JUnit4.class) 51 public class SimpleServiceTest { 52 @Test serviceDescriptor()53 public void serviceDescriptor() { 54 assertEquals("grpc.testing.SimpleService", SimpleServiceGrpc.getServiceDescriptor().getName()); 55 } 56 57 @Test serviceMethodDescriotrs()58 public void serviceMethodDescriotrs() { 59 MethodDescriptor<SimpleRequest, SimpleResponse> genericTypeShouldMatchWhenAssigned; 60 61 genericTypeShouldMatchWhenAssigned = SimpleServiceGrpc.getUnaryRpcMethod(); 62 assertEquals(UNARY, genericTypeShouldMatchWhenAssigned.getType()); 63 64 genericTypeShouldMatchWhenAssigned = SimpleServiceGrpc.getClientStreamingRpcMethod(); 65 assertEquals(CLIENT_STREAMING, genericTypeShouldMatchWhenAssigned.getType()); 66 67 genericTypeShouldMatchWhenAssigned = SimpleServiceGrpc.getServerStreamingRpcMethod(); 68 assertEquals(SERVER_STREAMING, genericTypeShouldMatchWhenAssigned.getType()); 69 70 genericTypeShouldMatchWhenAssigned = SimpleServiceGrpc.getBidiStreamingRpcMethod(); 71 assertEquals(BIDI_STREAMING, genericTypeShouldMatchWhenAssigned.getType()); 72 } 73 74 @Test generatedMethodsAreSampledToLocalTracing()75 public void generatedMethodsAreSampledToLocalTracing() throws Exception { 76 assertTrue(SimpleServiceGrpc.getUnaryRpcMethod().isSampledToLocalTracing()); 77 } 78 79 public static class AnnotationProcessor extends AbstractProcessor { 80 81 private boolean processedClass = false; 82 83 @Override getSupportedSourceVersion()84 public SourceVersion getSupportedSourceVersion() { 85 return SourceVersion.latestSupported(); 86 } 87 88 @Override getSupportedAnnotationTypes()89 public Set<String> getSupportedAnnotationTypes() { 90 return Collections.singleton(RpcMethod.class.getCanonicalName()); 91 } 92 verifyRpcMethodAnnotation( MethodDescriptor<SimpleRequest, SimpleResponse> descriptor, RpcMethod annotation)93 private void verifyRpcMethodAnnotation( 94 MethodDescriptor<SimpleRequest, SimpleResponse> descriptor, RpcMethod annotation) { 95 assertEquals(descriptor.getFullMethodName(), annotation.fullMethodName()); 96 assertEquals(descriptor.getType(), annotation.methodType()); 97 98 // Class objects may not be available at runtime, handle MirroredTypeException if it occurs 99 try { 100 assertEquals(SimpleRequest.class, annotation.requestType()); 101 } catch (MirroredTypeException e) { 102 assertEquals(SimpleRequest.class.getCanonicalName(), e.getTypeMirror().toString()); 103 } 104 105 try { 106 assertEquals(SimpleResponse.class, annotation.responseType()); 107 } catch (MirroredTypeException e) { 108 assertEquals(SimpleResponse.class.getCanonicalName(), e.getTypeMirror().toString()); 109 } 110 } 111 112 @Override process( Set<? extends TypeElement> annotations, RoundEnvironment roundEnv)113 public synchronized boolean process( 114 Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { 115 for (Element rootElement : roundEnv.getRootElements()) { 116 if (!rootElement.asType().toString().equals(SimpleServiceGrpc.class.getCanonicalName())) { 117 continue; 118 } 119 120 Map<String, RpcMethod> methodToAnnotation = new HashMap<>(); 121 for (Element enclosedElement : rootElement.getEnclosedElements()) { 122 RpcMethod annotation = enclosedElement.getAnnotation(RpcMethod.class); 123 if (annotation != null) { 124 methodToAnnotation.put(enclosedElement.getSimpleName().toString(), annotation); 125 } 126 } 127 128 verifyRpcMethodAnnotation( 129 SimpleServiceGrpc.getUnaryRpcMethod(), methodToAnnotation.get("getUnaryRpcMethod")); 130 verifyRpcMethodAnnotation( 131 SimpleServiceGrpc.getServerStreamingRpcMethod(), 132 methodToAnnotation.get("getServerStreamingRpcMethod")); 133 verifyRpcMethodAnnotation( 134 SimpleServiceGrpc.getClientStreamingRpcMethod(), 135 methodToAnnotation.get("getClientStreamingRpcMethod")); 136 verifyRpcMethodAnnotation( 137 SimpleServiceGrpc.getBidiStreamingRpcMethod(), 138 methodToAnnotation.get("getBidiStreamingRpcMethod")); 139 140 processedClass = true; 141 } 142 return false; 143 } 144 } 145 146 @Test testRpcMethodAnnotations()147 public void testRpcMethodAnnotations() throws Exception { 148 File grpcJavaFile = 149 new File("./src/generated/main/grpc/io/grpc/testing/protobuf/SimpleServiceGrpc.java"); 150 Assume.assumeTrue(grpcJavaFile.exists()); 151 152 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); 153 StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null); 154 AnnotationProcessor processor = new AnnotationProcessor(); 155 Iterable<? extends JavaFileObject> obs = fileManager.getJavaFileObjects(grpcJavaFile); 156 157 CompilationTask task = 158 compiler.getTask( 159 null, 160 fileManager, 161 null, 162 Collections.singleton("-proc:only"), 163 Collections.singleton(SimpleServiceGrpc.class.getCanonicalName()), 164 obs); 165 task.setProcessors(Collections.singleton(processor)); 166 assertTrue(task.call()); 167 assertTrue(processor.processedClass); 168 fileManager.close(); 169 } 170 } 171