/*
 * libsyncml - A syncml protocol implementation
 * Copyright (C) 2005  Armin Bauer <armin.bauer@opensync.org>
 * Copyright (C) 2008  Michael Bell <michael.bell@opensync.org>
 *
 * 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/sml_command_internals.h>
#include <libsyncml/sml_elements_internals.h>
#include <libsyncml/data_sync_api/sml_location.h>
#include <libsyncml/data_sync_api/sml_data_sync_change_item_internals.h>
#include <libsyncml/data_sync_api/sml_data_sync_defines.h>
#include <libsyncml/sml_error_internals.h>

static SmlAssembler *start_assembler(SmlSession *session, unsigned int limit)
{
	GError *error = NULL;

	SmlAssembler *assm = smlAssemblerNew(SML_MIMETYPE_XML, limit, &error);
	sml_fail_unless(assm != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	if (!smlAssemblerStart(assm, session, &error)) {
		sml_fail_unless(error != NULL, NULL);
		smlAssemblerFree(assm);
		return NULL;
	}
	return assm;
}

START_TEST (xml_assembler_message_empty)
{
	setup_testbed(NULL);
	GError *error = NULL;
	
	SmlLocation *loc = sml_location_new();
	sml_location_set_uri(loc, "/test");
	
	/* The session type must be SML_SESSION_TYPE_CLIENT
	 * because servers of SyncML 1.1 or higher must send MaxMsgSize.
	 */
	SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, 1, 0, &error);

	g_object_unref(loc);

	SmlAssembler *assm = start_assembler(session, 0);
	sml_fail_unless(assm != NULL, NULL);
	
	char *data = NULL;
	gsize size = 0;
	sml_fail_unless(!smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL);
	sml_fail_unless(error != NULL, NULL);
	SML_ERROR_FREE(error);
	
	sml_fail_unless(smlAssemblerFlush(assm) == 1, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	sml_fail_unless(!smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL);
	sml_fail_unless(error != NULL, NULL);
	SML_ERROR_FREE(error);
	
	smlAssemblerFree(assm);
	smlSessionUnref(session);
}
END_TEST

