• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016 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;
18 
19 import static com.google.common.base.Preconditions.checkState;
20 
21 import io.grpc.BindableService;
22 import io.grpc.ExperimentalApi;
23 import io.grpc.ManagedChannel;
24 import io.grpc.Server;
25 import io.grpc.ServerServiceDefinition;
26 import io.grpc.inprocess.InProcessChannelBuilder;
27 import io.grpc.inprocess.InProcessServerBuilder;
28 import io.grpc.stub.AbstractStub;
29 import io.grpc.util.MutableHandlerRegistry;
30 import java.util.UUID;
31 import java.util.concurrent.TimeUnit;
32 import org.junit.rules.ExternalResource;
33 import org.junit.rules.TestRule;
34 
35 /**
36  * {@code GrpcServerRule} is a JUnit {@link TestRule} that starts an in-process gRPC service with
37  * a {@link MutableHandlerRegistry} for adding services. It is particularly useful for mocking out
38  * external gRPC-based services and asserting that the expected requests were made.
39  *
40  * <p>An {@link AbstractStub} can be created against this service by using the
41  * {@link ManagedChannel} provided by {@link GrpcServerRule#getChannel()}.
42  */
43 @ExperimentalApi("https://github.com/grpc/grpc-java/issues/2488")
44 public final class GrpcServerRule extends ExternalResource {
45 
46   private ManagedChannel channel;
47   private Server server;
48   private String serverName;
49   private MutableHandlerRegistry serviceRegistry;
50   private boolean useDirectExecutor;
51 
52   /**
53    * Returns {@code this} configured to use a direct executor for the {@link ManagedChannel} and
54    * {@link Server}. This can only be called at the rule instantiation.
55    */
directExecutor()56   public final GrpcServerRule directExecutor() {
57     checkState(serverName == null, "directExecutor() can only be called at the rule instantiation");
58     useDirectExecutor = true;
59     return this;
60   }
61 
62   /**
63    * Returns a {@link ManagedChannel} connected to this service.
64    */
getChannel()65   public final ManagedChannel getChannel() {
66     return channel;
67   }
68 
69   /**
70    * Returns the underlying gRPC {@link Server} for this service.
71    */
getServer()72   public final Server getServer() {
73     return server;
74   }
75 
76   /**
77    * Returns the randomly generated server name for this service.
78    */
getServerName()79   public final String getServerName() {
80     return serverName;
81   }
82 
83   /**
84    * Returns the service registry for this service. The registry is used to add service instances
85    * (e.g. {@link BindableService} or {@link ServerServiceDefinition} to the server.
86    */
getServiceRegistry()87   public final MutableHandlerRegistry getServiceRegistry() {
88     return serviceRegistry;
89   }
90 
91   /**
92    * After the test has completed, clean up the channel and server.
93    */
94   @Override
after()95   protected void after() {
96     serverName = null;
97     serviceRegistry = null;
98 
99     channel.shutdown();
100     server.shutdown();
101 
102     try {
103       channel.awaitTermination(1, TimeUnit.MINUTES);
104       server.awaitTermination(1, TimeUnit.MINUTES);
105     } catch (InterruptedException e) {
106       Thread.currentThread().interrupt();
107       throw new RuntimeException(e);
108     } finally {
109       channel.shutdownNow();
110       channel = null;
111 
112       server.shutdownNow();
113       server = null;
114     }
115   }
116 
117   /**
118    * Before the test has started, create the server and channel.
119    */
120   @Override
before()121   protected void before() throws Throwable {
122     serverName = UUID.randomUUID().toString();
123 
124     serviceRegistry = new MutableHandlerRegistry();
125 
126     InProcessServerBuilder serverBuilder = InProcessServerBuilder.forName(serverName)
127         .fallbackHandlerRegistry(serviceRegistry);
128 
129     if (useDirectExecutor) {
130       serverBuilder.directExecutor();
131     }
132 
133     server = serverBuilder.build().start();
134 
135     InProcessChannelBuilder channelBuilder = InProcessChannelBuilder.forName(serverName);
136 
137     if (useDirectExecutor) {
138       channelBuilder.directExecutor();
139     }
140 
141     channel = channelBuilder.build();
142   }
143 }
144