diff options
author | Artur <artur@vaadin.com> | 2017-05-17 13:06:47 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-05-17 13:06:47 +0300 |
commit | 57d0b2fd4c87e3dfc64e33fc8a43e78c8394f31e (patch) | |
tree | bf4841347a7dca717d2024609955b64d904f6be3 /uitest | |
parent | 04700baf219daab66b04a05e07354d1809ebfb0f (diff) | |
download | vaadin-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')
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.")); } } |