[PATCH weston 2/6] tests: add sub-surface tree destruction permutations

ppaalanen at gmail.com ppaalanen at gmail.com
Fri May 17 06:46:04 PDT 2013


From: Pekka Paalanen <ppaalanen at gmail.com>

Add a test for varying the object destruction order in a complex
sub-surface tree.

This test attemps to fuzz the destruction of a sub-surface tree to make
sure the server does not crash on any wl_surface or wl_subsurface
destruction sequence.

Signed-off-by: Pekka Paalanen <pekka.paalanen at collabora.co.uk>
---
 tests/subsurface-test.c | 202 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 202 insertions(+)

diff --git a/tests/subsurface-test.c b/tests/subsurface-test.c
index 8f1fd14..0a210fb 100644
--- a/tests/subsurface-test.c
+++ b/tests/subsurface-test.c
@@ -24,6 +24,7 @@
 
 #include "weston-test-client-helper.h"
 #include "subsurface-client-protocol.h"
+#include <stdio.h>
 
 #define NUM_SUBSURFACES 3
 
@@ -323,3 +324,204 @@ TEST(test_subsurface_destroy_protocol)
 
 	client_roundtrip(client);
 }
+
+static void
+create_subsurface_tree(struct client *client, struct wl_surface **surfs,
+		       struct wl_subsurface **subs, int n)
+{
+	struct wl_subcompositor *subco;
+	int i;
+
+	subco = get_subcompositor(client);
+
+	for (i = 0; i < n; i++)
+		surfs[i] = wl_compositor_create_surface(client->wl_compositor);
+
+	/*
+	 * The tree of sub-surfaces:
+	 *                            0
+	 *                           / \
+	 *                          1   2 - 10
+	 *                         / \  |\
+	 *                        3   5 9 6
+	 *                       /       / \
+	 *                      4       7   8
+	 * Surface 0 has no wl_subsurface, others do.
+	 */
+
+	switch (n) {
+	default:
+		assert(0);
+		break;
+
+#define SUB_LINK(s,p) \
+	subs[s] = wl_subcompositor_get_subsurface(subco, surfs[s], surfs[p])
+
+	case 11:
+		SUB_LINK(10, 2);
+	case 10:
+		SUB_LINK(9, 2);
+	case 9:
+		SUB_LINK(8, 6);
+	case 8:
+		SUB_LINK(7, 6);
+	case 7:
+		SUB_LINK(6, 2);
+	case 6:
+		SUB_LINK(5, 1);
+	case 5:
+		SUB_LINK(4, 3);
+	case 4:
+		SUB_LINK(3, 1);
+	case 3:
+		SUB_LINK(2, 0);
+	case 2:
+		SUB_LINK(1, 0);
+
+#undef SUB_LINK
+	};
+}
+
+static void
+destroy_subsurface_tree(struct wl_surface **surfs,
+			struct wl_subsurface **subs, int n)
+{
+	int i;
+
+	for (i = n; i-- > 0; ) {
+		if (surfs[i])
+			wl_surface_destroy(surfs[i]);
+
+		if (subs[i])
+			wl_subsurface_destroy(subs[i]);
+	}
+}
+
+static int
+has_dupe(int *cnt, int n)
+{
+	int i;
+
+	for (i = 0; i < n; i++)
+		if (cnt[i] == cnt[n])
+			return 1;
+
+	return 0;
+}
+
+/* Note: number of permutations to test is: set_size! / (set_size - NSTEPS)!
+ */
+#define NSTEPS 3
+
+struct permu_state {
+	int set_size;
+	int cnt[NSTEPS];
+};
+
+static void
+permu_init(struct permu_state *s, int set_size)
+{
+	int i;
+
+	s->set_size = set_size;
+	for (i = 0; i < NSTEPS; i++)
+		s->cnt[i] = 0;
+}
+
+static int
+permu_next(struct permu_state *s)
+{
+	int k;
+
+	s->cnt[NSTEPS - 1]++;
+
+	while (1) {
+		if (s->cnt[0] >= s->set_size) {
+			return -1;
+		}
+
+		for (k = 1; k < NSTEPS; k++) {
+			if (s->cnt[k] >= s->set_size) {
+				s->cnt[k - 1]++;
+				s->cnt[k] = 0;
+				break;
+			}
+
+			if (has_dupe(s->cnt, k)) {
+				s->cnt[k]++;
+				break;
+			}
+		}
+
+		if (k == NSTEPS)
+			return 0;
+	}
+}
+
+static void
+destroy_permu_object(struct wl_surface **surfs,
+		     struct wl_subsurface **subs, int i)
+{
+	int h = (i + 1) / 2;
+
+	if (i & 1) {
+		fprintf(stderr, " [sub  %2d]", h);
+		wl_subsurface_destroy(subs[h]);
+		subs[h] = NULL;
+	} else {
+		fprintf(stderr, " [surf %2d]", h);
+		wl_surface_destroy(surfs[h]);
+		surfs[h] = NULL;
+	}
+}
+
+TEST(test_subsurface_destroy_permutations)
+{
+	/*
+	 * Test wl_surface and wl_subsurface destruction orders in a
+	 * complex tree of sub-surfaces.
+	 *
+	 * In the tree of sub-surfaces, go through every possible
+	 * permutation of destroying all wl_surface and wl_subsurface
+	 * objects. Execpt, to limit running time to a reasonable level,
+	 * execute only the first NSTEPS destructions from each
+	 * permutation, and ignore identical cases.
+	 */
+
+	const int test_size = 11;
+	struct client *client;
+	struct wl_surface *surfs[test_size];
+	struct wl_subsurface *subs[test_size];
+	struct permu_state per;
+	int counter = 0;
+	int i;
+
+	client = client_create(100, 50, 123, 77);
+	assert(client);
+
+	permu_init(&per, test_size * 2 - 1);
+	while (permu_next(&per) != -1) {
+		/* for each permutation of NSTEPS out of test_size */
+		memset(surfs, 0, sizeof surfs);
+		memset(subs, 0, sizeof subs);
+
+		create_subsurface_tree(client, surfs, subs, test_size);
+
+		fprintf(stderr, "permu");
+
+		for (i = 0; i < NSTEPS; i++)
+			fprintf(stderr, " %2d", per.cnt[i]);
+
+		for (i = 0; i < NSTEPS; i++)
+			destroy_permu_object(surfs, subs, per.cnt[i]);
+
+		fprintf(stderr, "\n");
+		client_roundtrip(client);
+
+		destroy_subsurface_tree(surfs, subs, test_size);
+		counter++;
+	}
+
+	client_roundtrip(client);
+	fprintf(stderr, "tried %d destroy permutations\n", counter);
+}
-- 
1.8.1.5



More information about the wayland-devel mailing list