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 5.5KB

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