Clover coverage report - clover
Coverage timestamp: Sat Oct 8 2005 22:54:17 EDT
file stats: LOC: 416   Methods: 21
NCLOC: 338   Classes: 7
 
 Source file Conditionals Statements Methods TOTAL
BugsTest.java 33.9% 39.7% 71.4% 40.9%
coverage coverage
 1   
 /*
 2   
  * Copyright 2002-2005 Timothy Wall
 3   
  *
 4   
  */
 5   
 package abbot.util;
 6   
 
 7   
 
 8   
 import java.awt.*;
 9   
 import java.awt.event.*;
 10   
 
 11   
 import javax.swing.*;
 12   
 
 13   
 import junit.extensions.abbot.*;
 14   
 import junit.extensions.abbot.Timer;
 15   
 import abbot.tester.Robot;
 16   
 import abbot.tester.ComponentTester;
 17   
 import abbot.Platform;
 18   
 
 19   
 /**
 20   
  Provides platform bugs detection.  Also serves as a repository of tests for
 21   
  all VM or OS-related bugs which affect Abbot operation.  A boolean test for
 22   
  each of these may appear in <code>abbot.util.Bugs</code>. <p> 
 23   
  Add tests that show the bug, then disable them only for the specific
 24   
  platform/VM versions that are known to display the bug (i.e. use
 25   
  Bugs.hasXXX() to avoid running the test).  This ensures that the bug
 26   
  is detected/tested for on new platforms/VMs, but doesn't needlessly clutter
 27   
  test results with known failures.  Define abbot.test.show_bugs=true in order
 28   
  to see the failures when running tests.
 29   
 
 30   
  @author twall
 31   
  */
 32   
 public class BugsTest extends ComponentTestFixture {
 33   
 
 34   
     /** Indicates whether to test for bugs on a platform where they are known
 35   
      * to exist, as opposed to silently ignoring them.
 36   
      */
 37   
     private static final boolean SHOW_BUGS =
 38   
         Boolean.getBoolean("abbot.test.show_bugs");
 39   
     private java.awt.Robot robot;
 40  9
     protected void setUp() throws Exception {
 41  9
         robot = new java.awt.Robot();
 42   
     }
 43   
     
 44   
     // OSX 1.4+
 45  1
     public void testWindowMotionBug() throws Exception {
 46   
         // NOTE: this test fails in AWT mode
 47  1
         if (Robot.getEventMode() == Robot.EM_AWT)
 48  0
             return;
 49   
 
 50  1
         if (!SHOW_BUGS && Bugs.hasMissingWindowMouseMotion())
 51  0
             return;
 52   
 
 53  1
         Frame f = new Frame(getName());
 54  1
         Window w = new Window(f);
 55  1
         showWindow(w, new Dimension(100, 100));
 56   
         class Flag { volatile boolean flag; }
 57  1
         final Flag flag1 = new Flag();
 58  1
         final Flag flag2 = new Flag();
 59  1
         AWTEventListener listener = new AWTEventListener() {
 60  2
             public void eventDispatched(AWTEvent e) {
 61  2
                 if (e.getID() == MouseEvent.MOUSE_MOVED) {
 62  2
                     flag1.flag = true;
 63   
                 }
 64   
             }
 65   
         };
 66  1
         w.addMouseMotionListener(new MouseMotionAdapter() {
 67  2
             public void mouseMoved(MouseEvent e) { flag2.flag = true; }
 68   
         });
 69  1
         new WeakAWTEventListener(listener, MouseEvent.MOUSE_MOTION_EVENT_MASK);
 70   
 
 71  1
         int x = w.getX() + w.getWidth()/2;
 72  1
         int y = w.getY() + w.getHeight()/2;
 73  1
         robot.mouseMove(x, y);
 74  1
         robot.mouseMove(x, y+1);
 75  1
         Timer timer = new Timer();
 76  1
         while (!flag1.flag || !flag2.flag) {
 77  0
             if (timer.elapsed() > 5000) {
 78  0
                 fail("No motion event received: AWTEventListener=" + flag1.flag
 79   
                      + ", MouseListener=" + flag2.flag);
 80   
             }
 81   
         }
 82   
     }
 83   
 
 84   
     // OSX 1.4+
 85  1
     public void testButtonSwapBug() throws Throwable {
 86   
         // NOTE: this test fails in AWT mode
 87  1
         if (Robot.getEventMode() == Robot.EM_AWT)
 88  0
             return;
 89  1
         if (!SHOW_BUGS && Bugs.hasRobotButtonsSwapped())
 90  0
             return;
 91  1
         javax.swing.JLabel label = new javax.swing.JLabel(getName());
 92  1
         MouseWatcher watcher = new MouseWatcher();
 93  1
         label.addMouseListener(watcher);
 94  1
         showFrame(label);
 95  1
         java.awt.Point pt = label.getLocationOnScreen();
 96  1
         robot.mouseMove(pt.x + label.getWidth()/2, pt.y + label.getHeight()/2);
 97  1
         robot.mousePress(MouseEvent.BUTTON2_MASK);
 98  1
         robot.mouseRelease(MouseEvent.BUTTON2_MASK);
 99  1
         Timer timer = new Timer();
 100  1
         while (!watcher.gotClick) {
 101  0
             if (timer.elapsed() > EVENT_GENERATION_DELAY)
 102  0
                 fail("Never received button 2 click event");
 103  0
             robot.delay(200);
 104   
         }
 105  1
         assertEquals("This platform has bad robot button 2 mask mapping",
 106   
                      MouseEvent.BUTTON2_MASK, watcher.modifiers);
 107   
 
 108  1
         watcher.gotClick = false;
 109  1
         robot.mousePress(MouseEvent.BUTTON3_MASK);
 110  1
         robot.mouseRelease(MouseEvent.BUTTON3_MASK);
 111  1
         timer.reset();
 112  1
         while (!watcher.gotClick) {
 113  0
             if (timer.elapsed() > EVENT_GENERATION_DELAY)
 114  0
                 fail("Never received button 3 click event");
 115  0
             robot.delay(200);
 116   
         }
 117  1
         assertEquals("This platform has bad robot button 3 mask mapping",
 118   
                      MouseEvent.BUTTON3_MASK, watcher.modifiers);
 119   
     }
 120   
 
 121   
     // Found on several platforms.  A subsequent mouse click on an entirely
 122   
     // different component is considered to have a click count of 2 if it
 123   
     // occurs within the double-click interval.
 124  1
     public void testMultiClickFrameBug() {
 125  1
         if (!SHOW_BUGS && Bugs.hasMultiClickFrameBug())
 126  1
             return;
 127  0
         String[] data = { "one", "two", "three", "four", "five" };
 128  0
         JFrame frame1 = new JFrame(getName() + "1");
 129  0
         JList list1 = new JList(data);
 130  0
         list1.setName("List 1");
 131  0
         frame1.getContentPane().add(list1);
 132   
         
 133  0
         JFrame frame2 = new JFrame(getName() + "2");
 134  0
         JList list2 = new JList(data);
 135  0
         list2.setName("List 2");
 136  0
         frame2.getContentPane().add(list2);
 137   
         
 138  0
         MouseWatcher mw1 = new MouseWatcher();
 139  0
         MouseWatcher mw2 = new MouseWatcher();
 140  0
         list1.addMouseListener(mw1);
 141  0
         list2.addMouseListener(mw2);
 142  0
         showWindow(frame1);
 143   
 
 144  0
         Point pt = list1.getLocationOnScreen();
 145  0
         robot.mouseMove(pt.x + list1.getWidth()/2, pt.y + list1.getHeight()/2);
 146  0
         robot.mousePress(MouseEvent.BUTTON1_MASK);
 147  0
         robot.mouseRelease(MouseEvent.BUTTON1_MASK);
 148  0
         robot.waitForIdle();
 149   
 
 150  0
         frame1.setVisible(false);
 151  0
         showWindow(frame2);
 152  0
         pt = list2.getLocationOnScreen();
 153  0
         robot.mouseMove(pt.x + list2.getWidth()/2, pt.y + list2.getHeight()/2);
 154  0
         robot.mousePress(MouseEvent.BUTTON1_MASK);
 155  0
         robot.mouseRelease(MouseEvent.BUTTON1_MASK);
 156  0
         robot.waitForIdle();
 157  0
         Timer timer = new Timer();
 158  0
         while (!mw1.gotClick) {
 159  0
             if (timer.elapsed() > EVENT_GENERATION_DELAY)
 160  0
                 fail("Never received click event on first frame");
 161  0
             robot.delay(200);
 162   
         }
 163  0
         timer.reset();
 164  0
         while (!mw2.gotClick) {
 165  0
             if (timer.elapsed() > EVENT_GENERATION_DELAY)
 166  0
                 fail("Never received click event on second frame");
 167  0
             robot.delay(200);
 168   
         }
 169  0
         assertEquals("Multi-click counting should not span frames",
 170   
                      1, mw1.clickCount);
 171  0
         assertEquals("Multi-click counting should not span frames",
 172   
                      1, mw2.clickCount);
 173   
     }
 174   
 
 175   
     /** W32 systems block on AWT PopupMenu.show.  If the method is invoked on
 176   
         the EDT, the result is that Robot.waitForIdle will lock up and events
 177   
         posted by Robot.postEvent will not be processed until the AWT popup
 178   
         goes away.  
 179   
     */
 180  1
     public void testShowAWTPopupMenuBlocks() throws Exception {
 181  1
         boolean blocks = Bugs.showAWTPopupMenuBlocks();
 182  1
         if (!SHOW_BUGS && blocks)
 183  1
             return;
 184   
 
 185  0
         Frame frame = new Frame(getName());
 186  0
         final PopupMenu popup = new PopupMenu();
 187  0
         MenuItem mi = new MenuItem("Open");
 188  0
         popup.add(mi);
 189  0
         final Label label = new Label(getName());
 190  0
         frame.add(label);
 191  0
         label.add(popup);
 192  0
         showWindow(frame);
 193  0
         assertEquals("Detected AWT popup state",
 194   
                      false, AWT.isAWTPopupMenuBlocking());
 195  0
         try {
 196   
             class Flag { volatile boolean flag; }
 197  0
             final Flag flag = new Flag();
 198  0
             Runnable show = new Runnable() {
 199  0
                 public void run() {
 200  0
                     popup.show(label, 0, label.getHeight());
 201   
                 }
 202   
             };
 203  0
             SwingUtilities.invokeLater(show);
 204  0
             SwingUtilities.invokeLater(new Runnable() {
 205  0
                 public void run() {
 206  0
                     flag.flag = true;
 207   
                 }
 208   
             });
 209  0
             Timer timer = new Timer();
 210  0
             while (!flag.flag) {
 211  0
                 if (timer.elapsed() > 5000)
 212  0
                     fail("An active AWT Popup blocks the event queue");
 213  0
                 Thread.sleep(10);
 214   
             }
 215   
         }
 216   
         finally {
 217  0
             AWT.dismissAWTPopup();
 218   
         }
 219   
     }
 220   
 
 221   
     /** Robot won't generate an ESC on OSX 1.3.1 (Apple VM bug). */
 222  1
     public void testEscapeKeyGenerationFailure() throws Exception {
 223  1
         final JTextField tf = new JTextField();
 224  1
         tf.setColumns(10);
 225  1
         KeyWatcher kw = new KeyWatcher();
 226  1
         tf.addKeyListener(kw);
 227  1
         showFrame(tf);
 228  1
     ComponentTester tester = new ComponentTester();
 229  1
     tester.actionFocus(tf);
 230  1
         int code = KeyEvent.VK_ESCAPE;
 231  1
         int mods = 0;
 232  1
     tester.actionKeyStroke(code, mods);
 233  1
         assertTrue("Never received key press", kw.gotPress);
 234  0
         assertTrue("Never received release", kw.gotRelease);
 235  0
         assertEquals("Wrong key code", code, kw.code);
 236  0
         assertEquals("Wrong modifiers", mods, kw.modifiers);
 237   
     }
 238   
 
 239  1
     public void testReportsIncorrectLockingKeyState() throws Throwable {
 240   
         // NOTE: this test fails in AWT mode
 241  1
         if (Robot.getEventMode() == Robot.EM_AWT)
 242  0
             return;
 243   
 
 244  1
         if (!SHOW_BUGS && Bugs.reportsIncorrectLockingKeyState())
 245  0
             return;
 246   
 
 247   
         // On w32, locking key state requires a non-disposed frame to work
 248   
         // properly! Not sure if this is a VM bug or not.
 249   
         // FIXME still gets sporadic failures on w32
 250  1
         if (Platform.isWindows()) {
 251  1
             showFrame(new JLabel(getName()));
 252   
         }
 253   
 
 254  1
         String[] KEYS = {
 255   
             "CAPS",
 256   
             "NUM",
 257   
             "SCROLL",
 258   
             "KANA",
 259   
         };
 260  1
         int[] CODES = { 
 261   
             KeyEvent.VK_CAPS_LOCK,
 262   
             KeyEvent.VK_NUM_LOCK,
 263   
             KeyEvent.VK_SCROLL_LOCK,
 264   
             KeyEvent.VK_KANA_LOCK,
 265   
         };
 266  1
     ComponentTester tester = new ComponentTester();
 267  1
         for (int i=0;i < CODES.length;i++) {
 268  4
             try {
 269  4
                 boolean state = Toolkit.getDefaultToolkit().
 270   
                     getLockingKeyState(CODES[i]);
 271  3
                 try {
 272  3
                     tester.actionKeyStroke(CODES[i]);
 273  3
                     boolean state2 = Toolkit.getDefaultToolkit().
 274   
                         getLockingKeyState(CODES[i]);
 275  3
                     assertEquals("Reported state of locking key '" + KEYS[i]
 276   
                                  + "' did not change",
 277   
                                  !state, state2);
 278   
                 }
 279   
                 finally {
 280  3
                     tester.actionKeyStroke(CODES[i]);
 281   
                 }
 282   
             }
 283   
             catch(UnsupportedOperationException e) {
 284   
                 // ignore
 285   
             }
 286   
             
 287   
         }
 288   
     }
 289   
 
 290  1
     public void testFileDialogMisreportsBounds() throws Exception {
 291  1
         if (!SHOW_BUGS && Bugs.fileDialogMisreportsBounds())
 292  1
             return;
 293  0
         JLabel label = new JLabel(getName());
 294  0
         Dimension size = Toolkit.getDefaultToolkit().getScreenSize();
 295  0
         Frame f = showFrame(label, size);
 296  0
         getRobot().move(f, 0, 0);
 297  0
         getRobot().waitForIdle();
 298  0
         FileDialog d = new FileDialog(f, getName(), FileDialog.LOAD);
 299   
         class Flag { volatile boolean flag; }
 300  0
         final Flag flag = new Flag();
 301  0
         FocusListener listener = new FocusAdapter() {
 302  0
             public void focusGained(FocusEvent e) {
 303  0
                 flag.flag = true;
 304   
             }
 305   
         };
 306  0
         size = new Dimension(400, 400);
 307  0
         showWindow(d, size, false);
 308  0
         getRobot().move(d, 100, 100);
 309  0
         getRobot().waitForIdle();
 310   
 
 311  0
         robot.delay(500);
 312  0
         getRobot().waitForIdle();
 313  0
         Point loc = d.getLocation();
 314  0
         Dimension dsize = d.getSize();
 315  0
         Rectangle actual =
 316   
             new Rectangle(loc.x, loc.y, dsize.width, dsize.height);
 317  0
         assertEquals("FileDialog reports wrong location or size",
 318   
                      new Rectangle(100, 100, 400, 400), actual);
 319   
 
 320   
         // Click inside the dialog; if the click misses, the frame will get
 321   
         // focus. 
 322  0
         f.addFocusListener(listener);
 323  0
         robot.mouseMove(loc.x + 50, loc.y + 50);
 324  0
         robot.mousePress(InputEvent.BUTTON1_MASK);
 325  0
         robot.mouseRelease(InputEvent.BUTTON1_MASK);
 326  0
         robot.delay(500);
 327  0
         robot.waitForIdle();
 328   
         // Note that no FOCUS_LOST or WINDOW_ACTIVATED is posted on the
 329   
         // FileDialog. 
 330  0
         assertFalse("Mouse click should not go to frame", flag.flag);
 331   
     }
 332   
 
 333  1
     public void testFileDialogRequiresDismiss() throws Exception {
 334  1
         if (!SHOW_BUGS && Bugs.fileDialogRequiresDismiss())
 335  1
             return;
 336  0
         Dimension size = Toolkit.getDefaultToolkit().getScreenSize();
 337  0
         JLabel label = new JLabel(getName());
 338  0
         Frame f = showFrame(label);
 339  0
         FileDialog d = new FileDialog(f, getName(), FileDialog.LOAD);
 340  0
         showWindow(d, null, false);
 341  0
         getRobot().move(f, (size.width - f.getWidth())/2,
 342   
                         (size.height - f.getHeight())/2);
 343  0
         getRobot().waitForIdle();
 344  0
         d.dispose();
 345  0
         assertFalse("Dialog should not be showing", d.isShowing());
 346   
 
 347   
         class Flag { volatile boolean flag; }
 348  0
         MouseWatcher mw = new MouseWatcher();
 349  0
         label.addMouseListener(mw);
 350   
 
 351  0
         robot.mouseMove(f.getX() + f.getWidth()/2, f.getY() + f.getHeight()/2);
 352  0
         robot.mousePress(InputEvent.BUTTON1_MASK);
 353  0
         robot.mouseRelease(InputEvent.BUTTON1_MASK);
 354  0
         robot.delay(500);
 355  0
         assertTrue("File Dialog is still showing", mw.gotPress);
 356   
     }
 357   
 
 358  1
     public void testHasKeyInputDelay() {
 359  1
         if (!SHOW_BUGS && Bugs.hasKeyInputDelay())
 360  0
             return;
 361  1
         if (Platform.isOSX())
 362  0
             fail("No test yet");
 363   
     }
 364   
 
 365   
     private class MouseWatcher extends MouseAdapter {
 366   
         public volatile boolean gotPress = false;
 367   
         public volatile boolean gotRelease = false;
 368   
         public volatile boolean gotClick = false;
 369   
         public volatile int clickCount = 0;
 370   
         public volatile boolean popupTrigger = false;
 371   
         public volatile Component source = null;
 372   
         public volatile int modifiers = 0;
 373   
         public volatile Point where = null;
 374  2
         public void mousePressed(MouseEvent me) {
 375  2
             gotPress = true;
 376  2
             source = me.getComponent();
 377  2
             popupTrigger = me.isPopupTrigger();
 378  2
             modifiers = me.getModifiers();
 379  2
             where = me.getPoint();
 380   
         }
 381  2
         public void mouseReleased(MouseEvent me) {
 382  2
             gotRelease = true;
 383  2
             popupTrigger = popupTrigger || me.isPopupTrigger();
 384   
         }
 385  2
         public void mouseClicked(MouseEvent me) {
 386  2
             gotClick = true;
 387  2
             clickCount = me.getClickCount();
 388   
         }
 389   
     }
 390   
 
 391   
     private class KeyWatcher extends KeyAdapter {
 392   
         public int code = KeyEvent.VK_UNDEFINED;
 393   
         public int modifiers = 0;
 394   
         public boolean gotPress = false;
 395   
         public boolean gotRelease = false;
 396  0
         public void keyPressed(KeyEvent ke) {
 397  0
             gotPress = true;
 398  0
             code = ke.getKeyCode();
 399  0
             modifiers = ke.getModifiers();
 400   
         }
 401  0
         public void keyReleased(KeyEvent ke) {
 402  0
             gotRelease = true;
 403   
         }
 404   
     }
 405   
 
 406  0
     public static void main(String[] args) {
 407  0
         if (!SHOW_BUGS) {
 408  0
             System.out.println("Use -Dabbot.test.show_bugs=true to run tests "
 409   
                                + "for known bugs on "
 410   
                                + System.getProperty("os.name") + ".");
 411  0
             System.out.println("By default, such tests are skipped.");
 412   
         }
 413  0
         RepeatHelper.runTests(args, BugsTest.class);
 414   
     }
 415   
 }
 416