/* * libsyncml - A syncml protocol implementation * Copyright (C) 2005 Armin Bauer * Copyright (C) 2008 Michael Bell * * 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 #include #include int client_connects; int client_disconnects; int client_receives; int client_errors; int server_connects; int server_disconnects; int server_receives; GList *links; void reset_testbed() { client_connects = 0; client_disconnects = 0; client_receives = 0; client_errors = 0; server_connects = 0; server_disconnects = 0; server_receives = 0; links = NULL; setup_testbed(NULL); } START_TEST (http_client_new) { reset_testbed(); GError *error = NULL; SmlTransport *tsp = smlTransportNew(SML_TRANSPORT_HTTP_CLIENT, &error); sml_fail_unless(tsp != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlTransportFree(tsp); } END_TEST START_TEST (http_client_init) { reset_testbed(); GError *error = NULL; SmlTransport *tsp = smlTransportNew(SML_TRANSPORT_HTTP_CLIENT, &error); sml_fail_unless(tsp != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlTransportSetConfigOption(tsp, "URL", "http://libsyncml.opensyncml.org", &error), "%s", GET_ERROR_MESSAGE(error)); sml_fail_unless(smlTransportInitialize(tsp, &error), "%s", GET_ERROR_MESSAGE(error)); sml_fail_unless(error == NULL, "%s", GET_ERROR_MESSAGE(error)); sml_fail_unless(smlTransportFinalize(tsp, &error), NULL); sml_fail_unless(error == NULL, NULL); smlTransportFree(tsp); } END_TEST /* TODO: Review if it's possible to fool libsoup with a wrong port. START_TEST (http_client_wrong_port) { reset_testbed(); GError *error = NULL; SmlTransport *tsp = smlTransportNew(SML_TRANSPORT_HTTP_CLIENT, &error); sml_fail_unless(tsp != NULL, NULL); sml_fail_unless(error == NULL, NULL); SmlTransportHttpClientConfig config; memset(&config, 0, sizeof(SmlTransportHttpClientConfig)); config.url = "http://libsyncml.opensync.org:-1/"; sml_fail_unless(!smlTransportInitialize(tsp, &config, &error), NULL); sml_fail_unless(error != NULL, NULL); SML_ERROR_FREE(error); smlTransportFree(tsp); } END_TEST */ START_TEST (http_client_init_no_url) { /* An HTTP client without an URL is an ERROR. */ reset_testbed(); GError *error = NULL; SmlTransport *tsp = smlTransportNew(SML_TRANSPORT_HTTP_CLIENT, &error); sml_fail_unless(tsp != NULL, NULL); sml_fail_unless(error == NULL, NULL); /* The port alone is a valid URL. */ sml_fail_unless(smlTransportSetConfigOption(tsp, "URL", "http://:80", &error), NULL); sml_fail_unless(error == NULL, NULL); /* The transport is not configured but libsoup can initialize a default client */ sml_fail_unless(smlTransportInitialize(tsp, &error), "%s", GET_ERROR_MESSAGE(error)); sml_fail_unless(error == NULL, "%s", GET_ERROR_MESSAGE(error)); sml_fail_unless(smlTransportFinalize(tsp, &error), "%s", GET_ERROR_MESSAGE(error)); sml_fail_unless(error == NULL, "%s", GET_ERROR_MESSAGE(error)); smlTransportFree(tsp); } END_TEST START_TEST (http_server_new) { reset_testbed(); GError *error = NULL; SmlTransport *tsp = smlTransportNew(SML_TRANSPORT_HTTP_SERVER, &error); sml_fail_unless(tsp != NULL, NULL); sml_fail_unless(error == NULL, NULL); smlTransportFree(tsp); } END_TEST gboolean _recv_client_event(SmlTransport *tsp, SmlLink *link_, SmlTransportEventType type, SmlTransportData *data, const GError *error, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %p, %d)", __func__, tsp, link_, type); sml_fail_unless(GPOINTER_TO_INT(userdata) == 1, NULL); switch (type) { case SML_TRANSPORT_EVENT_CONNECT_DONE: g_atomic_int_inc(&client_connects); break; case SML_TRANSPORT_EVENT_DISCONNECT_DONE: g_atomic_int_inc(&client_disconnects); break; case SML_TRANSPORT_EVENT_DATA: sml_fail_unless(!strcmp(data->data, "answer"), NULL); sml_fail_unless(data->size == 7, NULL); sml_fail_unless(data->type == SML_MIMETYPE_WBXML, NULL); g_atomic_int_inc(&client_receives); break; case SML_TRANSPORT_EVENT_ERROR: sml_fail_unless(error != NULL, NULL); g_atomic_int_inc(&client_errors); break; default: sml_fail_unless(FALSE, "An unexpected transport event %d was received.", type); break; } smlTrace(TRACE_EXIT, "%s()", __func__); return TRUE; } gboolean _recv_server_event(SmlTransport *tsp, SmlLink *link_, SmlTransportEventType type, SmlTransportData *data, const GError *error, void *userdata) { smlTrace(TRACE_ENTRY, "%s(%p, %d, %p)", __func__, link_, type, error); GError *locerror = NULL; SmlLink *last = NULL; switch (type) { case SML_TRANSPORT_EVENT_CONNECT_DONE: g_atomic_int_inc(&server_connects); links = g_list_append(links, link_); smlLinkRef(link_); break; case SML_TRANSPORT_EVENT_DISCONNECT_DONE: /* only real connections must be managed */ last = g_list_nth_data(links, g_list_length(links)-1); sml_fail_unless(last == link_, "The disconnected links do not match."); links = g_list_remove(links, last); smlLinkDeref(last); g_atomic_int_inc(&server_disconnects); break; case SML_TRANSPORT_EVENT_DATA: g_atomic_int_inc(&server_receives); if (!strcmp(data->data, "test")) { sml_fail_unless(data->size == 5, NULL); sml_fail_unless(data->type == SML_MIMETYPE_XML, NULL); sml_fail_unless(link_ != NULL, NULL); if (GPOINTER_TO_INT(userdata) == 1) { data = smlTransportDataNew((char *)"answer", 7, SML_MIMETYPE_WBXML, FALSE, &locerror); sml_fail_unless(data != NULL, NULL); sml_fail_unless(locerror == NULL, "%s", GET_ERROR_MESSAGE(locerror)); sml_fail_unless(smlTransportSend(tsp, link_, data, &locerror), "%s", GET_ERROR_MESSAGE(locerror)); smlTransportDataDeref(data); } else if (GPOINTER_TO_INT(userdata) == 2) { GError *newerror = NULL; SML_SET_ERROR(&newerror, SML_ERROR_GENERIC, "test"); smlTransportSendError(tsp, link_, newerror); SML_ERROR_FREE(newerror); } else if (GPOINTER_TO_INT(userdata) == 3) { sml_fail_unless(smlTransportDisconnect(tsp, link_, &locerror), "%s", GET_ERROR_MESSAGE(locerror)); } else { sml_fail_unless(FALSE, "Some unexpected userdata %i was detected.", GPOINTER_TO_INT(userdata)); } } else if (!strcmp(data->data, "error")) { sml_fail_unless(data->size == 6, NULL); sml_fail_unless(data->type == SML_MIMETYPE_XML, NULL); sml_fail_unless(link_ != NULL, NULL); GError *newerror = NULL; SML_SET_ERROR(&newerror, SML_ERROR_GENERIC, "test2"); smlTransportSendError(tsp, link_, newerror); SML_ERROR_FREE(newerror); } else { sml_fail_unless(FALSE, "The received data was not expected (%s).", data->data); } break; default: sml_fail_unless(FALSE, "An unexpected transport event %d was received.", type); break; } smlTrace(TRACE_EXIT, "%s()", __func__); return TRUE; } START_TEST (http_server_init) { reset_testbed(); GError *error = NULL; SmlTransport *tsp = smlTransportNew(SML_TRANSPORT_HTTP_SERVER, &error); sml_fail_unless(tsp != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlTransportSetConfigOption(tsp, "PORT", "32425", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(tsp, "URL", "/test", &error), NULL); smlTransportSetEventCallback(tsp, _recv_server_event, GINT_TO_POINTER(1)); sml_fail_unless(smlTransportInitialize(tsp, &error), "%s", GET_ERROR_MESSAGE(error)); sml_fail_unless(error == NULL, "%s", GET_ERROR_MESSAGE(error)); sml_fail_unless(smlTransportFinalize(tsp, &error), NULL); sml_fail_unless(error == NULL, NULL); smlTransportFree(tsp); } END_TEST START_TEST (http_server_wrong_port) { reset_testbed(); GError *error = NULL; SmlTransport *tsp = smlTransportNew(SML_TRANSPORT_HTTP_SERVER, &error); sml_fail_unless(tsp != NULL, NULL); sml_fail_unless(error == NULL, NULL); /* -1 is an illegal port. */ sml_fail_unless(smlTransportSetConfigOption(tsp, "PORT", "-1", &error) == FALSE, NULL); sml_fail_unless(error != NULL, NULL); SML_ERROR_FREE(error); /* The default config of libsoup can be used to setup a valid transport. */ sml_fail_unless(smlTransportInitialize(tsp, &error), "%s", GET_ERROR_MESSAGE(error)); sml_fail_unless(error == NULL, "%s", GET_ERROR_MESSAGE(error)); sml_fail_unless(smlTransportFinalize(tsp, &error), NULL); sml_fail_unless(error == NULL, NULL); smlTransportFree(tsp); } END_TEST START_TEST (http_connect) { reset_testbed(); GError *error = NULL; SmlTransport *server = smlTransportNew(SML_TRANSPORT_HTTP_SERVER, &error); SmlTransport *client = smlTransportNew(SML_TRANSPORT_HTTP_CLIENT, &error); sml_fail_unless(smlTransportSetConfigOption(client, "URL", "http://127.0.0.1:10008", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(server, "PORT", "10008", &error), NULL); smlTransportSetEventCallback(client, _recv_client_event, GINT_TO_POINTER(1)); smlTransportSetEventCallback(server, _recv_server_event, GINT_TO_POINTER(1)); sml_fail_unless(smlTransportInitialize(client, &error), "%s", GET_ERROR_MESSAGE(error)); sml_fail_unless(smlTransportInitialize(server, &error), "%s", GET_ERROR_MESSAGE(error)); sml_fail_unless(smlTransportConnect(client, &error), NULL); sml_fail_unless(error == NULL, NULL); while (client_connects == 0) { usleep(50); }; sml_fail_unless(client_connects == 1, NULL); sml_fail_unless(client_disconnects == 0, NULL); /* disconnect the client */ sml_fail_unless(smlTransportDisconnect(client, NULL, &error), "%s", GET_ERROR_MESSAGE(error)); sml_fail_unless(error == NULL, NULL); while (client_disconnects == 0) { usleep(50); }; sml_fail_unless(client_connects == 1, NULL); sml_fail_unless(client_disconnects == 1, NULL); /* cleanup the transports */ sml_fail_unless(smlTransportFinalize(server, &error), NULL); sml_fail_unless(smlTransportFinalize(client, &error), NULL); smlTransportFree(server); smlTransportFree(client); } END_TEST START_TEST (http_send) { reset_testbed(); GError *error = NULL; SmlTransport *server = smlTransportNew(SML_TRANSPORT_HTTP_SERVER, &error); SmlTransport *client = smlTransportNew(SML_TRANSPORT_HTTP_CLIENT, &error); sml_fail_unless(smlTransportSetConfigOption(client, "URL", "http://127.0.0.1:10009", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(server, "PORT", "10009", &error), NULL); smlTransportSetEventCallback(server, _recv_server_event, GINT_TO_POINTER(1)); smlTransportSetEventCallback(client, _recv_client_event, GINT_TO_POINTER(1)); sml_fail_unless(smlTransportInitialize(client, &error), "%s", GET_ERROR_MESSAGE(error)); sml_fail_unless(smlTransportInitialize(server, &error), "%s", GET_ERROR_MESSAGE(error)); SmlTransportData *data = smlTransportDataNew((char *)"test", 5, SML_MIMETYPE_XML, FALSE, &error); sml_fail_unless(data != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlTransportSend(client, NULL, data, &error), NULL); sml_fail_unless(error == NULL, NULL); smlTransportDataDeref(data); while(client_connects < 1) { usleep(50); } /* disconnect client */ sml_fail_unless(smlTransportDisconnect(client, NULL, &error), "%s", GET_ERROR_MESSAGE(error)); while(client_disconnects < 1) { usleep(50); } /* disconnect server */ sml_fail_unless(smlTransportDisconnect(server, g_list_nth_data(links, 0), &error), NULL); while(server_disconnects < 1) { usleep(50); } /* cleanup transports */ sml_fail_unless(smlTransportFinalize(server, &error), NULL); sml_fail_unless(smlTransportFinalize(client, &error), NULL); smlTransportFree(server); smlTransportFree(client); } END_TEST START_TEST (http_receive) { reset_testbed(); GError *error = NULL; SmlTransport *server = smlTransportNew(SML_TRANSPORT_HTTP_SERVER, &error); SmlTransport *client = smlTransportNew(SML_TRANSPORT_HTTP_CLIENT, &error); sml_fail_unless(smlTransportSetConfigOption(client, "URL", "http://127.0.0.1:10010", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(server, "PORT", "10010", &error), NULL); smlTransportSetEventCallback(server, _recv_server_event, GINT_TO_POINTER(3)); smlTransportSetEventCallback(client, _recv_client_event, GINT_TO_POINTER(1)); sml_fail_unless(smlTransportInitialize(client, &error), "%s", GET_ERROR_MESSAGE(error)); sml_fail_unless(smlTransportInitialize(server, &error), "%s", GET_ERROR_MESSAGE(error)); SmlTransportData *data = smlTransportDataNew((char *)"test", 5, SML_MIMETYPE_XML, FALSE, &error); sml_fail_unless(data != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlTransportSend(client, NULL, data, &error), NULL); sml_fail_unless(error == NULL, NULL); smlTransportDataDeref(data); while (server_receives < 1) { usleep(100); } sml_fail_unless(server_connects == 1, NULL); sml_fail_unless(server_receives == 1, NULL); /* the client must not be disconnected * because the server does not accept the connection */ while(server_disconnects < 1) { usleep(50); } /* cleanup transports */ sml_fail_unless(smlTransportFinalize(server, &error), NULL); sml_fail_unless(smlTransportFinalize(client, &error), NULL); smlTransportFree(server); smlTransportFree(client); } END_TEST START_TEST (http_reply) { reset_testbed(); GError *error = NULL; SmlTransport *server = smlTransportNew(SML_TRANSPORT_HTTP_SERVER, &error); SmlTransport *client = smlTransportNew(SML_TRANSPORT_HTTP_CLIENT, &error); sml_fail_unless(smlTransportSetConfigOption(client, "URL", "http://127.0.0.1:10011", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(server, "PORT", "10011", &error), NULL); smlTransportSetEventCallback(client, _recv_client_event, GINT_TO_POINTER(1)); smlTransportSetEventCallback(server, _recv_server_event, GINT_TO_POINTER(1)); sml_fail_unless(smlTransportInitialize(client, &error), "%s", GET_ERROR_MESSAGE(error)); sml_fail_unless(smlTransportInitialize(server, &error), "%s", GET_ERROR_MESSAGE(error)); SmlTransportData *data = smlTransportDataNew((char *)"test", 5, SML_MIMETYPE_XML, FALSE, &error); sml_fail_unless(data != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlTransportSend(client, NULL, data, &error), NULL); sml_fail_unless(error == NULL, NULL); smlTransportDataDeref(data); while (client_receives < 1) { usleep(100); } sml_fail_unless(client_receives == 1, NULL); sml_fail_unless(server_receives == 1, NULL); /* disconnect client */ sml_fail_unless(smlTransportDisconnect(client, NULL, &error), "%s", GET_ERROR_MESSAGE(error)); while(client_disconnects < 1) { usleep(50); } /* disconnect server */ sml_fail_unless(smlTransportDisconnect(server, g_list_nth_data(links, 0), &error), NULL); while(server_disconnects < 1) { usleep(50); } /* cleanup transports */ sml_fail_unless(smlTransportFinalize(server, &error), NULL); sml_fail_unless(smlTransportFinalize(client, &error), NULL); smlTransportFree(server); smlTransportFree(client); } END_TEST START_TEST (http_talk) { reset_testbed(); GError *error = NULL; SmlTransport *server = smlTransportNew(SML_TRANSPORT_HTTP_SERVER, &error); SmlTransport *client = smlTransportNew(SML_TRANSPORT_HTTP_CLIENT, &error); sml_fail_unless(smlTransportSetConfigOption(client, "URL", "http://127.0.0.1:10012", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(server, "PORT", "10012", &error), NULL); smlTransportSetEventCallback(client, _recv_client_event, GINT_TO_POINTER(1)); smlTransportSetEventCallback(server, _recv_server_event, GINT_TO_POINTER(1)); sml_fail_unless(smlTransportInitialize(client, &error), "%s", GET_ERROR_MESSAGE(error)); sml_fail_unless(smlTransportInitialize(server, &error), "%s", GET_ERROR_MESSAGE(error)); SmlTransportData *data = NULL; int i; for (i = 0; i < 20; i++) { data = smlTransportDataNew((char *)"test", 5, SML_MIMETYPE_XML, FALSE, &error); sml_fail_unless(data != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlTransportSend(client, NULL, data, &error), NULL); sml_fail_unless(error == NULL, NULL); smlTransportDataDeref(data); while (1) { usleep(100); if (client_receives == i+1) break; } } sml_fail_unless(client_receives == 20, NULL); sml_fail_unless(server_receives == 20, NULL); /* disconnect client */ sml_fail_unless(smlTransportDisconnect(client, NULL, &error), "%s", GET_ERROR_MESSAGE(error)); while(client_disconnects < 1) { usleep(50); } /* disconnect server */ for (i = 0; i < 20; i++) { /* start to disconnect from the end * to avoid conflicts with very fast SMP machines * which can process disconnects so fast * that the list will be cleaned up before * this for-loop ends */ smlTrace(TRACE_INTERNAL, "%s: Perparing next disconnect", __func__); sml_fail_unless(smlTransportDisconnect(server, g_list_nth_data(links, 19-i), &error), NULL); while(server_disconnects < i+1) { usleep(100); } } /* cleanup transports */ sml_fail_unless(smlTransportFinalize(server, &error), NULL); sml_fail_unless(smlTransportFinalize(client, &error), NULL); smlTransportFree(server); smlTransportFree(client); } END_TEST START_TEST (http_connect_error) { reset_testbed(); GError *error = NULL; SmlTransport *client = smlTransportNew(SML_TRANSPORT_HTTP_CLIENT, &error); sml_fail_unless(smlTransportSetConfigOption(client, "URL", "http://127.0.0.1:10013", &error), NULL); smlTransportSetEventCallback(client, _recv_client_event, GINT_TO_POINTER(1)); sml_fail_unless(smlTransportInitialize(client, &error), "%s", GET_ERROR_MESSAGE(error)); SmlTransportData *data = smlTransportDataNew((char *)"test", 5, SML_MIMETYPE_XML, FALSE, &error); sml_fail_unless(data != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlTransportSend(client, NULL, data, &error), NULL); sml_fail_unless(error == NULL, NULL); smlTransportDataDeref(data); while (client_errors == 0) { usleep(100); }; sml_fail_unless(client_connects == 0, NULL); sml_fail_unless(client_disconnects == 0, NULL); sml_fail_unless(client_receives == 0, NULL); sml_fail_unless(client_errors == 1, NULL); sml_fail_unless(smlTransportFinalize(client, &error), NULL); smlTransportFree(client); } END_TEST START_TEST (http_reject) { reset_testbed(); GError *error = NULL; SmlTransport *server = smlTransportNew(SML_TRANSPORT_HTTP_SERVER, &error); SmlTransport *client = smlTransportNew(SML_TRANSPORT_HTTP_CLIENT, &error); sml_fail_unless(smlTransportSetConfigOption(client, "URL", "http://127.0.0.1:10014", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(server, "PORT", "10014", &error), NULL); smlTransportSetEventCallback(client, _recv_client_event, GINT_TO_POINTER(1)); smlTransportSetEventCallback(server, _recv_server_event, GINT_TO_POINTER(2)); sml_fail_unless(smlTransportInitialize(client, &error), "%s", GET_ERROR_MESSAGE(error)); sml_fail_unless(smlTransportInitialize(server, &error), "%s", GET_ERROR_MESSAGE(error)); SmlTransportData *data = smlTransportDataNew((char *)"test", 5, SML_MIMETYPE_XML, FALSE, &error); sml_fail_unless(data != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlTransportSend(client, NULL, data, &error), NULL); sml_fail_unless(error == NULL, NULL); smlTransportDataDeref(data); while (server_receives == 0) { usleep(100); }; sml_fail_unless(server_receives == 1, NULL); while (client_errors == 0) { usleep(100); }; sml_fail_unless(smlTransportDisconnect(server, g_list_nth_data(links, 0), &error), NULL); while (server_disconnects == 0) { usleep(100); }; sml_fail_unless(client_connects == 0, NULL); sml_fail_unless(client_disconnects == 0, NULL); sml_fail_unless(client_receives == 0, NULL); sml_fail_unless(client_errors == 1, NULL); sml_fail_unless(server_disconnects == 1, NULL); sml_fail_unless(smlTransportFinalize(client, &error), NULL); sml_fail_unless(smlTransportFinalize(server, &error), "%s", GET_ERROR_MESSAGE(error)); smlTransportFree(client); smlTransportFree(server); } END_TEST START_TEST (http_multi_connect) { reset_testbed(); GError *error = NULL; SmlTransport *server = smlTransportNew(SML_TRANSPORT_HTTP_SERVER, &error); SmlTransport *client1 = smlTransportNew(SML_TRANSPORT_HTTP_CLIENT, &error); SmlTransport *client2 = smlTransportNew(SML_TRANSPORT_HTTP_CLIENT, &error); SmlTransport *client3 = smlTransportNew(SML_TRANSPORT_HTTP_CLIENT, &error); sml_fail_unless(smlTransportSetConfigOption(client1, "URL", "http://127.0.0.1:10015", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(client2, "URL", "http://127.0.0.1:10015", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(client3, "URL", "http://127.0.0.1:10015", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(server, "PORT", "10015", &error), NULL); smlTransportSetEventCallback(client1, _recv_client_event, GINT_TO_POINTER(1)); smlTransportSetEventCallback(client2, _recv_client_event, GINT_TO_POINTER(1)); smlTransportSetEventCallback(client3, _recv_client_event, GINT_TO_POINTER(1)); smlTransportSetEventCallback(server, _recv_server_event, GINT_TO_POINTER(1)); sml_fail_unless(smlTransportInitialize(client1, &error), "%s", GET_ERROR_MESSAGE(error)); sml_fail_unless(smlTransportInitialize(client2, &error), "%s", GET_ERROR_MESSAGE(error)); sml_fail_unless(smlTransportInitialize(client3, &error), "%s", GET_ERROR_MESSAGE(error)); sml_fail_unless(smlTransportInitialize(server, &error), "%s", GET_ERROR_MESSAGE(error)); SmlTransportData *data = smlTransportDataNew((char *)"test", 5, SML_MIMETYPE_XML, FALSE, &error); sml_fail_unless(data != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlTransportSend(client1, NULL, data, &error), NULL); sml_fail_unless(error == NULL, NULL); smlTransportDataDeref(data); /* It is necessary to perform the first request alone * because otherwise the test can fail on Solaris * because Solaris uses an outdated libsoup 2.2. */ while (client_receives != 1) { usleep(100); } data = smlTransportDataNew((char *)"test", 5, SML_MIMETYPE_XML, FALSE, &error); sml_fail_unless(data != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlTransportSend(client2, NULL, data, &error), NULL); sml_fail_unless(error == NULL, NULL); smlTransportDataDeref(data); data = smlTransportDataNew((char *)"test", 5, SML_MIMETYPE_XML, FALSE, &error); sml_fail_unless(data != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlTransportSend(client3, NULL, data, &error), NULL); sml_fail_unless(error == NULL, NULL); smlTransportDataDeref(data); while (client_receives != 3) { usleep(100); } sml_fail_unless(client_receives == 3, NULL); sml_fail_unless(server_receives == 3, NULL); sml_fail_unless(smlTransportDisconnect(client1, NULL, &error), "%s", GET_ERROR_MESSAGE(error)); sml_fail_unless(smlTransportDisconnect(client2, NULL, &error), "%s", GET_ERROR_MESSAGE(error)); sml_fail_unless(smlTransportDisconnect(client3, NULL, &error), "%s", GET_ERROR_MESSAGE(error)); while (client_disconnects < 3) { usleep(100); }; int i; for (i = g_list_length(links); i > 0; i--) { /* start to disconnect from the end * to avoid conflicts with very fast SMP machines * which can process disconnects so fast * that the list will be cleaned up before * this for-loop ends */ sml_fail_unless(smlTransportDisconnect(server, g_list_nth_data(links, i-1), &error), "%s", GET_ERROR_MESSAGE(error)); while (server_disconnects < 3 - i + 1) { usleep(100); } } sml_fail_unless(client_connects == 3, NULL); sml_fail_unless(server_connects == 3, NULL); sml_fail_unless(client_disconnects == 3, NULL); sml_fail_unless(server_disconnects == 3, NULL); sml_fail_unless(smlTransportFinalize(server, &error), NULL); sml_fail_unless(smlTransportFinalize(client1, &error), NULL); sml_fail_unless(smlTransportFinalize(client2, &error), NULL); sml_fail_unless(smlTransportFinalize(client3, &error), NULL); smlTransportFree(server); smlTransportFree(client1); smlTransportFree(client2); smlTransportFree(client3); } END_TEST START_TEST (http_multi_partial_error) { reset_testbed(); GError *error = NULL; SmlTransport *server = smlTransportNew(SML_TRANSPORT_HTTP_SERVER, &error); SmlTransport *client1 = smlTransportNew(SML_TRANSPORT_HTTP_CLIENT, &error); SmlTransport *client2 = smlTransportNew(SML_TRANSPORT_HTTP_CLIENT, &error); SmlTransport *client3 = smlTransportNew(SML_TRANSPORT_HTTP_CLIENT, &error); sml_fail_unless(smlTransportSetConfigOption(client1, "URL", "http://127.0.0.1:10016", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(client2, "URL", "http://127.0.0.1:10016", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(client3, "URL", "http://127.0.0.1:10016", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(server, "PORT", "10016", &error), NULL); smlTransportSetEventCallback(client1, _recv_client_event, GINT_TO_POINTER(1)); smlTransportSetEventCallback(client2, _recv_client_event, GINT_TO_POINTER(1)); smlTransportSetEventCallback(client3, _recv_client_event, GINT_TO_POINTER(1)); smlTransportSetEventCallback(server, _recv_server_event, GINT_TO_POINTER(1)); sml_fail_unless(smlTransportInitialize(client1, &error), "%s", GET_ERROR_MESSAGE(error)); sml_fail_unless(smlTransportInitialize(client2, &error), "%s", GET_ERROR_MESSAGE(error)); sml_fail_unless(smlTransportInitialize(client3, &error), "%s", GET_ERROR_MESSAGE(error)); sml_fail_unless(smlTransportInitialize(server, &error), "%s", GET_ERROR_MESSAGE(error)); SmlTransportData *data = smlTransportDataNew((char *)"test", 5, SML_MIMETYPE_XML, FALSE, &error); sml_fail_unless(data != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlTransportSend(client1, NULL, data, &error), NULL); sml_fail_unless(error == NULL, NULL); smlTransportDataDeref(data); /* It is necessary to perform the working request first * because otherwise the test can fail on Solaris * because Solaris uses an outdated libsoup 2.2. */ while (client_receives != 1) { usleep(100); } data = smlTransportDataNew((char *)"error", 6, SML_MIMETYPE_XML, FALSE, &error); sml_fail_unless(data != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlTransportSend(client2, NULL, data, &error), NULL); sml_fail_unless(error == NULL, NULL); smlTransportDataDeref(data); data = smlTransportDataNew((char *)"error", 6, SML_MIMETYPE_XML, FALSE, &error); sml_fail_unless(data != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlTransportSend(client3, NULL, data, &error), NULL); sml_fail_unless(error == NULL, NULL); smlTransportDataDeref(data); while (client_receives != 1 || client_errors != 2) { usleep(100); } sml_fail_unless(client_receives == 1, NULL); sml_fail_unless(client_errors == 2, NULL); sml_fail_unless(server_receives == 3, NULL); sml_fail_unless(smlTransportDisconnect(client1, NULL, &error), "%s", GET_ERROR_MESSAGE(error)); while (client_disconnects < 1) { usleep(100); } int i; for (i = g_list_length(links); i > 0; i--) { /* start to disconnect from the end * to avoid conflicts with very fast SMP machines * which can process disconnects so fast * that the list will be cleaned up before * this for-loop ends */ sml_fail_unless(smlTransportDisconnect(server, g_list_nth_data(links, i-1), &error), "%s", GET_ERROR_MESSAGE(error)); while (server_disconnects < 3 - i + 1) { usleep(100); } } sml_fail_unless(client_connects == 1, NULL); sml_fail_unless(server_connects == 3, NULL); sml_fail_unless(client_disconnects == 1, NULL); sml_fail_unless(server_disconnects == 3, NULL); sml_fail_unless(smlTransportFinalize(server, &error), NULL); sml_fail_unless(smlTransportFinalize(client1, &error), NULL); sml_fail_unless(smlTransportFinalize(client2, &error), NULL); sml_fail_unless(smlTransportFinalize(client3, &error), NULL); smlTransportFree(server); smlTransportFree(client1); smlTransportFree(client2); smlTransportFree(client3); } END_TEST START_TEST (http_multi_stress) { reset_testbed(); int num = 1000; GError *error = NULL; SmlTransport *server = smlTransportNew(SML_TRANSPORT_HTTP_SERVER, &error); SmlTransport *client1 = smlTransportNew(SML_TRANSPORT_HTTP_CLIENT, &error); SmlTransport *client2 = smlTransportNew(SML_TRANSPORT_HTTP_CLIENT, &error); SmlTransport *client3 = smlTransportNew(SML_TRANSPORT_HTTP_CLIENT, &error); sml_fail_unless(smlTransportSetConfigOption(client1, "URL", "http://127.0.0.1:10017", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(client2, "URL", "http://127.0.0.1:10017", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(client3, "URL", "http://127.0.0.1:10017", &error), NULL); sml_fail_unless(smlTransportSetConfigOption(server, "PORT", "10017", &error), NULL); smlTransportSetEventCallback(client1, _recv_client_event, GINT_TO_POINTER(1)); smlTransportSetEventCallback(client2, _recv_client_event, GINT_TO_POINTER(1)); smlTransportSetEventCallback(client3, _recv_client_event, GINT_TO_POINTER(1)); smlTransportSetEventCallback(server, _recv_server_event, GINT_TO_POINTER(1)); sml_fail_unless(smlTransportInitialize(client1, &error), "%s", GET_ERROR_MESSAGE(error)); sml_fail_unless(smlTransportInitialize(client2, &error), "%s", GET_ERROR_MESSAGE(error)); sml_fail_unless(smlTransportInitialize(client3, &error), "%s", GET_ERROR_MESSAGE(error)); sml_fail_unless(smlTransportInitialize(server, &error), "%s", GET_ERROR_MESSAGE(error)); SmlTransportData *data = NULL; int i; for (i = 0; i < num; i++) { data = smlTransportDataNew((char *)"test", 5, SML_MIMETYPE_XML, FALSE, &error); sml_fail_unless(data != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlTransportSend(client1, NULL, data, &error), NULL); sml_fail_unless(error == NULL, NULL); smlTransportDataDeref(data); /* It is necessary to perform the first request alone * because otherwise the test can fail on Solaris * because Solaris uses an outdated libsoup 2.2. */ while (client_receives < 1) { usleep(10); } data = smlTransportDataNew((char *)"test", 5, SML_MIMETYPE_XML, FALSE, &error); sml_fail_unless(data != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlTransportSend(client2, NULL, data, &error), NULL); sml_fail_unless(error == NULL, NULL); smlTransportDataDeref(data); data = smlTransportDataNew((char *)"test", 5, SML_MIMETYPE_XML, FALSE, &error); sml_fail_unless(data != NULL, NULL); sml_fail_unless(error == NULL, NULL); sml_fail_unless(smlTransportSend(client3, NULL, data, &error), NULL); sml_fail_unless(error == NULL, NULL); smlTransportDataDeref(data); while (1) { usleep(1); if (client_receives == (i+1)*3) break; } } sml_fail_unless(client_receives == 3 * num, NULL); sml_fail_unless(server_receives == 3 * num, NULL); sml_fail_unless(smlTransportDisconnect(client1, NULL, &error), "%s", GET_ERROR_MESSAGE(error)); sml_fail_unless(smlTransportDisconnect(client2, NULL, &error), "%s", GET_ERROR_MESSAGE(error)); sml_fail_unless(smlTransportDisconnect(client3, NULL, &error), "%s", GET_ERROR_MESSAGE(error)); for (i = g_list_length(links); i > 0; i--) { /* start to disconnect from the end * to avoid conflicts with very fast SMP machines * which can process disconnects so fast * that the list will be cleaned up before * this for-loop ends */ sml_fail_unless(smlTransportDisconnect(server, g_list_nth_data(links, i-1), &error), "%s", GET_ERROR_MESSAGE(error)); while (server_disconnects < (3 * num - i + 1)) { usleep(100); } } sml_fail_unless(client_connects == 3, NULL); sml_fail_unless(server_connects == 3 * num, NULL); sml_fail_unless(client_disconnects == 3, NULL); sml_fail_unless(server_disconnects == 3 * num, NULL); sml_fail_unless(smlTransportFinalize(server, &error), NULL); sml_fail_unless(smlTransportFinalize(client1, &error), NULL); sml_fail_unless(smlTransportFinalize(client2, &error), NULL); sml_fail_unless(smlTransportFinalize(client3, &error), NULL); smlTransportFree(server); smlTransportFree(client1); smlTransportFree(client2); smlTransportFree(client3); } END_TEST @SML_TESTCASE_CODE@