/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.netbeans.test.ide;

import java.awt.Component;
import java.awt.Container;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.event.KeyEvent;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JCheckBox;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import junit.framework.Test;
import org.netbeans.jellytools.Bundle;
import org.netbeans.jellytools.EditorOperator;
import org.netbeans.jellytools.FavoritesOperator;
import org.netbeans.jellytools.FilesTabOperator;
import org.netbeans.jellytools.HelpOperator;
import org.netbeans.jellytools.JellyTestCase;
import org.netbeans.jellytools.MainWindowOperator;
import org.netbeans.jellytools.NbDialogOperator;
import org.netbeans.jellytools.NewJavaFileNameLocationStepOperator;
import org.netbeans.jellytools.NewFileWizardOperator;
import org.netbeans.jellytools.NewJavaFileWizardOperator;
import org.netbeans.jellytools.NewJavaProjectNameLocationStepOperator;
import org.netbeans.jellytools.NewProjectWizardOperator;
import org.netbeans.jellytools.OptionsOperator;
import org.netbeans.jellytools.OutputOperator;
import org.netbeans.jellytools.OutputTabOperator;
import org.netbeans.jellytools.PluginsOperator;
import org.netbeans.jellytools.ProjectsTabOperator;
import org.netbeans.jellytools.RuntimeTabOperator;
import org.netbeans.jellytools.TopComponentOperator;
import org.netbeans.jellytools.actions.Action;
import org.netbeans.jellytools.actions.ActionNoBlock;
import org.netbeans.jellytools.actions.AttachWindowAction;
import org.netbeans.jellytools.actions.CompileJavaAction;
import org.netbeans.jellytools.actions.CopyAction;
import org.netbeans.jellytools.actions.CutAction;
import org.netbeans.jellytools.actions.DeleteAction;
import org.netbeans.jellytools.actions.NewFileAction;
import org.netbeans.jellytools.actions.PasteAction;
import org.netbeans.jellytools.actions.ViewAction;
import org.netbeans.jellytools.modules.debugger.actions.ContinueAction;
import org.netbeans.jellytools.modules.debugger.actions.DebugJavaFileAction;
import org.netbeans.jellytools.modules.debugger.actions.FinishDebuggerAction;
import org.netbeans.jellytools.modules.debugger.actions.NewBreakpointAction;
import org.netbeans.jellytools.modules.debugger.actions.ToggleBreakpointAction;
import org.netbeans.jellytools.nodes.JavaNode;
import org.netbeans.jellytools.nodes.Node;
import org.netbeans.jellytools.nodes.SourcePackagesNode;

import org.netbeans.jemmy.ComponentChooser;
import org.netbeans.jemmy.EventTool;
import org.netbeans.jemmy.JemmyException;
import org.netbeans.jemmy.JemmyProperties;
import org.netbeans.jemmy.QueueTool;
import org.netbeans.jemmy.TestOut;
import org.netbeans.jemmy.TimeoutExpiredException;
import org.netbeans.jemmy.Waitable;
import org.netbeans.jemmy.Waiter;
import org.netbeans.jemmy.operators.JButtonOperator;
import org.netbeans.jemmy.operators.JCheckBoxOperator;
import org.netbeans.jemmy.operators.JDialogOperator;
import org.netbeans.jemmy.operators.JLabelOperator;
import org.netbeans.jemmy.operators.JRadioButtonOperator;
import org.netbeans.jemmy.operators.JTextFieldOperator;
import org.netbeans.jemmy.operators.JTreeOperator;
import org.netbeans.jemmy.operators.WindowOperator;
import org.netbeans.jemmy.util.PNGEncoder;

import org.netbeans.junit.Log;
import org.netbeans.junit.NbModuleSuite;
import org.openide.windows.Mode;
import org.openide.windows.TopComponent;
import org.openide.windows.WindowManager;

/**
 * Overall validation suite for IDE.
 *
 * @author Jiri Skrivanek
 */
public class PerfIDEValidation extends JellyTestCase {
    
    protected static final String PROJECT_LOCATION = System.getProperty("xtest.userdir");

    /** Need to be defined because of JUnit */
    public PerfIDEValidation(String name) {
        super(name);
    }
    
    public static Test suite() throws IOException {
        NbModuleSuite.Configuration conf = NbModuleSuite.createConfiguration(
            PerfIDECommitValidationTest.class
        ).clusters(".*").enableModules(".*").honorAutoloadEager(true)
        .failOnException(Level.WARNING)
        .failOnMessage(Level.SEVERE);
        
        PerfCountingSecurityManager.initWrites();
        
        //conf = conf.addTest("testReflectionUsage");  // too easy to break:
        conf = conf.addTest("testWriteAccess");
        //conf = conf.addTest("testInitGC");
        conf = conf.addTest("testMainMenu");
        conf = conf.addTest("testHelp");
        conf = conf.addTest("testOptions");
        conf = conf.addTest("testNewProject");
        conf = conf.addTest("testShortcuts"); // sample project must exist before testShortcuts
        conf = conf.addTest("testNewFile");
        conf = conf.addTest("testProjectsView");
        conf = conf.addTest("testFilesView");
        conf = conf.addTest("testEditor");
        conf = conf.addTest("testBuildAndRun");
        conf = conf.addTest("testDebugging");
        conf = conf.addTest("testPlugins"); //needs net connectivity
        conf = conf.addTest("testJUnit");  //needs JUnit installed in testPlugins
        conf = conf.addTest("testXML");
        conf = conf.addTest("testDb");
        conf = conf.addTest("testWindowSystem");
        //conf = conf.addTest("testGCDocuments");
        //conf = conf.addTest("testGCProjects");
        return NbModuleSuite.create(conf);
    }

    /** Setup called before every test case. */
    @Override
    public void setUp() {
        System.out.println("########  " + getName() + "  #######");
        // Close help window if any - it should not stay open between test cases.
        // Otherwise it can break next tests.
        closeHelpWindow();
    }

    /** Tear down called after every test case. */
    @Override
    public void tearDown() {
    }
    // name of sample project
    private static final String SAMPLE_PROJECT_NAME = "SampleProject"; // NOI18N
    // name of first sample package
    private static final String SAMPLE1_PACKAGE_NAME = "sample1"; //NOI18N
    // name of sample class
    private static final String SAMPLE1_CLASS_NAME = "SampleClass1"; // NOI18N
    // name of sample file
    private static final String SAMPLE1_FILE_NAME = SAMPLE1_CLASS_NAME + ".java"; // NOI18N
    // name of sample class 2
    private static final String SAMPLE2_CLASS_NAME = "SampleClass2"; // NOI18N
    // name of sample file 2
    private static final String SAMPLE2_FILE_NAME = SAMPLE2_CLASS_NAME + ".java"; // NOI18N

    public void testWriteAccess() throws Exception {
        String msg = "No writes during startup.\n"
                + "Writing any files to disk during start is inefficient and usualy unnecessary.\n"
                + "Consider using declarative registration in your layer.xml file, or delaying\n"
                + "the initialization of the whole subsystem till it is really used.\n"
                + "In case it is necessary to perform the write, you can modify the\n"
                + "'allowed-file-write.txt' file in ide.kit module. More details at\n"
                + "http://wiki.netbeans.org/FitnessViaWhiteAndBlackList";

        PerfCountingSecurityManager.assertCounts(msg, 0);
        // disable further collecting of
        PerfCountingSecurityManager.initialize("non-existent", PerfCountingSecurityManager.Mode.CHECK_READ, null);
    }

