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.scene.control;
  27 
  28 import javafx.css.CssMetaData;
  29 import java.io.File;
  30 import java.lang.reflect.InvocationTargetException;
  31 import java.lang.reflect.Method;
  32 import java.lang.reflect.Modifier;
  33 import java.net.URL;
  34 import java.util.Arrays;
  35 import java.util.List;
  36 import javafx.beans.property.DoubleProperty;
  37 import javafx.beans.property.ObjectProperty;
  38 import javafx.beans.property.SimpleDoubleProperty;
  39 import javafx.beans.property.SimpleObjectProperty;
  40 import javafx.beans.value.ChangeListener;
  41 import javafx.beans.value.ObservableValue;
  42 import javafx.beans.value.WritableValue;
  43 import javafx.scene.Group;
  44 import javafx.scene.Node;
  45 import javafx.scene.shape.Rectangle;
  46 import com.sun.javafx.scene.control.Logging;
  47 import javafx.css.Styleable;
  48 import javafx.css.StyleableProperty;
  49 import org.junit.Before;
  50 import org.junit.Ignore;
  51 import org.junit.Test;
  52 import sun.util.logging.PlatformLogger;
  53 import sun.util.logging.PlatformLogger.Level;
  54 
  55 import static org.junit.Assert.*;
  56 
  57 /**
  58  * Things every Control needs to test:
  59  *  - Properties
  60  *     - Set the value, see that it changes
  61  *     - Set an illegal value, see that it is rejected
  62  *     - Bind to some other value, see that when the binding fires, the property is updated (vague)
  63  *  - CSS
  64  *     - Change state, watch the pseudo class state change
  65  *     - Default style-class has what you expect
  66  *     - (2nd order) impl_cssSettable returns true for thing in their default state
  67  *     - (2nd order) impl_cssSettable returns false for things manually specified
  68  *     - (3rd order) impl_cssKeys includes all the public properties
  69  *  - Methods
  70  *     - For all methods, calling the method mutates the state appropriately
  71  */
  72 public class ControlTest {
  73     private static final double MIN_WIDTH = 35;
  74     private static final double MIN_HEIGHT = 45;
  75     private static final double MAX_WIDTH = 2000;
  76     private static final double MAX_HEIGHT = 2011;
  77     private static final double PREF_WIDTH = 100;
  78     private static final double PREF_HEIGHT = 130;
  79     private static final double BASELINE_OFFSET = 10;
  80 
  81     private ControlStub c;
  82     private SkinStub<ControlStub> s;
  83     private ResizableRectangle skinNode;
  84 
  85     private Level originalLogLevel = null;
  86 
  87     @Before public void setUp() {
  88         c = new ControlStub();
  89         s = new SkinStub<ControlStub>(c);
  90         skinNode = new ResizableRectangle();
  91         skinNode.resize(20, 20);
  92         skinNode.minWidth = MIN_WIDTH;
  93         skinNode.minHeight = MIN_HEIGHT;
  94         skinNode.maxWidth = MAX_WIDTH;
  95         skinNode.maxHeight = MAX_HEIGHT;
  96         skinNode.prefWidth = PREF_WIDTH;
  97         skinNode.prefHeight = PREF_HEIGHT;
  98         skinNode.baselineOffset = BASELINE_OFFSET;
  99         s.setNode(skinNode);
 100     }
 101 
 102     private void disableLogging() {
 103         final PlatformLogger logger = Logging.getControlsLogger();
 104         originalLogLevel = logger.level();
 105         logger.setLevel(Level.OFF);
 106     }
 107 
 108     private void enableLogging() {
 109         final PlatformLogger logger = Logging.getControlsLogger();
 110 //        logger.setLevel(originalLogLevel);
 111         logger.setLevel(Level.FINE);
 112     }
 113 
 114     @Test public void focusTraversableIsTrueByDefault() {
 115         assertTrue(c.isFocusTraversable());
 116     }
 117 
 118     @Test public void resizableIsTrueByDefault() {
 119         assertTrue(c.isResizable());
 120     }
 121 
 122     @Test public void modifyingTheControlWidthUpdatesTheLayoutBounds() {
 123         c.resize(173, c.getHeight());
 124         assertEquals(173, c.getLayoutBounds().getWidth(), 0);
 125     }
 126 
 127     @Test public void modifyingTheControlWidthLeadsToRequestLayout() {
 128         // Make sure the Control has it's needsLayout flag cleared
 129         c.layout();
 130         assertTrue(!c.isNeedsLayout());
 131         // Run the test
 132         c.resize(173, c.getHeight());
 133         assertTrue(c.isNeedsLayout());
 134     }
 135 
 136     @Test public void modifyingTheControlHeightUpdatesTheLayoutBounds() {
 137         c.resize(c.getWidth(), 173);
 138         assertEquals(173, c.getLayoutBounds().getHeight(), 0);
 139     }
 140 
 141     @Test public void modifyingTheControlHeightLeadsToRequestLayout() {
 142         // Make sure the Control has it's needsLayout flag cleared
 143         c.layout();
 144         assertTrue(!c.isNeedsLayout());
 145         // Run the test
 146         c.resize(c.getWidth(), 173);
 147         assertTrue(c.isNeedsLayout());
 148     }
 149 
 150     @Test public void multipleModificationsToWidthAndHeightAreReflectedInLayoutBounds() {
 151         c.resize(723, 234);
 152         c.resize(992, 238);
 153         assertEquals(992, c.getLayoutBounds().getWidth(), 0);
 154         assertEquals(238, c.getLayoutBounds().getHeight(), 0);
 155     }
 156 
 157     @Test public void containsDelegatesToTheSkinWhenSet() {
 158         c.setSkin(s);
 159         skinNode.resize(100, 100);
 160         assertTrue(c.getSkin().getNode() != null);
 161         assertTrue(c.contains(50, 50));
 162     }
 163 
 164     @Test public void intersectsReturnsTrueWhenThereIsNoSkin() {
 165         c.relocate(0, 0);
 166         c.resize(100, 100);
 167         assertTrue(c.intersects(50, 50, 100, 100));
 168     }
 169 
 170     @Test public void intersectsDelegatesToTheSkinWhenSet() {
 171         c.setSkin(s);
 172         skinNode.resize(100, 100);
 173         assertTrue(c.intersects(50, 50, 100, 100));
 174     }
 175 
 176     @Test public void skinIsResizedToExactSizeOfControlOnLayout() {
 177         c.setSkin(s);
 178         c.resize(67, 998);
 179         c.layout();
 180         assertEquals(0, s.getNode().getLayoutBounds().getMinX(), 0);
 181         assertEquals(0, s.getNode().getLayoutBounds().getMinY(), 0);
 182         assertEquals(67, s.getNode().getLayoutBounds().getWidth(), 0);
 183         assertEquals(998, s.getNode().getLayoutBounds().getHeight(), 0);
 184     }
 185 
 186     @Test public void skinWithNodeLargerThanControlDoesntAffectLayoutBounds() {
 187         s.setNode(new Rectangle(0, 0, 1000, 1001));
 188         c.setSkin(s);
 189         c.resize(50, 40);
 190         c.layout();
 191         // Sanity check: the layout bounds of the skin node itself is large
 192         assertEquals(1000, c.getSkin().getNode().getLayoutBounds().getWidth(), 0);
 193         assertEquals(1001, c.getSkin().getNode().getLayoutBounds().getHeight(), 0);
 194         // Test: the layout bounds of the control is still 50, 40
 195         assertEquals(50, c.getLayoutBounds().getWidth(), 0);
 196         assertEquals(40, c.getLayoutBounds().getHeight(), 0);
 197     }
 198 
 199     /****************************************************************************
 200      * minWidth Tests                                                           *
 201      ***************************************************************************/
 202 
 203     @Test public void callsToSetMinWidthResultInRequestLayoutBeingCalledOnParentNotOnControl() {
 204         // Setup and sanity check
 205         Group parent = new Group();
 206         parent.getChildren().add(c);
 207         parent.layout();
 208         assertTrue(!parent.isNeedsLayout());
 209         assertTrue(!c.isNeedsLayout());
 210         // Test
 211         c.setMinWidth(123.45);
 212         assertTrue(parent.isNeedsLayout());
 213         assertTrue(!c.isNeedsLayout());
 214     }
 215 
 216     @Test public void getMinWidthReturnsTheMinWidthOfTheSkinNode() {
 217         c.setSkin(s);
 218         assertEquals(MIN_WIDTH, c.minWidth(-1), 0.0);
 219     }
 220 
 221     @Test public void getMinWidthReturnsTheCustomSetMinWidthWhenSpecified() {
 222         c.setSkin(s);
 223         c.setMinWidth(123.45);
 224         assertEquals(123.45, c.minWidth(-1), 0.0);
 225     }
 226 
 227     @Test public void getMinWidthReturnsTheCustomSetMinWidthWhenSpecifiedEvenWhenThereIsNoSkin() {
 228         c.setMinWidth(123.45);
 229         assertEquals(123.45, c.minWidth(-1), 0.0);
 230     }
 231 
 232     @Test public void minWidthWhenNoSkinIsSetIsZeroByDefault() {
 233         assertEquals(0, c.minWidth(-1), 0.0);
 234     }
 235 
 236     @Test public void resettingMinWidthTo_USE_PREF_SIZE_ReturnsThePrefWidthOfTheSkinNodeWhenThereIsASkin() {
 237         c.setSkin(s);
 238         c.setMinWidth(123.45);
 239         c.setMinWidth(Control.USE_PREF_SIZE);
 240         assertEquals(PREF_WIDTH, c.minWidth(-1), 0.0);
 241     }
 242 
 243     @Test public void resettingMinWidthTo_USE_PREF_SIZE_ReturnsZeroWhenThereIsNoSkinAndPrefWidthIsNotSet() {
 244         c.setMinWidth(123.45);
 245         c.setMinWidth(Control.USE_PREF_SIZE);
 246         assertEquals(0, c.minWidth(-1), 0.0);
 247     }
 248 
 249     @Test public void resettingMinWidthTo_USE_PREF_SIZE_ReturnsPrefWidthWhenThereIsNoSkinAndPrefWidthIsSet() {
 250         c.setMinWidth(123.45);
 251         c.setPrefWidth(98.6);
 252         c.setMinWidth(Control.USE_PREF_SIZE);
 253         assertEquals(98.6, c.minWidth(-1), 0.0);
 254     }
 255 
 256     @Test public void resettingMinWidthTo_USE_COMPUTED_SIZE_ReturnsTheMinWidthOfTheSkinNodeWhenThereIsASkin() {
 257         c.setSkin(s);
 258         c.setMinWidth(123.45);
 259         c.setMinWidth(Control.USE_COMPUTED_SIZE);
 260         assertEquals(MIN_WIDTH, c.minWidth(-1), 0.0);
 261     }
 262 
 263     @Test public void resettingMinWidthTo_USE_COMPUTED_SIZE_ReturnsZeroWhenThereIsNoSkinAndPrefWidthIsNotSet() {
 264         c.setMinWidth(123.45);
 265         c.setMinWidth(Control.USE_COMPUTED_SIZE);
 266         assertEquals(0, c.minWidth(-1), 0.0);
 267     }
 268 
 269     @Test public void minWidthIs_USE_COMPUTED_SIZE_ByDefault() {
 270         assertEquals(Control.USE_COMPUTED_SIZE, c.getMinWidth(), 0);
 271         assertEquals(Control.USE_COMPUTED_SIZE, c.minWidthProperty().get(), 0);
 272     }
 273 
 274     @Test public void minWidthCanBeSet() {
 275         c.setMinWidth(234);
 276         assertEquals(234, c.getMinWidth(), 0);
 277         assertEquals(234, c.minWidthProperty().get(), 0);
 278     }
 279 
 280     @Test public void minWidthCanBeBound() {
 281         DoubleProperty other = new SimpleDoubleProperty(939);
 282         c.minWidthProperty().bind(other);
 283         assertEquals(939, c.getMinWidth(), 0);
 284         other.set(332);
 285         assertEquals(332, c.getMinWidth(), 0);
 286     }
 287 
 288     @Test public void minWidthPropertyHasBeanReference() {
 289         assertSame(c, c.minWidthProperty().getBean());
 290     }
 291 
 292     @Test public void minWidthPropertyHasName() {
 293         assertEquals("minWidth", c.minWidthProperty().getName());
 294     }
 295 
 296     /****************************************************************************
 297      * minHeight Tests                                                          *
 298      ***************************************************************************/
 299 
 300     @Test public void callsToSetMinHeightResultInRequestLayoutBeingCalledOnParentNotOnControl() {
 301         // Setup and sanity check
 302         Group parent = new Group();
 303         parent.getChildren().add(c);
 304         parent.layout();
 305         assertTrue(!parent.isNeedsLayout());
 306         assertTrue(!c.isNeedsLayout());
 307         // Test
 308         c.setMinHeight(98.76);
 309         assertTrue(parent.isNeedsLayout());
 310         assertTrue(!c.isNeedsLayout());
 311     }
 312 
 313     @Test public void getMinHeightReturnsTheMinHeightOfTheSkinNode() {
 314         c.setSkin(s);
 315         assertEquals(MIN_HEIGHT, c.minHeight(-1), 0.0);
 316     }
 317 
 318     @Test public void getMinHeightReturnsTheCustomSetMinHeightWhenSpecified() {
 319         c.setSkin(s);
 320         c.setMinHeight(98.76);
 321         assertEquals(98.76, c.minHeight(-1), 0.0);
 322     }
 323 
 324     @Test public void getMinHeightReturnsTheCustomSetMinHeightWhenSpecifiedEvenWhenThereIsNoSkin() {
 325         c.setMinHeight(98.76);
 326         assertEquals(98.76, c.minHeight(-1), 0.0);
 327     }
 328 
 329     @Test public void minHeightWhenNoSkinIsSetIsZeroByDefault() {
 330         assertEquals(0, c.minHeight(-1), 0.0);
 331     }
 332 
 333     @Test public void resettingMinHeightTo_USE_PREF_SIZE_ReturnsThePrefHeightOfTheSkinNodeWhenThereIsASkin() {
 334         c.setSkin(s);
 335         c.setMinHeight(98.76);
 336         c.setMinHeight(Control.USE_PREF_SIZE);
 337         assertEquals(PREF_HEIGHT, c.minHeight(-1), 0.0);
 338     }
 339 
 340     @Test public void resettingMinHeightTo_USE_PREF_SIZE_ReturnsZeroWhenThereIsNoSkinAndPrefHeightIsNotSet() {
 341         c.setMinHeight(98.76);
 342         c.setMinHeight(Control.USE_PREF_SIZE);
 343         assertEquals(0, c.minHeight(-1), 0.0);
 344     }
 345 
 346     @Test public void resettingMinHeightTo_USE_PREF_SIZE_ReturnsPrefHeightWhenThereIsNoSkinAndPrefHeightIsSet() {
 347         c.setMinHeight(98.76);
 348         c.setPrefHeight(105.2);
 349         c.setMinHeight(Control.USE_PREF_SIZE);
 350         assertEquals(105.2, c.minHeight(-1), 0.0);
 351     }
 352 
 353     @Test public void resettingMinHeightTo_USE_COMPUTED_SIZE_ReturnsTheMinHeightOfTheSkinNodeWhenThereIsASkin() {
 354         c.setSkin(s);
 355         c.setMinHeight(98.76);
 356         c.setMinHeight(Control.USE_COMPUTED_SIZE);
 357         assertEquals(MIN_HEIGHT, c.minHeight(-1), 0.0);
 358     }
 359 
 360     @Test public void resettingMinHeightTo_USE_COMPUTED_SIZE_ReturnsZeroWhenThereIsNoSkinAndPrefHeightIsNotSet() {
 361         c.setMinHeight(98.76);
 362         c.setMinHeight(Control.USE_COMPUTED_SIZE);
 363         assertEquals(0, c.minHeight(-1), 0.0);
 364     }
 365 
 366     @Test public void minHeightIs_USE_COMPUTED_SIZE_ByDefault() {
 367         assertEquals(Control.USE_COMPUTED_SIZE, c.getMinHeight(), 0);
 368         assertEquals(Control.USE_COMPUTED_SIZE, c.minHeightProperty().get(), 0);
 369     }
 370 
 371     @Test public void minHeightCanBeSet() {
 372         c.setMinHeight(98.76);
 373         assertEquals(98.76, c.getMinHeight(), 0);
 374         assertEquals(98.76, c.minHeightProperty().get(), 0);
 375     }
 376 
 377     @Test public void minHeightCanBeBound() {
 378         DoubleProperty other = new SimpleDoubleProperty(939);
 379         c.minHeightProperty().bind(other);
 380         assertEquals(939, c.getMinHeight(), 0);
 381         other.set(332);
 382         assertEquals(332, c.getMinHeight(), 0);
 383     }
 384 
 385     @Test public void minHeightPropertyHasBeanReference() {
 386         assertSame(c, c.minHeightProperty().getBean());
 387     }
 388 
 389     @Test public void minHeightPropertyHasName() {
 390         assertEquals("minHeight", c.minHeightProperty().getName());
 391     }
 392 
 393     /****************************************************************************
 394      * maxWidth Tests                                                           *
 395      ***************************************************************************/
 396 
 397     @Test public void callsToSetMaxWidthResultInRequestLayoutBeingCalledOnParentNotOnControl() {
 398         // Setup and sanity check
 399         Group parent = new Group();
 400         parent.getChildren().add(c);
 401         parent.layout();
 402         assertTrue(!parent.isNeedsLayout());
 403         assertTrue(!c.isNeedsLayout());
 404         // Test
 405         c.setMaxWidth(500);
 406         assertTrue(parent.isNeedsLayout());
 407         assertTrue(!c.isNeedsLayout());
 408     }
 409 
 410     @Test public void getMaxWidthReturnsTheMaxWidthOfTheSkinNode() {
 411         c.setSkin(s);
 412         assertEquals(MAX_WIDTH, c.maxWidth(-1), 0.0);
 413     }
 414 
 415     @Test public void getMaxWidthReturnsTheCustomSetMaxWidthWhenSpecified() {
 416         c.setSkin(s);
 417         c.setMaxWidth(500);
 418         assertEquals(500, c.maxWidth(-1), 0.0);
 419     }
 420 
 421     @Test public void getMaxWidthReturnsTheCustomSetMaxWidthWhenSpecifiedEvenWhenThereIsNoSkin() {
 422         c.setMaxWidth(500);
 423         assertEquals(500, c.maxWidth(-1), 0.0);
 424     }
 425 
 426     @Test public void maxWidthWhenNoSkinIsSetIsZeroByDefault() {
 427         assertEquals(0, c.maxWidth(-1), 0.0);
 428     }
 429 
 430     @Test public void resettingMaxWidthTo_USE_PREF_SIZE_ReturnsThePrefWidthOfTheSkinNodeWhenThereIsASkin() {
 431         c.setSkin(s);
 432         c.setMaxWidth(500);
 433         c.setMaxWidth(Control.USE_PREF_SIZE);
 434         assertEquals(PREF_WIDTH, c.maxWidth(-1), 0.0);
 435     }
 436 
 437     @Test public void resettingMaxWidthTo_USE_PREF_SIZE_ReturnsZeroWhenThereIsNoSkinAndPrefWidthIsNotSet() {
 438         c.setMaxWidth(500);
 439         c.setMaxWidth(Control.USE_PREF_SIZE);
 440         assertEquals(0, c.maxWidth(-1), 0.0);
 441     }
 442 
 443     @Test public void resettingMaxWidthTo_USE_PREF_SIZE_ReturnsPrefWidthWhenThereIsNoSkinAndPrefWidthIsSet() {
 444         c.setMaxWidth(500);
 445         c.setPrefWidth(98.6);
 446         c.setMaxWidth(Control.USE_PREF_SIZE);
 447         assertEquals(98.6, c.maxWidth(-1), 0.0);
 448     }
 449 
 450     @Test public void resettingMaxWidthTo_USE_COMPUTED_SIZE_ReturnsTheMaxWidthOfTheSkinNodeWhenThereIsASkin() {
 451         c.setSkin(s);
 452         c.setMaxWidth(500);
 453         c.setMaxWidth(Control.USE_COMPUTED_SIZE);
 454         assertEquals(MAX_WIDTH, c.maxWidth(-1), 0.0);
 455     }
 456 
 457     @Test public void resettingMaxWidthTo_USE_COMPUTED_SIZE_ReturnsZeroWhenThereIsNoSkinAndPrefWidthIsNotSet() {
 458         c.setMaxWidth(500);
 459         c.setMaxWidth(Control.USE_COMPUTED_SIZE);
 460         assertEquals(0, c.maxWidth(-1), 0.0);
 461     }
 462 
 463     @Test public void maxWidthIs_USE_COMPUTED_SIZE_ByDefault() {
 464         assertEquals(Control.USE_COMPUTED_SIZE, c.getMaxWidth(), 0);
 465         assertEquals(Control.USE_COMPUTED_SIZE, c.maxWidthProperty().get(), 0);
 466     }
 467 
 468     @Test public void maxWidthCanBeSet() {
 469         c.setMaxWidth(500);
 470         assertEquals(500, c.getMaxWidth(), 0);
 471         assertEquals(500, c.maxWidthProperty().get(), 0);
 472     }
 473 
 474     @Test public void maxWidthCanBeBound() {
 475         DoubleProperty other = new SimpleDoubleProperty(939);
 476         c.maxWidthProperty().bind(other);
 477         assertEquals(939, c.getMaxWidth(), 0);
 478         other.set(332);
 479         assertEquals(332, c.getMaxWidth(), 0);
 480     }
 481 
 482     @Test public void maxWidthPropertyHasBeanReference() {
 483         assertSame(c, c.maxWidthProperty().getBean());
 484     }
 485 
 486     @Test public void maxWidthPropertyHasName() {
 487         assertEquals("maxWidth", c.maxWidthProperty().getName());
 488     }
 489 
 490     /****************************************************************************
 491      * maxHeight Tests                                                          *
 492      ***************************************************************************/
 493 
 494     @Test public void callsToSetMaxHeightResultInRequestLayoutBeingCalledOnParentNotOnControl() {
 495         // Setup and sanity check
 496         Group parent = new Group();
 497         parent.getChildren().add(c);
 498         parent.layout();
 499         assertTrue(!parent.isNeedsLayout());
 500         assertTrue(!c.isNeedsLayout());
 501         // Test
 502         c.setMaxHeight(450);
 503         assertTrue(parent.isNeedsLayout());
 504         assertTrue(!c.isNeedsLayout());
 505     }
 506 
 507     @Test public void getMaxHeightReturnsTheMaxHeightOfTheSkinNode() {
 508         c.setSkin(s);
 509         assertEquals(MAX_HEIGHT, c.maxHeight(-1), 0.0);
 510     }
 511 
 512     @Test public void getMaxHeightReturnsTheCustomSetMaxHeightWhenSpecified() {
 513         c.setSkin(s);
 514         c.setMaxHeight(450);
 515         assertEquals(450, c.maxHeight(-1), 0.0);
 516     }
 517 
 518     @Test public void getMaxHeightReturnsTheCustomSetMaxHeightWhenSpecifiedEvenWhenThereIsNoSkin() {
 519         c.setMaxHeight(500);
 520         assertEquals(500, c.maxHeight(-1), 0.0);
 521     }
 522 
 523     @Test public void maxHeightWhenNoSkinIsSetIsZeroByDefault() {
 524         assertEquals(0, c.maxHeight(-1), 0.0);
 525     }
 526 
 527     @Test public void resettingMaxHeightTo_USE_PREF_SIZE_ReturnsThePrefHeightOfTheSkinNodeWhenThereIsASkin() {
 528         c.setSkin(s);
 529         c.setMaxHeight(500);
 530         c.setMaxHeight(Control.USE_PREF_SIZE);
 531         assertEquals(PREF_HEIGHT, c.maxHeight(-1), 0.0);
 532     }
 533 
 534     @Test public void resettingMaxHeightTo_USE_PREF_SIZE_ReturnsZeroWhenThereIsNoSkinAndPrefHeightIsNotSet() {
 535         c.setMaxHeight(500);
 536         c.setMaxHeight(Control.USE_PREF_SIZE);
 537         assertEquals(0, c.maxHeight(-1), 0.0);
 538     }
 539 
 540     @Test public void resettingMaxHeightTo_USE_PREF_SIZE_ReturnsPrefHeightWhenThereIsNoSkinAndPrefHeightIsSet() {
 541         c.setMaxHeight(500);
 542         c.setPrefHeight(105.2);
 543         c.setMaxHeight(Control.USE_PREF_SIZE);
 544         assertEquals(105.2, c.maxHeight(-1), 0.0);
 545     }
 546 
 547     @Test public void resettingMaxHeightTo_USE_COMPUTED_SIZE_ReturnsTheMaxHeightOfTheSkinNodeWhenThereIsASkin() {
 548         c.setSkin(s);
 549         c.setMaxHeight(500);
 550         c.setMaxHeight(Control.USE_COMPUTED_SIZE);
 551         assertEquals(MAX_HEIGHT, c.maxHeight(-1), 0.0);
 552     }
 553 
 554     @Test public void resettingMaxHeightTo_USE_COMPUTED_SIZE_ReturnsZeroWhenThereIsNoSkinAndPrefHeightIsNotSet() {
 555         c.setMaxHeight(500);
 556         c.setMaxHeight(Control.USE_COMPUTED_SIZE);
 557         assertEquals(0, c.maxHeight(-1), 0.0);
 558     }
 559 
 560     @Test public void maxHeightIs_USE_COMPUTED_SIZE_ByDefault() {
 561         assertEquals(Control.USE_COMPUTED_SIZE, c.getMaxHeight(), 0);
 562         assertEquals(Control.USE_COMPUTED_SIZE, c.maxHeightProperty().get(), 0);
 563     }
 564 
 565     @Test public void maxHeightCanBeSet() {
 566         c.setMaxHeight(500);
 567         assertEquals(500, c.getMaxHeight(), 0);
 568         assertEquals(500, c.maxHeightProperty().get(), 0);
 569     }
 570 
 571     @Test public void maxHeightCanBeBound() {
 572         DoubleProperty other = new SimpleDoubleProperty(939);
 573         c.maxHeightProperty().bind(other);
 574         assertEquals(939, c.getMaxHeight(), 0);
 575         other.set(332);
 576         assertEquals(332, c.getMaxHeight(), 0);
 577     }
 578 
 579     @Test public void maxHeightPropertyHasBeanReference() {
 580         assertSame(c, c.maxHeightProperty().getBean());
 581     }
 582 
 583     @Test public void maxHeightPropertyHasName() {
 584         assertEquals("maxHeight", c.maxHeightProperty().getName());
 585     }
 586 
 587     /****************************************************************************
 588      * prefWidth Tests                                                          *
 589      ***************************************************************************/
 590 
 591     @Test public void callsToSetPrefWidthResultInRequestLayoutBeingCalledOnParentNotOnControl() {
 592         // Setup and sanity check
 593         Group parent = new Group();
 594         parent.getChildren().add(c);
 595         parent.layout();
 596         assertTrue(!parent.isNeedsLayout());
 597         assertTrue(!c.isNeedsLayout());
 598         // Test
 599         c.setPrefWidth(80);
 600         assertTrue(parent.isNeedsLayout());
 601         assertTrue(!c.isNeedsLayout());
 602     }
 603 
 604     @Test public void getPrefWidthReturnsThePrefWidthOfTheSkinNode() {
 605         c.setSkin(s);
 606         assertEquals(PREF_WIDTH, c.prefWidth(-1), 0.0);
 607     }
 608 
 609     @Test public void getPrefWidthReturnsTheCustomSetPrefWidthWhenSpecified() {
 610         c.setSkin(s);
 611         c.setPrefWidth(80);
 612         assertEquals(80, c.prefWidth(-1), 0.0);
 613     }
 614 
 615     @Test public void getPrefWidthReturnsTheCustomSetPrefWidthWhenSpecifiedEvenWhenThereIsNoSkin() {
 616         c.setPrefWidth(80);
 617         assertEquals(80, c.prefWidth(-1), 0.0);
 618     }
 619 
 620     @Test public void prefWidthWhenNoSkinIsSetIsZeroByDefault() {
 621         assertEquals(0, c.prefWidth(-1), 0.0);
 622     }
 623 
 624     @Ignore ("What should happen when the pref width is set to USE_PREF_SIZE? Seems it should be an exception")
 625     @Test public void resettingPrefWidthTo_USE_PREF_SIZE_ThrowsExceptionWhenThereIsASkin() {
 626         c.setSkin(s);
 627         c.setPrefWidth(80);
 628         c.setPrefWidth(Control.USE_PREF_SIZE);
 629         assertEquals(PREF_WIDTH, c.prefWidth(-1), 0.0);
 630     }
 631 
 632     @Test public void resettingPrefWidthTo_USE_COMPUTED_SIZE_ReturnsThePrefWidthOfTheSkinNodeWhenThereIsASkin() {
 633         c.setSkin(s);
 634         c.setPrefWidth(80);
 635         c.setPrefWidth(Control.USE_COMPUTED_SIZE);
 636         assertEquals(PREF_WIDTH, c.prefWidth(-1), 0.0);
 637     }
 638 
 639     @Test public void resettingPrefWidthTo_USE_COMPUTED_SIZE_ReturnsZeroWhenThereIsNoSkinAndPrefWidthIsNotSet() {
 640         c.setPrefWidth(80);
 641         c.setPrefWidth(Control.USE_COMPUTED_SIZE);
 642         assertEquals(0, c.prefWidth(-1), 0.0);
 643     }
 644 
 645     @Test public void prefWidthIs_USE_COMPUTED_SIZE_ByDefault() {
 646         assertEquals(Control.USE_COMPUTED_SIZE, c.getPrefWidth(), 0);
 647         assertEquals(Control.USE_COMPUTED_SIZE, c.prefWidthProperty().get(), 0);
 648     }
 649 
 650     @Test public void prefWidthCanBeSet() {
 651         c.setPrefWidth(80);
 652         assertEquals(80, c.getPrefWidth(), 0);
 653         assertEquals(80, c.prefWidthProperty().get(), 0);
 654     }
 655 
 656     @Test public void prefWidthCanBeBound() {
 657         DoubleProperty other = new SimpleDoubleProperty(939);
 658         c.prefWidthProperty().bind(other);
 659         assertEquals(939, c.getPrefWidth(), 0);
 660         other.set(332);
 661         assertEquals(332, c.getPrefWidth(), 0);
 662     }
 663 
 664     @Test public void prefWidthPropertyHasBeanReference() {
 665         assertSame(c, c.prefWidthProperty().getBean());
 666     }
 667 
 668     @Test public void prefWidthPropertyHasName() {
 669         assertEquals("prefWidth", c.prefWidthProperty().getName());
 670     }
 671 
 672     /****************************************************************************
 673      * prefHeight Tests                                                         *
 674      ***************************************************************************/
 675 
 676     @Test public void callsToSetPrefHeightResultInRequestLayoutBeingCalledOnParentNotOnControl() {
 677         // Setup and sanity check
 678         Group parent = new Group();
 679         parent.getChildren().add(c);
 680         parent.layout();
 681         assertTrue(!parent.isNeedsLayout());
 682         assertTrue(!c.isNeedsLayout());
 683         // Test
 684         c.setPrefHeight(92);
 685         assertTrue(parent.isNeedsLayout());
 686         assertTrue(!c.isNeedsLayout());
 687     }
 688 
 689     @Test public void getPrefHeightReturnsThePrefHeightOfTheSkinNode() {
 690         c.setSkin(s);
 691         assertEquals(PREF_HEIGHT, c.prefHeight(-1), 0.0);
 692     }
 693 
 694     @Test public void getPrefHeightReturnsTheCustomSetPrefHeightWhenSpecified() {
 695         c.setSkin(s);
 696         c.setPrefHeight(92);
 697         assertEquals(92, c.prefHeight(-1), 0.0);
 698     }
 699 
 700     @Test public void getPrefHeightReturnsTheCustomSetPrefHeightWhenSpecifiedEvenWhenThereIsNoSkin() {
 701         c.setPrefHeight(92);
 702         assertEquals(92, c.prefHeight(-1), 0.0);
 703     }
 704 
 705     @Test public void prefHeightWhenNoSkinIsSetIsZeroByDefault() {
 706         assertEquals(0, c.prefHeight(-1), 0.0);
 707     }
 708 
 709     @Ignore ("What should happen when the pref width is set to USE_PREF_SIZE? Seems it should be an exception")
 710     @Test public void resettingPrefHeightTo_USE_PREF_SIZE_ThrowsExceptionWhenThereIsASkin() {
 711         c.setSkin(s);
 712         c.setPrefHeight(92);
 713         c.setPrefHeight(Control.USE_PREF_SIZE);
 714         assertEquals(PREF_HEIGHT, c.prefHeight(-1), 0.0);
 715     }
 716 
 717     @Test public void resettingPrefHeightTo_USE_COMPUTED_SIZE_ReturnsThePrefHeightOfTheSkinNodeWhenThereIsASkin() {
 718         c.setSkin(s);
 719         c.setPrefHeight(92);
 720         c.setPrefHeight(Control.USE_COMPUTED_SIZE);
 721         assertEquals(PREF_HEIGHT, c.prefHeight(-1), 0.0);
 722     }
 723 
 724     @Test public void resettingPrefHeightTo_USE_COMPUTED_SIZE_ReturnsZeroWhenThereIsNoSkinAndPrefHeightIsNotSet() {
 725         c.setPrefHeight(92);
 726         c.setPrefHeight(Control.USE_COMPUTED_SIZE);
 727         assertEquals(0, c.prefHeight(-1), 0.0);
 728     }
 729 
 730     @Test public void prefHeightIs_USE_COMPUTED_SIZE_ByDefault() {
 731         assertEquals(Control.USE_COMPUTED_SIZE, c.getPrefHeight(), 0);
 732         assertEquals(Control.USE_COMPUTED_SIZE, c.prefHeightProperty().get(), 0);
 733     }
 734 
 735     @Test public void prefHeightCanBeSet() {
 736         c.setPrefHeight(98.76);
 737         assertEquals(98.76, c.getPrefHeight(), 0);
 738         assertEquals(98.76, c.prefHeightProperty().get(), 0);
 739     }
 740 
 741     @Test public void prefHeightCanBeBound() {
 742         DoubleProperty other = new SimpleDoubleProperty(939);
 743         c.prefHeightProperty().bind(other);
 744         assertEquals(939, c.getPrefHeight(), 0);
 745         other.set(332);
 746         assertEquals(332, c.getPrefHeight(), 0);
 747     }
 748 
 749     @Test public void prefHeightPropertyHasBeanReference() {
 750         assertSame(c, c.prefHeightProperty().getBean());
 751     }
 752 
 753     @Test public void prefHeightPropertyHasName() {
 754         assertEquals("prefHeight", c.prefHeightProperty().getName());
 755     }
 756 
 757     /*********************************************************************
 758      * Tests for the skin property                                       *
 759      ********************************************************************/
 760 
 761     @Test public void skinIsNullByDefault() {
 762         assertNull(c.getSkin());
 763         assertNull(c.contextMenuProperty().get());
 764     }
 765 
 766     @Test public void skinCanBeSet() {
 767         c.setSkin(s);
 768         assertSame(s, c.getSkin());
 769         assertSame(s, c.skinProperty().get());
 770     }
 771 
 772     @Test public void skinCanBeCleared() {
 773         c.setSkin(s);
 774         c.setSkin(null);
 775         assertNull(c.getSkin());
 776         assertNull(c.skinProperty().get());
 777     }
 778 
 779     @Test public void skinCanBeBound() {
 780         ObjectProperty other = new SimpleObjectProperty(s);
 781         c.skinProperty().bind(other);
 782         assertSame(s, c.getSkin());
 783         other.set(null);
 784         assertNull(c.getSkin());
 785     }
 786 
 787     @Test public void skinPropertyHasBeanReference() {
 788         assertSame(c, c.skinProperty().getBean());
 789     }
 790 
 791     @Test public void skinPropertyHasName() {
 792         assertEquals("skin", c.skinProperty().getName());
 793     }
 794 
 795     @Test public void canSpecifySkinViaCSS() {
 796         disableLogging();
 797         try {
 798             ((StyleableProperty)c.skinClassNameProperty()).applyStyle(null, "javafx.scene.control.SkinStub");
 799             assertNotNull(c.getSkin());
 800             assertTrue(c.getSkin() instanceof SkinStub);
 801             assertSame(c, c.getSkin().getSkinnable());
 802         } finally {
 803             enableLogging();
 804         }
 805     }
 806 
 807     @Test public void specifyingSameSkinTwiceViaCSSDoesntSetTwice() {
 808         disableLogging();
 809         try {
 810             SkinChangeListener listener = new SkinChangeListener();
 811             c.skinProperty().addListener(listener);
 812             ((StyleableProperty)c.skinClassNameProperty()).applyStyle(null, "javafx.scene.control.SkinStub");
 813             assertTrue(listener.changed);
 814             listener.changed = false;
 815             ((StyleableProperty)c.skinClassNameProperty()).applyStyle(null, "javafx.scene.control.SkinStub");
 816             assertFalse(listener.changed);
 817         } finally {
 818             enableLogging();
 819         }
 820     }
 821 
 822     @Test public void specifyingNullSkinNameHasNoEffect() {
 823         disableLogging();
 824         try {
 825             SkinChangeListener listener = new SkinChangeListener();
 826             c.skinProperty().addListener(listener);
 827             ((StyleableProperty)c.skinClassNameProperty()).applyStyle(null, null);
 828             assertFalse(listener.changed);
 829             assertNull(c.getSkin());
 830         } finally {
 831             enableLogging();
 832         }
 833     }
 834 
 835     @Test public void specifyingEmptyStringSkinNameHasNoEffect() {
 836         disableLogging();
 837         try {
 838             SkinChangeListener listener = new SkinChangeListener();
 839             c.skinProperty().addListener(listener);
 840             ((StyleableProperty)c.skinClassNameProperty()).applyStyle(null, "");
 841             assertFalse(listener.changed);
 842             assertNull(c.getSkin());
 843         } finally {
 844             enableLogging();
 845         }
 846     }
 847 
 848     @Test public void loadingSkinWithNoAppropriateConstructorResultsInNoSkin() {
 849         disableLogging();
 850         try {
 851             SkinChangeListener listener = new SkinChangeListener();
 852             c.skinProperty().addListener(listener);
 853             ((StyleableProperty)c.skinClassNameProperty()).applyStyle(null, "javafx.scene.control.ControlTest$BadSkin");
 854             assertFalse(listener.changed);
 855             assertNull(c.getSkin());
 856         } finally {
 857             enableLogging();
 858         }
 859     }
 860 
 861     @Test public void exceptionThrownDuringSkinConstructionResultsInNoSkin() {
 862         disableLogging();
 863         try {
 864             SkinChangeListener listener = new SkinChangeListener();
 865             c.skinProperty().addListener(listener);
 866             ((StyleableProperty)c.skinClassNameProperty()).applyStyle(null, "javafx.scene.control.ControlTest$ExceptionalSkin");
 867             assertFalse(listener.changed);
 868             assertNull(c.getSkin());
 869         } finally {
 870             enableLogging();
 871         }
 872     }
 873 
 874     /*********************************************************************
 875      * Tests for the tooltip property                                    *
 876      ********************************************************************/
 877 
 878     @Test public void tooltipIsNullByDefault() {
 879         assertNull(c.getTooltip());
 880         assertNull(c.tooltipProperty().get());
 881     }
 882 
 883     @Test public void tooltipCanBeSet() {
 884         Tooltip tip = new Tooltip("Hello");
 885         c.setTooltip(tip);
 886         assertSame(tip, c.getTooltip());
 887         assertSame(tip, c.tooltipProperty().get());
 888     }
 889 
 890     @Test public void tooltipCanBeCleared() {
 891         Tooltip tip = new Tooltip("Hello");
 892         c.setTooltip(tip);
 893         c.setTooltip(null);
 894         assertNull(c.getTooltip());
 895         assertNull(c.tooltipProperty().get());
 896     }
 897 
 898     @Test public void tooltipCanBeBound() {
 899         Tooltip tip = new Tooltip("Hello");
 900         ObjectProperty<Tooltip> other = new SimpleObjectProperty<Tooltip>(tip);
 901         c.tooltipProperty().bind(other);
 902         assertSame(tip, c.getTooltip());
 903         assertSame(tip, c.tooltipProperty().get());
 904         other.set(null);
 905         assertNull(c.getTooltip());
 906         assertNull(c.tooltipProperty().get());
 907     }
 908 
 909     @Test public void tooltipPropertyHasBeanReference() {
 910         assertSame(c, c.tooltipProperty().getBean());
 911     }
 912 
 913     @Test public void tooltipPropertyHasName() {
 914         assertEquals("tooltip", c.tooltipProperty().getName());
 915     }
 916 
 917     /*********************************************************************
 918      * Tests for the contextMenu property                                    *
 919      ********************************************************************/
 920 
 921     @Test public void contextMenuIsNullByDefault() {
 922         assertNull(c.getContextMenu());
 923         assertNull(c.contextMenuProperty().get());
 924     }
 925 
 926     @Test public void contextMenuCanBeSet() {
 927         ContextMenu menu = new ContextMenu();
 928         c.setContextMenu(menu);
 929         assertSame(menu, c.getContextMenu());
 930         assertSame(menu, c.contextMenuProperty().get());
 931     }
 932 
 933     @Test public void contextMenuCanBeCleared() {
 934         ContextMenu menu = new ContextMenu();
 935         c.setContextMenu(menu);
 936         c.setContextMenu(null);
 937         assertNull(c.getContextMenu());
 938         assertNull(c.getContextMenu());
 939     }
 940 
 941     @Test public void contextMenuCanBeBound() {
 942         ContextMenu menu = new ContextMenu();
 943         ObjectProperty<ContextMenu> other = new SimpleObjectProperty<ContextMenu>(menu);
 944         c.contextMenuProperty().bind(other);
 945         assertSame(menu, c.getContextMenu());
 946         assertSame(menu, c.contextMenuProperty().get());
 947         other.set(null);
 948         assertNull(c.getContextMenu());
 949         assertNull(c.contextMenuProperty().get());
 950     }
 951 
 952     @Test public void contextMenuPropertyHasBeanReference() {
 953         assertSame(c, c.contextMenuProperty().getBean());
 954     }
 955 
 956     @Test public void contextMenuPropertyHasName() {
 957         assertEquals("contextMenu", c.contextMenuProperty().getName());
 958     }
 959 
 960     /*********************************************************************
 961      * Miscellaneous tests                                               *
 962      ********************************************************************/
 963 
 964     @Test public void setMinSizeUpdatesBothMinWidthAndMinHeight() {
 965         c.setMinSize(123.45, 98.6);
 966         assertEquals(123.45, c.getMinWidth(), 0);
 967         assertEquals(98.6, c.getMinHeight(), 0);
 968     }
 969 
 970     @Test public void setMaxSizeUpdatesBothMaxWidthAndMaxHeight() {
 971         c.setMaxSize(658.9, 373.4);
 972         assertEquals(658.9, c.getMaxWidth(), 0);
 973         assertEquals(373.4, c.getMaxHeight(), 0);
 974     }
 975 
 976     @Test public void setPrefSizeUpdatesBothPrefWidthAndPrefHeight() {
 977         c.setPrefSize(720, 540);
 978         assertEquals(720, c.getPrefWidth(), 0);
 979         assertEquals(540, c.getPrefHeight(), 0);
 980     }
 981 
 982     @Test public void baselineOffsetIsZeroWhenThereIsNoSkin() {
 983         assertEquals(0, c.getBaselineOffset(), 0f);
 984     }
 985 
 986     @Test public void baselineOffsetUpdatedWhenTheSkinChanges() {
 987         c.setSkin(s);
 988         assertEquals(BASELINE_OFFSET, c.getBaselineOffset(), 0);
 989     }
 990 
 991     @Test
 992     public void testRT18097() {
 993         try {
 994             File f = System.getProperties().containsKey("CSS_META_DATA_TEST_DIR") ?
 995                     new File(System.getProperties().get("CSS_META_DATA_TEST_DIR").toString()) :
 996                     null;
 997             if (f == null) {
 998                 ClassLoader cl = Thread.currentThread().getContextClassLoader();
 999                 URL base = cl.getResource("javafx/../javafx");
1000                 f = new File(base.toURI());
1001             }
1002             //System.err.println(f.getPath());
1003             recursiveCheck(f, f.getPath().length() - 7);
1004         } catch (Exception ex) {
1005             ex.printStackTrace(System.err);
1006             fail(ex.getMessage());
1007         }
1008     }
1009 
1010     private static void checkClass(Class someClass) {
1011 
1012         // Ignore inner classes
1013         if (someClass.getEnclosingClass() != null) return;
1014 
1015         if (javafx.scene.control.Control.class.isAssignableFrom(someClass) &&
1016                 Modifier.isAbstract(someClass.getModifiers()) == false &&
1017                 !Modifier.isPrivate(someClass.getModifiers()) == false) {
1018             String what = someClass.getName();
1019             try {
1020                 // should get NoSuchMethodException if ctor is not public
1021 //                Constructor ctor = someClass.getConstructor((Class[])null);
1022                 Method m = someClass.getMethod("getClassCssMetaData", (Class[]) null);
1023 //                Node node = (Node)ctor.newInstance((Object[])null);
1024                 Node node = (Node)someClass.newInstance();
1025                 for (CssMetaData styleable : (List<CssMetaData<? extends Styleable, ?>>) m.invoke(null)) {
1026 
1027                     what = someClass.getName() + " " + styleable.getProperty();
1028                     WritableValue writable = styleable.getStyleableProperty(node);
1029                     assertNotNull(what, writable);
1030 
1031                     Object defaultValue = writable.getValue();
1032                     Object initialValue = styleable.getInitialValue((Node) someClass.newInstance());
1033 
1034                     if (defaultValue instanceof Number) {
1035                         // 5 and 5.0 are not the same according to equals,
1036                         // but they should be...
1037                         assert(initialValue instanceof Number);
1038                         double d1 = ((Number)defaultValue).doubleValue();
1039                         double d2 = ((Number)initialValue).doubleValue();
1040                         assertEquals(what, d1, d2, .001);
1041 
1042                     } else if (defaultValue != null && defaultValue.getClass().isArray()) {
1043                         assertTrue(what, Arrays.equals((Object[])defaultValue, (Object[])initialValue));
1044                     } else {
1045                         assertEquals(what, defaultValue, initialValue);
1046                     }
1047 
1048                 }
1049 
1050             } catch (NoSuchMethodException ex) {
1051                 fail("NoSuchMethodException: RT-18097 cannot be tested on " + what);
1052             } catch (IllegalAccessException ex) {
1053                 System.err.println("IllegalAccessException:  RT-18097 cannot be tested on " + what);
1054             } catch (IllegalArgumentException ex) {
1055                 fail("IllegalArgumentException:  RT-18097 cannot be tested on " + what);
1056             } catch (InvocationTargetException ex) {
1057                 fail("InvocationTargetException:  RT-18097 cannot be tested on " + what);
1058             } catch (InstantiationException ex) {
1059                 fail("InstantiationException:  RT-18097 cannot be tested on " + what);
1060             }
1061         }
1062     }
1063 
1064     private static void checkDirectory(File directory, final int pathLength) {
1065         if (directory.isDirectory()) {
1066 
1067             for (File file : directory.listFiles()) {
1068                 if (file.isFile() && file.getName().endsWith(".class")) {
1069                     final String filePath = file.getPath();
1070                     final int len = file.getPath().length() - ".class".length();
1071                     final String clName =
1072                         file.getPath().substring(pathLength+1, len).replace(File.separatorChar,'.');
1073                     if (clName.startsWith("javafx.scene") == false) continue;
1074                     try {
1075                         final Class cl = Class.forName(clName);
1076                         if (cl != null) checkClass(cl);
1077                     } catch(ClassNotFoundException ex) {
1078                         System.err.println(ex.toString() + " " + clName);
1079                     }
1080                 }
1081             }
1082         }
1083     }
1084 
1085     private static void recursiveCheck(File directory, int pathLength) {
1086         if (directory.isDirectory()) {
1087 //            System.out.println(directory.getPath());
1088             checkDirectory(directory, pathLength);
1089 
1090             for (File subFile : directory.listFiles()) {
1091                 recursiveCheck(subFile, pathLength);
1092             }
1093         }
1094     }
1095 
1096 
1097     // TODO need to test key event dispatch
1098 
1099 //    // test that the Control.Behavior methods correctly fix the coordinate
1100 //    // space values to match based on old node & new
1101 //    function testControlBehaviorCorrectlyMapsEventCoordinates() {
1102 //        var c = ControlStub { width: 20, height: 20, skin: SkinStub {} }
1103 //        var n = Rectangle { width: 100, height: 100 }
1104 //        var g:Group;
1105 //        // setting up a fairly complicated scene to see if the coordinate
1106 //        // values on the copied event are correct. This scene has two different
1107 //        // groups, and each group has a translate transform applied.
1108 //        // The node "n" where the event originated is in a different group
1109 //        // from the "c" node.
1110 //        //
1111 //        // in scene coords, n is 100x100 at 40, 52
1112 //        //                  c is 20x20 at 5, 30
1113 //        // in local coords n is 100x100 at 0, 0
1114 //        //                 c is 20x20 at 0, 0
1115 //        Scene {
1116 //            content: g = Group {
1117 //                // n is 100x100, child group is 40x10
1118 //                translateX: 40
1119 //                translateY: 52
1120 //                content: [
1121 //                    n,
1122 //                    Group {
1123 //                        // the content is 20x20. Scale makes it 40x10
1124 //                        translateX: -35
1125 //                        translateY: -22
1126 //                        content: c // this is 20x20
1127 //                    }
1128 //                ]
1129 //            }
1130 //        }
1131 //
1132 //        // BEGIN SANITY CHECK
1133 //        // start off with a couple sanity checks to make sure I have my math
1134 //        // right such that if the real portion of this test fails, I know it
1135 //        // is not due to a faulty test
1136 //
1137 //        // test local coords of n
1138 //        assertEquals(0, n.boundsInLocal.minX);
1139 //        assertEquals(0, n.boundsInLocal.minY);
1140 //        assertEquals(100, n.boundsInLocal.width);
1141 //        assertEquals(100, n.boundsInLocal.height);
1142 //
1143 //        // test local coords of c
1144 //        assertEquals(0, c.boundsInLocal.minX);
1145 //        assertEquals(0, c.boundsInLocal.minY);
1146 //        assertEquals(20, c.boundsInLocal.width);
1147 //        assertEquals(20, c.boundsInLocal.height);
1148 //
1149 //        // test scene coords of n
1150 //        assertEquals(40, n.localToScene(n.boundsInLocal).minX);
1151 //        assertEquals(52, n.localToScene(n.boundsInLocal).minY);
1152 //        assertEquals(100, n.localToScene(n.boundsInLocal).width);
1153 //        assertEquals(100, n.localToScene(n.boundsInLocal).height);
1154 //
1155 //        // test scene coords of c
1156 //        assertEquals(5, c.localToScene(c.boundsInLocal).minX);
1157 //        assertEquals(30, c.localToScene(c.boundsInLocal).minY);
1158 //        assertEquals(20, c.localToScene(c.boundsInLocal).width);
1159 //        assertEquals(20, c.localToScene(c.boundsInLocal).height);
1160 //        // END SANITY CHECK
1161 //
1162 //        // create a simple mouse event on node. The x/y are 0,0, thus in the
1163 //        // top left corner of the fill area of the rectangle.
1164 //        c.onMousePressed = function(evt:MouseEvent):Void {
1165 //            // this mouse event should have been translated from "g" space
1166 //            // to "c" space. Relative to "g", "c" is 40x10 at -35, -22
1167 //            //  so (0,0) in c space relative to n would be at 35, 22
1168 //            assertEquals(35.0, evt.x);
1169 //            assertEquals(22.0, evt.y);
1170 //        }
1171 //        // invoke the code path that leads to calling the previously defined
1172 //        // onMousePressed function handler
1173 //        mousePress(g, 0, 0);
1174 //    }
1175 
1176     /**
1177      * Used for representing the "node" of the Skin, such that each of the fields
1178      * minWidth, minHeight, maxWidth, maxHeight, prefWidth, and prefHeight have
1179      * different values, and thus can more easily detect bugs if the various
1180      * test methods fail (if they all had the same value, it would potentially
1181      * mask bugs where maxWidth was called instead of minWidth, and so forth).
1182      */
1183     public class ResizableRectangle extends Rectangle {
1184         private double minWidth;
1185         private double maxWidth;
1186         private double minHeight;
1187         private double maxHeight;
1188         private double prefWidth;
1189         private double prefHeight;
1190         private double baselineOffset;
1191 
1192         @Override public boolean isResizable() { return true; }
1193         @Override public double minWidth(double h) { return minWidth; }
1194         @Override public double minHeight(double w) { return minHeight; }
1195         @Override public double prefWidth(double height) { return prefWidth; }
1196         @Override public double prefHeight(double width) { return prefHeight; }
1197         @Override public double maxWidth(double h) { return maxWidth; }
1198         @Override public double maxHeight(double w) { return maxHeight; }
1199         @Override public double getBaselineOffset() { return baselineOffset; }
1200 
1201         @Override public void resize(double width, double height) {
1202             setWidth(width);
1203             setHeight(height);
1204         }
1205     }
1206 
1207     /**
1208      * This is a Skin without an appropriate constructor, and will fail
1209      * to load!
1210      * @param <C>
1211      */
1212     public static final class BadSkin<C extends Control> extends SkinStub<C> {
1213         public BadSkin() {
1214             super(null);
1215         }
1216     }
1217 
1218     /**
1219      * This is a Skin without an appropriate constructor, and will fail
1220      * to load!
1221      * @param <C>
1222      */
1223     public static final class ExceptionalSkin<C extends Control> extends SkinStub<C> {
1224         public ExceptionalSkin(C control) {
1225             super(control);
1226             throw new NullPointerException("I am EXCEPTIONAL!");
1227         }
1228     }
1229 
1230     public class SkinChangeListener implements ChangeListener<Skin> {
1231         boolean changed = false;
1232         @Override public void changed(ObservableValue<? extends Skin> observable, Skin oldValue, Skin newValue) {
1233             changed = true;
1234         }
1235     }
1236 }