InputVerifierTest.java revision 14851:980da45565c8
1/*
2 * Copyright (c) 2006, 2016, 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.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24/*
25  @test
26  @key headful
27  @bug 6378278
28  @summary Apparent missing key events causing Bugster to break
29  @author oleg.sukhodolsky: area=awt.focus
30  @run main InputVerifierTest
31*/
32
33/**
34 * InputVerifierTest.java
35 *
36 * summary: Apparent missing key events causing Bugster to break
37 */
38
39import java.awt.AWTException;
40import java.awt.BorderLayout;
41import java.awt.Component;
42import java.awt.Dialog;
43import java.awt.Frame;
44import java.awt.Point;
45import java.awt.Robot;
46import java.awt.TextArea;
47
48import java.awt.event.InputEvent;
49import java.awt.event.KeyEvent;
50
51import javax.swing.InputVerifier;
52import javax.swing.JComponent;
53import javax.swing.JFrame;
54import javax.swing.JTextField;
55
56public class InputVerifierTest
57{
58
59    //*** test-writer defined static variables go here ***
60    static volatile boolean ivWasCalled = false;
61
62    private static void init()
63    {
64        //*** Create instructions for the user here ***
65        String[] instructions =
66        {
67            "This is an AUTOMATIC test, simply wait until it is done.",
68            "The result (passed or failed) will be shown in the",
69            "message window below."
70        };
71        Sysout.createDialog( );
72        Sysout.printInstructions( instructions );
73
74        JFrame frame = new JFrame();
75        JTextField t1 = new JTextField();
76        t1.setInputVerifier(new InputVerifier() {
77            public boolean verify(JComponent input) {
78                Sysout.println("verify(" + input + ")");
79                ivWasCalled = true;
80                return true;
81            }
82        });
83        JTextField t2 = new JTextField();
84
85        frame.getContentPane().add(t1, BorderLayout.NORTH);
86        frame.getContentPane().add(t2, BorderLayout.SOUTH);
87        frame.setSize(200, 200);
88        frame.setVisible(true);
89
90        Robot r = null;
91        try {
92            r = new Robot();
93        } catch (AWTException e) {
94            e.printStackTrace();
95            InputVerifierTest.fail(e.toString());
96        }
97
98        try {
99            r.waitForIdle();
100
101            mouseClickOnComp(r, t1);
102            r.waitForIdle();
103
104            if (!t1.isFocusOwner()) {
105                throw new RuntimeException("t1 is not a focus owner");
106            }
107            ivWasCalled = false;
108            r.keyPress(KeyEvent.VK_TAB);
109            r.delay(10);
110            r.keyRelease(KeyEvent.VK_TAB);
111            r.waitForIdle();
112
113            if (!t2.isFocusOwner()) {
114                throw new RuntimeException("t2 is not a focus owner");
115            }
116            if (!ivWasCalled) {
117                throw new RuntimeException("InputVerifier was not called after tabbing");
118            }
119
120            mouseClickOnComp(r, t1);
121            r.waitForIdle();
122
123            if (!t1.isFocusOwner()) {
124                throw new RuntimeException("t1 is not a focus owner");
125            }
126
127            ivWasCalled = false;
128            mouseClickOnComp(r, t2);
129            r.waitForIdle();
130            if (!t2.isFocusOwner()) {
131                throw new RuntimeException("t2 is not a focus owner");
132            }
133            if (!ivWasCalled) {
134                throw new RuntimeException("InputVErifier was not called after mouse press");
135            }
136        } catch (Exception e) {
137            e.printStackTrace();
138            InputVerifierTest.fail(e.toString());
139        }
140
141        InputVerifierTest.pass();
142
143    }//End  init()
144
145    static void mouseClickOnComp(Robot r, Component comp) {
146        Point loc = comp.getLocationOnScreen();
147        loc.x += comp.getWidth() / 2;
148        loc.y += comp.getHeight() / 2;
149        r.mouseMove(loc.x, loc.y);
150        r.delay(10);
151        r.mousePress(InputEvent.BUTTON1_MASK);
152        r.delay(10);
153        r.mouseRelease(InputEvent.BUTTON1_MASK);
154    }
155
156    /*****************************************************
157     * Standard Test Machinery Section
158     * DO NOT modify anything in this section -- it's a
159     * standard chunk of code which has all of the
160     * synchronisation necessary for the test harness.
161     * By keeping it the same in all tests, it is easier
162     * to read and understand someone else's test, as
163     * well as insuring that all tests behave correctly
164     * with the test harness.
165     * There is a section following this for test-
166     * classes
167     ******************************************************/
168    private static boolean theTestPassed = false;
169    private static boolean testGeneratedInterrupt = false;
170    private static String failureMessage = "";
171
172    private static Thread mainThread = null;
173
174    private static int sleepTime = 300000;
175
176    // Not sure about what happens if multiple of this test are
177    //  instantiated in the same VM.  Being static (and using
178    //  static vars), it aint gonna work.  Not worrying about
179    //  it for now.
180    public static void main( String args[] ) throws InterruptedException
181    {
182        mainThread = Thread.currentThread();
183        try
184        {
185            init();
186        }
187        catch( TestPassedException e )
188        {
189            //The test passed, so just return from main and harness will
190            // interepret this return as a pass
191            return;
192        }
193        //At this point, neither test pass nor test fail has been
194        // called -- either would have thrown an exception and ended the
195        // test, so we know we have multiple threads.
196
197        //Test involves other threads, so sleep and wait for them to
198        // called pass() or fail()
199        try
200        {
201            Thread.sleep( sleepTime );
202            //Timed out, so fail the test
203            throw new RuntimeException( "Timed out after " + sleepTime/1000 + " seconds" );
204        }
205        catch (InterruptedException e)
206        {
207            //The test harness may have interrupted the test.  If so, rethrow the exception
208            // so that the harness gets it and deals with it.
209            if( ! testGeneratedInterrupt ) throw e;
210
211            //reset flag in case hit this code more than once for some reason (just safety)
212            testGeneratedInterrupt = false;
213
214            if ( theTestPassed == false )
215            {
216                throw new RuntimeException( failureMessage );
217            }
218        }
219
220    }//main
221
222    public static synchronized void setTimeoutTo( int seconds )
223    {
224        sleepTime = seconds * 1000;
225    }
226
227    public static synchronized void pass()
228    {
229        Sysout.println( "The test passed." );
230        Sysout.println( "The test is over, hit  Ctl-C to stop Java VM" );
231        //first check if this is executing in main thread
232        if ( mainThread == Thread.currentThread() )
233        {
234            //Still in the main thread, so set the flag just for kicks,
235            // and throw a test passed exception which will be caught
236            // and end the test.
237            theTestPassed = true;
238            throw new TestPassedException();
239        }
240        theTestPassed = true;
241        testGeneratedInterrupt = true;
242        mainThread.interrupt();
243    }//pass()
244
245    public static synchronized void fail()
246    {
247        //test writer didn't specify why test failed, so give generic
248        fail( "it just plain failed! :-)" );
249    }
250
251    public static synchronized void fail( String whyFailed )
252    {
253        Sysout.println( "The test failed: " + whyFailed );
254        Sysout.println( "The test is over, hit  Ctl-C to stop Java VM" );
255        //check if this called from main thread
256        if ( mainThread == Thread.currentThread() )
257        {
258            //If main thread, fail now 'cause not sleeping
259            throw new RuntimeException( whyFailed );
260        }
261        theTestPassed = false;
262        testGeneratedInterrupt = true;
263        failureMessage = whyFailed;
264        mainThread.interrupt();
265    }//fail()
266
267}// class InputVerifierTest
268
269//This exception is used to exit from any level of call nesting
270// when it's determined that the test has passed, and immediately
271// end the test.
272class TestPassedException extends RuntimeException
273{
274}
275
276//*********** End Standard Test Machinery Section **********
277
278/****************************************************
279 Standard Test Machinery
280 DO NOT modify anything below -- it's a standard
281  chunk of code whose purpose is to make user
282  interaction uniform, and thereby make it simpler
283  to read and understand someone else's test.
284 ****************************************************/
285
286/**
287 This is part of the standard test machinery.
288 It creates a dialog (with the instructions), and is the interface
289  for sending text messages to the user.
290 To print the instructions, send an array of strings to Sysout.createDialog
291  WithInstructions method.  Put one line of instructions per array entry.
292 To display a message for the tester to see, simply call Sysout.println
293  with the string to be displayed.
294 This mimics System.out.println but works within the test harness as well
295  as standalone.
296 */
297
298class Sysout
299{
300    private static TestDialog dialog;
301
302    public static void createDialogWithInstructions( String[] instructions )
303    {
304        dialog = new TestDialog( new Frame(), "Instructions" );
305        dialog.printInstructions( instructions );
306        dialog.setVisible(true);
307        println( "Any messages for the tester will display here." );
308    }
309
310    public static void createDialog( )
311    {
312        dialog = new TestDialog( new Frame(), "Instructions" );
313        String[] defInstr = { "Instructions will appear here. ", "" } ;
314        dialog.printInstructions( defInstr );
315        dialog.setVisible(true);
316        println( "Any messages for the tester will display here." );
317    }
318
319
320    public static void printInstructions( String[] instructions )
321    {
322        dialog.printInstructions( instructions );
323    }
324
325
326    public static void println( String messageIn )
327    {
328        dialog.displayMessage( messageIn );
329        System.out.println(messageIn);
330    }
331
332}// Sysout  class
333
334/**
335  This is part of the standard test machinery.  It provides a place for the
336   test instructions to be displayed, and a place for interactive messages
337   to the user to be displayed.
338  To have the test instructions displayed, see Sysout.
339  To have a message to the user be displayed, see Sysout.
340  Do not call anything in this dialog directly.
341  */
342class TestDialog extends Dialog
343{
344
345    TextArea instructionsText;
346    TextArea messageText;
347    int maxStringLength = 80;
348
349    //DO NOT call this directly, go through Sysout
350    public TestDialog( Frame frame, String name )
351    {
352        super( frame, name );
353        int scrollBoth = TextArea.SCROLLBARS_BOTH;
354        instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth );
355        add( "North", instructionsText );
356
357        messageText = new TextArea( "", 5, maxStringLength, scrollBoth );
358        add("Center", messageText);
359
360        pack();
361
362        setVisible(true);
363    }// TestDialog()
364
365    //DO NOT call this directly, go through Sysout
366    public void printInstructions( String[] instructions )
367    {
368        //Clear out any current instructions
369        instructionsText.setText( "" );
370
371        //Go down array of instruction strings
372
373        String printStr, remainingStr;
374        for( int i=0; i < instructions.length; i++ )
375        {
376            //chop up each into pieces maxSringLength long
377            remainingStr = instructions[ i ];
378            while( remainingStr.length() > 0 )
379            {
380                //if longer than max then chop off first max chars to print
381                if( remainingStr.length() >= maxStringLength )
382                {
383                    //Try to chop on a word boundary
384                    int posOfSpace = remainingStr.
385                        lastIndexOf( ' ', maxStringLength - 1 );
386
387                    if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1;
388
389                    printStr = remainingStr.substring( 0, posOfSpace + 1 );
390                    remainingStr = remainingStr.substring( posOfSpace + 1 );
391                }
392                //else just print
393                else
394                {
395                    printStr = remainingStr;
396                    remainingStr = "";
397                }
398
399                instructionsText.append( printStr + "\n" );
400
401            }// while
402
403        }// for
404
405    }//printInstructions()
406
407    //DO NOT call this directly, go through Sysout
408    public void displayMessage( String messageIn )
409    {
410        messageText.append( messageIn + "\n" );
411        System.out.println(messageIn);
412    }
413
414}// TestDialog  class
415