    /** Test creation of java project. 
     * - open New Project wizard from main menu (File|New Project)
     * - select Java Application project from Standard category
     * - in the next panel type project name and project location in
     * - finish the wizard
     * - wait until project appears in projects view
     * - wait classpath scanning finished
     */
    public void testNewJavaProject() {
        NewProjectWizardOperator.invoke().cancel();
        NewProjectWizardOperator npwo = NewProjectWizardOperator.invoke();
        // "Standard"
        String standardLabel = Bundle.getStringTrimmed("org.netbeans.modules.java.j2seproject.ui.wizards.Bundle", "Templates/Project/Standard");
        npwo.selectCategory(standardLabel);
        // "Java Application"
        String javaApplicationLabel = Bundle.getStringTrimmed("org.netbeans.modules.java.j2seproject.ui.wizards.Bundle", "template_app");
        npwo.selectProject(javaApplicationLabel);
        npwo.next();
        NewJavaProjectNameLocationStepOperator npnlso = new NewJavaProjectNameLocationStepOperator();
        npnlso.txtProjectName().setText(SAMPLE_PROJECT_NAME);
        npnlso.txtProjectLocation().setText(System.getProperty("netbeans.user")); // NOI18N
        npnlso.btFinish().pushNoBlock();
        npnlso.getTimeouts().setTimeout("ComponentOperator.WaitStateTimeout", 120000);
        npnlso.waitClosed();
        // wait project appear in projects view
        new ProjectsTabOperator().getProjectRootNode(SAMPLE_PROJECT_NAME);

        //disable the compile on save:
        ProjectsTabOperator.invoke().getProjectRootNode(SAMPLE_PROJECT_NAME).properties();
        // "Project Properties"
        String projectPropertiesTitle = Bundle.getStringTrimmed("org.netbeans.modules.java.j2seproject.ui.customizer.Bundle", "LBL_Customizer_Title");
        NbDialogOperator propertiesDialogOper = new NbDialogOperator(projectPropertiesTitle);
        // select "Compile" category
        String buildCategoryTitle = Bundle.getStringTrimmed("org.netbeans.modules.java.j2seproject.ui.customizer.Bundle", "LBL_Config_BuildCategory");
        String compileCategoryTitle = Bundle.getStringTrimmed("org.netbeans.modules.java.j2seproject.ui.customizer.Bundle", "LBL_Config_Build");
        new Node(new Node(new JTreeOperator(propertiesDialogOper), buildCategoryTitle), compileCategoryTitle).select();
        // actually disable the quick run:
        String compileOnSaveLabel = Bundle.getStringTrimmed("org.netbeans.modules.java.j2seproject.ui.customizer.Bundle", "CustomizerCompile.CompileOnSave");
        JCheckBox cb = JCheckBoxOperator.waitJCheckBox((Container) propertiesDialogOper.getSource(), compileOnSaveLabel, true, true);
        if (cb.isSelected()) {
            cb.doClick();
        }
        // confirm properties dialog
        propertiesDialogOper.ok();

        // wait classpath scanning finished
        PerfWatchProjects.waitScanFinished();
    }
    
    public void testNewJavaScriptProject() {
        NewProjectWizardOperator.invoke().cancel();
        NewProjectWizardOperator npwo = NewProjectWizardOperator.invoke();
        npwo.selectCategory("HTML5/JavaScript");
        npwo.selectProject("HTML5/JS Application");
        npwo.next();
        NewJavaProjectNameLocationStepOperator npnlso = new NewJavaProjectNameLocationStepOperator();
        npnlso.txtProjectName().setText("HTML5Project");
        npnlso.txtProjectLocation().setText(System.getProperty("netbeans.user")); // NOI18N
        npwo.finish();        
        // wait project appear in projects view
        new ProjectsTabOperator().getProjectRootNode("HTML5Project");
        // wait classpath scanning finished
        PerfWatchProjects.waitScanFinished();
    }
    
    /** Test new file wizard. 
     * - open New File wizard from main menu (File|New File)
     * - select sample project as target
     * - select Java Classes|Java Package file type
     * - in the next panel type package name in
     * - finish the wizard
     * - open New File wizard from context menu on created package node (New|File)
     * - select Java Classes|Java Main Class file type
     * - in the next panel type class name in
     * - finish the wizard
     * - check class is open in editor and close all opened documents
     */
    public void testNewFile() {
        // create a new package
        // "Java Classes"
        String javaClassesLabel = Bundle.getString("org.netbeans.modules.java.project.Bundle", "Templates/Classes");
        NewJavaFileWizardOperator.create(SAMPLE_PROJECT_NAME, javaClassesLabel, "Java Package", null, SAMPLE1_PACKAGE_NAME);
        // wait package node is created
        Node sample1Node = new Node(new SourcePackagesNode(SAMPLE_PROJECT_NAME), SAMPLE1_PACKAGE_NAME);

        // create a new classes

        NewFileWizardOperator.invoke(sample1Node, javaClassesLabel, "Java Main Class");
        NewJavaFileNameLocationStepOperator nameStepOper = new NewJavaFileNameLocationStepOperator();
        nameStepOper.setObjectName(SAMPLE1_CLASS_NAME);
        nameStepOper.finish();
        // check class is opened in Editor
        new EditorOperator(SAMPLE1_FILE_NAME);
        NewFileWizardOperator.invoke(sample1Node, javaClassesLabel, "Java Main Class");
        nameStepOper = new NewJavaFileNameLocationStepOperator();
        nameStepOper.setObjectName(SAMPLE2_CLASS_NAME);
        nameStepOper.finish();
        // check class is opened in Editor and then close all documents
        new EditorOperator(SAMPLE2_FILE_NAME).closeAllDocuments();
    }

    /** Test Projects view 
     * - expand source hierarchy and find sample class (SampleClass1.java)
     * - copy sample class and paste it to the same package
     * - confirm refactoring dialog
     * - verify creation of NewClass.java node
     * - cut NewClass.java
     * - paste it to another package
     * - confirm refactoring dialog
     * - delete NewClass.java node
     */
    public void testProjectsView() {
        ProjectsTabOperator.invoke();
        // needed for slower machines
        JemmyProperties.setCurrentTimeout("JTreeOperator.WaitNextNodeTimeout", 30000); // NOI18N
        SourcePackagesNode sourcePackagesNode = new SourcePackagesNode(SAMPLE_PROJECT_NAME);
        Node sample1Node = new Node(sourcePackagesNode, SAMPLE1_PACKAGE_NAME);
        Node sampleClass1Node = new Node(sample1Node, SAMPLE1_FILE_NAME);
        // test pop-up menu actions
        // "Copy"
        CopyAction copyAction = new CopyAction();
        copyAction.perform(sampleClass1Node);
        // "Paste"
        PasteAction pasteAction = new PasteAction();
        // "Refactor"
        String refactorItem = Bundle.getStringTrimmed("org.netbeans.modules.refactoring.spi.impl.Bundle", "LBL_Action");
        // "Copy..."
        String copyItem = Bundle.getStringTrimmed("org.netbeans.modules.refactoring.spi.impl.Bundle", "LBL_CopyAction");
        new ActionNoBlock(null, pasteAction.getPopupPath() + "|" + refactorItem + " " + copyItem).perform(sample1Node);

        String copyClassTitle = Bundle.getString("org.netbeans.modules.refactoring.java.ui.Bundle", "LBL_CopyClass");
        NbDialogOperator copyClassDialog = new NbDialogOperator(copyClassTitle);
        // "Refactor"
        String refactorLabel = Bundle.getStringTrimmed("org.netbeans.modules.refactoring.spi.impl.Bundle", "CTL_Finish");
        new JButtonOperator(copyClassDialog, refactorLabel).push();
        // refactoring is done asynchronously => need to wait until dialog dismisses
        copyClassDialog.waitClosed();

        Node newClassNode = new Node(sample1Node, "SampleClass11"); // NOI18N
        // "Cut"
        CutAction cutAction = new CutAction();
        cutAction.perform(newClassNode);
        // package created by default when the sample project was created
        Node sampleProjectPackage = new Node(sourcePackagesNode, SAMPLE_PROJECT_NAME.toLowerCase());
        // "Move..."
        String moveItem = Bundle.getStringTrimmed("org.netbeans.modules.refactoring.spi.impl.Bundle", "LBL_MoveAction");
        new ActionNoBlock(null, pasteAction.getPopupPath() + "|" + refactorItem + " " + moveItem).perform(sampleProjectPackage);
        new EventTool().waitNoEvent(1000);
        // confirm refactoring
        // "Move Class"
        String moveClassTitle = Bundle.getString("org.netbeans.modules.refactoring.java.ui.Bundle", "LBL_MoveClass");
        NbDialogOperator moveClassDialog = new NbDialogOperator(moveClassTitle);
        new JButtonOperator(moveClassDialog, refactorLabel).push();
        // refactoring is done asynchronously => need to wait until dialog dismisses
        try {
            moveClassDialog.waitClosed();
        } catch (TimeoutExpiredException e) {
            // try it once more
            moveClassDialog = new NbDialogOperator(moveClassTitle);
            new JButtonOperator(moveClassDialog, refactorLabel).push();
        }
        // "Delete"
        newClassNode = new Node(sampleProjectPackage, "SampleClass11"); // NOI18N
        new EventTool().waitNoEvent(2000);
        new DeleteAction().perform(newClassNode);
        DeleteAction.confirmDeletion();
    }

