package textbender.a.b.rhinohideDemo._; // Copyright 2007, Michael Allan. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Textbender Software"), to deal in the Textbender Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicence, and/or sell copies of the Textbender Software, and to permit persons to whom the Textbender Software is furnished to do so, subject to the following conditions: The preceding copyright notice and this permission notice shall be included in all copies or substantial portions of the Textbender Software. THE TEXTBENDER SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE TEXTBENDER SOFTWARE OR THE USE OR OTHER DEALINGS IN THE TEXTBENDER SOFTWARE. import java.awt.*; import java.security.*; import java.util.concurrent.atomic.*; import java.util.List; import javax.swing.*; import javax.swing.border.*; import org.junit.runner.*; import org.junit.runner.notification.*; import textbender.g.lang.*; import textbender.g.util.logging.*; import textbender.o.rhinohide.*; /** Test of Rhinohide, Core Level 1 (isolate). * *

BUG: hierarchy-mutation

*
* http://reluk.ca/var/cache/textbender-javadoc/textbender/a/b/rhinohideDemo/_/Core_1i_Test.html#hierarchy-mutation *
*

* These tests expose a bug on * IE, * caused by node hierarchy mutations. * All of the tests run successfully, but the browser crashes on page exit, * and the Plug-In produces this error trace. *

*

* Running in a single thread (applet start thread) does not help. *

*

* Consistently repeatable for any insertion, append or replacement of nodes (text or element) * within a parent node. Does not affect attribute nodes, however. *

*

* A bug is being filed with Sun. *

* * @see http://reluk.ca/var/cache/rhinohide-demo/textbender/a/b/rhinohideDemo/Core_1i_Test.html */ public @ThreadRestricted("AWT event dispatch") final class Core_1i_Test extends JApplet implements Runnable { /** Shared window for all tests. */ public static RhiWindow window() { return window; } private static volatile RhiWindow window; // - A p p l e t ---------------------------------------------------------------------- private final AtomicBoolean isStartedA = new AtomicBoolean(); public @ThreadSafe void start() { if( isStartedA.getAndSet( true )) return; // start once only LoggerX.i(getClass()).info( "starting" ); EventQueue.invokeLater( Core_1i_Test.this ); // in AWT event dispatch thread } private final AtomicBoolean isDestroyedA = new AtomicBoolean(); public @ThreadSafe void destroy() { if( isDestroyedA.getAndSet( true )) { assert false; return; } LoggerX.i(getClass()).info( "destroying" ); if( window != null ) { window.release(); window = null; } } // - R u n n a b l e ------------------------------------------------------------------ /** Runs this test applet. */ public void run() { reportList.addElement( "starting..." ); // ThreadSafe.U.disableChecking(); // I lack permission, I'm an unsigned applet { // Construct GUI. // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - JList reportListV = new JList( reportList ); reportListV.setBorder( new EmptyBorder( /*top*/2, /*left*/2, /*bottom*/2, /*right*/0 )); JScrollPane scrollPane = new JScrollPane( reportListV ); scrollPane.setBorder( null ); getContentPane().add( scrollPane, BorderLayout.CENTER ); } try { window = RhiWindow.createWindow( Core_1i_Test.this ); // Query DOM implementation. // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // final Document document = window.getDocument(); // reportList.addElement // ( // "browser supports Core Level 1... " + // document.getImplementation().hasFeature( "HTML", "1.0" ) // only "HTML" and "XML" valid, at this level // ); //// Core Level 1 is mandatory, and may not be queried // Start the tester. // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - final Thread thread = new Thread( new Tester(), "tester" ); thread.setDaemon( true ); thread.setPriority( Thread.NORM_PRIORITY - 1 ); thread.start(); // - - - reportList.addElement( "successfully started" ); } catch( AccessControlException x ) { reportList.addElement( "insufficient permissions to run tests, applet not trusted" ); } catch( Exception x ) // all, checked or not { LoggerX.i(getClass()).log( LoggerX.WARNING, /*message*/"", x ); } } //// P r i v a t e /////////////////////////////////////////////////////////////////////// @ThreadRestricted( "AWT event dispatch" ) private final DefaultListModel reportList = new DefaultListModel(); // ==================================================================================== private final class Tester implements Runnable { /** @throws AccessControlException if permissions are insufficient */ Tester() throws AccessControlException { AccessController.checkPermission( new AllPermission() ); // Eagerly. Actually, it needs only reflection I think (AccessDeclaredMembers). } private final JUnitCore junit = new JUnitCore(); // - R u n n a b l e -------------------------------------------------------------- public void run() { EventQueue.invokeLater( new Runnable() { public void run() // in AWT event dispatch thread { reportList.addElement( "running tests..." ); } }); final Result result = junit.run ( textbender.a.b.rhinohideDemo._.core.RhiDocumentFragment_1i.class , textbender.a.b.rhinohideDemo._.core.RhiElement_1i.class , textbender.a.b.rhinohideDemo._.core.RhiNode_1i.class ); final List failureList = result.getFailures(); EventQueue.invokeLater( new Runnable() { public void run() // in AWT event dispatch thread { for( final Failure failure: failureList ) { reportList.addElement( failure ); Throwable t = failure.getException(); if( t == null ) continue; LoggerX.i(getClass()).log( LoggerX.WARNING, /*message*/"", t ); reportList.addElement( " " + t.toString() ); } reportList.addElement( "test count: " + result.getRunCount() ); if( result.wasSuccessful() ) { reportList.addElement( "all tests successful" ); } else { reportList.addElement( "failure count: " + failureList.size() + " (details were output to the standard logger)" ); } } }); } } }