Merge lp:~vanvugt/compiz/untest into lp:compiz/0.9.9

Proposed by Daniel van Vugt on 2012-11-07
Status: Merged
Approved by: Daniel van Vugt on 2012-11-08
Approved revision: 3455
Merged at revision: 3455
Proposed branch: lp:~vanvugt/compiz/untest
Merge into: lp:compiz/0.9.9
Diff against target: 352 lines (+336/-0)
3 files modified
tests/system/CMakeLists.txt (+1/-0)
tests/system/untest/CMakeLists.txt (+11/-0)
tests/system/untest/untest.c (+324/-0)
To merge this branch: bzr merge lp:~vanvugt/compiz/untest
Reviewer Review Type Date Requested Status
Sam Spilsbury 2012-11-07 Approve on 2012-11-08
PS Jenkins bot (community) continuous-integration Approve on 2012-11-07
Review via email: mp+133210@code.launchpad.net

Commit message

Introducing untest, the Unredirect Fullscreen Windows Stress Tester.

Already I can use it to reliably crash X on my i965/precise desktop.

To post a comment you must log in.
Sam Spilsbury (smspillaz) wrote :

Looks like a useful tool, I have some questions though:

1. It seems like the purpose of this code is to throw up a window that the user can make fullscreen and unfullscreen (and/or pop up a dialog to redirect). That doesn't really guarantee that you're actually testing fullscreen window unredirection, because you need to be running compiz for it to work (and that just assumes that fullscreen window unredirection works in compiz). Maybe add a warning and/or start compiz if not started
2. Does it belong in the compiz source tree? Seems like it might be better as a separate driver test suite.

On a much broader note:

I think that providing integration tests like these for the drivers would be very useful, however, their use would just go up ten-fold if we could automate them and run them as a job in the QA lab.

Have you considered making a standalone integration test that doesn't depend on a running instance of compiz or anything like that? That makes it far easier for developers to rule out compiz using the API incorrectly as the problem. For example, the test would:

1. create a window
2. create a subwindow with an opengl visual
3. call XCompositeRedirectSubWindows
4. call XCompositeUnredirectWindow on the opengl subwindow
5. call XCompostieRedirectWindow on the opengl subwindow

You can then effectively script it to redirect and unredirect the subwindow as much as you want.

It might be that drivers only get upset when a composite overlay window is in use, so it might be worth looking into automating it that way.

review: Needs Information
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Daniel van Vugt (vanvugt) wrote :

1. Yes, it's intentional to not talk to compiz directly. It's cleaner that way. I was told already by Martin/Thomi that I can expect to have compiz running already in QA. And soon that will include unredirection enabled by default. I've already got Martin started trying to get performance testing automated using some benchmarks and games in the lab. This will be an addition to that.

2. Yes it belongs in the compiz source tree because it's testing for a bug that only happens with compiz (as far as we care/know), and its behaviour is directly linked to the expected behaviour of compiz. Even if the bugs occurred with other compositing window managers that did unredirection, the design of untest is specifically focussed on compiz.

3. Nice idea to Redirect/Unredirect from the test itself. But it's an enhancement for later and doesn't invalidate this proposal.

Sam Spilsbury (smspillaz) wrote :

OK for now. Please look into automating the test component.

review: Approve
Daniel van Vugt (vanvugt) wrote :

