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 
  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.
 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 
 169     public static synchronized void setTimeoutTo( int seconds )
 170     {
 171         sleepTime = seconds * 1000;
 172     }
 173 
 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 
 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 
 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 
 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 
 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 
 308     public static void printInstructions( String[] instructions )
 309     {
 310         dialog.printInstructions( instructions );
 311     }
 312 
 313 
 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
 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
 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
 396     public void displayMessage( String messageIn )
 397     {
 398         messageText.append( messageIn + "\n" );
 399         System.out.println(messageIn);
 400     }
 401 
 402 }// TestDialog  class