Hi Laurent, Thanks for your test! Great job :-)
I applied some minor changes for integration: * Renamed to TestSeqEventsMultipleContexts * A bit longer but should describe what this is about * Placed in jdk/java/awt/event/SequencedEvent * Encapsulated the window in TestWindow class * Instead of waiting 1s for windows to show, loop until windows are shown -or the test hard stops-. When I ran in my environment, 1s was not enough. This should make the test more resilent. We still depend on a timer but that is inevitably. * Incremented the time we wait for the TGs to finish. 2s was not enough in my runs. However, we now do frequent checks to finish earlier in the success path. * Calculated expected value in initilization time * Changed a bit how the test finishes * System.exit(0) is a failure for jtreg * We need status -1 for jtreg to detect failures, and will do a hard stop when time expires * Stack traces for the main thread are not much relevant * dispose window to exit gracefully on the success path * Removed unused code (button click action) * Added jtreg tags & copyright Webrev.02 with test integrated: * http://cr.openjdk.java.net/~mbalao/webrevs/8204142/8204142.webrev.02 * http://cr.openjdk.java.net/~mbalao/webrevs/8204142/8204142.webrev.02.zip Kind regards, Martin.- On Mon, Oct 15, 2018 at 3:38 PM, Laurent Bourgès <[email protected]> wrote: > Hi Martin, > >> Thanks for your feedback and happy to hear that it worked! >> >> In regards to pendingEvents sync, my understanding is that >> SequencedEvent objects will be posted to one EventQueue only and, thus, be >> dispatched by one EDT. >> > > Agreed. > > >> I had a quick look at "Exception in thread "AWT-EventQueue-1" >> java.lang.IllegalArgumentException: >> null source" exception and could not find any connection to the code >> modified in the context of this bug. Apparently, "activeWindow" variable in >> "WindowEvent.WINDOW_LOST_FOCUS" case is null >> (DefaultKeyboardFocusManager.dispatchEvent function). I thought that >> this was caused by the fact that the test is injecting events that modify >> the focus on both windows at a very high rate and, by the time >> DefaultKeyboardFocusManager dispatches the event, it could be too late. >> Just an hypothesis. >> > > I agree, it is certainly a side-effect: other issues may be triggered by > such event intensive test. > > >> Look forward to your re-written test. >> > > Here it is: > > import java.awt.BorderLayout; > import java.awt.Dimension; > import java.awt.event.ActionEvent; > import java.awt.event.ActionListener; > import java.util.ArrayList; > import java.util.List; > import java.util.concurrent.atomic.AtomicReference; > import javax.swing.JButton; > > import javax.swing.JFrame; > import javax.swing.JLabel; > import javax.swing.SwingUtilities; > import javax.swing.Timer; > > /* > * Running this code causes the AWT Event Queues to be blocked on OpenJDK11 > * javac --add-exports java.desktop/sun.awt=ALL-UNNAMED TestWinEvent.java > * > * @author Laurent Bourges > */ > public final class TestWinEvent extends JFrame implements ActionListener { > > private static final long serialVersionUID = 1L; > > private static final int NUM_WINDOW = 2; > private static final int INTERVAL = 50; > private static final int MAX_TIME = 10000; // 10s > private static final int MAX_COUNT = MAX_TIME / INTERVAL; > private static final List<TestWinEvent> WINDOWS = new > ArrayList<TestWinEvent>(); > > private final JButton btn; > private int counter = 0; > private final Timer t; > > public static void main(String[] args) { > try { > for (int i = 0; i < NUM_WINDOW; i++) { > createWin(i + 1); > } > > // Wait MAX_TIME + 2s > Thread.sleep(MAX_TIME + 2000); > > int total = 0; > for (TestWinEvent window : WINDOWS) { > total += window.getCounter(); > } > > // Failure if AWT hanging: assert > final int expected = MAX_COUNT * NUM_WINDOW; > if (total != expected) { > throw new IllegalStateException("Total [" + total + "] != > expected [" + expected + "] !"); > } > } catch (InterruptedException ie) { > ie.printStackTrace(); > } catch (IllegalStateException iae) { > iae.printStackTrace(); > } finally { > System.exit(0); > } > } > > private static void createWin(int tgNum) { > new Thread(new ThreadGroup("TG " + tgNum), > new Runnable() { > @Override > public void run() { > sun.awt.SunToolkit.createNewAppContext(); > > final AtomicReference<TestWinEvent> ref = new > AtomicReference<TestWinEvent>(); > > SwingUtilities.invokeLater(new Runnable() { > @Override > public void run() { > final TestWinEvent window = new > TestWinEvent(tgNum); > window.setVisible(true); > ref.set(window); > WINDOWS.add(window); > } > }); > > try { > // Wait 1s to show window > Thread.sleep(1000); > } catch (InterruptedException ie) { > ie.printStackTrace(); > } > > final TestWinEvent window = ref.get(); > if (window != null) { > window.enableTimer(true); > } > } > }).start(); > } > > TestWinEvent(final int num) { > super("Test Window [" + num + "]"); > setMinimumSize(new Dimension(300, 200)); > setLocation(100 + 400 * (num - 1), 100); > > setLayout(new BorderLayout()); > JLabel textBlock = new JLabel("Lorem ipsum dolor sit amet..."); > add(textBlock); > > btn = new JButton("TEST"); > btn.addActionListener(new ActionListener() { > @Override > public void actionPerformed(ActionEvent e) { > System.out.println("Button#" + num + " clicked: " + > counter); > } > > }); > add(btn, BorderLayout.SOUTH); > > setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); > pack(); > > t = new Timer(INTERVAL, this); > t.setRepeats(false); > } > > @Override > public void actionPerformed(ActionEvent e) { > this.toFront(); > btn.setText("TEST " + (++counter)); > this.toBack(); > if (counter < MAX_COUNT) { > enableTimer(true); > } else { > setVisible(false); > } > } > > void enableTimer(boolean enable) { > if (enable) { > t.start(); > } else { > t.stop(); > } > } > > int getCounter() { > return counter; > } > } > > I will attach it in the JBS bug. > > Regards, > Laurent >