I'm not sure who else's approval we're waiting for... ?

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'tests/system/CMakeLists.txt'
--- tests/system/CMakeLists.txt 2012-09-18 10:45:43 +0000
+++ tests/system/CMakeLists.txt 2012-11-07 10:50:25 +0000
@@ -1,1 +1,2 @@
1add_subdirectory (xorg-gtest)1add_subdirectory (xorg-gtest)
2add_subdirectory (untest)
23
=== added directory 'tests/system/untest'
=== added file 'tests/system/untest/CMakeLists.txt'
--- tests/system/untest/CMakeLists.txt 1970-01-01 00:00:00 +0000
+++ tests/system/untest/CMakeLists.txt 2012-11-07 10:50:25 +0000
@@ -0,0 +1,11 @@
1
2cmake_minimum_required (VERSION 2.6)
3
4include (FindPkgConfig)
5pkg_search_module (GTK REQUIRED gtk+-3.0)
6pkg_search_module (GL REQUIRED gl)
7
8add_executable (untest untest.c)
9include_directories (${GTK_INCLUDE_DIRS} ${GL_INCLUDE_DIRS})
10link_directories (${GTK_LIBRARY_DIRS} ${GL_LIBRARY_DIRECTORIES})
11target_link_libraries (untest ${GTK_LIBRARIES} ${GL_LIBRARIES})
012
=== added file 'tests/system/untest/untest.c'
--- tests/system/untest/untest.c 1970-01-01 00:00:00 +0000
+++ tests/system/untest/untest.c 2012-11-07 10:50:25 +0000
@@ -0,0 +1,324 @@
1/*
2 * Unredirect Fullscreen Windows Stress Tester
3 *
4 * Copyright (C) 2012 Canonical Ltd.
5 * Author: Daniel van Vugt <daniel.van.vugt@canonical.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
21 */
22
23#include <gtk/gtk.h>
24#include <gdk/gdkx.h>
25#include <GL/glx.h>
26
27#define SECONDS 1000
28#define MINUTES 60000
29
30#define FPS 30
31#define CYCLE_PERIOD 2 /* seconds */
32#define FULLSCREEN_PERIOD (3 * SECONDS)
33#define DIALOG_PERIOD (7 * SECONDS)
34
35#define PADDING 20
36
37#define RED {0, 0xffff, 0x0000, 0x0000}
38#define YELLOW {0, 0xffff, 0xffff, 0x0000}
39#define GREEN {0, 0x0000, 0xffff, 0x0000}
40#define CYAN {0, 0x0000, 0xffff, 0xffff}
41#define BLUE {0, 0x0000, 0x0000, 0xffff}
42#define MAGENTA {0, 0xffff, 0x0000, 0xffff}
43
44static const char *app_title = "Unredirect Fullscreen Windows Stress Tester";
45static const char *copyright = "Copyright (c) 2012 Canonical Ltd.";
46static gint test_duration = 120; /* seconds */
47static guint64 start_time = 0;
48static GLXWindow glxwin = None;
49static GtkButton *button;
50
51static void blend (guint16 scale, const GdkColor *a, const GdkColor *b,
52 GdkColor *c)
53{
54 unsigned long src = 0xffff - scale;
55 unsigned long dest = scale;
56 c->pixel = 0;
57 c->red = (guint16)((src * a->red + dest * b->red) / 0xffff);
58 c->green = (guint16)((src * a->green + dest * b->green) / 0xffff);
59 c->blue = (guint16)((src * a->blue + dest * b->blue) / 0xffff);
60}
61
62static gboolean cycle_color (gpointer data)
63{
64 static const GdkColor color_stop[] =
65 {RED, YELLOW, GREEN, CYAN, BLUE, MAGENTA};
66 static const int color_stops = sizeof(color_stop)/sizeof(color_stop[0]);
67 static guint16 pos = 0;
68 guint16 scale;
69 GtkWindow *win = GTK_WINDOW (data);
70 int from, to;
71 GdkColor color;
72
73 pos = (pos + 0xffff / (FPS * CYCLE_PERIOD)) & 0xffff;
74 from = (pos * color_stops) >> 16;
75 to = (from + 1) % color_stops;
76 scale = (pos * color_stops) & 0xffff;
77 blend (scale, color_stop+from, color_stop+to, &color);
78
79 if (glxwin == None)
80 {
81 gtk_widget_modify_bg (GTK_WIDGET (win), GTK_STATE_NORMAL, &color);
82 }
83 else
84 {
85 glClearColor (color.red / 65535.0f,
86 color.green / 65535.0f,
87 color.blue / 65535.0f,
88 1.0);
89 glClear (GL_COLOR_BUFFER_BIT);
90 glFinish ();
91 }
92
93 return TRUE;
94}
95
96static gboolean on_redraw (GtkWidget *widget, void *cr, gpointer data)
97{
98 GtkProgressBar *b = GTK_PROGRESS_BAR (data);
99 guint64 elapsed = g_get_real_time () - start_time;
100 gtk_progress_bar_set_fraction (b,
101 (float)elapsed / (1000000 * test_duration));
102 g_print ("\r%d%% ", (int)(elapsed / (10000 * test_duration)));
103 return FALSE;
104}
105
106static gboolean toggle_fullscreen (gpointer data)
107{
108 static gboolean is_fullscreen = FALSE;
109 GtkWindow *w = GTK_WINDOW (data);
110 is_fullscreen = !is_fullscreen;
111 if (is_fullscreen)
112 gtk_window_fullscreen (w);
113 else
114 gtk_window_unfullscreen (w);
115 return TRUE;
116}
117
118static gboolean toggle_dialog (gpointer data)
119{
120 static gboolean visible = FALSE;
121 GtkWindow *dialog = GTK_WINDOW (data);
122 visible = !visible;
123 gtk_widget_set_visible (GTK_WIDGET (dialog), visible);
124 return TRUE;
125}
126
127static void close_window (GtkWidget *widget, gpointer user_data)
128{
129 gtk_main_quit ();
130 g_print ("\rYou're a quitter. No test results for you.\n");
131}
132
133static gboolean end_test (gpointer data)
134{
135 gtk_main_quit ();
136 g_print ("\rCongratulations! Nothing crashed.\n");
137 return FALSE;
138}
139
140static gboolean init_opengl (GtkWindow *win)
141{
142 gboolean ret = FALSE;
143 static const int attr[] =
144 {
145 GLX_X_RENDERABLE, True,
146 GLX_DOUBLEBUFFER, False,
147 None
148 };
149 Display *dpy = gdk_x11_get_default_xdisplay ();
150 int screen = gdk_x11_get_default_screen ();
151 int nfb;
152 GLXFBConfig *fb = glXChooseFBConfig (dpy, screen, attr, &nfb);
153
154 if (fb != NULL && nfb > 0)
155 {
156 GdkWindow *gdkwin = gtk_widget_get_window (GTK_WIDGET (win));
157 Window xwin = gdk_x11_window_get_xid (gdkwin);
158 glxwin = glXCreateWindow (dpy, fb[0], xwin, NULL);
159 if (glxwin != None)
160 {
161 GLXContext ctx = glXCreateNewContext (dpy, fb[0], GLX_RGBA_TYPE,
162 NULL, True);
163 if (ctx != NULL)
164 {
165 if (glXMakeContextCurrent (dpy, glxwin, glxwin, ctx))
166 {
167 const char *vendor = (const char*)
168 glGetString (GL_VENDOR);
169 const char *renderer = (const char*)
170 glGetString (GL_RENDERER);
171 const char *version = (const char*)
172 glGetString (GL_VERSION);
173 g_print ("GL Vendor: %s\n"
174 "GL Renderer: %s\n"
175 "GL Version: %s\n"
176 "\n",
177 vendor != NULL ? vendor : "?",
178 renderer != NULL ? renderer : "?",
179 version != NULL ? version : "?");
180 ret = TRUE;
181 }
182 else
183 {
184 g_warning ("glXMakeContextCurrent failed. "
185 "OpenGL won't be used.\n");
186
187 }
188 }
189 }
190 else
191 {
192 g_warning ("glXCreateWindow failed. OpenGL won't be used.\n");
193 }
194 XFree (fb);
195 }
196 else
197 {
198 g_warning ("glXChooseFBConfig returned nothing. "
199 "OpenGL won't be used.\n");
200 }
201
202 return ret;
203}
204
205int main (int argc, char *argv[])
206{
207 static gboolean gl_disabled = FALSE;
208 static GOptionEntry custom_options[] =
209 {
210 {
211 "disable-opengl",
212 'd',
213 0,
214 G_OPTION_ARG_NONE,
215 &gl_disabled,
216 "Disable OpenGL rendering. Use GTK only.",
217 NULL
218 },
219 {
220 "test-duration",
221 't',
222 0,
223 G_OPTION_ARG_INT,
224 &test_duration,
225 "How long the test lasts (default 120 seconds)",
226 "SECONDS"
227 },
228 {
229 NULL,
230 0,
231 0,
232 G_OPTION_ARG_NONE,
233 NULL,
234 NULL,
235 NULL
236 }
237 };
238 GtkWindow *win;
239 GtkWindow *dialog;
240 GtkLabel *label;
241 GtkBox *vbox;
242 GtkBox *hbox;
243 GtkAlignment *align;
244 GtkProgressBar *bar;
245
246 g_print ("%s\n"
247 "%s\n"
248 "\n",
249 app_title, copyright);
250
251 if (!gtk_init_with_args (&argc, &argv, NULL, custom_options, NULL, NULL))
252 {
253 g_warning ("Invalid options? Try: %s --help\n", argv[0]);
254 return 1;
255 }
256
257 win = GTK_WINDOW (gtk_window_new (GTK_WINDOW_TOPLEVEL));
258 gtk_window_set_title (win, app_title);
259 gtk_window_set_default_size (win, 300, 300);
260 gtk_window_set_position (win, GTK_WIN_POS_CENTER);
261 gtk_widget_show (GTK_WIDGET (win));
262
263 align = GTK_ALIGNMENT (gtk_alignment_new (0.5f, 1.0f, 0.5f, 0.1f));
264 gtk_container_add (GTK_CONTAINER (win), GTK_WIDGET (align));
265 gtk_widget_show (GTK_WIDGET (align));
266
267 vbox = GTK_BOX (gtk_box_new (GTK_ORIENTATION_VERTICAL, PADDING));
268 gtk_container_add (GTK_CONTAINER (align), GTK_WIDGET (vbox));
269 gtk_widget_show (GTK_WIDGET (vbox));
270
271 hbox = GTK_BOX (gtk_box_new (GTK_ORIENTATION_HORIZONTAL, PADDING));
272 gtk_box_set_homogeneous (hbox, FALSE);
273 gtk_container_add (GTK_CONTAINER (vbox), GTK_WIDGET (hbox));
274 gtk_widget_show (GTK_WIDGET (hbox));
275
276 bar = GTK_PROGRESS_BAR (gtk_progress_bar_new ());
277 gtk_progress_bar_set_text (bar, NULL);
278 gtk_progress_bar_set_show_text (bar, TRUE);
279 gtk_container_add (GTK_CONTAINER (hbox), GTK_WIDGET (bar));
280 gtk_box_set_child_packing (hbox, GTK_WIDGET (bar), TRUE, TRUE, 0,
281 GTK_PACK_START);
282 gtk_widget_show (GTK_WIDGET (bar));
283
284 button = GTK_BUTTON (gtk_button_new_with_label ("Cancel"));
285 gtk_container_add (GTK_CONTAINER (hbox), GTK_WIDGET (button));
286 gtk_box_set_child_packing (hbox, GTK_WIDGET (button), FALSE, FALSE, 0,
287 GTK_PACK_END);
288 gtk_widget_show (GTK_WIDGET (button));
289
290 dialog = GTK_WINDOW (gtk_window_new (GTK_WINDOW_POPUP));
291 gtk_window_set_transient_for (dialog, win);
292 gtk_window_set_default_size (dialog, 100, 100);
293 gtk_window_set_position (dialog, GTK_WIN_POS_CENTER);
294
295 label = GTK_LABEL (gtk_label_new ("Popup!"));
296 gtk_label_set_justify (label, GTK_JUSTIFY_CENTER);
297 gtk_container_add (GTK_CONTAINER (dialog), GTK_WIDGET (label));
298 gtk_widget_show (GTK_WIDGET (label));
299
300 gtk_widget_realize (GTK_WIDGET (win));
301 if (!gl_disabled)
302 init_opengl (win);
303
304 /* XXX For now, hide the widgets in OpenGL mode. People will think the
305 flickering is a bug */
306 if (glxwin)
307 gtk_widget_hide (GTK_WIDGET (align));
308
309 g_timeout_add (1000 / FPS, cycle_color, win);
310 g_timeout_add (FULLSCREEN_PERIOD, toggle_fullscreen, win);
311 g_timeout_add (test_duration * SECONDS, end_test, NULL);
312 g_timeout_add (DIALOG_PERIOD, toggle_dialog, dialog);
313
314 g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (close_window),
315 NULL);
316 g_signal_connect (G_OBJECT (win), "draw", G_CALLBACK (on_redraw), bar);
317 g_signal_connect (G_OBJECT (win), "destroy", G_CALLBACK (close_window),
318 NULL);
319
320 start_time = g_get_real_time ();
321 gtk_main ();
322
323 return 0;
324}

Subscribers

People subscribed via source and target branches