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