1 /*
   2   test %I% %E%
   3   @bug 6315717
   4   @summary presses buttons in all permutations and verifies modifiers
   5   @author Andrei Dmitriev : area=awt.mouse
   6   @run main ModifierPermutation
   7  */
   8 //package modifierpermutation;
   9 
  10 /*
  11 The test will try to press-release every button present on the mouse in different order.
  12 Here are some abbreviations:
  13  BUTTON1 press = P1
  14  BUTTON2 press = P2 etc.
  15  BUTTON1 release = R1
  16  BUTTON2 release = R2 etc.
  17 Only sequences alike below are possible : <P1, P2, R2, R1>.
  18 Sequences like <P1, P2, R1, R2> will not be covered by this test due to its probable complexity.
  19  */
  20 
  21 import java.awt.*;
  22 import sun.awt.SunToolkit;
  23 import java.awt.event.*;
  24 import java.util.Arrays;
  25 
  26 public class ModifierPermutation {
  27     static boolean failed = false;
  28     final static int BUTTONSNUMBER = MouseInfo.getNumberOfButtons();
  29 
  30 /*
  31  * Because of some problems with BUTTONx_MASK
  32  * (they are not ordered. Instead, their values are: 16 8 4)
  33  * We have to use array [1..n] and make every permutation on its
  34  * containment. After each permutation, make the same thing with
  35  * array of buttons and array of expected modifiers.
  36  */
  37     static SunToolkit st = (SunToolkit)(Toolkit.getDefaultToolkit());
  38     //all button masks
  39     static int [] mouseButtons = new int [BUTTONSNUMBER]; //BUTTONx_MASK
  40     static int [] mouseButtonsDown = new int [BUTTONSNUMBER]; //BUTTONx_DOWN_MASK
  41 
  42     //used to store mouse buttons sequences to press/to release
  43     static int [] affectedButtonsToPressRelease;
  44 //    static int [] buttonsToRelease;
  45 //    static int [] modifiersToVerifyOnPressRelease;
  46 
  47     static Robot robot;
  48     static CheckingAdapter adapterTest1;
  49     static Frame f;
  50 
  51     static {
  52         for (int i = 0; i < BUTTONSNUMBER; i++){
  53             mouseButtons[i] = InputEvent.getMaskForButton(i+1); //then change first three elements here to BUTTONx_MASK
  54             mouseButtonsDown[i] = InputEvent.getMaskForButton(i+1);
  55         }
  56         //mouseButtons initially has following values : 16 8 4.
  57 /*        mouseButtons[0] = InputEvent.BUTTON1_MASK;
  58         mouseButtons[1] = InputEvent.BUTTON2_MASK;
  59         mouseButtons[2] = InputEvent.BUTTON3_MASK;
  60  */
  61     }
  62 
  63     public static void main(String s[]){
  64         init();
  65 
  66         try {
  67             robot = new Robot();
  68         } catch (Exception e){
  69             e.printStackTrace();
  70             throw new RuntimeException("Test failed.", e);
  71         }
  72         robot.delay(500);
  73         robot.mouseMove(f.getLocationOnScreen().x + f.getWidth()/2, f.getLocationOnScreen().y + f.getHeight()/2);
  74         robot.delay(500);
  75         //Top limit is the factorial of the number of existing buttons
  76         for (int k = 0; k < factorial(mouseButtons.length)-1; k++){
  77             //now we will press 2 up to maximum buttons and release them in different order and listen for
  78             // PRESSED events and check it's ExModifiers
  79             for (int buttonsToPressNumber = 2; buttonsToPressNumber <= BUTTONSNUMBER; buttonsToPressNumber++ ){
  80                 System.out.println(">>>");
  81 
  82                 //Now get the slice of affected buttons
  83                 affectedButtonsToPressRelease = Arrays.copyOf(mouseButtons, buttonsToPressNumber);
  84 //                modifiersToVerifyOnPressRelease = Arrays.copyOf(mouseButtons, buttonsToPressNumber);
  85 
  86                 //Now press all these buttons in the order as they are in array affectedButtonsToPressRelease
  87                 //And release all these buttons in back order.
  88 
  89                 dumpArray("Affected Buttons ", affectedButtonsToPressRelease);
  90                 pressAllButtons(affectedButtonsToPressRelease);
  91                 releaseAllButtonsForwardOrder(affectedButtonsToPressRelease);
  92 //                    nextPermutation(i, buttonsToRelease);
  93                 //TODO: press buttons and release them backward
  94                 //All I have to add is :
  95 //                pressAllButtons(affectedButtonsToPressRelease);
  96 //                releaseAllButtonsBackwardOrder(affectedButtonsToPressRelease);
  97 
  98                 System.out.println("<<<");
  99             }
 100             nextPermutation(k, mouseButtons);
 101 //            PermutationGenerator.nextPermutation(k, mouseButtonsDown);
 102             dumpArray("mouseButtons (step="+k+")", mouseButtons);
 103 //            dumpArray("mouseButtonsDown (step="+k+")", mouseButtonsDown);
 104         }
 105     }
 106 
 107     private static void init(){
 108         adapterTest1 = new CheckingAdapter();
 109         f = new Frame("Robot presses mouse here");
 110         f.setSize(300, 300);
 111         f.setVisible(true);
 112         f.addMouseListener(adapterTest1);
 113     }
 114     public static int factorial(int t){
 115         if (t <=1 ) {
 116             return 1;
 117         } else {
 118             return t*factorial(t-1);
 119         }
 120     }
 121 
 122     // use this variable to get current button on EDT in checkModifiers()
 123     static volatile int currentButtonIndexUnderAction;
 124 
 125     public static void pressAllButtons(int []array){
 126         for (int i = 0; i <array.length; i ++){
 127             if (failed) {
 128                 throw new RuntimeException("PRESSED_EVENT is not filled with correct values. Review messaage above.");
 129             }
 130             System.out.println("Pressing button = " + array[i]);
 131             currentButtonIndexUnderAction = i;
 132             robot.mousePress(array[i]);
 133             System.out.println("currentButtonIndexUnderAction ="+currentButtonIndexUnderAction);
 134             st.realSync();
 135             //            robot.delay(100);
 136         }
 137     }
 138 
 139     public static void releaseAllButtonsForwardOrder(int []array){
 140         for (int i = 0; i <array.length; i ++){
 141             System.out.println("Releasing button = " + array[i]);
 142             currentButtonIndexUnderAction = i;
 143             robot.mouseRelease(array[i]);
 144             System.out.println("currentButtonIndexUnderAction ="+currentButtonIndexUnderAction);
 145             st.realSync();
 146             //            robot.delay(100);
 147         }
 148     }
 149 
 150     public static void checkModifiersOnPress(MouseEvent e){
 151         System.out.println("checkModifiers. currentButtonIndexUnderAction ="+currentButtonIndexUnderAction);
 152         for (int i = 0; i<= currentButtonIndexUnderAction; i++){
 153             if ((e.getModifiersEx() & affectedButtonsToPressRelease[i]) == 0){
 154                 System.out.println("ERROR["+i+"]: PRESSED_EVENT is not filled with correct values. affectedButtonsToPressRelease[i]= "+affectedButtonsToPressRelease[i] +" Event = "+e);
 155                 ModifierPermutation.failed = true;
 156             } else {
 157                 System.out.println("CORRECT["+i+"]: affectedButtonsToPressRelease[i]= "+affectedButtonsToPressRelease[i]+ " Event = "+e);
 158             }
 159         }
 160     }
 161 
 162     /*======================================================================*/
 163     public static void dumpValues(int button, int modifiers, int modifiersStandard, int modifiersEx, int modifiersExStandard){
 164         System.out.println("Button = "+button + "Modifiers = "+ modifiers + " standard = "+ modifiersStandard);
 165         System.out.println("                   ModifiersEx = "+ modifiersEx + " standardEx = "+ modifiersExStandard);
 166     }
 167 
 168     public static void dumpArray(String id, int [] array){
 169         System.out.print(id);
 170         for (int i = 0; i < array.length; i++){
 171             System.out.print(array[i]+" ");
 172         }
 173         System.out.println();
 174     }
 175     public static void nextPermutation(int step, int []array){
 176         int i;
 177         int leftEl = 0;
 178         int rightEl = 0;
 179 
 180         i = array.length - 2;
 181         while (i>=0) {
 182             if (array[i] < array[i+1]){
 183                 leftEl = i;
 184                 //                        System.out.println("leftEl = "+leftEl);
 185                 break;
 186             }
 187             i--;
 188         }
 189 
 190         i = array.length - 1;
 191         while (i>=0) {
 192             if (array[i] > array[leftEl]) {
 193                 rightEl = i;
 194                 //                        System.out.println("rightEl = "+rightEl);
 195                 break;
 196             }
 197             i--;
 198         }
 199         swapElements(array, leftEl, rightEl);
 200         if (leftEl + 2 <  array.length){
 201             //                    System.out.println("sort");
 202             Arrays.sort(array, leftEl + 1 , array.length);
 203         }
 204     }
 205 
 206     public static void swapElements(int [] array, int leftEl, int rightEl){
 207         int tmp = array[leftEl];
 208         array[leftEl] = array[rightEl];
 209         array[rightEl] = tmp;
 210     }
 211 
 212     public static void checkModifiersOnRelease(MouseEvent e){
 213         System.out.println("CheckModifiersOnRelease. currentButtonIndexUnderAction ="+currentButtonIndexUnderAction);
 214         for (int i = currentButtonIndexUnderAction+1; i<affectedButtonsToPressRelease.length; i++){
 215             if ((e.getModifiersEx() & affectedButtonsToPressRelease[i]) == 0){
 216                 System.out.println("ERROR["+i+"]: RELEASED_EVENT is not filled with correct values. affectedButtonsToPressRelease[i]= "+affectedButtonsToPressRelease[i] +" Event = "+e);
 217                 ModifierPermutation.failed = true;
 218             } else {
 219                 System.out.println("CORRECT["+i+"]: affectedButtonsToPressRelease[i]= "+affectedButtonsToPressRelease[i]+ " Event = "+e);
 220             }
 221         }
 222     }
 223 
 224     public static void checkModifiersOnClick(MouseEvent e){
 225         System.out.println("CheckModifiersOnClick. currentButtonIndexUnderAction ="+currentButtonIndexUnderAction);
 226 //Actually the same as in checkModifiersOnRelease()
 227         for (int i = currentButtonIndexUnderAction+1; i<affectedButtonsToPressRelease.length; i++){
 228             if ((e.getModifiersEx() & affectedButtonsToPressRelease[i]) == 0){
 229                 System.out.println("ERROR["+i+"]: CLICK_EVENT is not filled with correct values. affectedButtonsToPressRelease[i]= "+affectedButtonsToPressRelease[i] +" Event = "+e);
 230                 ModifierPermutation.failed = true;
 231             } else {
 232                 System.out.println("CORRECT["+i+"]: affectedButtonsToPressRelease[i]= "+affectedButtonsToPressRelease[i]+ " Event = "+e);
 233             }
 234         }
 235     }
 236 }
 237 ///~ ModifierPermutation clas
 238 
 239 /* A class that invoke appropriate verification
 240  * routine with current modifier.
 241  */
 242 class CheckingAdapter extends MouseAdapter{
 243     public CheckingAdapter(){}
 244 
 245     public void mousePressed(MouseEvent e) {
 246         System.out.println("PRESSED "+e);
 247         ModifierPermutation.checkModifiersOnPress(e);
 248     }
 249     public void mouseReleased(MouseEvent e) {
 250         System.out.println("RELEASED "+e);
 251         ModifierPermutation.checkModifiersOnRelease(e);
 252 
 253     }
 254     public void mouseClicked(MouseEvent e) {
 255         System.out.println("CLICKED "+e);
 256         ModifierPermutation.checkModifiersOnClick(e);
 257     }
 258 }
 259 
 260 // A class that could make a standard permutation with no regard to the
 261 // values of array passed in.
 262 // It uses a buttonIndicesToPermutate array with [1..N] values to perform
 263 // these permutations.
 264 //Note that nextPermutation is a static method and you can't keep track
 265 // of more the single permutation sequence.
 266 /*
 267 class PermutationGenerator{
 268     final static int BUTTONSNUMBER = MouseInfo.getNumberOfButtons();
 269     static int [] buttonIndicesToPermutate = new int [BUTTONSNUMBER];;
 270     public PermutationGenerator(){
 271         for (int i = 0; i < BUTTONSNUMBER; i++){
 272             buttonIndicesToPermutate[i] = i+1; //fill it with [1..N] values
 273         }
 274     }
 275 
 276     public static void nextPermutation(int step, int []array){
 277         if (array.length != buttonIndicesToPermutate.length) {
 278             throw new IllegalArgumentException("Array should have length equals to mouse buttons number.");
 279         }
 280         int i;
 281         int leftEl = 0;
 282         int rightEl = 0;
 283 
 284         i = array.length - 2;
 285         while (i>=0) {
 286             if (buttonIndicesToPermutate[i] < buttonIndicesToPermutate[i+1]){
 287                 leftEl = i;
 288                 //                        System.out.println("leftEl = "+leftEl);
 289                 break;
 290             }
 291             i--;
 292         }
 293 
 294         i = array.length - 1;
 295         while (i>=0) {
 296             if (buttonIndicesToPermutate[i] >buttonIndicesToPermutate[leftEl]) {
 297                 rightEl = i;
 298                 //                        System.out.println("rightEl = "+rightEl);
 299                 break;
 300             }
 301             i--;
 302         }
 303         swapElements(array, leftEl, rightEl);
 304         swapElements(buttonIndicesToPermutate, leftEl, rightEl);
 305 
 306         if (leftEl + 2 <  array.length){
 307             //                    System.out.println("sort");
 308 //need to make our own sorting because arraysort makes this on actual values in array...
 309             Arrays.sort(array, leftEl + 1 , array.length);
 310             Arrays.sort(buttonIndicesToPermutate, leftEl + 1 , buttonIndicesToPermutate.length);
 311 //            sortArray(array, leftEl + 1 , array.length);
 312         }
 313     }
 314     public static void swapElements(int [] array, int leftEl, int rightEl){
 315         int tmp = array[leftEl];
 316         array[leftEl] = array[rightEl];
 317         array[rightEl] = tmp;
 318     }
 319 }
 320 */