s4-smbtorture: Make test names lowercase and dot-separated.
[metze/samba/wip.git] / source4 / torture / raw / search.c
index d4e317d9fbd1d118f6202ffe1cd5a216c855b4ca..60c9ad0bb36502afa329e132fb2e0b4397ed0414 100644 (file)
@@ -5,7 +5,7 @@
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
-#include "torture/torture.h"
 #include "system/filesys.h"
 #include "libcli/raw/libcliraw.h"
+#include "libcli/raw/raw_proto.h"
 #include "libcli/libcli.h"
 #include "torture/util.h"
+#include "lib/util/tsort.h"
 
 
 #define BASEDIR "\\testsearch"
 
+#define CHECK_STATUS_LEVEL(__tctx, __status, __level, __supp)          \
+       do {                                                            \
+               if (NT_STATUS_EQUAL(__status,                           \
+                       NT_STATUS_NOT_SUPPORTED) ||                     \
+                   NT_STATUS_EQUAL(__status,                           \
+                       NT_STATUS_NOT_IMPLEMENTED)) {                   \
+                       torture_warning(__tctx, "(%s) Info "            \
+                           "level "#__level" is %s",                   \
+                           __location__, nt_errstr(__status));         \
+                       __supp = false;                                 \
+               } else {                                                \
+                       torture_assert_ntstatus_ok_goto(__tctx,         \
+                           __status, ret, done, #__level" failed");    \
+                       __supp = true;                                  \
+               }                                                       \
+       } while (0)
+
 /*
   callback function for single_search
 */
-static BOOL single_search_callback(void *private, union smb_search_data *file)
+static bool single_search_callback(void *private_data, const union smb_search_data *file)
 {
-       union smb_search_data *data = private;
+       union smb_search_data *data = (union smb_search_data *)private_data;
 
        *data = *file;
 
-       return True;
+       return true;
 }
 
 /*
   do a single file (non-wildcard) search 
 */
 NTSTATUS torture_single_search(struct smbcli_state *cli, 
-                              TALLOC_CTX *mem_ctx,
+                              TALLOC_CTX *tctx,
                               const char *pattern,
                               enum smb_search_level level,
                               enum smb_search_data_level data_level,
@@ -80,7 +97,7 @@ NTSTATUS torture_single_search(struct smbcli_state *cli,
                return NT_STATUS_INVALID_LEVEL;
        }
 
-       status = smb_raw_search_first(cli->tree, mem_ctx,
+       status = smb_raw_search_first(cli->tree, tctx,
                                      &io, (void *)data, single_search_callback);
 
        if (NT_STATUS_IS_OK(status) && level == RAW_SEARCH_FFIRST) {
@@ -203,17 +220,17 @@ static const char *extract_name(void *data, enum smb_search_level level,
 /*
   extract the name from a smb_data structure and level
 */
-static int extract_resume_key(void *data, enum smb_search_level level,
-                             enum smb_search_data_level data_level)
+static uint32_t extract_resume_key(void *data, enum smb_search_level level,
+                                  enum smb_search_data_level data_level)
 {
        int i;
        for (i=0;i<ARRAY_SIZE(levels);i++) {
                if (level == levels[i].level &&
                    data_level == levels[i].data_level) {
-                       return (int)*(uint32_t *)(levels[i].resume_key_offset + (char *)data);
+                       return *(uint32_t *)(levels[i].resume_key_offset + (char *)data);
                }
        }
-       return -1;
+       return 0;
 }
 
 /* find a level in the table by name */
@@ -232,23 +249,24 @@ static union smb_search_data *find(const char *name)
 /* 
    basic testing of all RAW_SEARCH_* calls using a single file
 */
-static BOOL test_one_file(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
+static bool test_one_file(struct torture_context *tctx, 
+                         struct smbcli_state *cli)
 {
-       BOOL ret = True;
+       bool ret = true;
        int fnum;
        const char *fname = "\\torture_search.txt";
        const char *fname2 = "\\torture_search-NOTEXIST.txt";
        NTSTATUS status;
        int i;
        union smb_fileinfo all_info, alt_info, name_info, internal_info;
+       bool all_info_supported, alt_info_supported, name_info_supported,
+           internal_info_supported;
        union smb_search_data *s;
 
-       printf("Testing one file searches\n");
-
-       fnum = create_complex_file(cli, mem_ctx, fname);
+       fnum = create_complex_file(cli, tctx, fname);
        if (fnum == -1) {
                printf("ERROR: open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
-               ret = False;
+               ret = false;
                goto done;
        }
 
@@ -257,16 +275,17 @@ static BOOL test_one_file(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
                NTSTATUS expected_status;
                uint32_t cap = cli->transport->negotiate.capabilities;
 
-               printf("testing %s\n", levels[i].name);
+               torture_comment(tctx, "Testing %s\n", levels[i].name);
 
-               levels[i].status = torture_single_search(cli, mem_ctx, fname, 
+               levels[i].status = torture_single_search(cli, tctx, fname, 
                                                         levels[i].level,
                                                         levels[i].data_level,
                                                         0,
                                                         &levels[i].data);
 
                /* see if this server claims to support this level */
-               if ((cap & levels[i].capability_mask) != levels[i].capability_mask) {
+               if (((cap & levels[i].capability_mask) != levels[i].capability_mask)
+                   || NT_STATUS_EQUAL(levels[i].status, NT_STATUS_NOT_SUPPORTED)) {
                        printf("search level %s(%d) not supported by server\n",
                               levels[i].name, (int)levels[i].level);
                        continue;
@@ -276,11 +295,11 @@ static BOOL test_one_file(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
                        printf("search level %s(%d) failed - %s\n",
                               levels[i].name, (int)levels[i].level, 
                               nt_errstr(levels[i].status));
-                       ret = False;
+                       ret = false;
                        continue;
                }
 
-               status = torture_single_search(cli, mem_ctx, fname2, 
+               status = torture_single_search(cli, tctx, fname2, 
                                               levels[i].level,
                                               levels[i].data_level,
                                               0,
@@ -297,46 +316,34 @@ static BOOL test_one_file(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
                               levels[i].name, (int)levels[i].level, 
                               nt_errstr(expected_status),
                               nt_errstr(status));
-                       ret = False;
+                       ret = false;
                }
        }
 
        /* get the all_info file into to check against */
        all_info.generic.level = RAW_FILEINFO_ALL_INFO;
        all_info.generic.in.file.path = fname;
-       status = smb_raw_pathinfo(cli->tree, mem_ctx, &all_info);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("RAW_FILEINFO_ALL_INFO failed - %s\n", nt_errstr(status));
-               ret = False;
-               goto done;
-       }
+       status = smb_raw_pathinfo(cli->tree, tctx, &all_info);
+       CHECK_STATUS_LEVEL(tctx, status, "RAW_FILEINFO_ALL_INFO",
+           all_info_supported);
 
        alt_info.generic.level = RAW_FILEINFO_ALT_NAME_INFO;
        alt_info.generic.in.file.path = fname;
-       status = smb_raw_pathinfo(cli->tree, mem_ctx, &alt_info);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("RAW_FILEINFO_ALT_NAME_INFO failed - %s\n", nt_errstr(status));
-               ret = False;
-               goto done;
-       }
+       status = smb_raw_pathinfo(cli->tree, tctx, &alt_info);
+       CHECK_STATUS_LEVEL(tctx, status, "RAW_FILEINFO_ALT_NAME_INFO",
+           alt_info_supported);
 
        internal_info.generic.level = RAW_FILEINFO_INTERNAL_INFORMATION;
        internal_info.generic.in.file.path = fname;
-       status = smb_raw_pathinfo(cli->tree, mem_ctx, &internal_info);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("RAW_FILEINFO_INTERNAL_INFORMATION failed - %s\n", nt_errstr(status));
-               ret = False;
-               goto done;
-       }
+       status = smb_raw_pathinfo(cli->tree, tctx, &internal_info);
+       CHECK_STATUS_LEVEL(tctx, status, "RAW_FILEINFO_INTERNAL_INFORMATION",
+           internal_info_supported);
 
        name_info.generic.level = RAW_FILEINFO_NAME_INFO;
        name_info.generic.in.file.path = fname;
-       status = smb_raw_pathinfo(cli->tree, mem_ctx, &name_info);
-       if (!NT_STATUS_IS_OK(status)) {
-               printf("RAW_FILEINFO_NAME_INFO failed - %s\n", nt_errstr(status));
-               ret = False;
-               goto done;
-       }
+       status = smb_raw_pathinfo(cli->tree, tctx, &name_info);
+       CHECK_STATUS_LEVEL(tctx, status, "RAW_FILEINFO_NAME_INFO",
+           name_info_supported);
 
 #define CHECK_VAL(name, sname1, field1, v, sname2, field2) do { \
        s = find(name); \
@@ -346,7 +353,7 @@ static BOOL test_one_file(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
                               __location__, \
                                #sname1, #field1, (int)s->sname1.field1, \
                                #sname2, #field2, (int)v.sname2.out.field2); \
-                       ret = False; \
+                       ret = false; \
                } \
        }} while (0)
 
@@ -356,9 +363,9 @@ static BOOL test_one_file(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
                if (s->sname1.field1 != (~1 & nt_time_to_unix(v.sname2.out.field2))) { \
                        printf("(%s) %s/%s [%s] != %s/%s [%s]\n", \
                               __location__, \
-                               #sname1, #field1, timestring(mem_ctx, s->sname1.field1), \
-                               #sname2, #field2, nt_time_string(mem_ctx, v.sname2.out.field2)); \
-                       ret = False; \
+                               #sname1, #field1, timestring(tctx, s->sname1.field1), \
+                               #sname2, #field2, nt_time_string(tctx, v.sname2.out.field2)); \
+                       ret = false; \
                } \
        }} while (0)
 
@@ -368,9 +375,9 @@ static BOOL test_one_file(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
                if (s->sname1.field1 != v.sname2.out.field2) { \
                        printf("(%s) %s/%s [%s] != %s/%s [%s]\n", \
                               __location__, \
-                               #sname1, #field1, nt_time_string(mem_ctx, s->sname1.field1), \
-                               #sname2, #field2, nt_time_string(mem_ctx, v.sname2.out.field2)); \
-                       ret = False; \
+                               #sname1, #field1, nt_time_string(tctx, s->sname1.field1), \
+                               #sname2, #field2, nt_time_string(tctx, v.sname2.out.field2)); \
+                       ret = false; \
                } \
        }} while (0)
 
@@ -382,7 +389,7 @@ static BOOL test_one_file(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
                               __location__, \
                                #sname1, #field1, s->sname1.field1, \
                                #sname2, #field2, v.sname2.out.field2.s); \
-                       ret = False; \
+                       ret = false; \
                } \
        }} while (0)
 
@@ -391,12 +398,12 @@ static BOOL test_one_file(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
        if (s) { \
                if (!s->sname1.field1.s || \
                    strcmp(s->sname1.field1.s, v.sname2.out.field2.s) || \
-                   wire_bad_flags(&s->sname1.field1, flags, cli)) { \
+                   wire_bad_flags(&s->sname1.field1, flags, cli->transport)) { \
                        printf("(%s) %s/%s [%s] != %s/%s [%s]\n", \
                               __location__, \
                                #sname1, #field1, s->sname1.field1.s, \
                                #sname2, #field2, v.sname2.out.field2.s); \
-                       ret = False; \
+                       ret = false; \
                } \
        }} while (0)
 
@@ -405,12 +412,12 @@ static BOOL test_one_file(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
        if (s) { \
                if (!s->sname1.field1.s || \
                    strcmp(s->sname1.field1.s, fname) || \
-                   wire_bad_flags(&s->sname1.field1, flags, cli)) { \
+                   wire_bad_flags(&s->sname1.field1, flags, cli->transport)) { \
                        printf("(%s) %s/%s [%s] != %s\n", \
                               __location__, \
                                #sname1, #field1, s->sname1.field1.s, \
                                fname); \
-                       ret = False; \
+                       ret = false; \
                } \
        }} while (0)
 
@@ -423,7 +430,7 @@ static BOOL test_one_file(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
                               __location__, \
                                #sname1, #field1, s->sname1.field1, \
                                fname); \
-                       ret = False; \
+                       ret = false; \
                } \
        }} while (0)
        
@@ -494,21 +501,34 @@ static BOOL test_one_file(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
        CHECK_VAL("ID_FULL_DIRECTORY_INFO", id_full_directory_info,           ea_size, all_info, all_info, ea_size);
        CHECK_VAL("ID_BOTH_DIRECTORY_INFO", id_both_directory_info,           ea_size, all_info, all_info, ea_size);
 
-       CHECK_STR("SEARCH", search, name, alt_info, alt_name_info, fname);
-       CHECK_WSTR("BOTH_DIRECTORY_INFO", both_directory_info, short_name, alt_info, alt_name_info, fname, STR_UNICODE);
+       if (alt_info_supported) {
+               CHECK_STR("SEARCH", search, name, alt_info, alt_name_info,
+                   fname);
+               CHECK_WSTR("BOTH_DIRECTORY_INFO", both_directory_info,
+                   short_name, alt_info, alt_name_info, fname, STR_UNICODE);
+       }
 
        CHECK_NAME("STANDARD",            standard,            name, fname+1, 0);
        CHECK_NAME("EA_SIZE",             ea_size,             name, fname+1, 0);
        CHECK_NAME("DIRECTORY_INFO",      directory_info,      name, fname+1, STR_TERMINATE_ASCII);
        CHECK_NAME("FULL_DIRECTORY_INFO", full_directory_info, name, fname+1, STR_TERMINATE_ASCII);
-       CHECK_NAME("NAME_INFO",           name_info,           name, fname+1, STR_TERMINATE_ASCII);
+
+       if (name_info_supported) {
+               CHECK_NAME("NAME_INFO", name_info, name, fname+1,
+                   STR_TERMINATE_ASCII);
+       }
+
        CHECK_NAME("BOTH_DIRECTORY_INFO", both_directory_info, name, fname+1, STR_TERMINATE_ASCII);
        CHECK_NAME("ID_FULL_DIRECTORY_INFO", id_full_directory_info,           name, fname+1, STR_TERMINATE_ASCII);
        CHECK_NAME("ID_BOTH_DIRECTORY_INFO", id_both_directory_info,           name, fname+1, STR_TERMINATE_ASCII);
        CHECK_UNIX_NAME("UNIX_INFO",           unix_info,           name, fname+1, STR_TERMINATE_ASCII);
 
-       CHECK_VAL("ID_FULL_DIRECTORY_INFO", id_full_directory_info, file_id, internal_info, internal_information, file_id);
-       CHECK_VAL("ID_BOTH_DIRECTORY_INFO", id_both_directory_info, file_id, internal_info, internal_information, file_id);
+       if (internal_info_supported) {
+               CHECK_VAL("ID_FULL_DIRECTORY_INFO", id_full_directory_info,
+                   file_id, internal_info, internal_information, file_id);
+               CHECK_VAL("ID_BOTH_DIRECTORY_INFO", id_both_directory_info,
+                   file_id, internal_info, internal_information, file_id);
+       }
 
 done:
        smb_raw_exit(cli->session);
@@ -519,7 +539,7 @@ done:
 
 
 struct multiple_result {
-       TALLOC_CTX *mem_ctx;
+       TALLOC_CTX *tctx;
        int count;
        union smb_search_data *list;
 };
@@ -527,20 +547,20 @@ struct multiple_result {
 /*
   callback function for multiple_search
 */
-static BOOL multiple_search_callback(void *private, union smb_search_data *file)
+static bool multiple_search_callback(void *private_data, const union smb_search_data *file)
 {
-       struct multiple_result *data = private;
+       struct multiple_result *data = (struct multiple_result *)private_data;
 
 
        data->count++;
-       data->list = talloc_realloc(data->mem_ctx,
+       data->list = talloc_realloc(data->tctx,
                                      data->list, 
                                      union smb_search_data,
                                      data->count);
 
        data->list[data->count-1] = *file;
 
-       return True;
+       return true;
 }
 
 enum continue_type {CONT_FLAGS, CONT_NAME, CONT_RESUME_KEY};
@@ -549,7 +569,7 @@ enum continue_type {CONT_FLAGS, CONT_NAME, CONT_RESUME_KEY};
   do a single file (non-wildcard) search 
 */
 static NTSTATUS multiple_search(struct smbcli_state *cli, 
-                               TALLOC_CTX *mem_ctx,
+                               TALLOC_CTX *tctx,
                                const char *pattern,
                                enum smb_search_data_level data_level,
                                enum continue_type cont_type,
@@ -559,7 +579,7 @@ static NTSTATUS multiple_search(struct smbcli_state *cli,
        union smb_search_next io2;
        NTSTATUS status;
        const int per_search = 100;
-       struct multiple_result *result = data;
+       struct multiple_result *result = (struct multiple_result *)data;
 
        if (data_level == RAW_SEARCH_DATA_SEARCH) {
                io.search_first.level = RAW_SEARCH_SEARCH;
@@ -581,7 +601,7 @@ static NTSTATUS multiple_search(struct smbcli_state *cli,
                }
        }
 
-       status = smb_raw_search_first(cli->tree, mem_ctx,
+       status = smb_raw_search_first(cli->tree, tctx,
                                      &io, data, multiple_search_callback);
        
 
@@ -604,7 +624,7 @@ static NTSTATUS multiple_search(struct smbcli_state *cli,
                        case CONT_RESUME_KEY:
                                io2.t2fnext.in.resume_key = extract_resume_key(&result->list[result->count-1],
                                                                               io2.t2fnext.level, io2.t2fnext.data_level);
-                               if (io2.t2fnext.in.resume_key <= 0) {
+                               if (io2.t2fnext.in.resume_key == 0) {
                                        printf("Server does not support resume by key for level %s\n",
                                               level_name(io2.t2fnext.level, io2.t2fnext.data_level));
                                        return NT_STATUS_NOT_SUPPORTED;
@@ -622,7 +642,7 @@ static NTSTATUS multiple_search(struct smbcli_state *cli,
                        }
                }
 
-               status = smb_raw_search_next(cli->tree, mem_ctx,
+               status = smb_raw_search_next(cli->tree, tctx,
                                             &io2, data, multiple_search_callback);
                if (!NT_STATUS_IS_OK(status)) {
                        break;
@@ -640,28 +660,11 @@ static NTSTATUS multiple_search(struct smbcli_state *cli,
        return status;
 }
 
-#define CHECK_STATUS(status, correct) do { \
-       if (!NT_STATUS_EQUAL(status, correct)) { \
-               printf("(%s) Incorrect status %s - should be %s\n", \
-                      __location__, nt_errstr(status), nt_errstr(correct)); \
-               ret = False; \
-               goto done; \
-       }} while (0)
+#define CHECK_STATUS(status, correct) torture_assert_ntstatus_equal(tctx, status, correct, "incorrect status")
 
-#define CHECK_VALUE(v, correct) do { \
-       if ((v) != (correct)) { \
-               printf("(%s) Incorrect value %s=%ld - should be %ld\n", \
-                      __location__, #v, (long)v, (long)correct); \
-               ret = False; \
-               goto done; \
-       }} while (0)
+#define CHECK_VALUE(v, correct) torture_assert_int_equal(tctx, (v), (correct), "incorrect value");
 
-#define CHECK_STRING(v, correct) do { \
-       if (strcasecmp_m(v, correct) != 0) { \
-               printf("(%s) Incorrect value %s='%s' - should be '%s'\n", \
-                      __location__, #v, v, correct); \
-               ret = False; \
-       }} while (0)
+#define CHECK_STRING(v, correct) torture_assert_casestr_equal(tctx, v, correct, "incorrect value");
 
 
 static enum smb_search_data_level compare_data_level;
@@ -687,12 +690,13 @@ static int search_compare(union smb_search_data *d1, union smb_search_data *d2)
 /* 
    basic testing of search calls using many files
 */
-static BOOL test_many_files(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
+static bool test_many_files(struct torture_context *tctx, 
+                           struct smbcli_state *cli)
 {
        const int num_files = 700;
        int i, fnum, t;
        char *fname;
-       BOOL ret = True;
+       bool ret = true;
        NTSTATUS status;
        struct multiple_result result;
        struct {
@@ -726,19 +730,15 @@ static BOOL test_many_files(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
        };
 
        if (!torture_setup_dir(cli, BASEDIR)) {
-               return False;
+               return false;
        }
 
-       printf("Testing with %d files\n", num_files);
+       torture_comment(tctx, "Testing with %d files\n", num_files);
 
        for (i=0;i<num_files;i++) {
                fname = talloc_asprintf(cli, BASEDIR "\\t%03d-%d.txt", i, i);
                fnum = smbcli_open(cli->tree, fname, O_CREAT|O_RDWR, DENY_NONE);
-               if (fnum == -1) {
-                       printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
-                       ret = False;
-                       goto done;
-               }
+               torture_assert(tctx, fnum != -1, "Failed to create");
                talloc_free(fname);
                smbcli_close(cli->tree, fnum);
        }
@@ -746,28 +746,37 @@ static BOOL test_many_files(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
 
        for (t=0;t<ARRAY_SIZE(search_types);t++) {
                ZERO_STRUCT(result);
-               result.mem_ctx = talloc_new(mem_ctx);
+
+               if ((search_types[t].cont_type == CONT_RESUME_KEY) &&
+                   (search_types[t].data_level != RAW_SEARCH_DATA_SEARCH) &&
+                   !torture_setting_bool(tctx, "resume_key_support", true)) {
+                       torture_comment(tctx,
+                                       "SKIP: Continue %s via %s\n",
+                                       search_types[t].name, search_types[t].cont_name);
+                       continue;
+               }
+
+               result.tctx = talloc_new(tctx);
        
-               printf("Continue %s via %s\n", search_types[t].name, search_types[t].cont_name);
+               torture_comment(tctx,
+                               "Continue %s via %s\n", search_types[t].name, search_types[t].cont_name);
 
-               status = multiple_search(cli, mem_ctx, BASEDIR "\\*.*", 
+               status = multiple_search(cli, tctx, BASEDIR "\\*.*", 
                                         search_types[t].data_level,
                                         search_types[t].cont_type,
                                         &result);
-       
-               if (!NT_STATUS_IS_OK(status)) {
-                       printf("search type %s failed - %s\n", 
-                              search_types[t].name,
-                              nt_errstr(status));
-                       ret = False;
+               if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
+                       torture_warning(tctx, "search level %s not supported "
+                                       "by server",
+                                       search_types[t].name);
                        continue;
                }
+               torture_assert_ntstatus_ok(tctx, status, "search failed");
                CHECK_VALUE(result.count, num_files);
 
                compare_data_level = search_types[t].data_level;
 
-               qsort(result.list, result.count, sizeof(result.list[0]), 
-                     QSORT_CAST  search_compare);
+               TYPESAFE_QSORT(result.list, result.count, search_compare);
 
                for (i=0;i<result.count;i++) {
                        const char *s;
@@ -779,17 +788,12 @@ static BOOL test_many_files(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
                        }
                        s = extract_name(&result.list[i], level, compare_data_level);
                        fname = talloc_asprintf(cli, "t%03d-%d.txt", i, i);
-                       if (strcmp(fname, s)) {
-                               printf("Incorrect name %s at entry %d\n", s, i);
-                               ret = False;
-                               break;
-                       }
+                       torture_assert_str_equal(tctx, fname, s, "Incorrect name");
                        talloc_free(fname);
                }
-               talloc_free(result.mem_ctx);
+               talloc_free(result.tctx);
        }
 
-done:
        smb_raw_exit(cli->session);
        smbcli_deltree(cli->tree, BASEDIR);
 
@@ -799,7 +803,7 @@ done:
 /*
   check a individual file result
 */
-static BOOL check_result(struct multiple_result *result, const char *name, BOOL exist, uint32_t attrib)
+static bool check_result(struct multiple_result *result, const char *name, bool exist, uint32_t attrib)
 {
        int i;
        for (i=0;i<result->count;i++) {
@@ -809,35 +813,36 @@ static BOOL check_result(struct multiple_result *result, const char *name, BOOL
                if (exist) {
                        printf("failed: '%s' should exist with attribute %s\n", 
                               name, attrib_string(result->list, attrib));
-                       return False;
+                       return false;
                }
-               return True;
+               return true;
        }
 
        if (!exist) {
                printf("failed: '%s' should NOT exist (has attribute %s)\n", 
                       name, attrib_string(result->list, result->list[i].both_directory_info.attrib));
-               return False;
+               return false;
        }
 
        if ((result->list[i].both_directory_info.attrib&0xFFF) != attrib) {
                printf("failed: '%s' should have attribute 0x%x (has 0x%x)\n",
                       name, 
                       attrib, result->list[i].both_directory_info.attrib);
-               return False;
+               return false;
        }
-       return True;
+       return true;
 }
 
 /* 
    test what happens when the directory is modified during a search
 */
-static BOOL test_modify_search(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
+static bool test_modify_search(struct torture_context *tctx, 
+                                                          struct smbcli_state *cli)
 {
        const int num_files = 20;
        int i, fnum;
        char *fname;
-       BOOL ret = True;
+       bool ret = true;
        NTSTATUS status;
        struct multiple_result result;
        union smb_search_first io;
@@ -845,7 +850,7 @@ static BOOL test_modify_search(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
        union smb_setfileinfo sfinfo;
 
        if (!torture_setup_dir(cli, BASEDIR)) {
-               return False;
+               return false;
        }
 
        printf("Creating %d files\n", num_files);
@@ -855,7 +860,7 @@ static BOOL test_modify_search(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
                fnum = smbcli_open(cli->tree, fname, O_CREAT|O_RDWR, DENY_NONE);
                if (fnum == -1) {
                        printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
-                       ret = False;
+                       ret = false;
                        goto done;
                }
                talloc_free(fname);
@@ -864,7 +869,7 @@ static BOOL test_modify_search(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
 
        printf("pulling the first file\n");
        ZERO_STRUCT(result);
-       result.mem_ctx = talloc_new(mem_ctx);
+       result.tctx = talloc_new(tctx);
 
        io.t2ffirst.level = RAW_SEARCH_TRANS2;
        io.t2ffirst.data_level = RAW_SEARCH_DATA_BOTH_DIRECTORY_INFO;
@@ -874,7 +879,7 @@ static BOOL test_modify_search(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
        io.t2ffirst.in.storage_type = 0;
        io.t2ffirst.in.pattern = BASEDIR "\\*.*";
 
-       status = smb_raw_search_first(cli->tree, mem_ctx,
+       status = smb_raw_search_first(cli->tree, tctx,
                                      &io, &result, multiple_search_callback);
        CHECK_STATUS(status, NT_STATUS_OK);
        CHECK_VALUE(result.count, 1);
@@ -888,7 +893,7 @@ static BOOL test_modify_search(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
        io2.t2fnext.in.flags = 0;
        io2.t2fnext.in.last_name = result.list[result.count-1].both_directory_info.name.s;
 
-       status = smb_raw_search_next(cli->tree, mem_ctx,
+       status = smb_raw_search_next(cli->tree, tctx,
                                     &io2, &result, multiple_search_callback);
        CHECK_STATUS(status, NT_STATUS_OK);
        CHECK_VALUE(result.count, 2);
@@ -898,7 +903,7 @@ static BOOL test_modify_search(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
        printf("Changing attributes and deleting\n");
        smbcli_open(cli->tree, BASEDIR "\\T003-03.txt.2", O_CREAT|O_RDWR, DENY_NONE);
        smbcli_open(cli->tree, BASEDIR "\\T013-13.txt.2", O_CREAT|O_RDWR, DENY_NONE);
-       fnum = create_complex_file(cli, mem_ctx, BASEDIR "\\T013-13.txt.3");
+       fnum = create_complex_file(cli, tctx, BASEDIR "\\T013-13.txt.3");
        smbcli_unlink(cli->tree, BASEDIR "\\T014-14.txt");
        torture_set_file_attribute(cli->tree, BASEDIR "\\T015-15.txt", FILE_ATTRIBUTE_HIDDEN);
        torture_set_file_attribute(cli->tree, BASEDIR "\\T016-16.txt", FILE_ATTRIBUTE_NORMAL);
@@ -918,27 +923,27 @@ static BOOL test_modify_search(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
        io2.t2fnext.in.flags = 0;
        io2.t2fnext.in.last_name = ".";
 
-       status = smb_raw_search_next(cli->tree, mem_ctx,
+       status = smb_raw_search_next(cli->tree, tctx,
                                     &io2, &result, multiple_search_callback);
        CHECK_STATUS(status, NT_STATUS_OK);
        CHECK_VALUE(result.count, 20);
 
-       ret &= check_result(&result, "t009-9.txt", True, FILE_ATTRIBUTE_ARCHIVE);
-       ret &= check_result(&result, "t014-14.txt", False, 0);
-       ret &= check_result(&result, "t015-15.txt", False, 0);
-       ret &= check_result(&result, "t016-16.txt", True, FILE_ATTRIBUTE_NORMAL);
-       ret &= check_result(&result, "t017-17.txt", False, 0);
-       ret &= check_result(&result, "t018-18.txt", True, FILE_ATTRIBUTE_ARCHIVE);
-       ret &= check_result(&result, "t019-19.txt", True, FILE_ATTRIBUTE_ARCHIVE);
-       ret &= check_result(&result, "T013-13.txt.2", True, FILE_ATTRIBUTE_ARCHIVE);
-       ret &= check_result(&result, "T003-3.txt.2", False, 0);
-       ret &= check_result(&result, "T013-13.txt.3", True, FILE_ATTRIBUTE_ARCHIVE);
+       ret &= check_result(&result, "t009-9.txt", true, FILE_ATTRIBUTE_ARCHIVE);
+       ret &= check_result(&result, "t014-14.txt", false, 0);
+       ret &= check_result(&result, "t015-15.txt", false, 0);
+       ret &= check_result(&result, "t016-16.txt", true, FILE_ATTRIBUTE_NORMAL);
+       ret &= check_result(&result, "t017-17.txt", false, 0);
+       ret &= check_result(&result, "t018-18.txt", true, FILE_ATTRIBUTE_ARCHIVE);
+       ret &= check_result(&result, "t019-19.txt", true, FILE_ATTRIBUTE_ARCHIVE);
+       ret &= check_result(&result, "T013-13.txt.2", true, FILE_ATTRIBUTE_ARCHIVE);
+       ret &= check_result(&result, "T003-3.txt.2", false, 0);
+       ret &= check_result(&result, "T013-13.txt.3", true, FILE_ATTRIBUTE_ARCHIVE);
 
        if (!ret) {
                for (i=0;i<result.count;i++) {
                        printf("%s %s (0x%x)\n", 
                               result.list[i].both_directory_info.name.s, 
-                              attrib_string(mem_ctx, result.list[i].both_directory_info.attrib),
+                              attrib_string(tctx, result.list[i].both_directory_info.attrib),
                               result.list[i].both_directory_info.attrib);
                }
        }
@@ -954,27 +959,27 @@ done:
 /* 
    testing if directories always come back sorted
 */
-static BOOL test_sorted(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
+static bool test_sorted(struct torture_context *tctx, struct smbcli_state *cli)
 {
        const int num_files = 700;
        int i, fnum;
        char *fname;
-       BOOL ret = True;
+       bool ret = true;
        NTSTATUS status;
        struct multiple_result result;
 
        if (!torture_setup_dir(cli, BASEDIR)) {
-               return False;
+               return false;
        }
 
        printf("Creating %d files\n", num_files);
 
        for (i=0;i<num_files;i++) {
-               fname = talloc_asprintf(cli, BASEDIR "\\%s.txt", generate_random_str_list(mem_ctx, 10, "abcdefgh"));
+               fname = talloc_asprintf(cli, BASEDIR "\\%s.txt", generate_random_str_list(tctx, 10, "abcdefgh"));
                fnum = smbcli_open(cli->tree, fname, O_CREAT|O_RDWR, DENY_NONE);
                if (fnum == -1) {
                        printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
-                       ret = False;
+                       ret = false;
                        goto done;
                }
                talloc_free(fname);
@@ -983,9 +988,9 @@ static BOOL test_sorted(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
 
 
        ZERO_STRUCT(result);
-       result.mem_ctx = mem_ctx;
+       result.tctx = tctx;
        
-       status = multiple_search(cli, mem_ctx, BASEDIR "\\*.*", 
+       status = multiple_search(cli, tctx, BASEDIR "\\*.*", 
                                 RAW_SEARCH_DATA_BOTH_DIRECTORY_INFO,
                                 CONT_NAME, &result);   
        CHECK_STATUS(status, NT_STATUS_OK);
@@ -1017,17 +1022,23 @@ done:
 /* 
    basic testing of many old style search calls using separate dirs
 */
-static BOOL test_many_dirs(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
+static bool test_many_dirs(struct torture_context *tctx, 
+                                                  struct smbcli_state *cli)
 {
-       const int num_dirs = 100;
+       const int num_dirs = 20;
        int i, fnum, n;
        char *fname, *dname;
-       BOOL ret = True;
+       bool ret = true;
        NTSTATUS status;
        union smb_search_data *file, *file2, *file3;
 
+       if (!torture_setting_bool(tctx, "raw_search_search", true)) {
+               torture_comment(tctx, "Skipping these tests as the server "
+                       "doesn't support old style search calls\n");
+               return true;
+       }
        if (!torture_setup_dir(cli, BASEDIR)) {
-               return False;
+               return false;
        }
 
        printf("Creating %d dirs\n", num_dirs);
@@ -1038,7 +1049,7 @@ static BOOL test_many_dirs(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
                if (!NT_STATUS_IS_OK(status)) {
                        printf("(%s) Failed to create %s - %s\n", 
                               __location__, dname, nt_errstr(status));
-                       ret = False;
+                       ret = false;
                        goto done;
                }
 
@@ -1048,7 +1059,7 @@ static BOOL test_many_dirs(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
                        if (fnum == -1) {
                                printf("(%s) Failed to create %s - %s\n", 
                                       __location__, fname, smbcli_errstr(cli->tree));
-                               ret = False;
+                               ret = false;
                                goto done;
                        }
                        talloc_free(fname);
@@ -1058,9 +1069,9 @@ static BOOL test_many_dirs(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
                talloc_free(dname);
        }
 
-       file  = talloc_zero_array(mem_ctx, union smb_search_data, num_dirs);
-       file2 = talloc_zero_array(mem_ctx, union smb_search_data, num_dirs);
-       file3 = talloc_zero_array(mem_ctx, union smb_search_data, num_dirs);
+       file  = talloc_zero_array(tctx, union smb_search_data, num_dirs);
+       file2 = talloc_zero_array(tctx, union smb_search_data, num_dirs);
+       file3 = talloc_zero_array(tctx, union smb_search_data, num_dirs);
 
        printf("Search first on %d dirs\n", num_dirs);
 
@@ -1070,24 +1081,24 @@ static BOOL test_many_dirs(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
                io.search_first.data_level = RAW_SEARCH_DATA_SEARCH;
                io.search_first.in.max_count = 1;
                io.search_first.in.search_attrib = 0;
-               io.search_first.in.pattern = talloc_asprintf(mem_ctx, BASEDIR "\\d%d\\*.txt", i);
-               fname = talloc_asprintf(mem_ctx, "f%d-", i);
+               io.search_first.in.pattern = talloc_asprintf(tctx, BASEDIR "\\d%d\\*.txt", i);
+               fname = talloc_asprintf(tctx, "f%d-", i);
 
                io.search_first.out.count = 0;
 
-               status = smb_raw_search_first(cli->tree, mem_ctx,
+               status = smb_raw_search_first(cli->tree, tctx,
                                              &io, (void *)&file[i], single_search_callback);
                if (io.search_first.out.count != 1) {
                        printf("(%s) search first gave %d entries for dir %d - %s\n",
                               __location__, io.search_first.out.count, i, nt_errstr(status));
-                       ret = False;
+                       ret = false;
                        goto done;
                }
                CHECK_STATUS(status, NT_STATUS_OK);
                if (strncasecmp(file[i].search.name, fname, strlen(fname)) != 0) {
                        printf("(%s) incorrect name '%s' expected '%s'[12].txt\n", 
                               __location__, file[i].search.name, fname);
-                       ret = False;
+                       ret = false;
                        goto done;
                }
 
@@ -1104,23 +1115,23 @@ static BOOL test_many_dirs(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
                io2.search_next.in.max_count = 1;
                io2.search_next.in.search_attrib = 0;
                io2.search_next.in.id = file[i].search.id;
-               fname = talloc_asprintf(mem_ctx, "f%d-", i);
+               fname = talloc_asprintf(tctx, "f%d-", i);
 
                io2.search_next.out.count = 0;
 
-               status = smb_raw_search_next(cli->tree, mem_ctx,
+               status = smb_raw_search_next(cli->tree, tctx,
                                             &io2, (void *)&file2[i], single_search_callback);
                if (io2.search_next.out.count != 1) {
                        printf("(%s) search next gave %d entries for dir %d - %s\n",
                               __location__, io2.search_next.out.count, i, nt_errstr(status));
-                       ret = False;
+                       ret = false;
                        goto done;
                }
                CHECK_STATUS(status, NT_STATUS_OK);
                if (strncasecmp(file2[i].search.name, fname, strlen(fname)) != 0) {
                        printf("(%s) incorrect name '%s' expected '%s'[12].txt\n", 
                               __location__, file2[i].search.name, fname);
-                       ret = False;
+                       ret = false;
                        goto done;
                }
 
@@ -1138,15 +1149,15 @@ static BOOL test_many_dirs(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
                io2.search_next.in.max_count = 1;
                io2.search_next.in.search_attrib = 0;
                io2.search_next.in.id = file[i].search.id;
-               fname = talloc_asprintf(mem_ctx, "f%d-", i);
+               fname = talloc_asprintf(tctx, "f%d-", i);
                io2.search_next.out.count = 0;
 
-               status = smb_raw_search_next(cli->tree, mem_ctx,
+               status = smb_raw_search_next(cli->tree, tctx,
                                             &io2, (void *)&file3[i], single_search_callback);
                if (io2.search_next.out.count != 1) {
                        printf("(%s) search next gave %d entries for dir %d - %s\n",
                               __location__, io2.search_next.out.count, i, nt_errstr(status));
-                       ret = False;
+                       ret = false;
                        goto done;
                }
                CHECK_STATUS(status, NT_STATUS_OK);
@@ -1154,14 +1165,15 @@ static BOOL test_many_dirs(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
                if (strncasecmp(file3[i].search.name, file2[i].search.name, 3) != 0) {
                        printf("(%s) incorrect name '%s' on rewind at dir %d\n", 
                               __location__, file2[i].search.name, i);
-                       ret = False;
+                       ret = false;
                        goto done;
                }
 
-               if (strcmp(file3[i].search.name, file2[i].search.name) != 0) {
+               if (torture_setting_bool(tctx, "rewind_support", true) &&
+                   strcmp(file3[i].search.name, file2[i].search.name) != 0) {
                        printf("(%s) server did not rewind - got '%s' expected '%s'\n", 
                               __location__, file3[i].search.name, file2[i].search.name);
-                       ret = False;
+                       ret = false;
                        goto done;
                }
 
@@ -1180,21 +1192,29 @@ done:
 /* 
    testing of OS/2 style delete
 */
-static BOOL test_os2_delete(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
+static bool test_os2_delete(struct torture_context *tctx, 
+                                                       struct smbcli_state *cli)
 {
        const int num_files = 700;
        const int delete_count = 4;
        int total_deleted = 0;
        int i, fnum;
        char *fname;
-       BOOL ret = True;
+       bool ret = true;
        NTSTATUS status;
        union smb_search_first io;
        union smb_search_next io2;
        struct multiple_result result;
 
+       if (!torture_setting_bool(tctx, "search_ea_size", true)){
+               torture_comment(tctx,
+                               "Server does not support RAW_SEARCH_EA_SIZE "
+                               "level. Skipping this test\n");
+               return true;
+       }
+
        if (!torture_setup_dir(cli, BASEDIR)) {
-               return False;
+               return false;
        }
 
        printf("Testing OS/2 style delete on %d files\n", num_files);
@@ -1204,7 +1224,7 @@ static BOOL test_os2_delete(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
                fnum = smbcli_open(cli->tree, fname, O_CREAT|O_RDWR, DENY_NONE);
                if (fnum == -1) {
                        printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
-                       ret = False;
+                       ret = false;
                        goto done;
                }
                talloc_free(fname);
@@ -1213,7 +1233,7 @@ static BOOL test_os2_delete(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
 
 
        ZERO_STRUCT(result);
-       result.mem_ctx = mem_ctx;
+       result.tctx = tctx;
 
        io.t2ffirst.level = RAW_SEARCH_TRANS2;
        io.t2ffirst.data_level = RAW_SEARCH_DATA_EA_SIZE;
@@ -1223,7 +1243,7 @@ static BOOL test_os2_delete(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
        io.t2ffirst.in.storage_type = 0;
        io.t2ffirst.in.pattern = BASEDIR "\\*";
 
-       status = smb_raw_search_first(cli->tree, mem_ctx,
+       status = smb_raw_search_first(cli->tree, tctx,
                                      &io, &result, multiple_search_callback);
        CHECK_STATUS(status, NT_STATUS_OK);
 
@@ -1245,9 +1265,9 @@ static BOOL test_os2_delete(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
 
        do {
                ZERO_STRUCT(result);
-               result.mem_ctx = mem_ctx;
+               result.tctx = tctx;
 
-               status = smb_raw_search_next(cli->tree, mem_ctx,
+               status = smb_raw_search_next(cli->tree, tctx,
                                             &io2, &result, multiple_search_callback);
                if (!NT_STATUS_IS_OK(status)) {
                        break;
@@ -1272,7 +1292,7 @@ static BOOL test_os2_delete(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
        if (total_deleted != num_files) {
                printf("error: deleted %d - expected to delete %d\n", 
                       total_deleted, num_files);
-               ret = False;
+               ret = false;
        }
 
 done:
@@ -1291,10 +1311,11 @@ static int ealist_cmp(union smb_search_data *r1, union smb_search_data *r2)
 /* 
    testing of the rather strange ea_list level
 */
-static BOOL test_ea_list(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
+static bool test_ea_list(struct torture_context *tctx, 
+                                                struct smbcli_state *cli)
 {
        int  fnum;
-       BOOL ret = True;
+       bool ret = true;
        NTSTATUS status;
        union smb_search_first io;
        union smb_search_next nxt;
@@ -1302,11 +1323,17 @@ static BOOL test_ea_list(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
        union smb_setfileinfo setfile;
 
        if (!torture_setup_dir(cli, BASEDIR)) {
-               return False;
+               return false;
        }
 
        printf("Testing RAW_SEARCH_EA_LIST level\n");
 
+       if (!torture_setting_bool(tctx, "search_ea_support", true) ||
+           !torture_setting_bool(tctx, "ea_support", true)) {
+               printf("..skipped per target configuration.\n");
+               return true;
+       }
+
        fnum = smbcli_open(cli->tree, BASEDIR "\\file1.txt", O_CREAT|O_RDWR, DENY_NONE);
        smbcli_close(cli->tree, fnum);
 
@@ -1319,7 +1346,7 @@ static BOOL test_ea_list(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
        setfile.generic.level = RAW_SFILEINFO_EA_SET;
        setfile.generic.in.file.path = BASEDIR "\\file2.txt";
        setfile.ea_set.in.num_eas = 2;
-       setfile.ea_set.in.eas = talloc_array(mem_ctx, struct ea_struct, 2);
+       setfile.ea_set.in.eas = talloc_array(tctx, struct ea_struct, 2);
        setfile.ea_set.in.eas[0].flags = 0;
        setfile.ea_set.in.eas[0].name.s = "EA ONE";
        setfile.ea_set.in.eas[0].value = data_blob_string_const("VALUE 1");
@@ -1335,7 +1362,7 @@ static BOOL test_ea_list(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
        CHECK_STATUS(status, NT_STATUS_OK);
        
        ZERO_STRUCT(result);
-       result.mem_ctx = mem_ctx;
+       result.tctx = tctx;
 
        io.t2ffirst.level = RAW_SEARCH_TRANS2;
        io.t2ffirst.data_level = RAW_SEARCH_DATA_EA_LIST;
@@ -1345,11 +1372,11 @@ static BOOL test_ea_list(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
        io.t2ffirst.in.storage_type = 0;
        io.t2ffirst.in.pattern = BASEDIR "\\*";
        io.t2ffirst.in.num_names = 2;
-       io.t2ffirst.in.ea_names = talloc_array(mem_ctx, struct ea_name, 2);
+       io.t2ffirst.in.ea_names = talloc_array(tctx, struct ea_name, 2);
        io.t2ffirst.in.ea_names[0].name.s = "SECOND EA";
        io.t2ffirst.in.ea_names[1].name.s = "THIRD EA";
 
-       status = smb_raw_search_first(cli->tree, mem_ctx,
+       status = smb_raw_search_first(cli->tree, tctx,
                                      &io, &result, multiple_search_callback);
        CHECK_STATUS(status, NT_STATUS_OK);
        CHECK_VALUE(result.count, 2);
@@ -1362,18 +1389,17 @@ static BOOL test_ea_list(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
        nxt.t2fnext.in.flags = FLAG_TRANS2_FIND_REQUIRE_RESUME | FLAG_TRANS2_FIND_CONTINUE;
        nxt.t2fnext.in.last_name = result.list[1].ea_list.name.s;
        nxt.t2fnext.in.num_names = 2;
-       nxt.t2fnext.in.ea_names = talloc_array(mem_ctx, struct ea_name, 2);
+       nxt.t2fnext.in.ea_names = talloc_array(tctx, struct ea_name, 2);
        nxt.t2fnext.in.ea_names[0].name.s = "SECOND EA";
        nxt.t2fnext.in.ea_names[1].name.s = "THIRD EA";
 
-       status = smb_raw_search_next(cli->tree, mem_ctx,
+       status = smb_raw_search_next(cli->tree, tctx,
                                     &nxt, &result, multiple_search_callback);
        CHECK_STATUS(status, NT_STATUS_OK);
 
        /* we have to sort the result as different servers can return directories
           in different orders */
-       qsort(result.list, result.count, sizeof(result.list[0]), 
-             (comparison_fn_t)ealist_cmp);
+       TYPESAFE_QSORT(result.list, result.count, ealist_cmp);
 
        CHECK_VALUE(result.count, 3);
        CHECK_VALUE(result.list[0].ea_list.eas.num_eas, 2);
@@ -1397,40 +1423,103 @@ static BOOL test_ea_list(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
        CHECK_STRING(result.list[2].ea_list.eas.eas[1].name.s, "THIRD EA");
        CHECK_VALUE(result.list[2].ea_list.eas.eas[1].value.length, 0);
 
-done:
        smb_raw_exit(cli->session);
        smbcli_deltree(cli->tree, BASEDIR);
 
        return ret;
 }
 
-
-
-/* 
-   basic testing of all RAW_SEARCH_* calls using a single file
+/*
+ Test the behavior of max count parameter in TRANS2_FIND_FIRST2 and
+ TRANS2_FIND_NEXT2 queries
 */
-BOOL torture_raw_search(struct torture_context *torture)
+static bool test_max_count(struct torture_context *tctx,
+                          struct smbcli_state *cli)
 {
-       struct smbcli_state *cli;
-       BOOL ret = True;
-       TALLOC_CTX *mem_ctx;
+       const int num_files = 2;
+       int i, fnum;
+       char *fname;
+       bool ret = true;
+       NTSTATUS status;
+       struct multiple_result result;
+       union smb_search_first io;
+       union smb_search_next io2;
+
+       if (!torture_setup_dir(cli, BASEDIR)) {
+               return false;
+       }
+
+       torture_comment(tctx, "Creating %d files\n", num_files);
 
-       if (!torture_open_connection(&cli)) {
-               return False;
+       for (i=num_files-1;i>=0;i--) {
+               fname = talloc_asprintf(cli, BASEDIR "\\t%03d-%d.txt", i, i);
+               fnum = smbcli_open(cli->tree, fname, O_CREAT|O_RDWR, DENY_NONE);
+               if (fnum == -1) {
+                       torture_comment(tctx,
+                               "Failed to create %s - %s\n",
+                               fname, smbcli_errstr(cli->tree));
+                       ret = false;
+                       goto done;
+               }
+               talloc_free(fname);
+               smbcli_close(cli->tree, fnum);
        }
 
-       mem_ctx = talloc_init("torture_search");
+       torture_comment(tctx, "Set max_count parameter to 0. "
+                       "This should return 1 entry\n");
+       ZERO_STRUCT(result);
+       result.tctx = talloc_new(tctx);
 
-       ret &= test_one_file(cli, mem_ctx);
-       ret &= test_many_files(cli, mem_ctx);
-       ret &= test_sorted(cli, mem_ctx);
-       ret &= test_modify_search(cli, mem_ctx);
-       ret &= test_many_dirs(cli, mem_ctx);
-       ret &= test_os2_delete(cli, mem_ctx);
-       ret &= test_ea_list(cli, mem_ctx);
+       io.t2ffirst.level = RAW_SEARCH_TRANS2;
+       io.t2ffirst.data_level = RAW_SEARCH_DATA_BOTH_DIRECTORY_INFO;
+       io.t2ffirst.in.search_attrib = 0;
+       io.t2ffirst.in.max_count = 0;
+       io.t2ffirst.in.flags = 0;
+       io.t2ffirst.in.storage_type = 0;
+       io.t2ffirst.in.pattern = BASEDIR "\\*.*";
+
+       status = smb_raw_search_first(cli->tree, tctx,
+                                     &io, &result, multiple_search_callback);
+       CHECK_STATUS(status, NT_STATUS_OK);
+       CHECK_VALUE(result.count, 1);
+
+       torture_comment(tctx, "Set max_count to 1. This should also "
+                       "return 1 entry\n");
+       io2.t2fnext.level = RAW_SEARCH_TRANS2;
+       io2.t2fnext.data_level = RAW_SEARCH_DATA_BOTH_DIRECTORY_INFO;
+       io2.t2fnext.in.handle = io.t2ffirst.out.handle;
+       io2.t2fnext.in.max_count = 1;
+       io2.t2fnext.in.resume_key = 0;
+       io2.t2fnext.in.flags = 0;
+       io2.t2fnext.in.last_name =
+               result.list[result.count-1].both_directory_info.name.s;
+
+       status = smb_raw_search_next(cli->tree, tctx,
+                                    &io2, &result, multiple_search_callback);
+       CHECK_STATUS(status, NT_STATUS_OK);
+       CHECK_VALUE(result.count, 2);
+done:
+       smb_raw_exit(cli->session);
+       smbcli_deltree(cli->tree, BASEDIR);
 
-       torture_close_connection(cli);
-       talloc_free(mem_ctx);
-       
        return ret;
 }
+
+/* 
+   basic testing of all RAW_SEARCH_* calls using a single file
+*/
+struct torture_suite *torture_raw_search(TALLOC_CTX *mem_ctx)
+{
+       struct torture_suite *suite = torture_suite_create(mem_ctx, "search");
+
+       torture_suite_add_1smb_test(suite, "one file search", test_one_file);
+       torture_suite_add_1smb_test(suite, "many files", test_many_files);
+       torture_suite_add_1smb_test(suite, "sorted", test_sorted);
+       torture_suite_add_1smb_test(suite, "modify search", test_modify_search);
+       torture_suite_add_1smb_test(suite, "many dirs", test_many_dirs);
+       torture_suite_add_1smb_test(suite, "os2 delete", test_os2_delete);
+       torture_suite_add_1smb_test(suite, "ea list", test_ea_list);
+       torture_suite_add_1smb_test(suite, "max count", test_max_count);
+
+       return suite;
+}