aboutsummaryrefslogtreecommitdiffstats
path: root/uitest/src
diff options
context:
space:
mode:
authorArtur <artur@vaadin.com>2017-05-16 15:14:11 +0300
committerPekka Hyvönen <pekka@vaadin.com>2017-05-16 15:14:11 +0300
commitaa3ad5db0f3c5e1c95dd0b84c229851460da6449 (patch)
tree0fd7bf987c7503b745921b2866316a9ed170514f /uitest/src
parent76a0e04cb056fe2c6e2ad62f6d0972b2347a0fcf (diff)
downloadvaadin-framework-aa3ad5db0f3c5e1c95dd0b84c229851460da6449.tar.gz
vaadin-framework-aa3ad5db0f3c5e1c95dd0b84c229851460da6449.zip
Clean connector tracker after each access block to stop memory leaks (#9305)
Immediately clean connectors which the client side does not know about Fixes #9303
Diffstat (limited to 'uitest/src')
-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.java78
-rw-r--r--uitest/src/test/java/com/vaadin/tests/application/MissingHierarchyDetectionTest.java10
3 files changed, 130 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 8f35d69112..54c19c3353 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.AbstractReindeerTestUI;
+import com.vaadin.server.VaadinService;
+import com.vaadin.tests.components.AbstractReindeerTestUIWithLog;
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 AbstractReindeerTestUI {
+public class MissingHierarchyDetection extends AbstractReindeerTestUIWithLog {
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<>());
public class BrokenCssLayout extends CssLayout
implements SelectiveRenderer {
@@ -49,6 +59,29 @@ public class MissingHierarchyDetection extends AbstractReindeerTestUI {
@Override
protected void setup(VaadinRequest request) {
+ // Catch log messages so we can see if there is an error
+ 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 AbstractReindeerTestUI {
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..fdcfe24776
--- /dev/null
+++ b/uitest/src/main/java/com/vaadin/tests/components/ui/ConnectorTrackerMemoryLeakUI.java
@@ -0,0 +1,78 @@
+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.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<>(200);
+ private VerticalLayout layout = new VerticalLayout();
+
+ @Override
+ protected void init(VaadinRequest vaadinRequest) {
+
+ Button button = new Button(BUTTON_CAPTION);
+ button.addClickListener(e -> {
+ 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();
+ items.forEach(i -> panel.addComponent(new Button(i, e -> {
+ 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 2a97dbaaf6..80eb0735da 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."));
}
}