assertj / assertj/assertj-swing

Orphaned event (EventQueue.dummyRunnable) in an eventQueue will break waitForIdle.

Aperta
#243 1 commento 0 reazioni 0 assegnatari Vedi su GitHub
Lingua principale
Java
Stelle
121
Fork
52
Metriche di merge delle PR
Nessuna PR unita negli ultimi 30g

Descrizione

I've seen a sporadic failure where waitForIdle gets into a state where it times out after 10 seconds. The application is actually idle when this happens. This causes a lot of grief for us because it makes all the test run at a snails pace (20 minutes instead of 20 seconds).

2 important conditions for this failure:

1) install a custom eventQueue via Toolkit.getDefaultToolkit().getSystemEventQueue().push()
2) create and hide a Window first. (this is a splash screen in our real app).

After a lot of debugging by adding logs to BasicRobot waitForIdle, I manage to catch it where the custom event queue was empty, but it was waiting for a java.awt.EventQueue to drain. It contained an InvocationEvent with this runnable. "runnable=java.awt.EventQueue$1@2d1630f3". Looking into that lead me to the first anonymous class in EventQueue, which is the member variable "dummyRunnable". That dummyRunnable is used in push/pop to wake up the EDT.

I theorized that if the EDT was already awake when the new Queue was pushed, then that event could be left.

That didn't fail initially when I only had 1 window and tried the push from within an InvokeAndWait. I then expanded the test to create a window, hide it, push a new queue and then wait.

That reproduces the failure. Simple test case below. I think that the first queue (for the hidden window?) is really dead? maybe it should be removed from the "windowMonitor.allEventQueues()" in BasicRobot? I got this far, and now I'm at a loss as to how to proceed.

```
package ajs.eq.fail;

import java.awt.EventQueue;
import java.awt.Toolkit;
import java.lang.reflect.InvocationTargetException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import org.assertj.swing.core.BasicRobot;

public class AjsEqFail {

private final static EventQueue myQueue = new EventQueue() {

};
public static void main(String[] args) {
BasicRobot r = (BasicRobot) BasicRobot.robotWithCurrentAwtHierarchy();
r.settings().simpleWaitForIdle(false);
final JFrame f = new JFrame();
f.setBounds(10,10,300,300);
f.setVisible(true);
r.waitForIdle();
System.out.println("waited");
try {
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
System.out.println("Hi3");
}
});
System.out.println("Hi1");
f.setVisible(false);
Toolkit.getDefaultToolkit().getSystemEventQueue().push(myQueue);
JFrame f2 = new JFrame();
f2.setVisible(true);
f2.setBounds(10,10,300,300);
System.out.println("Hi2");
}
});
} catch (InterruptedException ex) {
Logger.getLogger(AjsEqFail.class.getName()).log(Level.SEVERE, null, ex);
} catch (InvocationTargetException ex) {
Logger.getLogger(AjsEqFail.class.getName()).log(Level.SEVERE, null, ex);
}
r.waitForIdle(); //<-------------this times eventually (30 seconds?) but should be immediate.
System.out.println("waited2");
}

}

```

Guida per i contributori

Apri la guida per i contributori

Direzione di ricerca

Inizia con BasicRobot.waitForIdle e la gestione di windowMonitor.allEventQueues(), quindi esamina il comportamento di push/pop di java.awt.EventQueue attorno al riproduttore fornito. Esegui l’esempio con un JFrame nascosto e una EventQueue personalizzata; il lavoro è completato quando waitForIdle restituisce prontamente senza trattare una coda orfana o dummyRunnable come lavoro in sospeso.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
java
Ambito
desktop, testing-qa
Tipo di issue
Bug
Difficoltà
4/5
Tempo stimato
3-5 giorni
Stato di attività
Ferma
Chiarezza
Da chiarire
Idoneità per principianti
30/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.