1 /* 2 * Copyright (c) 2019, 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 8204142 27 * @summary Deadlock when queueing SequencedEvent of different AppContexts 28 * @author Laurent Bourges 29 * @modules java.desktop/sun.awt 30 * @run main/othervm/timeout=30 MultipleContextsFunctionalTest 31 */ 32 33 import java.awt.BorderLayout; 34 import java.awt.Dimension; 35 import java.awt.event.ActionEvent; 36 import java.awt.event.ActionListener; 37 import java.util.ArrayList; 38 import java.util.List; 39 import java.util.concurrent.atomic.AtomicReference; 40 import javax.swing.JButton; 41 import javax.swing.JFrame; 42 import javax.swing.JLabel; 43 import javax.swing.SwingUtilities; 44 import javax.swing.Timer; 45 46 public final class MultipleContextsFunctionalTest { 47 48 private static final long serialVersionUID = 1L; 49 50 private static final int NUM_WINDOW = 2; 51 private static final int INTERVAL = 50; 52 private static final int MAX_TIME = 10000; // 10s 53 private static final int TOLERANCE = 10000;// 10s 54 private static final int CHECK_LAPSE = 100; 55 private static final int MAX_COUNT = MAX_TIME / INTERVAL; 56 private static final int EXPECTED = MAX_COUNT * NUM_WINDOW; 57 private static final List<TestWindow> WINDOWS = new ArrayList<TestWindow>(); 58 59 public static void main(String[] args) { 60 for (int i = 0; i < NUM_WINDOW; i++) { 61 createWin(i); 62 } 63 64 int total = 0; 65 int waitingTime = MAX_TIME + TOLERANCE; 66 while (waitingTime > 0 && total != EXPECTED) { 67 try { 68 Thread.sleep(CHECK_LAPSE); 69 } catch (InterruptedException e) { 70 e.printStackTrace(); 71 } 72 waitingTime -= CHECK_LAPSE; 73 74 total = 0; 75 for (TestWindow window : WINDOWS) { 76 total += window.getCounter(); 77 } 78 } 79 80 // Failure if AWT hanging: assert 81 System.out.println("Total [" + total + "] - Expected [" + EXPECTED + "]"); 82 if (total == EXPECTED) { 83 System.out.println("Test PASSED"); 84 return; 85 } 86 System.out.println("Test FAILED"); 87 Runtime.getRuntime().halt(-1); 88 } 89 90 private static void createWin(int tgNum) { 91 new Thread(new ThreadGroup("TG " + tgNum), 92 new Runnable() { 93 @Override 94 public void run() { 95 sun.awt.SunToolkit.createNewAppContext(); 96 97 final AtomicReference<TestWindow> ref = 98 new AtomicReference<TestWindow>(); 99 100 SwingUtilities.invokeLater(new Runnable() { 101 @Override 102 public void run() { 103 final TestWindow window = new TestWindow(tgNum); 104 window.setVisible(true); 105 ref.set(window); 106 WINDOWS.add(window); 107 } 108 }); 109 110 // Wait for window to show 111 TestWindow window = ref.get(); 112 while (window == null) { 113 try { 114 Thread.sleep(100); 115 } catch (InterruptedException ie) { 116 ie.printStackTrace(); 117 } 118 window = ref.get(); 119 } 120 window.enableTimer(true); 121 } 122 }).start(); 123 } 124 125 private static final class TestWindow extends JFrame implements ActionListener { 126 127 private final JButton btn; 128 private int counter = 0; 129 private final Timer t; 130 131 TestWindow(final int num) { 132 super("Test Window [" + num + "]"); 133 setMinimumSize(new Dimension(300, 200)); 134 setLocation(100 + 400 * (num - 1), 100); 135 136 setLayout(new BorderLayout()); 137 JLabel textBlock = new JLabel("Lorem ipsum dolor sit amet..."); 138 add(textBlock); 139 140 btn = new JButton("TEST"); 141 add(btn, BorderLayout.SOUTH); 142 143 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 144 pack(); 145 146 t = new Timer(INTERVAL, this); 147 t.setRepeats(false); 148 } 149 150 @Override 151 public void actionPerformed(ActionEvent e) { 152 this.toFront(); 153 btn.setText("TEST " + (++counter)); 154 this.toBack(); 155 if (counter < MAX_COUNT) { 156 enableTimer(true); 157 } else { 158 dispose(); 159 } 160 } 161 162 void enableTimer(boolean enable) { 163 if (enable) { 164 t.start(); 165 } else { 166 t.stop(); 167 } 168 } 169 170 int getCounter() { 171 return counter; 172 } 173 } 174 }