    /** Test Files view 
     * - expand files hierarchy and find sample class (SampleClass1.java) 
     * and select main method node.
     */
    public void testFilesView() {
        FilesTabOperator filesTabOper = FilesTabOperator.invoke();
        // needed for slower machines
        JemmyProperties.setCurrentTimeout("JTreeOperator.WaitNextNodeTimeout", 30000); // NOI18N
        Node sourcePackagesNode = new Node(filesTabOper.getProjectNode(SAMPLE_PROJECT_NAME), "src"); // NOI18N
        Node sample1Node = new Node(sourcePackagesNode, SAMPLE1_PACKAGE_NAME); // NOI18N
        Node sampleClass1Node = new Node(sample1Node, SAMPLE1_FILE_NAME);
        // It is possible to test also pop-up menu actions as in testProjectsView, but
        // it is redundant IMO
    }

    /** Test of DB module.
     * It only tests whether the Databases node is present in Runtime view, 
     * Add Driver action is enabled on Drivers node and Connect action is available
     * on default JDBC-ODBC Bridge node.
     * - find Databases|Drivers node in Runtime tab
     * - open and close Add Driver dialog from context menu on Drivers node
     * - open and close Connect Using dialog on JDBC-ODBC Bridge node
     */
    public void testDb() {
        // "Databases"
        String databasesLabel = Bundle.getString("org.netbeans.modules.db.explorer.node.Bundle", "RootNode_DISPLAYNAME");
        Node databasesNode = new Node(RuntimeTabOperator.invoke().getRootNode(), databasesLabel);
        // "Please wait..."
        String waitNodeLabel = Bundle.getString("org.openide.nodes.Bundle", "LBL_WAIT");
        // wait until the wait node dismiss and after that start waiting for Drivers node
        // (see issue http://www.netbeans.org/issues/show_bug.cgi?id=43910 - Creation of 
        // children under Databases node is not properly synchronized)
        try {
            databasesNode.waitChildNotPresent(waitNodeLabel);
        } catch (JemmyException e) {
            // Ignore and try to continue. Sometimes it happens "Please, wait" node
            // is still available (maybe some threading issue).
            log("Timeout expired: " + e.getMessage());
        }
        // "Drivers"
        String driversLabel = Bundle.getString("org.netbeans.modules.db.explorer.node.Bundle", "DriverListNode_DISPLAYNAME");
        Node driversNode = new Node(RuntimeTabOperator.invoke().getRootNode(), databasesLabel + "|" + driversLabel);
        // "Add Driver ..."
        String addDriverItem = Bundle.getString("org.netbeans.modules.db.explorer.action.Bundle", "AddNewDriver");
        // open a dialog to add a new JDBC driver
        new ActionNoBlock(null, addDriverItem).perform(driversNode);
        String addDriverTitle = Bundle.getString("org.netbeans.modules.db.explorer.dlg.Bundle", "AddDriverDialogTitle");
        new NbDialogOperator(addDriverTitle).cancel();

        // wait until the wait node dismiss and after that start waiting for JDBC_ODBC Bridge node
        // (see issue http://www.netbeans.org/issues/show_bug.cgi?id=43910 - Creation of 
        // children under Databases node is not properly synchronized)
        try {
            driversNode.waitChildNotPresent(waitNodeLabel);
        } catch (JemmyException e) {
            // Ignore and try to continue. Sometimes it happens "Please, wait" node
            // is still available (maybe some threading issue).
            log("Timeout expired: " + e.getMessage());
        }
        // node Java DB (Embedded) should be present always
        Node javaDBNode = new Node(driversNode, "Java DB (Embedded"); // NOI18N
        // open a dialog to create a new connection
        new ActionNoBlock(null, "Connect Using...").perform(javaDBNode);
        // "New Connection Wizard"
        String connectionDialogTitle = Bundle.getString("org.netbeans.modules.db.explorer.dlg.Bundle", "PredefinedWizard.WizardTitle");
        new NbDialogOperator(connectionDialogTitle).cancel();
    }

    /** Test Help 
     * - open Help window from main menu (Help|Help Contents)
     */
    public void testHelp() {
        // increasing time because opening of help window can last longer on slower machines
        JemmyProperties.setCurrentTimeout("JMenuOperator.PushMenuTimeout", 60000);
        // open "Help|Contents"
        HelpOperator helpOper = HelpOperator.invoke();
        // check help window opened
        // title is "Help - All"
        helpOper.close();
    }

    /** Test Main Menu 
     * - open and close New Project wizard (main menu item File|New Project...)
     * - open and close Javadoc Index Search top component (main menu item Tools|Javadoc Index Search)
     */
    public void testMainMenu() {
        // open and close New Project wizard
        NewProjectWizardOperator.invoke().close();

        //workaround for issue 166989
        if (System.getProperty("os.name").equals("Mac OS X")) {
            try {
                new NbDialogOperator("Warning").close();
            } catch (TimeoutExpiredException e) {
            }
        }
    }

    /** Test global shortcuts. 
     * - open and close new file wizard (CTRL+N)
     * - open and close Javadoc Index Search top component (Shift+F1)
     * - open and close new breakpoint dialog (Ctrl+Shift+F8)
     */
    public void testShortcuts() {
        // test global shortcuts
        // open new wizard (Ctrl+N)
        Node node = new SourcePackagesNode(SAMPLE_PROJECT_NAME);
        // push Escape key to ensure there is no thing blocking shortcut execution
        MainWindowOperator.getDefault().pushKey(KeyEvent.VK_ESCAPE);
        NewFileAction newFileAction = new NewFileAction();
        try {
            newFileAction.performShortcut(node);
            new NewFileWizardOperator().close();
            // On some linux it may happen autorepeat is activated and it 
            // opens dialog multiple times. So, we need to close all modal dialogs.
            // See issue http://www.netbeans.org/issues/show_bug.cgi?id=56672.
            closeAllModal();
        } catch (TimeoutExpiredException e) {
            // need to be realiable test => repeat action once more to be sure it is problem in IDE
            // this time use events instead of Robot
            node.select();
            MainWindowOperator.getDefault().pushKey(
                    newFileAction.getKeyStrokes()[0].getKeyCode(),
                    newFileAction.getKeyStrokes()[0].getModifiers());
            new NewFileWizardOperator().close();
        }
        // open Javadoc Index Search (Shift+F1)
        // "Javadoc Index Search"
        String javadocTitle = Bundle.getString("org.netbeans.modules.javadoc.search.Bundle",
                "CTL_SEARCH_WindowTitle");
        Action searchAction = new Action(null, null, KeyStroke.getKeyStroke(KeyEvent.VK_F1, KeyEvent.SHIFT_MASK));
        try {
            searchAction.perform(MainWindowOperator.getDefault());
            new TopComponentOperator(javadocTitle).close();
        } catch (TimeoutExpiredException e) {
            // need to be realiable test => repeat action once more to be sure it is problem in IDE
            // this time use events instead of Robot
            MainWindowOperator.getDefault().pushKey(KeyEvent.VK_F1, KeyEvent.SHIFT_MASK);
            new TopComponentOperator(javadocTitle).close();
        }
        // open new breakpoint dialog (Ctrl+Shift+F8)
        String newBreakpointTitle = Bundle.getString("org.netbeans.modules.debugger.ui.actions.Bundle", "CTL_Breakpoint_Title");
        NewBreakpointAction newBreakpointAction = new NewBreakpointAction();
        try {
            newBreakpointAction.performShortcut(MainWindowOperator.getDefault());
            new NbDialogOperator(newBreakpointTitle).close();
            // On some linux it may happen autorepeat is activated and it 
            // opens dialog multiple times. So, we need to close all modal dialogs.
            // See issue http://www.netbeans.org/issues/show_bug.cgi?id=56672.
            closeAllModal();
        } catch (TimeoutExpiredException e) {
            // need to be realiable test => repeat action once more to be sure it is problem in IDE
            // this time use events instead of Robot
            MainWindowOperator.getDefault().pushKey(
                    newBreakpointAction.getKeyStrokes()[0].getKeyCode(),
                    newBreakpointAction.getKeyStrokes()[0].getModifiers());
            new NbDialogOperator(newBreakpointTitle).close();
        }
    }

