You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

AbstractClientConnectorTest.java 6.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. /*
  2. * Copyright 2000-2016 Vaadin Ltd.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  5. * use this file except in compliance with the License. You may obtain a copy of
  6. * 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, WITHOUT
  12. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  13. * License for the specific language governing permissions and limitations under
  14. * the License.
  15. */
  16. package com.vaadin.server;
  17. import static org.junit.Assert.assertEquals;
  18. import static org.junit.Assert.assertNotNull;
  19. import static org.junit.Assert.assertNull;
  20. import static org.junit.Assert.assertTrue;
  21. import static org.junit.Assert.fail;
  22. import static org.mockito.Mockito.mock;
  23. import static org.mockito.Mockito.times;
  24. import static org.mockito.Mockito.verify;
  25. import java.io.IOException;
  26. import java.io.InputStream;
  27. import java.lang.ref.WeakReference;
  28. import java.lang.reflect.Field;
  29. import java.net.URL;
  30. import java.util.Map;
  31. import org.apache.commons.io.IOUtils;
  32. import org.junit.Test;
  33. import org.mockito.Mockito;
  34. import com.vaadin.shared.MouseEventDetails;
  35. import com.vaadin.shared.communication.FieldRpc.BlurServerRpc;
  36. import com.vaadin.shared.ui.ClickRpc;
  37. /**
  38. * We test that AbstractClientConnector has a suitable isThis method which is
  39. * needed to correctly perform an equals check between a proxy and it's
  40. * underlying instance.
  41. *
  42. * @author Vaadin Ltd
  43. */
  44. public class AbstractClientConnectorTest {
  45. @Test
  46. public void registerRPCMultiInterfaceTest() {
  47. AbstractClientConnector mock = mock(AbstractClientConnector.class);
  48. MultiServerRpcMock implementation = new MultiServerRpcMock();
  49. Mockito.doCallRealMethod().when(mock).registerRpc(implementation);
  50. try {
  51. mock.registerRpc(implementation);
  52. fail("expected exception");
  53. } catch (Exception expected) {
  54. assertEquals(
  55. "Use registerRpc(T implementation, Class<T> rpcInterfaceType) "
  56. + "if the Rpc implementation implements more than one interface",
  57. expected.getMessage());
  58. }
  59. }
  60. @Test
  61. public void registerRPCInterfaceTest() {
  62. AbstractClientConnector mock = mock(AbstractClientConnector.class);
  63. ServerRpcMock implementation = new ServerRpcMock();
  64. Mockito.doCallRealMethod().when(mock).registerRpc(implementation);
  65. mock.registerRpc(implementation);
  66. verify(mock, times(1)).registerRpc(implementation, ClickRpc.class);
  67. }
  68. @Test
  69. public void registerRPCInterfaceLastTest() {
  70. AbstractClientConnector mock = mock(AbstractClientConnector.class);
  71. ServerRpcLastMock implementation = new ServerRpcLastMock();
  72. Mockito.doCallRealMethod().when(mock).registerRpc(implementation);
  73. mock.registerRpc(implementation);
  74. verify(mock, times(1)).registerRpc(implementation, ClickRpc.class);
  75. }
  76. @Test
  77. public void stateTypeCacheDoesNotLeakMemory()
  78. throws IllegalArgumentException, IllegalAccessException,
  79. NoSuchFieldException, SecurityException, InterruptedException,
  80. ClassNotFoundException {
  81. Field stateTypeCacheField = AbstractClientConnector.class
  82. .getDeclaredField("STATE_TYPE_CACHE");
  83. stateTypeCacheField.setAccessible(true);
  84. Map<Class<?>, ?> stateTypeCache = (Map<Class<?>, ?>) stateTypeCacheField
  85. .get(null);
  86. WeakReference<Class<?>> classRef = loadClass(
  87. "com.vaadin.server.AbstractClientConnector");
  88. stateTypeCache.put(classRef.get(), null);
  89. int size = stateTypeCache.size();
  90. assertNotNull("Class should not yet be garbage collected",
  91. classRef.get());
  92. for (int i = 0; i < 100; ++i) {
  93. System.gc();
  94. if (stateTypeCache.size() < size) {
  95. break;
  96. }
  97. Thread.sleep(100);
  98. }
  99. assertTrue(stateTypeCache.size() < size);
  100. assertNull("Class should be garbage collected", classRef.get());
  101. }
  102. private WeakReference<Class<?>> loadClass(String name)
  103. throws ClassNotFoundException {
  104. ClassLoader loader = new TestClassLoader();
  105. Class<?> loaded = loader.loadClass(name);
  106. return new WeakReference<>(loaded);
  107. }
  108. private class ServerRpcLastMock
  109. implements Comparable<ServerRpcLastMock>, ClickRpc {
  110. private static final long serialVersionUID = -2822356895755286180L;
  111. @Override
  112. public void click(MouseEventDetails mouseDetails) {
  113. }
  114. @Override
  115. public int compareTo(ServerRpcLastMock o) {
  116. return 0;
  117. }
  118. }
  119. private class ServerRpcMock implements ClickRpc {
  120. private static final long serialVersionUID = 2822356895755286180L;
  121. @Override
  122. public void click(MouseEventDetails mouseDetails) {
  123. }
  124. }
  125. private class MultiServerRpcMock implements ClickRpc, BlurServerRpc {
  126. private static final long serialVersionUID = -7611999715560330373L;
  127. @Override
  128. public void blur() {
  129. }
  130. @Override
  131. public void click(MouseEventDetails mouseDetails) {
  132. }
  133. }
  134. private static class TestClassLoader extends ClassLoader {
  135. @Override
  136. public Class<?> loadClass(String name) throws ClassNotFoundException {
  137. if (!name.startsWith("com.vaadin.")) {
  138. return super.loadClass(name);
  139. }
  140. String path = name.replace('.', '/').concat(".class");
  141. URL resource = Thread.currentThread().getContextClassLoader()
  142. .getResource(path);
  143. try (InputStream stream = resource.openStream()) {
  144. byte[] bytes = IOUtils.toByteArray(stream);
  145. return defineClass(name, bytes, 0, bytes.length);
  146. } catch (IOException e) {
  147. throw new ClassNotFoundException();
  148. }
  149. }
  150. }
  151. }