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