Home | History | Annotate | Download | only in protobuf
      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.element.Element;
     36 import javax.lang.model.element.TypeElement;
     37 import javax.lang.model.type.MirroredTypeException;
     38 import javax.tools.JavaCompiler;
     39 import javax.tools.JavaCompiler.CompilationTask;
     40 import javax.tools.JavaFileObject;
     41 import javax.tools.StandardJavaFileManager;
     42 import javax.tools.ToolProvider;
     43 import org.junit.Assume;
     44 import org.junit.Test;
     45 import org.junit.runner.RunWith;
     46 import org.junit.runners.JUnit4;
     47 
     48 /** Test to verify that the proto file simpleservice.proto generates the expected service. */
     49 @RunWith(JUnit4.class)
     50 public class SimpleServiceTest {
     51   @Test
     52   public void serviceDescriptor() {
     53     assertEquals("grpc.testing.SimpleService", SimpleServiceGrpc.getServiceDescriptor().getName());
     54   }
     55 
     56   @Test
     57   public void serviceMethodDescriotrs() {
     58     MethodDescriptor<SimpleRequest, SimpleResponse> genericTypeShouldMatchWhenAssigned;
     59 
     60     genericTypeShouldMatchWhenAssigned = SimpleServiceGrpc.getUnaryRpcMethod();
     61     assertEquals(UNARY, genericTypeShouldMatchWhenAssigned.getType());
     62 
     63     genericTypeShouldMatchWhenAssigned = SimpleServiceGrpc.getClientStreamingRpcMethod();
     64     assertEquals(CLIENT_STREAMING, genericTypeShouldMatchWhenAssigned.getType());
     65 
     66     genericTypeShouldMatchWhenAssigned = SimpleServiceGrpc.getServerStreamingRpcMethod();
     67     assertEquals(SERVER_STREAMING, genericTypeShouldMatchWhenAssigned.getType());
     68 
     69     genericTypeShouldMatchWhenAssigned = SimpleServiceGrpc.getBidiStreamingRpcMethod();
     70     assertEquals(BIDI_STREAMING, genericTypeShouldMatchWhenAssigned.getType());
     71   }
     72 
     73   @Test
     74   public void generatedMethodsAreSampledToLocalTracing() throws Exception {
     75     assertTrue(SimpleServiceGrpc.getUnaryRpcMethod().isSampledToLocalTracing());
     76   }
     77 
     78   public static class AnnotationProcessor extends AbstractProcessor {
     79 
     80     private boolean processedClass = false;
     81 
     82     @Override
     83     public Set<String> getSupportedAnnotationTypes() {
     84       return Collections.singleton(RpcMethod.class.getCanonicalName());
     85     }
     86 
     87     private void verifyRpcMethodAnnotation(
     88         MethodDescriptor<SimpleRequest, SimpleResponse> descriptor, RpcMethod annotation) {
     89       assertEquals(descriptor.getFullMethodName(), annotation.fullMethodName());
     90       assertEquals(descriptor.getType(), annotation.methodType());
     91 
     92       // Class objects may not be available at runtime, handle MirroredTypeException if it occurs
     93       try {
     94         assertEquals(SimpleRequest.class, annotation.requestType());
     95       } catch (MirroredTypeException e) {
     96         assertEquals(SimpleRequest.class.getCanonicalName(), e.getTypeMirror().toString());
     97       }
     98 
     99       try {
    100         assertEquals(SimpleResponse.class, annotation.responseType());
    101       } catch (MirroredTypeException e) {
    102         assertEquals(SimpleResponse.class.getCanonicalName(), e.getTypeMirror().toString());
    103       }
    104     }
    105 
    106     @Override
    107     public synchronized boolean process(
    108         Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
    109       for (Element rootElement : roundEnv.getRootElements()) {
    110         if (!rootElement.asType().toString().equals(SimpleServiceGrpc.class.getCanonicalName())) {
    111           continue;
    112         }
    113 
    114         Map<String, RpcMethod> methodToAnnotation = new HashMap<String, RpcMethod>();
    115         for (Element enclosedElement : rootElement.getEnclosedElements()) {
    116           RpcMethod annotation = enclosedElement.getAnnotation(RpcMethod.class);
    117           if (annotation != null) {
    118             methodToAnnotation.put(enclosedElement.getSimpleName().toString(), annotation);
    119           }
    120         }
    121 
    122         verifyRpcMethodAnnotation(
    123             SimpleServiceGrpc.getUnaryRpcMethod(), methodToAnnotation.get("getUnaryRpcMethod"));
    124         verifyRpcMethodAnnotation(
    125             SimpleServiceGrpc.getServerStreamingRpcMethod(),
    126             methodToAnnotation.get("getServerStreamingRpcMethod"));
    127         verifyRpcMethodAnnotation(
    128             SimpleServiceGrpc.getClientStreamingRpcMethod(),
    129             methodToAnnotation.get("getClientStreamingRpcMethod"));
    130         verifyRpcMethodAnnotation(
    131             SimpleServiceGrpc.getBidiStreamingRpcMethod(),
    132             methodToAnnotation.get("getBidiStreamingRpcMethod"));
    133 
    134         processedClass = true;
    135       }
    136       return false;
    137     }
    138   }
    139 
    140   @Test
    141   public void testRpcMethodAnnotations() throws Exception {
    142     File grpcJavaFile =
    143         new File("./src/generated/main/grpc/io/grpc/testing/protobuf/SimpleServiceGrpc.java");
    144     Assume.assumeTrue(grpcJavaFile.exists());
    145 
    146     JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
    147     StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
    148     AnnotationProcessor processor = new AnnotationProcessor();
    149     Iterable<? extends JavaFileObject> obs = fileManager.getJavaFileObjects(grpcJavaFile);
    150 
    151     CompilationTask task =
    152         compiler.getTask(
    153             null,
    154             fileManager,
    155             null,
    156             Collections.singleton("-proc:only"),
    157             Collections.singleton(SimpleServiceGrpc.class.getCanonicalName()),
    158             obs);
    159     task.setProcessors(Collections.singleton(processor));
    160     assertTrue(task.call());
    161     assertTrue(processor.processedClass);
    162     fileManager.close();
    163   }
    164 }
    165