Java tutorial
/* * Copyright 2000-2016 Vaadin Ltd. * * 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 com.vaadin.server; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import java.io.IOException; import java.io.InputStream; import java.lang.ref.WeakReference; import java.lang.reflect.Field; import java.net.URL; import java.util.Map; import org.apache.commons.io.IOUtils; import org.junit.Test; import org.mockito.Mockito; import com.vaadin.shared.MouseEventDetails; import com.vaadin.shared.communication.FieldRpc.BlurServerRpc; import com.vaadin.shared.ui.ClickRpc; /** * We test that AbstractClientConnector has a suitable isThis method which is * needed to correctly perform an equals check between a proxy and it's * underlying instance. * * @author Vaadin Ltd */ public class AbstractClientConnectorTest { @Test public void registerRPCMultiInterfaceTest() { AbstractClientConnector mock = mock(AbstractClientConnector.class); MultiServerRpcMock implementation = new MultiServerRpcMock(); Mockito.doCallRealMethod().when(mock).registerRpc(implementation); try { mock.registerRpc(implementation); fail("expected exception"); } catch (Exception expected) { assertEquals( "Use registerRpc(T implementation, Class<T> rpcInterfaceType) " + "if the Rpc implementation implements more than one interface", expected.getMessage()); } } @Test public void registerRPCInterfaceTest() { AbstractClientConnector mock = mock(AbstractClientConnector.class); ServerRpcMock implementation = new ServerRpcMock(); Mockito.doCallRealMethod().when(mock).registerRpc(implementation); mock.registerRpc(implementation); verify(mock, times(1)).registerRpc(implementation, ClickRpc.class); } @Test public void registerRPCInterfaceLastTest() { AbstractClientConnector mock = mock(AbstractClientConnector.class); ServerRpcLastMock implementation = new ServerRpcLastMock(); Mockito.doCallRealMethod().when(mock).registerRpc(implementation); mock.registerRpc(implementation); verify(mock, times(1)).registerRpc(implementation, ClickRpc.class); } @Test public void stateTypeCacheDoesNotLeakMemory() throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException, InterruptedException, ClassNotFoundException { Field stateTypeCacheField = AbstractClientConnector.class.getDeclaredField("STATE_TYPE_CACHE"); stateTypeCacheField.setAccessible(true); Map<Class<?>, ?> stateTypeCache = (Map<Class<?>, ?>) stateTypeCacheField.get(null); WeakReference<Class<?>> classRef = loadClass("com.vaadin.server.AbstractClientConnector"); stateTypeCache.put(classRef.get(), null); int size = stateTypeCache.size(); assertNotNull("Class should not yet be garbage collected", classRef.get()); for (int i = 0; i < 100; ++i) { System.gc(); if (stateTypeCache.size() < size) { break; } Thread.sleep(100); } assertTrue(stateTypeCache.size() < size); assertNull("Class should be garbage collected", classRef.get()); } private WeakReference<Class<?>> loadClass(String name) throws ClassNotFoundException { ClassLoader loader = new TestClassLoader(); Class<?> loaded = loader.loadClass(name); return new WeakReference<>(loaded); } private class ServerRpcLastMock implements Comparable<ServerRpcLastMock>, ClickRpc { private static final long serialVersionUID = -2822356895755286180L; @Override public void click(MouseEventDetails mouseDetails) { } @Override public int compareTo(ServerRpcLastMock o) { return 0; } } private class ServerRpcMock implements ClickRpc { private static final long serialVersionUID = 2822356895755286180L; @Override public void click(MouseEventDetails mouseDetails) { } } private class MultiServerRpcMock implements ClickRpc, BlurServerRpc { private static final long serialVersionUID = -7611999715560330373L; @Override public void blur() { } @Override public void click(MouseEventDetails mouseDetails) { } } private static class TestClassLoader extends ClassLoader { @Override public Class<?> loadClass(String name) throws ClassNotFoundException { if (!name.startsWith("com.vaadin.")) { return super.loadClass(name); } String path = name.replace('.', '/').concat(".class"); URL resource = Thread.currentThread().getContextClassLoader().getResource(path); try (InputStream stream = resource.openStream()) { byte[] bytes = IOUtils.toByteArray(stream); return defineClass(name, bytes, 0, bytes.length); } catch (IOException e) { throw new ClassNotFoundException(); } } } }