    /** Test Source Editor
     * - opens sample class in Editor (context menu Open on the node)
     * - type abbreviation 'sout' into main method and then 'Hello'
     * - verify it is written 'System.out.println("Hello");'
     * - select the text and call copy from editor's context menu
     * - insert dummy text at next line , select it and paste the text in the clipboard
     * - select second 'Hello' and delete it by context menu
     * - insert 'Good bye' instead
     * - select fourth line, cut it and paste it at line 3
     */
    public void testEditor() {
        // open sample file in Editor
        SourcePackagesNode sourcePackagesNode = new SourcePackagesNode(SAMPLE_PROJECT_NAME);
        Node sample1Node = new Node(sourcePackagesNode, SAMPLE1_PACKAGE_NAME);
        JavaNode sampleClass1Node = new JavaNode(sample1Node, SAMPLE1_FILE_NAME);
        sampleClass1Node.open();
        // find open file in editor
        EditorOperator eo = new EditorOperator(SAMPLE1_FILE_NAME);
        eo.setCaretPosition("public static void main", true);
        int insertLine = eo.getLineNumber() + 2;
        eo.insert("\n", insertLine, 1); // NOI18N
        // Need to disable verification because shortcut "sout" is replaced
        // by "System.out.println("");" and "sout" is not found in Editor
        eo.setCaretPositionToLine(insertLine);
        eo.txtEditorPane().setVerification(false);
        eo.txtEditorPane().typeText("sout"); // NOI18N
        eo.txtEditorPane().typeKey('\t');
        eo.txtEditorPane().setVerification(true);
        eo.insert("Hello"); // NOI18N
        //eo.insert("System.out.println(\"Hello\");\n", insertLine+1, 1); // NOI18N
        final String textToCopy = "System.out.println(\"Hello\");"; // NOI18N
        eo.select(textToCopy);
        int oldDispatchingModel = JemmyProperties.getCurrentDispatchingModel();
        // "Copy"
        CopyAction copyAction = new CopyAction();
        try {
            copyAction.perform(eo);
        } catch (TimeoutExpiredException e) {
            // if not succed try it second time in Robot mode
            JemmyProperties.setCurrentDispatchingModel(JemmyProperties.ROBOT_MODEL_MASK);
            copyAction.perform(eo);
        } finally {
            // set previous dispatching model
            JemmyProperties.setCurrentDispatchingModel(oldDispatchingModel);
        }
        // wait until clipboard contains text to copy
        try {
            new Waiter(new Waitable() {

                @Override
                public Object actionProduced(Object obj) {
                    try {
                        String text = Toolkit.getDefaultToolkit().getSystemClipboard().
                                getContents(null).getTransferData(DataFlavor.stringFlavor).toString();
                        return textToCopy.equals(text) ? Boolean.TRUE : null;
                    } catch (UnsupportedFlavorException e) {
                        // The following exception can be thrown when clipboard is empty.
                        // java.awt.datatransfer.UnsupportedFlavorException: Unicode String
                        // at org.openide.util.datatransfer.ExTransferable$Empty.getTransferData(ExTransferable.java:461)
                        // Ignore this exception.
                        return null;
                    } catch (IOException ioe) {
                        throw new JemmyException("Failed getting clipboard content.", ioe);
                    }
                }

                @Override
                public String getDescription() {
                    return ("Clipboard contains " + textToCopy); // NOI18N
                }
            }).waitAction(null);
        } catch (Exception ie) {
            throw new JemmyException("Interrupted.", ie);
        }
        eo.insert("int xxxx;\n", insertLine + 1, 1); // NOI18N
        eo.select("int xxxx;"); // NOI18N
        PasteAction pasteAction = new PasteAction();
        try {
            pasteAction.perform(eo);
        } catch (TimeoutExpiredException e) {
            // if not succed try it second time in Robot mode
            JemmyProperties.setCurrentDispatchingModel(JemmyProperties.ROBOT_MODEL_MASK);
            pasteAction.perform(eo);
        } finally {
            // set previous dispatching model
            JemmyProperties.setCurrentDispatchingModel(oldDispatchingModel);
        }
        eo.select("Hello", 1); // NOI18N
        // "Delete"
        DeleteAction deleteAction = new DeleteAction();
        deleteAction.performMenu(eo);
        // wait Hello is deleted
        eo.txtEditorPane().waitText("System.out.println(\"\");"); // NOI18N
        eo.insert("Good bye"); // NOI18N
        // test cut action
        eo.select(3);
        // "Cut"
        CutAction cutAction = new CutAction();
        try {
            cutAction.perform(eo);
        } catch (TimeoutExpiredException e) {
            // if not succed try it second time in Robot mode
            JemmyProperties.setCurrentDispatchingModel(JemmyProperties.ROBOT_MODEL_MASK);
            cutAction.perform(eo);
        } finally {
            // set previous dispatching model
            JemmyProperties.setCurrentDispatchingModel(oldDispatchingModel);
        }
        // need to wait a little until editor content is refreshed after cut action
        new EventTool().waitNoEvent(500);
        // select from column 1 to 2 at line 3 
        eo.select(2, 1, 2);
        try {
            pasteAction.perform(eo);
        } catch (TimeoutExpiredException e) {
            // if not succed try it second time in Robot mode
            JemmyProperties.setCurrentDispatchingModel(JemmyProperties.ROBOT_MODEL_MASK);
            pasteAction.perform(eo);
        } finally {
            // set previous dispatching model
            JemmyProperties.setCurrentDispatchingModel(oldDispatchingModel);
        }
    }

    /** Test build and run.
     * - select sample class node and call "Build|Compile "SampleClass1.java"" main menu item
     * - wait until compilation finishes (track status bar)
     * - select sample class node and call "Run|Run File|Run "SampleClass1.java"" main menu item
     * - wait until run finishes
     * - from context menu set sample project as main project
     * - call "Build|Build Main Project" main menu item
     * - wait until build finishes
     * - call "Run|Run Main Project" main menu item
     * - wait until run finishes
     */
    public void testBuildAndRun() {
        SourcePackagesNode sourcePackagesNode = new SourcePackagesNode(SAMPLE_PROJECT_NAME);
        Node sample1Node = new Node(sourcePackagesNode, SAMPLE1_PACKAGE_NAME);
        JavaNode sampleClass1Node = new JavaNode(sample1Node, SAMPLE1_FILE_NAME);
        // increase timeout to 60 seconds
        MainWindowOperator.getDefault().getTimeouts().setTimeout("Waiter.WaitingTime", 60000);
        // start to track Main Window status bar
        MainWindowOperator.StatusTextTracer stt = MainWindowOperator.getDefault().getStatusTextTracer();
        stt.start();
        // call Build|Compile main menu item
        new CompileJavaAction().perform(sampleClass1Node);
        // "SampleProject (compile-single)"
        String compileSingleTarget = Bundle.getString(
                "org.apache.tools.ant.module.run.Bundle",
                "TITLE_output_target",
                new Object[]{SAMPLE_PROJECT_NAME, null, "compile-single"});  // NOI18N
        // "Finished building SampleProject (compile-single)"
        String finishedCompileSingleLabel = Bundle.getString(
                "org.apache.tools.ant.module.run.Bundle",
                "FMT_finished_target_status",
                new String[]{compileSingleTarget});
        // wait message "Finished building SampleProject (compile-single)"
        stt.waitText(finishedCompileSingleLabel);        

        // "Run"
        // TODO bundle property name should be changed back to Menu/RunProject after updating bundle
        String runItem = Bundle.getStringTrimmed("org.netbeans.modules.project.ui.Bundle", "Menu/BuildProject");
        // "Run File"
        String runFileItem = Bundle.getStringTrimmed("org.netbeans.modules.project.ui.actions.Bundle",
                "LBL_RunSingleAction_Name",
                new Object[]{new Integer(1), SAMPLE1_FILE_NAME});
        // call "Run|Run File|Run "SampleClass1.java""
        new Action(runItem + "|" + runFileItem, null).perform(sampleClass1Node);
        // "SampleProject (run-single)"
        String runSingleTarget = Bundle.getString(
                "org.apache.tools.ant.module.run.Bundle",
                "TITLE_output_target",
                new Object[]{SAMPLE_PROJECT_NAME, null, "run-single"});  // NOI18N
        // "Finished building SampleProject (run-single)"
        String finishedRunSingleLabel = Bundle.getString(
                "org.apache.tools.ant.module.run.Bundle",
                "FMT_finished_target_status",
                new String[]{runSingleTarget});
        // wait message "Finished building SampleProject (run-single)"
        stt.waitText(finishedRunSingleLabel); // NOI18N
        // check Hello and Good bye was printed out to the output window

        OutputTabOperator outputOper = new OutputTabOperator("run-single"); //NOI18N
        outputOper.waitText("Hello"); //NOI18N
        outputOper.waitText("Good bye"); //NOI18N

        // "Run"
        String buildItem = Bundle.getStringTrimmed("org.netbeans.modules.project.ui.Bundle", "Menu/BuildProject");
        // "Build Main Project"
        String buildMainProjectItem = Bundle.getStringTrimmed("org.netbeans.modules.project.ui.actions.Bundle", "LBL_BuildMainProjectAction_Name");
        // call "Run|Build Main Project" main menu item
        new Action(buildItem + "|" + buildMainProjectItem, null).perform();
        // "SampleProject (jar)"
        String jarTarget = Bundle.getString(
                "org.apache.tools.ant.module.run.Bundle",
                "TITLE_output_target",
                new Object[]{SAMPLE_PROJECT_NAME, null, "jar"});  // NOI18N
        // "Finished building SampleProject (jar)"
        String finishedJarLabel = Bundle.getString(
                "org.apache.tools.ant.module.run.Bundle",
                "FMT_finished_target_status",
                new String[]{jarTarget});
        // wait message "Finished building SampleProject (jar)"
        stt.waitText(finishedJarLabel);

        // Run Main Project
        String runMainProjectItem = Bundle.getStringTrimmed("org.netbeans.modules.project.ui.actions.Bundle", "LBL_RunMainProjectAction_Name");
        // call "Run|Run Main Project" main menu item
        new Action(runItem + "|" + runMainProjectItem, null).perform();
        // "SampleProject (run)"
        String runTarget = Bundle.getString(
                "org.apache.tools.ant.module.run.Bundle",
                "TITLE_output_target",
                new Object[]{SAMPLE_PROJECT_NAME, null, "run"});  // NOI18N
        // "Finished building SampleProject (run)"
        String finishedRunLabel = Bundle.getString(
                "org.apache.tools.ant.module.run.Bundle",
                "FMT_finished_target_status",
                new String[]{runTarget});
        // wait message "Finished building SampleProject (run)"
        stt.waitText(finishedRunLabel);

        stt.stop();
    }

