• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 //     * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 //     * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 //     * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 package com.google.protobuf;
32 
33 import com.google.protobuf.Descriptors.FileDescriptor;
34 import com.google.protobuf.Descriptors.MethodDescriptor;
35 import protobuf_unittest.MessageWithNoOuter;
36 import protobuf_unittest.ServiceWithNoOuter;
37 import protobuf_unittest.UnittestProto.BarRequest;
38 import protobuf_unittest.UnittestProto.BarResponse;
39 import protobuf_unittest.UnittestProto.FooRequest;
40 import protobuf_unittest.UnittestProto.FooResponse;
41 import protobuf_unittest.UnittestProto.TestAllTypes;
42 import protobuf_unittest.UnittestProto.TestService;
43 import protobuf_unittest.no_generic_services_test.UnittestNoGenericServices;
44 import java.util.HashSet;
45 import java.util.Set;
46 import junit.framework.TestCase;
47 import org.easymock.classextension.EasyMock;
48 import org.easymock.IArgumentMatcher;
49 import org.easymock.classextension.IMocksControl;
50 
51 /**
52  * Tests services and stubs.
53  *
54  * @author kenton@google.com Kenton Varda
55  */
56 public class ServiceTest extends TestCase {
57   private IMocksControl control;
58   private RpcController mockController;
59 
60   private final Descriptors.MethodDescriptor fooDescriptor =
61       TestService.getDescriptor().getMethods().get(0);
62   private final Descriptors.MethodDescriptor barDescriptor =
63       TestService.getDescriptor().getMethods().get(1);
64 
65   @Override
setUp()66   protected void setUp() throws Exception {
67     super.setUp();
68     control = EasyMock.createStrictControl();
69     mockController = control.createMock(RpcController.class);
70   }
71 
72   // =================================================================
73 
74   /** Tests Service.callMethod(). */
testCallMethod()75   public void testCallMethod() throws Exception {
76     FooRequest fooRequest = FooRequest.newBuilder().build();
77     BarRequest barRequest = BarRequest.newBuilder().build();
78     MockCallback<Message> fooCallback = new MockCallback<Message>();
79     MockCallback<Message> barCallback = new MockCallback<Message>();
80     TestService mockService = control.createMock(TestService.class);
81 
82     mockService.foo(
83         EasyMock.same(mockController),
84         EasyMock.same(fooRequest),
85         this.<FooResponse>wrapsCallback(fooCallback));
86     mockService.bar(
87         EasyMock.same(mockController),
88         EasyMock.same(barRequest),
89         this.<BarResponse>wrapsCallback(barCallback));
90     control.replay();
91 
92     mockService.callMethod(
93         fooDescriptor, mockController,
94         fooRequest, fooCallback);
95     mockService.callMethod(
96         barDescriptor, mockController,
97         barRequest, barCallback);
98     control.verify();
99   }
100 
101   /** Tests Service.get{Request,Response}Prototype(). */
testGetPrototype()102   public void testGetPrototype() throws Exception {
103     TestService mockService = control.createMock(TestService.class);
104 
105     assertSame(mockService.getRequestPrototype(fooDescriptor), FooRequest.getDefaultInstance());
106     assertSame(mockService.getResponsePrototype(fooDescriptor), FooResponse.getDefaultInstance());
107     assertSame(mockService.getRequestPrototype(barDescriptor), BarRequest.getDefaultInstance());
108     assertSame(mockService.getResponsePrototype(barDescriptor), BarResponse.getDefaultInstance());
109   }
110 
111   /** Tests generated stubs. */
testStub()112   public void testStub() throws Exception {
113     FooRequest fooRequest = FooRequest.newBuilder().build();
114     BarRequest barRequest = BarRequest.newBuilder().build();
115     MockCallback<FooResponse> fooCallback = new MockCallback<FooResponse>();
116     MockCallback<BarResponse> barCallback = new MockCallback<BarResponse>();
117     RpcChannel mockChannel = control.createMock(RpcChannel.class);
118     TestService stub = TestService.newStub(mockChannel);
119 
120     mockChannel.callMethod(
121         EasyMock.same(fooDescriptor),
122         EasyMock.same(mockController),
123         EasyMock.same(fooRequest),
124         EasyMock.same(FooResponse.getDefaultInstance()),
125         this.<Message>wrapsCallback(fooCallback));
126     mockChannel.callMethod(
127         EasyMock.same(barDescriptor),
128         EasyMock.same(mockController),
129         EasyMock.same(barRequest),
130         EasyMock.same(BarResponse.getDefaultInstance()),
131         this.<Message>wrapsCallback(barCallback));
132     control.replay();
133 
134     stub.foo(mockController, fooRequest, fooCallback);
135     stub.bar(mockController, barRequest, barCallback);
136     control.verify();
137   }
138 
139   /** Tests generated blocking stubs. */
testBlockingStub()140   public void testBlockingStub() throws Exception {
141     FooRequest fooRequest = FooRequest.newBuilder().build();
142     BarRequest barRequest = BarRequest.newBuilder().build();
143     BlockingRpcChannel mockChannel = control.createMock(BlockingRpcChannel.class);
144     TestService.BlockingInterface stub = TestService.newBlockingStub(mockChannel);
145 
146     FooResponse fooResponse = FooResponse.newBuilder().build();
147     BarResponse barResponse = BarResponse.newBuilder().build();
148 
149     EasyMock.expect(
150             mockChannel.callBlockingMethod(
151                 EasyMock.same(fooDescriptor),
152                 EasyMock.same(mockController),
153                 EasyMock.same(fooRequest),
154                 EasyMock.same(FooResponse.getDefaultInstance())))
155         .andReturn(fooResponse);
156     EasyMock.expect(
157             mockChannel.callBlockingMethod(
158                 EasyMock.same(barDescriptor),
159                 EasyMock.same(mockController),
160                 EasyMock.same(barRequest),
161                 EasyMock.same(BarResponse.getDefaultInstance())))
162         .andReturn(barResponse);
163     control.replay();
164 
165     assertSame(fooResponse, stub.foo(mockController, fooRequest));
166     assertSame(barResponse, stub.bar(mockController, barRequest));
167     control.verify();
168   }
169 
testNewReflectiveService()170   public void testNewReflectiveService() {
171     ServiceWithNoOuter.Interface impl = control.createMock(ServiceWithNoOuter.Interface.class);
172     RpcController controller = control.createMock(RpcController.class);
173     Service service = ServiceWithNoOuter.newReflectiveService(impl);
174 
175     MethodDescriptor fooMethod = ServiceWithNoOuter.getDescriptor().findMethodByName("Foo");
176     MessageWithNoOuter request = MessageWithNoOuter.getDefaultInstance();
177     RpcCallback<Message> callback =
178         new RpcCallback<Message>() {
179           @Override
180           public void run(Message parameter) {
181             // No reason this should be run.
182             fail();
183           }
184         };
185     RpcCallback<TestAllTypes> specializedCallback = RpcUtil.specializeCallback(callback);
186 
187     impl.foo(EasyMock.same(controller), EasyMock.same(request), EasyMock.same(specializedCallback));
188     EasyMock.expectLastCall();
189 
190     control.replay();
191 
192     service.callMethod(fooMethod, controller, request, callback);
193 
194     control.verify();
195   }
196 
testNewReflectiveBlockingService()197   public void testNewReflectiveBlockingService() throws ServiceException {
198     ServiceWithNoOuter.BlockingInterface impl =
199         control.createMock(ServiceWithNoOuter.BlockingInterface.class);
200     RpcController controller = control.createMock(RpcController.class);
201     BlockingService service = ServiceWithNoOuter.newReflectiveBlockingService(impl);
202 
203     MethodDescriptor fooMethod = ServiceWithNoOuter.getDescriptor().findMethodByName("Foo");
204     MessageWithNoOuter request = MessageWithNoOuter.getDefaultInstance();
205 
206     TestAllTypes expectedResponse = TestAllTypes.getDefaultInstance();
207     EasyMock.expect(impl.foo(EasyMock.same(controller), EasyMock.same(request)))
208         .andReturn(expectedResponse);
209 
210     control.replay();
211 
212     Message response = service.callBlockingMethod(fooMethod, controller, request);
213     assertEquals(expectedResponse, response);
214 
215     control.verify();
216   }
217 
testNoGenericServices()218   public void testNoGenericServices() throws Exception {
219     // Non-services should be usable.
220     UnittestNoGenericServices.TestMessage message =
221         UnittestNoGenericServices.TestMessage.newBuilder()
222             .setA(123)
223             .setExtension(UnittestNoGenericServices.testExtension, 456)
224             .build();
225     assertEquals(123, message.getA());
226     assertEquals(1, UnittestNoGenericServices.TestEnum.FOO.getNumber());
227 
228     // Build a list of the class names nested in UnittestNoGenericServices.
229     String outerName =
230         "protobuf_unittest.no_generic_services_test.UnittestNoGenericServices";
231     Class<?> outerClass = Class.forName(outerName);
232 
233     Set<String> innerClassNames = new HashSet<String>();
234     for (Class<?> innerClass : outerClass.getClasses()) {
235       String fullName = innerClass.getName();
236       // Figure out the unqualified name of the inner class.
237       // Note:  Surprisingly, the full name of an inner class will be separated
238       //   from the outer class name by a '$' rather than a '.'.  This is not
239       //   mentioned in the documentation for java.lang.Class.  I don't want to
240       //   make assumptions, so I'm just going to accept any character as the
241       //   separator.
242       assertTrue(fullName.startsWith(outerName));
243 
244       if (!Service.class.isAssignableFrom(innerClass)
245           && !Message.class.isAssignableFrom(innerClass)
246           && !ProtocolMessageEnum.class.isAssignableFrom(innerClass)) {
247         // Ignore any classes not generated by the base code generator.
248         continue;
249       }
250 
251       innerClassNames.add(fullName.substring(outerName.length() + 1));
252     }
253 
254     // No service class should have been generated.
255     assertTrue(innerClassNames.contains("TestMessage"));
256     assertTrue(innerClassNames.contains("TestEnum"));
257     assertFalse(innerClassNames.contains("TestService"));
258 
259     // But descriptors are there.
260     FileDescriptor file = UnittestNoGenericServices.getDescriptor();
261     assertEquals(1, file.getServices().size());
262     assertEquals("TestService", file.getServices().get(0).getName());
263     assertEquals(1, file.getServices().get(0).getMethods().size());
264     assertEquals("Foo", file.getServices().get(0).getMethods().get(0).getName());
265   }
266 
267 
268   // =================================================================
269 
270   /**
271    * wrapsCallback() is an EasyMock argument predicate. wrapsCallback(c) matches a callback if
272    * calling that callback causes c to be called. In other words, c wraps the given callback.
273    */
wrapsCallback(MockCallback<?> callback)274   private <T extends Message> RpcCallback<T> wrapsCallback(MockCallback<?> callback) {
275     EasyMock.reportMatcher(new WrapsCallback(callback));
276     return null;
277   }
278 
279   /** The parameter to wrapsCallback() must be a MockCallback. */
280   private static class MockCallback<T extends Message> implements RpcCallback<T> {
281     private boolean called = false;
282 
isCalled()283     public boolean isCalled() {
284       return called;
285     }
286 
reset()287     public void reset() {
288       called = false;
289     }
290 
291     @Override
run(T message)292     public void run(T message) {
293       called = true;
294     }
295   }
296 
297   /** Implementation of the wrapsCallback() argument matcher. */
298   private static class WrapsCallback implements IArgumentMatcher {
299     private MockCallback<?> callback;
300 
WrapsCallback(MockCallback<?> callback)301     public WrapsCallback(MockCallback<?> callback) {
302       this.callback = callback;
303     }
304 
305     @Override
306     @SuppressWarnings("unchecked")
matches(Object actual)307     public boolean matches(Object actual) {
308       if (!(actual instanceof RpcCallback)) {
309         return false;
310       }
311       RpcCallback actualCallback = (RpcCallback) actual;
312 
313       callback.reset();
314       actualCallback.run(null);
315       return callback.isCalled();
316     }
317 
318     @Override
appendTo(StringBuffer buffer)319     public void appendTo(StringBuffer buffer) {
320       buffer.append("wrapsCallback(mockCallback)");
321     }
322   }
323 }
324