diff --git a/configure.ac b/configure.ac index 1976df4aa..617d5204a 100644 --- a/configure.ac +++ b/configure.ac @@ -634,6 +634,7 @@ tests/src/editor/Makefile tests/src/editor/test-data.txt tests/src/vfs/Makefile tests/src/vfs/smbfs/Makefile +tests/src/vfs/smbfs/it/Makefile ]) fi diff --git a/src/vfs/smbfs/Makefile.am b/src/vfs/smbfs/Makefile.am index b9c0c6a49..7d3e4207d 100644 --- a/src/vfs/smbfs/Makefile.am +++ b/src/vfs/smbfs/Makefile.am @@ -3,7 +3,9 @@ AM_CPPFLAGS = $(GLIB_CFLAGS) -I$(top_srcdir) noinst_LTLIBRARIES = libvfs-smbfs.la libvfs_smbfs_la_SOURCES = \ + dir.c \ init.c init.h \ internal.c internal.h \ + stat.c \ vfs_class.c vfs_subclass.c diff --git a/src/vfs/smbfs/dir.c b/src/vfs/smbfs/dir.c new file mode 100644 index 000000000..3de888875 --- /dev/null +++ b/src/vfs/smbfs/dir.c @@ -0,0 +1,210 @@ +/* Virtual File System: Samba file system. + The internal functions: dirs + + Copyright (C) 2013 + The Free Software Foundation, Inc. + + Written by: + Slava Zanko , 2013 + + This file is part of the Midnight Commander. + + The Midnight Commander 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 3 of the License, + or (at your option) any later version. + + The Midnight Commander is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + 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, see . + */ + +#include + +#include + +#include "lib/global.h" + +#include "internal.h" + +/*** global variables ****************************************************************************/ + +/*** file scope macro definitions ****************************************************************/ + +/*** file scope type declarations ****************************************************************/ + +typedef struct +{ + int handle; + smbfs_super_data_t *super_data; +} smbfs_dir_data_t; + +/*** file scope variables ************************************************************************/ + +/*** file scope functions ************************************************************************/ +/* --------------------------------------------------------------------------------------------- */ + +/* --------------------------------------------------------------------------------------------- */ +/*** public functions ****************************************************************************/ +/* --------------------------------------------------------------------------------------------- */ +/** + * Open a directory stream corresponding to the directory name. + * + * @param vpath path to directory + * @param error pointer to the error handler + * @return directory data handler if success, NULL otherwise + */ + +void * +smbfs_opendir (const vfs_path_t * vpath, GError ** error) +{ + smbfs_dir_data_t *smbfs_dir = NULL; + struct vfs_s_super *super; + smbfs_super_data_t *super_data; + const vfs_path_element_t *path_element; + int handle; + char *smb_url; + + super = vfs_get_super_by_vpath (vpath, TRUE); + if (super == NULL) + return NULL; + + path_element = vfs_path_get_by_index (vpath, -1); + + super_data = (smbfs_super_data_t *) super->data; + + smb_url = smbfs_make_url (path_element, TRUE); + errno = 0; + handle = smbc_opendir (smb_url); + g_free (smb_url); + + if (handle < 0) + g_set_error (error, MC_ERROR, errno, "%s", smbfs_strerror (errno)); + else + { + smbfs_dir = g_new0 (smbfs_dir_data_t, 1); + smbfs_dir->handle = handle; + smbfs_dir->super_data = super_data; + } + + return (void *) smbfs_dir; +} + +/* --------------------------------------------------------------------------------------------- */ +/** + * Get a pointer to a structure representing the next directory entry. + * + * @param data directory data handler + * @param error pointer to the error handler + * @return information about direntry if success, NULL otherwise + */ + +void * +smbfs_readdir (void *data, GError ** error) +{ + struct smbc_dirent *smb_direntry; + smbfs_dir_data_t *smbfs_dir = (smbfs_dir_data_t *) data; + + static union vfs_dirent smbfs_dirent; + + errno = 0; + smb_direntry = smbc_readdir (smbfs_dir->handle); + if (smb_direntry == NULL) + { + if (errno != 0) + g_set_error (error, MC_ERROR, errno, "%s", smbfs_strerror (errno)); + return NULL; + } + + g_strlcpy (smbfs_dirent.dent.d_name, smb_direntry->name, BUF_MEDIUM); + compute_namelen (&smbfs_dirent.dent); + return &smbfs_dirent; +} + +/* --------------------------------------------------------------------------------------------- */ +/** + * Close the directory stream. + * + * @param data directory data handler + * @param error pointer to the error handler + * @return 0 if sucess, negative value otherwise + */ + +int +smbfs_closedir (void *data, GError ** error) +{ + int return_code; + smbfs_dir_data_t *smbfs_dir = (smbfs_dir_data_t *) data; + + errno = 0; + return_code = smbc_closedir (smbfs_dir->handle); + + if (return_code < 0) + g_set_error (error, MC_ERROR, errno, "%s", smbfs_strerror (errno)); + + g_free (smbfs_dir); + return return_code; +} + +/* --------------------------------------------------------------------------------------------- */ +/** + * Create a new directory. + * + * @param vpath path directory + * @param mode mode (see man 2 open) + * @param error pointer to the error handler + * @return 0 if sucess, negative value otherwise + */ + +int +smbfs_mkdir (const vfs_path_t * vpath, mode_t mode, GError ** error) +{ + int return_code; + char *smb_url; + const vfs_path_element_t *path_element; + + path_element = vfs_path_get_by_index (vpath, -1); + smb_url = smbfs_make_url (path_element, TRUE); + errno = 0; + return_code = smbc_mkdir (smb_url, mode); + g_free (smb_url); + + if (return_code != 0) + g_set_error (error, MC_ERROR, errno, "%s", smbfs_strerror (errno)); + + return return_code; +} + +/* --------------------------------------------------------------------------------------------- */ +/** + * Remove a directory. + * + * @param vpath path directory + * @param error pointer to the error handler + * @return 0 if sucess, negative value otherwise + */ + +int +smbfs_rmdir (const vfs_path_t * vpath, GError ** error) +{ + int return_code; + char *smb_url; + const vfs_path_element_t *path_element; + + path_element = vfs_path_get_by_index (vpath, -1); + smb_url = smbfs_make_url (path_element, TRUE); + errno = 0; + return_code = smbc_rmdir (smb_url); + g_free (smb_url); + + if (return_code != 0) + g_set_error (error, MC_ERROR, errno, "%s", smbfs_strerror (errno)); + + return return_code; +} + +/* --------------------------------------------------------------------------------------------- */ diff --git a/src/vfs/smbfs/internal.c b/src/vfs/smbfs/internal.c index 9afd45cb5..1042193d8 100644 --- a/src/vfs/smbfs/internal.c +++ b/src/vfs/smbfs/internal.c @@ -24,6 +24,7 @@ */ #include +#include #include "lib/global.h" @@ -33,6 +34,9 @@ /*** file scope macro definitions ****************************************************************/ +#define SMBFS_ERRORS_PREFIX "smbfs: " +#define SMBFS_ERRORS_PREFIX_LEN sizeof(SMBFS_ERRORS_PREFIX) + /*** file scope type declarations ****************************************************************/ /*** file scope variables ************************************************************************/ @@ -60,4 +64,93 @@ smbfs_cb_authdata_provider (const char *server, const char *share, } /* --------------------------------------------------------------------------------------------- */ +/** + * Get error string for SAMBA connections by error number. + * + * @param err_no error number + * @return the string representation of the error + */ +const char * +smbfs_strerror (int err_no) +{ + const char *error_str; + switch (err_no) + { + case EINVAL: + error_str = _("smbfs: an incorrect form of file/URL was passed"); + break; + case EPERM: + case ENODEV: + error_str = _("smbfs: the workgroup or server could not be found"); + break; + default: + { + static char sys_error_str[BUF_LARGE]; + strcpy (sys_error_str, SMBFS_ERRORS_PREFIX); + strncpy (sys_error_str + SMBFS_ERRORS_PREFIX_LEN - 1, g_strerror (err_no), + BUF_LARGE - SMBFS_ERRORS_PREFIX_LEN); + sys_error_str[BUF_LARGE - 1] = '\0'; + error_str = sys_error_str; + } + } + return error_str; +} + +/* --------------------------------------------------------------------------------------------- */ + +char * +smbfs_make_url (const vfs_path_element_t * element, gboolean with_path) +{ + GString *buffer; + + if (element == NULL) + return NULL; + + buffer = g_string_new ("smb://"); + + if (element->user != NULL) + { + g_string_append (buffer, element->user); + + if (element->password != NULL) + { + g_string_append_c (buffer, ':'); + g_string_append (buffer, element->password); + } + } + + if (element->host != NULL) + { + if ((element->user != NULL)) + g_string_append_c (buffer, '@'); + if (element->ipv6) + g_string_append_c (buffer, '['); + g_string_append (buffer, element->host); + if (element->ipv6) + g_string_append_c (buffer, ']'); + } + + if (*element->path != '\0') + { + if (*(buffer->str + buffer->len) != PATH_SEP) + g_string_append_c (buffer, PATH_SEP); + + if (with_path) + g_string_append (buffer, element->path); + else + { + const char *slash_pointer; + + slash_pointer = strchr (element->path, PATH_SEP); + if (slash_pointer == NULL) + g_string_append (buffer, element->path); + else + g_string_append_len (buffer, element->path, slash_pointer - element->path); + } + } + + return g_string_free (buffer, FALSE); +} + +/* --------------------------------------------------------------------------------------------- */ diff --git a/src/vfs/smbfs/internal.h b/src/vfs/smbfs/internal.h index 74db8c448..e4c39882a 100644 --- a/src/vfs/smbfs/internal.h +++ b/src/vfs/smbfs/internal.h @@ -17,6 +17,11 @@ /*** structures declarations (and typedefs of structures)*****************************************/ +typedef struct +{ + int socket_handle; +} smbfs_super_data_t; + /*** global variables defined in .c file *********************************************************/ extern struct vfs_class smbfs_class; @@ -33,6 +38,19 @@ void smbfs_cb_authdata_provider (const char *server, const char *share, char *workgroup, int wgmaxlen, char *username, int unmaxlen, char *password, int pwmaxlen); +const char *smbfs_strerror (int err_no); + +char *smbfs_make_url (const vfs_path_element_t * element, gboolean with_path); + +void *smbfs_opendir (const vfs_path_t * vpath, GError ** error); +void *smbfs_readdir (void *data, GError ** error); +int smbfs_closedir (void *data, GError ** error); +int smbfs_mkdir (const vfs_path_t * vpath, mode_t mode, GError ** error); +int smbfs_rmdir (const vfs_path_t * vpath, GError ** error); + +int smbfs_lstat (const vfs_path_t * vpath, struct stat *buf, GError ** error); +int smbfs_stat (const vfs_path_t * vpath, struct stat *buf, GError ** error); + /*** inline functions ****************************************************************************/ diff --git a/src/vfs/smbfs/stat.c b/src/vfs/smbfs/stat.c new file mode 100644 index 000000000..c13de6af0 --- /dev/null +++ b/src/vfs/smbfs/stat.c @@ -0,0 +1,92 @@ +/* Virtual File System: SFTP file system. + The stat functions + + Copyright (C) 2013 + The Free Software Foundation, Inc. + + Written by: + Slava Zanko , 2013 + + This file is part of the Midnight Commander. + + The Midnight Commander 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 3 of the License, + or (at your option) any later version. + + The Midnight Commander is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + 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, see . + */ + +#include +#include + +#include "lib/global.h" + +#include "internal.h" + +/*** global variables ****************************************************************************/ + +/*** file scope macro definitions ****************************************************************/ + +/*** file scope type declarations ****************************************************************/ + +/*** file scope variables ************************************************************************/ + +/*** file scope functions ************************************************************************/ +/* --------------------------------------------------------------------------------------------- */ + +/* --------------------------------------------------------------------------------------------- */ +/*** public functions ****************************************************************************/ +/* --------------------------------------------------------------------------------------------- */ +/** + * Getting information about a symbolic link. + * + * @param vpath path to file, directory or symbolic link + * @param buf buffer for store stat-info + * @param error pointer to error object + * @return 0 if sucess, negative value otherwise + */ + +int +smbfs_lstat (const vfs_path_t * vpath, struct stat *buf, GError ** error) +{ + int return_code; + char *smb_url; + const vfs_path_element_t *path_element; + + path_element = vfs_path_get_by_index (vpath, -1); + smb_url = smbfs_make_url (path_element, TRUE); + + errno = 0; + return_code = smbc_stat (smb_url, buf); + + if (return_code != 0) + g_set_error (error, MC_ERROR, errno, "%s", smbfs_strerror (errno)); + + g_free (smb_url); + return return_code; +} + +/* --------------------------------------------------------------------------------------------- */ +/** + * Getting information about a file or directory. + * + * @param vpath path to file or directory + * @param buf buffer for store stat-info + * @param error pointer to error object + * @return 0 if sucess, negative value otherwise + */ + +int +smbfs_stat (const vfs_path_t * vpath, struct stat *buf, GError ** error) +{ + return smbfs_lstat (vpath, buf, error); +} + +/* --------------------------------------------------------------------------------------------- */ diff --git a/src/vfs/smbfs/vfs_class.c b/src/vfs/smbfs/vfs_class.c index 58912438c..e7129ae50 100644 --- a/src/vfs/smbfs/vfs_class.c +++ b/src/vfs/smbfs/vfs_class.c @@ -27,6 +27,8 @@ #include #include "lib/global.h" +#include "lib/vfs/utilvfs.h" +#include "lib/tty/tty.h" /* tty_enable_interrupt_key () */ #include "internal.h" @@ -51,6 +53,8 @@ struct vfs_class smbfs_class; static int smbfs_cb_init (struct vfs_class *me) { + SMBCCTX *smb_context; + (void) me; if (smbc_init (smbfs_cb_authdata_provider, 0)) @@ -59,6 +63,9 @@ smbfs_cb_init (struct vfs_class *me) return FALSE; } + smb_context = smbc_set_context (NULL); + smbc_setDebug (smb_context, 0); + return TRUE; } @@ -75,6 +82,188 @@ smbfs_cb_done (struct vfs_class *me) (void) me; } +/* --------------------------------------------------------------------------------------------- */ +/** + * Callback for opening directory. + * + * @param vpath path to directory + * @return directory data handler if success, NULL otherwise + */ + +static void * +smbfs_cb_opendir (const vfs_path_t * vpath) +{ + GError *error = NULL; + void *ret_value; + + /* reset interrupt flag */ + tty_got_interrupt (); + + ret_value = smbfs_opendir (vpath, &error); + vfs_show_gerror (&error); + return ret_value; +} + +/* --------------------------------------------------------------------------------------------- */ +/** + * Callback for reading directory entry. + * + * @param data directory data handler + * @return information about direntry if success, NULL otherwise + */ + +static void * +smbfs_cb_readdir (void *data) +{ + GError *error = NULL; + union vfs_dirent *smbfs_dirent; + + if (tty_got_interrupt ()) + { + tty_disable_interrupt_key (); + return NULL; + } + + smbfs_dirent = smbfs_readdir (data, &error); + if (!vfs_show_gerror (&error)) + { + if (smbfs_dirent != NULL) + vfs_print_message (_("smbfs: (Ctrl-G break) Listing... %s"), smbfs_dirent->dent.d_name); + else + vfs_print_message (_("smbfs: Listing done.")); + } + + return smbfs_dirent; +} + +/* --------------------------------------------------------------------------------------------- */ +/** + * Callback for closing directory. + * + * @param data directory data handler + * @return 0 if sucess, negative value otherwise + */ + +static int +smbfs_cb_closedir (void *data) +{ + int rc; + GError *error = NULL; + + rc = smbfs_closedir (data, &error); + vfs_show_gerror (&error); + return rc; +} + +/* --------------------------------------------------------------------------------------------- */ + +/** + * Callback for fill_names VFS function. + * Add Samba connections to the 'Active VFS connections' list + * + * @param me unused + * @param func callback function for adding Samba-connection to list of active connections + */ + +static void +smbfs_cb_fill_names (struct vfs_class *me, fill_names_f func) +{ + GList *iter; + + (void) me; + + for (iter = smbfs_subclass.supers; iter != NULL; iter = g_list_next (iter)) + { + const struct vfs_s_super *super = (const struct vfs_s_super *) iter->data; + char *name; + + name = vfs_path_element_build_pretty_path_str (super->path_element); + + func (name); + g_free (name); + } +} + +/* --------------------------------------------------------------------------------------------- */ +/** + * Callback for mkdir VFS-function. + * + * @param vpath path directory + * @param mode mode (see man 2 open) + * @return 0 if sucess, negative value otherwise + */ + +static int +smbfs_cb_mkdir (const vfs_path_t * vpath, mode_t mode) +{ + int rc; + GError *error = NULL; + + rc = smbfs_mkdir (vpath, mode, &error); + vfs_show_gerror (&error); + return rc; +} + +/* --------------------------------------------------------------------------------------------- */ +/** + * Callback for rmdir VFS-function. + * + * @param vpath path directory + * @param mode mode (see man 2 open) + * @return 0 if sucess, negative value otherwise + */ + +static int +smbfs_cb_rmdir (const vfs_path_t * vpath) +{ + int rc; + GError *error = NULL; + + rc = smbfs_rmdir (vpath, &error); + vfs_show_gerror (&error); + return rc; +} + +/* --------------------------------------------------------------------------------------------- */ +/** + * Callback for lstat VFS-function. + * + * @param vpath path to file or directory + * @param buf buffer for store stat-info + * @return 0 if sucess, negative value otherwise + */ + +static int +smbfs_cb_lstat (const vfs_path_t * vpath, struct stat *buf) +{ + int rc; + GError *error = NULL; + + rc = smbfs_lstat (vpath, buf, &error); + vfs_show_gerror (&error); + return rc; +} + +/* --------------------------------------------------------------------------------------------- */ +/** + * Callback for stat VFS-function. + * + * @param vpath path to file or directory + * @param buf buffer for store stat-info + * @return 0 if sucess, negative value otherwise + */ + +static int +smbfs_cb_stat (const vfs_path_t * vpath, struct stat *buf) +{ + int rc; + GError *error = NULL; + + rc = smbfs_stat (vpath, buf, &error); + vfs_show_gerror (&error); + return rc; +} + /* --------------------------------------------------------------------------------------------- */ /*** public functions ****************************************************************************/ /* --------------------------------------------------------------------------------------------- */ @@ -103,6 +292,35 @@ smbfs_init_class_callbacks (void) { smbfs_class.init = smbfs_cb_init; smbfs_class.done = smbfs_cb_done; + + smbfs_class.fill_names = smbfs_cb_fill_names; + + smbfs_class.opendir = smbfs_cb_opendir; + smbfs_class.readdir = smbfs_cb_readdir; + smbfs_class.closedir = smbfs_cb_closedir; + smbfs_class.mkdir = smbfs_cb_mkdir; + smbfs_class.rmdir = smbfs_cb_rmdir; + + smbfs_class.stat = smbfs_cb_stat; + smbfs_class.lstat = smbfs_cb_lstat; + /* + smbfs_class.fstat = smbfs_cb_fstat; + smbfs_class.symlink = smbfs_cb_symlink; + smbfs_class.link = smbfs_cb_link; + smbfs_class.utime = smbfs_cb_utime; + smbfs_class.mknod = smbfs_cb_mknod; + smbfs_class.chown = smbfs_cb_chown; + smbfs_class.chmod = smbfs_cb_chmod; + + smbfs_class.open = smbfs_cb_open; + smbfs_class.read = smbfs_cb_read; + smbfs_class.write = smbfs_cb_write; + smbfs_class.close = smbfs_cb_close; + smbfs_class.lseek = smbfs_cb_lseek; + smbfs_class.unlink = smbfs_cb_unlink; + smbfs_class.rename = smbfs_cb_rename; + smbfs_class.ferrno = smbfs_cb_errno; + */ } /* --------------------------------------------------------------------------------------------- */ diff --git a/src/vfs/smbfs/vfs_subclass.c b/src/vfs/smbfs/vfs_subclass.c index 9e17cdc23..e3760c583 100644 --- a/src/vfs/smbfs/vfs_subclass.c +++ b/src/vfs/smbfs/vfs_subclass.c @@ -24,8 +24,10 @@ */ #include +#include #include "lib/global.h" +#include "lib/vfs/utilvfs.h" #include "internal.h" @@ -41,6 +43,104 @@ struct vfs_s_subclass smbfs_subclass; /*** file scope functions ************************************************************************/ /* --------------------------------------------------------------------------------------------- */ +/** + * Callback for checking if connection is equal to existing connection. + * + * @param vpath_element path element with connetion data + * @param super data with exists connection + * @param vpath unused + * @param cookie unused + * @return TRUE if connections is equal, FALSE otherwise + */ + +static gboolean +smbfs_cb_is_equal_connection (const vfs_path_element_t * vpath_element, struct vfs_s_super *super, + const vfs_path_t * vpath, void *cookie) +{ + gboolean result = TRUE; + char *url1, *url2; + + (void) vpath; + (void) cookie; + + url1 = smbfs_make_url (vpath_element, FALSE); + url2 = smbfs_make_url (super->path_element, FALSE); + result = (strcmp (url1, url2) == 0); + g_free (url2); + g_free (url1); + + return result; +} + +/* --------------------------------------------------------------------------------------------- */ +/** + * Callback for opening new connection. + * + * @param super connection data + * @param vpath unused + * @param vpath_element path element with connetion data + * @return 0 if success, -1 otherwise + */ + +static int +smbfs_cb_open_connection (struct vfs_s_super *super, + const vfs_path_t * vpath, const vfs_path_element_t * vpath_element) +{ + smbfs_super_data_t *smbfs_super_data; + + (void) vpath; + + smbfs_super_data = g_new0 (smbfs_super_data_t, 1); + + super->data = (void *) smbfs_super_data; + + super->path_element = vfs_path_element_clone (vpath_element); + + super->name = g_strdup (PATH_SEP_STR); + super->root = + vfs_s_new_inode (vpath_element->class, super, + vfs_s_default_stat (vpath_element->class, S_IFDIR | 0755)); + + return 0; +} + +/* --------------------------------------------------------------------------------------------- */ +/** + * Callback for closing connection. + * + * @param me unused + * @param super connection data + */ + +static void +smbfs_cb_close_connection (struct vfs_class *me, struct vfs_s_super *super) +{ + GError *error = NULL; + + (void) me; + vfs_show_gerror (&error); + g_free (super->data); +} + +/* --------------------------------------------------------------------------------------------- */ +/** + * Callback for getting directory content. + * + * @param me unused + * @param dir unused + * @param remote_path unused + * @return always 0 + */ + +static int +smbfs_cb_dir_load (struct vfs_class *me, struct vfs_s_inode *dir, char *remote_path) +{ + (void) me; + (void) dir; + (void) remote_path; + + return 0; +} /* --------------------------------------------------------------------------------------------- */ /*** public functions ****************************************************************************/ @@ -66,7 +166,10 @@ smbfs_init_subclass (void) void smbfs_init_subclass_callbacks (void) { - + smbfs_subclass.archive_same = smbfs_cb_is_equal_connection; + smbfs_subclass.open_archive = smbfs_cb_open_connection; + smbfs_subclass.free_archive = smbfs_cb_close_connection; + smbfs_subclass.dir_load = smbfs_cb_dir_load; } /* --------------------------------------------------------------------------------------------- */ diff --git a/tests/lib/vfs/vfs_split.c b/tests/lib/vfs/vfs_split.c index 549d6dbb7..e55eb2b7a 100644 --- a/tests/lib/vfs/vfs_split.c +++ b/tests/lib/vfs/vfs_split.c @@ -168,6 +168,20 @@ static const struct test_vfs_split_ds "test2:", &vfs_test_ops2 }, + { /* 11. split with empty path */ + "#test2:/", + "", + "", + "test2:", + &vfs_test_ops2 + }, + { /* 12. split with single shash path */ + "#test2://", + "", + "/", + "test2:", + &vfs_test_ops2 + }, }; /* *INDENT-ON* */ diff --git a/tests/src/vfs/Makefile.am b/tests/src/vfs/Makefile.am index 9576574ea..c32345ede 100644 --- a/tests/src/vfs/Makefile.am +++ b/tests/src/vfs/Makefile.am @@ -1 +1,5 @@ -SUBDIRS = smbfs +SUBDIRS = . + +if ENABLE_VFS_SMB +SUBDIRS += smbfs +endif diff --git a/tests/src/vfs/smbfs/Makefile.am b/tests/src/vfs/smbfs/Makefile.am index 8b1378917..00ed0d368 100644 --- a/tests/src/vfs/smbfs/Makefile.am +++ b/tests/src/vfs/smbfs/Makefile.am @@ -1 +1,40 @@ +SUBDIRS = . it +EXTRA_DIST = samba.stories + +AM_CPPFLAGS = \ + $(GLIB_CFLAGS) \ + -I$(top_srcdir) \ + -I$(top_srcdir)/lib/vfs \ + @CHECK_CFLAGS@ + +AM_LDFLAGS = @TESTS_LDFLAGS@ + +LIBS=@CHECK_LIBS@ \ + $(top_builddir)/src/libinternal.la \ + $(top_builddir)/lib/libmc.la + +TESTS = \ + dir__smbfs_opendir \ + dir__smbfs_readdir \ + internal__smbfs_make_url \ + internal__smbfs_strerror \ + stat__smbfs_lstat + +check_PROGRAMS = $(TESTS) + +dir__smbfs_opendir_SOURCES = \ + dir__smbfs_opendir.c + +dir__smbfs_readdir_SOURCES = \ + dir__smbfs_readdir.c + + +dir__smbfs_strerror_SOURCES = \ + internal__smbfs_strerror.c + +internal__smbfs_make_url_SOURCES = \ + internal__smbfs_make_url.c + +stat__smbfs_lstat_SOURCES = \ + stat__smbfs_lstat.c diff --git a/tests/src/vfs/smbfs/dir__smbfs_opendir.c b/tests/src/vfs/smbfs/dir__smbfs_opendir.c new file mode 100644 index 000000000..108c306a2 --- /dev/null +++ b/tests/src/vfs/smbfs/dir__smbfs_opendir.c @@ -0,0 +1,251 @@ +/* + src/vfs/smbfs - tests for opendir function + + Copyright (C) 2013 + The Free Software Foundation, Inc. + + Written by: + Slava Zanko , 2013 + + This file is part of the Midnight Commander. + + The Midnight Commander 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 3 of the License, + or (at your option) any later version. + + The Midnight Commander is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + 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, see . + */ + +#define TEST_SUITE_NAME "/src/vfs/smbfs" + +#include "tests/mctest.h" + +#include "lib/vfs/vfs.h" +#include "lib/strutil.h" + +#include "src/vfs/local/local.h" +#include "src/vfs/smbfs/init.h" +#include "src/vfs/smbfs/internal.h" + +/* --------------------------------------------------------------------------------------------- */ + + +/* @CapturedValue */ +static char *smbc_opendir__smb_url__captured; +/* @ThenReturnValue */ +static int smbc_opendir__return_value; + +/* @Mock */ +int +smbc_opendir (const char *smb_url) +{ + smbc_opendir__smb_url__captured = g_strdup (smb_url); + + return smbc_opendir__return_value; +} + +static void +smbc_opendir__init (void) +{ + smbc_opendir__smb_url__captured = NULL; + smbc_opendir__return_value = -1; +} + +static void +smbc_opendir__deinit (void) +{ + g_free (smbc_opendir__smb_url__captured); +} + + +/* --------------------------------------------------------------------------------------------- */ + +/* @CapturedValue */ +static vfs_path_t *vfs_get_super_by_vpath__vpath__captured; +/* @CapturedValue */ +static gboolean vfs_get_super_by_vpath__is_create_new__captured; + +/* @ThenReturnValue */ +static struct vfs_s_super *vfs_get_super_by_vpath__return_value; + +/* @Mock */ +struct vfs_s_super * +vfs_get_super_by_vpath (const vfs_path_t * vpath, gboolean is_create_new) +{ + vfs_get_super_by_vpath__vpath__captured = vfs_path_clone (vpath); + vfs_get_super_by_vpath__is_create_new__captured = is_create_new; + return vfs_get_super_by_vpath__return_value; +} + +static void +vfs_get_super_by_vpath__init (void) +{ + vfs_get_super_by_vpath__vpath__captured = NULL; + vfs_get_super_by_vpath__is_create_new__captured = FALSE; + vfs_get_super_by_vpath__return_value = NULL; +} + +static void +vfs_get_super_by_vpath__deinit (void) +{ + vfs_path_free (vfs_get_super_by_vpath__vpath__captured); + g_free (vfs_get_super_by_vpath__return_value); +} + +/* --------------------------------------------------------------------------------------------- */ + +/* @Before */ +static void +setup (void) +{ + str_init_strings (NULL); + + vfs_init (); + init_localfs (); + init_smbfs (); + + vfs_setup_work_dir (); + + vfs_get_super_by_vpath__init (); + smbc_opendir__init (); +} + +/* --------------------------------------------------------------------------------------------- */ + +/* @After */ +static void +teardown (void) +{ + smbc_opendir__deinit (); + vfs_get_super_by_vpath__deinit (); + + vfs_shut (); + str_uninit_strings (); +} + +/* --------------------------------------------------------------------------------------------- */ + +/* @Test */ +/* *INDENT-OFF* */ +START_TEST (test_smbfs_open_dir_fail) +/* *INDENT-ON* */ +{ + /* given */ + void *actual_result; + GError *error = NULL; + vfs_path_t *input_vpath; + + input_vpath = vfs_path_from_str ("/smb:/someserver/path/to/file.ext"); /* wrong URL. Should be smb://... */ + + /* prepare mocked functions */ + vfs_get_super_by_vpath__return_value = g_new0 (struct vfs_s_super, 1); + smbc_opendir__return_value = -1; + + /* when */ + + actual_result = smbfs_opendir (input_vpath, &error); + + /* then */ + + /* checking mock calls */ + mctest_assert_ptr_ne (vfs_get_super_by_vpath__vpath__captured, NULL); + mctest_assert_int_eq (vfs_get_super_by_vpath__is_create_new__captured, TRUE); + mctest_assert_str_eq (vfs_path_as_str (vfs_get_super_by_vpath__vpath__captured), + vfs_path_as_str (input_vpath)); + + mctest_assert_str_eq (smbc_opendir__smb_url__captured, + "smb:////smb:/someserver/path/to/file.ext"); + + /* checking actual data */ + mctest_assert_ptr_eq (actual_result, NULL); + + /* checking error object */ + mctest_assert_ptr_ne (error, NULL); + + g_error_free (error); + vfs_path_free (input_vpath); +} +/* *INDENT-OFF* */ +END_TEST +/* *INDENT-ON* */ + +/* --------------------------------------------------------------------------------------------- */ + +/* @Test */ +/* *INDENT-OFF* */ +START_TEST (test_smbfs_open_dir_success) +/* *INDENT-ON* */ +{ + /* given */ + void *actual_result; + GError *error = NULL; + vfs_path_t *input_vpath; + + input_vpath = vfs_path_from_str ("smb://someserver/path/to/file.ext"); + + /* prepare mocked functions */ + vfs_get_super_by_vpath__return_value = g_new0 (struct vfs_s_super, 1); + smbc_opendir__return_value = 0; + + /* when */ + + actual_result = smbfs_opendir (input_vpath, &error); + + /* then */ + + /* checking mock calls */ + mctest_assert_ptr_ne (vfs_get_super_by_vpath__vpath__captured, NULL); + mctest_assert_int_eq (vfs_get_super_by_vpath__is_create_new__captured, TRUE); + mctest_assert_str_eq (vfs_path_as_str (vfs_get_super_by_vpath__vpath__captured), + vfs_path_as_str (input_vpath)); + + mctest_assert_str_eq (smbc_opendir__smb_url__captured, "smb://someserver/path/to/file.ext"); + + /* checking actual data */ + mctest_assert_ptr_ne (actual_result, NULL); + + /* checking error object */ + mctest_assert_ptr_eq (error, NULL); + + vfs_path_free (input_vpath); + g_free (actual_result); +} +/* *INDENT-OFF* */ +END_TEST +/* *INDENT-ON* */ + +/* --------------------------------------------------------------------------------------------- */ + +int +main (void) +{ + int number_failed; + + Suite *s = suite_create (TEST_SUITE_NAME); + TCase *tc_core = tcase_create ("Core"); + SRunner *sr; + + tcase_add_checked_fixture (tc_core, setup, teardown); + + /* Add new tests here: *************** */ + tcase_add_test (tc_core, test_smbfs_open_dir_fail); + tcase_add_test (tc_core, test_smbfs_open_dir_success); + /* *********************************** */ + + suite_add_tcase (s, tc_core); + sr = srunner_create (s); + srunner_set_log (sr, "smbfs_opendir.log"); + srunner_run_all (sr, CK_NORMAL); + number_failed = srunner_ntests_failed (sr); + srunner_free (sr); + return (number_failed == 0) ? 0 : 1; +} + +/* --------------------------------------------------------------------------------------------- */ diff --git a/tests/src/vfs/smbfs/dir__smbfs_readdir.c b/tests/src/vfs/smbfs/dir__smbfs_readdir.c new file mode 100644 index 000000000..3b448dcf8 --- /dev/null +++ b/tests/src/vfs/smbfs/dir__smbfs_readdir.c @@ -0,0 +1,193 @@ +/* + src/vfs/smbfs - tests for readdir function + + Copyright (C) 2013 + The Free Software Foundation, Inc. + + Written by: + Slava Zanko , 2013 + + This file is part of the Midnight Commander. + + The Midnight Commander 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 3 of the License, + or (at your option) any later version. + + The Midnight Commander is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + 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, see . + */ + +#define TEST_SUITE_NAME "/src/vfs/smbfs" + +#include "tests/mctest.h" +#include + +#include "lib/vfs/vfs.h" +#include "lib/strutil.h" + +#include "src/vfs/local/local.h" +#include "src/vfs/smbfs/init.h" +#include "src/vfs/smbfs/internal.h" + +typedef struct +{ + int handle; + smbfs_super_data_t *super_data; +} smbfs_dir_data_t; + +/* --------------------------------------------------------------------------------------------- */ + +static int smbfs_readdir__errno; + +/* @CapturedValue */ +static int smbc_readdir__handle__captured; +/* @ThenReturnValue */ +static struct smbc_dirent *smbc_readdir__return_value; + +/* @Mock */ +struct smbc_dirent * +smbc_readdir (unsigned int handle) +{ + smbc_readdir__handle__captured = handle; + errno = smbfs_readdir__errno; + + return smbc_readdir__return_value; +} + +/* --------------------------------------------------------------------------------------------- */ + +/* @Before */ +static void +setup (void) +{ + str_init_strings (NULL); + + vfs_init (); + init_localfs (); + init_smbfs (); + + vfs_setup_work_dir (); +} + +/* --------------------------------------------------------------------------------------------- */ + +/* @After */ +static void +teardown (void) +{ + vfs_shut (); + str_uninit_strings (); +} + +/* --------------------------------------------------------------------------------------------- */ + +/* @Test */ +/* *INDENT-OFF* */ +START_TEST (test_smbfs_read_dir_fail) +/* *INDENT-ON* */ +{ + /* given */ + union vfs_dirent *actual_result; + GError *error = NULL; + smbfs_dir_data_t input_smbfs_dir_data; + + input_smbfs_dir_data.handle = 12345; + + /* prepare mocked functions */ + smbc_readdir__return_value = NULL; + + /* when */ + smbfs_readdir__errno = ENODEV; + actual_result = smbfs_readdir (&input_smbfs_dir_data, &error); + + /* then */ + + /* checking mock calls */ + mctest_assert_int_eq (smbc_readdir__handle__captured, 12345); + + /* checking actual data */ + mctest_assert_ptr_eq (actual_result, NULL); + + /* checking error object */ + mctest_assert_ptr_ne (error, NULL); + + g_error_free (error); +} +/* *INDENT-OFF* */ +END_TEST +/* *INDENT-ON* */ + +/* --------------------------------------------------------------------------------------------- */ + +/* @Test */ +/* *INDENT-OFF* */ +START_TEST (test_smbfs_read_dir_success) +/* *INDENT-ON* */ +{ + /* given */ + union vfs_dirent *actual_result; + GError *error = NULL; + smbfs_dir_data_t input_smbfs_dir_data; + struct smbc_dirent return_value; + + input_smbfs_dir_data.handle = 12345; + strcpy (return_value.name, "file.ext"); + + /* prepare mocked functions */ + smbc_readdir__return_value = &return_value; + + /* when */ + + smbfs_readdir__errno = 0; + actual_result = smbfs_readdir (&input_smbfs_dir_data, &error); + + /* then */ + + /* checking mock calls */ + mctest_assert_int_eq (smbc_readdir__handle__captured, 12345); + + /* checking actual data */ + mctest_assert_ptr_ne (actual_result, NULL); + mctest_assert_str_eq (actual_result->dent.d_name, "file.ext"); + + /* checking error object */ + mctest_assert_ptr_eq (error, NULL); +} +/* *INDENT-OFF* */ +END_TEST +/* *INDENT-ON* */ + +/* --------------------------------------------------------------------------------------------- */ + +int +main (void) +{ + int number_failed; + + Suite *s = suite_create (TEST_SUITE_NAME); + TCase *tc_core = tcase_create ("Core"); + SRunner *sr; + + tcase_add_checked_fixture (tc_core, setup, teardown); + + /* Add new tests here: *************** */ + tcase_add_test (tc_core, test_smbfs_read_dir_fail); + tcase_add_test (tc_core, test_smbfs_read_dir_success); + /* *********************************** */ + + suite_add_tcase (s, tc_core); + sr = srunner_create (s); + srunner_set_log (sr, "smbfs_readdir.log"); + srunner_run_all (sr, CK_NORMAL); + number_failed = srunner_ntests_failed (sr); + srunner_free (sr); + return (number_failed == 0) ? 0 : 1; +} + +/* --------------------------------------------------------------------------------------------- */ diff --git a/tests/src/vfs/smbfs/internal__smbfs_make_url.c b/tests/src/vfs/smbfs/internal__smbfs_make_url.c new file mode 100644 index 000000000..f95beeeac --- /dev/null +++ b/tests/src/vfs/smbfs/internal__smbfs_make_url.c @@ -0,0 +1,268 @@ +/* + src/vfs/smbfs - tests for check URL making function. + + Copyright (C) 2013 + The Free Software Foundation, Inc. + + Written by: + Slava Zanko , 2013 + + This file is part of the Midnight Commander. + + The Midnight Commander 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 3 of the License, + or (at your option) any later version. + + The Midnight Commander is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + 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, see . + */ + +#define TEST_SUITE_NAME "/src/vfs/smbfs" + +#include "tests/mctest.h" + +#include "lib/vfs/vfs.h" +#include "lib/strutil.h" + +#include "src/vfs/local/local.h" +#include "src/vfs/smbfs/init.h" +#include "src/vfs/smbfs/internal.h" + +/* --------------------------------------------------------------------------------------------- */ + +/* @Before */ +static void +setup (void) +{ + str_init_strings (NULL); + + vfs_init (); + init_localfs (); + init_smbfs (); + + vfs_setup_work_dir (); +} + +/* --------------------------------------------------------------------------------------------- */ + +/* @After */ +static void +teardown (void) +{ + vfs_shut (); + str_uninit_strings (); +} + +/* --------------------------------------------------------------------------------------------- */ + +/* @DataSource("test_make_url_ds") */ +/* *INDENT-OFF* */ +static const struct test_make_url_ds +{ + const char *input_path; + gboolean input_with_path; + const char *expected_url; +} test_make_url_ds[] = +{ + { /* 0. */ + "/smb://", + TRUE, + "smb://" + }, + { /* 1. */ + "/smb://", + FALSE, + "smb://" + }, + { /* 2. */ + "/smb://MCTESTSERVER", + TRUE, + "smb://MCTESTSERVER" + }, + { /* 3. */ + "/smb://MCTESTSERVER", + FALSE, + "smb://MCTESTSERVER" + }, + { /* 4. */ + "/smb://WORKGROUP", + TRUE, + "smb://WORKGROUP" + }, + { /* 5. */ + "/smb://WORKGROUP", + FALSE, + "smb://WORKGROUP" + }, + { /* 6. */ + "/smb://WORKGROUP;smbUser@", + TRUE, + "smb://WORKGROUP;smbUser@" + }, + { /* 7. */ + "/smb://WORKGROUP;smbUser@", + FALSE, + "smb://WORKGROUP;smbUser@" + }, + { /* 8. */ + "/smb://WORKGROUP;smbUser:smbPass@", + TRUE, + "smb://WORKGROUP;smbUser:smbPass@" + }, + { /* 9. */ + "/smb://WORKGROUP;smbUser:smbPass@", + FALSE, + "smb://WORKGROUP;smbUser:smbPass@" + }, + { /* 10. */ + "smb://MCTESTSERVER/SHARE", + TRUE, + "smb://MCTESTSERVER/SHARE" + }, + { /* 11. */ + "smb://MCTESTSERVER/SHARE", + FALSE, + "smb://MCTESTSERVER/SHARE" + }, + { /* 12. */ + "smb://WORKGROUP;MCTESTSERVER/SHARE", + TRUE, + "smb://WORKGROUP;MCTESTSERVER/SHARE" + }, + { /* 13. */ + "smb://WORKGROUP;MCTESTSERVER/SHARE", + FALSE, + "smb://WORKGROUP;MCTESTSERVER/SHARE" + }, + { /* 14. */ + "smb://smbUser@MCTESTSERVER/SHARE/RESTRICTED_SHARE", + TRUE, + "smb://smbUser@MCTESTSERVER/SHARE/RESTRICTED_SHARE", + }, + { /* 15. */ + "smb://smbUser@MCTESTSERVER/SHARE/RESTRICTED_SHARE", + FALSE, + "smb://smbUser@MCTESTSERVER/SHARE", + }, + { /* 16. */ + "smb://smbUser:smbPass@MCTESTSERVER/SHARE/RESTRICTED_SHARE", + TRUE, + "smb://smbUser:smbPass@MCTESTSERVER/SHARE/RESTRICTED_SHARE" + }, + { /* 17. */ + "smb://smbUser:smbPass@MCTESTSERVER/SHARE/RESTRICTED_SHARE", + FALSE, + "smb://smbUser:smbPass@MCTESTSERVER/SHARE" + }, + { /* 18. */ + "smb://WORKGROUP;smbUser@MCTESTSERVER/SHARE/RESTRICTED_SHARE", + TRUE, + "smb://WORKGROUP;smbUser@MCTESTSERVER/SHARE/RESTRICTED_SHARE" + }, + { /* 19. */ + "smb://WORKGROUP;smbUser@MCTESTSERVER/SHARE/RESTRICTED_SHARE", + FALSE, + "smb://WORKGROUP;smbUser@MCTESTSERVER/SHARE" + }, + { /* 20. */ + "smb://WORKGROUP;smbUser:smbPass@MCTESTSERVER/SHARE/RESTRICTED_SHARE", + TRUE, + "smb://WORKGROUP;smbUser:smbPass@MCTESTSERVER/SHARE/RESTRICTED_SHARE" + }, + { /* 21. */ + "smb://WORKGROUP;smbUser:smbPass@MCTESTSERVER/SHARE/RESTRICTED_SHARE", + FALSE, + "smb://WORKGROUP;smbUser:smbPass@MCTESTSERVER/SHARE" + }, + { /* 22. */ + "smb://WORKGROUP;smbUser:smbPass@MCTESTSERVER/SHARE/RESTRICTED_SHARE/path/to/file.ext", + TRUE, + "smb://WORKGROUP;smbUser:smbPass@MCTESTSERVER/SHARE/RESTRICTED_SHARE/path/to/file.ext", + }, + { /* 23. */ + "smb://WORKGROUP;smbUser:smbPass@MCTESTSERVER/SHARE/RESTRICTED_SHARE/path/to/file.ext", + FALSE, + "smb://WORKGROUP;smbUser:smbPass@MCTESTSERVER/SHARE" + }, + { /* 24. */ + "smb://MCTESTSERVER/RESTRICTED_SHARE/path/to/file.ext", + TRUE, + "smb://MCTESTSERVER/RESTRICTED_SHARE/path/to/file.ext", + }, + { /* 25. */ + "smb://MCTESTSERVER/RESTRICTED_SHARE/path/to/file.ext", + FALSE, + "smb://MCTESTSERVER/RESTRICTED_SHARE" + }, + { /* 26. */ + "smb://[::1]/SHARE/path/to/file.ext", + TRUE, + "smb://[::1]/SHARE/path/to/file.ext", + }, + { /* 25. */ + "smb://[::1]/SHARE/path/to/file.ext", + FALSE, + "smb://[::1]/SHARE" + }, +}; +/* *INDENT-ON* */ + +/* @Test(dataSource = "test_make_url_ds") */ +/* *INDENT-OFF* */ +START_PARAMETRIZED_TEST (test_make_url, test_make_url_ds) +/* *INDENT-ON* */ +{ + /* given */ + char *url; + const vfs_path_element_t *element; + vfs_path_t *vpath; + + vpath = vfs_path_from_str (data->input_path); + element = vfs_path_get_by_index (vpath, -1); + + + /* when */ + url = smbfs_make_url (element, data->input_with_path); + + /* then */ + vfs_path_free (vpath); + mctest_assert_str_eq (url, data->expected_url); + g_free (url); +} +/* *INDENT-OFF* */ +END_PARAMETRIZED_TEST +/* *INDENT-ON* */ + +/* --------------------------------------------------------------------------------------------- */ + +int +main (void) +{ + int number_failed; + + Suite *s = suite_create (TEST_SUITE_NAME); + TCase *tc_core = tcase_create ("Core"); + SRunner *sr; + + tcase_add_checked_fixture (tc_core, setup, teardown); + + /* Add new tests here: *************** */ + mctest_add_parameterized_test (tc_core, test_make_url, test_make_url_ds); + /* *********************************** */ + + suite_add_tcase (s, tc_core); + sr = srunner_create (s); + srunner_set_log (sr, "internal__smbfs_make_url.log"); + srunner_run_all (sr, CK_NORMAL); + number_failed = srunner_ntests_failed (sr); + srunner_free (sr); + return (number_failed == 0) ? 0 : 1; +} + +/* --------------------------------------------------------------------------------------------- */ diff --git a/tests/src/vfs/smbfs/internal__smbfs_strerror.c b/tests/src/vfs/smbfs/internal__smbfs_strerror.c new file mode 100644 index 000000000..60adab131 --- /dev/null +++ b/tests/src/vfs/smbfs/internal__smbfs_strerror.c @@ -0,0 +1,169 @@ +/* + src/vfs/smbfs - tests for opendir function + + Copyright (C) 2013 + The Free Software Foundation, Inc. + + Written by: + Slava Zanko , 2013 + + This file is part of the Midnight Commander. + + The Midnight Commander 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 3 of the License, + or (at your option) any later version. + + The Midnight Commander is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + 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, see . + */ + +#define TEST_SUITE_NAME "/src/vfs/smbfs" + +#include "tests/mctest.h" +#include +#include + +#include "lib/vfs/vfs.h" +#include "lib/strutil.h" + +#include "src/vfs/smbfs/internal.h" + +/* --------------------------------------------------------------------------------------------- */ + +/* @Before */ +static void +setup (void) +{ + str_init_strings (NULL); + setlocale (LC_MESSAGES, "POSIX"); +} + +/* --------------------------------------------------------------------------------------------- */ + +/* @After */ +static void +teardown (void) +{ + str_uninit_strings (); +} + +/* --------------------------------------------------------------------------------------------- */ + +/* @DataSource("test_smbfs_strerror_transform_ds") */ +/* *INDENT-OFF* */ +static const struct test_smbfs_strerror_transform_ds +{ + const int input_errno; +} test_smbfs_strerror_transform_ds[] = +{ + { /* 0. */ + EDEADLK + }, + { /* 1. */ + ENAMETOOLONG + }, + { /* 2. */ + EAGAIN + }, +}; +/* *INDENT-ON* */ + +/* @Test(dataSource = "test_smbfs_strerror_transform_ds") */ +/* *INDENT-OFF* */ +START_PARAMETRIZED_TEST (test_smbfs_strerror_transform, test_smbfs_strerror_transform_ds) +/* *INDENT-ON* */ +{ + /* given */ + const char *actual_result; + + /* when */ + actual_result = smbfs_strerror (data->input_errno); + + /* then */ + + fail_unless (strncmp (actual_result, "smbfs: ", 7) == 0, + "actual_result(%s) pointer should be started with the 'smbfs: ' string\n", + actual_result); +} +/* *INDENT-OFF* */ +END_PARAMETRIZED_TEST +/* *INDENT-ON* */ + +/* --------------------------------------------------------------------------------------------- */ + +/* @DataSource("test_smbfs_strerror_ds") */ +/* *INDENT-OFF* */ +static const struct test_smbfs_strerror_ds +{ + const int input_errno; + const char *expected_result; +} test_smbfs_strerror_ds[] = +{ + { /* 0. */ + EINVAL, + "smbfs: an incorrect form of file/URL was passed" + }, + { /* 1. */ + EPERM, + "smbfs: the workgroup or server could not be found" + }, + { /* 2. */ + ENODEV, + "smbfs: the workgroup or server could not be found" + }, +}; +/* *INDENT-ON* */ + +/* @Test(dataSource = "test_smbfs_strerror_ds") */ +/* *INDENT-OFF* */ +START_PARAMETRIZED_TEST (test_smbfs_strerror, test_smbfs_strerror_ds) +/* *INDENT-ON* */ +{ + /* given */ + const char *actual_result; + + /* when */ + actual_result = smbfs_strerror (data->input_errno); + + /* then */ + mctest_assert_str_eq (actual_result, data->expected_result); +} +/* *INDENT-OFF* */ +END_PARAMETRIZED_TEST +/* *INDENT-ON* */ + +/* --------------------------------------------------------------------------------------------- */ + +int +main (void) +{ + int number_failed; + + Suite *s = suite_create (TEST_SUITE_NAME); + TCase *tc_core = tcase_create ("Core"); + SRunner *sr; + + tcase_add_checked_fixture (tc_core, setup, teardown); + + /* Add new tests here: *************** */ + mctest_add_parameterized_test (tc_core, test_smbfs_strerror_transform, + test_smbfs_strerror_transform_ds); + mctest_add_parameterized_test (tc_core, test_smbfs_strerror, test_smbfs_strerror_ds); + /* *********************************** */ + + suite_add_tcase (s, tc_core); + sr = srunner_create (s); + srunner_set_log (sr, "smbfs_strerror.log"); + srunner_run_all (sr, CK_NORMAL); + number_failed = srunner_ntests_failed (sr); + srunner_free (sr); + return (number_failed == 0) ? 0 : 1; +} + +/* --------------------------------------------------------------------------------------------- */ diff --git a/tests/src/vfs/smbfs/it/Makefile.am b/tests/src/vfs/smbfs/it/Makefile.am new file mode 100644 index 000000000..a4892cc74 --- /dev/null +++ b/tests/src/vfs/smbfs/it/Makefile.am @@ -0,0 +1,33 @@ +AM_CPPFLAGS = \ + $(GLIB_CFLAGS) \ + -I$(top_srcdir) \ + -I$(top_srcdir)/lib/vfs \ + @CHECK_CFLAGS@ + +AM_LDFLAGS = @TESTS_LDFLAGS@ + +LIBS=@CHECK_LIBS@ \ + $(top_builddir)/src/libinternal.la \ + $(top_builddir)/lib/libmc.la + + +INTEGRATION_SMBFS = \ + open_dir_test \ + mkdir_rmdir_stat_test + +# run as make TESTS='$(INTEGRATION)' check +# see samba.stories(background) for getting requirements to your environment +INTEGRATION = $(INTEGRATION_SMBFS) + +noinst_PROGRAMS = $(INTEGRATION) + +TESTS = + +check_PROGRAMS = $(TESTS) + + +open_dir_test_SOURCES = \ + open_dir_test.c + +mkdir_rmdir_stat_test_SOURCES = \ + mkdir_rmdir_stat_test.c \ No newline at end of file diff --git a/tests/src/vfs/smbfs/it/mkdir_rmdir_stat_test.c b/tests/src/vfs/smbfs/it/mkdir_rmdir_stat_test.c new file mode 100644 index 000000000..80cfd2908 --- /dev/null +++ b/tests/src/vfs/smbfs/it/mkdir_rmdir_stat_test.c @@ -0,0 +1,148 @@ +/* + src/vfs/smbfs - integration tests for smbfs. + You should set up your environment as it described in samba.stories + file (in the Background section). + + Copyright (C) 2013 + The Free Software Foundation, Inc. + + Written by: + Slava Zanko , 2013 + + This file is part of the Midnight Commander. + + The Midnight Commander 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 3 of the License, + or (at your option) any later version. + + The Midnight Commander is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + 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, see . + */ + +#define TEST_SUITE_NAME "/src/vfs/smbfs/it" + +#include "tests/mctest.h" + +#include "lib/vfs/vfs.h" +#include "lib/strutil.h" + +#include "src/vfs/local/local.h" +#include "src/vfs/smbfs/init.h" + +/* --------------------------------------------------------------------------------------------- */ + +/* @Before */ +static void +setup (void) +{ + str_init_strings (NULL); + + vfs_init (); + init_localfs (); + init_smbfs (); + + vfs_setup_work_dir (); +} + +/* --------------------------------------------------------------------------------------------- */ + +/* @After */ +static void +teardown (void) +{ + vfs_shut (); + str_uninit_strings (); +} + +/* --------------------------------------------------------------------------------------------- */ + +/* @Test */ +/* *INDENT-OFF* */ +START_TEST (test_mk_rm_dir) +/* *INDENT-ON* */ +{ + /* given */ + int actual_result; + vfs_path_t *input_dir; + + input_dir = + vfs_path_from_str ("smb://smbUser:smbPass@MCTESTSERVER/SHARE/mk_rm_dir_test"); + + /* when */ + actual_result = mc_mkdir (input_dir, 0755); + + /* then */ + mc_rmdir (input_dir); + vfs_path_free (input_dir); + + mctest_assert_int_eq (actual_result, 0); +} +/* *INDENT-OFF* */ +END_TEST +/* *INDENT-ON* */ + +/* --------------------------------------------------------------------------------------------- */ + +/* @Test */ +/* *INDENT-OFF* */ +START_TEST (test_stat_dir) +/* *INDENT-ON* */ +{ + /* given */ + int actual_result; + vfs_path_t *input_dir; + struct stat actual_stat; + + input_dir = + vfs_path_from_str ("smb://smbUser:smbPass@MCTESTSERVER/SHARE/stat_dir_test"); + + mc_mkdir (input_dir, 0755); + + /* when */ + actual_result = mc_lstat (input_dir, &actual_stat); + + /* then */ + mc_rmdir (input_dir); + vfs_path_free (input_dir); + + mctest_assert_int_eq (actual_result, 0); + mctest_assert_int_eq (S_ISDIR (actual_stat.st_mode), 1); +} +/* *INDENT-OFF* */ +END_TEST +/* *INDENT-ON* */ + +/* --------------------------------------------------------------------------------------------- */ + +int +main (void) +{ + int number_failed; + + Suite *s = suite_create (TEST_SUITE_NAME); + TCase *tc_core = tcase_create ("Core"); + SRunner *sr; + + tcase_add_checked_fixture (tc_core, setup, teardown); + + /* Add new tests here: *************** */ + tcase_add_test (tc_core, test_mk_rm_dir); + tcase_add_test (tc_core, test_stat_dir); + /* *********************************** */ + + suite_add_tcase (s, tc_core); + sr = srunner_create (s); + srunner_set_log (sr, "mkdir_rmdir_stat_test.log"); + srunner_run_all (sr, CK_NORMAL); + number_failed = srunner_ntests_failed (sr); + srunner_free (sr); + return (number_failed == 0) ? 0 : 1; +} + +/* --------------------------------------------------------------------------------------------- */ diff --git a/tests/src/vfs/smbfs/it/open_dir_test.c b/tests/src/vfs/smbfs/it/open_dir_test.c new file mode 100644 index 000000000..eb92f75d8 --- /dev/null +++ b/tests/src/vfs/smbfs/it/open_dir_test.c @@ -0,0 +1,155 @@ +/* + src/vfs/smbfs - integration tests for smbfs. + You should set up your environment as it described in samba.stories + file (in the Background section). + + Copyright (C) 2013 + The Free Software Foundation, Inc. + + Written by: + Slava Zanko , 2013 + + This file is part of the Midnight Commander. + + The Midnight Commander 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 3 of the License, + or (at your option) any later version. + + The Midnight Commander is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + 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, see . + */ + +#define TEST_SUITE_NAME "/src/vfs/smbfs/it" + +#include "tests/mctest.h" + +#include "lib/vfs/vfs.h" +#include "lib/strutil.h" + +#include "src/vfs/local/local.h" +#include "src/vfs/smbfs/init.h" + +gboolean vfs_show_gerror (GError ** error); + +gboolean +vfs_show_gerror (GError ** error) +{ + if (error && *error) + fprintf (stderr, "ERROR: %s\n", (*error)->message); + return TRUE; +} + +/* --------------------------------------------------------------------------------------------- */ + +/* @Before */ +static void +setup (void) +{ + str_init_strings (NULL); + + vfs_init (); + init_localfs (); + init_smbfs (); + + vfs_setup_work_dir (); +} + +/* --------------------------------------------------------------------------------------------- */ + +/* @After */ +static void +teardown (void) +{ + vfs_shut (); + str_uninit_strings (); +} + +/* --------------------------------------------------------------------------------------------- */ + +/* @DataSource("test_open_dir_ds") */ +/* *INDENT-OFF* */ +static const struct test_open_dir_ds +{ + const char *cd_directory; +} test_open_dir_ds[] = +{ + { /* 0. */ + "smb://MCTESTSERVER" + }, + { /* 1. */ + "smb://WORKGROUP" + }, + { /* 2. */ + "smb://MCTESTSERVER/SHARE" + }, + { /* 3. */ + "smb://smbUser:smbPass@MCTESTSERVER/RESTRICTED_SHARE" + }, + { /* 4. */ + "smb://smbUser:smbPass@MCTESTSERVER/SHARE" + }, + { /* 5. */ + "smb://WORKGROUP;smbUser:smbPass@MCTESTSERVER/RESTRICTED_SHARE" + }, + { /* 6. */ + "smb://WORKGROUP;smbUser:smbPass@MCTESTSERVER/SHARE" + }, +/* TODO: investigate why an error occured while I tried to see all samba resources + { + "smb://" + }, +*/ +}; +/* *INDENT-ON* */ + +/* @Test(dataSource = "test_open_dir_ds") */ +/* *INDENT-OFF* */ +START_PARAMETRIZED_TEST (test_open_dir, test_open_dir_ds) +/* *INDENT-ON* */ +{ + /* given */ + DIR *dir_handle; + + /* when */ + dir_handle = mc_opendir (vfs_path_from_str (data->cd_directory)); + + /* then */ + mctest_assert_ptr_ne (dir_handle, NULL); +} +/* *INDENT-OFF* */ +END_PARAMETRIZED_TEST +/* *INDENT-ON* */ + +/* --------------------------------------------------------------------------------------------- */ + +int +main (void) +{ + int number_failed; + + Suite *s = suite_create (TEST_SUITE_NAME); + TCase *tc_core = tcase_create ("Core"); + SRunner *sr; + + tcase_add_checked_fixture (tc_core, setup, teardown); + + /* Add new tests here: *************** */ + mctest_add_parameterized_test (tc_core, test_open_dir, test_open_dir_ds); + /* *********************************** */ + + suite_add_tcase (s, tc_core); + sr = srunner_create (s); + srunner_set_log (sr, "open_dir_test.log"); + srunner_run_all (sr, CK_NORMAL); + number_failed = srunner_ntests_failed (sr); + srunner_free (sr); + return (number_failed == 0) ? 0 : 1; +} + +/* --------------------------------------------------------------------------------------------- */ diff --git a/tests/src/vfs/smbfs/samba.stories b/tests/src/vfs/smbfs/samba.stories index 52d88b78e..99fa79a0f 100644 --- a/tests/src/vfs/smbfs/samba.stories +++ b/tests/src/vfs/smbfs/samba.stories @@ -147,7 +147,7 @@ Then: Should be visible the content of shared resource: #------------------------------------------------------------------------------------------------------ -Scenario: 11. Copy file to the r/o share +Scenario: 11. Copy/move/create file on r/o share Given: I see a filepanels And One of panels pointed to the smb://MCTESTSERVER/SHARE/test-ro-dir When: I try to copy any file to the share @@ -155,7 +155,7 @@ Then: Should be raised an error dialog with message: Access denied #------------------------------------------------------------------------------------------------------ -Scenario: 12. Copy file to the r/w share +Scenario: 12. Copy/move/create file on r/w share Given: I see a filepanels And One of panels pointed to the smb://MCTESTSERVER/SHARE/test-dir When: I try to copy any file to the share diff --git a/tests/src/vfs/smbfs/stat__smbfs_lstat.c b/tests/src/vfs/smbfs/stat__smbfs_lstat.c new file mode 100644 index 000000000..ba88b559e --- /dev/null +++ b/tests/src/vfs/smbfs/stat__smbfs_lstat.c @@ -0,0 +1,206 @@ +/* + src/vfs/smbfs - tests for stat functions + + Copyright (C) 2013 + The Free Software Foundation, Inc. + + Written by: + Slava Zanko , 2013 + + This file is part of the Midnight Commander. + + The Midnight Commander 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 3 of the License, + or (at your option) any later version. + + The Midnight Commander is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + 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, see . + */ + +#define TEST_SUITE_NAME "/src/vfs/smbfs" + +#include "tests/mctest.h" + +#include "lib/vfs/vfs.h" +#include "lib/strutil.h" + +#include "src/vfs/local/local.h" +#include "src/vfs/smbfs/init.h" +#include "src/vfs/smbfs/internal.h" + +/* --------------------------------------------------------------------------------------------- */ + + +/* @CapturedValue */ +static char *smbc_stat__smb_url__captured; +/* @CapturedValue */ +static struct stat *smbc_stat__st__captured; +/* @ThenReturnValue */ +static int smbc_stat__return_value; + +/* @Mock */ +int +smbc_stat (const char *smb_url, struct stat *st) +{ + smbc_stat__smb_url__captured = g_strdup (smb_url); + smbc_stat__st__captured = st; + + return smbc_stat__return_value; +} + +static void +smbc_stat__init (void) +{ + smbc_stat__smb_url__captured = NULL; +} + +static void +smbc_stat__deinit (void) +{ + g_free (smbc_stat__smb_url__captured); +} + +/* --------------------------------------------------------------------------------------------- */ + +/* @Before */ +static void +setup (void) +{ + str_init_strings (NULL); + + vfs_init (); + init_localfs (); + init_smbfs (); + + vfs_setup_work_dir (); + + smbc_stat__init (); +} + +/* --------------------------------------------------------------------------------------------- */ + +/* @After */ +static void +teardown (void) +{ + smbc_stat__deinit (); + + vfs_shut (); + str_uninit_strings (); +} + +/* --------------------------------------------------------------------------------------------- */ + +/* @Test */ +/* *INDENT-OFF* */ +START_TEST (test_smbfs_stat_fail) +/* *INDENT-ON* */ +{ + /* given */ + int actual_result; + GError *error = NULL; + vfs_path_t *input_vpath; + struct stat st; + + input_vpath = vfs_path_from_str ("/smb:/someserver/path/to/file.ext"); /* wrong URL. Should be smb://... */ + + /* prepare mocked functions */ + smbc_stat__return_value = -1; + + /* when */ + + actual_result = smbfs_stat (input_vpath, &st, &error); + + /* then */ + + /* checking mock calls */ + mctest_assert_str_eq (smbc_stat__smb_url__captured, "smb:////smb:/someserver/path/to/file.ext"); + mctest_assert_ptr_eq (smbc_stat__st__captured, &st); + + /* checking actual data */ + mctest_assert_int_ne (actual_result, 0); + + /* checking error object */ + mctest_assert_ptr_ne (error, NULL); + + g_error_free (error); + vfs_path_free (input_vpath); +} +/* *INDENT-OFF* */ +END_TEST +/* *INDENT-ON* */ + +/* --------------------------------------------------------------------------------------------- */ + +/* @Test */ +/* *INDENT-OFF* */ +START_TEST (test_smbfs_stat_success) +/* *INDENT-ON* */ +{ + /* given */ + int actual_result; + GError *error = NULL; + vfs_path_t *input_vpath; + struct stat st; + + input_vpath = vfs_path_from_str ("smb://someserver/path/to/file.ext"); + + /* prepare mocked functions */ + smbc_stat__return_value = 0; + + /* when */ + + actual_result = smbfs_stat (input_vpath, &st, &error); + + /* then */ + + /* checking mock calls */ + mctest_assert_str_eq (smbc_stat__smb_url__captured, "smb://someserver/path/to/file.ext"); + mctest_assert_ptr_eq (smbc_stat__st__captured, &st); + + /* checking actual data */ + mctest_assert_int_eq (actual_result, 0); + + /* checking error object */ + mctest_assert_ptr_eq (error, NULL); + + vfs_path_free (input_vpath); +} +/* *INDENT-OFF* */ +END_TEST +/* *INDENT-ON* */ + +/* --------------------------------------------------------------------------------------------- */ + +int +main (void) +{ + int number_failed; + + Suite *s = suite_create (TEST_SUITE_NAME); + TCase *tc_core = tcase_create ("Core"); + SRunner *sr; + + tcase_add_checked_fixture (tc_core, setup, teardown); + + /* Add new tests here: *************** */ + tcase_add_test (tc_core, test_smbfs_stat_fail); + tcase_add_test (tc_core, test_smbfs_stat_success); + /* *********************************** */ + + suite_add_tcase (s, tc_core); + sr = srunner_create (s); + srunner_set_log (sr, "smbfs_opendir.log"); + srunner_run_all (sr, CK_NORMAL); + number_failed = srunner_ntests_failed (sr); + srunner_free (sr); + return (number_failed == 0) ? 0 : 1; +} + +/* --------------------------------------------------------------------------------------------- */