    /** Test JUnit support
     * - add methods to sample class
     * - from context menu on sample class node call "Tools|Create JUnit Tests" item
     * - confirm Create Tests dialog
     * - select "JUnit 3.x" in "Select JUnit Version" dialog
     * - click "Select" button to confirm dialog
     * - find generated test under "Test Packages"
     * - check whether test was open in editor and if includes test of public, 
     * protected, default but not private methods
     * - close the test
     * - select sample class
     * - call "Navigate|Go to Test" main menu item
     * - check test class is opened in editor
     * - run single test from main menu "Run|Run File|Test SampleClass2.java"
     * - check status bar that test was executed
     * - run test project from main menu "Run|Test SampleProject"
     * - check status bar that test was executed
     * - from context menu on sample package call "Tools|Create JUnit Tests" item
     * - confirm Create Tests dialog
     * - find generated suite under "Test Packages"
     * - open the suite class and check if contains generated test class
     * - close all documents in editor
     */
    public void testJUnit() throws InterruptedException {
        // open sample file in Editor
        SourcePackagesNode sourcePackagesNode = new SourcePackagesNode(SAMPLE_PROJECT_NAME);
        Node sample1Node = new Node(sourcePackagesNode, SAMPLE1_PACKAGE_NAME);
        JavaNode sampleClass2Node = new JavaNode(sample1Node, SAMPLE2_FILE_NAME);
        sampleClass2Node.open();
        // find open sample file in editor
        EditorOperator eo = new EditorOperator(SAMPLE2_FILE_NAME);
        eo.setCaretPosition("public static void main", true);
        int insertLine = eo.getLineNumber() + 3;
        // add methods declarations to sample file
        String publicMethod = "\n    public void publicMethod() {\n    }\n";  // NOI18N
        eo.insert(publicMethod, insertLine, 1);
        String privateMethod = "\n    private void privateMethod() {\n    }\n";  //NOI18N
        eo.insert(privateMethod, insertLine + 3, 1);
        String protectedMethod = "\n    protected void protectedMethod() {\n    }\n";  //NOI18N
        eo.insert(protectedMethod, insertLine + 3, 1);
        String defaultMethod = "\n    void defaultMethod() {\n    }\n";  //NOI18N
        eo.insert(defaultMethod, insertLine + 3, 1);
        eo.save();
        // need to wait until new methods are parsed
        PerfWatchProjects.waitScanFinished();

        // "Tools"
        String toolsItem = Bundle.getStringTrimmed("org.netbeans.core.ui.resources.Bundle", "Menu/Tools"); // NOI18N
        ActionNoBlock createTestsAction = new ActionNoBlock(null, toolsItem + "|Create/Update Tests");
        createTestsAction.perform(sampleClass2Node);
        // "Create Tests"
        String createTestsTitle = Bundle.getString("org.netbeans.modules.junit.Bundle", "JUnitCfgOfCreate.Title");
        new NbDialogOperator(createTestsTitle).ok();
        // "Select JUnit Version"
        String selectJUnitVersionTitle = Bundle.getString("org.netbeans.modules.junit.Bundle", "LBL_title_select_generator");
        NbDialogOperator selectVersionOper = new NbDialogOperator(selectJUnitVersionTitle);
        // "JUnit 3.x"
        String version3Label = Bundle.getStringTrimmed("org.netbeans.modules.junit.Bundle", "LBL_JUnit3_generator");
        new JRadioButtonOperator(selectVersionOper, version3Label).push();
        // "Select"
        String selectLabel = Bundle.getStringTrimmed("org.netbeans.modules.junit.Bundle", "LBL_Select");
        new JButtonOperator(selectVersionOper, selectLabel).pushNoBlock();

        // wait until test node is created
        // "Test Packages"
        String testPackagesLabel = Bundle.getString("org.netbeans.modules.java.j2seproject.Bundle", "NAME_test.src.dir");
        Node testPackagesNode = new Node(new ProjectsTabOperator().getProjectRootNode(SAMPLE_PROJECT_NAME), testPackagesLabel);
        // Test Packages|sample1|SampleClass1Test.java
        new JavaNode(testPackagesNode, SAMPLE1_PACKAGE_NAME + "|" + SAMPLE2_CLASS_NAME + "Test.java"); // NOI18N

        // check default, protected and public method tests created and private is not created
        EditorOperator eoTest = new EditorOperator(SAMPLE2_CLASS_NAME + "Test.java");    // NOI18N
        // wait code is generated
        eoTest.txtEditorPane().waitText("testDefaultMethod"); // NOI18N
        eoTest.txtEditorPane().waitText("testProtectedMethod"); // NOI18N
        eoTest.txtEditorPane().waitText("testPublicMethod"); // NOI18N
        assertFalse("Created test should not include test of private method.", eoTest.contains("testPrivateMethod")); // NOI18N
        eoTest.close();

        // go to test
        // "Navigate"
        String navigateItem = Bundle.getStringTrimmed("org.netbeans.core.ui.resources.Bundle", "Menu/GoTo"); // NOI18N
        // "Go to Test"
        String goToTestItem = Bundle.getString("org.netbeans.modules.junit.Bundle", "LBL_Action_GoToTest");  // NOI18N
        // go to test ("Navigate|Go to Test") - main menu action
        Action gotoTestAction = new Action(navigateItem + "|" + goToTestItem, null);
        gotoTestAction.perform(sampleClass2Node);
        // wait until test is opened in editor
        new EditorOperator(SAMPLE2_CLASS_NAME + "Test.java");    // NOI18N

        // run generated test

        // "Run" 
        // TODO bundle property name should be changed back to Menu/RunProject after updating bundle
        String runItem = Bundle.getStringTrimmed("org.netbeans.modules.project.ui.Bundle", "Menu/BuildProject");
        // "Test File"
        String testFileItem = Bundle.getStringTrimmed("org.netbeans.modules.project.ui.actions.Bundle",
                "LBL_TestSingleAction_Name",
                new Object[]{new Integer(1), SAMPLE2_FILE_NAME});
        // "Test Project"
        String testProjectItem = Bundle.getStringTrimmed("org.netbeans.modules.project.ui.actions.Bundle",
                "LBL_TestProjectAction_Name",
                new Object[]{new Integer(1), SAMPLE_PROJECT_NAME});

        // increase timeout to 60 seconds
        MainWindowOperator.getDefault().getTimeouts().setTimeout("Waiter.WaitingTime", 60000); // NOI18N
        // start to track Main Window status bar
        MainWindowOperator.StatusTextTracer stt = MainWindowOperator.getDefault().getStatusTextTracer();
        stt.start();
        // call "Run|Test "SampleClass2.java""
        new Action(runItem + "|" + testFileItem, null).perform(sampleClass2Node);

        // check status line
        // "SampleProject (test-single)"
        String testSingleTarget = Bundle.getString(
                "org.apache.tools.ant.module.run.Bundle",
                "TITLE_output_target",
                new Object[]{SAMPLE_PROJECT_NAME, null, "test-single"});  // NOI18N
        String testTarget = Bundle.getString(
                "org.apache.tools.ant.module.run.Bundle",
                "TITLE_output_target",
                new Object[]{SAMPLE_PROJECT_NAME, null, "test"});  // NOI18N
        // "Build of SampleProject (test-single) failed."
        String failedMessage = Bundle.getString(
                "org.apache.tools.ant.module.run.Bundle",
                "FMT_target_failed_status",
                new Object[]{testSingleTarget});
        // wait message "Build of SampleProject (test-single) failed."
        stt.waitText(failedMessage);

        // call "Run|Test "SampleProject""
        new Action(runItem + "|" + testProjectItem, null).perform(sampleClass2Node);
        // "Finished building SampleProject (test)"
        String finishedMessage = Bundle.getString(
                "org.apache.tools.ant.module.run.Bundle",
                "FMT_finished_target_status",
                new Object[]{testTarget});
        // wait message "Finished building SampleProject (test)"
        stt.waitText(finishedMessage);
        stt.stop();

        // test JUnit on folder
        createTestsAction.perform(sample1Node);
        new NbDialogOperator(createTestsTitle).ok();
        // wait until test node is created
        // Test Packages|sample1|Sample1Suite.java
        JavaNode suiteNode = new JavaNode(testPackagesNode, SAMPLE1_PACKAGE_NAME + "|Suite.java"); // NOI18N
        suiteNode.open();
        // check suite is open in editor and it conteins generated test class
        assertTrue("Created suite should include test of public method.",
                new EditorOperator("Suite").contains(SAMPLE2_CLASS_NAME + "Test")); // NOI18N
        EditorOperator.closeDiscardAll();
    }

