1 // Protocol Buffers - Google's data interchange format 2 // Copyright 2008 Google Inc. All rights reserved. 3 // 4 // Use of this source code is governed by a BSD-style 5 // license that can be found in the LICENSE file or at 6 // https://developers.google.com/open-source/licenses/bsd 7 8 package com.google.protobuf; 9 10 import static com.google.common.truth.Truth.assertThat; 11 import static com.google.common.truth.Truth.assertWithMessage; 12 import static org.mockito.Mockito.verify; 13 import static org.mockito.Mockito.when; 14 15 import com.google.protobuf.Descriptors.FileDescriptor; 16 import com.google.protobuf.Descriptors.MethodDescriptor; 17 import protobuf_unittest.MessageWithNoOuter; 18 import protobuf_unittest.ServiceWithNoOuter; 19 import protobuf_unittest.UnittestProto.BarRequest; 20 import protobuf_unittest.UnittestProto.BarResponse; 21 import protobuf_unittest.UnittestProto.FooRequest; 22 import protobuf_unittest.UnittestProto.FooResponse; 23 import protobuf_unittest.UnittestProto.TestAllTypes; 24 import protobuf_unittest.UnittestProto.TestService; 25 import protobuf_unittest.no_generic_services_test.UnittestNoGenericServices; 26 import java.util.HashSet; 27 import java.util.Set; 28 import org.junit.Test; 29 import org.junit.runner.RunWith; 30 import org.junit.runners.JUnit4; 31 import org.mockito.InOrder; 32 import org.mockito.Mockito; 33 34 @RunWith(JUnit4.class) 35 public class ServiceTest { 36 private final Descriptors.MethodDescriptor fooDescriptor = 37 TestService.getDescriptor().getMethods().get(0); 38 private final Descriptors.MethodDescriptor barDescriptor = 39 TestService.getDescriptor().getMethods().get(1); 40 private static final FooRequest FOO_REQUEST = FooRequest.getDefaultInstance(); 41 private static final BarRequest BAR_REQUEST = BarRequest.getDefaultInstance(); 42 private static final RpcController MOCK_RPC_CONTROLLER = Mockito.mock(RpcController.class); 43 private static final FooResponse FOO_RESPONSE = FooResponse.getDefaultInstance(); 44 private static final BarResponse BAR_RESPONSE = BarResponse.getDefaultInstance(); 45 private static final MessageWithNoOuter MESSAGE_WITH_NO_OUTER = 46 MessageWithNoOuter.getDefaultInstance(); 47 48 /** Tests Service.callMethod(). */ 49 @Test 50 @SuppressWarnings({"unchecked", "rawtypes"}) testCallMethod()51 public void testCallMethod() throws Exception { 52 TestService mockService = Mockito.mock(TestService.class); 53 RpcCallback mockFooRpcCallback = Mockito.mock(RpcCallback.class); 54 RpcCallback mockBarRpcCallback = Mockito.mock(RpcCallback.class); 55 InOrder order = Mockito.inOrder(mockService); 56 57 mockService.callMethod(fooDescriptor, MOCK_RPC_CONTROLLER, FOO_REQUEST, mockFooRpcCallback); 58 mockService.callMethod(barDescriptor, MOCK_RPC_CONTROLLER, BAR_REQUEST, mockBarRpcCallback); 59 order 60 .verify(mockService) 61 .foo( 62 Mockito.same(MOCK_RPC_CONTROLLER), 63 Mockito.same(FOO_REQUEST), 64 Mockito.same(mockFooRpcCallback)); 65 order 66 .verify(mockService) 67 .bar( 68 Mockito.same(MOCK_RPC_CONTROLLER), 69 Mockito.same(BAR_REQUEST), 70 Mockito.same(mockBarRpcCallback)); 71 } 72 73 /** Tests Service.get{Request,Response}Prototype(). */ 74 @Test testGetPrototype()75 public void testGetPrototype() throws Exception { 76 Descriptors.MethodDescriptor fooDescriptor = TestService.getDescriptor().getMethods().get(0); 77 Descriptors.MethodDescriptor barDescriptor = TestService.getDescriptor().getMethods().get(1); 78 TestService mockService = Mockito.mock(TestService.class); 79 80 assertThat(mockService.getRequestPrototype(fooDescriptor)).isSameInstanceAs(FOO_REQUEST); 81 assertThat(mockService.getResponsePrototype(fooDescriptor)).isSameInstanceAs(FOO_RESPONSE); 82 assertThat(mockService.getRequestPrototype(barDescriptor)).isSameInstanceAs(BAR_REQUEST); 83 assertThat(mockService.getResponsePrototype(barDescriptor)).isSameInstanceAs(BAR_RESPONSE); 84 } 85 86 /** Tests generated stubs. */ 87 @Test 88 @SuppressWarnings({"unchecked", "rawtypes"}) testStub()89 public void testStub() throws Exception { 90 RpcCallback mockFooRpcCallback = Mockito.mock(RpcCallback.class); 91 RpcCallback mockBarRpcCallback = Mockito.mock(RpcCallback.class); 92 RpcChannel mockRpcChannel = Mockito.mock(RpcChannel.class); 93 InOrder order = Mockito.inOrder(mockRpcChannel); 94 TestService stub = TestService.newStub(mockRpcChannel); 95 96 stub.foo(MOCK_RPC_CONTROLLER, FOO_REQUEST, mockFooRpcCallback); 97 stub.bar(MOCK_RPC_CONTROLLER, BAR_REQUEST, mockBarRpcCallback); 98 99 order 100 .verify(mockRpcChannel) 101 .callMethod( 102 Mockito.same(fooDescriptor), 103 Mockito.same(MOCK_RPC_CONTROLLER), 104 Mockito.same(FOO_REQUEST), 105 Mockito.same(FOO_RESPONSE), 106 Mockito.any(RpcCallback.class)); 107 order 108 .verify(mockRpcChannel) 109 .callMethod( 110 Mockito.same(barDescriptor), 111 Mockito.same(MOCK_RPC_CONTROLLER), 112 Mockito.same(BAR_REQUEST), 113 Mockito.same(BAR_RESPONSE), 114 Mockito.any(RpcCallback.class)); 115 } 116 117 /** Tests generated blocking stubs. */ 118 @Test testBlockingStub()119 public void testBlockingStub() throws Exception { 120 BlockingRpcChannel mockBlockingRpcChannel = Mockito.mock(BlockingRpcChannel.class); 121 TestService.BlockingInterface stub = TestService.newBlockingStub(mockBlockingRpcChannel); 122 123 when(mockBlockingRpcChannel.callBlockingMethod( 124 Mockito.same(fooDescriptor), 125 Mockito.same(MOCK_RPC_CONTROLLER), 126 Mockito.same(FOO_REQUEST), 127 Mockito.same(FOO_RESPONSE))) 128 .thenReturn(FOO_RESPONSE); 129 when(mockBlockingRpcChannel.callBlockingMethod( 130 Mockito.same(barDescriptor), 131 Mockito.same(MOCK_RPC_CONTROLLER), 132 Mockito.same(BAR_REQUEST), 133 Mockito.same(BAR_RESPONSE))) 134 .thenReturn(BAR_RESPONSE); 135 136 assertThat(FOO_RESPONSE).isSameInstanceAs(stub.foo(MOCK_RPC_CONTROLLER, FOO_REQUEST)); 137 assertThat(BAR_RESPONSE).isSameInstanceAs(stub.bar(MOCK_RPC_CONTROLLER, BAR_REQUEST)); 138 } 139 140 @Test testNewReflectiveService()141 public void testNewReflectiveService() { 142 ServiceWithNoOuter.Interface impl = Mockito.mock(ServiceWithNoOuter.Interface.class); 143 Service service = ServiceWithNoOuter.newReflectiveService(impl); 144 145 MethodDescriptor fooMethod = ServiceWithNoOuter.getDescriptor().findMethodByName("Foo"); 146 RpcCallback<Message> callback = 147 new RpcCallback<Message>() { 148 @Override 149 public void run(Message parameter) { 150 // No reason this should be run. 151 assertWithMessage("should not run").fail(); 152 } 153 }; 154 RpcCallback<TestAllTypes> specializedCallback = RpcUtil.specializeCallback(callback); 155 156 service.callMethod(fooMethod, MOCK_RPC_CONTROLLER, MESSAGE_WITH_NO_OUTER, callback); 157 verify(impl) 158 .foo( 159 Mockito.same(MOCK_RPC_CONTROLLER), 160 Mockito.same(MESSAGE_WITH_NO_OUTER), 161 Mockito.same(specializedCallback)); 162 } 163 164 @Test testNewReflectiveBlockingService()165 public void testNewReflectiveBlockingService() throws ServiceException { 166 ServiceWithNoOuter.BlockingInterface impl = 167 Mockito.mock(ServiceWithNoOuter.BlockingInterface.class); 168 169 BlockingService service = ServiceWithNoOuter.newReflectiveBlockingService(impl); 170 171 MethodDescriptor fooMethod = ServiceWithNoOuter.getDescriptor().findMethodByName("Foo"); 172 173 TestAllTypes expectedResponse = TestAllTypes.getDefaultInstance(); 174 175 when(impl.foo(Mockito.same(MOCK_RPC_CONTROLLER), Mockito.same(MESSAGE_WITH_NO_OUTER))) 176 .thenReturn(expectedResponse); 177 Message response = 178 service.callBlockingMethod(fooMethod, MOCK_RPC_CONTROLLER, MESSAGE_WITH_NO_OUTER); 179 assertThat(response).isEqualTo(expectedResponse); 180 } 181 182 @Test testNoGenericServices()183 public void testNoGenericServices() throws Exception { 184 // Non-services should be usable. 185 UnittestNoGenericServices.TestMessage message = 186 UnittestNoGenericServices.TestMessage.newBuilder() 187 .setA(123) 188 .setExtension(UnittestNoGenericServices.testExtension, 456) 189 .build(); 190 assertThat(message.getA()).isEqualTo(123); 191 assertThat(UnittestNoGenericServices.TestEnum.FOO.getNumber()).isEqualTo(1); 192 193 // Build a list of the class names nested in UnittestNoGenericServices. 194 String outerName = 195 "protobuf_unittest.no_generic_services_test.UnittestNoGenericServices"; 196 Class<?> outerClass = Class.forName(outerName); 197 198 Set<String> innerClassNames = new HashSet<>(); 199 for (Class<?> innerClass : outerClass.getClasses()) { 200 String fullName = innerClass.getName(); 201 // Figure out the unqualified name of the inner class. 202 // Note: Surprisingly, the full name of an inner class will be separated 203 // from the outer class name by a '$' rather than a '.'. This is not 204 // mentioned in the documentation for java.lang.Class. I don't want to 205 // make assumptions, so I'm just going to accept any character as the 206 // separator. 207 assertThat(fullName).startsWith(outerName); 208 209 if (!Service.class.isAssignableFrom(innerClass) 210 && !Message.class.isAssignableFrom(innerClass) 211 && !ProtocolMessageEnum.class.isAssignableFrom(innerClass)) { 212 // Ignore any classes not generated by the base code generator. 213 continue; 214 } 215 216 innerClassNames.add(fullName.substring(outerName.length() + 1)); 217 } 218 219 // No service class should have been generated. 220 assertThat(innerClassNames).contains("TestMessage"); 221 assertThat(innerClassNames).contains("TestEnum"); 222 assertThat(innerClassNames).doesNotContain("TestService"); 223 224 // But descriptors are there. 225 FileDescriptor file = UnittestNoGenericServices.getDescriptor(); 226 assertThat(file.getServices()).hasSize(1); 227 assertThat(file.getServices().get(0).getName()).isEqualTo("TestService"); 228 assertThat(file.getServices().get(0).getMethods()).hasSize(1); 229 assertThat(file.getServices().get(0).getMethods().get(0).getName()).isEqualTo("Foo"); 230 } 231 } 232