VirtualBox

source: vbox/trunk/src/VBox/Additions/x11/VBoxClient/testcase/tstSeamlessX11-auto.cpp

Last change on this file was 99601, checked in by vboxsync, 13 months ago

Guest Additions/VBoxClient: Moved the X11-specific code for seamless mode into an own submodule and using the actual service as a (runtime) wrapper (for also the Wayland-specific code later) [build fix]. bugref:10427

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 24.6 KB
Line 
1/* $Id: tstSeamlessX11-auto.cpp 99601 2023-05-04 10:43:08Z vboxsync $ */
2/** @file
3 * Automated test of the X11 seamless Additions code.
4 * @todo Better separate test data from implementation details!
5 */
6
7/*
8 * Copyright (C) 2007-2023 Oracle and/or its affiliates.
9 *
10 * This file is part of VirtualBox base platform packages, as
11 * available from https://www.virtualbox.org.
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation, in version 3 of the
16 * License.
17 *
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 * General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, see <https://www.gnu.org/licenses>.
25 *
26 * SPDX-License-Identifier: GPL-3.0-only
27 */
28
29#include <stdlib.h> /* exit() */
30
31#include <X11/Xatom.h>
32#include <X11/Xmu/WinUtil.h>
33
34#include <iprt/initterm.h>
35#include <iprt/mem.h>
36#include <iprt/path.h>
37#include <iprt/semaphore.h>
38#include <iprt/stream.h>
39#include <iprt/string.h>
40
41#include "../seamless.h"
42
43#undef DefaultRootWindow
44
45/******************************************************
46* Mock X11 functions needed by the seamless X11 class *
47******************************************************/
48
49int XFree(void *data)
50{
51 RTMemFree(data);
52 return 0;
53}
54
55#define TEST_DISPLAY ((Display *)0xffff)
56#define TEST_ROOT ((Window)1)
57
58void VBClLogError(const char *pszFormat, ...)
59{
60 va_list args;
61 va_start(args, pszFormat);
62 char *psz = NULL;
63 RTStrAPrintfV(&psz, pszFormat, args);
64 va_end(args);
65
66 AssertPtr(psz);
67 RTPrintf("Error: %s", psz);
68
69 RTStrFree(psz);
70}
71
72/** Exit with a fatal error. */
73void VBClLogFatalError(const char *pszFormat, ...)
74{
75 va_list args;
76 va_start(args, pszFormat);
77 char *psz = NULL;
78 RTStrAPrintfV(&psz, pszFormat, args);
79 va_end(args);
80
81 AssertPtr(psz);
82 RTPrintf("Fatal error: %s", psz);
83
84 RTStrFree(psz);
85
86 exit(1);
87}
88
89void VBClLogVerbose(unsigned iLevel, const char *pszFormat, ...)
90{
91 RT_NOREF(iLevel);
92
93 va_list va;
94 va_start(va, pszFormat);
95 RTPrintf("%s", pszFormat);
96 va_end(va);
97}
98
99extern "C" Display *XOpenDisplay(const char *display_name);
100Display *XOpenDisplay(const char *display_name)
101{
102 RT_NOREF1(display_name);
103 return TEST_DISPLAY;
104}
105
106extern "C" int XCloseDisplay(Display *display);
107int XCloseDisplay(Display *display)
108{
109 RT_NOREF1(display);
110 Assert(display == TEST_DISPLAY);
111 return 0;
112}
113
114enum
115{
116 ATOM_PROP = 1,
117 ATOM_DESKTOP_PROP
118};
119
120extern "C" Atom XInternAtom(Display *display, const char *atom_name, Bool only_if_exists);
121Atom XInternAtom(Display *display, const char *atom_name, Bool only_if_exists)
122{
123 RT_NOREF2(only_if_exists, display);
124 Assert(display == TEST_DISPLAY);
125 if (!RTStrCmp(atom_name, WM_TYPE_PROP))
126 return (Atom) ATOM_PROP;
127 if (!RTStrCmp(atom_name, WM_TYPE_DESKTOP_PROP))
128 return (Atom) ATOM_DESKTOP_PROP;
129 AssertFailed();
130 return (Atom)0;
131}
132
133/** The window (if any) on which the WM_TYPE_PROP property is set to the
134 * WM_TYPE_DESKTOP_PROP atom. */
135static Window g_hSmlsDesktopWindow = 0;
136
137extern "C" int XGetWindowProperty(Display *display, Window w, Atom property,
138 long long_offset, long long_length,
139 Bool delProp, Atom req_type,
140 Atom *actual_type_return,
141 int *actual_format_return,
142 unsigned long *nitems_return,
143 unsigned long *bytes_after_return,
144 unsigned char **prop_return);
145int XGetWindowProperty(Display *display, Window w, Atom property,
146 long long_offset, long long_length, Bool delProp,
147 Atom req_type, Atom *actual_type_return,
148 int *actual_format_return,
149 unsigned long *nitems_return,
150 unsigned long *bytes_after_return,
151 unsigned char **prop_return)
152{
153 RT_NOREF2(display, long_length);
154 Assert(display == TEST_DISPLAY);
155 Atom atomType = XInternAtom (display, WM_TYPE_PROP, true);
156 Atom atomTypeDesktop = XInternAtom (display, WM_TYPE_DESKTOP_PROP, true);
157 /* We only handle things we expect. */
158 AssertReturn((req_type == XA_ATOM) || (req_type == AnyPropertyType),
159 0xffff);
160 AssertReturn(property == atomType, 0xffff);
161 *actual_type_return = XA_ATOM;
162 *actual_format_return = sizeof(Atom) * 8;
163 *nitems_return = 0;
164 *bytes_after_return = sizeof(Atom);
165 *prop_return = NULL;
166 if ((w != g_hSmlsDesktopWindow) || (g_hSmlsDesktopWindow == 0))
167 return Success;
168 AssertReturn(long_offset == 0, 0);
169 AssertReturn(delProp == false, 0);
170 unsigned char *pProp;
171 pProp = (unsigned char *)RTMemDup(&atomTypeDesktop,
172 sizeof(atomTypeDesktop));
173 AssertReturn(pProp, 0xffff);
174 *nitems_return = 1;
175 *prop_return = pProp;
176 *bytes_after_return = 0;
177 return 0;
178}
179
180#if 0 /* unused */
181/** Sets the current set of properties for all mock X11 windows */
182static void smlsSetDesktopWindow(Window hWin)
183{
184 g_hSmlsDesktopWindow = hWin;
185}
186#endif
187
188extern "C" Bool XShapeQueryExtension(Display *dpy, int *event_basep, int *error_basep);
189Bool XShapeQueryExtension(Display *dpy, int *event_basep, int *error_basep)
190{
191 RT_NOREF3(dpy, event_basep, error_basep);
192 Assert(dpy == TEST_DISPLAY);
193 return true;
194}
195
196/* We silently ignore this for now. */
197extern "C" int XSelectInput(Display *display, Window w, long event_mask);
198int XSelectInput(Display *display, Window w, long event_mask)
199{
200 RT_NOREF3(display, w, event_mask);
201 Assert(display == TEST_DISPLAY);
202 return 0;
203}
204
205/* We silently ignore this for now. */
206extern "C" void XShapeSelectInput(Display *display, Window w, unsigned long event_mask);
207void XShapeSelectInput(Display *display, Window w, unsigned long event_mask)
208{
209 RT_NOREF3(display, w, event_mask);
210 Assert(display == TEST_DISPLAY);
211}
212
213extern "C" Window XDefaultRootWindow(Display *display);
214Window XDefaultRootWindow(Display *display)
215{
216 RT_NOREF1(display);
217 Assert(display == TEST_DISPLAY);
218 return TEST_ROOT;
219}
220
221static unsigned g_cSmlsWindows = 0;
222static Window *g_paSmlsWindows = NULL;
223static XWindowAttributes *g_paSmlsWinAttribs = NULL;
224static const char **g_papszSmlsWinNames = NULL;
225
226extern "C" Status XQueryTree(Display *display, Window w, Window *root_return,
227 Window *parent_return, Window **children_return,
228 unsigned int *nchildren_return);
229Status XQueryTree(Display *display, Window w, Window *root_return,
230 Window *parent_return, Window **children_return,
231 unsigned int *nchildren_return)
232{
233 RT_NOREF1(display);
234 Assert(display == TEST_DISPLAY);
235 AssertReturn(w == TEST_ROOT, False); /* We support nothing else */
236 AssertPtrReturn(children_return, False);
237 AssertReturn(g_paSmlsWindows, False);
238 if (root_return)
239 *root_return = TEST_ROOT;
240 if (parent_return)
241 *parent_return = TEST_ROOT;
242 *children_return = (Window *)RTMemDup(g_paSmlsWindows,
243 g_cSmlsWindows * sizeof(Window));
244 if (nchildren_return)
245 *nchildren_return = g_cSmlsWindows;
246 return (g_cSmlsWindows != 0);
247}
248
249extern "C" Window XmuClientWindow(Display *dpy, Window win);
250Window XmuClientWindow(Display *dpy, Window win)
251{
252 RT_NOREF1(dpy);
253 Assert(dpy == TEST_DISPLAY);
254 return win;
255}
256
257extern "C" Status XGetWindowAttributes(Display *display, Window w,
258 XWindowAttributes *window_attributes_return);
259Status XGetWindowAttributes(Display *display, Window w,
260 XWindowAttributes *window_attributes_return)
261{
262 RT_NOREF1(display);
263 Assert(display == TEST_DISPLAY);
264 AssertPtrReturn(window_attributes_return, 1);
265 for (unsigned i = 0; i < g_cSmlsWindows; ++i)
266 if (g_paSmlsWindows[i] == w)
267 {
268 *window_attributes_return = g_paSmlsWinAttribs[i];
269 return 1;
270 }
271 return 0;
272}
273
274extern "C" Status XGetWMNormalHints(Display *display, Window w,
275 XSizeHints *hints_return,
276 long *supplied_return);
277
278Status XGetWMNormalHints(Display *display, Window w,
279 XSizeHints *hints_return, long *supplied_return)
280{
281 RT_NOREF4(display, w, hints_return, supplied_return);
282 Assert(display == TEST_DISPLAY);
283 return 1;
284}
285
286static void smlsSetWindowAttributes(XWindowAttributes *pAttribs,
287 Window *pWindows, unsigned cAttribs,
288 const char **paNames)
289{
290 g_paSmlsWinAttribs = pAttribs;
291 g_paSmlsWindows = pWindows;
292 g_cSmlsWindows = cAttribs;
293 g_papszSmlsWinNames = paNames;
294}
295
296static Window g_SmlsShapedWindow = 0;
297static int g_cSmlsShapeRectangles = 0;
298static XRectangle *g_pSmlsShapeRectangles = NULL;
299
300extern "C" XRectangle *XShapeGetRectangles (Display *dpy, Window window,
301 int kind, int *count,
302 int *ordering);
303XRectangle *XShapeGetRectangles (Display *dpy, Window window, int kind,
304 int *count, int *ordering)
305{
306 RT_NOREF2(dpy, kind);
307 Assert(dpy == TEST_DISPLAY);
308 if ((window != g_SmlsShapedWindow) || (window == 0))
309 return NULL; /* Probably not correct, but works for us. */
310 *count = g_cSmlsShapeRectangles;
311 *ordering = 0;
312 return (XRectangle *)RTMemDup(g_pSmlsShapeRectangles,
313 sizeof(XRectangle)
314 * g_cSmlsShapeRectangles);
315}
316
317static void smlsSetShapeRectangles(Window window, int cRects,
318 XRectangle *pRects)
319{
320 g_SmlsShapedWindow = window;
321 g_cSmlsShapeRectangles = cRects;
322 g_pSmlsShapeRectangles = pRects;
323}
324
325static int g_SmlsEventType = 0;
326static Window g_SmlsEventWindow = 0;
327
328/* This should not be needed in the bits of the code we test. */
329extern "C" int XNextEvent(Display *display, XEvent *event_return);
330int XNextEvent(Display *display, XEvent *event_return)
331{
332 RT_NOREF1(display);
333 Assert(display == TEST_DISPLAY);
334 event_return->xany.type = g_SmlsEventType;
335 event_return->xany.window = g_SmlsEventWindow;
336 event_return->xmap.window = g_SmlsEventWindow;
337 return True;
338}
339
340/* Mock XPending(): this also should not be needed. Just in case, always
341 * return that at least one event is pending to be processed. */
342extern "C" int XPending(Display *display);
343int XPending(Display *display)
344{
345 RT_NOREF1(display);
346 return 1;
347}
348
349static void smlsSetNextEvent(int type, Window window)
350{
351 g_SmlsEventType = type;
352 g_SmlsEventWindow = window;
353}
354
355/* This should not be needed in the bits of the code we test. */
356extern "C" Status XSendEvent(Display *display, Window w, Bool propagate,
357 long event_mask, XEvent *event_send);
358Status XSendEvent(Display *display, Window w, Bool propagate,
359 long event_mask, XEvent *event_send)
360{
361 RT_NOREF5(display, w, propagate, event_mask, event_send);
362 Assert(display == TEST_DISPLAY);
363 AssertFailedReturn(0);
364}
365
366/* This should not be needed in the bits of the code we test. */
367extern "C" int XFlush(Display *display);
368int XFlush(Display *display)
369{
370 RT_NOREF1(display);
371 Assert(display == TEST_DISPLAY);
372 AssertFailedReturn(0);
373}
374
375/** Global "received a notification" flag. */
376static bool g_fNotified = false;
377
378/** Dummy host callback. */
379void VBClSeamlessSendRegionUpdate(RTRECT *pRects, size_t cRects)
380{
381 RT_NOREF2(pRects, cRects);
382 g_fNotified = true;
383}
384
385int VbglR3SeamlessSetCap(bool bState)
386{
387 RTPrintf("%s\n", bState ? "Seamless capability set"
388 : "Seamless capability unset");
389 return VINF_SUCCESS;
390}
391
392int VbglR3CtlFilterMask(uint32_t u32OrMask, uint32_t u32NotMask)
393{
394 RTPrintf("IRQ filter mask changed. Or mask: 0x%x. Not mask: 0x%x\n",
395 u32OrMask, u32NotMask);
396 return VINF_SUCCESS;
397}
398
399int VbglR3SeamlessWaitEvent(VMMDevSeamlessMode *pMode)
400{
401 RT_NOREF(pMode);
402 return VINF_SUCCESS;
403}
404
405static bool gotNotification(void)
406{
407 if (!g_fNotified)
408 return false;
409 g_fNotified = false;
410 return true;
411}
412
413/*****************************
414* The actual tests to be run *
415*****************************/
416
417/** The name of the unit test */
418static const char *g_pszTestName = NULL;
419
420/*** Test fixture data and data structures ***/
421
422/** A structure describing a test fixture to be run through. Each fixture
423 * describes the state of the windows visible (and unmapped) on the X server
424 * before and after a particular event is delivered, and the expected
425 * on-screen positions of all interesting visible windows at the end of the
426 * fixture as reported by the code (currently in the order it is likely to
427 * report them in, @todo sort this). We expect that the set of visible
428 * windows will be the same whether we start the code before the event and
429 * handle it or start the code after the event.
430 */
431struct SMLSFIXTURE
432{
433 /** The number of windows visible before the event */
434 unsigned cWindowsBefore;
435 /** An array of Window IDs for the visible and unmapped windows before
436 * the event */
437 Window *pahWindowsBefore;
438 /** The window attributes matching the windows in @a paWindowsBefore */
439 XWindowAttributes *paAttribsBefore;
440 /** The window names matching the windows in @a paWindowsBefore */
441 const char **papszNamesBefore;
442 /** The shaped window before the event - we allow at most one of these.
443 * Zero for none. */
444 Window hShapeWindowBefore;
445 /** The number of rectangles in the shaped window before the event. */
446 int cShapeRectsBefore;
447 /** The rectangles in the shaped window before the event */
448 XRectangle *paShapeRectsBefore;
449 /** The number of windows visible after the event */
450 unsigned cWindowsAfter;
451 /** An array of Window IDs for the visible and unmapped windows after
452 * the event */
453 Window *pahWindowsAfter;
454 /** The window attributes matching the windows in @a paWindowsAfter */
455 XWindowAttributes *paAttribsAfter;
456 /** The window names matching the windows in @a paWindowsAfter */
457 const char **papszNamesAfter;
458 /** The shaped window after the event - we allow at most one of these.
459 * Zero for none. */
460 Window hShapeWindowAfter;
461 /** The number of rectangles in the shaped window after the event. */
462 int cShapeRectsAfter;
463 /** The rectangles in the shaped window after the event */
464 XRectangle *paShapeRectsAfter;
465 /** The event to delivered */
466 int x11EventType;
467 /** The window for which the event in @enmEvent is delivered */
468 Window hEventWindow;
469 /** The number of windows expected to be reported at the end of the
470 * fixture */
471 unsigned cReportedRects;
472 /** The onscreen positions of those windows. */
473 RTRECT *paReportedRects;
474 /** Do we expect notification after the event? */
475 bool fExpectNotification;
476};
477
478/*** Test fixture to test the code against X11 configure (move) events ***/
479
480static Window g_ahWin1[] = { 20 };
481static XWindowAttributes g_aAttrib1Before[] =
482{ { 100, 200, 200, 300, 0, 0, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, IsViewable }
483};
484static XRectangle g_aRectangle1[] =
485{
486 { 0, 0, 50, 50 },
487 { 50, 50, 150, 250 }
488};
489static XWindowAttributes g_aAttrib1After[] =
490{ { 200, 300, 200, 300, 0, 0, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, IsViewable }
491};
492static const char *g_apszNames1[] = { "Test Window" };
493
494AssertCompile(RT_ELEMENTS(g_ahWin1) == RT_ELEMENTS(g_aAttrib1Before));
495AssertCompile(RT_ELEMENTS(g_ahWin1) == RT_ELEMENTS(g_aAttrib1After));
496AssertCompile(RT_ELEMENTS(g_ahWin1) == RT_ELEMENTS(g_apszNames1));
497
498static RTRECT g_aRects1[] =
499{
500 { 200, 300, 250, 350 },
501 { 250, 350, 400, 600 }
502};
503
504static SMLSFIXTURE g_testMove =
505{
506 RT_ELEMENTS(g_ahWin1),
507 g_ahWin1,
508 g_aAttrib1Before,
509 g_apszNames1,
510 20,
511 RT_ELEMENTS(g_aRectangle1),
512 g_aRectangle1,
513 RT_ELEMENTS(g_ahWin1),
514 g_ahWin1,
515 g_aAttrib1After,
516 g_apszNames1,
517 20,
518 RT_ELEMENTS(g_aRectangle1),
519 g_aRectangle1,
520 ConfigureNotify,
521 20,
522 RT_ELEMENTS(g_aRects1),
523 g_aRects1,
524 true
525};
526
527/*** Test fixture to test the code against X11 configure (resize) events ***/
528
529static XWindowAttributes g_aAttrib2Before[] =
530{ { 100, 200, 200, 300, 0, 0, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, IsViewable }
531};
532static XRectangle g_aRectangle2Before[] =
533{
534 { 0, 0, 50, 50 },
535 { 50, 50, 100, 100 }
536};
537
538AssertCompile(RT_ELEMENTS(g_ahWin1) == RT_ELEMENTS(g_aAttrib2Before));
539
540static SMLSFIXTURE g_testResize =
541{
542 RT_ELEMENTS(g_ahWin1),
543 g_ahWin1,
544 g_aAttrib2Before,
545 g_apszNames1,
546 20,
547 RT_ELEMENTS(g_aRectangle2Before),
548 g_aRectangle2Before,
549 RT_ELEMENTS(g_ahWin1),
550 g_ahWin1,
551 g_aAttrib1After,
552 g_apszNames1,
553 20,
554 RT_ELEMENTS(g_aRectangle1),
555 g_aRectangle1,
556 ConfigureNotify,
557 20,
558 RT_ELEMENTS(g_aRects1),
559 g_aRects1,
560 true
561};
562
563/*** Test fixture to test the code against X11 map events ***/
564
565static XWindowAttributes g_aAttrib3Before[] =
566{ { 200, 300, 200, 300, 0, 0, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, IsUnmapped }
567};
568
569AssertCompile(RT_ELEMENTS(g_ahWin1) == RT_ELEMENTS(g_aAttrib3Before));
570
571static SMLSFIXTURE g_testMap =
572{
573 RT_ELEMENTS(g_ahWin1),
574 g_ahWin1,
575 g_aAttrib3Before,
576 g_apszNames1,
577 20,
578 RT_ELEMENTS(g_aRectangle1),
579 g_aRectangle1,
580 RT_ELEMENTS(g_ahWin1),
581 g_ahWin1,
582 g_aAttrib1After,
583 g_apszNames1,
584 20,
585 RT_ELEMENTS(g_aRectangle1),
586 g_aRectangle1,
587 MapNotify,
588 20,
589 RT_ELEMENTS(g_aRects1),
590 g_aRects1,
591 true
592};
593
594/*** Test fixtures to test the code against X11 unmap events ***/
595
596static XWindowAttributes g_aAttrib4After[] =
597{ { 100, 200, 300, 400, 0, 0, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, IsUnmapped }
598};
599
600AssertCompile(RT_ELEMENTS(g_ahWin1) == RT_ELEMENTS(g_aAttrib4After));
601
602static SMLSFIXTURE g_testUnmap =
603{
604 RT_ELEMENTS(g_ahWin1),
605 g_ahWin1,
606 g_aAttrib1Before,
607 g_apszNames1,
608 20,
609 RT_ELEMENTS(g_aRectangle1),
610 g_aRectangle1,
611 RT_ELEMENTS(g_ahWin1),
612 g_ahWin1,
613 g_aAttrib4After,
614 g_apszNames1,
615 20,
616 RT_ELEMENTS(g_aRectangle1),
617 g_aRectangle1,
618 UnmapNotify,
619 20,
620 0,
621 NULL,
622 true
623};
624
625/*** A window we are not monitoring has been unmapped. Nothing should
626 *** happen, especially nothing bad. ***/
627
628static RTRECT g_aRects2[] =
629{
630 { 100, 200, 150, 250 },
631 { 150, 250, 300, 500 }
632};
633
634static SMLSFIXTURE g_testUnmapOther =
635{
636 RT_ELEMENTS(g_ahWin1),
637 g_ahWin1,
638 g_aAttrib1Before,
639 g_apszNames1,
640 20,
641 RT_ELEMENTS(g_aRectangle1),
642 g_aRectangle1,
643 RT_ELEMENTS(g_ahWin1),
644 g_ahWin1,
645 g_aAttrib1Before,
646 g_apszNames1,
647 20,
648 RT_ELEMENTS(g_aRectangle1),
649 g_aRectangle1,
650 UnmapNotify,
651 21,
652 RT_ELEMENTS(g_aRects2),
653 g_aRects2,
654 false
655};
656
657/*** Test fixture to test the code against X11 shape events ***/
658
659static XRectangle g_aRectangle5Before[] =
660{
661 { 0, 0, 200, 200 }
662};
663
664static SMLSFIXTURE g_testShape =
665{
666 RT_ELEMENTS(g_ahWin1),
667 g_ahWin1,
668 g_aAttrib1After,
669 g_apszNames1,
670 20,
671 RT_ELEMENTS(g_aRectangle5Before),
672 g_aRectangle5Before,
673 RT_ELEMENTS(g_ahWin1),
674 g_ahWin1,
675 g_aAttrib1After,
676 g_apszNames1,
677 20,
678 RT_ELEMENTS(g_aRectangle1),
679 g_aRectangle1,
680 VBoxShapeNotify,
681 20,
682 RT_ELEMENTS(g_aRects1),
683 g_aRects1,
684 true
685};
686
687/*** And the test code proper ***/
688
689/** Compare two RTRECT structures */
690static bool smlsCompRect(RTRECT *pFirst, RTRECT *pSecond)
691{
692 return ( (pFirst->xLeft == pSecond->xLeft)
693 && (pFirst->yTop == pSecond->yTop)
694 && (pFirst->xRight == pSecond->xRight)
695 && (pFirst->yBottom == pSecond->yBottom));
696}
697
698static void smlsPrintDiffRects(RTRECT *pExp, RTRECT *pGot)
699{
700 RTPrintf(" Expected: %d, %d, %d, %d. Got: %d, %d, %d, %d\n",
701 pExp->xLeft, pExp->yTop, pExp->xRight, pExp->yBottom,
702 pGot->xLeft, pGot->yTop, pGot->xRight, pGot->yBottom);
703}
704
705/** Run through a test fixture */
706static unsigned smlsDoFixture(SMLSFIXTURE *pFixture, const char *pszDesc)
707{
708 VBClX11SeamlessMonitor subject;
709 unsigned cErrs = 0;
710
711 subject.init(VBClSeamlessSendRegionUpdate);
712 smlsSetWindowAttributes(pFixture->paAttribsBefore,
713 pFixture->pahWindowsBefore,
714 pFixture->cWindowsBefore,
715 pFixture->papszNamesBefore);
716 smlsSetShapeRectangles(pFixture->hShapeWindowBefore,
717 pFixture->cShapeRectsBefore,
718 pFixture->paShapeRectsBefore);
719 subject.start();
720 smlsSetWindowAttributes(pFixture->paAttribsAfter,
721 pFixture->pahWindowsAfter,
722 pFixture->cWindowsAfter,
723 pFixture->papszNamesAfter);
724 smlsSetShapeRectangles(pFixture->hShapeWindowAfter,
725 pFixture->cShapeRectsAfter,
726 pFixture->paShapeRectsAfter);
727 smlsSetNextEvent(pFixture->x11EventType, pFixture->hEventWindow);
728 if (gotNotification()) /* Initial window tree rebuild */
729 {
730 RTPrintf("%s: fixture: %s. Notification was set before the first event!!!\n",
731 g_pszTestName, pszDesc);
732 ++cErrs;
733 }
734 subject.nextConfigurationEvent();
735 if (!gotNotification())
736 {
737 RTPrintf("%s: fixture: %s. No notification was sent for the initial window tree rebuild.\n",
738 g_pszTestName, pszDesc);
739 ++cErrs;
740 }
741 smlsSetNextEvent(0, 0);
742 subject.nextConfigurationEvent();
743 if (pFixture->fExpectNotification && !gotNotification())
744 {
745 RTPrintf("%s: fixture: %s. No notification was sent after the event.\n",
746 g_pszTestName, pszDesc);
747 ++cErrs;
748 }
749 RTRECT *pRects = subject.getRects();
750 size_t cRects = subject.getRectCount();
751 if (cRects != pFixture->cReportedRects)
752 {
753 RTPrintf("%s: fixture: %s. Wrong number of rectangles reported after processing event (expected %u, got %u).\n",
754 g_pszTestName, pszDesc, pFixture->cReportedRects,
755 cRects);
756 ++cErrs;
757 }
758 else
759 for (unsigned i = 0; i < cRects; ++i)
760 if (!smlsCompRect(&pRects[i], &pFixture->paReportedRects[i]))
761 {
762 RTPrintf("%s: fixture: %s. Rectangle %u wrong after processing event.\n",
763 g_pszTestName, pszDesc, i);
764 smlsPrintDiffRects(&pFixture->paReportedRects[i],
765 &pRects[i]);
766 ++cErrs;
767 break;
768 }
769 subject.stop();
770 subject.start();
771 if (cRects != pFixture->cReportedRects)
772 {
773 RTPrintf("%s: fixture: %s. Wrong number of rectangles reported without processing event (expected %u, got %u).\n",
774 g_pszTestName, pszDesc, pFixture->cReportedRects,
775 cRects);
776 ++cErrs;
777 }
778 else
779 for (unsigned i = 0; i < cRects; ++i)
780 if (!smlsCompRect(&pRects[i], &pFixture->paReportedRects[i]))
781 {
782 RTPrintf("%s: fixture: %s. Rectangle %u wrong without processing event.\n",
783 g_pszTestName, pszDesc, i);
784 smlsPrintDiffRects(&pFixture->paReportedRects[i],
785 &pRects[i]);
786 ++cErrs;
787 break;
788 }
789 return cErrs;
790}
791
792int main(int argc, char **argv)
793{
794 RTR3InitExe(argc, &argv, 0);
795 unsigned cErrs = 0;
796 g_pszTestName = RTPathFilename(argv[0]);
797
798 RTPrintf("%s: TESTING\n", g_pszTestName);
799
800/** @todo r=bird: This testcase is broken and we didn't notice because we
801 * don't run it on the testboxes! @bugref{9842} */
802if (argc == 1)
803{
804 RTPrintf("%s: Note! This testcase is broken, skipping!\n", g_pszTestName);
805 return RTEXITCODE_SUCCESS;
806}
807
808 cErrs += smlsDoFixture(&g_testMove,
809 "ConfigureNotify event (window moved)");
810 // Currently not working
811 cErrs += smlsDoFixture(&g_testResize,
812 "ConfigureNotify event (window resized)");
813 cErrs += smlsDoFixture(&g_testMap, "MapNotify event");
814 cErrs += smlsDoFixture(&g_testUnmap, "UnmapNotify event");
815 cErrs += smlsDoFixture(&g_testUnmapOther,
816 "UnmapNotify event for unmonitored window");
817 cErrs += smlsDoFixture(&g_testShape, "ShapeNotify event");
818 if (cErrs > 0)
819 RTPrintf("%u errors\n", cErrs);
820 return cErrs == 0 ? 0 : 1;
821}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use