    /** Test Debugging
     * - find sample class in editor
     * - select text 'System.out.println("Hello");' and push Shift+F8 to toggle breakpoint
     * - select text 'System.out.println("Good bye");' and call 'Toggle Breakpoint" context menu item
     * - run debugger from main menu ("Run "SampleClass1.java" in  Debugger")
     * - wait until first breakpoint is reached and call Continue from main menu
     * - wait until second breakpoint is reached and check 'Hello' is printed to output
     * - finish debugger by main menu action (Finish Debugger Session)
     * - delete sample class
     */
    public void testDebugging() throws Throwable {
        // Status bar tracer
        MainWindowOperator.StatusTextTracer stt = MainWindowOperator.getDefault().getStatusTextTracer();
        SourcePackagesNode sourcePackagesNode = new SourcePackagesNode(SAMPLE_PROJECT_NAME);
        JavaNode sampleClass1Node = new JavaNode(sourcePackagesNode, SAMPLE1_PACKAGE_NAME + "|" + SAMPLE1_FILE_NAME);
        // flag to stop debugger in finally
        boolean debuggerStarted = false;
        try {
            // find sample file in Editor
            EditorOperator eo = new EditorOperator(SAMPLE1_FILE_NAME);
            eo.setCaretPosition("public static void main", true);
            final int insertLine = eo.getLineNumber() + 2;

            // if file not contains brpText from previous test cases, insert it
            String brpText = "System.out.println(\"Hello\");"; // NOI18N
            if (!eo.contains(brpText)) {
                eo.insert(brpText + "\n", insertLine, 1);
            }
            eo.select(brpText);

            ToggleBreakpointAction toggleBreakpointAction = new ToggleBreakpointAction();
            try {
                // toggle breakpoint via Shift+F8
                toggleBreakpointAction.performShortcut(eo);
                waitBreakpoint(eo, insertLine);
            } catch (TimeoutExpiredException e) {
                // need to be realiable test => repeat action once more to be sure it is problem in IDE
                // this time use events instead of Robot
                MainWindowOperator.getDefault().pushKey(
                        toggleBreakpointAction.getKeyStrokes()[0].getKeyCode(),
                        toggleBreakpointAction.getKeyStrokes()[0].getModifiers());
                waitBreakpoint(eo, insertLine);
            }

            // if file not contains second brpText from previous test cases, insert it
            brpText = "System.out.println(\"Good bye\");"; // NOI18N
            if (!eo.contains(brpText)) {
                eo.insert(brpText + "\n", insertLine + 1, 1);
            }
            eo.select(brpText);
            // toggle breakpoint via pop-up menu
            // clickForPopup(0, 0) used in the past sometimes caused that menu
            // was opened outside editor area because editor roll up after 
            // text was selected
            toggleBreakpointAction.perform(eo.txtEditorPane());
            // wait second breakpoint established
            waitBreakpoint(eo, insertLine + 1);
            // start to track Main Window status bar
            stt.start();
            debuggerStarted = true;
            // start debugging
            new DebugJavaFileAction().performMenu(sampleClass1Node);
            // check the first breakpoint reached
            // wait status text "Thread main stopped at SampleClass1.java:"
            // increase timeout to 60 seconds
            MainWindowOperator.getDefault().getTimeouts().setTimeout("Waiter.WaitingTime", 60000);
            String labelLine = Bundle.getString("org.netbeans.modules.debugger.jpda.ui.Bundle",
                    "CTL_Thread_stopped",
                    new String[]{"main", SAMPLE1_FILE_NAME, null, String.valueOf(insertLine)}); // NOI18N
            stt.waitText(labelLine);
            // continue debugging
            new ContinueAction().perform();
            // check the second breakpoint reached
            // wait status text "Thread main stopped at SampleClass1.java:"
            String labelLine1 = Bundle.getString("org.netbeans.modules.debugger.jpda.ui.Bundle",
                    "CTL_Thread_stopped",
                    new String[]{"main", SAMPLE1_FILE_NAME, null, String.valueOf(insertLine)}); // NOI18N
            stt.waitText(labelLine1);
            // check "Hello" was printed out in Output
            OutputTabOperator oto = new OutputTabOperator("debug-single"); // NOI18N
            // wait until text Hello is not written in to the Output
            oto.waitText("Hello"); // NOI18N
        } catch (Throwable th) {
            try {
                // capture screen before cleanup in finally clause is completed
                PNGEncoder.captureScreen(getWorkDir().getAbsolutePath() + File.separator + "screenBeforeCleanup.png");
            } catch (Exception e1) {
                // ignore it
            }
            th.printStackTrace(getLog());
            throw th;
        } finally {
            if (debuggerStarted) {
                // finish debugging
                new FinishDebuggerAction().perform();
                // check status line
                // "SampleProject (debug-single)"
                String outputTarget = Bundle.getString(
                        "org.apache.tools.ant.module.run.Bundle",
                        "TITLE_output_target",
                        new Object[]{SAMPLE_PROJECT_NAME, null, "debug-single"});  // NOI18N
                // "Finished building SampleProject (debug-single)"
                String finishedMessage = Bundle.getString(
                        "org.apache.tools.ant.module.run.Bundle",
                        "FMT_finished_target_status",
                        new Object[]{outputTarget});
                stt.waitText(finishedMessage);
            }
            stt.stop();
            // delete sample class
            sampleClass1Node.delete();
            String confirmTitle = Bundle.getString("org.netbeans.modules.refactoring.java.ui.Bundle", "LBL_SafeDel_Delete"); // NOI18N
            String confirmButton = UIManager.getDefaults().get("OptionPane.okButtonText").toString(); // NOI18N
            // "Confirm Object Deletion"
            new JButtonOperator(new NbDialogOperator(confirmTitle), confirmButton).push();
        }
    }

