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 javafx.concurrent;
  27 
  28 import java.util.Arrays;
  29 import java.util.Collection;
  30 import java.util.concurrent.atomic.AtomicBoolean;
  31 import javafx.beans.value.ChangeListener;
  32 import javafx.beans.value.ObservableValue;
  33 import javafx.concurrent.mocks.EpicFailTask;
  34 import org.junit.Test;
  35 import org.junit.runner.RunWith;
  36 import org.junit.runners.Parameterized;
  37 
  38 import static org.junit.Assert.*;
  39 
  40 /**
  41  * This tests that state is correct when a Task throws an exception partway through.
  42  * In this particular case, the progress is updated to 50% before the exception
  43  * occurs.
  44  */
  45 @RunWith(Parameterized.class)
  46 public class ServiceExceptionTest extends ServiceTestBase {
  47     @Parameterized.Parameters public static Collection implementations() {
  48         return Arrays.asList(new Object[][]{
  49                 { new Exception("Exception") },
  50                 { new IllegalArgumentException("IAE") },
  51                 { new NullPointerException("NPE") },
  52                 { new RuntimeException("RuntimeException") }
  53         });
  54     }
  55 
  56     private Exception exception;
  57 
  58     public ServiceExceptionTest(Exception th) {
  59         this.exception = th;
  60     }
  61 
  62     @Override protected TestServiceFactory setupServiceFactory() {
  63         return new TestServiceFactory() {
  64             @Override protected AbstractTask createTestTask() {
  65                 return new EpicFailTask(ServiceExceptionTest.this.exception);
  66             }
  67         };
  68     }
  69 
  70     /************************************************************************
  71      * Run the concurrent and check that the exception property is set, and that
  72      * the value property is null. The progress fields may be in some
  73      * arbitrary state.
  74      ***********************************************************************/
  75 
  76     /**
  77      * Whenever the exception occurs we should have the exception property set
  78      */
  79     @Test public void exceptionShouldBeSet() {
  80         service.start();
  81         handleEvents();
  82         assertSame(exception, service.getException());
  83         assertSame(exception, service.exceptionProperty().get());
  84     }
  85 
  86     @Test public void exceptionPropertyNotification() {
  87         final AtomicBoolean passed = new AtomicBoolean(false);
  88         service.exceptionProperty().addListener((o, oldValue, newValue) -> passed.set(newValue == exception));
  89         service.start();
  90         handleEvents();
  91         assertTrue(passed.get());
  92     }
  93 
  94     /**
  95      * The value should always be null if an exception occurs before the end of the Task.
  96      */
  97     @Test public void valueShouldBeNull() {
  98         service.start();
  99         handleEvents();
 100         assertNull(service.getValue());
 101         assertNull(service.valueProperty().get());
 102     }
 103 
 104     @Test public void runningShouldBeFalse() {
 105         service.start();
 106         handleEvents();
 107         assertFalse(service.isRunning());
 108         assertFalse(service.runningProperty().get());
 109     }
 110 
 111     @Test public void runningPropertyNotification() {
 112         final AtomicBoolean passed = new AtomicBoolean(false);
 113         service.runningProperty().addListener((o, oldValue, newValue) -> passed.set(!newValue));
 114         service.start();
 115         handleEvents();
 116         assertTrue(passed.get());
 117     }
 118 
 119     @Test public void workDoneShouldBeTen() {
 120         service.start();
 121         handleEvents();
 122         assertEquals(10, service.getWorkDone(), 0);
 123         assertEquals(10, service.workDoneProperty().get(), 0);
 124     }
 125 
 126     @Test public void workDonePropertyNotification() {
 127         final AtomicBoolean passed = new AtomicBoolean(false);
 128         service.workDoneProperty().addListener((observable, oldValue, newValue) -> passed.set(newValue.doubleValue() == 10));
 129         service.start();
 130         handleEvents();
 131         assertTrue(passed.get());
 132     }
 133 
 134     @Test public void totalWorkShouldBeTwenty() {
 135         service.start();
 136         handleEvents();
 137         assertEquals(20, service.getTotalWork(), 0);
 138         assertEquals(20, service.totalWorkProperty().get(), 0);
 139     }
 140 
 141     @Test public void totalWorkPropertyNotification() {
 142         final AtomicBoolean passed = new AtomicBoolean(false);
 143         service.totalWorkProperty().addListener((observable, oldValue, newValue) -> passed.set(newValue.doubleValue() == 20));
 144         service.start();
 145         handleEvents();
 146         assertTrue(passed.get());
 147     }
 148 
 149     @Test public void afterRunningProgressShouldBe_FiftyPercent() {
 150         service.start();
 151         handleEvents();
 152         assertEquals(.5, service.getProgress(), 0);
 153         assertEquals(.5, service.progressProperty().get(), 0);
 154     }
 155 
 156     @Test public void progressPropertyNotification() {
 157         final AtomicBoolean passed = new AtomicBoolean(false);
 158         service.progressProperty().addListener((observable, oldValue, newValue) -> passed.set(newValue.doubleValue() == .5));
 159         service.start();
 160         handleEvents();
 161         assertTrue(passed.get());
 162     }
 163 
 164     @Test public void stateShouldBe_FAILED() {
 165         service.start();
 166         handleEvents();
 167         assertSame(Worker.State.FAILED, service.getState());
 168         assertSame(Worker.State.FAILED, service.stateProperty().get());
 169     }
 170 
 171     @Test public void statePropertyNotification() {
 172         final AtomicBoolean passed = new AtomicBoolean(false);
 173         service.stateProperty().addListener((observable, oldValue, newValue) -> passed.set(newValue == Worker.State.FAILED));
 174         service.start();
 175         handleEvents();
 176         assertTrue(passed.get());
 177     }
 178 
 179     @Test public void messageShouldBeLastSetValue() {
 180         service.start();
 181         handleEvents();
 182         assertEquals("About to fail", service.getMessage());
 183         assertEquals("About to fail", service.messageProperty().get());
 184     }
 185 
 186     @Test public void messagePropertyNotification() {
 187         final AtomicBoolean passed = new AtomicBoolean(false);
 188         service.messageProperty().addListener((observable, oldValue, newValue) -> passed.set("About to fail".equals(service.getMessage())));
 189         service.start();
 190         handleEvents();
 191         assertTrue(passed.get());
 192     }
 193 
 194     @Test public void titleShouldBeLastSetValue() {
 195         service.start();
 196         handleEvents();
 197         assertEquals("Epic Fail", service.getTitle());
 198         assertEquals("Epic Fail", service.titleProperty().get());
 199     }
 200 
 201     @Test public void titlePropertyNotification() {
 202         final AtomicBoolean passed = new AtomicBoolean(false);
 203         service.titleProperty().addListener((observable, oldValue, newValue) -> passed.set("Epic Fail".equals(service.getTitle())));
 204         service.start();
 205         handleEvents();
 206         assertTrue(passed.get());
 207     }
 208 }