From: Pekka Paalanen <ppaala...@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.paala...@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

_______________________________________________
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to