    /** Test Options  
     * - open Options window from main menu Tools|Options
     * - select Editor category
     * - select Fonts & Colors category
     * - select Keymap category
     * - select General category
     * - pick Manual Proxy Setting
     * - set Proxy Host to emea-proxy.uk.oracle.com
     * - set Proxy Port to 80
     * - click OK to confirm and close Options window
     */
    public void testOptions() {
        OptionsOperator optionsOper = OptionsOperator.invoke();
        optionsOper.selectEditor();
        optionsOper.selectFontAndColors();
        optionsOper.selectKeymap();
        optionsOper.selectGeneral();
        // "Manual Proxy Setting"
        String hTTPProxyLabel = Bundle.getStringTrimmed(
                "org.netbeans.core.ui.options.general.Bundle", "CTL_Use_HTTP_Proxy");
        new JRadioButtonOperator(optionsOper, hTTPProxyLabel).push();
        // "HTTP Proxy:"
        String proxyHostLabel = Bundle.getStringTrimmed(
                "org.netbeans.core.ui.options.general.Bundle", "CTL_Proxy_Host");
        JLabelOperator jloHost = new JLabelOperator(optionsOper, proxyHostLabel);
        new JTextFieldOperator((JTextField) jloHost.getLabelFor()).setText("www-proxy.uk.oracle.com"); // NOI18N
        // "Port:"
        String proxyPortLabel = Bundle.getStringTrimmed(
                "org.netbeans.core.ui.options.general.Bundle", "CTL_Proxy_Port");
        JLabelOperator jloPort = new JLabelOperator(optionsOper, proxyPortLabel);
        new JTextFieldOperator((JTextField) jloPort.getLabelFor()).setText("80"); // NOI18N
        optionsOper.ok();
    }

    /** Test XML
     * - open "Tools|DTDs and XML Schemas"
     * - select "NetBeans Catalog|-//DTD XMLCatalog//EN"
     * - call "View" on it
     * - check it is opened in editor and close it
     * - close "DTDs and XML Schemas" dialog
     * - create XML file
     * - call "Check XML" on xml node
     * - find and close output tab
     * - call "Validate XML" on xml node
     * - find and close output tab
     * - call "Generate DTD" on xml node
     * - set name and confirm the dialog
     * - wait until dtd is opened in editor and close it
     * - call "Check DTD" on dtd node
     * - find and close output tab
     * - call "Generate DOM Tree Scanner" on dtd node
     * - set name and confirm the dialog
     * - wait until scanner is opened in editor and close it
     */
    public void testXML() {
        // check XML Entity Catalogs

        // "Tools"
        String toolsItem = Bundle.getStringTrimmed("org.netbeans.core.ui.resources.Bundle", "Menu/Tools"); // NOI18N
        // "DTDs and XML Schemas"
        String dtdsItem = Bundle.getStringTrimmed("org.netbeans.modules.xml.catalog.Bundle", "LBL_CatalogAction_Name");
        new Action(toolsItem + "|" + dtdsItem, null).perform();
        // "DTDs and XML Schemas"
        String dtdsTitle = Bundle.getString("org.netbeans.modules.xml.catalog.Bundle", "LBL_CatalogPanel_Title");
        NbDialogOperator dtdsOper = new NbDialogOperator(dtdsTitle);

        String publicID = "-//DTD XMLCatalog//EN";
        Node catalogNode = new Node(new JTreeOperator(dtdsOper),
                "NetBeans Catalog|"
                + publicID);
        // view and close it
        new ViewAction().perform(catalogNode);
        new EditorOperator(publicID).close();
        dtdsOper.close();

        // create an XML file

        // create xml package
        // select Source Packages to not create xml folder in Test Packages
        new SourcePackagesNode(SAMPLE_PROJECT_NAME).select();
        // "Java Classes"
        String javaClassesLabel = Bundle.getString("org.netbeans.modules.java.project.Bundle", "Templates/Classes");
        NewJavaFileWizardOperator.create(SAMPLE_PROJECT_NAME, javaClassesLabel, "Java Package", null, "xml"); // NOI18N
        Node xmlNode = new Node(new SourcePackagesNode(SAMPLE_PROJECT_NAME), "xml"); //NOI18N
        // "XML"
        String xmlCategory = Bundle.getString("org.netbeans.api.xml.resources.Bundle", "Templates/XML");
        // "XML Document"
        String xmlDocument = Bundle.getString("org.netbeans.modules.xml.resources.Bundle", "Templates/XML/XMLDocument.xml");
        NewFileWizardOperator.invoke(xmlNode, xmlCategory, xmlDocument);
        NewJavaFileNameLocationStepOperator nameStepOper = new NewJavaFileNameLocationStepOperator();
        nameStepOper.setObjectName("XMLDocument");  // NOI18N
        nameStepOper.next();
        nameStepOper.finish();
        // wait node is present
        Node xmlDocumentNode = new Node(xmlNode, "XMLDocument.xml"); // NOI18N
        // wait xml document is open in editor
        new EditorOperator("XMLDocument.xml").close();  // NOI18N

        // "Check XML"

        String checkXMLItem = Bundle.getStringTrimmed("org.netbeans.modules.xml.tools.actions.Bundle", "NAME_Check_XML");
        // invoke context action to check xml
        new Action(null, checkXMLItem).perform(xmlDocumentNode);
        // "XML check"
        String xmlCheckTitle = Bundle.getString("org.netbeans.modules.xml.actions.Bundle", "TITLE_XML_check_window");
        // find and close an output with the result of xml check
        new OutputTabOperator(xmlCheckTitle).close();

        // "Validate XML"

        String validateItem = Bundle.getStringTrimmed("org.netbeans.modules.xml.tools.actions.Bundle", "NAME_Validate_XML");
        // invoke context action to validate xml
        new Action(null, validateItem).perform(xmlDocumentNode);
        // find and close an output with the result of xml validation
        new OutputTabOperator(xmlCheckTitle).close();

        // "Generate DTD..."

        String generateDTDItem = Bundle.getStringTrimmed("org.netbeans.modules.xml.tools.generator.Bundle", "PROP_GenerateDTD");
        new ActionNoBlock(null, generateDTDItem).perform(xmlDocumentNode);
        // "Select File Name"
        String selectTitle = Bundle.getString("org.netbeans.modules.xml.tools.generator.Bundle", "PROP_fileNameTitle");
        NbDialogOperator selectDialog = new NbDialogOperator(selectTitle);
        // name has to be set because of issue http://www.netbeans.org/issues/show_bug.cgi?id=46049
        new JTextFieldOperator(selectDialog).setText("DTD");
        String oKLabel = Bundle.getString("org.netbeans.core.windows.services.Bundle", "OK_OPTION_CAPTION");
        new JButtonOperator(selectDialog, oKLabel).push();
        // wait DTD is open in editor
        new EditorOperator("DTD.dtd").close();  // NOI18N
        Node dtdNode = new Node(xmlNode, "DTD.dtd"); // NOI18N

        // "Check DTD"

        String checkDTDItem = Bundle.getStringTrimmed("org.netbeans.modules.xml.tools.actions.Bundle", "NAME_Validate_DTD");
        new Action(null, checkDTDItem).perform(dtdNode);
        // find and close an output with the result of dtd check
        new OutputTabOperator(xmlCheckTitle).close();

        // "Generate DOM Tree Scanner"
        String generateScannerItem = Bundle.getStringTrimmed("org.netbeans.modules.xml.tools.generator.Bundle", "PROP_GenerateDOMScanner");
        new ActionNoBlock(null, generateScannerItem).perform(dtdNode);
        selectDialog = new NbDialogOperator(selectTitle);
        new JButtonOperator(selectDialog, oKLabel).push();
        // wait Scanner is open in editor
        new EditorOperator("DTDScanner.java").close();  // NOI18N
        new Node(xmlNode, "DTDScanner.java"); // NOI18N
    }

    /** Test Window System 
     * - open Favorites top component from main menu Window|Favorites
     * - attach Favorites as last tab to output mode
     * - attach Favorites to top of Projects tab
     * - attach Favorites to right of output mode
     * - attach Favorites as last tab to explorer mode (next to Projects)
     * - close Favorites
     * - open sample1|SampleClass2.java file
     * - maximize opened editor by menu item "Maximize Window" on its tab
     * - restore editor by menu item "Restore Window" on its tab
     * - close all open editors
     */
    public void testWindowSystem() {
        final ProjectsTabOperator projectsOper = ProjectsTabOperator.invoke();
        final FavoritesOperator favoritesOper = FavoritesOperator.invoke();

        // test attaching
        favoritesOper.attachTo(new OutputOperator(), AttachWindowAction.AS_LAST_TAB);
        favoritesOper.attachTo(projectsOper, AttachWindowAction.TOP);
        favoritesOper.attachTo(new OutputOperator(), AttachWindowAction.RIGHT);
        favoritesOper.attachTo(projectsOper, AttachWindowAction.AS_LAST_TAB);
        // wait until TopComponent is in new location and is showing
        final TopComponent projectsTc = (TopComponent) projectsOper.getSource();
        final TopComponent favoritesTc = (TopComponent) favoritesOper.getSource();
        try {
            new Waiter(new Waitable() {

                @Override
                public Object actionProduced(Object tc) {
                    // run in dispatch thread
                    Mode mode1 = (Mode) projectsOper.getQueueTool().invokeSmoothly(new QueueTool.QueueAction("findMode") {    // NOI18N

                        @Override
                        public Object launch() {
                            return WindowManager.getDefault().findMode(projectsTc);
                        }
                    });
                    Mode mode2 = (Mode) favoritesOper.getQueueTool().invokeSmoothly(new QueueTool.QueueAction("findMode") {    // NOI18N

                        @Override
                        public Object launch() {
                            return WindowManager.getDefault().findMode(favoritesTc);
                        }
                    });
                    return (mode1 == mode2 && favoritesTc.isShowing()) ? Boolean.TRUE : null;
                }

                @Override
                public String getDescription() {
                    return ("Favorites TopComponent is next to Projects TopComponent."); // NOI18N
                }
            }).waitAction(null);
        } catch (InterruptedException e) {
            throw new JemmyException("Interrupted.", e); // NOI18N
        }
        favoritesOper.close();

        // test maximize/restore
        // open sample file in Editor
        SourcePackagesNode sourcePackagesNode = new SourcePackagesNode(SAMPLE_PROJECT_NAME);
        Node sample1Node = new Node(sourcePackagesNode, SAMPLE1_PACKAGE_NAME);
        JavaNode sampleClass2Node = new JavaNode(sample1Node, SAMPLE2_FILE_NAME);
        sampleClass2Node.open();
        // find open file in editor
        EditorOperator eo = new EditorOperator(SAMPLE2_FILE_NAME);
        eo.maximize();
        eo.restore();
        EditorOperator.closeDiscardAll();
    }

