From d2c7e33f3ec58852b01bf5c5ec4e8aa636f01279 Mon Sep 17 00:00:00 2001 From: zpencer Date: Thu, 8 Feb 2018 16:31:23 -0800 Subject: [PATCH] core: pull out reusable forwarding test, refactoring forwarding tests (#3480) --- .../io/grpc/ForwardingChannelBuilderTest.java | 22 ++---- .../ForwardingServerCallListenerTest.java | 49 ++++-------- .../test/java/io/grpc/ForwardingTestUtil.java | 72 ++++++++++++++++++ .../internal/ForwardingNameResolverTest.java | 75 +++++++++++++++++++ .../ForwardingReadableBufferTest.java | 35 +++++++-- 5 files changed, 197 insertions(+), 56 deletions(-) create mode 100644 core/src/test/java/io/grpc/ForwardingTestUtil.java create mode 100644 core/src/test/java/io/grpc/internal/ForwardingNameResolverTest.java diff --git a/core/src/test/java/io/grpc/ForwardingChannelBuilderTest.java b/core/src/test/java/io/grpc/ForwardingChannelBuilderTest.java index 57b473b959..e433215b91 100644 --- a/core/src/test/java/io/grpc/ForwardingChannelBuilderTest.java +++ b/core/src/test/java/io/grpc/ForwardingChannelBuilderTest.java @@ -19,11 +19,11 @@ package io.grpc; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; import com.google.common.base.Defaults; import java.lang.reflect.Method; import java.lang.reflect.Modifier; +import java.util.Collections; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -45,20 +45,12 @@ public class ForwardingChannelBuilderTest { } @Test - public void allBuilderMethodsForwarded() throws Exception { - for (Method method : ManagedChannelBuilder.class.getDeclaredMethods()) { - if (Modifier.isStatic(method.getModifiers()) || Modifier.isPrivate(method.getModifiers())) { - continue; - } - Class[] argTypes = method.getParameterTypes(); - Object[] args = new Object[argTypes.length]; - for (int i = 0; i < argTypes.length; i++) { - args[i] = Defaults.defaultValue(argTypes[i]); - } - - method.invoke(testChannelBuilder, args); - method.invoke(verify(mockDelegate), args); - } + public void allMethodsForwarded() throws Exception { + ForwardingTestUtil.testMethodsForwarded( + ManagedChannelBuilder.class, + mockDelegate, + testChannelBuilder, + Collections.emptyList()); } @Test diff --git a/core/src/test/java/io/grpc/ForwardingServerCallListenerTest.java b/core/src/test/java/io/grpc/ForwardingServerCallListenerTest.java index 676dcccc41..bf83d7df38 100644 --- a/core/src/test/java/io/grpc/ForwardingServerCallListenerTest.java +++ b/core/src/test/java/io/grpc/ForwardingServerCallListenerTest.java @@ -19,6 +19,8 @@ package io.grpc; import static org.mockito.Mockito.verify; import io.grpc.ForwardingServerCallListener.SimpleForwardingServerCallListener; +import java.lang.reflect.Method; +import java.util.Collections; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -26,51 +28,32 @@ import org.junit.runners.JUnit4; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +/** + * Unit tests for {@link ForwardingServerCallListener}. + */ @RunWith(JUnit4.class) public class ForwardingServerCallListenerTest { - @Mock private ServerCall.Listener serverCallListener; - private ForwardingServerCallListener forwarder; + @Mock private ServerCall.Listener serverCallListener; + private ForwardingServerCallListener forwarder; @Before public void setUp() { MockitoAnnotations.initMocks(this); - forwarder = new SimpleForwardingServerCallListener(serverCallListener) {}; + forwarder = new SimpleForwardingServerCallListener(serverCallListener) {}; + } + + @Test + public void allMethodsForwarded() throws Exception { + ForwardingTestUtil.testMethodsForwarded( + ServerCall.Listener.class, serverCallListener, forwarder, Collections.emptyList()); } @Test public void onMessage() { - forwarder.onMessage(null); + forwarder.onMessage(12345); - verify(serverCallListener).onMessage(null); - } - - @Test - public void onHalfClose() { - forwarder.onHalfClose(); - - verify(serverCallListener).onHalfClose(); - } - - @Test - public void onCancel() { - forwarder.onCancel(); - - verify(serverCallListener).onCancel(); - } - - @Test - public void onComplete() { - forwarder.onComplete(); - - verify(serverCallListener).onComplete(); - } - - @Test - public void onReady() { - forwarder.onReady(); - - verify(serverCallListener).onReady(); + verify(serverCallListener).onMessage(12345); } } diff --git a/core/src/test/java/io/grpc/ForwardingTestUtil.java b/core/src/test/java/io/grpc/ForwardingTestUtil.java new file mode 100644 index 0000000000..00682da48f --- /dev/null +++ b/core/src/test/java/io/grpc/ForwardingTestUtil.java @@ -0,0 +1,72 @@ +/* + * Copyright 2017, gRPC Authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.grpc; + +import static junit.framework.TestCase.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mockingDetails; +import static org.mockito.Mockito.verify; + +import com.google.common.base.Defaults; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.Collection; + +/** + * A util class to help test forwarding classes. + */ +public final class ForwardingTestUtil { + /** + * Use reflection to perform a basic sanity test. The forwarding class should forward all public + * methods to the delegate, except for those in skippedMethods. + * This does NOT verify that arguments or return values are forwarded properly. It only alerts + * the developer if a forward method is missing. + * + * @param delegateClass The class whose methods should be forwarded. + * @param mockDelegate The mockito mock of the delegate class. + * @param forwarder The forwarder object that forwards to the mockDelegate. + * @param skippedMethods A collection of methods that are skipped by the test. + */ + public static void testMethodsForwarded( + Class delegateClass, + T mockDelegate, + T forwarder, + Collection skippedMethods) throws Exception { + assertTrue(mockingDetails(mockDelegate).isMock()); + assertFalse(mockingDetails(forwarder).isMock()); + + for (Method method : delegateClass.getDeclaredMethods()) { + if (Modifier.isStatic(method.getModifiers()) + || Modifier.isPrivate(method.getModifiers()) + || skippedMethods.contains(method)) { + continue; + } + Class[] argTypes = method.getParameterTypes(); + Object[] args = new Object[argTypes.length]; + for (int i = 0; i < argTypes.length; i++) { + args[i] = Defaults.defaultValue(argTypes[i]); + } + method.invoke(forwarder, args); + try { + method.invoke(verify(mockDelegate), args); + } catch (InvocationTargetException e) { + throw new AssertionError(String.format("Method was not forwarded: %s", method)); + } + } + } +} diff --git a/core/src/test/java/io/grpc/internal/ForwardingNameResolverTest.java b/core/src/test/java/io/grpc/internal/ForwardingNameResolverTest.java new file mode 100644 index 0000000000..ccce42a43e --- /dev/null +++ b/core/src/test/java/io/grpc/internal/ForwardingNameResolverTest.java @@ -0,0 +1,75 @@ +/* + * Copyright 2017, gRPC Authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.grpc.internal; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import io.grpc.Attributes; +import io.grpc.EquivalentAddressGroup; +import io.grpc.ForwardingTestUtil; +import io.grpc.NameResolver; +import io.grpc.Status; +import java.lang.reflect.Method; +import java.util.Collections; +import java.util.List; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * Unit tests for {@link ForwardingNameResolver}. + */ +@RunWith(JUnit4.class) +public class ForwardingNameResolverTest { + private final NameResolver delegate = mock(NameResolver.class); + private final NameResolver forwarder = new ForwardingNameResolver(delegate) { + }; + + @Test + public void allMethodsForwarded() throws Exception { + ForwardingTestUtil.testMethodsForwarded( + NameResolver.class, + delegate, + forwarder, + Collections.emptyList()); + } + + @Test + public void getServiceAuthority() { + String auth = "example.com"; + when(delegate.getServiceAuthority()).thenReturn(auth); + + assertEquals(auth, forwarder.getServiceAuthority()); + } + + @Test + public void start() { + NameResolver.Listener listener = new NameResolver.Listener() { + @Override + public void onAddresses(List servers, Attributes attributes) { } + + @Override + public void onError(Status error) { } + }; + + forwarder.start(listener); + verify(delegate).start(listener); + } +} diff --git a/core/src/test/java/io/grpc/internal/ForwardingReadableBufferTest.java b/core/src/test/java/io/grpc/internal/ForwardingReadableBufferTest.java index 48970a7f8a..0b130ac2f5 100644 --- a/core/src/test/java/io/grpc/internal/ForwardingReadableBufferTest.java +++ b/core/src/test/java/io/grpc/internal/ForwardingReadableBufferTest.java @@ -17,10 +17,16 @@ package io.grpc.internal; import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import io.grpc.ForwardingTestUtil; import java.io.IOException; +import java.io.OutputStream; +import java.lang.reflect.Method; +import java.nio.ByteBuffer; +import java.util.Collections; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -43,6 +49,15 @@ public class ForwardingReadableBufferTest { buffer = new ForwardingReadableBuffer(delegate) {}; } + @Test + public void allMethodsForwarded() throws Exception { + ForwardingTestUtil.testMethodsForwarded( + ReadableBuffer.class, + delegate, + buffer, + Collections.emptyList()); + } + @Test public void readableBytes() { when(delegate.readableBytes()).thenReturn(1); @@ -73,23 +88,26 @@ public class ForwardingReadableBufferTest { @Test public void readBytes() { - buffer.readBytes(null, 1, 2); + byte[] dest = new byte[1]; + buffer.readBytes(dest, 1, 2); - verify(delegate).readBytes(null, 1, 2); + verify(delegate).readBytes(dest, 1, 2); } @Test public void readBytes_overload1() { - buffer.readBytes(null); + ByteBuffer dest = mock(ByteBuffer.class); + buffer.readBytes(dest); - verify(delegate).readBytes(null); + verify(delegate).readBytes(dest); } @Test public void readBytes_overload2() throws IOException { - buffer.readBytes(null, 1); + OutputStream dest = mock(OutputStream.class); + buffer.readBytes(dest, 1); - verify(delegate).readBytes(null, 1); + verify(delegate).readBytes(dest, 1); } @Test @@ -108,9 +126,10 @@ public class ForwardingReadableBufferTest { @Test public void array() { - when(delegate.array()).thenReturn(null); + byte[] array = new byte[1]; + when(delegate.array()).thenReturn(array); - assertEquals(null, buffer.array()); + assertEquals(array, buffer.array()); } @Test