From: <svn...@op...> - 2005-03-21 22:47:11
|
Author: azrael Date: 2005-03-21 23:47:53 +0100 (Mon, 21 Mar 2005) New Revision: 388 Added: branches/experimental-branch/tests/mock-plugin/ branches/experimental-branch/tests/mock-plugin/Makefile.am branches/experimental-branch/tests/mock-plugin/mock_format.c branches/experimental-branch/tests/mock-plugin/mock_sync.c branches/experimental-branch/tests/mock-plugin/mock_sync.h Log: Added a new mock plugin that replaces the real file-sync plugin in the unit tests Added: branches/experimental-branch/tests/mock-plugin/Makefile.am =================================================================== --- branches/experimental-branch/tests/mock-plugin/Makefile.am 2005-03-21 22:47:00 UTC (rev 387) +++ branches/experimental-branch/tests/mock-plugin/Makefile.am 2005-03-21 22:47:53 UTC (rev 388) @@ -0,0 +1,15 @@ +plugindir=@OPENSYNC_PLUGINDIR@ +configdir=@OPENSYNC_CONFIGDIR@ +formatsdir=@OPENSYNC_FORMATSDIR@ + +INCLUDES = @PACKAGE_CFLAGS@ + +AM_CFLAGS = -Wall -Werror + +EXTRA_DIST = mock_sync.h + +noinst_LTLIBRARIES = mock_sync.la + +mock_sync_la_SOURCES = mock_sync.c +mock_sync_la_LDFLAGS = -avoid-version -export-dynamic -module +mock_sync_la_LIBADD = @PACKAGE_LIBS@ @LIBS@ @FAM_LIBS@ Added: branches/experimental-branch/tests/mock-plugin/mock_format.c =================================================================== --- branches/experimental-branch/tests/mock-plugin/mock_format.c 2005-03-21 22:47:00 UTC (rev 387) +++ branches/experimental-branch/tests/mock-plugin/mock_format.c 2005-03-21 22:47:53 UTC (rev 388) @@ -0,0 +1,162 @@ +/* + * file - A plugin for file objects for the opensync framework + * Copyright (C) 2004-2005 Armin Bauer <arm...@op...> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <opensync/opensync.h> +#include <glib.h> +#include "mock_sync.h" + +static OSyncConvCmpResult compare_file(OSyncChange *leftchange, OSyncChange *rightchange) +{ + osync_trace(TRACE_ENTRY, "%s(%p, %p)", __func__, leftchange, rightchange); + fs_fileinfo *leftfile = (fs_fileinfo *)osync_change_get_data(leftchange); + fs_fileinfo *rightfile = (fs_fileinfo *)osync_change_get_data(rightchange); + + osync_bool data_same = FALSE; + osync_bool path_same = FALSE; + + if (!strcmp(osync_change_get_uid(leftchange), osync_change_get_uid(rightchange))) + path_same = TRUE; + + osync_trace(TRACE_INTERNAL, "%i %i", leftfile->size, rightfile->size); + + if (leftfile->size == rightfile->size) { + if (leftfile->data == rightfile->data) { + data_same = TRUE; + } else { + if (!memcmp(leftfile->data, rightfile->data, leftfile->size)) + data_same = TRUE; + } + } + + if (data_same && path_same) { + osync_trace(TRACE_EXIT, "%s: Same", __func__); + return CONV_DATA_SAME; + } + if (path_same) { + osync_trace(TRACE_EXIT, "%s: Similar", __func__); + return CONV_DATA_SIMILAR; + } + osync_trace(TRACE_EXIT, "%s: Mismatch", __func__); + return CONV_DATA_MISMATCH; +} + +static osync_bool conv_file_to_plain(void *user_data, char *input, int inpsize, char **output, int *outpsize, osync_bool *free_input, OSyncError **error) +{ + osync_debug("FILE", 4, "start: %s", __func__); + fs_fileinfo *file = (fs_fileinfo *)input; + + *free_input = FALSE; + *output = file->data; + *outpsize = file->size; + return TRUE; +} + +static osync_bool conv_plain_to_file(void *user_data, char *input, int inpsize, char **output, int *outpsize, osync_bool *free_input, OSyncError **error) +{ + osync_debug("FILE", 4, "start: %s", __func__); + fs_fileinfo *file = g_malloc0(sizeof(fs_fileinfo)); + + file->data = input; + file->size = inpsize; + + *free_input = FALSE; + *output = (char *)file; + *outpsize = sizeof(file); + return TRUE; +} + +static void destroy_file(char *input, size_t inpsize) +{ + fs_fileinfo *file = (fs_fileinfo *)input; + if (inpsize != sizeof(fs_fileinfo)) { + osync_debug("FILE", 0, "destroy_file: Wrong data size: %d, but it should be %u", inpsize, sizeof(fs_fileinfo)); + return; + } + g_free(file->data); + g_free(file); +} + +static void duplicate_file(OSyncChange *change) +{ + osync_debug("FILE", 4, "start: %s", __func__); + char *newuid = g_strdup_printf ("%s-dupe", osync_change_get_uid(change)); + osync_change_set_uid(change, newuid); + g_free(newuid); +} + +static osync_bool copy_file(const char *input, int inpsize, char **output, int *outpsize) +{ + osync_debug("FILE", 4, "start: %s", __func__); + + fs_fileinfo *oldfile = (fs_fileinfo *)input; + fs_fileinfo *newfile = g_malloc0(sizeof(fs_fileinfo)); + + newfile->filestats = oldfile->filestats; + newfile->size = oldfile->size; + + if (oldfile->size) { + newfile->data = g_malloc0(oldfile->size); + memcpy(newfile->data, oldfile->data, oldfile->size); + } + + *output = (char *)newfile; + *outpsize = inpsize; + return TRUE; +} + +static void create_file(OSyncChange *change) +{ + osync_debug("FILE", 4, "start: %s", __func__); + + fs_fileinfo *newfile = g_malloc0(sizeof(fs_fileinfo)); + + char *data = osync_rand_str(g_random_int_range(1, 100)); + newfile->data = data; + newfile->size = strlen(data) + 1; + + osync_change_set_data(change, (char *)newfile, sizeof(newfile), TRUE); + if (!osync_change_get_uid(change)) + osync_change_set_uid(change, osync_rand_str(6)); +} + +static char *print_file(OSyncChange *change) +{ + osync_debug("FILE", 4, "start: %s", __func__); + fs_fileinfo *file = (fs_fileinfo *)osync_change_get_data(change); + + char *printable = g_strdup_printf ("File: %s\nSize: %i", osync_change_get_uid(change), file->size); + return printable; +} + +void get_info(OSyncEnv *env) +{ + osync_env_register_objtype(env, "data"); + osync_env_register_objformat(env, "data", "mockformat"); + osync_env_format_set_compare_func(env, "mockformat", compare_file); + osync_env_format_set_duplicate_func(env, "mockformat", duplicate_file); + osync_env_format_set_destroy_func(env, "mockformat", destroy_file); + osync_env_format_set_print_func(env, "mockformat", print_file); + osync_env_format_set_copy_func(env, "mockformat", copy_file); + osync_env_format_set_create_func(env, "mockformat", create_file); + + osync_env_format_set_create_func(env, "mockformat", create_file); + osync_env_register_converter(env, CONVERTER_DECAP, "mockformat", "plain", conv_file_to_plain); + osync_env_register_converter(env, CONVERTER_ENCAP, "plain", "mockformat", conv_plain_to_file); +} Added: branches/experimental-branch/tests/mock-plugin/mock_sync.c =================================================================== --- branches/experimental-branch/tests/mock-plugin/mock_sync.c 2005-03-21 22:47:00 UTC (rev 387) +++ branches/experimental-branch/tests/mock-plugin/mock_sync.c 2005-03-21 22:47:53 UTC (rev 388) @@ -0,0 +1,410 @@ +/* + * mock-sync - A mock-plugin for the opensync framework + * Copyright (C) 2004-2005 Armin Bauer <arm...@op...> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "mock_sync.h" + +static osync_bool mock_get_error(OSyncMember *member, const char *domain) +{ + const char *env = g_getenv(domain); + if (!env) + return FALSE; + + int num = atoi(env); + int mask = 1 << (osync_member_get_id(member) - 1); + if (num & mask) { + char *chancestr = g_strdup_printf("%s_PROB", domain); + const char *chance = g_getenv(chancestr); + g_free(chancestr); + if (!chance) + return TRUE; + int prob = atoi(chance); + if (prob >= g_random_int_range(0, 100)) + return TRUE; + } + return FALSE; +} + +static void *mock_initialize(OSyncMember *member, OSyncError **error) +{ + osync_trace(TRACE_ENTRY, "%s(%p, %p)", __func__, member, error); + + if (mock_get_error(member, "INIT_NULL")) { + osync_error_set(error, OSYNC_ERROR_EXPECTED, "Triggering INIT_NULL error"); + osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error)); + return NULL; + } + + char *configdata; + int configsize; + if (!osync_member_get_config(member, &configdata, NULL, error)) { + osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error)); + return NULL; + } + + mock_env *env = (mock_env *)configdata; + + env->member = member; + env->hashtable = osync_hashtable_new(); + + osync_trace(TRACE_EXIT, "%s: %p", __func__, env); + return (void *)env; +} + +static void mock_connect(OSyncContext *ctx) +{ + osync_trace(TRACE_ENTRY, "%s(%p)", __func__, ctx); + mock_env *env = (mock_env *)osync_context_get_plugin_data(ctx); + + if (mock_get_error(env->member, "CONNECT_ERROR")) { + osync_context_report_error(ctx, OSYNC_ERROR_EXPECTED, "Triggering CONNECT_ERROR error"); + osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, "Triggering CONNECT_ERROR error"); + return; + } + + if (mock_get_error(env->member, "CONNECT_TIMEOUT")) { + osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, "Triggering CONNECT_TIMEOUT error"); + return; + } + + OSyncError *error = NULL; + if (!osync_hashtable_load(env->hashtable, env->member, &error)) { + osync_context_report_osyncerror(ctx, &error); + osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error)); + osync_error_free(&error); + return; + } + + if (!osync_anchor_compare(env->member, "path", env->path)) + osync_member_set_slow_sync(env->member, "data", TRUE); + + GError *direrror = NULL; + + env->dir = g_dir_open(env->path, 0, &direrror); + if (direrror) { + //Unable to open directory + osync_context_report_error(ctx, OSYNC_ERROR_FILE_NOT_FOUND, "Unable to open directory %s", env->path); + g_error_free (direrror); + } else { + osync_context_report_success(ctx); + } + + osync_trace(TRACE_EXIT, "%s", __func__); +} + +static char *mock_generate_hash(mock_fileinfo *info) +{ + char *hash = g_strdup_printf("%i-%i", (int)info->filestats.st_mtime, (int)info->filestats.st_ctime); + return hash; +} + +static void mock_get_changeinfo(OSyncContext *ctx) +{ + mock_env *env = (mock_env *)osync_context_get_plugin_data(ctx); + + if (mock_get_error(env->member, "GET_CHANGES_ERROR")) { + osync_context_report_error(ctx, OSYNC_ERROR_EXPECTED, "Triggering GET_CHANGES_ERROR error"); + return; + } + if (mock_get_error(env->member, "GET_CHANGES_TIMEOUT")) + return; + if (mock_get_error(env->member, "GET_CHANGES_TIMEOUT2")) + sleep(8); + + if (osync_member_get_slow_sync(env->member, "data")) { + osync_debug("FILE-SYNC", 3, "Slow sync requested"); + osync_hashtable_set_slow_sync(env->hashtable, "data"); + } + + GDir *dir; + GError *gerror = NULL; + const char *de = NULL; + + dir = g_dir_open(env->path, 0, &gerror); + if (!dir) { + osync_trace(TRACE_EXIT_ERROR, "mock_report_dir: Unable to open directory %s: %s", path, gerror ? gerror->message : "None"); + return; + } + while ((de = g_dir_read_name(dir))) { + char *filename = g_build_filename(env->path, de, NULL); + if (g_file_test(filename, G_FILE_TEST_IS_REGULAR)) { + /* Report normal files */ + OSyncChange *change = osync_change_new(); + osync_change_set_member(change, env->member); + osync_change_set_uid(change, de); + + osync_change_set_objformat_string(change, "file"); + + mock_fileinfo *info = g_malloc0(sizeof(mock_fileinfo)); + + struct stat buf; + stat(filename, &buf); + char *hash = mock_generate_hash(&buf); + osync_change_set_hash(change, hash); + + if (mock_get_error(env->member, "ONLY_INFO")) { + osync_change_set_data(change, (char *)info, sizeof(mock_fileinfo), FALSE); + } else { + if (!osync_file_read(filename, &info->data, &info->size, &error)) { + osync_context_report_osyncerror(ctx, &error); + g_free(filename); + return; + } + + osync_change_set_data(change, (char *)file_info, sizeof(mock_fileinfo), TRUE); + } + + if (osync_hashtable_detect_change(env->hashtable, change)) { + osync_context_report_change(ctx, change); + osync_hashtable_update_hash(env->hashtable, change); + } + g_free(hash); + } + } + g_dir_close(dir); + + osync_context_report_success(ctx); +} + +static void mock_get_data(OSyncContext *ctx, OSyncChange *change) +{ + mock_env *env = (mock_env *)osync_context_get_plugin_data(ctx); + mock_fileinfo *file_info = (mock_fileinfo *)osync_change_get_data(change); + + if (mock_get_error(env->member, "GET_DATA_ERROR")) { + osync_context_report_error(ctx, OSYNC_ERROR_EXPECTED, "Triggering GET_DATA_ERROR error"); + return; + } + if (mock_get_error(env->member, "GET_DATA_TIMEOUT")) + return; + + char *filename = g_strdup_printf("%s/%s", env->path, osync_change_get_uid(change)); + OSyncError *error = NULL; + if (!osync_file_read(filename, &file_info->data, &file_info->size, &error)) { + osync_context_report_osyncerror(ctx, &error); + g_free(filename); + return; + } + + osync_change_set_data(change, (char *)file_info, sizeof(mock_fileinfo), TRUE); + g_free(filename); + + osync_context_report_success(ctx); +} + +static void mock_read(OSyncContext *ctx, OSyncChange *change) +{ + mock_env *env = (mock_env *)osync_context_get_plugin_data(ctx); + + char *filename = g_strdup_printf("%s/%s", env->path, osync_change_get_uid(change)); + + mock_fileinfo *info = g_malloc0(sizeof(mock_fileinfo)); + stat(filename, &info->filestats); + + OSyncError *error = NULL; + if (!osync_file_read(filename, &info->data, &info->size, &error)) { + osync_context_report_osyncerror(ctx, &error); + g_free(filename); + return; + } + + osync_change_set_data(change, (char *)info, sizeof(mock_fileinfo), TRUE); + + g_free(filename); + + osync_context_report_success(ctx); +} + +static osync_bool mock_access(OSyncContext *ctx, OSyncChange *change) +{ + /*TODO: Create directory for file, if it doesn't exist */ + osync_debug("FILE-SYNC", 4, "start: %s", __func__); + mock_env *env = (mock_env *)osync_context_get_plugin_data(ctx); + mock_fileinfo *file_info = (mock_fileinfo *)osync_change_get_data(change); + + char *filename = NULL; + OSyncError *error = NULL; + filename = g_strdup_printf ("%s/%s", env->path, osync_change_get_uid(change)); + + switch (osync_change_get_changetype(change)) { + case CHANGE_DELETED: + if (!remove(filename) == 0) { + osync_debug("FILE-SYNC", 0, "Unable to remove file %s", filename); + osync_context_report_error(ctx, OSYNC_ERROR_FILE_NOT_FOUND, "Unable to write"); + g_free(filename); + return FALSE; + } + break; + case CHANGE_ADDED: + if (g_file_test(filename, G_FILE_TEST_EXISTS)) { + osync_debug("FILE-SYNC", 0, "File %s already exists", filename); + osync_context_report_error(ctx, OSYNC_ERROR_EXISTS, "Entry already exists"); + g_free(filename); + return FALSE; + } + /* No break. Continue below */ + case CHANGE_MODIFIED: + //FIXME add permission and ownership for file-sync + if (!osync_file_write(filename, file_info->data, file_info->size, 0700, &error)) { + osync_debug("FILE-SYNC", 0, "Unable to write to file %s", filename); + osync_context_report_osyncerror(ctx, &error); + g_free(filename); + return FALSE; + } + stat(filename, &file_info->filestats); + osync_change_set_hash(change, mock_generate_hash(file_info)); + break; + default: + osync_debug("FILE-SYNC", 0, "Unknown change type"); + } + osync_context_report_success(ctx); + g_free(filename); + osync_debug("FILE-SYNC", 4, "end: %s", __func__); + return TRUE; +} + +static osync_bool mock_commit_change(OSyncContext *ctx, OSyncChange *change) +{ + osync_debug("FILE-SYNC", 4, "start: %s", __func__); + osync_debug("FILE-SYNC", 3, "Writing change %s with changetype %i", osync_change_get_uid(change), osync_change_get_changetype(change)); + mock_env *env = (mock_env *)osync_context_get_plugin_data(ctx); + + if (mock_get_error(env->member, "COMMIT_ERROR")) { + osync_context_report_error(ctx, OSYNC_ERROR_EXPECTED, "Triggering COMMIT_ERROR error"); + return FALSE; + } + if (mock_get_error(env->member, "COMMIT_TIMEOUT")) + return FALSE; + + if (!mock_access(ctx, change)) + return FALSE; + + osync_hashtable_update_hash(env->hashtable, change); + osync_debug("FILE-SYNC", 4, "end: %s", __func__); + return TRUE; +} + +static void mock_sync_done(OSyncContext *ctx) +{ + osync_debug("FILE-SYNC", 3, "start: %s", __func__); + mock_env *env = (mock_env *)osync_context_get_plugin_data(ctx); + + if (mock_get_error(env->member, "SYNC_DONE_ERROR")) { + osync_context_report_error(ctx, OSYNC_ERROR_EXPECTED, "Triggering SYNC_DONE_ERROR error"); + return; + } + if (mock_get_error(env->member, "SYNC_DONE_TIMEOUT")) + return; + + osync_anchor_update(env->member, "path", env->path); + osync_context_report_success(ctx); + osync_debug("FILE-SYNC", 3, "end: %s", __func__); +} + +static void mock_disconnect(OSyncContext *ctx) +{ + osync_debug("FILE-SYNC", 3, "start: %s", __func__); + mock_env *env = (mock_env *)osync_context_get_plugin_data(ctx); + + if (mock_get_error(env->member, "DISCONNECT_ERROR")) { + osync_context_report_error(ctx, OSYNC_ERROR_EXPECTED, "Triggering DISCONNECT_ERROR error"); + return; + } + if (mock_get_error(env->member, "DISCONNECT_TIMEOUT")) + return; + + g_dir_close(env->dir); + osync_hashtable_close(env->hashtable); + osync_context_report_success(ctx); + osync_debug("FILE-SYNC", 3, "end: %s", __func__); +} + +static void mock_finalize(void *data) +{ + osync_debug("FILE-SYNC", 3, "start: %s", __func__); + mock_env *env = (mock_env *)data; + osync_hashtable_free(env->hashtable); + + g_free(env->path); + g_free(env); +} + +static osync_bool mock_is_available(OSyncError **error) +{ + if (g_getenv("IS_NOT_AVAILABLE")) { + osync_error_set(error, OSYNC_ERROR_GENERIC, "file-sync plugin is not available"); + return FALSE; + } + return TRUE; +} + +static void mock_batch_commit(void *data, OSyncContext **contexts, OSyncChange **changes) +{ + mock_env *env = (mock_env *)data; + osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, env, contexts, changes); + osync_trace(TRACE_EXIT, "%s", __func__); +} + +static void mock_committed_all(void *data) +{ + mock_env *env = (mock_env *)data; + osync_trace(TRACE_ENTRY, "%s(%p)", __func__, env); + osync_trace(TRACE_EXIT, "%s", __func__); +} + +void get_info(OSyncPluginInfo *info) +{ + info->name = "mock-sync"; + info->longname = "Mock Plugin"; + info->description = "Mock Plugin"; + info->version = 1; + + info->functions.initialize = mock_initialize; + info->functions.connect = mock_connect; + info->functions.sync_done = mock_sync_done; + info->functions.disconnect = mock_disconnect; + info->functions.finalize = mock_finalize; + info->functions.get_changeinfo = mock_get_changeinfo; + info->functions.get_data = mock_get_data; + + osync_plugin_accept_objtype(info, "data"); + osync_plugin_accept_objformat(info, "data", "mockformat", NULL); + + osync_plugin_set_access_objformat(info, "data", "mockformat", mock_access); + osync_plugin_set_read_objformat(info, "data", "mockformat", mock_read); + + //Lets reduce the timeouts a bit so the checks work faster + info->timeouts.disconnect_timeout = 5; + info->timeouts.connect_timeout = 5; + info->timeouts.sync_done_timeout = 5; + info->timeouts.get_changeinfo_timeout = 5; + info->timeouts.get_data_timeout = 5; + info->timeouts.commit_timeout = 5; + + if (g_getenv("IS_AVAILABLE")) + info->functions.is_available = mock_is_available; + + if (g_getenv("BATCH_COMMIT1")) { + osync_plugin_set_batch_commit_objformat(info, "data", "mockformat", mock_batch_commit); + } else { + osync_plugin_set_commit_objformat(info, "data", "mockformat", mock_commit_change); + if (g_getenv("BATCH_COMMIT2")) + osync_plugin_set_committed_all_objformat(info, "data", "mockformat", mock_committed_all); + } +} Added: branches/experimental-branch/tests/mock-plugin/mock_sync.h =================================================================== --- branches/experimental-branch/tests/mock-plugin/mock_sync.h 2005-03-21 22:47:00 UTC (rev 387) +++ branches/experimental-branch/tests/mock-plugin/mock_sync.h 2005-03-21 22:47:53 UTC (rev 388) @@ -0,0 +1,16 @@ +#include <opensync/opensync.h> +#include <sys/stat.h> +#include <stdio.h> +#include <glib.h> +#include <string.h> +#include <config.h> + +#include <libxml/xmlmemory.h> +#include <libxml/parser.h> + +typedef struct mockenv { + char *path; + OSyncMember *member; + GDir *dir; + OSyncHashTable *hashtable; +} filesyncinfo; |