    /** Test Plugins
     * - open Plugins window from main menu Tools|Plugins
     * - wait until tabbed pane is enabled and the Installed tab is enabled
     * - click "Reload Catalog" button
     * - wait until "Available Plugins" tab is enabled
     * - switch to "Available Plugins" tab
     * - type "JUnit" into Search field
     * - wait until table contains "JUnit" module in the first row
     * - select that row
     * - click check box for the module
     * - click Install button
     * - in "NetBeans IDE Installer" dialog click Next
     * - click "I accept..." radio button
     * - click Install button
     * - wait until the module is turned on (message in main window status bar)
     * - click Finish button to dismiss the dialog
     * - switch to Installed tab
     * - select "netbeans.org Source Browser" plugin
     * - click Deactivate button
     * - wait for "NetBeans IDE Installer" dialog
     * - click Cancel
     * - Cancel deactivation because it requires restart (it can be fixed in future releases)
     * - close Plugins dialog
     */
    public void testPlugins() {
        final String PLUGIN_LABEL = "JUnit"; //NOI18N
        PluginsOperator pluginsOper = null;
        try {
            pluginsOper = PluginsOperator.invoke();
            pluginsOper.reloadCatalog();
            // Install

            pluginsOper.selectAvailablePlugins();
            pluginsOper.search(PLUGIN_LABEL);
            pluginsOper.install(PLUGIN_LABEL);

            // Deactivate

            pluginsOper.selectInstalled();
            try {
                pluginsOper.cbShowDetails().setSelected(true);
            } catch (JemmyException e) {
                log("Show Details check box not found - details already shown.");
            }
            pluginsOper.selectPlugin(PLUGIN_LABEL);
            pluginsOper.deactivate();
            pluginsOper.installer().cancel();

            /* Because it needs restart to deactivate module (probably can be changed in 
             * future releases), we skip this part.
             * 
            // check Status line
            // "Turning off modules...done."
            String turningOffLabel = Bundle.getString("org.netbeans.core.startup.Bundle", "MSG_finish_disable_modules");
            // increase timeout to 120 seconds
            MainWindowOperator.getDefault().getTimeouts().setTimeout("Waiter.WaitingTime", 120000);
            MainWindowOperator.getDefault().waitStatusText(turningOffLabel);
            // click Finish button
            String finishLabel = Bundle.getStringTrimmed("org.netbeans.modules.autoupdate.ui.wizards.Bundle", "InstallUnitWizardModel_Buttons_Finish");
            new JButtonOperator(installerOper, finishLabel).push();
            
            // Activate module
            
            pluginsOper.selectInstalled();
            pluginsOper.selectPlugin(PLUGIN_LABEL);
            pluginsOper.activate();
            // "Activate"
            String activateInDialogLabel = Bundle.getStringTrimmed("org.netbeans.modules.autoupdate.ui.wizards.Bundle", "UninstallUnitWizardModel_Buttons_TurnOn");
            new JButtonOperator(pluginsOper.installer(), activateInDialogLabel).pushNoBlock();
            // check Status line
            // "Turning on modules...done."
            String turningOnLabel = Bundle.getString("org.netbeans.core.startup.Bundle", "MSG_finish_enable_modules");
            // increase timeout to 120 seconds
            MainWindowOperator.getDefault().getTimeouts().setTimeout("Waiter.WaitingTime", 120000);
            MainWindowOperator.getDefault().waitStatusText(turningOnLabel);
            // click Finish button
            pluginsOper.installer().finish();
             */

            pluginsOper.close();
        } catch (JemmyException e) {
            // close possible error dialog
            // "Error"
            String errorTitle = Bundle.getString("org.netbeans.modules.autoupdate.ui.Bundle", "CTL_Error");
            if (JDialogOperator.findJDialog(errorTitle, true, true) != null) {
                new NbDialogOperator(errorTitle).close();
            }
            // close Plugins dialog
            if (pluginsOper != null) {
                pluginsOper.close();
            }
            throw e;
        }
    }

    public void testInitGC() throws Exception {
        PerfWatchProjects.initialize();
        Log.enableInstances(Logger.getLogger("TIMER"), "TextDocument", Level.FINEST);
    }
    
    public void testPrepareGC() throws Exception {
        if ( ("1.8".equals(System.getProperty("java.specification.version")))) {
            System.out.println(System.getProperty("netbeans.user"));
            //workaround to allow for smooth functioning of some tests on patched jdk8
            Runtime.getRuntime().exec("cp -f /space/build-impl.xml /space/memtesting/performance/build/test/qa-functional/work/userdir0/SampleProject/nbproject/build-impl.xml");
        }
    }

    public void testGCDocuments() throws Exception {
        PerfWatchProjects.assertTextDocuments();
    }
    
    public void testAnalyzeGCDocuments() throws Exception {
        PerfWatchProjects.analyzeHeapDump(PerfWatchProjects.getPath(),true);
    }

    public void testGCProjects() throws Exception {
            PerfWatchProjects.assertProjects();
    }
    
    public void testAnalyzeGCProjects() throws Exception {
            PerfWatchProjects.analyzeHeapDump(PerfWatchProjects.getPath(),false);
    }

    public void testReflectionUsage() throws Exception {
        PerfCountingSecurityManager.assertReflection(0, "allowed-reflection.txt");
    }

    /** Closes help window if any. It should not stay open between test cases.
     *  Otherwise it can break next tests.
     */
    private static void closeHelpWindow() {
        Window helpWindow = WindowOperator.findWindow(new ComponentChooser() {

            @Override
            public boolean checkComponent(Component comp) {
                WindowOperator winOper = new WindowOperator((Window) comp);
                winOper.setOutput(TestOut.getNullOutput());
                return null != winOper.findSubComponent(new ComponentChooser() {

                    @Override
                    public boolean checkComponent(Component comp) {
                        return comp.getClass().getName().startsWith("javax.help.JHelp"); //NOI18N
                    }

                    @Override
                    public String getDescription() {
                        return ("any javax.help");  //NOI18N
                    }
                });
            }

            @Override
            public String getDescription() {
                return "containing any javax.help.JHelp component";  //NOI18N
            }
        });
        if (helpWindow != null) {
            new WindowOperator(helpWindow).close();
        }
    }

    /**
     * Waits for breakpoint at specified line in editor.
     *
     * @param line line with breakpoint
     * @param eo EditorOperator instance
     */
    private static void waitBreakpoint(EditorOperator eo, final int line) throws Exception {
        new Waiter(new Waitable() {

            @Override
            public Object actionProduced(Object editorOper) {
                Object[] annotations = ((EditorOperator) editorOper).getAnnotations(line);
                for (int i = 0; i < annotations.length; i++) {
                    if ("Breakpoint".equals(EditorOperator.getAnnotationType(annotations[i]))) { // NOI18N
                        return Boolean.TRUE;
                    }
                }
                return null;
            }

            @Override
            public String getDescription() {
                return ("Wait breakpoint established on line " + line); // NOI18N
            }
        }).waitAction(eo);
    }

    private void sleep(int i) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }
}
