1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 package ifc.accessibility;
28 
29 import com.sun.star.accessibility.AccessibleRole;
30 import com.sun.star.accessibility.XAccessible;
31 import com.sun.star.accessibility.XAccessibleContext;
32 import com.sun.star.accessibility.XAccessibleSelection;
33 import com.sun.star.uno.UnoRuntime;
34 
35 import lib.MultiMethodTest;
36 import lib.Status;
37 import lib.StatusException;
38 
39 
40 /**
41  * Testing <code>com.sun.star.accessibility.XAccessibleSelection</code>
42  * interface methods :
43  * <ul>
44  *  <li><code>selectAccessibleChild()</code></li>
45  *  <li><code>isAccessibleChildSelected()</code></li>
46  *  <li><code>clearAccessibleSelection()</code></li>
47  *  <li><code>selectAllAccessibleChildren()</code></li>
48  *  <li><code>getSelectedAccessibleChildCount()</code></li>
49  *  <li><code>getSelectedAccessibleChild()</code></li>
50  *  <li><code>deselectAccessibleChild()</code></li>
51  * </ul> <p>
52  *
53  * This test needs the following object relations :
54  * <ul>
55  *  <li> <code>'XAccessibleSelection.multiSelection'</code>
56  *  (of type <code>Boolean</code>) <b> optional </b>:
57  *   Indicates whether or not mutiply children could be selected.
58  *   If the relation is <code>false</code> then more than 1 child
59  *   couldn't be selected. </li>
60  * </ul> <p>
61  *
62  * @see com.sun.star.accessibility.XAccessibleSelection
63  */
64 public class _XAccessibleSelection extends MultiMethodTest {
65     private static final String className = "com.sun.star.accessibility.XAccessibleSelection";
66     public XAccessibleSelection oObj = null;
67     XAccessibleContext xAC = null;
68     int childCount;
69     protected boolean multiSelection = true;
70     protected boolean OneAlwaysSelected = false;
71 
72     // temporary while accessibility package is in com.sun.star
73     protected String getTestedClassName() {
74         return className;
75     }
76 
77     /**
78      * Retrieves the interface <code>XAccessibleContext</code>
79      * and object relation.
80      * @see com.sun.star.accessibility.XAccessibleContext
81      * @see ifc.accessibility.XAccessibleContext
82      */
83     protected void before() {
84         xAC = (XAccessibleContext) UnoRuntime.queryInterface(
85                       XAccessibleContext.class, oObj);
86 
87         if (xAC == null) {
88             throw new StatusException(Status.failed(
89                                               "Couldn't query XAccessibleContext. Test must be modified"));
90         }
91 
92         Boolean b = (Boolean) tEnv.getObjRelation(
93                             "XAccessibleSelection.multiSelection");
94 
95         if (b != null) {
96             multiSelection = b.booleanValue();
97         }
98 
99         Boolean b2 = (Boolean) tEnv.getObjRelation(
100                              "XAccessibleSelection.OneAlwaysSelected");
101 
102         if (b2 != null) {
103             OneAlwaysSelected = b2.booleanValue();
104         }
105 
106         childCount = xAC.getAccessibleChildCount();
107         log.println("Child count: " + childCount);
108     }
109 
110     /**
111      * Selects accessible child with index some wrong indexes
112      * and with legal index.
113      * Has OK status if exception was thrown for wrong indexes
114      * and if exception wasn't thrown for correct index.
115      */
116     public void _selectAccessibleChild() {
117         boolean res = true;
118 
119         try {
120             log.println("Try to select child with index " + childCount);
121             oObj.selectAccessibleChild(childCount);
122             log.println("Exception was expected");
123             res = false;
124         } catch (com.sun.star.lang.IndexOutOfBoundsException e) {
125             log.println("Expected exception");
126             res = true;
127         }
128 
129         try {
130             log.println("Try to select child with index -1");
131             oObj.selectAccessibleChild(-1);
132             log.println("Exception was expected");
133             res = false;
134         } catch (com.sun.star.lang.IndexOutOfBoundsException e) {
135             log.println("Expected exception");
136             res &= true;
137         }
138 
139         log.println("ChildCount: " + childCount);
140 
141         int usedChilds = childCount;
142 
143         if (childCount > 500) {
144             log.println("Restricting to 500");
145             usedChilds = 500;
146         }
147 
148         if (usedChilds > 0) {
149             try {
150                 for (int i = 0; i < usedChilds; i++) {
151                     log.print("Trying to select child with index " + i + ": ");
152 
153                     if (isSelectable(tEnv.getTestObject(), i)) {
154                         oObj.selectAccessibleChild(i);
155                         log.println("OK");
156                     } else {
157                         log.println("Child isn't selectable");
158                     }
159                 }
160 
161                 res &= true;
162             } catch (com.sun.star.lang.IndexOutOfBoundsException e) {
163                 log.println("Unexpected exception");
164                 e.printStackTrace(log);
165                 res = false;
166             }
167         }
168 
169         tRes.tested("selectAccessibleChild()", res);
170     }
171 
172     /**
173      * Calls the method with the wrong index and with the correct index.
174      * Has OK status if exception was thrown for wrong index and
175      * if exception wasn't thrown for the correct index.
176      */
177     public void _isAccessibleChildSelected() {
178         executeMethod("selectAccessibleChild()");
179 
180         boolean res = true;
181         boolean isSelected = false;
182 
183         try {
184             log.print("isAccessibleChildSelected(-1)? ");
185             isSelected = oObj.isAccessibleChildSelected(-1);
186             log.println(res);
187             log.println("Exception was expected");
188             res = false;
189         } catch (com.sun.star.lang.IndexOutOfBoundsException e) {
190             log.println("Expected exception");
191             res = true;
192         }
193 
194         try {
195             log.print("isAccessibleChildSelected(" + childCount + ")? ");
196             isSelected = oObj.isAccessibleChildSelected(childCount);
197             log.println(isSelected);
198             log.println("Exception was expected");
199             res = false;
200         } catch (com.sun.star.lang.IndexOutOfBoundsException e) {
201             log.println("Expected exception");
202             res &= true;
203         }
204 
205         int SelectableChildCount = chkSelectable(tEnv.getTestObject());
206 
207         if (SelectableChildCount > 500) {
208             SelectableChildCount = 500;
209         }
210 
211         log.println("SelectableChildCount: " + SelectableChildCount);
212 
213         if (SelectableChildCount > 0) {
214             try {
215                 oObj.selectAllAccessibleChildren();
216 
217                 for (int k = 0; k < SelectableChildCount; k++) {
218                     log.println("Trying to select child with index " + k);
219 
220                     if (isSelectable(tEnv.getTestObject(), k)) {
221                         oObj.selectAccessibleChild(k);
222                         shortWait();
223                         isSelected = oObj.isAccessibleChildSelected(k);
224                         log.println("isAccessibleChildSelected - " +
225                                     isSelected);
226                         res &= isSelected;
227                     } else {
228                         log.println("Child isn't selectable");
229                     }
230                 }
231             } catch (com.sun.star.lang.IndexOutOfBoundsException e) {
232                 log.println("Unexpected exception");
233                 e.printStackTrace(log);
234                 res = false;
235             }
236         }
237 
238         tRes.tested("isAccessibleChildSelected()", res);
239     }
240 
241     /**
242      * Calls the method.
243      * Has OK status if the method <code>isAccessibleChildSelected()</code>
244      * returned <code>false</code>.
245      */
246     public void _clearAccessibleSelection() {
247         executeMethod("isAccessibleChildSelected()");
248 
249         boolean res = true;
250 
251         log.println("clearAccessibleSelection");
252         oObj.clearAccessibleSelection();
253 
254 
255         // clearAccessibleSelection() call is oneway so we need
256         // some waiting
257         shortWait();
258 
259         if ((childCount > 0) && !OneAlwaysSelected) {
260             try {
261                 log.print("isAccessibleChildSelected(" + (childCount - 1) +
262                           ")? ");
263 
264                 boolean isSel = oObj.isAccessibleChildSelected(childCount - 1);
265                 log.println(isSel);
266                 res = !isSel;
267             } catch (com.sun.star.lang.IndexOutOfBoundsException e) {
268                 log.println("Unexpected exception");
269                 e.printStackTrace(log);
270                 res = false;
271             }
272         } else if (OneAlwaysSelected) {
273             log.println("Can't clear selection, one child is always selected");
274         }
275 
276         tRes.tested("clearAccessibleSelection()", res);
277     }
278 
279     /**
280      * Calls the method.
281      * Has OK status if the method <code>isAccessibleChildSelected()</code>
282      * returns <code>true</code> for first and for last accessible child
283      * or if multiselection is not allowed.
284      */
285     public void _selectAllAccessibleChildren() {
286         executeMethod("clearAccessibleSelection()");
287 
288         log.println("selectAllAccessibleChildren...");
289         oObj.selectAllAccessibleChildren();
290 
291 
292         // selectAllAccessibleChildren() call is oneway so we need
293         // some waiting
294         shortWait();
295 
296         boolean res = true;
297         boolean isSelected = true;
298 
299         int SelectableChildCount = chkSelectable(tEnv.getTestObject());
300 
301         if ((SelectableChildCount > 0) && multiSelection) {
302             try {
303                 log.print("isAccessibleChildSelected(1)? ");
304                 isSelected = oObj.isAccessibleChildSelected(1);
305                 log.println(isSelected);
306                 res = isSelected;
307 
308                 log.print("isAccessibleChildSelected(" + (childCount - 1) +
309                           ")? ");
310                 isSelected = oObj.isAccessibleChildSelected(childCount - 1);
311                 log.println(isSelected);
312                 res &= isSelected;
313             } catch (com.sun.star.lang.IndexOutOfBoundsException e) {
314                 log.println("Unexpected exception");
315                 e.printStackTrace(log);
316                 res = false;
317             }
318         }
319 
320         tRes.tested("selectAllAccessibleChildren()", res);
321     }
322 
323     /**
324      * Calls the method. Clears accessible selection and calls the method again.
325      * <p>
326      * Has OK status if the method returns number equal to number of accessible
327      * child count after first call if multiselection allowed, or
328      * 1 returned if multiselection not allowed.
329      * And if the method returns a zero after clearing selection.
330      */
331     public void _getSelectedAccessibleChildCount() {
332         log.println("getSelectedAccessibleChildCount():");
333 
334         if (multiSelection) {
335             oObj.selectAllAccessibleChildren();
336         } else {
337             int usedChilds = childCount;
338 
339             if (childCount > 500) {
340                 log.println("Restricting to 500");
341                 usedChilds = 500;
342             }
343 
344             if (usedChilds > 0) {
345                 try {
346                     for (int i = 0; i < usedChilds; i++) {
347 
348                         if (isSelectable(tEnv.getTestObject(), i)) {
349                             log.print("Trying to select child with index "+i+": ");
350                             oObj.selectAccessibleChild(i);
351                             long curtime = System.currentTimeMillis();
352                             long checktime = System.currentTimeMillis();
353 
354                             while (!oObj.isAccessibleChildSelected(i) && (checktime-curtime<5000)) {
355                                 checktime = System.currentTimeMillis();
356                             }
357 
358                             log.println("OK");
359                         }
360                     }
361                 } catch (com.sun.star.lang.IndexOutOfBoundsException e) {
362                     log.println("Unexpected exception");
363                     e.printStackTrace(log);
364                 }
365             }
366         }
367 
368         int sCount = chkSelectable(tEnv.getTestObject());
369         log.println("Found " + sCount + " selectable Childs");
370 
371         int selectedCount = oObj.getSelectedAccessibleChildCount();
372         log.println("After selecting all accessible " + selectedCount +
373                     " are selected");
374 
375         boolean res = true;
376 
377         if (multiSelection) {
378             res &= (selectedCount == sCount);
379         } else {
380             res &= (selectedCount == 1);
381         }
382 
383         log.println("clearAccessibleSelection...");
384         oObj.clearAccessibleSelection();
385         log.print("getSelectedAccessibleChildCount: ");
386         selectedCount = oObj.getSelectedAccessibleChildCount();
387         log.println(selectedCount);
388 
389         if (OneAlwaysSelected) {
390             res &= (selectedCount == 1);
391         } else {
392             res &= (selectedCount == 0);
393         }
394 
395         tRes.tested("getSelectedAccessibleChildCount()", res);
396     }
397 
398     /**
399      * Calls the method with wrong and correct indexes.
400      * Has OK status if exception was thrown for the wrong indexes,
401      * if exception wasn't thrown for the correct index and
402      * if the method have returned a not null for the correct index.
403      */
404     public void _getSelectedAccessibleChild() {
405         executeMethod("getSelectedAccessibleChildCount()");
406 
407         boolean res = true;
408         int selectedCount = oObj.getSelectedAccessibleChildCount();
409         log.println("getSelectedAccessibleChildCount: " + selectedCount);
410 
411         try {
412             log.println("getSelectedAccessibleChild(-1)");
413             oObj.getSelectedAccessibleChild(-1);
414             log.println("Exception was expected");
415             res = false;
416         } catch (com.sun.star.lang.IndexOutOfBoundsException e) {
417             log.println("Expected exception");
418             res = true;
419         }
420 
421         try {
422             log.println("getSelectedAccessibleChild(" + selectedCount + ")");
423             oObj.getSelectedAccessibleChild(selectedCount);
424             log.println("Exception was expected");
425             res &= false;
426         } catch (com.sun.star.lang.IndexOutOfBoundsException e) {
427             log.println("Expected exception");
428             res &= true;
429         }
430 
431         int SelectableChildCount = chkSelectable(tEnv.getTestObject());
432 
433         if (SelectableChildCount > 500) {
434             SelectableChildCount = 500;
435         }
436 
437         if (SelectableChildCount > 0) {
438             int k = 0;
439             try {
440                 for (k = 0; k < SelectableChildCount; k++) {
441                     log.println("Trying to select child with index " + k);
442 
443                     if (isSelectable(tEnv.getTestObject(), k)) {
444                         oObj.selectAccessibleChild(k);
445                         shortWait();
446                         log.println("selected child count: " +
447                                     oObj.getSelectedAccessibleChildCount());
448                         XAccessible selChild = oObj.getSelectedAccessibleChild(0);
449                         res &= (selChild != null);
450                         log.println("valid child - " + (selChild != null));
451                     } else {
452                         log.println("Child isn't selectable");
453                     }
454                 }
455             } catch (com.sun.star.lang.IndexOutOfBoundsException e) {
456                 log.println("Unexpected exception: Last relevant calls:\n " +
457                             "\toObj.selectAccessibleChild("+k+")\n" +
458                             "\toObj.getSelectedAccessibleChild(0)");
459                 e.printStackTrace(log);
460                 res = false;
461             }
462         }
463 
464         tRes.tested("getSelectedAccessibleChild()", res);
465     }
466 
467     /**
468      * Calls the method with wrong and with correct indexes.
469      * Has OK status if exceptions were thrown for the calls with
470      * the wrong indexes, if exception wasn't thrown for the call
471      * with correct index and if number of selected child was
472      * decreased after the correct call.
473      */
474     public void _deselectAccessibleChild() {
475         executeMethod("getSelectedAccessibleChild()");
476 
477         boolean res = true;
478         int selCount = oObj.getSelectedAccessibleChildCount();
479         log.println("getSelectedAccessibleChildCount():" + selCount);
480 
481         try {
482             log.println("deselectAccessibleChild(-1)");
483             oObj.deselectAccessibleChild(-1);
484             log.println("Exception was expected");
485             res = false;
486         } catch (com.sun.star.lang.IndexOutOfBoundsException e) {
487             log.println("Expected exception");
488             res &= true;
489         }
490 
491         try {
492             log.println("deselectAccessibleChild(" + (childCount + 1) + ")");
493             oObj.deselectAccessibleChild(childCount + 1);
494             log.println("Exception was expected");
495             res = false;
496         } catch (com.sun.star.lang.IndexOutOfBoundsException e) {
497             log.println("Expected exception");
498             res &= true;
499         }
500 
501         log.println("#################");
502         log.println("Selecting all accessible");
503         oObj.selectAllAccessibleChildren();
504         selCount = oObj.getSelectedAccessibleChildCount();
505         log.println("getSelectedAccessibleChildCount():" + selCount);
506 
507         if ((childCount > 0) && (selCount > 0)) {
508             try {
509                 int maxCount = chkSelectable(tEnv.getTestObject());
510 
511                 if (childCount > 100) {
512                     maxCount = 100;
513                 }
514 
515                 for (int k = 0; k < maxCount; k++) {
516                     log.println("deselectAccessibleChild(" + k + ")");
517 
518                     if (oObj.isAccessibleChildSelected(k)) {
519                         oObj.deselectAccessibleChild(k);
520                     }
521                 }
522 
523                 int newSelCount = oObj.getSelectedAccessibleChildCount();
524                 log.println("getSelectedAccessibleChildCount():" +
525                             newSelCount);
526 
527                 if (OneAlwaysSelected && (selCount == 1)) {
528                     log.println("One Child is always selected");
529                     res &= true;
530                 } else {
531                     res &= (selCount > newSelCount);
532                 }
533             } catch (com.sun.star.lang.IndexOutOfBoundsException e) {
534                 log.println("Unexpected exception");
535                 e.printStackTrace(log);
536                 res = false;
537             }
538         }
539 
540         tRes.tested("deselectAccessibleChild()", res);
541     }
542 
543     protected static int chkSelectable(Object Testcase) {
544         int ret = 0;
545         XAccessibleContext accCon = (XAccessibleContext) UnoRuntime.queryInterface(
546                                             XAccessibleContext.class, Testcase);
547         int cc = accCon.getAccessibleChildCount();
548 
549         if (cc > 500) {
550             return cc;
551         }
552 
553         for (int i = 0; i < cc; i++) {
554             try {
555                 if (accCon.getAccessibleChild(i).getAccessibleContext()
556                           .getAccessibleStateSet()
557                           .contains(com.sun.star.accessibility.AccessibleStateType.SELECTABLE)) {
558                     ret = ret + 1;
559                     System.out.println("Child " + i + " is selectable");
560                 }
561             } catch (com.sun.star.lang.IndexOutOfBoundsException iab) {
562             }
563         }
564 
565         return ret;
566     }
567 
568     protected static boolean isSelectable(Object Testcase, int index) {
569         XAccessibleContext accCon = (XAccessibleContext) UnoRuntime.queryInterface(
570                                             XAccessibleContext.class, Testcase);
571         boolean res = false;
572 
573         try {
574             if (accCon.getAccessibleChild(index).getAccessibleContext()
575                       .getAccessibleStateSet()
576                       .contains(com.sun.star.accessibility.AccessibleStateType.SELECTABLE)) {
577                 res = true;
578             }
579 
580             //selecting menuitems or the separator will lead to closing the menu
581             if ((accCon.getAccessibleChild(index).getAccessibleContext()
582                        .getAccessibleRole() == AccessibleRole.MENU_ITEM) ||
583                     (accCon.getAccessibleChild(index).getAccessibleContext()
584                            .getAccessibleRole() == AccessibleRole.SEPARATOR)) {
585                 res = false;
586             }
587         } catch (com.sun.star.lang.IndexOutOfBoundsException e) {
588             System.out.println("Exception while checking for selectability");
589         }
590 
591         return res;
592     }
593 
594     private void shortWait() {
595         try {
596             Thread.sleep(500);
597         } catch (InterruptedException ex) {
598         }
599     }
600 }