summaryrefslogtreecommitdiffstats
path: root/uitest
diff options
context:
space:
mode:
authorArtur <artur@vaadin.com>2017-05-17 13:06:47 +0300
committerGitHub <noreply@github.com>2017-05-17 13:06:47 +0300
commit57d0b2fd4c87e3dfc64e33fc8a43e78c8394f31e (patch)
treebf4841347a7dca717d2024609955b64d904f6be3 /uitest
parent04700baf219daab66b04a05e07354d1809ebfb0f (diff)
downloadvaadin-framework-57d0b2fd4c87e3dfc64e33fc8a43e78c8394f31e.tar.gz
vaadin-framework-57d0b2fd4c87e3dfc64e33fc8a43e78c8394f31e.zip
Clean connector tracker after each access block to stop memory leaks (#9331)
Immediately clean connectors which the client side does not know about Fixes #9303
Diffstat (limited to 'uitest')
-rw-r--r--uitest/src/main/java/com/vaadin/tests/application/MissingHierarchyDetection.java47
-rw-r--r--uitest/src/main/java/com/vaadin/tests/components/ui/ConnectorTrackerMemoryLeakUI.java87
-rw-r--r--uitest/src/test/java/com/vaadin/tests/application/MissingHierarchyDetectionTest.java10
3 files changed, 139 insertions, 5 deletions
diff --git a/uitest/src/main/java/com/vaadin/tests/application/MissingHierarchyDetection.java b/uitest/src/main/java/com/vaadin/tests/application/MissingHierarchyDetection.java
index 9e463569c0..ff60b66f20 100644
--- a/uitest/src/main/java/com/vaadin/tests/application/MissingHierarchyDetection.java
+++ b/uitest/src/main/java/com/vaadin/tests/application/MissingHierarchyDetection.java
@@ -15,8 +15,16 @@
*/
package com.vaadin.tests.application;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.logging.Handler;
+import java.util.logging.LogRecord;
+import java.util.logging.Logger;
+
import com.vaadin.server.VaadinRequest;
-import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.tests.components.AbstractTestUIWithLog;
+import com.vaadin.server.VaadinService;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Component;
@@ -24,13 +32,15 @@ import com.vaadin.ui.CssLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.SelectiveRenderer;
-public class MissingHierarchyDetection extends AbstractTestUI {
+public class MissingHierarchyDetection extends AbstractTestUIWithLog {
private boolean isChildRendered = true;
private BrokenCssLayout brokenLayout = new BrokenCssLayout();
private CssLayout normalLayout = new CssLayout(
new Label("Normal layout child"));
+ private List<LogRecord> pendingErrors = Collections
+ .synchronizedList(new ArrayList<LogRecord>());
public class BrokenCssLayout extends CssLayout
implements SelectiveRenderer {
@@ -49,6 +59,29 @@ public class MissingHierarchyDetection extends AbstractTestUI {
@Override
protected void setup(VaadinRequest request) {
+ // Catch log messages so we can see if there is an error
+ final Logger vaadinServiceLogger = Logger
+ .getLogger(VaadinService.class.getName());
+ vaadinServiceLogger.addHandler(new Handler() {
+
+ @Override
+ public void publish(LogRecord record) {
+ if (record.getThrown() instanceof AssertionError) {
+ pendingErrors.add(record);
+ vaadinServiceLogger.removeHandler(this);
+ }
+ }
+
+ @Override
+ public void flush() {
+
+ }
+
+ @Override
+ public void close() throws SecurityException {
+
+ }
+ });
addComponent(brokenLayout);
addComponent(normalLayout);
addComponent(new Button("Toggle properly", new Button.ClickListener() {
@@ -64,6 +97,16 @@ public class MissingHierarchyDetection extends AbstractTestUI {
toggle(false);
}
}));
+ addComponent(new Button("Check for errors", new Button.ClickListener() {
+ @Override
+ public void buttonClick(ClickEvent event) {
+ if (!pendingErrors.isEmpty()) {
+ log(pendingErrors.remove(0).getThrown().getMessage());
+ } else {
+ log("No errors");
+ }
+ }
+ }));
}
private void toggle(boolean properly) {
diff --git a/uitest/src/main/java/com/vaadin/tests/components/ui/ConnectorTrackerMemoryLeakUI.java b/uitest/src/main/java/com/vaadin/tests/components/ui/ConnectorTrackerMemoryLeakUI.java
new file mode 100644
index 0000000000..a8f9d08d8d
--- /dev/null
+++ b/uitest/src/main/java/com/vaadin/tests/components/ui/ConnectorTrackerMemoryLeakUI.java
@@ -0,0 +1,87 @@
+package com.vaadin.tests.components.ui;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.CssLayout;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.UI;
+import com.vaadin.ui.VerticalLayout;
+import com.vaadin.ui.Window;
+
+public class ConnectorTrackerMemoryLeakUI extends UI {
+
+ public static final String BUTTON_CAPTION = "Kill!";
+ public static final String LABEL_STOPPED = "Still alive!";
+ private CssLayout panel = new CssLayout();
+ private List<String> items = new ArrayList<String>(200);
+ private VerticalLayout layout = new VerticalLayout();
+
+ @Override
+ protected void init(VaadinRequest vaadinRequest) {
+
+ Button button = new Button(BUTTON_CAPTION);
+ button.addClickListener(new Button.ClickListener() {
+ @Override
+ public void buttonClick(ClickEvent event) {
+ gc();
+ long memory = Runtime.getRuntime().totalMemory();
+ System.out.println("Before: " + memory);
+ // To simulate 200 concurrent session we do this 200 times
+ for (int i = 0; i < 200; i++) {
+
+ // Clear items
+ items.clear();
+ for (int j = 1; j <= 200; j++) {
+
+ // Add one item and update the panel with those
+ items.add("Item #" + j);
+ updatePanel(panel, items);
+ }
+ }
+
+ // We made it this far. Good for us.
+ Label labelStop = new Label(LABEL_STOPPED);
+ layout.addComponent(labelStop);
+ gc();
+ long delta = Runtime.getRuntime().totalMemory() - memory;
+ memory = memory + delta;
+ System.out.println(" After: " + memory + " (+" + delta + ")");
+ }
+ });
+
+ layout.addComponents(button, panel);
+ setContent(layout);
+ }
+
+ private void gc() {
+ // Sometimes the VM needs a couple of "suggestions" to actually
+ // perform gc. There is no automated test for this UI so tweak if
+ // needed.
+ for (int i = 0; i < 3; i++) {
+ Runtime.getRuntime().gc();
+ }
+
+ try {
+ Thread.sleep(500);
+ } catch (InterruptedException e1) {
+ }
+ }
+
+ private static void updatePanel(CssLayout panel, List<String> items) {
+ panel.removeAllComponents();
+ for (String i : items) {
+ panel.addComponent(new Button(i, new Button.ClickListener() {
+ @Override
+ public void buttonClick(ClickEvent event) {
+ Window w = new Window();
+ UI.getCurrent().addWindow(w);
+ }
+ }));
+ }
+ }
+
+}
diff --git a/uitest/src/test/java/com/vaadin/tests/application/MissingHierarchyDetectionTest.java b/uitest/src/test/java/com/vaadin/tests/application/MissingHierarchyDetectionTest.java
index ad44fe6f89..c047c9a12b 100644
--- a/uitest/src/test/java/com/vaadin/tests/application/MissingHierarchyDetectionTest.java
+++ b/uitest/src/test/java/com/vaadin/tests/application/MissingHierarchyDetectionTest.java
@@ -41,10 +41,14 @@ public class MissingHierarchyDetectionTest extends SingleBrowserTest {
assertNoSystemNotifications();
Assert.assertTrue(isElementPresent(LabelElement.class));
- ButtonElement toggleInproperly = $(ButtonElement.class)
+ ButtonElement toggleImproperly = $(ButtonElement.class)
.caption("Toggle improperly").first();
- toggleInproperly.click();
+ toggleImproperly.click();
- assertSystemNotification();
+ $(ButtonElement.class).caption("Check for errors").first().click();
+ Assert.assertTrue(
+ "No error was logged for the missing hierarchy change event",
+ getLogRow(0).contains(
+ "is no longer visible to the client, but no corresponding hierarchy change was sent."));
}
}