Unix SMB/CIFS implementation.
SMB torture tester utility functions
Copyright (C) Andrew Tridgell 2003
+ Copyright (C) Jelmer Vernooij 2006
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 "system/shmem.h"
#include "system/wait.h"
#include "system/time.h"
+#include "torture/ui.h"
#include "torture/torture.h"
+#include "util/dlinklist.h"
+#include "auth/credentials/credentials.h"
+#include "param/param.h"
/**
setup a directory ready for a test
*/
-_PUBLIC_ BOOL torture_setup_dir(struct smbcli_state *cli, const char *dname)
+_PUBLIC_ bool torture_setup_dir(struct smbcli_state *cli, const char *dname)
{
smb_raw_exit(cli->session);
if (smbcli_deltree(cli->tree, dname) == -1 ||
union smb_open io;
TALLOC_CTX *mem_ctx;
- mem_ctx = talloc_init("create_directory_handle");
+ mem_ctx = talloc_named_const(tree, 0, "create_directory_handle");
io.generic.level = RAW_OPEN_NTCREATEX;
io.ntcreatex.in.root_fid = 0;
check that a wire string matches the flags specified
not 100% accurate, but close enough for testing
*/
-BOOL wire_bad_flags(struct smb_wire_string *str, int flags, struct smbcli_state *cli)
+bool wire_bad_flags(struct smb_wire_string *str, int flags, struct smbcli_transport *transport)
{
- BOOL server_unicode;
+ bool server_unicode;
int len;
if (!str || !str->s) return True;
len = strlen(str->s);
if (flags & STR_TERMINATE) len++;
- server_unicode = (cli->transport->negotiate.capabilities&CAP_UNICODE)?True:False;
+ server_unicode = (transport->negotiate.capabilities&CAP_UNICODE)?True:False;
if (getenv("CLI_FORCE_ASCII") || !lp_unicode()) {
server_unicode = False;
}
*/
void torture_all_info(struct smbcli_tree *tree, const char *fname)
{
- TALLOC_CTX *mem_ctx = talloc_init("%s", fname);
+ TALLOC_CTX *mem_ctx = talloc_named(tree, 0, "%s", fname);
union smb_fileinfo finfo;
NTSTATUS status;
/*
set a attribute on a file
*/
-BOOL torture_set_file_attribute(struct smbcli_tree *tree, const char *fname, uint16_t attrib)
+bool torture_set_file_attribute(struct smbcli_tree *tree, const char *fname, uint16_t attrib)
{
union smb_setfileinfo sfinfo;
NTSTATUS status;
NTSTATUS status;
TALLOC_CTX *mem_ctx;
- mem_ctx = talloc_init("torture_set_sparse");
+ mem_ctx = talloc_named_const(tree, 0, "torture_set_sparse");
if (!mem_ctx) {
return NT_STATUS_NO_MEMORY;
}
return NT_STATUS_EA_CORRUPT_ERROR;
}
-BOOL torture_open_connection_share(TALLOC_CTX *mem_ctx,
+_PUBLIC_ bool torture_open_connection_share(TALLOC_CTX *mem_ctx,
struct smbcli_state **c,
const char *hostname,
const char *sharename,
return False;
}
- (*c)->transport->options.use_oplocks = use_oplocks;
- (*c)->transport->options.use_level2_oplocks = use_level_II_oplocks;
+ (*c)->transport->options.use_oplocks = lp_parm_bool(NULL, "torture",
+ "use_oplocks", false);
+ (*c)->transport->options.use_level2_oplocks = lp_parm_bool(NULL, "torture",
+ "use_level2_oplocks", false);
return True;
}
-_PUBLIC_ BOOL torture_open_connection(struct smbcli_state **c, int conn_index)
+_PUBLIC_ bool torture_get_conn_index(int conn_index,
+ TALLOC_CTX *mem_ctx,
+ char **host, char **share)
{
- const char *host = lp_parm_string(-1, "torture", "host");
- const char *share = lp_parm_string(-1, "torture", "share");
char **unc_list = NULL;
int num_unc_names = 0;
const char *p;
+
+ (*host) = talloc_strdup(mem_ctx, lp_parm_string(NULL, "torture", "host"));
+ (*share) = talloc_strdup(mem_ctx, lp_parm_string(NULL, "torture", "share"));
- p = lp_parm_string(-1, "torture", "unclist");
- if (p) {
- char *h, *s;
- unc_list = file_lines_load(p, &num_unc_names, NULL);
- if (!unc_list || num_unc_names <= 0) {
- printf("Failed to load unc names list from '%s'\n", p);
- exit(1);
- }
+ p = lp_parm_string(NULL, "torture", "unclist");
+ if (!p) {
+ return True;
+ }
- if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names],
- NULL, &h, &s)) {
- printf("Failed to parse UNC name %s\n",
- unc_list[conn_index % num_unc_names]);
- exit(1);
- }
- host = h;
- share = s;
+ unc_list = file_lines_load(p, &num_unc_names, NULL);
+ if (!unc_list || num_unc_names <= 0) {
+ DEBUG(0,("Failed to load unc names list from '%s'\n", p));
+ return False;
+ }
+
+ if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names],
+ mem_ctx, host, share)) {
+ DEBUG(0, ("Failed to parse UNC name %s\n",
+ unc_list[conn_index % num_unc_names]));
+ return False;
}
- return torture_open_connection_share(NULL, c, host, share, NULL);
+ talloc_free(unc_list);
+ return True;
}
-_PUBLIC_ BOOL torture_open_connection_ev(struct smbcli_state **c,
+
+
+_PUBLIC_ bool torture_open_connection_ev(struct smbcli_state **c,
int conn_index,
struct event_context *ev)
{
- const char *host = lp_parm_string(-1, "torture", "host");
- const char *share = lp_parm_string(-1, "torture", "share");
- char **unc_list = NULL;
- int num_unc_names = 0;
- const char *p;
-
- p = lp_parm_string(-1, "torture", "unclist");
- if (p) {
- char *h, *s;
- unc_list = file_lines_load(p, &num_unc_names, NULL);
- if (!unc_list || num_unc_names <= 0) {
- printf("Failed to load unc names list from '%s'\n", p);
- exit(1);
- }
+ char *host, *share;
+ bool ret;
- if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names],
- NULL, &h, &s)) {
- printf("Failed to parse UNC name %s\n",
- unc_list[conn_index % num_unc_names]);
- exit(1);
- }
- host = h;
- share = s;
+ if (!torture_get_conn_index(conn_index, ev, &host, &share)) {
+ return False;
}
+ ret = torture_open_connection_share(NULL, c, host, share, ev);
+ talloc_free(host);
+ talloc_free(share);
+
+ return ret;
+}
- return torture_open_connection_share(NULL, c, host, share, ev);
+_PUBLIC_ bool torture_open_connection(struct smbcli_state **c, int conn_index)
+{
+ return torture_open_connection_ev(c, conn_index,
+ cli_credentials_get_event_context(cmdline_credentials));
}
-_PUBLIC_ BOOL torture_close_connection(struct smbcli_state *c)
+_PUBLIC_ bool torture_close_connection(struct smbcli_state *c)
{
- BOOL ret = True;
+ bool ret = True;
if (!c) return True;
if (NT_STATUS_IS_ERR(smbcli_tdis(c))) {
printf("tdis failed (%s)\n", smbcli_errstr(c->tree));
/* check if the server produced the expected error code */
-_PUBLIC_ BOOL check_error(const char *location, struct smbcli_state *c,
+_PUBLIC_ bool check_error(const char *location, struct smbcli_state *c,
uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
{
NTSTATUS status;
{
}
-double torture_create_procs(BOOL (*fn)(struct smbcli_state *, int), BOOL *result)
+double torture_create_procs(struct torture_context *tctx,
+ bool (*fn)(struct torture_context *, struct smbcli_state *, int), bool *result)
{
int i, status;
volatile pid_t *child_status;
- volatile BOOL *child_status_out;
+ volatile bool *child_status_out;
int synccount;
int tries = 8;
+ int torture_nprocs = torture_setting_int(tctx, "nprocs", 4);
double start_time_limit = 10 + (torture_nprocs * 1.5);
struct timeval tv;
return -1;
}
- child_status_out = (volatile BOOL *)shm_setup(sizeof(BOOL)*torture_nprocs);
+ child_status_out = (volatile bool *)shm_setup(sizeof(bool)*torture_nprocs);
if (!child_status_out) {
printf("Failed to setup result status shared memory\n");
return -1;
_exit(1);
}
- child_status_out[i] = fn(current_cli, i);
+ child_status_out[i] = fn(tctx, current_cli, i);
_exit(0);
}
}
return timeval_elapsed(&tv);
}
-static BOOL wrap_old_torture_multifn(struct torture_context *torture,
- const void *_fn)
+static bool wrap_smb_multi_test(struct torture_context *torture,
+ struct torture_tcase *tcase,
+ struct torture_test *test)
{
- BOOL (*fn)(struct smbcli_state *, int ) = _fn;
- BOOL result;
+ bool (*fn)(struct torture_context *, struct smbcli_state *, int ) = test->fn;
+ bool result;
- torture_create_procs(fn, &result);
+ torture_create_procs(torture, fn, &result);
return result;
}
-_PUBLIC_ NTSTATUS register_torture_multi_op(const char *name,
- BOOL (*multi_fn)(struct smbcli_state *, int ))
+_PUBLIC_ struct torture_test *torture_suite_add_smb_multi_test(
+ struct torture_suite *suite,
+ const char *name,
+ bool (*run) (struct torture_context *,
+ struct smbcli_state *,
+ int i))
+{
+ struct torture_test *test;
+ struct torture_tcase *tcase;
+
+ tcase = torture_suite_add_tcase(suite, name);
+
+ test = talloc(tcase, struct torture_test);
+
+ test->name = talloc_strdup(test, name);
+ test->description = NULL;
+ test->run = wrap_smb_multi_test;
+ test->fn = run;
+ test->dangerous = false;
+
+ DLIST_ADD_END(tcase->tests, test, struct torture_test *);
+
+ return test;
+
+}
+
+static bool wrap_simple_2smb_test(struct torture_context *torture_ctx,
+ struct torture_tcase *tcase,
+ struct torture_test *test)
{
- struct torture_suite *suite;
+ bool (*fn) (struct torture_context *, struct smbcli_state *,
+ struct smbcli_state *);
+ bool ret;
+
+ struct smbcli_state *cli1, *cli2;
+
+ if (!torture_open_connection(&cli1, 0) ||
+ !torture_open_connection(&cli2, 1))
+ return false;
+
+ fn = test->fn;
+
+ ret = fn(torture_ctx, cli1, cli2);
+
+ talloc_free(cli1);
+ talloc_free(cli2);
+
+ return ret;
+}
+
+
+
+_PUBLIC_ struct torture_test *torture_suite_add_2smb_test(
+ struct torture_suite *suite,
+ const char *name,
+ bool (*run) (struct torture_context *,
+ struct smbcli_state *,
+ struct smbcli_state *))
+{
+ struct torture_test *test;
+ struct torture_tcase *tcase;
+
+ tcase = torture_suite_add_tcase(suite, name);
+
+ test = talloc(tcase, struct torture_test);
+
+ test->name = talloc_strdup(test, name);
+ test->description = NULL;
+ test->run = wrap_simple_2smb_test;
+ test->fn = run;
+ test->dangerous = false;
+
+ DLIST_ADD_END(tcase->tests, test, struct torture_test *);
+
+ return test;
+
+}
+
+static bool wrap_simple_1smb_test(struct torture_context *torture_ctx,
+ struct torture_tcase *tcase,
+ struct torture_test *test)
+{
+ bool (*fn) (struct torture_context *, struct smbcli_state *);
+ bool ret;
+
+ struct smbcli_state *cli1;
+
+ if (!torture_open_connection(&cli1, 0))
+ return false;
+
+ fn = test->fn;
+
+ ret = fn(torture_ctx, cli1);
+
+ talloc_free(cli1);
+
+ return ret;
+}
+
+_PUBLIC_ struct torture_test *torture_suite_add_1smb_test(
+ struct torture_suite *suite,
+ const char *name,
+ bool (*run) (struct torture_context *, struct smbcli_state *))
+{
+ struct torture_test *test;
+ struct torture_tcase *tcase;
+
+ tcase = torture_suite_add_tcase(suite, name);
+
+ test = talloc(tcase, struct torture_test);
- suite = torture_suite_create(talloc_autofree_context(), name);
+ test->name = talloc_strdup(test, name);
+ test->description = NULL;
+ test->run = wrap_simple_1smb_test;
+ test->fn = run;
+ test->dangerous = false;
- torture_suite_add_simple_tcase(suite, name,
- wrap_old_torture_multifn,
- multi_fn);
- torture_register_suite(suite);
+ DLIST_ADD_END(tcase->tests, test, struct torture_test *);
- return NT_STATUS_OK;
+ return test;
}