1 /*
2 * Copyright © 2012 Collabora, Ltd.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial
14 * portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
20 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24 */
25
26 #include "config.h"
27
28 #include <stdio.h>
29 #include <string.h>
30
31 #include "weston-test-client-helper.h"
32 #include "weston-test-fixture-compositor.h"
33
34 static enum test_result_code
fixture_setup(struct weston_test_harness * harness)35 fixture_setup(struct weston_test_harness *harness)
36 {
37 struct compositor_setup setup;
38
39 compositor_setup_defaults(&setup);
40
41 return weston_test_harness_execute_as_client(harness, &setup);
42 }
43 DECLARE_FIXTURE_SETUP(fixture_setup);
44
45 #define NUM_SUBSURFACES 3
46
47 struct compound_surface {
48 struct wl_subcompositor *subco;
49 struct wl_surface *parent;
50 struct wl_surface *child[NUM_SUBSURFACES];
51 struct wl_subsurface *sub[NUM_SUBSURFACES];
52 };
53
54 static struct wl_subcompositor *
get_subcompositor(struct client * client)55 get_subcompositor(struct client *client)
56 {
57 struct global *g;
58 struct global *global_sub = NULL;
59 struct wl_subcompositor *sub;
60
61 wl_list_for_each(g, &client->global_list, link) {
62 if (strcmp(g->interface, "wl_subcompositor"))
63 continue;
64
65 if (global_sub)
66 assert(0 && "multiple wl_subcompositor objects");
67
68 global_sub = g;
69 }
70
71 assert(global_sub && "no wl_subcompositor found");
72
73 assert(global_sub->version == 1);
74
75 sub = wl_registry_bind(client->wl_registry, global_sub->name,
76 &wl_subcompositor_interface, 1);
77 assert(sub);
78
79 return sub;
80 }
81
82 static void
populate_compound_surface(struct compound_surface * com,struct client * client)83 populate_compound_surface(struct compound_surface *com, struct client *client)
84 {
85 int i;
86
87 com->subco = get_subcompositor(client);
88
89 com->parent = wl_compositor_create_surface(client->wl_compositor);
90
91 for (i = 0; i < NUM_SUBSURFACES; i++) {
92 com->child[i] =
93 wl_compositor_create_surface(client->wl_compositor);
94 com->sub[i] =
95 wl_subcompositor_get_subsurface(com->subco,
96 com->child[i],
97 com->parent);
98 }
99 }
100
TEST(test_subsurface_basic_protocol)101 TEST(test_subsurface_basic_protocol)
102 {
103 struct client *client;
104 struct compound_surface com1;
105 struct compound_surface com2;
106
107 client = create_client_and_test_surface(100, 50, 123, 77);
108 assert(client);
109
110 populate_compound_surface(&com1, client);
111 populate_compound_surface(&com2, client);
112
113 client_roundtrip(client);
114 }
115
TEST(test_subsurface_position_protocol)116 TEST(test_subsurface_position_protocol)
117 {
118 struct client *client;
119 struct compound_surface com;
120 int i;
121
122 client = create_client_and_test_surface(100, 50, 123, 77);
123 assert(client);
124
125 populate_compound_surface(&com, client);
126 for (i = 0; i < NUM_SUBSURFACES; i++)
127 wl_subsurface_set_position(com.sub[i],
128 (i + 2) * 20, (i + 2) * 10);
129
130 client_roundtrip(client);
131 }
132
TEST(test_subsurface_placement_protocol)133 TEST(test_subsurface_placement_protocol)
134 {
135 struct client *client;
136 struct compound_surface com;
137
138 client = create_client_and_test_surface(100, 50, 123, 77);
139 assert(client);
140
141 populate_compound_surface(&com, client);
142
143 wl_subsurface_place_above(com.sub[0], com.child[1]);
144 wl_subsurface_place_above(com.sub[1], com.parent);
145 wl_subsurface_place_below(com.sub[2], com.child[0]);
146 wl_subsurface_place_below(com.sub[1], com.parent);
147
148 client_roundtrip(client);
149 }
150
TEST(test_subsurface_paradox)151 TEST(test_subsurface_paradox)
152 {
153 struct client *client;
154 struct wl_surface *parent;
155 struct wl_subcompositor *subco;
156
157 client = create_client_and_test_surface(100, 50, 123, 77);
158 assert(client);
159
160 subco = get_subcompositor(client);
161 parent = wl_compositor_create_surface(client->wl_compositor);
162
163 /* surface is its own parent */
164 wl_subcompositor_get_subsurface(subco, parent, parent);
165
166 expect_protocol_error(client, &wl_subcompositor_interface,
167 WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE);
168 }
169
TEST(test_subsurface_identical_link)170 TEST(test_subsurface_identical_link)
171 {
172 struct client *client;
173 struct compound_surface com;
174
175 client = create_client_and_test_surface(100, 50, 123, 77);
176 assert(client);
177
178 populate_compound_surface(&com, client);
179
180 /* surface is already a subsurface */
181 wl_subcompositor_get_subsurface(com.subco, com.child[0], com.parent);
182
183 expect_protocol_error(client, &wl_subcompositor_interface,
184 WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE);
185 }
186
TEST(test_subsurface_change_link)187 TEST(test_subsurface_change_link)
188 {
189 struct client *client;
190 struct compound_surface com;
191 struct wl_surface *stranger;
192
193 client = create_client_and_test_surface(100, 50, 123, 77);
194 assert(client);
195
196 stranger = wl_compositor_create_surface(client->wl_compositor);
197 populate_compound_surface(&com, client);
198
199 /* surface is already a subsurface */
200 wl_subcompositor_get_subsurface(com.subco, com.child[0], stranger);
201
202 expect_protocol_error(client, &wl_subcompositor_interface,
203 WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE);
204 }
205
TEST(test_subsurface_nesting)206 TEST(test_subsurface_nesting)
207 {
208 struct client *client;
209 struct compound_surface com;
210 struct wl_surface *stranger;
211
212 client = create_client_and_test_surface(100, 50, 123, 77);
213 assert(client);
214
215 stranger = wl_compositor_create_surface(client->wl_compositor);
216 populate_compound_surface(&com, client);
217
218 /* parent is a sub-surface */
219 wl_subcompositor_get_subsurface(com.subco, stranger, com.child[0]);
220
221 client_roundtrip(client);
222 }
223
TEST(test_subsurface_nesting_parent)224 TEST(test_subsurface_nesting_parent)
225 {
226 struct client *client;
227 struct compound_surface com;
228 struct wl_surface *stranger;
229
230 client = create_client_and_test_surface(100, 50, 123, 77);
231 assert(client);
232
233 stranger = wl_compositor_create_surface(client->wl_compositor);
234 populate_compound_surface(&com, client);
235
236 /* surface is already a parent */
237 wl_subcompositor_get_subsurface(com.subco, com.parent, stranger);
238
239 client_roundtrip(client);
240 }
241
TEST(test_subsurface_loop_paradox)242 TEST(test_subsurface_loop_paradox)
243 {
244 struct client *client;
245 struct wl_surface *surface[3];
246 struct wl_subcompositor *subco;
247
248 client = create_client_and_test_surface(100, 50, 123, 77);
249 assert(client);
250
251 subco = get_subcompositor(client);
252 surface[0] = wl_compositor_create_surface(client->wl_compositor);
253 surface[1] = wl_compositor_create_surface(client->wl_compositor);
254 surface[2] = wl_compositor_create_surface(client->wl_compositor);
255
256 /* create a nesting loop */
257 wl_subcompositor_get_subsurface(subco, surface[1], surface[0]);
258 wl_subcompositor_get_subsurface(subco, surface[2], surface[1]);
259 wl_subcompositor_get_subsurface(subco, surface[0], surface[2]);
260
261 expect_protocol_error(client, &wl_subcompositor_interface,
262 WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE);
263 }
264
TEST(test_subsurface_place_above_nested_parent)265 TEST(test_subsurface_place_above_nested_parent)
266 {
267 struct client *client;
268 struct compound_surface com;
269 struct wl_surface *grandchild;
270 struct wl_subcompositor *subco;
271 struct wl_subsurface *sub;
272
273 client = create_client_and_test_surface(100, 50, 123, 77);
274 assert(client);
275
276 populate_compound_surface(&com, client);
277
278 subco = get_subcompositor(client);
279 grandchild = wl_compositor_create_surface(client->wl_compositor);
280 sub = wl_subcompositor_get_subsurface(subco, grandchild, com.child[0]);
281
282 wl_subsurface_place_above(sub, com.child[0]);
283
284 client_roundtrip(client);
285 }
286
TEST(test_subsurface_place_above_grandparent)287 TEST(test_subsurface_place_above_grandparent)
288 {
289 struct client *client;
290 struct compound_surface com;
291 struct wl_surface *grandchild;
292 struct wl_subsurface *sub;
293 struct wl_subcompositor *subco;
294
295 client = create_client_and_test_surface(100, 50, 123, 77);
296 assert(client);
297
298 populate_compound_surface(&com, client);
299
300 subco = get_subcompositor(client);
301 grandchild = wl_compositor_create_surface(client->wl_compositor);
302 sub = wl_subcompositor_get_subsurface(subco, grandchild, com.child[0]);
303
304 /* can't place a subsurface above its grandparent */
305 wl_subsurface_place_above(sub, com.parent);
306
307 expect_protocol_error(client, &wl_subsurface_interface,
308 WL_SUBSURFACE_ERROR_BAD_SURFACE);
309 }
310
TEST(test_subsurface_place_above_great_aunt)311 TEST(test_subsurface_place_above_great_aunt)
312 {
313 struct client *client;
314 struct compound_surface com;
315 struct wl_surface *grandchild;
316 struct wl_subsurface *sub;
317 struct wl_subcompositor *subco;
318
319 client = create_client_and_test_surface(100, 50, 123, 77);
320 assert(client);
321
322 populate_compound_surface(&com, client);
323
324 subco = get_subcompositor(client);
325 grandchild = wl_compositor_create_surface(client->wl_compositor);
326 sub = wl_subcompositor_get_subsurface(subco, grandchild, com.child[0]);
327
328 /* can't place a subsurface above its parents' siblings */
329 wl_subsurface_place_above(sub, com.child[1]);
330
331 expect_protocol_error(client, &wl_subsurface_interface,
332 WL_SUBSURFACE_ERROR_BAD_SURFACE);
333 }
334
TEST(test_subsurface_place_above_child)335 TEST(test_subsurface_place_above_child)
336 {
337 struct client *client;
338 struct compound_surface com;
339 struct wl_surface *grandchild;
340 struct wl_subcompositor *subco;
341
342 client = create_client_and_test_surface(100, 50, 123, 77);
343 assert(client);
344
345 populate_compound_surface(&com, client);
346
347 subco = get_subcompositor(client);
348 grandchild = wl_compositor_create_surface(client->wl_compositor);
349 wl_subcompositor_get_subsurface(subco, grandchild, com.child[0]);
350
351 /* can't place a subsurface above its own child subsurface */
352 wl_subsurface_place_above(com.sub[0], grandchild);
353
354 expect_protocol_error(client, &wl_subsurface_interface,
355 WL_SUBSURFACE_ERROR_BAD_SURFACE);
356 }
357
TEST(test_subsurface_place_below_nested_parent)358 TEST(test_subsurface_place_below_nested_parent)
359 {
360 struct client *client;
361 struct compound_surface com;
362 struct wl_subcompositor *subco;
363 struct wl_surface *grandchild;
364 struct wl_subsurface *sub;
365
366 client = create_client_and_test_surface(100, 50, 123, 77);
367 assert(client);
368
369 populate_compound_surface(&com, client);
370
371 subco = get_subcompositor(client);
372 grandchild = wl_compositor_create_surface(client->wl_compositor);
373 sub = wl_subcompositor_get_subsurface(subco, grandchild, com.child[0]);
374
375 wl_subsurface_place_below(sub, com.child[0]);
376
377 client_roundtrip(client);
378 }
379
TEST(test_subsurface_place_below_grandparent)380 TEST(test_subsurface_place_below_grandparent)
381 {
382 struct client *client;
383 struct compound_surface com;
384 struct wl_surface *grandchild;
385 struct wl_subsurface *sub;
386 struct wl_subcompositor *subco;
387
388 client = create_client_and_test_surface(100, 50, 123, 77);
389 assert(client);
390
391 populate_compound_surface(&com, client);
392
393 subco = get_subcompositor(client);
394 grandchild = wl_compositor_create_surface(client->wl_compositor);
395 sub = wl_subcompositor_get_subsurface(subco, grandchild, com.child[0]);
396
397 /* can't place a subsurface below its grandparent */
398 wl_subsurface_place_below(sub, com.parent);
399
400 expect_protocol_error(client, &wl_subsurface_interface,
401 WL_SUBSURFACE_ERROR_BAD_SURFACE);
402 }
403
TEST(test_subsurface_place_below_great_aunt)404 TEST(test_subsurface_place_below_great_aunt)
405 {
406 struct client *client;
407 struct compound_surface com;
408 struct wl_surface *grandchild;
409 struct wl_subsurface *sub;
410 struct wl_subcompositor *subco;
411
412 client = create_client_and_test_surface(100, 50, 123, 77);
413 assert(client);
414
415 populate_compound_surface(&com, client);
416
417 subco = get_subcompositor(client);
418 grandchild = wl_compositor_create_surface(client->wl_compositor);
419 sub = wl_subcompositor_get_subsurface(subco, grandchild, com.child[0]);
420
421 /* can't place a subsurface below its parents' siblings */
422 wl_subsurface_place_below(sub, com.child[1]);
423
424 expect_protocol_error(client, &wl_subsurface_interface,
425 WL_SUBSURFACE_ERROR_BAD_SURFACE);
426 }
427
TEST(test_subsurface_place_below_child)428 TEST(test_subsurface_place_below_child)
429 {
430 struct client *client;
431 struct compound_surface com;
432 struct wl_surface *grandchild;
433 struct wl_subcompositor *subco;
434
435 client = create_client_and_test_surface(100, 50, 123, 77);
436 assert(client);
437
438 populate_compound_surface(&com, client);
439
440 subco = get_subcompositor(client);
441 grandchild = wl_compositor_create_surface(client->wl_compositor);
442 wl_subcompositor_get_subsurface(subco, grandchild, com.child[0]);
443
444 /* can't place a subsurface below its own child subsurface */
445 wl_subsurface_place_below(com.sub[0], grandchild);
446
447 expect_protocol_error(client, &wl_subsurface_interface,
448 WL_SUBSURFACE_ERROR_BAD_SURFACE);
449 }
450
TEST(test_subsurface_place_above_stranger)451 TEST(test_subsurface_place_above_stranger)
452 {
453 struct client *client;
454 struct compound_surface com;
455 struct wl_surface *stranger;
456
457 client = create_client_and_test_surface(100, 50, 123, 77);
458 assert(client);
459
460 stranger = wl_compositor_create_surface(client->wl_compositor);
461 populate_compound_surface(&com, client);
462
463 /* bad sibling */
464 wl_subsurface_place_above(com.sub[0], stranger);
465
466 expect_protocol_error(client, &wl_subsurface_interface,
467 WL_SUBSURFACE_ERROR_BAD_SURFACE);
468 }
469
TEST(test_subsurface_place_below_stranger)470 TEST(test_subsurface_place_below_stranger)
471 {
472 struct client *client;
473 struct compound_surface com;
474 struct wl_surface *stranger;
475
476 client = create_client_and_test_surface(100, 50, 123, 77);
477 assert(client);
478
479 stranger = wl_compositor_create_surface(client->wl_compositor);
480 populate_compound_surface(&com, client);
481
482 /* bad sibling */
483 wl_subsurface_place_below(com.sub[0], stranger);
484
485 expect_protocol_error(client, &wl_subsurface_interface,
486 WL_SUBSURFACE_ERROR_BAD_SURFACE);
487 }
488
TEST(test_subsurface_place_above_foreign)489 TEST(test_subsurface_place_above_foreign)
490 {
491 struct client *client;
492 struct compound_surface com1;
493 struct compound_surface com2;
494
495 client = create_client_and_test_surface(100, 50, 123, 77);
496 assert(client);
497
498 populate_compound_surface(&com1, client);
499 populate_compound_surface(&com2, client);
500
501 /* bad sibling */
502 wl_subsurface_place_above(com1.sub[0], com2.child[0]);
503
504 expect_protocol_error(client, &wl_subsurface_interface,
505 WL_SUBSURFACE_ERROR_BAD_SURFACE);
506 }
507
TEST(test_subsurface_place_below_foreign)508 TEST(test_subsurface_place_below_foreign)
509 {
510 struct client *client;
511 struct compound_surface com1;
512 struct compound_surface com2;
513
514 client = create_client_and_test_surface(100, 50, 123, 77);
515 assert(client);
516
517 populate_compound_surface(&com1, client);
518 populate_compound_surface(&com2, client);
519
520 /* bad sibling */
521 wl_subsurface_place_below(com1.sub[0], com2.child[0]);
522
523 expect_protocol_error(client, &wl_subsurface_interface,
524 WL_SUBSURFACE_ERROR_BAD_SURFACE);
525 }
526
TEST(test_subsurface_destroy_protocol)527 TEST(test_subsurface_destroy_protocol)
528 {
529 struct client *client;
530 struct compound_surface com;
531
532 client = create_client_and_test_surface(100, 50, 123, 77);
533 assert(client);
534
535 populate_compound_surface(&com, client);
536
537 /* not needed anymore */
538 wl_subcompositor_destroy(com.subco);
539
540 /* detach child from parent */
541 wl_subsurface_destroy(com.sub[0]);
542
543 /* destroy: child, parent */
544 wl_surface_destroy(com.child[1]);
545 wl_surface_destroy(com.parent);
546
547 /* destroy: parent, child */
548 wl_surface_destroy(com.child[2]);
549
550 /* destroy: sub, child */
551 wl_surface_destroy(com.child[0]);
552
553 /* 2x destroy: child, sub */
554 wl_subsurface_destroy(com.sub[2]);
555 wl_subsurface_destroy(com.sub[1]);
556
557 client_roundtrip(client);
558 }
559
560 static void
create_subsurface_tree(struct client * client,struct wl_surface ** surfs,struct wl_subsurface ** subs,int n)561 create_subsurface_tree(struct client *client, struct wl_surface **surfs,
562 struct wl_subsurface **subs, int n)
563 {
564 struct wl_subcompositor *subco;
565 int i;
566
567 subco = get_subcompositor(client);
568
569 for (i = 0; i < n; i++)
570 surfs[i] = wl_compositor_create_surface(client->wl_compositor);
571
572 /*
573 * The tree of sub-surfaces:
574 * 0
575 * / \
576 * 1 2 - 10
577 * / \ |\
578 * 3 5 9 6
579 * / / \
580 * 4 7 8
581 * Surface 0 has no wl_subsurface, others do.
582 */
583
584 switch (n) {
585 default:
586 assert(0);
587 break;
588
589 #define SUB_LINK(s,p) \
590 subs[s] = wl_subcompositor_get_subsurface(subco, surfs[s], surfs[p])
591
592 case 11:
593 SUB_LINK(10, 2);
594 /* fallthrough */
595 case 10:
596 SUB_LINK(9, 2);
597 /* fallthrough */
598 case 9:
599 SUB_LINK(8, 6);
600 /* fallthrough */
601 case 8:
602 SUB_LINK(7, 6);
603 /* fallthrough */
604 case 7:
605 SUB_LINK(6, 2);
606 /* fallthrough */
607 case 6:
608 SUB_LINK(5, 1);
609 /* fallthrough */
610 case 5:
611 SUB_LINK(4, 3);
612 /* fallthrough */
613 case 4:
614 SUB_LINK(3, 1);
615 /* fallthrough */
616 case 3:
617 SUB_LINK(2, 0);
618 /* fallthrough */
619 case 2:
620 SUB_LINK(1, 0);
621
622 #undef SUB_LINK
623 };
624 }
625
626 static void
destroy_subsurface_tree(struct wl_surface ** surfs,struct wl_subsurface ** subs,int n)627 destroy_subsurface_tree(struct wl_surface **surfs,
628 struct wl_subsurface **subs, int n)
629 {
630 int i;
631
632 for (i = n; i-- > 0; ) {
633 if (surfs[i])
634 wl_surface_destroy(surfs[i]);
635
636 if (subs[i])
637 wl_subsurface_destroy(subs[i]);
638 }
639 }
640
641 static int
has_dupe(int * cnt,int n)642 has_dupe(int *cnt, int n)
643 {
644 int i;
645
646 for (i = 0; i < n; i++)
647 if (cnt[i] == cnt[n])
648 return 1;
649
650 return 0;
651 }
652
653 /* Note: number of permutations to test is: set_size! / (set_size - NSTEPS)!
654 */
655 #define NSTEPS 3
656
657 struct permu_state {
658 int set_size;
659 int cnt[NSTEPS];
660 };
661
662 static void
permu_init(struct permu_state * s,int set_size)663 permu_init(struct permu_state *s, int set_size)
664 {
665 int i;
666
667 s->set_size = set_size;
668 for (i = 0; i < NSTEPS; i++)
669 s->cnt[i] = 0;
670 }
671
672 static int
permu_next(struct permu_state * s)673 permu_next(struct permu_state *s)
674 {
675 int k;
676
677 s->cnt[NSTEPS - 1]++;
678
679 while (1) {
680 if (s->cnt[0] >= s->set_size) {
681 return -1;
682 }
683
684 for (k = 1; k < NSTEPS; k++) {
685 if (s->cnt[k] >= s->set_size) {
686 s->cnt[k - 1]++;
687 s->cnt[k] = 0;
688 break;
689 }
690
691 if (has_dupe(s->cnt, k)) {
692 s->cnt[k]++;
693 break;
694 }
695 }
696
697 if (k == NSTEPS)
698 return 0;
699 }
700 }
701
702 static void
destroy_permu_object(struct wl_surface ** surfs,struct wl_subsurface ** subs,int i)703 destroy_permu_object(struct wl_surface **surfs,
704 struct wl_subsurface **subs, int i)
705 {
706 int h = (i + 1) / 2;
707
708 if (i & 1) {
709 testlog(" [sub %2d]", h);
710 wl_subsurface_destroy(subs[h]);
711 subs[h] = NULL;
712 } else {
713 testlog(" [surf %2d]", h);
714 wl_surface_destroy(surfs[h]);
715 surfs[h] = NULL;
716 }
717 }
718
TEST(test_subsurface_destroy_permutations)719 TEST(test_subsurface_destroy_permutations)
720 {
721 /*
722 * Test wl_surface and wl_subsurface destruction orders in a
723 * complex tree of sub-surfaces.
724 *
725 * In the tree of sub-surfaces, go through every possible
726 * permutation of destroying all wl_surface and wl_subsurface
727 * objects. Execpt, to limit running time to a reasonable level,
728 * execute only the first NSTEPS destructions from each
729 * permutation, and ignore identical cases.
730 */
731
732 const int test_size = 11;
733 struct client *client;
734 struct wl_surface *surfs[test_size];
735 struct wl_subsurface *subs[test_size];
736 struct permu_state per;
737 int counter = 0;
738 int i;
739
740 client = create_client_and_test_surface(100, 50, 123, 77);
741 assert(client);
742
743 permu_init(&per, test_size * 2 - 1);
744 while (permu_next(&per) != -1) {
745 /* for each permutation of NSTEPS out of test_size */
746 memset(surfs, 0, sizeof surfs);
747 memset(subs, 0, sizeof subs);
748
749 create_subsurface_tree(client, surfs, subs, test_size);
750
751 testlog("permu");
752
753 for (i = 0; i < NSTEPS; i++)
754 testlog(" %2d", per.cnt[i]);
755
756 for (i = 0; i < NSTEPS; i++)
757 destroy_permu_object(surfs, subs, per.cnt[i]);
758
759 testlog("\n");
760 client_roundtrip(client);
761
762 destroy_subsurface_tree(surfs, subs, test_size);
763 counter++;
764 }
765
766 client_roundtrip(client);
767 testlog("tried %d destroy permutations\n", counter);
768 }
769