START_TEST (xml_assembler_message_only_header)
{
	setup_testbed(NULL);
	GError *error = NULL;
	
	SmlLocation *loc = sml_location_new();
	sml_location_set_uri(loc, "/test");

	/* The session type must be SML_SESSION_TYPE_CLIENT
	 * because servers of SyncML 1.1 or higher must send MaxMsgSize.
	 */
	SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, 1, 0, &error);

	g_object_unref(loc);
	
	SmlAssembler *assm = start_assembler(session, 0);
	sml_fail_unless(assm != NULL, NULL);
	
	sml_fail_unless(smlAssemblerAddHeader(assm, session, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	char *data = NULL;
	gsize size = 0;
	sml_fail_unless(!smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL);
	sml_fail_unless(error != NULL, NULL);
	SML_ERROR_FREE(error);
	
	sml_fail_unless(smlAssemblerFlush(assm) == 1, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	sml_fail_unless(!smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL);
	sml_fail_unless(error != NULL, NULL);
	SML_ERROR_FREE(error);
	
	smlAssemblerFree(assm);
	smlSessionUnref(session);
}
END_TEST

START_TEST (xml_assembler_message_status)
{
	setup_testbed(NULL);
	GError *error = NULL;
	
	SmlLocation *loc = sml_location_new();
	sml_location_set_uri(loc, "/test");
	
	/* The session type must be SML_SESSION_TYPE_CLIENT
	 * because servers of SyncML 1.1 or higher must send MaxMsgSize.
	 */
	SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, 1, 0, &error);

	SmlAssembler *assm = start_assembler(session, 0);
	sml_fail_unless(assm != NULL, NULL);
	
	sml_fail_unless(smlAssemblerAddHeader(assm, session, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	sml_fail_unless(smlAssemblerReserveStatus(assm, 1, 1, 1, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	SmlStatus *status = smlStatusNew(SML_NO_ERROR, 1, 1, loc, loc, SML_COMMAND_TYPE_SYNC, &error);
	sml_fail_unless(status != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	g_object_unref(loc);
	
	sml_fail_unless(smlAssemblerAddStatus(assm, status, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	smlStatusUnref(status);
	
	char *data = NULL;
	gsize size = 0;
	sml_fail_unless(smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(data != NULL, NULL);
	sml_fail_unless(size != 0, NULL);
	
	g_free(data);
	
	sml_fail_unless(smlAssemblerFlush(assm) == 1, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	sml_fail_unless(!smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL);
	sml_fail_unless(error != NULL, NULL);
	SML_ERROR_FREE(error);
	
	smlAssemblerFree(assm);
	smlSessionUnref(session);
}
END_TEST

START_TEST (xml_assembler_message_cmd)
{
	setup_testbed(NULL);
	GError *error = NULL;
	
	SmlLocation *loc = sml_location_new();
	sml_location_set_uri(loc, "/test");
	
	/* The session type must be SML_SESSION_TYPE_CLIENT
	 * because servers of SyncML 1.1 or higher must send MaxMsgSize.
	 */
	SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, 1, 0, &error);

	SmlAssembler *assm = start_assembler(session, 0);
	sml_fail_unless(assm != NULL, NULL);
	
	sml_fail_unless(smlAssemblerAddHeader(assm, session, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	SmlCommand *cmd = smlCommandNewAlert(SML_ALERT_TWO_WAY, loc, loc, "next", "last", NULL, &error);
	sml_fail_unless(cmd != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	cmd->cmdID = 1;
	
	g_object_unref(loc);
	
	sml_fail_unless(smlAssemblerStartCommand(assm, NULL, cmd, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	smlCommandUnref(cmd);
	
	sml_fail_unless(smlAssemblerEndCommand(assm, NULL, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
		
	char *data = NULL;
	gsize size = 0;
	sml_fail_unless(smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(data != NULL, NULL);
	sml_fail_unless(size != 0, NULL);
	
	g_free(data);
	
	sml_fail_unless(smlAssemblerFlush(assm) == 1, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	sml_fail_unless(!smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL);
	sml_fail_unless(error != NULL, NULL);
	SML_ERROR_FREE(error);
	
	smlAssemblerFree(assm);
	smlSessionUnref(session);
}
END_TEST

START_TEST (xml_assembler_message_subcmd)
{
	setup_testbed(NULL);
	GError *error = NULL;
	
	SmlLocation *loc = sml_location_new();
	sml_location_set_uri(loc, "/test");
	
	/* The session type must be SML_SESSION_TYPE_CLIENT
	 * because servers of SyncML 1.1 or higher must send MaxMsgSize.
	 */
	SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, 1, 0, &error);

	SmlAssembler *assm = start_assembler(session, 0);
	sml_fail_unless(assm != NULL, NULL);
	
	sml_fail_unless(smlAssemblerAddHeader(assm, session, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	SmlCommand *cmd1 = smlCommandNewSync(loc, loc, 0, &error);
	sml_fail_unless(cmd1 != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	cmd1->cmdID = 1;
	
	g_object_unref(loc);
	
	sml_fail_unless(smlAssemblerStartCommand(assm, NULL, cmd1, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	SmlCommand *cmd2 = NULL;
	TEST_DATA_SYNC_CHANGE_ITEM_NEW(SML_CHANGE_ADD, "uid", "data", 5, SML_ELEMENT_TEXT_VCARD);
	cmd2 = smlCommandNewChange(TEST_DATA_SYNC_CHANGE_ITEM, &error);
	TEST_DATA_SYNC_CHANGE_ITEM_FREE();
	sml_fail_unless(cmd2 != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	cmd2->cmdID = 2;
	
	sml_fail_unless(smlAssemblerStartCommand(assm, cmd1, cmd2, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	smlCommandUnref(cmd2);
	
	sml_fail_unless(smlAssemblerEndCommand(assm, cmd1, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	smlCommandUnref(cmd1);
	
	sml_fail_unless(smlAssemblerEndCommand(assm, NULL, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	char *data = NULL;
	gsize size = 0;
	sml_fail_unless(smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(data != NULL, NULL);
	sml_fail_unless(size != 0, NULL);
	
	g_free(data);
	
	sml_fail_unless(smlAssemblerFlush(assm) == 1, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	sml_fail_unless(!smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL);
	sml_fail_unless(error != NULL, NULL);
	SML_ERROR_FREE(error);
	
	smlAssemblerFree(assm);
	smlSessionUnref(session);
}
END_TEST

START_TEST (xml_assembler_message_several_subcmd)
{
	setup_testbed(NULL);
	GError *error = NULL;
	
	SmlLocation *loc = sml_location_new();
	sml_location_set_uri(loc, "/test");
	
	/* The session type must be SML_SESSION_TYPE_CLIENT
	 * because servers of SyncML 1.1 or higher must send MaxMsgSize.
	 */
	SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, 1, 0, &error);

	SmlAssembler *assm = start_assembler(session, 0);
	sml_fail_unless(assm != NULL, NULL);
	
	sml_fail_unless(smlAssemblerAddHeader(assm, session, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	SmlCommand *cmd1 = smlCommandNewSync(loc, loc, 0, &error);
	sml_fail_unless(cmd1 != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	cmd1->cmdID = 1;
	
	sml_fail_unless(smlAssemblerStartCommand(assm, NULL, cmd1, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	SmlCommand *cmd2 = NULL;
	TEST_DATA_SYNC_CHANGE_ITEM_NEW(SML_CHANGE_ADD, "uid", "data", 5, SML_ELEMENT_TEXT_VCARD);
	cmd2 = smlCommandNewChange(TEST_DATA_SYNC_CHANGE_ITEM, &error);
	TEST_DATA_SYNC_CHANGE_ITEM_FREE();
	cmd2->cmdID = 2;
	
	sml_fail_unless(smlAssemblerStartCommand(assm, cmd1, cmd2, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	smlCommandUnref(cmd2);
	
	sml_fail_unless(smlAssemblerEndCommand(assm, cmd1, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	TEST_DATA_SYNC_CHANGE_ITEM_NEW(SML_CHANGE_ADD, "uid2", "data2", 5, SML_ELEMENT_TEXT_VCARD);
	cmd2 = smlCommandNewChange(TEST_DATA_SYNC_CHANGE_ITEM, &error);
	TEST_DATA_SYNC_CHANGE_ITEM_FREE();
	cmd2->cmdID = 3;
	
	sml_fail_unless(smlAssemblerStartCommand(assm, cmd1, cmd2, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	smlCommandUnref(cmd2);
	
	sml_fail_unless(smlAssemblerEndCommand(assm, cmd1, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	smlCommandUnref(cmd1);
	
	sml_fail_unless(smlAssemblerEndCommand(assm, NULL, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	cmd1 = smlCommandNewSync(loc, loc, 0, &error);
	sml_fail_unless(cmd1 != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	cmd1->cmdID = 4;
	
	g_object_unref(loc);
	
	sml_fail_unless(smlAssemblerStartCommand(assm, NULL, cmd1, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	TEST_DATA_SYNC_CHANGE_ITEM_NEW(SML_CHANGE_ADD, "uid", "data", 5, SML_ELEMENT_TEXT_VCARD);
	cmd2 = smlCommandNewChange(TEST_DATA_SYNC_CHANGE_ITEM, &error);
	TEST_DATA_SYNC_CHANGE_ITEM_FREE();
	cmd2->cmdID = 5;
	
	sml_fail_unless(smlAssemblerStartCommand(assm, cmd1, cmd2, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	smlCommandUnref(cmd2);
	
	sml_fail_unless(smlAssemblerEndCommand(assm, cmd1, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	TEST_DATA_SYNC_CHANGE_ITEM_NEW(SML_CHANGE_ADD, "uid2", "data2", 5, SML_ELEMENT_TEXT_VCARD);
	cmd2 = smlCommandNewChange(TEST_DATA_SYNC_CHANGE_ITEM, &error);
	TEST_DATA_SYNC_CHANGE_ITEM_FREE();
	cmd2->cmdID = 6;
	
	sml_fail_unless(smlAssemblerStartCommand(assm, cmd1, cmd2, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	smlCommandUnref(cmd2);
	
	sml_fail_unless(smlAssemblerEndCommand(assm, cmd1, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	smlCommandUnref(cmd1);
	
	sml_fail_unless(smlAssemblerEndCommand(assm, NULL, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	char *data = NULL;
	gsize size = 0;
	sml_fail_unless(smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(data != NULL, NULL);
	sml_fail_unless(size != 0, NULL);
	
	g_free(data);
	
	sml_fail_unless(smlAssemblerFlush(assm) == 1, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	sml_fail_unless(!smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL);
	sml_fail_unless(error != NULL, NULL);
	SML_ERROR_FREE(error);
	
	smlAssemblerFree(assm);
	smlSessionUnref(session);
}
END_TEST

START_TEST (xml_assembler_message_flush_open)
{
	setup_testbed(NULL);
	GError *error = NULL;
	
	SmlLocation *loc = sml_location_new();
	sml_location_set_uri(loc, "/test");
	
	/* The session type must be SML_SESSION_TYPE_CLIENT
	 * because servers of SyncML 1.1 or higher must send MaxMsgSize.
	 */
	SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, 1, 0, &error);

	SmlAssembler *assm = start_assembler(session, 0);
	sml_fail_unless(assm != NULL, NULL);
	
	sml_fail_unless(smlAssemblerAddHeader(assm, session, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	SmlCommand *cmd1 = smlCommandNewSync(loc, loc, 0, &error);
	sml_fail_unless(cmd1 != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	cmd1->cmdID = 1;
	
	g_object_unref(loc);
	
	sml_fail_unless(smlAssemblerStartCommand(assm, NULL, cmd1, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	SmlCommand *cmd2 = NULL;
	TEST_DATA_SYNC_CHANGE_ITEM_NEW(SML_CHANGE_ADD, "uid", "data", 5, SML_ELEMENT_TEXT_VCARD);
	cmd2 = smlCommandNewChange(TEST_DATA_SYNC_CHANGE_ITEM, &error);
	TEST_DATA_SYNC_CHANGE_ITEM_FREE();
	cmd2->cmdID = 2;
	
	sml_fail_unless(smlAssemblerStartCommand(assm, cmd1, cmd2, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	smlCommandUnref(cmd2);
	
	sml_fail_unless(smlAssemblerEndCommand(assm, cmd1, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	char *data = NULL;
	gsize size = 0;
	sml_fail_unless(smlAssemblerRun(assm, &data, &size, NULL, FALSE, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(data != NULL, NULL);
	sml_fail_unless(size != 0, NULL);
	
	g_free(data);
	
	sml_fail_unless(smlAssemblerFlush(assm) == 1, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	sml_fail_unless(smlAssemblerStartCommand(assm, NULL, cmd1, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	TEST_DATA_SYNC_CHANGE_ITEM_NEW(SML_CHANGE_ADD, "uid2", "data2", 5, SML_ELEMENT_TEXT_VCARD);
	cmd2 = smlCommandNewChange(TEST_DATA_SYNC_CHANGE_ITEM, &error);
	TEST_DATA_SYNC_CHANGE_ITEM_FREE();
	cmd2->cmdID = 3;
	
	sml_fail_unless(smlAssemblerStartCommand(assm, cmd1, cmd2, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	smlCommandUnref(cmd2);
	
	sml_fail_unless(smlAssemblerEndCommand(assm, cmd1, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	smlCommandUnref(cmd1);
	
	sml_fail_unless(smlAssemblerEndCommand(assm, NULL, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	sml_fail_unless(smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(data != NULL, NULL);
	sml_fail_unless(size != 0, NULL);
	
	g_free(data);
	
	sml_fail_unless(smlAssemblerFlush(assm) == 1, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	sml_fail_unless(!smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL);
	sml_fail_unless(error != NULL, NULL);
	SML_ERROR_FREE(error);
	
	smlAssemblerFree(assm);
	smlSessionUnref(session);
}
END_TEST

/** - start sync1
 * - add change to sync1
 * - start sync2
 * - add change to sync2
 * - end sync1
 * - add change to sync1
 * - add change to sync2
 * - end root (sync1)
 * - add change to sync2
 * - end root (sync2)
 */
START_TEST (xml_assembler_out_of_order)
{
	setup_testbed(NULL);
	GError *error = NULL;
	
	SmlLocation *loc = sml_location_new();
	sml_location_set_uri(loc, "/test");
	
	/* The session type must be SML_SESSION_TYPE_CLIENT
	 * because servers of SyncML 1.1 or higher must send MaxMsgSize.
	 */
	SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, 1, 0, &error);

	SmlAssembler *assm = start_assembler(session, 0);
	sml_fail_unless(assm != NULL, NULL);
	
	sml_fail_unless(smlAssemblerAddHeader(assm, session, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	SmlCommand *cmd1 = smlCommandNewSync(loc, loc, 0, &error);
	sml_fail_unless(cmd1 != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	cmd1->cmdID = 1;
	
	sml_fail_unless(smlAssemblerStartCommand(assm, NULL, cmd1, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	SmlCommand *cmd2 = NULL;
	TEST_DATA_SYNC_CHANGE_ITEM_NEW(SML_CHANGE_ADD, "change1sync1", "data", 5, SML_ELEMENT_TEXT_VCARD);
	cmd2 = smlCommandNewChange(TEST_DATA_SYNC_CHANGE_ITEM, &error);
	TEST_DATA_SYNC_CHANGE_ITEM_FREE();
	cmd2->cmdID = 2;
	
	sml_fail_unless(smlAssemblerStartCommand(assm, cmd1, cmd2, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	smlCommandUnref(cmd2);
	
	sml_fail_unless(smlAssemblerEndCommand(assm, cmd1, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	SmlCommand *cmd3 = smlCommandNewSync(loc, loc, 0, &error);
	sml_fail_unless(cmd3 != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	cmd3->cmdID = 4;
	
	g_object_unref(loc);
	
	sml_fail_unless(smlAssemblerStartCommand(assm, NULL, cmd3, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	TEST_DATA_SYNC_CHANGE_ITEM_NEW(SML_CHANGE_ADD, "change1sync2", "data", 5, SML_ELEMENT_TEXT_VCARD);
	cmd2 = smlCommandNewChange(TEST_DATA_SYNC_CHANGE_ITEM, &error);
	TEST_DATA_SYNC_CHANGE_ITEM_FREE();
	cmd2->cmdID = 5;
	
	sml_fail_unless(smlAssemblerStartCommand(assm, cmd3, cmd2, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	smlCommandUnref(cmd2);
	
	sml_fail_unless(smlAssemblerEndCommand(assm, cmd3, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	TEST_DATA_SYNC_CHANGE_ITEM_NEW(SML_CHANGE_ADD, "change2sync1", "data2", 5, SML_ELEMENT_TEXT_VCARD);
	cmd2 = smlCommandNewChange(TEST_DATA_SYNC_CHANGE_ITEM, &error);
	TEST_DATA_SYNC_CHANGE_ITEM_FREE();
	cmd2->cmdID = 3;
	
	sml_fail_unless(smlAssemblerStartCommand(assm, cmd1, cmd2, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	smlCommandUnref(cmd2);
	
	sml_fail_unless(smlAssemblerEndCommand(assm, cmd1, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	TEST_DATA_SYNC_CHANGE_ITEM_NEW(SML_CHANGE_ADD, "change2sync2", "data2", 5, SML_ELEMENT_TEXT_VCARD);
	cmd2 = smlCommandNewChange(TEST_DATA_SYNC_CHANGE_ITEM, &error);
	TEST_DATA_SYNC_CHANGE_ITEM_FREE();
	cmd2->cmdID = 6;
	
	sml_fail_unless(smlAssemblerStartCommand(assm, cmd3, cmd2, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	smlCommandUnref(cmd2);
	
	sml_fail_unless(smlAssemblerEndCommand(assm, cmd3, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	sml_fail_unless(smlAssemblerEndCommand(assm, NULL, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	TEST_DATA_SYNC_CHANGE_ITEM_NEW(SML_CHANGE_ADD, "change3sync2", "data2", 5, SML_ELEMENT_TEXT_VCARD);
	cmd2 = smlCommandNewChange(TEST_DATA_SYNC_CHANGE_ITEM, &error);
	TEST_DATA_SYNC_CHANGE_ITEM_FREE();
	cmd2->cmdID = 7;
	
	sml_fail_unless(smlAssemblerStartCommand(assm, cmd3, cmd2, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	smlCommandUnref(cmd2);
	
	sml_fail_unless(smlAssemblerEndCommand(assm, cmd3, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	smlCommandUnref(cmd3);
	smlCommandUnref(cmd1);
	
	sml_fail_unless(smlAssemblerEndCommand(assm, NULL, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	char *data = NULL;
	gsize size = 0;
	sml_fail_unless(smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(data != NULL, NULL);
	sml_fail_unless(size != 0, NULL);
	
	g_free(data);
	
	sml_fail_unless(smlAssemblerFlush(assm) == 1, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	sml_fail_unless(!smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL);
	sml_fail_unless(error != NULL, NULL);
	SML_ERROR_FREE(error);
	
	smlAssemblerFree(assm);
	smlSessionUnref(session);
}
END_TEST

START_TEST (xml_assembler_limit1)
{
	setup_testbed(NULL);
	GError *error = NULL;
	
	SmlLocation *loc = sml_location_new();
	sml_location_set_uri(loc, "/test");
	
	/* The session type must be SML_SESSION_TYPE_CLIENT
	 * because servers of SyncML 1.1 or higher must send MaxMsgSize.
	 */
	SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, 1, 0, &error);

	g_object_unref(loc);
	
	SmlAssembler *assm = start_assembler(session, 1);
	sml_fail_unless(assm != NULL, NULL);
	
	sml_fail_unless(!smlAssemblerAddHeader(assm, session, &error), NULL);
	sml_fail_unless(error != NULL, NULL);
	SML_ERROR_FREE(error);
	
	char *data = NULL;
	gsize size = 0;
	sml_fail_unless(!smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL);
	sml_fail_unless(error != NULL, NULL);
	SML_ERROR_FREE(error);
	
	smlAssemblerFree(assm);
	smlSessionUnref(session);
}
END_TEST

START_TEST (xml_assembler_limit2)
{
	setup_testbed(NULL);
	GError *error = NULL;
	
	SmlLocation *loc = sml_location_new();
	sml_location_set_uri(loc, "/test");
	
	/* The session type must be SML_SESSION_TYPE_CLIENT
	 * because servers of SyncML 1.1 or higher must send MaxMsgSize.
	 */
	SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, 1, 0, &error);

	g_object_unref(loc);
	
	SmlAssembler *assm = start_assembler(session, 100);
	sml_fail_unless(assm != NULL, NULL);
	
	sml_fail_unless(!smlAssemblerAddHeader(assm, session, &error), NULL);
	sml_fail_unless(error != NULL, NULL);
	SML_ERROR_FREE(error);
	
	char *data = NULL;
	gsize size = 0;
	sml_fail_unless(!smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL);
	sml_fail_unless(error != NULL, NULL);
	SML_ERROR_FREE(error);
	
	smlAssemblerFree(assm);
	smlSessionUnref(session);
}
END_TEST

START_TEST (xml_assembler_limit3)
{
	setup_testbed(NULL);
	GError *error = NULL;
	
	SmlLocation *loc = sml_location_new();
	sml_location_set_uri(loc, "/test");
	
	/* The session type must be SML_SESSION_TYPE_CLIENT
	 * because servers of SyncML 1.1 or higher must send MaxMsgSize.
	 */
	SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, 1, 0, &error);

	SmlAssembler *assm = start_assembler(session, 220);
	sml_fail_unless(assm != NULL, NULL);
	
	sml_fail_unless(smlAssemblerReserveStatus(assm, 1, 1, 1, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	sml_fail_unless(smlAssemblerAddHeader(assm, session, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	SmlStatus *status = smlStatusNew(SML_NO_ERROR, 1, 1, loc, loc, SML_COMMAND_TYPE_SYNC, &error);
	sml_fail_unless(status != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	g_object_unref(loc);
	
	sml_fail_unless(smlAssemblerAddStatus(assm, status, &error) == SML_ASSEMBLER_RESULT_MISMATCH, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	smlStatusUnref(status);
	
	char *data = NULL;
	gsize size = 0;
	sml_fail_unless(!smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL);
	sml_fail_unless(error != NULL, NULL);
	SML_ERROR_FREE(error);
	
	smlAssemblerFree(assm);
	smlSessionUnref(session);
}
END_TEST

START_TEST (xml_assembler_limit4)
{
	setup_testbed(NULL);
	GError *error = NULL;
	
	SmlLocation *loc = sml_location_new();
	sml_location_set_uri(loc, "/test");
	
	/* The session type must be SML_SESSION_TYPE_CLIENT
	 * because servers of SyncML 1.1 or higher must send MaxMsgSize.
	 */
	SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, 1, 0, &error);

	SmlAssembler *assm = start_assembler(session, 380);
	sml_fail_unless(assm != NULL, NULL);
	
	sml_fail_unless(smlAssemblerAddHeader(assm, session, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	sml_fail_unless(smlAssemblerReserveStatus(assm, 1, 1, 1, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	SmlStatus *status = smlStatusNew(SML_NO_ERROR, 1, 1, loc, loc, SML_COMMAND_TYPE_SYNC, &error);
	sml_fail_unless(status != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	g_object_unref(loc);
	
	sml_fail_unless(smlAssemblerAddStatus(assm, status, &error) == SML_ASSEMBLER_RESULT_OK, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	smlStatusUnref(status);
	
	char *data = NULL;
	gsize size = 0;
	sml_fail_unless(smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	g_free(data);
	
	smlAssemblerFree(assm);
	smlSessionUnref(session);
}
END_TEST

START_TEST (xml_assembler_limit5)
{
	setup_testbed(NULL);
	GError *error = NULL;
	
	SmlLocation *loc = sml_location_new();
	sml_location_set_uri(loc, "/test");
	
	/* The session type must be SML_SESSION_TYPE_CLIENT
	 * because servers of SyncML 1.1 or higher must send MaxMsgSize.
	 */
	SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, 1, 0, &error);

	SmlAssembler *assm = start_assembler(session, 500);
	sml_fail_unless(assm != NULL, NULL);
	
	sml_fail_unless(smlAssemblerAddHeader(assm, session, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	sml_fail_unless(smlAssemblerReserveStatus(assm, 1, 1, 1, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	SmlStatus *status = smlStatusNew(SML_NO_ERROR, 1, 1, loc, loc, SML_COMMAND_TYPE_SYNC, &error);
	sml_fail_unless(status != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	sml_fail_unless(smlAssemblerAddStatus(assm, status, &error) == SML_ASSEMBLER_RESULT_OK, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	smlStatusUnref(status);
	
	SmlCommand *cmd = smlCommandNewAlert(SML_ALERT_TWO_WAY, loc, loc, "next", "last", NULL, &error);
	sml_fail_unless(cmd != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	cmd->cmdID = 1;
	
	g_object_unref(loc);
	
	sml_fail_unless(smlAssemblerStartCommand(assm, NULL, cmd, &error) == SML_ASSEMBLER_RESULT_MISMATCH, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	char *data = NULL;
	gsize size = 0;
	sml_fail_unless(smlAssemblerRun(assm, &data, &size, NULL, FALSE, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(data != NULL, NULL);
	sml_fail_unless(size != 0, NULL);
	
	g_free(data);
	
	sml_fail_unless(smlAssemblerFlush(assm) == 1, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	sml_fail_unless(smlAssemblerStartCommand(assm, NULL, cmd, &error) == SML_ASSEMBLER_RESULT_OK, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	smlCommandUnref(cmd);
	
	sml_fail_unless(smlAssemblerEndCommand(assm, NULL, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	sml_fail_unless(smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(data != NULL, NULL);
	sml_fail_unless(size != 0, NULL);
	
	g_free(data);
	
	smlAssemblerFree(assm);
	smlSessionUnref(session);
}
END_TEST

START_TEST (xml_assembler_devinf)
{
	setup_testbed(NULL);
	GError *error = NULL;
	
	SmlLocation *loc = sml_location_new();
	sml_location_set_uri(loc, "/test");
	
	/* The session type must be SML_SESSION_TYPE_CLIENT
	 * because servers of SyncML 1.1 or higher must send MaxMsgSize.
	 */
	SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, 1, 0, &error);

	SmlAssembler *assm = start_assembler(session, 0);
	sml_fail_unless(assm != NULL, NULL);
	
	sml_fail_unless(smlAssemblerReserveStatus(assm, 0, 1, 1, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	sml_fail_unless(smlAssemblerAddHeader(assm, session, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
		
	SmlStatus *status = smlStatusNew(SML_NO_ERROR, 0, 1, loc, loc, SML_COMMAND_TYPE_HEADER, &error);
	sml_fail_unless(status != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	g_object_unref(loc);
	
	sml_fail_unless(smlAssemblerAddStatus(assm, status, &error) == SML_ASSEMBLER_RESULT_OK, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	smlStatusUnref(status);
	
	SmlDevInf *devinf = sml_dev_inf_new();
	sml_fail_unless(devinf != NULL, NULL);
	sml_dev_inf_set_dev_typ(devinf, SML_DEVINF_DEVTYP_WORKSTATION);
	sml_fail_unless(sml_dev_inf_set_dev_id(devinf, "mydevice", &error), "%s", GET_ERROR_MESSAGE(error));
	sml_fail_unless(devinf != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	SmlCommand *cmd = smlCommandNewDevInfPut(devinf, SML_DEVINF_VERSION_11, &error);
	sml_fail_unless(cmd != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	cmd->cmdID = 1;
	
	g_object_unref(devinf);
	
	sml_fail_unless(smlAssemblerStartCommand(assm, NULL, cmd, &error) == SML_ASSEMBLER_RESULT_OK, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	smlCommandUnref(cmd);
	
	sml_fail_unless(smlAssemblerEndCommand(assm, NULL, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	char *data = NULL;
	gsize size = 0;
	sml_fail_unless(smlAssemblerRun(assm, &data, &size, NULL, FALSE, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(data != NULL, NULL);
	sml_fail_unless(size != 0, NULL);
	
	g_free(data);
	
	sml_fail_unless(smlAssemblerFlush(assm) == 1, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	smlAssemblerFree(assm);
	smlSessionUnref(session);
}
END_TEST

START_TEST (xml_assembler_devinf12)
{
	setup_testbed(NULL);
	GError *error = NULL;
	
	SmlLocation *loc = sml_location_new();
	sml_location_set_uri(loc, "/test");
	
	/* The session type must be SML_SESSION_TYPE_CLIENT
	 * because servers of SyncML 1.1 or higher must send MaxMsgSize.
	 */
	SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, 1, 0, &error);

	SmlAssembler *assm = start_assembler(session, 0);
	sml_fail_unless(assm != NULL, NULL);
	
	sml_fail_unless(smlAssemblerReserveStatus(assm, 0, 1, 1, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	sml_fail_unless(smlAssemblerAddHeader(assm, session, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
		
	SmlStatus *status = smlStatusNew(SML_NO_ERROR, 0, 1, loc, loc, SML_COMMAND_TYPE_HEADER, &error);
	sml_fail_unless(status != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	g_object_unref(loc);
	
	sml_fail_unless(smlAssemblerAddStatus(assm, status, &error) == SML_ASSEMBLER_RESULT_OK, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	smlStatusUnref(status);
	
	SmlDevInf *devinf = sml_dev_inf_new();
	sml_fail_unless(devinf != NULL, NULL);
	sml_dev_inf_set_dev_typ(devinf, SML_DEVINF_DEVTYP_WORKSTATION);
	sml_fail_unless(sml_dev_inf_set_dev_id(devinf, "mydevice", &error), "%s", GET_ERROR_MESSAGE(error));
	sml_fail_unless(devinf != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	SmlCommand *cmd = smlCommandNewDevInfPut(devinf, SML_DEVINF_VERSION_12, &error);
	sml_fail_unless(cmd != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	cmd->cmdID = 1;
	
	g_object_unref(devinf);
	
	sml_fail_unless(smlAssemblerStartCommand(assm, NULL, cmd, &error) == SML_ASSEMBLER_RESULT_OK, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	smlCommandUnref(cmd);
	
	sml_fail_unless(smlAssemblerEndCommand(assm, NULL, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	char *data = NULL;
	gsize size = 0;
	sml_fail_unless(smlAssemblerRun(assm, &data, &size, NULL, FALSE, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(data != NULL, NULL);
	sml_fail_unless(size != 0, NULL);
	
	g_free(data);
	
	sml_fail_unless(smlAssemblerFlush(assm) == 1, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	smlAssemblerFree(assm);
	smlSessionUnref(session);
}
END_TEST

START_TEST (xml_assembler_order)
{
	setup_testbed(NULL);
	GError *error = NULL;
	
	SmlLocation *loc = sml_location_new();
	sml_location_set_uri(loc, "/test");
	
	/* The session type must be SML_SESSION_TYPE_CLIENT
	 * because servers of SyncML 1.1 or higher must send MaxMsgSize.
	 */
	SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, 1, 0, &error);

	SmlAssembler *assm = start_assembler(session, 0);
	sml_fail_unless(assm != NULL, NULL);
	
	sml_fail_unless(smlAssemblerAddHeader(assm, session, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	sml_fail_unless(smlAssemblerReserveStatus(assm, 0, 1, 1, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(smlAssemblerReserveStatus(assm, 1, 1, 2, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(smlAssemblerReserveStatus(assm, 2, 1, 3, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	SmlStatus *status = smlStatusNew(SML_NO_ERROR, 2, 1, loc, loc, SML_COMMAND_TYPE_PUT, &error);
	sml_fail_unless(status != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	sml_fail_unless(smlAssemblerAddStatus(assm, status, &error) == SML_ASSEMBLER_RESULT_OK, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	smlStatusUnref(status);
	
	status = smlStatusNew(SML_NO_ERROR, 1, 1, loc, loc, SML_COMMAND_TYPE_SYNC, &error);
	sml_fail_unless(status != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	sml_fail_unless(smlAssemblerAddStatus(assm, status, &error) == SML_ASSEMBLER_RESULT_OK, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	smlStatusUnref(status);
	
	status = smlStatusNew(SML_NO_ERROR, 0, 1, loc, loc, SML_COMMAND_TYPE_HEADER, &error);
	sml_fail_unless(status != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	g_object_unref(loc);
	
	sml_fail_unless(smlAssemblerAddStatus(assm, status, &error) == SML_ASSEMBLER_RESULT_OK, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	smlStatusUnref(status);
	
	char *data = NULL;
	gsize size = 0;
	sml_fail_unless(smlAssemblerRun(assm, &data, &size, NULL, FALSE, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(data != NULL, NULL);
	sml_fail_unless(size != 0, NULL);
	
	smlAssemblerFree(assm);
	smlSessionUnref(session);
	
	SmlParser *parser = start_parser(data, &error);
	sml_fail_unless(parser != NULL, "%s", GET_ERROR_MESSAGE(error));
	
	SmlHeader *header = NULL;
	SmlCred *cred = NULL;
	sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL);
	sml_fail_unless(header != NULL, NULL);
	sml_fail_unless(cred == NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	sml_fail_unless(header->messageID == 1, NULL);
	smlHeaderFree(header);
	
	sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL);
	sml_fail_unless(status != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	sml_fail_unless(status->type == SML_COMMAND_TYPE_HEADER, NULL);
	smlStatusUnref(status);
	
	sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL);
	sml_fail_unless(status != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	sml_fail_unless(status->type == SML_COMMAND_TYPE_SYNC, NULL);
	smlStatusUnref(status);
	
	sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL);
	sml_fail_unless(status != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	sml_fail_unless(status->type == SML_COMMAND_TYPE_PUT, NULL);
	smlStatusUnref(status);
	
	sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL);
	sml_fail_unless(status == NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	gboolean final = TRUE;
	gboolean end = TRUE;
	sml_fail_unless(smlParserEnd(parser, &final, &end, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(final == FALSE, NULL);
	sml_fail_unless(end == FALSE, NULL);
	
	smlParserFree(parser);
		
	g_free(data);
}
END_TEST

/* - Reserve 3 statuses
 * - Add one status
 * - Should report missing statuses
 * - Run(final) -> error since statuses are missing
 * - Run(not final) & Flush -> data should have one status
 * - Should report missing statuses
 * - Add 2 remaining statuses
 * - Should not report missing statuses
 * - Run & Flush -> data should have the 2 remaining statuses
 */
START_TEST (xml_assembler_reuse)
{
	setup_testbed(NULL);
	GError *error = NULL;
	
	SmlLocation *loc = sml_location_new();
	sml_location_set_uri(loc, "/test");
	
	/* The session type must be SML_SESSION_TYPE_CLIENT
	 * because servers of SyncML 1.1 or higher must send MaxMsgSize.
	 */
	SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, 1, 0, &error);

	SmlAssembler *assm = start_assembler(session, 0);
	sml_fail_unless(assm != NULL, NULL);
	
	sml_fail_unless(smlAssemblerAddHeader(assm, session, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	sml_fail_unless(smlAssemblerIsStatusMissing(assm) == FALSE, NULL);
	
	sml_fail_unless(smlAssemblerReserveStatus(assm, 0, 1, 1, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(smlAssemblerReserveStatus(assm, 1, 1, 2, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(smlAssemblerReserveStatus(assm, 2, 1, 3, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	
	SmlStatus *status = smlStatusNew(SML_NO_ERROR, 0, 1, loc, loc, SML_COMMAND_TYPE_HEADER, &error);
	sml_fail_unless(status != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	char *data = NULL;
	gsize size = 0;
	/* Must fail since nothing has been added at all */
	sml_fail_unless(!smlAssemblerRun(assm, &data, &size, NULL, FALSE, &error), NULL);
	sml_fail_unless(error != NULL, NULL);
	sml_fail_unless(data == NULL, NULL);
	sml_fail_unless(size == 0, NULL);
	SML_ERROR_FREE(error);
	
	sml_fail_unless(smlAssemblerAddStatus(assm, status, &error) == SML_ASSEMBLER_RESULT_OK, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	smlStatusUnref(status);
	
	sml_fail_unless(smlAssemblerIsStatusMissing(assm) == TRUE, NULL);
	
	/* Must fail since not all statuses have been added */
	sml_fail_unless(!smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL);
	sml_fail_unless(error != NULL, NULL);
	sml_fail_unless(data == NULL, NULL);
	sml_fail_unless(size == 0, NULL);
	SML_ERROR_FREE(error);
	
	/* Must work */
	sml_fail_unless(smlAssemblerRun(assm, &data, &size, NULL, FALSE, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(data != NULL, NULL);
	sml_fail_unless(size != 0, NULL);
	
	sml_fail_unless(smlAssemblerFlush(assm) == 3, NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(smlAssemblerAddHeader(assm, session, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	sml_fail_unless(smlAssemblerIsStatusMissing(assm) == TRUE, NULL);
	
	SmlParser *parser = start_parser(data, &error);
	sml_fail_unless(parser != NULL, "%s", GET_ERROR_MESSAGE(error));
	
	SmlHeader *header = NULL;
	SmlCred *cred = NULL;
	sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL);
	sml_fail_unless(header != NULL, NULL);
	sml_fail_unless(cred == NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	sml_fail_unless(header->messageID == 1, NULL);
	smlHeaderFree(header);
	
	sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL);
	sml_fail_unless(status != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	sml_fail_unless(status->type == SML_COMMAND_TYPE_HEADER, NULL);
	smlStatusUnref(status);
	
	sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL);
	sml_fail_unless(status == NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	gboolean final = TRUE;
	gboolean end = TRUE;
	sml_fail_unless(smlParserEnd(parser, &final, &end, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(final == FALSE, NULL);
	sml_fail_unless(end == FALSE, NULL);
	
	smlParserFree(parser);
	g_free(data);
	
	status = smlStatusNew(SML_NO_ERROR, 1, 1, loc, loc, SML_COMMAND_TYPE_SYNC, &error);
	sml_fail_unless(status != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	sml_fail_unless(smlAssemblerAddStatus(assm, status, &error) == SML_ASSEMBLER_RESULT_OK, NULL);
	sml_fail_unless(error == NULL, NULL);
	smlStatusUnref(status);
	
	status = smlStatusNew(SML_NO_ERROR, 2, 1, loc, loc, SML_COMMAND_TYPE_PUT, &error);
	sml_fail_unless(status != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	g_object_unref(loc);
	
	sml_fail_unless(smlAssemblerAddStatus(assm, status, &error) == SML_ASSEMBLER_RESULT_OK, NULL);
	sml_fail_unless(error == NULL, NULL);
	smlStatusUnref(status);
	
	sml_fail_unless(smlAssemblerIsStatusMissing(assm) == FALSE, NULL);
	
	data = NULL;
	size = 0;
	sml_fail_unless(smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(data != NULL, NULL);
	sml_fail_unless(size != 0, NULL);
	
	smlAssemblerFree(assm);
	smlSessionUnref(session);
	
	parser = start_parser(data, &error);
	sml_fail_unless(parser != NULL, "%s", GET_ERROR_MESSAGE(error));
	
	header = NULL;
	sml_fail_unless(smlParserGetHeader(parser, &header, &cred, &error), NULL);
	sml_fail_unless(header != NULL, NULL);
	sml_fail_unless(cred == NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	sml_fail_unless(header->messageID == 1, NULL);
	smlHeaderFree(header);
	
	sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL);
	sml_fail_unless(status != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	sml_fail_unless(status->type == SML_COMMAND_TYPE_SYNC, NULL);
	smlStatusUnref(status);
	
	sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL);
	sml_fail_unless(status != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	sml_fail_unless(status->type == SML_COMMAND_TYPE_PUT, NULL);
	smlStatusUnref(status);
	
	sml_fail_unless(smlParserGetStatus(parser, &status, &error), NULL);
	sml_fail_unless(status == NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	final = TRUE;
	end = TRUE;
	sml_fail_unless(smlParserEnd(parser, &final, &end, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(final == TRUE, NULL);
	sml_fail_unless(end == TRUE, NULL);
	
	smlParserFree(parser);
	g_free(data);
	
}
END_TEST

START_TEST (xml_assembler_leak)
{
	setup_testbed(NULL);
	GError *error = NULL;
	
	SmlLocation *loc = sml_location_new();
	sml_location_set_uri(loc, "/test");
	
	/* The session type must be SML_SESSION_TYPE_CLIENT
	 * because servers of SyncML 1.1 or higher must send MaxMsgSize.
	 */
	SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, 1, 0, &error);

	SmlAssembler *assm = start_assembler(session, 0);
	sml_fail_unless(assm != NULL, NULL);
	
	sml_fail_unless(smlAssemblerAddHeader(assm, session, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	sml_fail_unless(smlAssemblerReserveStatus(assm, 0, 1, 1, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(smlAssemblerReserveStatus(assm, 1, 1, 2, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(smlAssemblerReserveStatus(assm, 2, 1, 3, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	char *data = NULL;
	gsize size = 0;
	/* Must fail since nothing has been added at all */
	sml_fail_unless(!smlAssemblerRun(assm, &data, &size, NULL, FALSE, &error), NULL);
	sml_fail_unless(error != NULL, NULL);
	sml_fail_unless(data == NULL, NULL);
	sml_fail_unless(size == 0, NULL);
	SML_ERROR_FREE(error);
	
	sml_fail_unless(smlAssemblerFlush(assm) == 4, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	smlAssemblerFree(assm);
	
	assm = start_assembler(session, 0);
	sml_fail_unless(assm != NULL, NULL);
	
	sml_fail_unless(smlAssemblerAddHeader(assm, session, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	SmlStatus *status = smlStatusNew(SML_NO_ERROR, 0, 1, loc, loc, SML_COMMAND_TYPE_HEADER, &error);
	sml_fail_unless(status != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	sml_fail_unless(smlAssemblerAddStatus(assm, status, &error) != SML_ASSEMBLER_RESULT_OK, NULL);
	sml_fail_unless(error != NULL, NULL);
	SML_ERROR_FREE(error);
	
	smlStatusUnref(status);
	
	/* Must fail since not all statuses have been added */
	sml_fail_unless(!smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL);
	sml_fail_unless(error != NULL, NULL);
	sml_fail_unless(data == NULL, NULL);
	sml_fail_unless(size == 0, NULL);
	SML_ERROR_FREE(error);
	
	sml_fail_unless(smlAssemblerFlush(assm) == 1, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	smlAssemblerFree(assm);
	
	assm = start_assembler(session, 0);
	sml_fail_unless(assm != NULL, NULL);
	
	sml_fail_unless(smlAssemblerAddHeader(assm, session, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	SmlCommand *cmd2 = NULL;
	TEST_DATA_SYNC_CHANGE_ITEM_NEW(SML_CHANGE_ADD, "change1sync1", "data", 5, SML_ELEMENT_TEXT_VCARD);
	cmd2 = smlCommandNewChange(TEST_DATA_SYNC_CHANGE_ITEM, &error);
	TEST_DATA_SYNC_CHANGE_ITEM_FREE();
	cmd2->cmdID = 2;
	
	sml_fail_unless(smlAssemblerStartCommand(assm, NULL, cmd2, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	smlCommandUnref(cmd2);
	
	/* Must fail since not all statuses have been added */
	sml_fail_unless(smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL);
	sml_fail_unless(error== NULL, NULL);
	sml_fail_unless(data != NULL, NULL);
	sml_fail_unless(size != 0, NULL);
	
	g_free(data);
	
	sml_fail_unless(smlAssemblerFlush(assm) == 1, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	g_object_unref(loc);
	smlAssemblerFree(assm);
	smlSessionUnref(session);
}
END_TEST

START_TEST (xml_assembler_stress)
{
	setup_testbed(NULL);
	int num_cmd = 1000;
	int num_status = 1000;
	
	GError *error = NULL;
	
	SmlLocation *loc = sml_location_new();
	sml_location_set_uri(loc, "/test");
	
	/* The session type must be SML_SESSION_TYPE_CLIENT
	 * because servers of SyncML 1.1 or higher must send MaxMsgSize.
	 */
	SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, 1, 0, &error);

	SmlAssembler *assm = start_assembler(session, 0);
	sml_fail_unless(assm != NULL, NULL);
	
	sml_fail_unless(smlAssemblerAddHeader(assm, session, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	int i = 0;
	for (i = 0; i < num_status; i++) {
		sml_fail_unless(smlAssemblerReserveStatus(assm, i + 1, 1, 1, &error), NULL);
		sml_fail_unless(error == NULL, NULL);
		
		SmlStatus *status = smlStatusNew(SML_NO_ERROR, i + 1, 1, loc, loc, SML_COMMAND_TYPE_SYNC, &error);
		sml_fail_unless(status != NULL, NULL);
		sml_fail_unless(error == NULL, NULL);
	
	
		sml_fail_unless(smlAssemblerAddStatus(assm, status, &error), NULL);
		sml_fail_unless(error == NULL, NULL);
		
		smlStatusUnref(status);
	}
	
	for (i = 0; i < num_cmd; i++) {
		SmlCommand *cmd1 = smlCommandNewSync(loc, loc, 0, &error);
		sml_fail_unless(cmd1 != NULL, NULL);
		sml_fail_unless(error == NULL, NULL);
		cmd1->cmdID = i + 1 + num_status;
	
		sml_fail_unless(smlAssemblerStartCommand(assm, NULL, cmd1, &error), NULL);
		sml_fail_unless(error == NULL, NULL);
	
		smlCommandUnref(cmd1);
		
		sml_fail_unless(smlAssemblerEndCommand(assm, NULL, &error), NULL);
		sml_fail_unless(error == NULL, NULL);
	}
	
	char *data = NULL;
	gsize size = 0;
	sml_fail_unless(smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(data != NULL, NULL);
	sml_fail_unless(size != 0, NULL);
	
	g_free(data);
	
	sml_fail_unless(smlAssemblerFlush(assm) == 1, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	sml_fail_unless(!smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL);
	sml_fail_unless(error != NULL, NULL);
	SML_ERROR_FREE(error);
	
	g_object_unref(loc);
	smlAssemblerFree(assm);
	smlSessionUnref(session);
}
END_TEST

START_TEST (xml_assembler_stress_limit)
{
	setup_testbed(NULL);
	int num_cmd = 1000;
	int num_status = 1000;
	
	int limit = 50000;
	
	GError *error = NULL;
	
	SmlLocation *loc = sml_location_new();
	sml_location_set_uri(loc, "/test");
	
	/* The session type must be SML_SESSION_TYPE_CLIENT
	 * because servers of SyncML 1.1 or higher must send MaxMsgSize.
	 */
	SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, 1, 0, &error);

	SmlAssembler *assm = start_assembler(session, limit);
	sml_fail_unless(assm != NULL, NULL);
	
	sml_fail_unless(smlAssemblerAddHeader(assm, session, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	int i = 0;
	for (i = 0; i < num_status; i++) {
		sml_fail_unless(smlAssemblerReserveStatus(assm, i + 1, 1, 1, &error), NULL);
		sml_fail_unless(error == NULL, NULL);
		
		SmlStatus *status = smlStatusNew(SML_NO_ERROR, i + 1, 1, loc, loc, SML_COMMAND_TYPE_SYNC, &error);
		sml_fail_unless(status != NULL, NULL);
		sml_fail_unless(error == NULL, NULL);
	
		SmlAssemblerResult res = smlAssemblerAddStatus(assm, status, &error);
		if (res == SML_ASSEMBLER_RESULT_MISMATCH) {
			char *data = NULL;
			gsize size = 0;
			sml_fail_unless(smlAssemblerRun(assm, &data, &size, NULL, FALSE, &error), NULL);
			sml_fail_unless(error == NULL, NULL);
			sml_fail_unless(data != NULL, NULL);
			sml_fail_unless(size != 0, NULL);
			
			g_free(data);
			
			smlAssemblerFlush(assm);
			
			sml_fail_unless(smlAssemblerAddStatus(assm, status, &error) == SML_ASSEMBLER_RESULT_OK, NULL);
			sml_fail_unless(error == NULL, NULL);
		} else if (res != SML_ASSEMBLER_RESULT_OK) {
			sml_fail_unless(FALSE, "%s", GET_ERROR_MESSAGE(error));
		}
		
		smlStatusUnref(status);
	}
	
	for (i = 0; i < num_cmd; i++) {
		SmlCommand *cmd1 = smlCommandNewSync(loc, loc, 0, &error);
		sml_fail_unless(cmd1 != NULL, NULL);
		sml_fail_unless(error == NULL, NULL);
		cmd1->cmdID = i + 1 + num_status;
	
		SmlAssemblerResult res = smlAssemblerStartCommand(assm, NULL, cmd1, &error);
		
		if (res == SML_ASSEMBLER_RESULT_MISMATCH) {
			char *data = NULL;
			gsize size = 0;
			sml_fail_unless(smlAssemblerRun(assm, &data, &size, NULL, FALSE, &error), NULL);
			sml_fail_unless(error == NULL, NULL);
			sml_fail_unless(data != NULL, NULL);
			sml_fail_unless(size != 0, NULL);
			
			g_free(data);
			
			sml_fail_unless(smlAssemblerFlush(assm) == 1, NULL);
			sml_fail_unless(error == NULL, NULL);
			
			sml_fail_unless(smlAssemblerStartCommand(assm, NULL, cmd1, &error), NULL);
			sml_fail_unless(error == NULL, NULL);
		} else if (res != SML_ASSEMBLER_RESULT_OK) {
			sml_fail_unless(FALSE, "%s", GET_ERROR_MESSAGE(error));
		}
	
		smlCommandUnref(cmd1);
		
		sml_fail_unless(smlAssemblerEndCommand(assm, NULL, &error), NULL);
		sml_fail_unless(error == NULL, NULL);
	}
	
	char *data = NULL;
	gsize size = 0;
	sml_fail_unless(smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(data != NULL, NULL);
	sml_fail_unless(size != 0, NULL);
	
	g_free(data);
	
	sml_fail_unless(smlAssemblerFlush(assm) == 1, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	sml_fail_unless(!smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL);
	sml_fail_unless(error != NULL, NULL);
	SML_ERROR_FREE(error);
	
	g_object_unref(loc);
	smlAssemblerFree(assm);
	smlSessionUnref(session);
}
END_TEST

START_TEST (xml_assembler_stress_large_limit)
{
	setup_testbed(NULL);
	int num_cmd = 1000;
	int num_status = 1000;
	
	int limit = 500000000;
	
	GError *error = NULL;
	
	SmlLocation *loc = sml_location_new();
	sml_location_set_uri(loc, "/test");
	
	/* The session type must be SML_SESSION_TYPE_CLIENT
	 * because servers of SyncML 1.1 or higher must send MaxMsgSize.
	 */
	SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, 1, 0, &error);

	SmlAssembler *assm = start_assembler(session, limit);
	sml_fail_unless(assm != NULL, NULL);
	
	sml_fail_unless(smlAssemblerAddHeader(assm, session, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	int i = 0;
	for (i = 0; i < num_status; i++) {
		sml_fail_unless(smlAssemblerReserveStatus(assm, i + 1, 1, 1, &error), NULL);
		sml_fail_unless(error == NULL, NULL);
		
		SmlStatus *status = smlStatusNew(SML_NO_ERROR, i + 1, 1, loc, loc, SML_COMMAND_TYPE_SYNC, &error);
		sml_fail_unless(status != NULL, NULL);
		sml_fail_unless(error == NULL, NULL);
		
		sml_fail_unless(smlAssemblerAddStatus(assm, status, &error) == SML_ASSEMBLER_RESULT_OK, NULL);
		sml_fail_unless(error == NULL, NULL);
		
		smlStatusUnref(status);
	}
	
	for (i = 0; i < num_cmd; i++) {
		SmlCommand *cmd1 = smlCommandNewSync(loc, loc, 0, &error);
		sml_fail_unless(cmd1 != NULL, NULL);
		sml_fail_unless(error == NULL, NULL);
		cmd1->cmdID = i + 1 + num_status;
	
		sml_fail_unless(smlAssemblerStartCommand(assm, NULL, cmd1, &error) == SML_ASSEMBLER_RESULT_OK, NULL);
		sml_fail_unless(error == NULL, NULL);
	
		smlCommandUnref(cmd1);
		
		sml_fail_unless(smlAssemblerEndCommand(assm, NULL, &error), NULL);
		sml_fail_unless(error == NULL, NULL);
	}
	
	char *data = NULL;
	gsize size = 0;
	sml_fail_unless(smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(data != NULL, NULL);
	sml_fail_unless(size != 0, NULL);
	
	g_free(data);
	
	sml_fail_unless(smlAssemblerFlush(assm) == 1, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	sml_fail_unless(!smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL);
	sml_fail_unless(error != NULL, NULL);
	SML_ERROR_FREE(error);
	
	g_object_unref(loc);
	smlAssemblerFree(assm);
	smlSessionUnref(session);
}
END_TEST

START_TEST (xml_assembler_large_obj)
{
	setup_testbed(NULL);
	int limit = 500000;
	
	GError *error = NULL;
	
	SmlLocation *loc = sml_location_new();
	sml_location_set_uri(loc, "/test");
	
	/* The session type must be SML_SESSION_TYPE_CLIENT
	 * because servers of SyncML 1.1 or higher must send MaxMsgSize.
	 */
	SmlSession *session = smlSessionNew(SML_SESSION_TYPE_CLIENT, SML_MIMETYPE_XML, SML_VERSION_12, SML_PROTOCOL_SYNCML, loc, loc, 1, 0, &error);

	SmlAssembler *assm = start_assembler(session, limit);
	sml_fail_unless(assm != NULL, NULL);
	
	sml_fail_unless(smlAssemblerAddHeader(assm, session, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	
	SmlCommand *cmd1 = smlCommandNewSync(loc, loc, 0, &error);
	sml_fail_unless(cmd1 != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	cmd1->cmdID = 1;
	
	smlAssemblerStartCommand(assm, NULL, cmd1, &error);
	
	SmlCommand *cmd2 = NULL;
	TEST_DATA_SYNC_CHANGE_ITEM_NEW(SML_CHANGE_ADD, "uid", "data", 5, SML_ELEMENT_TEXT_VCARD);
	cmd2 = smlCommandNewChange(TEST_DATA_SYNC_CHANGE_ITEM, &error);
	TEST_DATA_SYNC_CHANGE_ITEM_FREE();
	sml_fail_unless(cmd2 != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	cmd2->cmdID = 2;
	
	sml_fail_unless(smlAssemblerStartCommand(assm, cmd1, cmd2, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	smlCommandUnref(cmd2);
	
	sml_fail_unless(smlAssemblerEndCommand(assm, cmd1, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	TEST_DATA_SYNC_CHANGE_ITEM_NEW(SML_CHANGE_ADD, "uid", "data", 5, SML_ELEMENT_TEXT_VCARD);
	sml_data_sync_change_item_set_missing_data(TEST_DATA_SYNC_CHANGE_ITEM, TRUE);
	sml_data_sync_change_item_set_planned_size(TEST_DATA_SYNC_CHANGE_ITEM, 200);
	cmd2 = smlCommandNewChange(TEST_DATA_SYNC_CHANGE_ITEM, &error);
	TEST_DATA_SYNC_CHANGE_ITEM_FREE();
	sml_fail_unless(cmd2 != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	cmd2->cmdID = 2;
	
	sml_fail_unless(smlAssemblerStartCommand(assm, cmd1, cmd2, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	smlCommandUnref(cmd2);
	
	sml_fail_unless(smlAssemblerEndCommand(assm, cmd1, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	TEST_DATA_SYNC_CHANGE_ITEM_NEW(SML_CHANGE_ADD, "uid", "data", 5, SML_ELEMENT_TEXT_VCARD);
	cmd2 = smlCommandNewChange(TEST_DATA_SYNC_CHANGE_ITEM, &error);
	TEST_DATA_SYNC_CHANGE_ITEM_FREE();
	sml_fail_unless(cmd2 != NULL, NULL);
	sml_fail_unless(error == NULL, NULL);
	cmd2->cmdID = 2;
	
	sml_fail_unless(!smlAssemblerStartCommand(assm, cmd1, cmd2, &error), NULL);
	sml_fail_unless(error != NULL, NULL);
	SML_ERROR_FREE(error);
	
	smlCommandUnref(cmd2);
	
	sml_fail_unless(smlAssemblerEndCommand(assm, cmd1, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	smlCommandUnref(cmd1);
	
	sml_fail_unless(smlAssemblerEndCommand(assm, NULL, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	
	char *data = NULL;
	gsize size = 0;
	sml_fail_unless(smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL);
	sml_fail_unless(error == NULL, NULL);
	sml_fail_unless(data != NULL, NULL);
	sml_fail_unless(size != 0, NULL);
	
	g_free(data);
	
	sml_fail_unless(smlAssemblerFlush(assm) == 1, NULL);
	sml_fail_unless(error == NULL, NULL);
	
	sml_fail_unless(!smlAssemblerRun(assm, &data, &size, NULL, TRUE, &error), NULL);
	sml_fail_unless(error != NULL, NULL);
	SML_ERROR_FREE(error);
	
	g_object_unref(loc);
	smlAssemblerFree(assm);
	smlSessionUnref(session);
}
END_TEST

@SML_TESTCASE_CODE@

