1 /*
   2  * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   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 javafx.beans.property.ObjectProperty;
  29 import javafx.beans.property.SimpleObjectProperty;
  30 import test.javafx.concurrent.mocks.SimpleTask;
  31 import java.util.concurrent.CountDownLatch;
  32 import java.util.concurrent.Executor;
  33 import java.util.concurrent.atomic.AtomicBoolean;
  34 import javafx.concurrent.Service;
  35 import javafx.concurrent.Service;
  36 import javafx.concurrent.ServiceShim;
  37 import javafx.concurrent.Task;
  38 import javafx.concurrent.Task;
  39 import javafx.concurrent.TaskShim;
  40 import javafx.concurrent.Worker;
  41 import javafx.concurrent.Worker;
  42 import org.junit.Before;
  43 import org.junit.Test;
  44 import static org.junit.Assert.assertEquals;
  45 import static org.junit.Assert.assertFalse;
  46 import static org.junit.Assert.assertNull;
  47 import static org.junit.Assert.assertSame;
  48 import static org.junit.Assert.assertTrue;
  49 
  50 /**
  51  */
  52 public class ServiceTest {
  53     private Service<String> service;
  54 
  55     @Before public void setup() {
  56         // I don't use the AbstractService here because I don't want to
  57         // take advantage of the built in executor / threading stuff
  58         service = new ServiceShim<String>() {
  59             @Override public Task<String> createTask() {
  60                 return new SimpleTask();
  61             }
  62 
  63             @Override public void checkThread() { }
  64             @Override public void runLater(Runnable r) {
  65                 r.run();
  66             }
  67         };
  68     }
  69 
  70     /******************************************************************
  71      * Executor Property                                              *
  72      *****************************************************************/
  73 
  74     /**
  75      * Tests that the executor property is null by default
  76      */
  77     @Test public void executorDefaultsToNull() {
  78         assertNull(service.getExecutor());
  79         assertNull(service.executorProperty().get());
  80     }
  81 
  82     /**
  83      * Tests that you can set the executor. This will set the executor
  84      * to some non-default setting and check that the same instance is
  85      * then set on the service
  86      */
  87     @Test public void executorCanBeSet() {
  88         final Executor e = command -> { };
  89         service.setExecutor(e);
  90         assertSame(e, service.getExecutor());
  91         assertSame(e, service.executorProperty().get());
  92     }
  93 
  94     /**
  95      * Tests that you can bind the executor property of a Service
  96      */
  97     @Test public void executorCanBeBound() {
  98         final Executor e = command -> { };
  99         ObjectProperty<Executor> other = new SimpleObjectProperty<Executor>(e);
 100         service.executorProperty().bind(other);
 101         assertSame(e, service.getExecutor());
 102         assertSame(e, service.executorProperty().get());
 103         other.set(null);
 104         assertNull(service.getExecutor());
 105         assertNull(service.executorProperty().get());
 106     }
 107 
 108     /**
 109      * Tests that if you specify a custom executor, then it is used when
 110      * you attempt to run a service
 111      */
 112     @Test public void executorIsUsed() {
 113         final AtomicBoolean results = new AtomicBoolean(false);
 114         final Executor e = command -> results.set(true);
 115         service.setExecutor(e);
 116         service.start();
 117         assertTrue(results.get());
 118     }
 119 
 120     /******************************************************************
 121      * Test initial values for properties                             *
 122      *****************************************************************/
 123 
 124     @Test public void stateDefaultsTo_READY() {
 125         assertSame(Worker.State.READY, service.getState());
 126         assertSame(Worker.State.READY, service.stateProperty().get());
 127     }
 128 
 129     @Test public void valueDefaultsToNull() {
 130         assertNull(service.getValue());
 131         assertNull(service.valueProperty().get());
 132     }
 133 
 134     @Test public void exceptionDefaultsToNull() {
 135         assertNull(service.getException());
 136         assertNull(service.exceptionProperty().get());
 137     }
 138 
 139     @Test public void workDoneDefaultsTo_NegativeOne() {
 140         assertEquals(-1, service.getWorkDone(), 0);
 141         assertEquals(-1, service.workDoneProperty().get(), 0);
 142     }
 143 
 144     @Test public void totalWorkDefaultsTo_NegativeOne() {
 145         assertEquals(-1, service.getTotalWork(), 0);
 146         assertEquals(-1, service.totalWorkProperty().get(), 0);
 147     }
 148 
 149     @Test public void progressDefaultsTo_NegativeOne() {
 150         assertEquals(-1, service.getProgress(), 0);
 151         assertEquals(-1, service.progressProperty().get(), 0);
 152     }
 153 
 154     @Test public void runningDefaultsToFalse() {
 155         assertFalse(service.isRunning());
 156         assertFalse(service.runningProperty().get());
 157     }
 158 
 159     @Test public void messageDefaultsToEmptyString() {
 160         assertEquals("", service.getMessage());
 161         assertEquals("", service.messageProperty().get());
 162     }
 163 
 164     @Test public void titleDefaultsToEmptyString() {
 165         assertEquals("", service.getTitle());
 166         assertEquals("", service.titleProperty().get());
 167     }
 168 
 169     /******************************************************************
 170      * Test that 32 simultaneous services will run concurrently       *
 171      *****************************************************************/
 172 
 173     // This test should be reliable. Each of the concurrent tasks takes 1 second to complete
 174     // and several micro / milliseconds to get setup and execute. So 2 seconds should be more
 175     // than enough time.
 176     @Test(timeout = 2000) public void testManyServicesRunConcurrently() throws Exception {
 177         final CountDownLatch latch = new CountDownLatch(32);
 178         for (int i=0; i<32; i++) {
 179             Service<Void> s = new ServiceShim<Void>() {
 180                 @Override public void checkThread() { }
 181                 @Override public void runLater(Runnable r) { r.run(); }
 182 
 183                 @Override protected Task<Void> createTask() {
 184                     return new TaskShim<Void>() {
 185                         @Override protected Void call() throws Exception {
 186                             Thread.sleep(1000);
 187                             latch.countDown();
 188                             return null;
 189                         }
 190 
 191                         @Override public void runLater(Runnable r) {
 192                             r.run();
 193                         }
 194 
 195                         @Override public boolean isFxApplicationThread() {
 196                             return true;
 197                         }
 198                     };
 199 
 200                 }
 201             };
 202             s.start();
 203         }
 204         latch.await();
 205     }
 206 }