modules/graphics/src/test/java/test/javafx/concurrent/ServiceLifecycleTest.java

Print this page
rev 9250 : 8134762: Refactor Javafx graphics module tests for clear separation of tests
Reviewed-by:


   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 }