s4:torture:smb2: in the durable-v2-reopen1 test, use a minimal request
[Samba/gebeck_regimport.git] / source4 / torture / smb2 / durable_v2_open.c
blob85620965d1e8edc26c12b96ca12bc9dff6294c24
1 /*
2 Unix SMB/CIFS implementation.
4 test suite for SMB2 version two of durable opens
6 Copyright (C) Michael Adam 2012
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include "libcli/smb2/smb2.h"
24 #include "libcli/smb2/smb2_calls.h"
25 #include "../libcli/smb/smbXcli_base.h"
26 #include "torture/torture.h"
27 #include "torture/smb2/proto.h"
28 #include "librpc/ndr/libndr.h"
30 #define CHECK_VAL(v, correct) do { \
31 if ((v) != (correct)) { \
32 torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s got 0x%x - should be 0x%x\n", \
33 __location__, #v, (int)v, (int)correct); \
34 ret = false; \
35 }} while (0)
37 #define CHECK_STATUS(status, correct) do { \
38 if (!NT_STATUS_EQUAL(status, correct)) { \
39 torture_result(tctx, TORTURE_FAIL, __location__": Incorrect status %s - should be %s", \
40 nt_errstr(status), nt_errstr(correct)); \
41 ret = false; \
42 goto done; \
43 }} while (0)
45 #define CHECK_CREATED(__io, __created, __attribute) \
46 do { \
47 CHECK_VAL((__io)->out.create_action, NTCREATEX_ACTION_ ## __created); \
48 CHECK_VAL((__io)->out.alloc_size, 0); \
49 CHECK_VAL((__io)->out.size, 0); \
50 CHECK_VAL((__io)->out.file_attr, (__attribute)); \
51 CHECK_VAL((__io)->out.reserved2, 0); \
52 } while(0)
54 /**
55 * basic durable_open test.
56 * durable state should only be granted when requested
57 * along with a batch oplock or a handle lease.
59 * This test tests durable open with all possible oplock types.
62 struct durable_open_vs_oplock {
63 const char *level;
64 const char *share_mode;
65 bool durable;
66 bool persistent;
69 #define NUM_OPLOCK_TYPES 4
70 #define NUM_SHARE_MODES 8
71 #define NUM_OPLOCK_OPEN_TESTS ( NUM_OPLOCK_TYPES * NUM_SHARE_MODES )
72 static struct durable_open_vs_oplock durable_open_vs_oplock_table[NUM_OPLOCK_OPEN_TESTS] =
74 { "", "", false, false },
75 { "", "R", false, false },
76 { "", "W", false, false },
77 { "", "D", false, false },
78 { "", "RD", false, false },
79 { "", "RW", false, false },
80 { "", "WD", false, false },
81 { "", "RWD", false, false },
83 { "s", "", false, false },
84 { "s", "R", false, false },
85 { "s", "W", false, false },
86 { "s", "D", false, false },
87 { "s", "RD", false, false },
88 { "s", "RW", false, false },
89 { "s", "WD", false, false },
90 { "s", "RWD", false, false },
92 { "x", "", false, false },
93 { "x", "R", false, false },
94 { "x", "W", false, false },
95 { "x", "D", false, false },
96 { "x", "RD", false, false },
97 { "x", "RW", false, false },
98 { "x", "WD", false, false },
99 { "x", "RWD", false, false },
101 { "b", "", true, false },
102 { "b", "R", true, false },
103 { "b", "W", true, false },
104 { "b", "D", true, false },
105 { "b", "RD", true, false },
106 { "b", "RW", true, false },
107 { "b", "WD", true, false },
108 { "b", "RWD", true, false },
111 static bool test_one_durable_v2_open_oplock(struct torture_context *tctx,
112 struct smb2_tree *tree,
113 const char *fname,
114 bool request_persistent,
115 struct durable_open_vs_oplock test)
117 NTSTATUS status;
118 TALLOC_CTX *mem_ctx = talloc_new(tctx);
119 struct smb2_handle _h;
120 struct smb2_handle *h = NULL;
121 bool ret = true;
122 struct smb2_create io;
124 smb2_util_unlink(tree, fname);
126 smb2_oplock_create_share(&io, fname,
127 smb2_util_share_access(test.share_mode),
128 smb2_util_oplock_level(test.level));
129 io.in.durable_open = false;
130 io.in.durable_open_v2 = true;
131 io.in.persistent_open = request_persistent;
132 io.in.create_guid = GUID_random();
134 status = smb2_create(tree, mem_ctx, &io);
135 CHECK_STATUS(status, NT_STATUS_OK);
136 _h = io.out.file.handle;
137 h = &_h;
138 CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
139 CHECK_VAL(io.out.durable_open, false);
140 CHECK_VAL(io.out.durable_open_v2, test.durable);
141 CHECK_VAL(io.out.persistent_open, test.persistent);
142 CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level(test.level));
144 done:
145 if (h != NULL) {
146 smb2_util_close(tree, *h);
148 smb2_util_unlink(tree, fname);
149 talloc_free(mem_ctx);
151 return ret;
154 static bool test_durable_v2_open_oplock_table(struct torture_context *tctx,
155 struct smb2_tree *tree,
156 const char *fname,
157 bool request_persistent,
158 struct durable_open_vs_oplock *table,
159 uint8_t num_tests)
161 bool ret = true;
162 uint8_t i;
164 smb2_util_unlink(tree, fname);
166 for (i = 0; i < num_tests; i++) {
167 ret = test_one_durable_v2_open_oplock(tctx,
168 tree,
169 fname,
170 request_persistent,
171 table[i]);
172 if (ret == false) {
173 goto done;
177 done:
178 smb2_util_unlink(tree, fname);
180 return ret;
183 bool test_durable_v2_open_oplock(struct torture_context *tctx,
184 struct smb2_tree *tree)
186 bool ret;
187 char fname[256];
189 /* Choose a random name in case the state is left a little funky. */
190 snprintf(fname, 256, "durable_open_oplock_%s.dat",
191 generate_random_str(tctx, 8));
193 ret = test_durable_v2_open_oplock_table(tctx, tree, fname,
194 false, /* request_persistent */
195 durable_open_vs_oplock_table,
196 NUM_OPLOCK_OPEN_TESTS);
198 talloc_free(tree);
200 return ret;
204 * basic durable handle open test.
205 * persistent state should only be granted when requested
206 * along with a batch oplock or a handle lease.
208 * This test tests persistent open with all valid lease types.
211 struct durable_open_vs_lease {
212 const char *type;
213 const char *share_mode;
214 bool durable;
215 bool persistent;
218 #define NUM_LEASE_TYPES 5
219 #define NUM_LEASE_OPEN_TESTS ( NUM_LEASE_TYPES * NUM_SHARE_MODES )
220 static struct durable_open_vs_lease durable_open_vs_lease_table[NUM_LEASE_OPEN_TESTS] =
222 { "", "", false, false },
223 { "", "R", false, false },
224 { "", "W", false, false },
225 { "", "D", false, false },
226 { "", "RW", false, false },
227 { "", "RD", false, false },
228 { "", "WD", false, false },
229 { "", "RWD", false, false },
231 { "R", "", false, false },
232 { "R", "R", false, false },
233 { "R", "W", false, false },
234 { "R", "D", false, false },
235 { "R", "RW", false, false },
236 { "R", "RD", false, false },
237 { "R", "DW", false, false },
238 { "R", "RWD", false, false },
240 { "RW", "", false, false },
241 { "RW", "R", false, false },
242 { "RW", "W", false, false },
243 { "RW", "D", false, false },
244 { "RW", "RW", false, false },
245 { "RW", "RD", false, false },
246 { "RW", "WD", false, false },
247 { "RW", "RWD", false, false },
249 { "RH", "", true, false },
250 { "RH", "R", true, false },
251 { "RH", "W", true, false },
252 { "RH", "D", true, false },
253 { "RH", "RW", true, false },
254 { "RH", "RD", true, false },
255 { "RH", "WD", true, false },
256 { "RH", "RWD", true, false },
258 { "RHW", "", true, false },
259 { "RHW", "R", true, false },
260 { "RHW", "W", true, false },
261 { "RHW", "D", true, false },
262 { "RHW", "RW", true, false },
263 { "RHW", "RD", true, false },
264 { "RHW", "WD", true, false },
265 { "RHW", "RWD", true, false },
268 static bool test_one_durable_v2_open_lease(struct torture_context *tctx,
269 struct smb2_tree *tree,
270 const char *fname,
271 bool request_persistent,
272 struct durable_open_vs_lease test)
274 NTSTATUS status;
275 TALLOC_CTX *mem_ctx = talloc_new(tctx);
276 struct smb2_handle _h;
277 struct smb2_handle *h = NULL;
278 bool ret = true;
279 struct smb2_create io;
280 struct smb2_lease ls;
281 uint64_t lease;
283 smb2_util_unlink(tree, fname);
285 lease = random();
287 smb2_lease_create_share(&io, &ls, false /* dir */, fname,
288 smb2_util_share_access(test.share_mode),
289 lease,
290 smb2_util_lease_state(test.type));
291 io.in.durable_open = false;
292 io.in.durable_open_v2 = true;
293 io.in.persistent_open = request_persistent;
294 io.in.create_guid = GUID_random();
296 status = smb2_create(tree, mem_ctx, &io);
297 CHECK_STATUS(status, NT_STATUS_OK);
298 _h = io.out.file.handle;
299 h = &_h;
300 CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
301 CHECK_VAL(io.out.durable_open, false);
302 CHECK_VAL(io.out.durable_open_v2, test.durable);
303 CHECK_VAL(io.out.persistent_open, test.persistent);
304 CHECK_VAL(io.out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE);
305 CHECK_VAL(io.out.lease_response.lease_key.data[0], lease);
306 CHECK_VAL(io.out.lease_response.lease_key.data[1], ~lease);
307 CHECK_VAL(io.out.lease_response.lease_state,
308 smb2_util_lease_state(test.type));
309 done:
310 if (h != NULL) {
311 smb2_util_close(tree, *h);
313 smb2_util_unlink(tree, fname);
314 talloc_free(mem_ctx);
316 return ret;
319 static bool test_durable_v2_open_lease_table(struct torture_context *tctx,
320 struct smb2_tree *tree,
321 const char *fname,
322 bool request_persistent,
323 struct durable_open_vs_lease *table,
324 uint8_t num_tests)
326 bool ret = true;
327 uint8_t i;
329 smb2_util_unlink(tree, fname);
331 for (i = 0; i < num_tests; i++) {
332 ret = test_one_durable_v2_open_lease(tctx,
333 tree,
334 fname,
335 request_persistent,
336 table[i]);
337 if (ret == false) {
338 goto done;
342 done:
343 smb2_util_unlink(tree, fname);
345 return ret;
348 bool test_durable_v2_open_lease(struct torture_context *tctx,
349 struct smb2_tree *tree)
351 char fname[256];
352 bool ret = true;
353 uint32_t caps;
355 caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
356 if (!(caps & SMB2_CAP_LEASING)) {
357 torture_skip(tctx, "leases are not supported");
360 /* Choose a random name in case the state is left a little funky. */
361 snprintf(fname, 256, "durable_open_lease_%s.dat", generate_random_str(tctx, 8));
363 ret = test_durable_v2_open_lease_table(tctx, tree, fname,
364 false, /* request_persistent */
365 durable_open_vs_lease_table,
366 NUM_LEASE_OPEN_TESTS);
368 talloc_free(tree);
369 return ret;
373 * basic test for doing a durable open
374 * and do a durable reopen on the same connection
375 * while the first open is still active (fails)
377 bool test_durable_v2_open_reopen1(struct torture_context *tctx,
378 struct smb2_tree *tree)
380 NTSTATUS status;
381 TALLOC_CTX *mem_ctx = talloc_new(tctx);
382 char fname[256];
383 struct smb2_handle _h;
384 struct smb2_handle *h = NULL;
385 struct smb2_create io1, io2;
386 bool ret = true;
388 /* Choose a random name in case the state is left a little funky. */
389 snprintf(fname, 256, "durable_v2_open_reopen1_%s.dat",
390 generate_random_str(tctx, 8));
392 smb2_util_unlink(tree, fname);
394 smb2_oplock_create_share(&io1, fname,
395 smb2_util_share_access(""),
396 smb2_util_oplock_level("b"));
397 io1.in.durable_open = false;
398 io1.in.durable_open_v2 = true;
399 io1.in.persistent_open = false;
400 io1.in.create_guid = GUID_random();
401 io1.in.timeout = UINT32_MAX;
403 status = smb2_create(tree, mem_ctx, &io1);
404 CHECK_STATUS(status, NT_STATUS_OK);
405 _h = io1.out.file.handle;
406 h = &_h;
407 CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
408 CHECK_VAL(io1.out.oplock_level, smb2_util_oplock_level("b"));
409 CHECK_VAL(io1.out.durable_open, false);
410 CHECK_VAL(io1.out.durable_open_v2, true);
411 CHECK_VAL(io1.out.persistent_open, false);
412 CHECK_VAL(io1.out.timeout, io1.in.timeout);
414 /* try a durable reconnect while the file is still open */
415 ZERO_STRUCT(io2);
416 io2.in.fname = "";
417 io2.in.durable_handle_v2 = h;
418 io2.in.create_guid = io1.in.create_guid;
419 status = smb2_create(tree, mem_ctx, &io2);
420 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
422 done:
423 if (h != NULL) {
424 smb2_util_close(tree, *h);
427 smb2_util_unlink(tree, fname);
429 talloc_free(tree);
431 talloc_free(mem_ctx);
433 return ret;
437 * basic test for doing a durable open
438 * tcp disconnect, reconnect, do a durable reopen (succeeds)
440 bool test_durable_v2_open_reopen2(struct torture_context *tctx,
441 struct smb2_tree *tree)
443 NTSTATUS status;
444 TALLOC_CTX *mem_ctx = talloc_new(tctx);
445 char fname[256];
446 struct smb2_handle _h;
447 struct smb2_handle *h = NULL;
448 struct smb2_create io1, io2;
449 bool ret = true;
451 /* Choose a random name in case the state is left a little funky. */
452 snprintf(fname, 256, "durable_v2_open_reopen2_%s.dat",
453 generate_random_str(tctx, 8));
455 smb2_util_unlink(tree, fname);
457 smb2_oplock_create_share(&io1, fname,
458 smb2_util_share_access(""),
459 smb2_util_oplock_level("b"));
460 io1.in.durable_open = false;
461 io1.in.durable_open_v2 = true;
462 io1.in.persistent_open = false;
463 io1.in.create_guid = GUID_random();
464 io1.in.timeout = UINT32_MAX;
466 status = smb2_create(tree, mem_ctx, &io1);
467 CHECK_STATUS(status, NT_STATUS_OK);
468 _h = io1.out.file.handle;
469 h = &_h;
470 CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
471 CHECK_VAL(io1.out.oplock_level, smb2_util_oplock_level("b"));
472 CHECK_VAL(io1.out.durable_open, false);
473 CHECK_VAL(io1.out.durable_open_v2, true);
474 CHECK_VAL(io1.out.persistent_open, false);
475 CHECK_VAL(io1.out.timeout, io1.in.timeout);
477 /* disconnect, reconnect and then do durable reopen */
478 talloc_free(tree);
479 tree = NULL;
481 if (!torture_smb2_connection(tctx, &tree)) {
482 torture_warning(tctx, "couldn't reconnect, bailing\n");
483 ret = false;
484 goto done;
487 ZERO_STRUCT(io2);
488 io2.in.fname = "";
489 io2.in.durable_handle_v2 = h;
490 status = smb2_create(tree, mem_ctx, &io2);
491 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
493 ZERO_STRUCT(io2);
494 io2.in.fname = "__non_existing_fname__";
495 io2.in.durable_handle_v2 = h;
496 status = smb2_create(tree, mem_ctx, &io2);
497 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
499 ZERO_STRUCT(io2);
500 io2.in.fname = fname;
501 io2.in.durable_handle_v2 = h;
502 status = smb2_create(tree, mem_ctx, &io2);
503 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
505 ZERO_STRUCT(io2);
507 * These are completely ignored by the server
509 io2.in.security_flags = 0x78;
510 io2.in.oplock_level = 0x78;
511 io2.in.impersonation_level = 0x12345678;
512 io2.in.create_flags = 0x12345678;
513 io2.in.reserved = 0x12345678;
514 io2.in.desired_access = 0x12345678;
515 io2.in.file_attributes = 0x12345678;
516 io2.in.share_access = 0x12345678;
517 io2.in.create_disposition = 0x12345678;
518 io2.in.create_options = 0x12345678;
519 io2.in.fname = "__non_existing_fname__";
522 * only io2.in.durable_handle_v2 and
523 * io2.in.create_guid are checked
525 io2.in.durable_open_v2 = false;
526 io2.in.durable_handle_v2 = h;
527 io2.in.create_guid = io1.in.create_guid;
528 h = NULL;
530 status = smb2_create(tree, mem_ctx, &io2);
531 CHECK_STATUS(status, NT_STATUS_OK);
532 CHECK_CREATED(&io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
533 CHECK_VAL(io2.out.durable_open, false);
534 CHECK_VAL(io2.out.durable_open_v2, true);
535 CHECK_VAL(io2.out.persistent_open, false);
536 CHECK_VAL(io2.out.oplock_level, smb2_util_oplock_level("b"));
537 _h = io2.out.file.handle;
538 h = &_h;
540 done:
541 if (h != NULL) {
542 smb2_util_close(tree, *h);
545 smb2_util_unlink(tree, fname);
547 talloc_free(tree);
549 talloc_free(mem_ctx);
551 return ret;
555 * basic persistent open test.
557 * This test tests durable open with all possible oplock types.
560 struct durable_open_vs_oplock persistent_open_oplock_ca_table[NUM_OPLOCK_OPEN_TESTS] =
562 { "", "", true, true },
563 { "", "R", true, true },
564 { "", "W", true, true },
565 { "", "D", true, true },
566 { "", "RD", true, true },
567 { "", "RW", true, true },
568 { "", "WD", true, true },
569 { "", "RWD", true, true },
571 { "s", "", true, true },
572 { "s", "R", true, true },
573 { "s", "W", true, true },
574 { "s", "D", true, true },
575 { "s", "RD", true, true },
576 { "s", "RW", true, true },
577 { "s", "WD", true, true },
578 { "s", "RWD", true, true },
580 { "x", "", true, true },
581 { "x", "R", true, true },
582 { "x", "W", true, true },
583 { "x", "D", true, true },
584 { "x", "RD", true, true },
585 { "x", "RW", true, true },
586 { "x", "WD", true, true },
587 { "x", "RWD", true, true },
589 { "b", "", true, true },
590 { "b", "R", true, true },
591 { "b", "W", true, true },
592 { "b", "D", true, true },
593 { "b", "RD", true, true },
594 { "b", "RW", true, true },
595 { "b", "WD", true, true },
596 { "b", "RWD", true, true },
599 bool test_persistent_open_oplock(struct torture_context *tctx,
600 struct smb2_tree *tree)
602 char fname[256];
603 bool ret = true;
604 uint32_t share_capabilities;
605 bool share_is_ca = false;
606 struct durable_open_vs_oplock *table;
608 /* Choose a random name in case the state is left a little funky. */
609 snprintf(fname, 256, "persistent_open_oplock_%s.dat", generate_random_str(tctx, 8));
611 share_capabilities = smb2cli_tcon_capabilities(tree->smbXcli);
612 share_is_ca = share_capabilities & SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY;
614 if (share_is_ca) {
615 table = persistent_open_oplock_ca_table;
616 } else {
617 table = durable_open_vs_oplock_table;
620 ret = test_durable_v2_open_oplock_table(tctx, tree, fname,
621 true, /* request_persistent */
622 table,
623 NUM_OPLOCK_OPEN_TESTS);
625 talloc_free(tree);
627 return ret;
631 * basic persistent handle open test.
632 * persistent state should only be granted when requested
633 * along with a batch oplock or a handle lease.
635 * This test tests persistent open with all valid lease types.
638 struct durable_open_vs_lease persistent_open_lease_ca_table[NUM_LEASE_OPEN_TESTS] =
640 { "", "", true, true },
641 { "", "R", true, true },
642 { "", "W", true, true },
643 { "", "D", true, true },
644 { "", "RW", true, true },
645 { "", "RD", true, true },
646 { "", "WD", true, true },
647 { "", "RWD", true, true },
649 { "R", "", true, true },
650 { "R", "R", true, true },
651 { "R", "W", true, true },
652 { "R", "D", true, true },
653 { "R", "RW", true, true },
654 { "R", "RD", true, true },
655 { "R", "DW", true, true },
656 { "R", "RWD", true, true },
658 { "RW", "", true, true },
659 { "RW", "R", true, true },
660 { "RW", "W", true, true },
661 { "RW", "D", true, true },
662 { "RW", "RW", true, true },
663 { "RW", "RD", true, true },
664 { "RW", "WD", true, true },
665 { "RW", "RWD", true, true },
667 { "RH", "", true, true },
668 { "RH", "R", true, true },
669 { "RH", "W", true, true },
670 { "RH", "D", true, true },
671 { "RH", "RW", true, true },
672 { "RH", "RD", true, true },
673 { "RH", "WD", true, true },
674 { "RH", "RWD", true, true },
676 { "RHW", "", true, true },
677 { "RHW", "R", true, true },
678 { "RHW", "W", true, true },
679 { "RHW", "D", true, true },
680 { "RHW", "RW", true, true },
681 { "RHW", "RD", true, true },
682 { "RHW", "WD", true, true },
683 { "RHW", "RWD", true, true },
686 bool test_persistent_open_lease(struct torture_context *tctx,
687 struct smb2_tree *tree)
689 char fname[256];
690 bool ret = true;
691 uint32_t caps;
692 uint32_t share_capabilities;
693 bool share_is_ca;
694 struct durable_open_vs_lease *table;
696 caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
697 if (!(caps & SMB2_CAP_LEASING)) {
698 torture_skip(tctx, "leases are not supported");
701 /* Choose a random name in case the state is left a little funky. */
702 snprintf(fname, 256, "persistent_open_lease_%s.dat", generate_random_str(tctx, 8));
704 share_capabilities = smb2cli_tcon_capabilities(tree->smbXcli);
705 share_is_ca = share_capabilities & SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY;
707 if (share_is_ca) {
708 table = persistent_open_lease_ca_table;
709 } else {
710 table = durable_open_vs_lease_table;
713 ret = test_durable_v2_open_lease_table(tctx, tree, fname,
714 true, /* request_persistent */
715 table,
716 NUM_LEASE_OPEN_TESTS);
718 talloc_free(tree);
720 return ret;
723 struct torture_suite *torture_smb2_durable_v2_open_init(void)
725 struct torture_suite *suite =
726 torture_suite_create(talloc_autofree_context(), "durable-v2-open");
728 torture_suite_add_1smb2_test(suite, "open-oplock", test_durable_v2_open_oplock);
729 torture_suite_add_1smb2_test(suite, "open-lease", test_durable_v2_open_lease);
730 torture_suite_add_1smb2_test(suite, "reopen1", test_durable_v2_open_reopen1);
731 torture_suite_add_1smb2_test(suite, "reopen2", test_durable_v2_open_reopen2);
732 torture_suite_add_1smb2_test(suite, "persistent-open-oplock", test_persistent_open_oplock);
733 torture_suite_add_1smb2_test(suite, "persistent-open-lease", test_persistent_open_lease);
735 suite->description = talloc_strdup(suite, "SMB2-DURABLE-V2-OPEN tests");
737 return suite;