1 /*
2  * Copyright (c) 2008, 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   @bug 6681889
27   @summary Showing a deserialized frame should not throw NPE
28   @author anthony.petrov@...: area=awt.toplevel
29   @run main PropertyChangeListenerLockSerialization
30 */
31 
32 
33 /**
34  * PropertyChangeListenerLockSerialization.java
35  *
36  * summary: Showing a deserialized frame should not throw NPE
37  */
38 
39 import java.awt.*;
40 import java.awt.event.*;
41 import java.io.*;
42 import java.net.*;
43 
44 public class PropertyChangeListenerLockSerialization
45 {
46 
init()47     private static void init()
48     {
49         //*** Create instructions for the user here ***
50 
51         String[] instructions =
52         {
53             "This is an AUTOMATIC test, simply wait until it is done.",
54             "The result (passed or failed) will be shown in the",
55             "message window below."
56         };
57         Sysout.createDialog( );
58         Sysout.printInstructions( instructions );
59 
60         File file =
61             new File(System.getProperty("test.classes", "."), "frame.ser");
62 
63         Frame f = new Frame("Frame");
64         f.setBounds(250, 50, 300, 300);
65         try {
66             OutputStream o = new FileOutputStream(file);
67             ObjectOutputStream oo = new ObjectOutputStream(o);
68 
69             oo.writeObject(f);
70             oo.close();
71         } catch (IOException ex) {
72             ex.printStackTrace();
73             fail("Unable to serialize the frame: " + ex);
74         }
75 
76         // Cleanup the frame
77         f.dispose();
78         f = null;
79 
80         try {
81             ObjectInputStream i = new ObjectInputStream(new FileInputStream(file));
82 
83             f = (Frame)i.readObject();
84             f.show();
85         } catch (NullPointerException ex) {
86             ex.printStackTrace();
87             fail("The NullPointerException has been thrown: " + ex);
88         } catch (Exception ex) {
89             ex.printStackTrace();
90             fail("Error while deserializing the frame: " + ex);
91         }
92 
93         // Cleanup the frame
94         f.dispose();
95         f = null;
96 
97         pass();
98 
99     }//End  init()
100 
101 
102 
103     /*****************************************************
104      * Standard Test Machinery Section
105      * DO NOT modify anything in this section -- it's a
106      * standard chunk of code which has all of the
107      * synchronisation necessary for the test harness.
108      * By keeping it the same in all tests, it is easier
109      * to read and understand someone else's test, as
110      * well as insuring that all tests behave correctly
111      * with the test harness.
112      * There is a section following this for test-
113      * classes
114      ******************************************************/
115     private static boolean theTestPassed = false;
116     private static boolean testGeneratedInterrupt = false;
117     private static String failureMessage = "";
118 
119     private static Thread mainThread = null;
120 
121     private static int sleepTime = 300000;
122 
123     // Not sure about what happens if multiple of this test are
124     //  instantiated in the same VM.  Being static (and using
125     //  static vars), it aint gonna work.  Not worrying about
126     //  it for now.
main( String args[] )127     public static void main( String args[] ) throws InterruptedException
128     {
129         mainThread = Thread.currentThread();
130         try
131         {
132             init();
133         }
134         catch( TestPassedException e )
135         {
136             //The test passed, so just return from main and harness will
137             // interepret this return as a pass
138             return;
139         }
140         //At this point, neither test pass nor test fail has been
141         // called -- either would have thrown an exception and ended the
142         // test, so we know we have multiple threads.
143 
144         //Test involves other threads, so sleep and wait for them to
145         // called pass() or fail()
146         try
147         {
148             Thread.sleep( sleepTime );
149             //Timed out, so fail the test
150             throw new RuntimeException( "Timed out after " + sleepTime/1000 + " seconds" );
151         }
152         catch (InterruptedException e)
153         {
154             //The test harness may have interrupted the test.  If so, rethrow the exception
155             // so that the harness gets it and deals with it.
156             if( ! testGeneratedInterrupt ) throw e;
157 
158             //reset flag in case hit this code more than once for some reason (just safety)
159             testGeneratedInterrupt = false;
160 
161             if ( theTestPassed == false )
162             {
163                 throw new RuntimeException( failureMessage );
164             }
165         }
166 
167     }//main
168 
setTimeoutTo( int seconds )169     public static synchronized void setTimeoutTo( int seconds )
170     {
171         sleepTime = seconds * 1000;
172     }
173 
pass()174     public static synchronized void pass()
175     {
176         Sysout.println( "The test passed." );
177         Sysout.println( "The test is over, hit  Ctl-C to stop Java VM" );
178         //first check if this is executing in main thread
179         if ( mainThread == Thread.currentThread() )
180         {
181             //Still in the main thread, so set the flag just for kicks,
182             // and throw a test passed exception which will be caught
183             // and end the test.
184             theTestPassed = true;
185             throw new TestPassedException();
186         }
187         theTestPassed = true;
188         testGeneratedInterrupt = true;
189         mainThread.interrupt();
190     }//pass()
191 
fail()192     public static synchronized void fail()
193     {
194         //test writer didn't specify why test failed, so give generic
195         fail( "it just plain failed! :-)" );
196     }
197 
fail( String whyFailed )198     public static synchronized void fail( String whyFailed )
199     {
200         Sysout.println( "The test failed: " + whyFailed );
201         Sysout.println( "The test is over, hit  Ctl-C to stop Java VM" );
202         //check if this called from main thread
203         if ( mainThread == Thread.currentThread() )
204         {
205             //If main thread, fail now 'cause not sleeping
206             throw new RuntimeException( whyFailed );
207         }
208         theTestPassed = false;
209         testGeneratedInterrupt = true;
210         failureMessage = whyFailed;
211         mainThread.interrupt();
212     }//fail()
213 
214 }// class PropertyChangeListenerLockSerialization
215 
216 //This exception is used to exit from any level of call nesting
217 // when it's determined that the test has passed, and immediately
218 // end the test.
219 class TestPassedException extends RuntimeException
220 {
221 }
222 
223 //*********** End Standard Test Machinery Section **********
224 
225 
226 //************ Begin classes defined for the test ****************
227 
228 // if want to make listeners, here is the recommended place for them, then instantiate
229 //  them in init()
230 
231 /* Example of a class which may be written as part of a test
232 class NewClass implements anInterface
233  {
234    static int newVar = 0;
235 
236    public void eventDispatched(AWTEvent e)
237     {
238       //Counting events to see if we get enough
239       eventCount++;
240 
241       if( eventCount == 20 )
242        {
243          //got enough events, so pass
244 
245          PropertyChangeListenerLockSerialization.pass();
246        }
247       else if( tries == 20 )
248        {
249          //tried too many times without getting enough events so fail
250 
251          PropertyChangeListenerLockSerialization.fail();
252        }
253 
254     }// eventDispatched()
255 
256  }// NewClass class
257 
258 */
259 
260 
261 //************** End classes defined for the test *******************
262 
263 
264 
265 
266 /****************************************************
267  Standard Test Machinery
268  DO NOT modify anything below -- it's a standard
269   chunk of code whose purpose is to make user
270   interaction uniform, and thereby make it simpler
271   to read and understand someone else's test.
272  ****************************************************/
273 
274 /**
275  This is part of the standard test machinery.
276  It creates a dialog (with the instructions), and is the interface
277   for sending text messages to the user.
278  To print the instructions, send an array of strings to Sysout.createDialog
279   WithInstructions method.  Put one line of instructions per array entry.
280  To display a message for the tester to see, simply call Sysout.println
281   with the string to be displayed.
282  This mimics System.out.println but works within the test harness as well
283   as standalone.
284  */
285 
286 class Sysout
287 {
288     private static TestDialog dialog;
289 
createDialogWithInstructions( String[] instructions )290     public static void createDialogWithInstructions( String[] instructions )
291     {
292         dialog = new TestDialog( new Frame(), "Instructions" );
293         dialog.printInstructions( instructions );
294         dialog.setVisible(true);
295         println( "Any messages for the tester will display here." );
296     }
297 
createDialog( )298     public static void createDialog( )
299     {
300         dialog = new TestDialog( new Frame(), "Instructions" );
301         String[] defInstr = { "Instructions will appear here. ", "" } ;
302         dialog.printInstructions( defInstr );
303         dialog.setVisible(true);
304         println( "Any messages for the tester will display here." );
305     }
306 
307 
printInstructions( String[] instructions )308     public static void printInstructions( String[] instructions )
309     {
310         dialog.printInstructions( instructions );
311     }
312 
313 
println( String messageIn )314     public static void println( String messageIn )
315     {
316         dialog.displayMessage( messageIn );
317         System.out.println(messageIn);
318     }
319 
320 }// Sysout  class
321 
322 /**
323   This is part of the standard test machinery.  It provides a place for the
324    test instructions to be displayed, and a place for interactive messages
325    to the user to be displayed.
326   To have the test instructions displayed, see Sysout.
327   To have a message to the user be displayed, see Sysout.
328   Do not call anything in this dialog directly.
329   */
330 class TestDialog extends Dialog
331 {
332 
333     TextArea instructionsText;
334     TextArea messageText;
335     int maxStringLength = 80;
336 
337     //DO NOT call this directly, go through Sysout
TestDialog( Frame frame, String name )338     public TestDialog( Frame frame, String name )
339     {
340         super( frame, name );
341         int scrollBoth = TextArea.SCROLLBARS_BOTH;
342         instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth );
343         add( "North", instructionsText );
344 
345         messageText = new TextArea( "", 5, maxStringLength, scrollBoth );
346         add("Center", messageText);
347 
348         pack();
349 
350         setVisible(true);
351     }// TestDialog()
352 
353     //DO NOT call this directly, go through Sysout
printInstructions( String[] instructions )354     public void printInstructions( String[] instructions )
355     {
356         //Clear out any current instructions
357         instructionsText.setText( "" );
358 
359         //Go down array of instruction strings
360 
361         String printStr, remainingStr;
362         for( int i=0; i < instructions.length; i++ )
363         {
364             //chop up each into pieces maxSringLength long
365             remainingStr = instructions[ i ];
366             while( remainingStr.length() > 0 )
367             {
368                 //if longer than max then chop off first max chars to print
369                 if( remainingStr.length() >= maxStringLength )
370                 {
371                     //Try to chop on a word boundary
372                     int posOfSpace = remainingStr.
373                         lastIndexOf( ' ', maxStringLength - 1 );
374 
375                     if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1;
376 
377                     printStr = remainingStr.substring( 0, posOfSpace + 1 );
378                     remainingStr = remainingStr.substring( posOfSpace + 1 );
379                 }
380                 //else just print
381                 else
382                 {
383                     printStr = remainingStr;
384                     remainingStr = "";
385                 }
386 
387                 instructionsText.append( printStr + "\n" );
388 
389             }// while
390 
391         }// for
392 
393     }//printInstructions()
394 
395     //DO NOT call this directly, go through Sysout
displayMessage( String messageIn )396     public void displayMessage( String messageIn )
397     {
398         messageText.append( messageIn + "\n" );
399         System.out.println(messageIn);
400     }
401 
402 }// TestDialog  class
403