1 /*
   2  * Copyright (c) 2010, 2015, 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 com.oracle.javafx.jmx;
  27 
  28 import com.oracle.javafx.jmx.json.JSONDocument;
  29 import javafx.collections.ObservableList;
  30 import javafx.scene.Group;
  31 import javafx.scene.Node;
  32 import javafx.scene.Parent;
  33 import javafx.scene.Scene;
  34 import javafx.scene.shape.Circle;
  35 import javafx.scene.shape.Line;
  36 import javafx.scene.shape.Rectangle;
  37 import javafx.stage.Stage;
  38 import javafx.stage.Window;
  39 
  40 import org.junit.BeforeClass;
  41 import org.junit.Test;
  42 import static org.junit.Assert.*;
  43 
  44 import java.util.HashSet;
  45 import java.util.Iterator;
  46 import java.util.List;
  47 import java.util.Set;
  48 
  49 public class SGMXBean_sceneGraph_Test {
  50 
  51     private final SGMXBean mxBean = new SGMXBeanImpl();
  52 
  53     private static Stage stage1;
  54     private static Stage stage2;
  55 
  56     private static int nodesCount;
  57 
  58     @BeforeClass
  59     public static void setUp() {
  60         stage1 = new Stage();
  61         Scene scene1 = new Scene(new Group(
  62                 new Rectangle(100, 100),
  63                 new Circle(30),
  64                 new Group(
  65                     new Rectangle(30, 30),
  66                     new Line(0, 0, 100, 30)
  67                 )));
  68         stage1.setScene(scene1);
  69         stage1.show();
  70 
  71         stage2 = new Stage();
  72         Scene scene2 = new Scene(new Group(
  73                 new Circle(100),
  74                 new Line(30, 30, 20, 100)));
  75         stage2.setScene(scene2);
  76         stage2.show();
  77 
  78         final List<Window> windows = Window.getWindows();
  79         nodesCount = 0;
  80         for (Window w : windows) {
  81             nodesCount += countNodes(w.getScene().getRoot());
  82         }
  83     }
  84 
  85     private static int countNodes(Parent p) {
  86         ObservableList<Node> children = p.getChildrenUnmodifiable();
  87         int res = 1; // the node itself
  88         for (int i = 0; i < children.size(); i++) {
  89             final Node n = children.get(i);
  90             if (n instanceof Parent) {
  91                 res += countNodes((Parent)n);
  92             } else {
  93                 res++;
  94             }
  95         }
  96         return res;
  97     }
  98 
  99     @Test
 100     public void sceneGraphsStructureTest() {
 101         mxBean.pause();
 102         JSONDocument jwindows = TestUtils.getJSONDocument(mxBean.getWindows());
 103         int[] ids = TestUtils.getWindowIDs(jwindows);
 104         for (int i = 0; i < ids.length; i++) {
 105             JSONDocument sg = TestUtils.getJSONDocument(mxBean.getSGTree(ids[i]));
 106             checkSGStructure(sg);
 107         }
 108     }
 109 
 110     private static void checkSGStructure(JSONDocument d) {
 111         assertEquals(JSONDocument.Type.OBJECT, d.type());
 112         JSONDocument jchildren = d.get("children");
 113         if (jchildren.equals(JSONDocument.EMPTY_OBJECT)) {
 114             return;
 115         }
 116         assertEquals(JSONDocument.Type.ARRAY, jchildren.type());
 117         for (int i = 0; i < jchildren.array().size(); i++) {
 118             checkSGStructure(jchildren.get(i));
 119         }
 120     }
 121 
 122     @Test
 123     public void nodesCountTest() {
 124         mxBean.pause();
 125         JSONDocument jwindows = TestUtils.getJSONDocument(mxBean.getWindows());
 126         int[] ids = TestUtils.getWindowIDs(jwindows);
 127         int jNodeCount = 0;
 128         for (int i = 0; i < ids.length; i++) {
 129             JSONDocument sg = TestUtils.getJSONDocument(mxBean.getSGTree(ids[i]));
 130             jNodeCount += countNodes(sg);
 131         }
 132         assertEquals(nodesCount, jNodeCount);
 133     }
 134 
 135     private static int countNodes(JSONDocument d) {
 136         JSONDocument jchildren = d.get("children");
 137         if (jchildren.equals(JSONDocument.EMPTY_OBJECT)) {
 138             return 1;
 139         }
 140         int res = 1; // the node (container) itself
 141         for (int i = 0; i < jchildren.array().size(); i++) {
 142             res += countNodes(jchildren.get(i));
 143         }
 144         return res;
 145     }
 146 
 147     @Test
 148     public void nodesHaveIDsTest() {
 149         mxBean.pause();
 150         JSONDocument jwindows = TestUtils.getJSONDocument(mxBean.getWindows());
 151         int[] ids = TestUtils.getWindowIDs(jwindows);
 152         for (int i = 0; i < ids.length; i++) {
 153             JSONDocument sg = TestUtils.getJSONDocument(mxBean.getSGTree(ids[i]));
 154             checkNodeHasID(sg);
 155         }
 156     }
 157 
 158     private static void checkNodeHasID(JSONDocument d) {
 159         Number id = d.getNumber("id");
 160         assertNotNull(id);
 161         JSONDocument jchildren = d.get("children");
 162         if (jchildren.equals(JSONDocument.EMPTY_OBJECT)) {
 163             return;
 164         }
 165         for (int i = 0; i < jchildren.array().size(); i++) {
 166             checkNodeHasID(jchildren.get(i));
 167         }
 168     }
 169 
 170     @Test
 171     public void nodesHaveUniqueIDsTest() {
 172         Set<Number> ids = new HashSet<Number>();
 173         mxBean.pause();
 174         JSONDocument jwindows = TestUtils.getJSONDocument(mxBean.getWindows());
 175         int[] windowIDs = TestUtils.getWindowIDs(jwindows);
 176         for (int i = 0; i < windowIDs.length; i++) {
 177             JSONDocument sg = TestUtils.getJSONDocument(mxBean.getSGTree(windowIDs[i]));
 178             checkNodeHasUniqueID(sg, ids);
 179         }
 180     }
 181 
 182     private static void checkNodeHasUniqueID(JSONDocument d, Set<Number> ids) {
 183         Number id = d.getNumber("id");
 184         assertFalse(ids.contains(id));
 185         ids.add(id);
 186         JSONDocument jchildren = d.get("children");
 187         if (jchildren.equals(JSONDocument.EMPTY_OBJECT)) {
 188             return;
 189         }
 190         for (int i = 0; i < jchildren.array().size(); i++) {
 191             checkNodeHasUniqueID(jchildren.get(i), ids);
 192         }
 193     }
 194 }