1 /*
  2  * Copyright (c) 2020, 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 myapp2;
 27 
 28 import java.io.IOException;
 29 import java.net.URL;
 30 import java.util.ArrayList;
 31 import java.util.Iterator;
 32 import java.util.List;
 33 import java.util.Set;
 34 import java.util.TreeMap;
 35 
 36 import javafx.application.Application;
 37 import javafx.application.Platform;
 38 import javafx.event.ActionEvent;
 39 import javafx.fxml.FXMLLoader;
 40 import javafx.scene.Node;
 41 import javafx.scene.Parent;
 42 import javafx.scene.Scene;
 43 import javafx.scene.control.Button;
 44 import javafx.scene.input.MouseButton;
 45 import javafx.scene.input.MouseEvent;
 46 import javafx.scene.layout.AnchorPane;
 47 import javafx.stage.Stage;
 48 
 49 import javax.script.Bindings;
 50 import javax.script.ScriptContext;
 51 
 52 import static myapp2.Constants.*;
 53 import pseudoScriptEngineCompilable.InvocationInfos;
 54 import pseudoScriptEngineCompilable.RgfPseudoScriptEngineCompilable;
 55 
 56 /**
 57  * Modular test application for testing FXML.
 58  * This is launched by ModuleLauncherTest.
 59  */
 60 public class FXMLScriptDeployment2Compile_On extends Application {
 61 
 62     static boolean bDebug = false; // true; // display invocation list
 63 
 64     /** Runs the application and invokes the tests.
 65      *  @param args the command line arguments, if any given the RgfPseudoScriptEngine invocation logs get displayed
 66      *              which are used in the asserCorrectInvocations() method
 67      */
 68     public static void main(String[] args) {
 69         try {
 70             // any argument will cause the bDebug flag to be set to true
 71             if (args.length > 0) {
 72                bDebug = true;
 73             }
 74             new FXMLScriptDeployment2Compile_On().launch();
 75             // for debugging, allows to study invocation logs in detail
 76             if (bDebug) { dumpEvalInformation(); }
 77             assertCorrectInvocations();
 78         } catch (AssertionError ex) {
 79             System.err.println("ASSERTION ERROR: caught unexpected exception: " + ex);
 80             ex.printStackTrace(System.err);
 81             System.exit(ERROR_ASSERTION_FAILURE);
 82         } catch (Error | Exception ex) {
 83             System.err.println("ERROR: caught unexpected exception: " + ex);
 84             ex.printStackTrace(System.err);
 85             System.exit(ERROR_UNEXPECTED_EXCEPTION);
 86         }
 87         System.exit(ERROR_NONE);    // not in stop() method as we need to run the assertions first
 88     }
 89 
 90     @Override
 91     public void start(Stage mainStage) {
 92         URL fxmlUrl = null;
 93         Parent rootNode = null;
 94         Scene scene = null;
 95         Button btn = null;
 96         try {
 97              fxmlUrl = Util.getURL(FXMLScriptDeployment2Compile_On.class, "demo_02_on");
 98              rootNode = FXMLLoader.load(fxmlUrl);
 99              scene = new Scene(rootNode);
100              btn = (Button) scene.lookup("#idButton");
101         }
102         catch (Exception ioe) {
103             ioe.printStackTrace();
104             System.exit(ERROR_UNEXPECTED_EXCEPTION);
105         }
106             // fire three events on the button
107         btn.fire();
108         btn.fireEvent(new ActionEvent());
109         btn.fireEvent(new MouseEvent(MouseEvent.MOUSE_CLICKED,
110                                        0,       // double x,
111                                        0,       // double y,
112                                        0,       // double screenX,
113                                        0,       // double screenY,
114                                        MouseButton.PRIMARY,         // MouseButton button,
115                                        0,       // int clickCount,
116                                        false,   // boolean shiftDown,
117                                        false,   // boolean controlDown,
118                                        false,   // boolean altDown,
119                                        false,   // boolean metaDown,
120                                        true,    // boolean primaryButtonDown,
121                                        false,   // boolean middleButtonDown,
122                                        false,   // boolean secondaryButtonDown,
123                                        false,   // boolean synthesized,
124                                        false,   // boolean popupTrigger,
125                                        false,   // boolean stillSincePress,
126                                        null     // PickResult pickResult
127                                      )
128                       );
129 
130         // mainStage.setScene(scene);
131         // mainStage.show();
132         Platform.exit();
133     }
134 
135     // show engine invocations with script text and their Bindings
136     static void dumpEvalInformation() {
137         System.err.println("\nListing eval() invocation information (invocationList):");
138 
139         Iterator<RgfPseudoScriptEngineCompilable> it = RgfPseudoScriptEngineCompilable.getEnginesUsed().iterator();
140         while (it.hasNext()) {
141             RgfPseudoScriptEngineCompilable rpse = it.next();
142             ArrayList invocationList = rpse.getInvocationList();
143             System.err.println("ScriptEngine: [" + rpse + "]");
144 
145             Iterator<InvocationInfos> itEval = invocationList.iterator();
146             int count = 1;
147             while (itEval.hasNext()) {
148                 System.err.println("\teval() invocation # " + count + ": ");
149                 InvocationInfos entry = itEval.next();
150                 System.err.println(entry.toDebugFormat("\t\t"));    // indentation
151                 count++;
152                 System.err.println();
153             }
154         }
155     }
156 
157     static void assertCorrectInvocations() {
158             // test only creates one engine for a script controller
159         Util.assertTrue("exactly one pseudo script engine instance",
160                         RgfPseudoScriptEngineCompilable.getEnginesUsed().size() == 1);
161         RgfPseudoScriptEngineCompilable rpse = RgfPseudoScriptEngineCompilable.getEnginesUsed().get(0);
162 
163         ArrayList invocationList = rpse.getInvocationList();
164         Util.assertTrue("exactly nine script engine invocations", invocationList.size() == 9);
165 
166         final String FILENAME = "javax.script.filename";
167         final String ARGV = "javax.script.argv";
168         final String EVENT = "event";
169         final String IDBUTTON = "idButton";
170         final String IDROOT = "idRoot";
171         final String LOCATION = "location";    // always FXML File hosting script controller code
172         final String RESOURCES = "resources";   // always null in this test
173 
174         for (Integer invocation = 1; invocation <= invocationList.size(); invocation++) {
175             InvocationInfos entry = (InvocationInfos) invocationList.get(invocation - 1);
176             String script = entry.script;
177             TreeMap<Integer,TreeMap> scopes = (TreeMap) entry.bindings;
178 
179             TreeMap<String,Object> engineBindings = scopes.get(100);
180             TreeMap<String,Object> globalBindings = scopes.get(200);
181 
182             Object obj = null;
183             Button btn = null;
184 
185             // global Bindings
186             Util.assertExists(IDROOT + " in global scope Bindings", globalBindings.containsKey(IDROOT));
187             obj = globalBindings.get(IDROOT);
188             Util.assertType(IDROOT, AnchorPane.class, obj);
189 
190             Util.assertExists(LOCATION + " in global scope Bindings", globalBindings.containsKey(LOCATION));
191             obj = globalBindings.get(LOCATION);
192             Util.assertType(LOCATION, URL.class, obj);
193 
194             Util.assertExists(RESOURCES + " in global scope Bindings", globalBindings.containsKey(RESOURCES));
195             obj = globalBindings.get(RESOURCES);
196             Util.assertNull(RESOURCES,obj);
197 
198             if (invocation == 1) {
199                 Util.assertNotExists(IDBUTTON + " in global scope Bindings", globalBindings.containsKey(IDBUTTON));
200             }
201             else {
202                 Util.assertExists(IDBUTTON + " in global scope Bindings", globalBindings.containsKey(IDBUTTON));
203                 obj = globalBindings.get(IDBUTTON);
204                 Util.assertType(IDBUTTON, Button.class, obj);
205                 btn = (Button) obj;
206             }
207 
208             // engine Bindings
209             Util.assertExists(FILENAME + " in engine scope Bindings", engineBindings.containsKey(FILENAME));
210             if (invocation < 7) {  // no event objects, no arguments
211                 Util.assertNotExists(ARGV + " in engine scope Bindings", engineBindings.containsKey(ARGV));
212                 Util.assertNotExists(EVENT + " in engine scope Bindings", engineBindings.containsKey(EVENT));
213             }
214             else {    // this has events on the Button
215                 Util.assertExists(ARGV + " in engine scope Bindings", engineBindings.containsKey(ARGV));
216                 Object[] argv = (Object[]) engineBindings.get(ARGV);
217 
218                 Util.assertExists(EVENT + " in engine scope Bindings", engineBindings.containsKey(EVENT));
219                 obj = engineBindings.get(EVENT);
220 
221                 Util.assertSame("argv[0] == event", argv[0], obj);
222 
223                 if (invocation == 9) {
224                     Util.assertType(EVENT, MouseEvent.class, obj);
225                     MouseEvent ev = (MouseEvent) obj;
226                     Util.assertSame("MouseEvent.getSource() == btn", ev.getSource(), btn);
227                     Util.assertSame("MouseEvent.MOUSE_CLICKED", MouseEvent.MOUSE_CLICKED, ev.getEventType());
228                 } else {
229                     Util.assertType(EVENT, ActionEvent.class, obj);
230                     ActionEvent ev = (ActionEvent) obj;
231                     Util.assertSame("ActionEvent.getSource() == btn", ev.getSource(), btn);
232                 }
233             }
234 
235             // check filename and script
236             String filename = (String) engineBindings.get(FILENAME);
237             boolean ok = false;
238             switch (invocation) {
239                 case 1:
240                     Util.assertEndsWith  ("demo_02_topscript.sqtmc", filename);
241                     Util.assertStartsWith("RgfPseudoCompiledScript.eval(): RgfPseudoCompiledScript=[demo_02_topscript.sqtmc file - pseudo script", script);
242                     break;
243 
244                 case 2:
245                     Util.assertEndsWith  ("demo_02_middlescript.sqtmc", filename);
246                     Util.assertStartsWith("RgfPseudoCompiledScript.eval(): RgfPseudoCompiledScript=[demo_02_middlescript.sqtmc file - pseudo script", script);
247                     break;
248 
249                 case 3:
250                     Util.assertEndsWith("demo_02_on.fxml-script_starting_at_line_52", filename);
251                     Util.assertStartsWith("RgfPseudoCompiledScript.eval(): RgfPseudoCompiledScript=[demo_02_on.fxml embedded script sqtmc - line # 52", script);
252                     break;
253 
254                 case 4:
255                     Util.assertEndsWith  ("demo_02_bottomscript.sqtmc", filename);
256                     Util.assertStartsWith("RgfPseudoCompiledScript.eval(): RgfPseudoCompiledScript=[demo_02_bottomscript.sqtmc file - pseudo script", script);
257                     break;
258 
259                 case 5:
260                     Util.assertEndsWith("demo_02_on.fxml-script_starting_at_line_56", filename);
261                     Util.assertStartsWith("RgfPseudoCompiledScript.eval(): RgfPseudoCompiledScript=[something (line # 56)", script);
262                     break;
263 
264                 case 6:
265                     Util.assertEndsWith("demo_02_on.fxml-script_starting_at_line_59", filename);
266                     Util.assertStartsWith("RgfPseudoCompiledScript.eval(): RgfPseudoCompiledScript=[demo_02_on.fxml (line # 59):", script);
267                     break;
268 
269                 case 7:     // same as case 8 (same button clicked)
270                     Util.assertEndsWith("demo_02_on.fxml-onAction_attribute_in_element_ending_at_line_46", filename);
271                     Util.assertStartsWith("RgfPseudoCompiledScript.eval(Bindings bindings): RgfPseudoCompiledScript=[demo_02_on.fxml embedded event - ActionEvent - line # 45 -", script);
272                     break;
273 
274                 case 8:     // same as case 7 (same button clicked)
275                     Util.assertEndsWith("demo_02_on.fxml-onAction_attribute_in_element_ending_at_line_46", filename);
276                     Util.assertStartsWith("RgfPseudoCompiledScript.eval(Bindings bindings): RgfPseudoCompiledScript=[demo_02_on.fxml embedded event - ActionEvent - line # 45 -", script);
277                     break;
278 
279                 case 9:
280                     Util.assertEndsWith("demo_02_on.fxml-onMouseClicked_attribute_in_element_ending_at_line_46", filename);
281                     Util.assertStartsWith("RgfPseudoCompiledScript.eval(Bindings bindings): RgfPseudoCompiledScript=[demo_02_on.fxml embedded event - MouseClicked - line # 44", script);
282                     break;
283             }
284         }
285     }
286 }