6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package javafx.concurrent;
27
28 import javafx.beans.value.ChangeListener;
29 import javafx.beans.value.ObservableValue;
30 import javafx.concurrent.mocks.MythicalEvent;
31 import javafx.concurrent.mocks.SimpleTask;
32 import javafx.event.Event;
33 import javafx.event.EventHandler;
34 import java.util.concurrent.ConcurrentLinkedQueue;
35 import java.util.concurrent.CountDownLatch;
36 import java.util.concurrent.Executor;
37 import java.util.concurrent.atomic.AtomicBoolean;
38 import java.util.concurrent.atomic.AtomicInteger;
39 import java.util.concurrent.atomic.AtomicReference;
40 import org.junit.After;
41 import org.junit.Test;
42 import static org.junit.Assert.assertEquals;
43 import static org.junit.Assert.assertFalse;
44 import static org.junit.Assert.assertNotNull;
45 import static org.junit.Assert.assertNull;
46 import static org.junit.Assert.assertSame;
47 import static org.junit.Assert.assertTrue;
48
49 /**
50 * Tests various rules regarding the lifecycle of a Service.
51 */
52 public class ServiceLifecycleTest extends ServiceTestBase {
53 /**
54 * The ManualExecutor is used so that there is some time period between
55 * when something is scheduled and when it actually runs, such that the
56 * test code has to manually tell it that it can now run.
57 */
58 protected ManualExecutor executor;
59
60 /**
61 * The task to run, which has methods on it to allow me to manually
62 * put it into a passing, failed, or whatnot state.
63 */
64 protected ManualTask task;
65
66 @Override protected TestServiceFactory setupServiceFactory() {
67 return new TestServiceFactory() {
68 @Override protected AbstractTask createTestTask() {
69 return task = new ManualTask();
70 }
71 };
72 }
73
74 @Override protected Executor createExecutor() {
75 return executor = new ManualExecutor(super.createExecutor());
76 }
77
78 @After public void tearDown() {
79 if (task != null) task.finish.set(true);
80 }
81
82 /**
83 * This class will schedule the task, and then you can execute
84 * it manually by calling executeScheduled. In this way I can
85 * test when a Service is scheduled but not yet started.
86 */
87 protected final class ManualExecutor implements Executor {
88 private Runnable scheduled;
1465 s.getOnScheduled();
1466 s.getOnSucceeded();
1467 s.isRunning();
1468 s.getState();
1469 s.getTitle();
1470 s.getTotalWork();
1471 s.getValue();
1472 s.getWorkDone();
1473 } finally {
1474 if (s != null) s.shutdown();
1475 }
1476 });
1477 random.test();
1478 }
1479
1480 @Test public void canInvokeSettersOnRandomThread() {
1481 RandomThread random = new RandomThread(() -> {
1482 DoNothingService s = null;
1483 try {
1484 s = new DoNothingService();
1485 s.setEventHandler(WorkerStateEvent.ANY, event -> {
1486 });
1487 s.setOnCancelled(event -> {
1488 });
1489 s.setOnFailed(event -> {
1490 });
1491 s.setOnReady(event -> {
1492 });
1493 s.setOnRunning(event -> {
1494 });
1495 s.setOnScheduled(event -> {
1496 });
1497 s.setOnSucceeded(event -> {
1498 });
1499 } finally {
1500 if (s != null) s.shutdown();
1501 }
1502 });
1503 random.test();
1504 }
1505
1513 if (s != null) s.shutdown();
1514 }
1515 });
1516 random.test();
1517 }
1518
1519 @Test (expected = IllegalStateException.class)
1520 public void cannotInvokeRestartOnRandomThreadAfterStart() throws Throwable {
1521 assertThrowsException(s -> s.restart());
1522 }
1523
1524 @Test (expected = IllegalStateException.class)
1525 public void cannotInvokeCancelOnRandomThreadAfterStart() throws Throwable {
1526 assertThrowsException(s -> {
1527 s.cancel();
1528 });
1529 }
1530
1531 @Test (expected = IllegalStateException.class)
1532 public void cannotInvokeSettersOnRandomThreadAfterStart_1() throws Throwable {
1533 assertThrowsException(s -> s.setEventHandler(WorkerStateEvent.ANY, event -> {
1534 }));
1535 }
1536
1537 @Test (expected = IllegalStateException.class)
1538 public void cannotInvokeSettersOnRandomThreadAfterStart_2() throws Throwable {
1539 assertThrowsException(s -> s.setOnCancelled(event -> {
1540 }));
1541 }
1542
1543 @Test (expected = IllegalStateException.class)
1544 public void cannotInvokeSettersOnRandomThreadAfterStart_3() throws Throwable {
1545 assertThrowsException(s -> s.setOnFailed(event -> { }));
1546 }
1547
1548 @Test (expected = IllegalStateException.class)
1549 public void cannotInvokeSettersOnRandomThreadAfterStart_4() throws Throwable {
1550 assertThrowsException(s -> s.setOnReady(event -> { }));
1551 }
1552
1553 @Test (expected = IllegalStateException.class)
1837 }
1838 }
1839
1840 public void test() throws AssertionError {
1841 start();
1842 try {
1843 testCompleted.await();
1844 } catch (InterruptedException e) {
1845 throw new AssertionError("Test did not complete normally");
1846 }
1847 if (error != null) {
1848 throw new AssertionError(error);
1849 }
1850 }
1851 }
1852
1853 /**
1854 * A service which does absolutely nothing and isn't hardwired to believe that
1855 * the test thread is the FX thread (unlike the other services in these tests)
1856 */
1857 private static final class DoNothingService extends Service {
1858 private Thread pretendFXThread;
1859 private ConcurrentLinkedQueue<Runnable> eventQueue = new ConcurrentLinkedQueue<>();
1860 private volatile boolean shutdown = false;
1861
1862 public DoNothingService() {
1863 setExecutor(command -> {
1864 Thread backgroundThread = new Thread(command);
1865 backgroundThread.start();
1866 });
1867 }
1868
1869 void shutdown() {
1870 shutdown = true;
1871 }
1872
1873 @Override protected Task createTask() {
1874 return new Task() {
1875 @Override protected Object call() throws Exception {
1876 return null;
1877 }
1878
1879 @Override boolean isFxApplicationThread() {
1880 return Thread.currentThread() == pretendFXThread;
1881 }
1882
1883 @Override
1884 void runLater(Runnable r) {
1885 DoNothingService.this.runLater(r);
1886 }
1887 };
1888 }
1889
1890 @Override void runLater(Runnable r) {
1891 eventQueue.add(r);
1892 if (pretendFXThread == null) {
1893 pretendFXThread = new Thread() {
1894 @Override public void run() {
1895 while (!shutdown) {
1896 Runnable event = eventQueue.poll();
1897 if (event != null) {
1898 event.run();
1899 }
1900 }
1901 }
1902 };
1903 pretendFXThread.start();
1904 }
1905 }
1906
1907 @Override boolean isFxApplicationThread() {
1908 return Thread.currentThread() == pretendFXThread;
1909 }
1910 }
1911
1912 /***************************************************************************
1913 * *
1914 * A mythical subclass should be able to set an event handler and *
1915 * have events fired on the Service work. *
1916 * *
1917 **************************************************************************/
1918
1919 @Test public void eventFiredOnSubclassWorks() {
1920 final AtomicBoolean result = new AtomicBoolean(false);
1921 TestServiceFactory factory = new TestServiceFactory() {
1922 @Override protected AbstractTask createTestTask() {
1923 return new SimpleTask();
1924 }
1925
1926 @Override protected Service<String> createService() {
1927 MythicalService svc = new MythicalService();
1928 svc.setHandler(mythicalEvent -> result.set(true));
1929 svc.fireEvent(new MythicalEvent());
1930 return svc;
1931 }
1932 };
1933 Service<String> svc = factory.createService();
1934 svc.start();
1935 assertTrue(result.get());
1936 }
1937
1938 private static final class MythicalService extends Service<String> {
1939 public void setHandler(EventHandler<MythicalEvent> h) {
1940 super.setEventHandler(MythicalEvent.ANY, h);
1941 }
1942
1943 @Override protected Task<String> createTask() {
1944 return new SimpleTask();
1945 }
1946
1947 @Override void checkThread() { }
1948
1949 @Override void runLater(Runnable r) {
1950 r.run();
1951 }
1952 }
1953 }
|
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package test.javafx.concurrent;
27
28 import com.sun.org.apache.xerces.internal.util.DOMUtil;
29 import javafx.beans.value.ChangeListener;
30 import javafx.beans.value.ObservableValue;
31 import test.javafx.concurrent.mocks.MythicalEvent;
32 import test.javafx.concurrent.mocks.SimpleTask;
33 import javafx.event.Event;
34 import javafx.event.EventHandler;
35 import java.util.concurrent.ConcurrentLinkedQueue;
36 import java.util.concurrent.CountDownLatch;
37 import java.util.concurrent.Executor;
38 import java.util.concurrent.atomic.AtomicBoolean;
39 import java.util.concurrent.atomic.AtomicInteger;
40 import java.util.concurrent.atomic.AtomicReference;
41 import javafx.concurrent.Service;
42 import javafx.concurrent.ServiceShim;
43 import javafx.concurrent.Task;
44 import javafx.concurrent.TaskShim;
45 import javafx.concurrent.Worker;
46 import javafx.concurrent.WorkerStateEvent;
47 import javafx.event.EventType;
48 import org.junit.After;
49 import org.junit.Test;
50 import static org.junit.Assert.assertEquals;
51 import static org.junit.Assert.assertFalse;
52 import static org.junit.Assert.assertNotNull;
53 import static org.junit.Assert.assertNull;
54 import static org.junit.Assert.assertSame;
55 import static org.junit.Assert.assertTrue;
56
57 /**
58 * Tests various rules regarding the lifecycle of a Service.
59 */
60 public class ServiceLifecycleTest extends ServiceTestBase {
61 /**
62 * The ManualExecutor is used so that there is some time period between
63 * when something is scheduled and when it actually runs, such that the
64 * test code has to manually tell it that it can now run.
65 */
66 protected ManualExecutor executor;
67
68 /**
69 * The task to run, which has methods on it to allow me to manually
70 * put it into a passing, failed, or whatnot state.
71 */
72 protected ManualTask task;
73
74 @Override protected TestServiceFactory setupServiceFactory() {
75 return new TestServiceFactory() {
76 @Override public AbstractTask createTestTask() {
77 return task = new ManualTask();
78 }
79 };
80 }
81
82 @Override protected Executor createExecutor() {
83 return executor = new ManualExecutor(super.createExecutor());
84 }
85
86 @After public void tearDown() {
87 if (task != null) task.finish.set(true);
88 }
89
90 /**
91 * This class will schedule the task, and then you can execute
92 * it manually by calling executeScheduled. In this way I can
93 * test when a Service is scheduled but not yet started.
94 */
95 protected final class ManualExecutor implements Executor {
96 private Runnable scheduled;
1473 s.getOnScheduled();
1474 s.getOnSucceeded();
1475 s.isRunning();
1476 s.getState();
1477 s.getTitle();
1478 s.getTotalWork();
1479 s.getValue();
1480 s.getWorkDone();
1481 } finally {
1482 if (s != null) s.shutdown();
1483 }
1484 });
1485 random.test();
1486 }
1487
1488 @Test public void canInvokeSettersOnRandomThread() {
1489 RandomThread random = new RandomThread(() -> {
1490 DoNothingService s = null;
1491 try {
1492 s = new DoNothingService();
1493 ServiceShim.setEventHandler(s, WorkerStateEvent.ANY, event -> {
1494 });
1495 s.setOnCancelled(event -> {
1496 });
1497 s.setOnFailed(event -> {
1498 });
1499 s.setOnReady(event -> {
1500 });
1501 s.setOnRunning(event -> {
1502 });
1503 s.setOnScheduled(event -> {
1504 });
1505 s.setOnSucceeded(event -> {
1506 });
1507 } finally {
1508 if (s != null) s.shutdown();
1509 }
1510 });
1511 random.test();
1512 }
1513
1521 if (s != null) s.shutdown();
1522 }
1523 });
1524 random.test();
1525 }
1526
1527 @Test (expected = IllegalStateException.class)
1528 public void cannotInvokeRestartOnRandomThreadAfterStart() throws Throwable {
1529 assertThrowsException(s -> s.restart());
1530 }
1531
1532 @Test (expected = IllegalStateException.class)
1533 public void cannotInvokeCancelOnRandomThreadAfterStart() throws Throwable {
1534 assertThrowsException(s -> {
1535 s.cancel();
1536 });
1537 }
1538
1539 @Test (expected = IllegalStateException.class)
1540 public void cannotInvokeSettersOnRandomThreadAfterStart_1() throws Throwable {
1541 assertThrowsException(s ->
1542 ServiceShim.setEventHandler(s, WorkerStateEvent.ANY, event -> {
1543 }));
1544 }
1545
1546 @Test (expected = IllegalStateException.class)
1547 public void cannotInvokeSettersOnRandomThreadAfterStart_2() throws Throwable {
1548 assertThrowsException(s -> s.setOnCancelled(event -> {
1549 }));
1550 }
1551
1552 @Test (expected = IllegalStateException.class)
1553 public void cannotInvokeSettersOnRandomThreadAfterStart_3() throws Throwable {
1554 assertThrowsException(s -> s.setOnFailed(event -> { }));
1555 }
1556
1557 @Test (expected = IllegalStateException.class)
1558 public void cannotInvokeSettersOnRandomThreadAfterStart_4() throws Throwable {
1559 assertThrowsException(s -> s.setOnReady(event -> { }));
1560 }
1561
1562 @Test (expected = IllegalStateException.class)
1846 }
1847 }
1848
1849 public void test() throws AssertionError {
1850 start();
1851 try {
1852 testCompleted.await();
1853 } catch (InterruptedException e) {
1854 throw new AssertionError("Test did not complete normally");
1855 }
1856 if (error != null) {
1857 throw new AssertionError(error);
1858 }
1859 }
1860 }
1861
1862 /**
1863 * A service which does absolutely nothing and isn't hardwired to believe that
1864 * the test thread is the FX thread (unlike the other services in these tests)
1865 */
1866 private static final class DoNothingService extends ServiceShim {
1867 private Thread pretendFXThread;
1868 private ConcurrentLinkedQueue<Runnable> eventQueue = new ConcurrentLinkedQueue<>();
1869 private volatile boolean shutdown = false;
1870
1871 public DoNothingService() {
1872 setExecutor(command -> {
1873 Thread backgroundThread = new Thread(command);
1874 backgroundThread.start();
1875 });
1876 }
1877
1878 void shutdown() {
1879 shutdown = true;
1880 }
1881
1882 @Override protected Task createTask() {
1883 return new TaskShim() {
1884 @Override protected Object call() throws Exception {
1885 return null;
1886 }
1887
1888 @Override public boolean isFxApplicationThread() {
1889 return Thread.currentThread() == pretendFXThread;
1890 }
1891
1892 @Override
1893 public void runLater(Runnable r) {
1894 DoNothingService.this.runLater(r);
1895 }
1896 };
1897 }
1898
1899 @Override public void runLater(Runnable r) {
1900 eventQueue.add(r);
1901 if (pretendFXThread == null) {
1902 pretendFXThread = new Thread() {
1903 @Override public void run() {
1904 while (!shutdown) {
1905 Runnable event = eventQueue.poll();
1906 if (event != null) {
1907 event.run();
1908 }
1909 }
1910 }
1911 };
1912 pretendFXThread.start();
1913 }
1914 }
1915
1916 @Override public boolean isFxApplicationThread() {
1917 return Thread.currentThread() == pretendFXThread;
1918 }
1919 }
1920
1921 /***************************************************************************
1922 * *
1923 * A mythical subclass should be able to set an event handler and *
1924 * have events fired on the Service work. *
1925 * *
1926 **************************************************************************/
1927
1928 @Test public void eventFiredOnSubclassWorks() {
1929 final AtomicBoolean result = new AtomicBoolean(false);
1930 TestServiceFactory factory = new TestServiceFactory() {
1931 @Override public AbstractTask createTestTask() {
1932 return new SimpleTask();
1933 }
1934
1935 @Override public Service<String> createService() {
1936 MythicalService svc = new MythicalService();
1937 svc.setHandler(mythicalEvent -> result.set(true));
1938 ServiceShim.fireEvent(svc, new MythicalEvent());
1939 return svc;
1940 }
1941 };
1942 Service<String> svc = factory.createService();
1943 svc.start();
1944 assertTrue(result.get());
1945 }
1946
1947 private static final class MythicalService extends ServiceShim<String> {
1948 public void setHandler(EventHandler<MythicalEvent> h) {
1949 ServiceShim.setEventHandler(this, MythicalEvent.ANY, h);
1950 }
1951
1952 @Override protected Task<String> createTask() {
1953 return new SimpleTask();
1954 }
1955
1956 @Override public void checkThread() { }
1957
1958 @Override public void runLater(Runnable r) {
1959 r.run();
1960 }
1961 }
1962 }
|