diff options
Diffstat (limited to 'uitest/src/com/vaadin')
4 files changed, 364 insertions, 2 deletions
diff --git a/uitest/src/com/vaadin/tests/applicationcontext/CloseUI.java b/uitest/src/com/vaadin/tests/applicationcontext/CloseUI.java index bec8c0a10f..c88f482a7b 100644 --- a/uitest/src/com/vaadin/tests/applicationcontext/CloseUI.java +++ b/uitest/src/com/vaadin/tests/applicationcontext/CloseUI.java @@ -119,7 +119,7 @@ public class CloseUI extends AbstractTestUI { @Override public void run() { - ui.access(new Runnable() { + ui.accessSynchronously(new Runnable() { @Override public void run() { diff --git a/uitest/src/com/vaadin/tests/applicationcontext/UIRunSafelyThread.java b/uitest/src/com/vaadin/tests/applicationcontext/UIRunSafelyThread.java index ddc0f28664..c9af2c000d 100644 --- a/uitest/src/com/vaadin/tests/applicationcontext/UIRunSafelyThread.java +++ b/uitest/src/com/vaadin/tests/applicationcontext/UIRunSafelyThread.java @@ -11,7 +11,7 @@ public abstract class UIRunSafelyThread extends Thread { @Override public void run() { - ui.access(new Runnable() { + ui.accessSynchronously(new Runnable() { @Override public void run() { diff --git a/uitest/src/com/vaadin/tests/components/ui/UiAccess.html b/uitest/src/com/vaadin/tests/components/ui/UiAccess.html new file mode 100644 index 0000000000..664b15c16f --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/ui/UiAccess.html @@ -0,0 +1,127 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> +<head profile="http://selenium-ide.openqa.org/profiles/test-case"> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> +<link rel="selenium.base" href="" /> +<title>New Test</title> +</head> +<body> +<table cellpadding="1" cellspacing="1" border="1"> +<thead> +<tr><td rowspan="1" colspan="3">New Test</td></tr> +</thead><tbody> +<tr> + <td>open</td> + <td>/run/com.vaadin.tests.components.ui.UiAccess?restartApplication</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>vaadin=runcomvaadintestscomponentsuiUiAccess::/VVerticalLayout[0]/Slot[2]/VVerticalLayout[0]/Slot[0]/VButton[0]/domChild[0]/domChild[0]</td> + <td></td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestscomponentsuiUiAccess::PID_SLog_row_2</td> + <td>exact:0. Access from UI thread future is done? false</td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestscomponentsuiUiAccess::PID_SLog_row_1</td> + <td>1. Access from UI thread is run</td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestscomponentsuiUiAccess::PID_SLog_row_0</td> + <td>exact:2. beforeClientResponse future is done? true</td> +</tr> +<tr> + <td>click</td> + <td>vaadin=runcomvaadintestscomponentsuiUiAccess::/VVerticalLayout[0]/Slot[2]/VVerticalLayout[0]/Slot[1]/VButton[0]/domChild[0]/domChild[0]</td> + <td></td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestscomponentsuiUiAccess::PID_SLog_row_1</td> + <td>0. Initial background message</td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestscomponentsuiUiAccess::PID_SLog_row_0</td> + <td>exact:1. Thread has current response? false</td> +</tr> +<tr> + <td>waitForText</td> + <td>vaadin=runcomvaadintestscomponentsuiUiAccess::PID_SLog_row_4</td> + <td>0. Initial background message</td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestscomponentsuiUiAccess::PID_SLog_row_2</td> + <td>exact:2. Thread got lock, inital future done? true</td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestscomponentsuiUiAccess::PID_SLog_row_1</td> + <td>exact:3. Access has current response? true</td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestscomponentsuiUiAccess::PID_SLog_row_0</td> + <td>exact:4. Thread is still alive? false</td> +</tr> +<tr> + <td>click</td> + <td>vaadin=runcomvaadintestscomponentsuiUiAccess::/VVerticalLayout[0]/Slot[2]/VVerticalLayout[0]/Slot[2]/VButton[0]/domChild[0]/domChild[0]</td> + <td></td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestscomponentsuiUiAccess::PID_SLog_row_2</td> + <td>0. Throwing exception in access</td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestscomponentsuiUiAccess::PID_SLog_row_1</td> + <td>exact:1. firstFuture is done? true</td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestscomponentsuiUiAccess::PID_SLog_row_0</td> + <td>2. Got exception from firstFuture: java.lang.RuntimeException: Catch me if you can</td> +</tr> +<tr> + <td>click</td> + <td>vaadin=runcomvaadintestscomponentsuiUiAccess::/VVerticalLayout[0]/Slot[2]/VVerticalLayout[0]/Slot[3]/VButton[0]/domChild[0]/domChild[0]</td> + <td></td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestscomponentsuiUiAccess::PID_SLog_row_0</td> + <td>0. future was cancled, should not start</td> +</tr> +<tr> + <td>click</td> + <td>vaadin=runcomvaadintestscomponentsuiUiAccess::/VVerticalLayout[0]/Slot[2]/VVerticalLayout[0]/Slot[4]/VButton[0]/domChild[0]/domChild[0]</td> + <td></td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestscomponentsuiUiAccess::PID_SLog_row_2</td> + <td>0. Waiting for thread to start</td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestscomponentsuiUiAccess::PID_SLog_row_1</td> + <td>1. Thread started, waiting for interruption</td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestscomponentsuiUiAccess::PID_SLog_row_0</td> + <td>2. I was interrupted</td> +</tr> + +</tbody></table> +</body> +</html> diff --git a/uitest/src/com/vaadin/tests/components/ui/UiAccess.java b/uitest/src/com/vaadin/tests/components/ui/UiAccess.java new file mode 100644 index 0000000000..c68da6ee54 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/ui/UiAccess.java @@ -0,0 +1,235 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package com.vaadin.tests.components.ui; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.locks.ReentrantLock; + +import com.vaadin.server.VaadinRequest; +import com.vaadin.server.VaadinService; +import com.vaadin.tests.components.AbstractTestUIWithLog; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; + +public class UiAccess extends AbstractTestUIWithLog { + + private Future<Void> checkFromBeforeClientResponse; + + @Override + protected void setup(VaadinRequest request) { + addComponent(new Button("Access from UI thread", + new Button.ClickListener() { + + @Override + public void buttonClick(ClickEvent event) { + log.clear(); + // Ensure beforeClientResponse is invoked + markAsDirty(); + checkFromBeforeClientResponse = access(new Runnable() { + @Override + public void run() { + log("Access from UI thread is run"); + } + }); + log("Access from UI thread future is done? " + + checkFromBeforeClientResponse.isDone()); + } + })); + addComponent(new Button("Access from background thread", + new Button.ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + log.clear(); + final CountDownLatch latch = new CountDownLatch(1); + + new Thread() { + @Override + public void run() { + final boolean threadHasCurrentResponse = VaadinService + .getCurrentResponse() != null; + // session is locked by request thread at this + // point + final Future<Void> initialFuture = access(new Runnable() { + @Override + public void run() { + log("Initial background message"); + log("Thread has current response? " + + threadHasCurrentResponse); + } + }); + + // Let request thread continue + latch.countDown(); + + // Wait until thread can be locked + while (!getSession().getLockInstance() + .tryLock()) { + try { + Thread.sleep(100); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + try { + log("Thread got lock, inital future done? " + + initialFuture.isDone()); + setPollInterval(-1); + } finally { + getSession().unlock(); + } + final Thread thisThread = this; + access(new Runnable() { + @Override + public void run() { + log("Access has current response? " + + (VaadinService + .getCurrentResponse() != null)); + log("Thread is still alive? " + + thisThread.isAlive()); + } + }); + } + }.start(); + + // Wait for thread to do initialize before continuing + try { + latch.await(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + + setPollInterval(3000); + } + })); + addComponent(new Button("Access throwing exception", + new Button.ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + log.clear(); + final Future<Void> firstFuture = access(new Runnable() { + @Override + public void run() { + log("Throwing exception in access"); + throw new RuntimeException( + "Catch me if you can"); + } + }); + access(new Runnable() { + @Override + public void run() { + log("firstFuture is done? " + + firstFuture.isDone()); + try { + firstFuture.get(); + log("Should not get here"); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } catch (ExecutionException e) { + log("Got exception from firstFuture: " + + e.getMessage()); + } + } + }); + } + })); + addComponent(new Button("Cancel future before started", + new Button.ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + log.clear(); + Future<Void> future = access(new Runnable() { + @Override + public void run() { + log("Should not get here"); + } + }); + future.cancel(false); + log("future was cancled, should not start"); + } + })); + addComponent(new Button("Cancel running future", + new Button.ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + log.clear(); + final ReentrantLock interruptLock = new ReentrantLock(); + + final Future<Void> future = access(new Runnable() { + @Override + public void run() { + log("Waiting for thread to start"); + while (!interruptLock.isLocked()) { + try { + Thread.sleep(100); + } catch (InterruptedException e) { + log("Premature interruption"); + throw new RuntimeException(e); + } + } + + log("Thread started, waiting for interruption"); + try { + interruptLock.lockInterruptibly(); + } catch (InterruptedException e) { + log("I was interrupted"); + } + } + }); + + new Thread() { + @Override + public void run() { + interruptLock.lock(); + // Wait until UI thread has started waiting for + // the lock + while (!interruptLock.hasQueuedThreads()) { + try { + Thread.sleep(100); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + + future.cancel(true); + } + }.start(); + } + })); + } + + @Override + public void beforeClientResponse(boolean initial) { + if (checkFromBeforeClientResponse != null) { + log("beforeClientResponse future is done? " + + checkFromBeforeClientResponse.isDone()); + checkFromBeforeClientResponse = null; + } + } + + @Override + protected String getTestDescription() { + return "Test for various ways of using UI.access"; + } + + @Override + protected Integer getTicketNumber() { + return Integer.valueOf(11897); + } + +} |