From: <svn...@op...> - 2009-08-04 14:36:13
|
Author: bellmich Date: Tue Aug 4 16:35:52 2009 New Revision: 1225 URL: http://libsyncml.opensync.org/changeset/1225 Log: added SmlChangeItem including tests The integration into the API itself is not done until now. Added: trunk/libsyncml/data_sync_api/sml_change_item.c trunk/libsyncml/data_sync_api/sml_change_item.h trunk/libsyncml/data_sync_api/sml_change_item_internals.h trunk/tests/check_data_sync_api_change_item.c Modified: trunk/libsyncml/CMakeLists.txt trunk/tests/CMakeLists.txt Modified: trunk/libsyncml/CMakeLists.txt ============================================================================== --- trunk/libsyncml/CMakeLists.txt Sat Aug 1 17:23:46 2009 (r1224) +++ trunk/libsyncml/CMakeLists.txt Tue Aug 4 16:35:52 2009 (r1225) @@ -24,6 +24,7 @@ data_sync_api/data_sync_client.c data_sync_api/data_sync_server.c data_sync_api/sml_location.c + data_sync_api/sml_change_item.c data_sync_api/sml_map_item.c data_sync_api/transport_http_client.c data_sync_api/transport_http_server.c @@ -79,6 +80,7 @@ INSTALL( FILES data_sync_api/sml_location.h + data_sync_api/sml_change_item.h data_sync_api/sml_map_item.h data_sync_api/defines.h data_sync_api/standard.h Added: trunk/libsyncml/data_sync_api/sml_change_item.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ trunk/libsyncml/data_sync_api/sml_change_item.c Tue Aug 4 16:35:52 2009 (r1225) @@ -0,0 +1,549 @@ +/* sml_change_item.c + * + * Copyright (C) 2009 Michael Bell <mic...@op...> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#include "sml_change_item_internals.h" +#include "../sml_error_internals.h" +#include <string.h> + +G_DEFINE_TYPE (SmlChangeItem, sml_change_item, G_TYPE_OBJECT) + +enum +{ + PROP_0, + PROP_REMOTE, + PROP_LOCAL, + PROP_DATA, + PROP_PLANNED_SIZE, + PROP_CONTENT_TYPE, + PROP_MISSING_DATA +}; + +struct _SmlChangeItemPrivate +{ + SmlLocation* remote; + SmlLocation* local; + gchar* data; + guint64 planned_size; + gchar* content_type; + gboolean missing_data; +}; + +static void +sml_change_item_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_REMOTE: + g_value_set_object (value, SML_CHANGE_ITEM (object)->priv->remote); + break; + case PROP_LOCAL: + g_value_set_object (value, SML_CHANGE_ITEM (object)->priv->local); + break; + case PROP_DATA: + g_value_set_string (value, SML_CHANGE_ITEM (object)->priv->data); + break; + case PROP_PLANNED_SIZE: + g_value_set_uint64 (value, SML_CHANGE_ITEM (object)->priv->planned_size); + break; + case PROP_CONTENT_TYPE: + g_value_set_string (value, SML_CHANGE_ITEM (object)->priv->content_type); + break; + case PROP_MISSING_DATA: + g_value_set_boolean (value, SML_CHANGE_ITEM (object)->priv->missing_data); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +sml_change_item_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_REMOTE: + if (SML_CHANGE_ITEM (object)->priv->remote) + g_object_unref (SML_CHANGE_ITEM (object)->priv->remote); + SML_CHANGE_ITEM (object)->priv->remote = SML_LOCATION (value); + g_object_ref(SML_CHANGE_ITEM (object)->priv->remote); + break; + case PROP_LOCAL: + if (SML_CHANGE_ITEM (object)->priv->local) + g_object_unref (SML_CHANGE_ITEM (object)->priv->local); + SML_CHANGE_ITEM (object)->priv->local = SML_LOCATION (value); + g_object_ref(SML_CHANGE_ITEM (object)->priv->local); + break; + case PROP_DATA: + g_free (SML_CHANGE_ITEM (object)->priv->data); + SML_CHANGE_ITEM (object)->priv->data = g_strdup (g_value_get_string (value)); + break; + case PROP_PLANNED_SIZE: + SML_CHANGE_ITEM (object)->priv->planned_size = g_value_get_uint64 (value); + break; + case PROP_CONTENT_TYPE: + g_free (SML_CHANGE_ITEM (object)->priv->content_type); + SML_CHANGE_ITEM (object)->priv->content_type = g_strdup (g_value_get_string (value)); + break; + case PROP_MISSING_DATA: + SML_CHANGE_ITEM (object)->priv->missing_data = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +sml_change_item_finalize (GObject *object) +{ + SmlChangeItem *self = (SmlChangeItem *) object; + if (self->priv->remote) + g_object_unref(self->priv->remote); + if (self->priv->local) + g_object_unref(self->priv->local); + g_free(self->priv->data); + g_free(self->priv->content_type); + /* all pointers must be NULL */ + self->priv->remote = NULL; + self->priv->local = NULL; + self->priv->data = NULL; + self->priv->planned_size = 0; + self->priv->content_type = NULL; + G_OBJECT_CLASS (sml_change_item_parent_class)->finalize (object); +} + +static void +sml_change_item_class_init (SmlChangeItemClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (SmlChangeItemPrivate)); + + object_class->get_property = sml_change_item_get_property; + object_class->set_property = sml_change_item_set_property; + object_class->finalize = sml_change_item_finalize; + + /** + * SmlChangeItem:remote: + * + * The remote SmlLocation property. + */ + g_object_class_install_property (object_class, + PROP_REMOTE, + g_param_spec_object ("remote", + "remote SmlLocation", + "remote SmlLocation", + G_TYPE_OBJECT, + G_PARAM_READWRITE)); + /** + * SmlChangeItem:local: + * + * The local SmlLocation property. + */ + g_object_class_install_property (object_class, + PROP_LOCAL, + g_param_spec_object ("local", + "local SmlLocation", + "local SmlLocation", + G_TYPE_OBJECT, + G_PARAM_READWRITE)); + /** + * SmlChangeItem:data: + * + * The property. + */ + g_object_class_install_property (object_class, + PROP_DATA, + g_param_spec_string ("data", + "data", + "", + NULL, + G_PARAM_READWRITE)); + /** + * SmlChangeItem:planned_size: + * + * The property. + */ + g_object_class_install_property (object_class, + PROP_PLANNED_SIZE, + g_param_spec_uint64 ("planned_size", + "planned size", + "", + 0, + G_MAXUINT64, + 0, + G_PARAM_READWRITE)); + /** + * SmlChangeItem:content_type: + * + * The property. + */ + g_object_class_install_property (object_class, + PROP_CONTENT_TYPE, + g_param_spec_string ("content_type", + "content-type", + "", + NULL, + G_PARAM_READWRITE)); + /** + * SmlChangeItem:missing_data: + * + * The MoreData flag property. + */ + g_object_class_install_property (object_class, + PROP_MISSING_DATA, + g_param_spec_boolean ("missing_data", + "MoreData flag", + "MoreData flag", + FALSE, + G_PARAM_READWRITE)); + +} + +static void +sml_change_item_init (SmlChangeItem *self) +{ + self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, + SML_TYPE_CHANGE_ITEM, + SmlChangeItemPrivate); +} + +/** + * sml_change_item_new: + * + * Creates a new instance of #SmlChangeItem. + * + * Return value: the newly created #SmlChangeItem instance + */ +SmlChangeItem* +sml_change_item_new (void) +{ + return g_object_new (SML_TYPE_CHANGE_ITEM, NULL); +} + +/** + * sml_change_item_get_remote: + * @self: A #SmlChangeItem + * + * Gets the remote SmlLocation property. + * + * Return value: + */ +SmlLocation* +sml_change_item_get_remote (SmlChangeItem *self) +{ + g_return_val_if_fail (SML_IS_CHANGE_ITEM (self), NULL); + return self->priv->remote; +} + +/** + * sml_change_item_set_remote: + * @self: A #SmlChangeItem + * @remote: + * + * Sets the remote SmlLocation property. + */ +gboolean +sml_change_item_set_remote (SmlChangeItem *self, + SmlLocation* remote, + GError **error) +{ + sml_return_val_error_if_fail (SML_IS_CHANGE_ITEM (self), FALSE, error, SML_ERROR_GENERIC, "There must be a SmlChangeItem object."); + sml_return_val_error_if_fail (!remote || sml_location_get_uri(remote), FALSE, error, SML_ERROR_GENERIC, "The location must have an URI."); + + if (self->priv->remote) + g_object_unref (self->priv->remote); + self->priv->remote = remote; + if (remote) + g_object_ref (remote); +} + +/** + * sml_change_item_get_local: + * @self: A #SmlChangeItem + * + * Gets the local SmlLocation property. + * + * Return value: + */ +SmlLocation* +sml_change_item_get_local (SmlChangeItem *self) +{ + g_return_val_if_fail (SML_IS_CHANGE_ITEM (self), NULL); + return self->priv->local; +} + +/** + * sml_change_item_set_local: + * @self: A #SmlChangeItem + * @local: + * + * Sets the local SmlLocation property. + */ +gboolean +sml_change_item_set_local (SmlChangeItem *self, + SmlLocation* local, + GError **error) +{ + sml_return_val_error_if_fail (SML_IS_CHANGE_ITEM (self), FALSE, error, SML_ERROR_GENERIC, "There must be a SmlChangeItem object."); + sml_return_val_error_if_fail (!local || sml_location_get_uri(local), FALSE, error, SML_ERROR_GENERIC, "The location must have an URI."); + + if (self->priv->local) + g_object_unref (self->priv->local); + self->priv->local = local; + if (local) + g_object_ref (local); +} + +/** + * sml_change_item_get_data: + * @self: A #SmlChangeItem + * + * Gets the data property. + * + * Return value: + */ +G_CONST_RETURN gchar* +sml_change_item_get_data (SmlChangeItem *self) +{ + g_return_val_if_fail (SML_IS_CHANGE_ITEM (self), NULL); + return self->priv->data; +} + +/** + * sml_change_item_set_data: + * @self: A #SmlChangeItem + * @data: + * @size: + * + * Sets the data property. + */ +gboolean +sml_change_item_set_data (SmlChangeItem *self, + const gchar* data, + gsize size, + GError **error) +{ + sml_return_val_error_if_fail (SML_IS_CHANGE_ITEM (self), FALSE, error, SML_ERROR_GENERIC, "There must be a SmlChangeItem object."); + sml_return_val_error_if_fail (data != NULL, FALSE, error, SML_ERROR_GENERIC, "The data must be different from NULL."); + sml_return_val_error_if_fail (strlen(data), FALSE, error, SML_ERROR_GENERIC, "The data must not be the empty word."); + + /* if the size is not set then we copy the whole string */ + + if (!size) + size = strlen(data); + + g_free (self->priv->data); + self->priv->data = g_strndup(data, size); + + sml_return_val_error_if_fail (self->priv->data, FALSE, error, SML_ERROR_GENERIC, "Cannot copy the data - out of memory."); + + return TRUE; +} + +/** + * sml_change_item_get_planned_size: + * @self: A #SmlChangeItem + * + * Gets the planned size property. + * + * Return value: + */ +gsize +sml_change_item_get_planned_size (SmlChangeItem *self) +{ + g_return_val_if_fail (SML_IS_CHANGE_ITEM (self), 0); + return self->priv->planned_size; +} + +/** + * sml_change_item_set_planned_size: + * @self: A #SmlChangeItem + * @planned_size: + * + * Sets the planned size property. + */ +void +sml_change_item_set_planned_size (SmlChangeItem *self, + gsize planned_size) +{ + g_return_if_fail (SML_IS_CHANGE_ITEM (self)); + self->priv->planned_size = planned_size; +} + +/** + * sml_change_item_get_content_type: + * @self: A #SmlChangeItem + * + * Gets the content-type property. + * + * Return value: + */ +G_CONST_RETURN gchar* +sml_change_item_get_content_type (SmlChangeItem *self) +{ + g_return_val_if_fail (SML_IS_CHANGE_ITEM (self), NULL); + return self->priv->content_type; +} + +/** + * sml_change_item_set_content_type: + * @self: A #SmlChangeItem + * @content_type: + * + * Sets the content-type property. + */ +gboolean +sml_change_item_set_content_type (SmlChangeItem *self, + const gchar* content_type, + GError **error) +{ + sml_return_val_error_if_fail (SML_IS_CHANGE_ITEM (self), FALSE, error, SML_ERROR_GENERIC, "There must be a SmlChangeItem object."); + sml_return_val_error_if_fail (content_type != NULL, FALSE, error, SML_ERROR_GENERIC, "The content-type must be different from NULL."); + sml_return_val_error_if_fail (strlen(content_type), FALSE, error, SML_ERROR_GENERIC, "The content-type must be different from the empty word."); + + g_free (self->priv->content_type); + self->priv->content_type = g_strdup (content_type); + + sml_return_val_error_if_fail (self->priv->content_type, FALSE, error, SML_ERROR_GENERIC, "Cannot copy the content-type - out of memory."); + + return TRUE; +} + +/** + * sml_change_item_get_missing_data: + * @self: A #SmlChangeItem + * + * Gets the MoreData flag property. + * + * Return value: + */ +gboolean +sml_change_item_get_missing_data (SmlChangeItem *self) +{ + g_return_val_if_fail (SML_IS_CHANGE_ITEM (self), FALSE); + return self->priv->missing_data; +} + +/** + * sml_change_item_set_missing_data: + * @self: A #SmlChangeItem + * @missing_data: + * + * Sets the MoreData flag property. + */ +void +sml_change_item_set_missing_data (SmlChangeItem *self, + gboolean missing_data) +{ + g_return_if_fail (SML_IS_CHANGE_ITEM (self)); + self->priv->missing_data = missing_data; +} + +/** + * sml_change_item_get_fragment: + * @self: A #SmlChangeItem + * + * + */ +SmlChangeItem* +sml_change_item_get_fragment (SmlChangeItem *self, + gsize start, + gsize max_size, + GError **error) +{ + sml_return_val_error_if_fail (SML_IS_CHANGE_ITEM (self), NULL, error, SML_ERROR_GENERIC, "There must be a SmlChangeItem object."); + sml_return_val_error_if_fail (self->priv->data, NULL, error, SML_ERROR_GENERIC, "There must be some data."); + sml_return_val_error_if_fail (max_size, NULL, error, SML_ERROR_GENERIC, "There is no maximum size set."); + + SmlChangeItem *frag = sml_change_item_new(); + sml_return_val_error_if_fail (frag, NULL, error, SML_ERROR_GENERIC, "Cannot create new instance of SmlChangeItem - out of memory."); + + if (start == 0 && max_size < strlen(self->priv->data)) + sml_change_item_set_planned_size(frag, strlen(self->priv->data)); + + if (!sml_change_item_set_data(frag, self->priv->data + start, max_size, error)) + goto error; + + if (start + max_size < strlen(self->priv->data)) + sml_change_item_set_missing_data(frag, TRUE); + else + sml_change_item_set_missing_data(frag, FALSE); + + if (sml_change_item_get_remote(self) != NULL && + !sml_change_item_set_remote(frag, sml_change_item_get_remote(self), error)) + goto error; + if (sml_change_item_get_local(self) != NULL && + !sml_change_item_set_local(frag, sml_change_item_get_local(self), error)) + goto error; + + if (sml_change_item_get_content_type(self) != NULL && + !sml_change_item_set_content_type(frag, sml_change_item_get_content_type(self), error)) + goto error; + + return frag; +error: + if (frag) + g_object_unref(frag); + return NULL; +} + +/** + * sml_change_item_attach_fragment: + * @self: A #SmlChangeItem + * + * + */ +gboolean +sml_change_item_attach_fragment (SmlChangeItem *self, + SmlChangeItem *frag, + GError **error) +{ + sml_return_val_error_if_fail (SML_IS_CHANGE_ITEM (self), FALSE, error, SML_ERROR_GENERIC, "There must be a SmlChangeItem object."); + sml_return_val_error_if_fail (SML_IS_CHANGE_ITEM (frag), FALSE, error, SML_ERROR_GENERIC, "There must be a fragmentation object."); + sml_return_val_error_if_fail (frag->priv->data, FALSE, error, SML_ERROR_GENERIC, "The fragment does not contain any data."); + sml_return_val_error_if_fail (strlen(frag->priv->data), FALSE, error, SML_ERROR_GENERIC, "The fragment does only contain an empty string."); + sml_return_val_error_if_fail ((!self->priv->content_type && !frag->priv->content_type) || + (self->priv->content_type && frag->priv->content_type && + strcmp(self->priv->content_type, frag->priv->content_type) == 0), + FALSE, error, SML_ERROR_GENERIC, "The content-types do not match."); + sml_return_val_error_if_fail (strlen(self->priv->data) < self->priv->planned_size, FALSE, error, SML_ERROR_GENERIC, "The data is already complete."); + sml_return_val_error_if_fail (strlen(self->priv->data)+strlen(frag->priv->data) <= self->priv->planned_size, + FALSE, error, SML_ERROR_GENERIC, "The fragment is too large."); + + gchar *complete = NULL; + if (self->priv->data) + complete = g_strconcat(self->priv->data, frag->priv->data, NULL); + else + complete = g_strdup(frag->priv->data); + sml_return_val_error_if_fail (complete, FALSE, error, SML_ERROR_GENERIC, "Cannot copy the fragment - out of memory."); + + g_free(self->priv->data); + self->priv->data = complete; + + if (self->priv->planned_size && self->priv->planned_size == strlen(self->priv->data)) + self->priv->missing_data = FALSE; + + return TRUE; +} + Added: trunk/libsyncml/data_sync_api/sml_change_item.h ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ trunk/libsyncml/data_sync_api/sml_change_item.h Tue Aug 4 16:35:52 2009 (r1225) @@ -0,0 +1,64 @@ +/* sml_change_item.h + * + * Copyright (C) 2009 Michael Bell <mic...@op...> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#ifndef __SML_CHANGE_ITEM_H__ +#define __SML_CHANGE_ITEM_H__ + +#include <glib-object.h> +#include <libsyncml/data_sync_api/sml_location.h> + +G_BEGIN_DECLS + +#define SML_TYPE_CHANGE_ITEM (sml_change_item_get_type()) +#define SML_CHANGE_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SML_TYPE_CHANGE_ITEM, SmlChangeItem)) +#define SML_CHANGE_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SML_TYPE_CHANGE_ITEM, SmlChangeItemClass)) +#define SML_IS_CHANGE_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SML_TYPE_CHANGE_ITEM)) +#define SML_IS_CHANGE_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SML_TYPE_CHANGE_ITEM)) +#define SML_CHANGE_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SML_TYPE_CHANGE_ITEM, SmlChangeItemClass)) + +typedef struct _SmlChangeItem SmlChangeItem; +typedef struct _SmlChangeItemClass SmlChangeItemClass; +typedef struct _SmlChangeItemPrivate SmlChangeItemPrivate; + +struct _SmlChangeItem +{ + GObject parent; + + /*< private >*/ + SmlChangeItemPrivate *priv; +}; + +struct _SmlChangeItemClass +{ + GObjectClass parent_class; +}; + +GType sml_change_item_get_type (void); +SmlChangeItem* sml_change_item_new (void); +SmlLocation* sml_change_item_get_remote (SmlChangeItem *self); +gboolean sml_change_item_set_remote (SmlChangeItem *self, SmlLocation* remote, GError **error); +SmlLocation* sml_change_item_get_local (SmlChangeItem *self); +gboolean sml_change_item_set_local (SmlChangeItem *self, SmlLocation* local, GError **error); +G_CONST_RETURN gchar* sml_change_item_get_data (SmlChangeItem *self); +gboolean sml_change_item_set_data (SmlChangeItem *self, const gchar *data, gsize size, GError **error); + +G_END_DECLS + +#endif /* __SML_CHANGE_ITEM_H__ */ Added: trunk/libsyncml/data_sync_api/sml_change_item_internals.h ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ trunk/libsyncml/data_sync_api/sml_change_item_internals.h Tue Aug 4 16:35:52 2009 (r1225) @@ -0,0 +1,40 @@ +/* sml_change_item_internals.h + * + * Copyright (C) 2009 Michael Bell <mic...@op...> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#ifndef __SML_CHANGE_ITEM_INTERNALS_H__ +#define __SML_CHANGE_ITEM_INTERNALS_H__ + +#include <glib-object.h> +#include <libsyncml/data_sync_api/sml_change_item.h> + +G_BEGIN_DECLS + +gsize sml_change_item_get_planned_size (SmlChangeItem *self); +void sml_change_item_set_planned_size (SmlChangeItem *self, gsize planned_size); +G_CONST_RETURN gchar* sml_change_item_get_content_type (SmlChangeItem *self); +gboolean sml_change_item_set_content_type (SmlChangeItem *self, const gchar* content_type, GError **error); +gboolean sml_change_item_get_missing_data (SmlChangeItem *self); +void sml_change_item_set_missing_data (SmlChangeItem *self, gboolean missing_data); +gboolean sml_change_item_attach_fragment (SmlChangeItem *self, SmlChangeItem *fragment, GError **error); +SmlChangeItem* sml_change_item_get_fragment (SmlChangeItem *self, gsize start, gsize max_size, GError **error); + +G_END_DECLS + +#endif /* __SML_CHANGE_ITEM_INTERNALS_H__ */ Modified: trunk/tests/CMakeLists.txt ============================================================================== --- trunk/tests/CMakeLists.txt Sat Aug 1 17:23:46 2009 (r1224) +++ trunk/tests/CMakeLists.txt Tue Aug 4 16:35:52 2009 (r1225) @@ -89,6 +89,41 @@ SML_ADD_TESTCASE( location_references ) SML_END_TEST() + SML_START_TEST( "change_item" data_sync_api_change_item check_data_sync_api_change_item.c ${TEST_TARGET_LIBRARIES} ) + SML_ADD_TESTCASE( change_item_new ) + SML_ADD_TESTCASE( change_item_set_local ) + SML_ADD_TESTCASE( change_item_set_local_null ) + SML_ADD_TESTCASE( change_item_set_local_missing_uri ) + SML_ADD_TESTCASE( change_item_get_local ) + SML_ADD_TESTCASE( change_item_set_remote ) + SML_ADD_TESTCASE( change_item_set_remote_null ) + SML_ADD_TESTCASE( change_item_set_remote_missing_uri ) + SML_ADD_TESTCASE( change_item_get_remote ) + SML_ADD_TESTCASE( change_item_set_data ) + SML_ADD_TESTCASE( change_item_set_data_with_limit ) + SML_ADD_TESTCASE( change_item_set_data_with_length ) + SML_ADD_TESTCASE( change_item_set_data_with_overflow ) + SML_ADD_TESTCASE( change_item_set_data_not_null ) + SML_ADD_TESTCASE( change_item_get_data ) + SML_ADD_TESTCASE( change_item_get_data_with_limit ) + SML_ADD_TESTCASE( change_item_get_data_with_length ) + SML_ADD_TESTCASE( change_item_get_data_with_overflow ) + SML_ADD_TESTCASE( change_item_set_planned_size ) + SML_ADD_TESTCASE( change_item_get_planned_size ) + SML_ADD_TESTCASE( change_item_set_content_type ) + SML_ADD_TESTCASE( change_item_set_content_type_not_null ) + SML_ADD_TESTCASE( change_item_get_content_type ) + SML_ADD_TESTCASE( change_item_get_fragment_missing_data ) + SML_ADD_TESTCASE( change_item_get_fragment ) + SML_ADD_TESTCASE( change_item_get_too_large_fragment ) + SML_ADD_TESTCASE( change_item_get_illegal_fragment ) + SML_ADD_TESTCASE( change_item_attach_empty_fragment ) + SML_ADD_TESTCASE( change_item_attach_fragment ) + SML_ADD_TESTCASE( change_item_attach_too_long_fragment ) + SML_ADD_TESTCASE( change_item_attach_unnecessary_fragment ) + SML_ADD_TESTCASE( change_item_references ) + SML_END_TEST() + SML_START_TEST( "map_item" data_sync_api_map_item check_data_sync_api_map_item.c ${TEST_TARGET_LIBRARIES} ) SML_ADD_TESTCASE( map_item_new ) SML_ADD_TESTCASE( map_item_set_local ) Added: trunk/tests/check_data_sync_api_change_item.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ trunk/tests/check_data_sync_api_change_item.c Tue Aug 4 16:35:52 2009 (r1225) @@ -0,0 +1,875 @@ +/* + * libsyncml - A syncml protocol implementation + * Copyright (C) 2009 Michael Bell <mic...@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 "tests/support.h" + +#include <libsyncml/data_sync_api/sml_change_item_internals.h> + +START_TEST (change_item_new) +{ + setup_testbed(NULL); + SmlChangeItem *item = sml_change_item_new(); + sml_fail_unless(item != NULL, NULL); + g_object_unref(item); +} +END_TEST + +START_TEST (change_item_set_local) +{ + setup_testbed(NULL); + + GError *error = NULL; + SmlLocation *location = sml_location_new(); + sml_fail_unless(location != NULL, NULL); + sml_fail_unless(sml_location_set_uri(location, "1234", &error), "%s", error?error->message:"No GError set."); + sml_fail_unless(error == NULL, NULL); + + SmlChangeItem *item = sml_change_item_new(); + sml_fail_unless(item != NULL, NULL); + + sml_fail_unless(sml_change_item_set_local(item, location, &error), "%s", error?error->message:"No GError set."); + sml_fail_unless(error == NULL, NULL); + + g_object_unref(location); + g_object_unref(item); +} +END_TEST + +START_TEST (change_item_set_local_null) +{ + setup_testbed(NULL); + + GError *error = NULL; + + SmlChangeItem *item = sml_change_item_new(); + sml_fail_unless(item != NULL, NULL); + + sml_fail_unless(sml_change_item_set_local(item, NULL, &error), "%s", error?error->message:"No GError set."); + sml_fail_unless(error == NULL, NULL); + + g_object_unref(item); +} +END_TEST + +START_TEST (change_item_set_local_missing_uri) +{ + setup_testbed(NULL); + + GError *error = NULL; + SmlLocation *location = sml_location_new(); + sml_fail_unless(location != NULL, NULL); + + SmlChangeItem *item = sml_change_item_new(); + sml_fail_unless(item != NULL, NULL); + + sml_fail_unless(!sml_change_item_set_local(item, location, &error), "The location must have an URI."); + sml_fail_unless(error != NULL, NULL); + + g_error_free(error); + g_object_unref(location); + g_object_unref(item); +} +END_TEST + +START_TEST (change_item_get_local) +{ + setup_testbed(NULL); + + GError *error = NULL; + SmlLocation *location = sml_location_new(); + sml_fail_unless(location != NULL, NULL); + sml_fail_unless(sml_location_set_uri(location, "1234", &error), "%s", error?error->message:"No GError set."); + sml_fail_unless(error == NULL, NULL); + + SmlChangeItem *item = sml_change_item_new(); + sml_fail_unless(item != NULL, NULL); + + sml_fail_unless(sml_change_item_get_local(item) == NULL, "The local location is not set until now."); + + sml_fail_unless(sml_change_item_set_local(item, location, &error), "%s", error?error->message:"No GError set."); + sml_fail_unless(error == NULL, NULL); + + sml_fail_unless(sml_change_item_get_local(item) != NULL, "The local location must be set now."); + sml_fail_unless(sml_change_item_get_local(item) == location, "The local location must be 1234."); + + sml_fail_unless(sml_change_item_set_local(item, NULL, &error), "%s", error?error->message:"No GError set."); + sml_fail_unless(error == NULL, NULL); + + sml_fail_unless(sml_change_item_get_local(item) == NULL, "The local location was deleted."); + + g_object_unref(location); + g_object_unref(item); +} +END_TEST + +START_TEST (change_item_set_remote) +{ + setup_testbed(NULL); + + GError *error = NULL; + SmlLocation *location = sml_location_new(); + sml_fail_unless(location != NULL, NULL); + sml_fail_unless(sml_location_set_uri(location, "1234", &error), "%s", error?error->message:"No GError set."); + sml_fail_unless(error == NULL, NULL); + + SmlChangeItem *item = sml_change_item_new(); + sml_fail_unless(item != NULL, NULL); + + sml_fail_unless(sml_change_item_set_remote(item, location, &error), "%s", error?error->message:"No GError set."); + sml_fail_unless(error == NULL, NULL); + + g_object_unref(location); + g_object_unref(item); +} +END_TEST + +START_TEST (change_item_set_remote_null) +{ + setup_testbed(NULL); + + GError *error = NULL; + + SmlChangeItem *item = sml_change_item_new(); + sml_fail_unless(item != NULL, NULL); + + sml_fail_unless(sml_change_item_set_remote(item, NULL, &error), "%s", error?error->message:"No GError set."); + sml_fail_unless(error == NULL, NULL); + + g_object_unref(item); +} +END_TEST + +START_TEST (change_item_set_remote_missing_uri) +{ + setup_testbed(NULL); + + GError *error = NULL; + SmlLocation *location = sml_location_new(); + sml_fail_unless(location != NULL, NULL); + + SmlChangeItem *item = sml_change_item_new(); + sml_fail_unless(item != NULL, NULL); + + sml_fail_unless(!sml_change_item_set_remote(item, location, &error), "The location must have an URI."); + sml_fail_unless(error != NULL, NULL); + + g_error_free(error); + g_object_unref(location); + g_object_unref(item); +} +END_TEST + +START_TEST (change_item_get_remote) +{ + setup_testbed(NULL); + + GError *error = NULL; + SmlLocation *location = sml_location_new(); + sml_fail_unless(location != NULL, NULL); + sml_fail_unless(sml_location_set_uri(location, "1234", &error), "%s", error?error->message:"No GError set."); + sml_fail_unless(error == NULL, NULL); + + SmlChangeItem *item = sml_change_item_new(); + sml_fail_unless(item != NULL, NULL); + + sml_fail_unless(sml_change_item_get_remote(item) == NULL, "The remote location is not set until now."); + + sml_fail_unless(sml_change_item_set_remote(item, location, &error), "%s", error?error->message:"No GError set."); + sml_fail_unless(error == NULL, NULL); + + sml_fail_unless(sml_change_item_get_remote(item) != NULL, "The remote location must be set now."); + sml_fail_unless(sml_change_item_get_remote(item) == location, "The remote location must be 1234."); + + sml_fail_unless(sml_change_item_set_remote(item, NULL, &error), "%s", error?error->message:"No GError set."); + sml_fail_unless(error == NULL, NULL); + + sml_fail_unless(sml_change_item_get_remote(item) == NULL, "The remote location was deleted."); + + g_object_unref(location); + g_object_unref(item); +} +END_TEST + +START_TEST (change_item_set_data) +{ + setup_testbed(NULL); + + GError *error = NULL; + + SmlChangeItem *item = sml_change_item_new(); + sml_fail_unless(item != NULL, NULL); + + const gchar* data = "I am a vCard."; + sml_fail_unless(sml_change_item_set_data(item, data, 0, &error), "%s", error?error->message:"No GError set."); + sml_fail_unless(error == NULL, NULL); + + g_object_unref(item); +} +END_TEST + +START_TEST (change_item_set_data_with_limit) +{ + setup_testbed(NULL); + + GError *error = NULL; + + SmlChangeItem *item = sml_change_item_new(); + sml_fail_unless(item != NULL, NULL); + + const gchar* data = "I am a vCard."; + sml_fail_unless(sml_change_item_set_data(item, data, strlen(data)-3, &error), "%s", error?error->message:"No GError set."); + sml_fail_unless(error == NULL, NULL); + + g_object_unref(item); +} +END_TEST + +START_TEST (change_item_set_data_with_length) +{ + setup_testbed(NULL); + + GError *error = NULL; + + SmlChangeItem *item = sml_change_item_new(); + sml_fail_unless(item != NULL, NULL); + + const gchar* data = "I am a vCard."; + sml_fail_unless(sml_change_item_set_data(item, data, strlen(data), &error), "%s", error?error->message:"No GError set."); + sml_fail_unless(error == NULL, NULL); + + g_object_unref(item); +} +END_TEST + +START_TEST (change_item_set_data_with_overflow) +{ + setup_testbed(NULL); + + GError *error = NULL; + + SmlChangeItem *item = sml_change_item_new(); + sml_fail_unless(item != NULL, NULL); + + const gchar* data = "I am a vCard."; + sml_fail_unless(sml_change_item_set_data(item, data, strlen(data)+3, &error), "%s", error?error->message:"No GError set."); + sml_fail_unless(error == NULL, NULL); + + g_object_unref(item); +} +END_TEST + +START_TEST (change_item_set_data_not_null) +{ + setup_testbed(NULL); + + GError *error = NULL; + + SmlChangeItem *item = sml_change_item_new(); + sml_fail_unless(item != NULL, NULL); + + sml_fail_unless(sml_change_item_set_local(item, NULL, &error), "%s", error?error->message:"No GError set."); + sml_fail_unless(error == NULL, NULL); + + g_object_unref(item); +} +END_TEST + +START_TEST (change_item_get_data) +{ + setup_testbed(NULL); + + GError *error = NULL; + + SmlChangeItem *item = sml_change_item_new(); + sml_fail_unless(item != NULL, NULL); + + sml_fail_unless(sml_change_item_get_data(item) == NULL, NULL); + + const gchar* data = "I am a vCard."; + sml_fail_unless(sml_change_item_set_data(item, data, 0, &error), "%s", error?error->message:"No GError set."); + sml_fail_unless(error == NULL, NULL); + + const char* result = sml_change_item_get_data(item); + sml_fail_unless(result != NULL, "The data must be present."); + sml_fail_unless(strcmp(result, data) == 0, "The data must be '%s'.", result); + + g_object_unref(item); +} +END_TEST + +START_TEST (change_item_get_data_with_limit) +{ + setup_testbed(NULL); + + GError *error = NULL; + + SmlChangeItem *item = sml_change_item_new(); + sml_fail_unless(item != NULL, NULL); + + sml_fail_unless(sml_change_item_get_data(item) == NULL, NULL); + + const gchar* data = "I am a vCard."; + sml_fail_unless(sml_change_item_set_data(item, data, strlen(data)-3, &error), "%s", error?error->message:"No GError set."); + sml_fail_unless(error == NULL, NULL); + + const char* result = sml_change_item_get_data(item); + sml_fail_unless(result != NULL, "The data must be present."); + sml_fail_unless(strlen(data)-3 == strlen(result), "The data has the wrong length."); + sml_fail_unless(strncmp(result, data, strlen(data)-3) == 0, "The data must be a part from '%s'.", result); + + g_object_unref(item); +} +END_TEST + +START_TEST (change_item_get_data_with_length) +{ + setup_testbed(NULL); + + GError *error = NULL; + + SmlChangeItem *item = sml_change_item_new(); + sml_fail_unless(item != NULL, NULL); + + sml_fail_unless(sml_change_item_get_data(item) == NULL, NULL); + + const gchar* data = "I am a vCard."; + sml_fail_unless(sml_change_item_set_data(item, data, strlen(data), &error), "%s", error?error->message:"No GError set."); + sml_fail_unless(error == NULL, NULL); + + const char* result = sml_change_item_get_data(item); + sml_fail_unless(result != NULL, "The data must be present."); + sml_fail_unless(strcmp(result, data) == 0, "The data must be '%s'.", result); + + g_object_unref(item); +} +END_TEST + +START_TEST (change_item_get_data_with_overflow) +{ + setup_testbed(NULL); + + GError *error = NULL; + + SmlChangeItem *item = sml_change_item_new(); + sml_fail_unless(item != NULL, NULL); + + sml_fail_unless(sml_change_item_get_data(item) == NULL, NULL); + + const gchar* data = "I am a vCard."; + sml_fail_unless(sml_change_item_set_data(item, data, strlen(data)+3, &error), "%s", error?error->message:"No GError set."); + sml_fail_unless(error == NULL, NULL); + + const char* result = sml_change_item_get_data(item); + sml_fail_unless(result != NULL, "The data must be present."); + sml_fail_unless(strcmp(result, data) == 0, "The data must be '%s'.", result); + + g_object_unref(item); +} +END_TEST + +START_TEST (change_item_set_planned_size) +{ + setup_testbed(NULL); + + GError *error = NULL; + + SmlChangeItem *item = sml_change_item_new(); + sml_fail_unless(item != NULL, NULL); + + sml_change_item_set_planned_size(item, 0); + sml_change_item_set_planned_size(item, 1); + sml_change_item_set_planned_size(item, 2); + sml_change_item_set_planned_size(item, 0); + sml_change_item_set_planned_size(item, 1); + sml_change_item_set_planned_size(item, 0); + sml_change_item_set_planned_size(item, 2); + sml_change_item_set_planned_size(item, 2); + sml_change_item_set_planned_size(item, 0); + + g_object_unref(item); +} +END_TEST + +START_TEST (change_item_get_planned_size) +{ + setup_testbed(NULL); + + GError *error = NULL; + + SmlChangeItem *item = sml_change_item_new(); + sml_fail_unless(item != NULL, NULL); + + sml_fail_unless(sml_change_item_get_planned_size(item) == 0, NULL); + sml_change_item_set_planned_size(item, 0); + sml_fail_unless(sml_change_item_get_planned_size(item) == 0, NULL); + sml_change_item_set_planned_size(item, 1); + sml_fail_unless(sml_change_item_get_planned_size(item) == 1, NULL); + sml_change_item_set_planned_size(item, 2); + sml_fail_unless(sml_change_item_get_planned_size(item) == 2, NULL); + sml_change_item_set_planned_size(item, 0); + sml_fail_unless(sml_change_item_get_planned_size(item) == 0, NULL); + sml_change_item_set_planned_size(item, 1); + sml_fail_unless(sml_change_item_get_planned_size(item) == 1, NULL); + sml_change_item_set_planned_size(item, 0); + sml_fail_unless(sml_change_item_get_planned_size(item) == 0, NULL); + sml_change_item_set_planned_size(item, 2); + sml_fail_unless(sml_change_item_get_planned_size(item) == 2, NULL); + sml_change_item_set_planned_size(item, 2); + sml_fail_unless(sml_change_item_get_planned_size(item) == 2, NULL); + sml_change_item_set_planned_size(item, 0); + sml_fail_unless(sml_change_item_get_planned_size(item) == 0, NULL); + + g_object_unref(item); +} +END_TEST + +START_TEST (change_item_set_content_type) +{ + setup_testbed(NULL); + + GError *error = NULL; + + SmlChangeItem *item = sml_change_item_new(); + sml_fail_unless(item != NULL, NULL); + + sml_fail_unless(sml_change_item_set_content_type(item, "text/plain", &error), "%s", error?error->message:"No GError set."); + sml_fail_unless(error == NULL, NULL); + + sml_fail_unless(sml_change_item_set_content_type(item, "text/html", &error), "%s", error?error->message:"No GError set."); + sml_fail_unless(error == NULL, NULL); + + g_object_unref(item); +} +END_TEST + +START_TEST (change_item_set_content_type_not_null) +{ + setup_testbed(NULL); + + GError *error = NULL; + + SmlChangeItem *item = sml_change_item_new(); + sml_fail_unless(item != NULL, NULL); + + sml_fail_unless(!sml_change_item_set_content_type(item, NULL, &error), NULL); + sml_fail_unless(error != NULL, NULL); + + g_error_free(error); + g_object_unref(item); +} +END_TEST + +START_TEST (change_item_get_content_type) +{ + setup_testbed(NULL); + + GError *error = NULL; + + SmlChangeItem *item = sml_change_item_new(); + sml_fail_unless(item != NULL, NULL); + + sml_fail_unless(sml_change_item_get_content_type(item) == NULL, "The default content-type is NULL."); + + sml_fail_unless(sml_change_item_set_content_type(item, "text/plain", &error), "%s", error?error->message:"No GError set."); + sml_fail_unless(error == NULL, NULL); + const char* result = sml_change_item_get_content_type(item); + sml_fail_unless(result != NULL, "The content-type is present."); + sml_fail_unless(strcmp(result, "text/plain") == 0, "The content-type must be text/plain."); + + sml_fail_unless(sml_change_item_set_content_type(item, "text/html", &error), "%s", error?error->message:"No GError set."); + sml_fail_unless(error == NULL, NULL); + result = sml_change_item_get_content_type(item); + sml_fail_unless(result != NULL, "The content-type is present."); + sml_fail_unless(strcmp(result, "text/html") == 0, "The content-type must be text/html."); + + sml_fail_unless(!sml_change_item_set_content_type(item, NULL, &error), NULL); + sml_fail_unless(error != NULL, NULL); + g_error_free(error); + error = NULL; + result = sml_change_item_get_content_type(item); + sml_fail_unless(result != NULL, "The content-type is present."); + sml_fail_unless(strcmp(result, "text/html") == 0, "The content-type must be text/html."); + + g_object_unref(item); +} +END_TEST + +START_TEST (change_item_get_fragment_missing_data) +{ + setup_testbed(NULL); + + GError *error = NULL; + + SmlChangeItem *item = sml_change_item_new(); + + sml_fail_unless(!sml_change_item_get_fragment(item, 0, 10, &error), "Fragmentation on empty items is not supported."); + sml_fail_unless(error != NULL, NULL); + + g_error_free(error); + g_object_unref(item); +} +END_TEST + +START_TEST (change_item_get_fragment) +{ + setup_testbed(NULL); + + GError *error = NULL; + + SmlChangeItem *item = sml_change_item_new(); + + const gchar* data = "1234567890abcdefghijklmnopqrstuvwxyz"; + sml_fail_unless(sml_change_item_set_data(item, data, 0, &error), "%s", error?error->message:"No GError set."); + sml_fail_unless(error == NULL, NULL); + + /* get the first chunk */ + + SmlChangeItem *frag = sml_change_item_get_fragment(item, 0, 10, &error); + sml_fail_unless(frag != NULL, "%s", error?error->message:"No GError set."); + sml_fail_unless(error == NULL, NULL); + sml_fail_unless(sml_change_item_get_local(frag) == NULL, NULL); + sml_fail_unless(sml_change_item_get_remote(frag) == NULL, NULL); + sml_fail_unless(sml_change_item_get_content_type(frag) == NULL, NULL); + sml_fail_unless(sml_change_item_get_missing_data(frag) == TRUE, NULL); + /* only the first element contains the size */ + sml_fail_unless(sml_change_item_get_planned_size(frag) == strlen(data), NULL); + sml_fail_unless(sml_change_item_get_data(frag) != NULL, NULL); + sml_fail_unless(strcmp("1234567890", sml_change_item_get_data(frag)) == 0, NULL); + g_object_unref(frag); + frag = NULL; + + /* set location and content-type */ + + SmlLocation *location = sml_location_new(); + sml_fail_unless(location != NULL, NULL); + sml_fail_unless(sml_location_set_uri(location, "1234", &error), "%s", error?error->message:"No GError set."); + sml_fail_unless(error == NULL, NULL); + + sml_fail_unless(sml_change_item_set_local(item, location, &error), "%s", error?error->message:"No GError set."); + sml_fail_unless(error == NULL, NULL); + sml_fail_unless(sml_change_item_set_remote(item, location, &error), "%s", error?error->message:"No GError set."); + sml_fail_unless(error == NULL, NULL); + sml_fail_unless(sml_change_item_set_content_type(item, "text/plain", &error), "%s", error?error->message:"No GError set."); + sml_fail_unless(error == NULL, NULL); + + /* get the next chunk with location and content-type */ + + frag = sml_change_item_get_fragment(item, 10, 10, &error); + sml_fail_unless(frag != NULL, "%s", error?error->message:"No GError set."); + sml_fail_unless(error == NULL, NULL); + sml_fail_unless(sml_change_item_get_local(frag) == location, NULL); + sml_fail_unless(sml_change_item_get_remote(frag) == location, NULL); + sml_fail_unless(sml_change_item_get_content_type(frag) != NULL, NULL); + sml_fail_unless(strcmp(sml_change_item_get_content_type(frag), "text/plain") == 0, NULL); + sml_fail_unless(sml_change_item_get_missing_data(frag) == TRUE, NULL); + sml_fail_unless(sml_change_item_get_planned_size(frag) == 0, NULL); + sml_fail_unless(sml_change_item_get_data(frag) != NULL, NULL); + sml_fail_unless(strcmp("abcdefghij", sml_change_item_get_data(frag)) == 0, NULL); + g_object_unref(frag); + + /* get last chunk */ + + frag = sml_change_item_get_fragment(item, 20, 16, &error); + sml_fail_unless(frag != NULL, "%s", error?error->message:"No GError set."); + sml_fail_unless(error == NULL, NULL); + sml_fail_unless(sml_change_item_get_local(frag) == location, NULL); + sml_fail_unless(sml_change_item_get_remote(frag) == location, NULL); + sml_fail_unless(sml_change_item_get_content_type(frag) != NULL, NULL); + sml_fail_unless(strcmp(sml_change_item_get_content_type(frag), "text/plain") == 0, NULL); + sml_fail_unless(sml_change_item_get_missing_data(frag) == FALSE, NULL); + sml_fail_unless(sml_change_item_get_planned_size(frag) == 0, NULL); + sml_fail_unless(sml_change_item_get_data(frag) != NULL, NULL); + sml_fail_unless(strcmp("klmnopqrstuvwxyz", sml_change_item_get_data(frag)) == 0, NULL); + g_object_unref(frag); + + g_object_unref(location); + g_object_unref(item); +} +END_TEST + +START_TEST (change_item_get_too_large_fragment) +{ + setup_testbed(NULL); + + GError *error = NULL; + + SmlChangeItem *item = sml_change_item_new(); + + const gchar* data = "1234567890abcdefghijklmnopqrstuvwxyz"; + sml_fail_unless(sml_change_item_set_data(item, data, 0, &error), "%s", error?error->message:"No GError set."); + sml_fail_unless(error == NULL, NULL); + + /* get the first chunk */ + + SmlChangeItem *frag = sml_change_item_get_fragment(item, 0, strlen(data)+1, &error); + sml_fail_unless(frag != NULL, "%s", error?error->message:"No GError set."); + sml_fail_unless(error == NULL, NULL); + sml_fail_unless(sml_change_item_get_local(frag) == NULL, NULL); + sml_fail_unless(sml_change_item_get_remote(frag) == NULL, NULL); + sml_fail_unless(sml_change_item_get_content_type(frag) == NULL, NULL); + sml_fail_unless(sml_change_item_get_missing_data(frag) == FALSE, NULL); + sml_fail_unless(sml_change_item_get_planned_size(frag) == 0, NULL); + sml_fail_unless(sml_change_item_get_data(frag) != NULL, NULL); + sml_fail_unless(strcmp(data, sml_change_item_get_data(frag)) == 0, NULL); + g_object_unref(frag); + frag = NULL; + + g_object_unref(item); +} +END_TEST + +START_TEST (change_item_get_illegal_fragment) +{ + setup_testbed(NULL); + + GError *error = NULL; + + SmlChangeItem *item = sml_change_item_new(); + + const gchar* data = "1234567890abcdefghijklmnopqrstuvwxyz"; + sml_fail_unless(sml_change_item_set_data(item, data, 0, &error), "%s", error?error->message:"No GError set."); + sml_fail_unless(error == NULL, NULL); + + /* get the first chunk */ + + sml_fail_unless(!sml_change_item_get_fragment(item, strlen(data), 10, &error), "The fragment start position is too large."); + sml_fail_unless(error != NULL, NULL); + g_error_free(error); + + g_object_unref(item); +} +END_TEST + +START_TEST (change_item_attach_empty_fragment) +{ + setup_testbed(NULL); + + GError *error = NULL; + + SmlChangeItem *item = sml_change_item_new(); + SmlChangeItem *frag = sml_change_item_new(); + + sml_fail_unless(!sml_change_item_attach_fragment(item, NULL, &error), "A fragment cannot be empty."); + sml_fail_unless(error != NULL, NULL); + g_error_free(error); + error = NULL; + + sml_fail_unless(!sml_change_item_attach_fragment(item, frag, &error), "A fragment cannot be empty."); + sml_fail_unless(error != NULL, NULL); + g_error_free(error); + error = NULL; + + g_object_unref(item); +} +END_TEST + +START_TEST (change_item_attach_fragment) +{ + setup_testbed(NULL); + + GError *error = NULL; + + SmlChangeItem *item = sml_change_item_new(); + + const gchar* data1 = "1234567890"; + const gchar* data2 = "abcdefghij"; + const gchar* data3 = "klmnopqrstuvwxyz"; + + sml_change_item_set_planned_size(item, strlen(data1) + strlen(data2) + strlen(data3)); + sml_fail_unless(sml_change_item_set_data(item, data1, 0, &error), "%s", error?error->message:"No GError set."); + sml_fail_unless(error == NULL, NULL); + sml_change_item_set_missing_data(item, TRUE); + + /* add the first chunk */ + + SmlChangeItem *frag = sml_change_item_new(); + sml_fail_unless(frag != NULL, "%s", error?error->message:"No GError set."); + sml_fail_unless(sml_change_item_set_data(frag, data2, 0, &error), "%s", error?error->message:"No GError set."); + sml_fail_unless(error == NULL, NULL); + sml_change_item_set_missing_data(frag, TRUE); + + sml_fail_unless(sml_change_item_attach_fragment(item, frag, &error), "%s", error?error->message:"No GError set."); + sml_fail_unless(error == NULL, NULL); + + sml_fail_unless(strlen(sml_change_item_get_data(item)) == strlen(data1) + strlen(data2), NULL); + sml_fail_unless(sml_change_item_get_missing_data(item) == TRUE, NULL); + sml_fail_unless(sml_change_item_get_local(item) == NULL, NULL); + sml_fail_unless(sml_change_item_get_remote(item) == NULL, NULL); + sml_fail_unless(sml_change_item_get_content_type(item) == NULL, NULL); + g_object_unref(frag); + frag = NULL; + + /* set location and content-type */ + + SmlLocation *location = sml_location_new(); + sml_fail_unless(location != NULL, NULL); + sml_fail_unless(sml_location_set_uri(location, "1234", &error), "%s", error?error->message:"No GError set."); + sml_fail_unless(error == NULL, NULL); + + sml_fail_unless(sml_change_item_set_local(item, location, &error), "%s", error?error->message:"No GError set."); + sml_fail_unless(error == NULL, NULL); + sml_fail_unless(sml_change_item_set_remote(item, location, &error), "%s", error?error->message:"No GError set."); + sml_fail_unless(error == NULL, NULL); + sml_fail_unless(sml_change_item_set_content_type(item, "text/plain", &error), "%s", error?error->message:"No GError set."); + sml_fail_unless(error == NULL, NULL); + + /* add the last chunk with location and content-type */ + + frag = sml_change_item_new(); + sml_fail_unless(frag != NULL, "%s", error?error->message:"No GError set."); + sml_fail_unless(sml_change_item_set_data(frag, data3, 0, &error), "%s", error?error->message:"No GError set."); + sml_fail_unless(error == NULL, NULL); + sml_change_item_set_missing_data(frag, FALSE); + sml_fail_unless(sml_change_item_set_local(frag, location, &error), "%s", error?error->message:"No GError set."); + sml_fail_unless(error == NULL, NULL); + sml_fail_unless(sml_change_item_set_remote(frag, location, &error), "%s", error?error->message:"No GError set."); + sml_fail_unless(error == NULL, NULL); + sml_fail_unless(sml_change_item_set_content_type(frag, "text/plain", &error), "%s", error?error->message:"No GError set."); + sml_fail_unless(error == NULL, NULL); + + sml_fail_unless(sml_change_item_attach_fragment(item, frag, &error), "%s", error?error->message:"No GError set."); + sml_fail_unless(error == NULL, NULL); + + sml_fail_unless(strlen(sml_change_item_get_data(item)) == strlen(data1) + strlen(data2) + strlen(data3), NULL); + sml_fail_unless(sml_change_item_get_missing_data(item) == FALSE, NULL); + sml_fail_unless(sml_change_item_get_local(item) == location, NULL); + sml_fail_unless(sml_change_item_get_remote(item) == location, NULL); + sml_fail_unless(strcmp(sml_change_item_get_content_type(item), "text/plain") == 0, NULL); + g_object_unref(frag); + frag = NULL; + + g_object_unref(location); + g_object_unref(item); +} +END_TEST + +START_TEST (change_item_attach_too_long_fragment) +{ + setup_testbed(NULL); + + GError *error = NULL; + + SmlChangeItem *item = sml_change_item_new(); + + const gchar* data1 = "1234567890"; + const gchar* data3 = "klmnopqrstuvwxyz"; + const gchar* datak = "klmnopqrstuvwxyzABC"; + + sml_change_item_set_planned_size(item, strlen(data1) + strlen(data3)); + sml_fail_unless(sml_change_item_set_data(item, data1, 0, &error), "%s", error?error->message:"No GError set."); + sml_fail_unless(error == NULL, NULL); + sml_change_item_set_missing_data(item, TRUE); + + /* add the too large chunk */ + + SmlChangeItem *frag = sml_change_item_new(); + sml_fail_unless(frag != NULL, "%s", error?error->message:"No GError set."); + sml_fail_unless(sml_change_item_set_data(frag, datak, 0, &error), "%s", error?error->message:"No GError set."); + sml_fail_unless(error == NULL, NULL); + sml_change_item_set_missing_data(frag, FALSE); + + sml_fail_unless(!sml_change_item_attach_fragment(item, frag, &error), "The fragment is larger then the planned size."); + sml_fail_unless(error != NULL, NULL); + + g_error_free(error); + g_object_unref(frag); + g_object_unref(item); +} +END_TEST + +START_TEST (change_item_attach_unnecessary_fragment) +{ + setup_testbed(NULL); + + GError *error = NULL; + + SmlChangeItem *item = sml_change_item_new(); + + const gchar* data1 = "1234567890"; + const gchar* data2 = "abcdefghij"; + const gchar* data3 = "klmnopqrstuvwxyz"; + + sml_change_item_set_planned_size(item, strlen(data1) + strlen(data2)); + sml_fail_unless(sml_change_item_set_data(item, data1, 0, &error), "%s", error?error->message:"No GError set."); + sml_fail_unless(error == NULL, NULL); + sml_change_item_set_missing_data(item, TRUE); + + /* add the first and last chunk */ + + SmlChangeItem *frag = sml_change_item_new(); + sml_fail_unless(frag != NULL, "%s", error?error->message:"No GError set."); + sml_fail_unless(sml_change_item_set_data(frag, data2, 0, &error), "%s", error?error->message:"No GError set."); + sml_fail_unless(error == NULL, NULL); + sml_change_item_set_missing_data(frag, FALSE); + + sml_fail_unless(sml_change_item_attach_fragment(item, frag, &error), "%s", error?error->message:"No GError set."); + sml_fail_unless(error == NULL, NULL); + + sml_fail_unless(strlen(sml_change_item_get_data(item)) == strlen(data1) + strlen(data2), NULL); + sml_fail_unless(sml_change_item_get_missing_data(item) == FALSE, NULL); + sml_fail_unless(sml_change_item_get_local(item) == NULL, NULL); + sml_fail_unless(sml_change_item_get_remote(item) == NULL, NULL); + sml_fail_unless(sml_change_item_get_content_type(item) == NULL, NULL); + g_object_unref(frag); + frag = NULL; + + /* add the unnecessary chunk */ + + frag = sml_change_item_new(); + sml_fail_unless(frag != NULL, "%s", error?error->message:"No GError set."); + sml_fail_unless(sml_change_item_set_data(frag, data3, 0, &error), "%s", error?error->message:"No GError set."); + sml_fail_unless(error == NULL, NULL); + sml_change_item_set_missing_data(frag, FALSE); + + sml_fail_unless(!sml_change_item_attach_fragment(item, frag, &error), "The chunk is not necessary."); + sml_fail_unless(error != NULL, NULL); + + g_error_free(error); + g_object_unref(frag); + g_object_unref(item); +} +END_TEST + +START_TEST (change_item_references) +{ + setup_testbed(NULL); + + GError *error = NULL; + + SmlChangeItem *item = sml_change_item_new(); + sml_fail_unless(item != NULL, NULL); + + sml_fail_unless(sml_change_item_set_data(item, "1234", 0, &error), "%s", error?error->message:"No GError set."); + sml_fail_unless(error == NULL, NULL); + + g_object_ref(item); + + sml_fail_unless(sml_change_item_get_data(item) != NULL, "The data was not set."); + + g_object_unref(item); + + sml_fail_unless(sml_change_item_get_data(item) != NULL, "The data is already cleaned up."); + + g_object_unref(item); +} +END_TEST + +@SML_TESTCASE_CODE@ + |