diff --git a/mms-lib/test/Makefile b/mms-lib/test/Makefile index f566ce9..74eb11a 100644 --- a/mms-lib/test/Makefile +++ b/mms-lib/test/Makefile @@ -11,4 +11,5 @@ all: @$(MAKE) -C test_retrieve $* @$(MAKE) -C test_retrieve_cancel $* @$(MAKE) -C test_retrieve_no_proxy $* + @$(MAKE) -C test_retrieve_order $* @$(MAKE) -C test_send $* diff --git a/mms-lib/test/common/test_connman.c b/mms-lib/test/common/test_connman.c index 4f63f31..595671f 100644 --- a/mms-lib/test/common/test_connman.c +++ b/mms-lib/test/common/test_connman.c @@ -38,6 +38,27 @@ G_DEFINE_TYPE(MMSConnManTest, mms_connman_test, MMS_TYPE_CONNMAN); #define MMS_CONNMAN_TEST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),\ MMS_TYPE_CONNMAN_TEST, MMSConnManTest)) +static +gboolean +mms_connman_test_busy_cb( + gpointer data) +{ + MMSConnManTest* test = MMS_CONNMAN_TEST(data); + mms_connman_busy_dec(&test->cm); + mms_connman_ref(&test->cm); + return G_SOURCE_REMOVE; +} + +static +void +mms_connman_test_make_busy( + MMSConnManTest* test) +{ + mms_connman_ref(&test->cm); + mms_connman_busy_inc(&test->cm); + g_idle_add(mms_connman_test_busy_cb, test); +} + void mms_connman_test_set_port( MMSConnMan* cm, @@ -74,6 +95,7 @@ mms_connman_test_close_connection( MMSConnManTest* test = MMS_CONNMAN_TEST(cm); if (test->conn) { MMS_DEBUG("Closing connection..."); + mms_connman_test_make_busy(test); mms_connection_close(test->conn); mms_connection_unref(test->conn); test->conn = NULL; @@ -111,6 +133,7 @@ mms_connman_test_open_connection( if (test->offline) { return NULL; } else { + mms_connman_test_make_busy(test); test->conn = mms_connection_test_new(imsi, test->port, test->proxy); if (test->connect_fn) test->connect_fn(test->connect_param); return mms_connection_ref(test->conn); diff --git a/mms-lib/test/common/test_handler.c b/mms-lib/test/common/test_handler.c index 3c1d475..bd275d0 100644 --- a/mms-lib/test/common/test_handler.c +++ b/mms-lib/test/common/test_handler.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2015 Jolla Ltd. + * Copyright (C) 2013-2016 Jolla Ltd. * Contact: Slava Monich * * This program is free software; you can redistribute it and/or modify @@ -30,10 +30,8 @@ typedef struct mms_handler_test { MMSDispatcher* dispatcher; mms_handler_test_prenotify_fn prenotify_fn; mms_handler_test_postnotify_fn postnotify_fn; - mms_handler_test_msgreceived_fn msgreceived_fn; void* prenotify_data; void* postnotify_data; - void* msgreceived_data; } MMSHandlerTest; typedef enum mms_handler_record_type { @@ -84,6 +82,19 @@ struct mms_handler_message_received_call { void* param; }; +enum mms_handler_signal { + SIGNAL_MESSAGE_RECEIVED, + SIGNAL_MESSAGE_RECEIVE_STATE_CHANGED, + SIGNAL_MESSAGE_SEND_STATE_CHANGED, + SIGNAL_COUNT +}; + +#define SIGNAL_MESSAGE_RECEIVED_NAME "message-received" +#define SIGNAL_MESSAGE_RECEIVE_STATE_CHANGED_NAME "receive-state-changed" +#define SIGNAL_MESSAGE_SEND_STATE_CHANGED_NAME "send-state-changed" + +static guint mms_handler_test_signals[SIGNAL_COUNT] = { 0 }; + G_DEFINE_TYPE(MMSHandlerTest, mms_handler_test, MMS_TYPE_HANDLER); #define MMS_TYPE_HANDLER_TEST (mms_handler_test_get_type()) #define MMS_HANDLER_TEST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \ @@ -569,9 +580,8 @@ mms_handler_test_message_received( recv->msg = mms_message_ref(msg); mms_handler_busy_inc(handler); - if (test->msgreceived_fn) { - test->msgreceived_fn(handler, msg, test->msgreceived_data); - } + g_signal_emit(handler, mms_handler_test_signals[ + SIGNAL_MESSAGE_RECEIVED], 0, msg); call->handler = mms_handler_ref(handler); call->msg = mms_message_ref(msg); @@ -596,6 +606,8 @@ mms_handler_test_message_receive_state_changed( if (recv) { recv->state = state; MMS_DEBUG("Message %s receive state %d", id, state); + g_signal_emit(handler, mms_handler_test_signals[ + SIGNAL_MESSAGE_RECEIVE_STATE_CHANGED], 0, id, state); return TRUE; } else { MMS_ERR("No such incoming message: %s", id); @@ -641,6 +653,8 @@ mms_handler_test_message_send_state_changed( } else { MMS_DEBUG("Message %s send state %d", id, state); } + g_signal_emit(handler, mms_handler_test_signals[ + SIGNAL_MESSAGE_SEND_STATE_CHANGED], 0, id, state, details); return TRUE; } else { MMS_ERR("No such outbound message: %s", id); @@ -768,6 +782,21 @@ mms_handler_test_class_init( klass->fn_read_report = mms_handler_test_read_report; klass->fn_read_report_send_status = mms_handler_test_read_report_send_status; + mms_handler_test_signals[SIGNAL_MESSAGE_RECEIVED] = + g_signal_new(SIGNAL_MESSAGE_RECEIVED_NAME, + G_OBJECT_CLASS_TYPE(klass), G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, NULL, G_TYPE_NONE, + 1, G_TYPE_POINTER); + mms_handler_test_signals[SIGNAL_MESSAGE_RECEIVE_STATE_CHANGED] = + g_signal_new(SIGNAL_MESSAGE_RECEIVE_STATE_CHANGED_NAME, + G_OBJECT_CLASS_TYPE(klass), G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, NULL, G_TYPE_NONE, + 2, G_TYPE_POINTER, G_TYPE_INT); + mms_handler_test_signals[SIGNAL_MESSAGE_SEND_STATE_CHANGED] = + g_signal_new(SIGNAL_MESSAGE_SEND_STATE_CHANGED_NAME, + G_OBJECT_CLASS_TYPE(klass), G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, NULL, G_TYPE_NONE, + 3, G_TYPE_POINTER, G_TYPE_INT, G_TYPE_POINTER); } static @@ -819,16 +848,34 @@ mms_handler_test_set_postnotify_fn( test->postnotify_data = user_data; } -void -mms_handler_test_set_msgreceived_fn( +gulong +mms_handler_test_add_msgreceived_fn( MMSHandler* handler, mms_handler_test_msgreceived_fn cb, void* user_data) { - MMSHandlerTest* test = MMS_HANDLER_TEST(handler); - MMS_ASSERT(!test->msgreceived_fn); - test->msgreceived_fn = cb; - test->msgreceived_data = user_data; + return g_signal_connect(handler, SIGNAL_MESSAGE_RECEIVED_NAME, + G_CALLBACK(cb), user_data); +} + +gulong +mms_handler_test_add_send_state_fn( + MMSHandler* handler, + mms_handler_test_send_state_fn cb, + void* user_data) +{ + return g_signal_connect(handler, SIGNAL_MESSAGE_SEND_STATE_CHANGED_NAME, + G_CALLBACK(cb), user_data); +} + +gulong +mms_handler_test_add_receive_state_fn( + MMSHandler* handler, + mms_handler_test_receive_state_fn cb, + void* user_data) +{ + return g_signal_connect(handler, SIGNAL_MESSAGE_RECEIVE_STATE_CHANGED_NAME, + G_CALLBACK(cb), user_data); } void @@ -843,8 +890,6 @@ mms_handler_test_reset( test->prenotify_data = NULL; test->postnotify_fn = NULL; test->postnotify_data = NULL; - test->msgreceived_fn = NULL; - test->msgreceived_data = NULL; } /* diff --git a/mms-lib/test/common/test_handler.h b/mms-lib/test/common/test_handler.h index e0db3a8..9319f21 100644 --- a/mms-lib/test/common/test_handler.h +++ b/mms-lib/test/common/test_handler.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2015 Jolla Ltd. + * Copyright (C) 2013-2016 Jolla Ltd. * Contact: Slava Monich * * This program is free software; you can redistribute it and/or modify @@ -116,6 +116,21 @@ typedef void MMSMessage* msg, void* user_data); +typedef void +(*mms_handler_test_receive_state_fn)( + MMSHandler* handler, + const char* id, + MMS_RECEIVE_STATE state, + void* user_data); + +typedef void +(*mms_handler_test_send_state_fn)( + MMSHandler* handler, + const char* id, + MMS_SEND_STATE state, + const char* details, + void* user_data); + void mms_handler_test_set_prenotify_fn( MMSHandler* handler, @@ -128,12 +143,24 @@ mms_handler_test_set_postnotify_fn( mms_handler_test_postnotify_fn cb, void* user_data); -void -mms_handler_test_set_msgreceived_fn( +gulong +mms_handler_test_add_msgreceived_fn( MMSHandler* handler, mms_handler_test_msgreceived_fn cb, void* user_data); +gulong +mms_handler_test_add_send_state_fn( + MMSHandler* handler, + mms_handler_test_send_state_fn cb, + void* user_data); + +gulong +mms_handler_test_add_receive_state_fn( + MMSHandler* handler, + mms_handler_test_receive_state_fn cb, + void* user_data); + void mms_handler_test_reset( MMSHandler* handler); diff --git a/mms-lib/test/common/test_http.c b/mms-lib/test/common/test_http.c index ce737fd..29a3fec 100644 --- a/mms-lib/test/common/test_http.c +++ b/mms-lib/test/common/test_http.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2014 Jolla Ltd. + * Copyright (C) 2013-2016 Jolla Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -18,17 +18,30 @@ #include -/* A single HTTP transaction */ +/* A single HTTP response */ +typedef struct test_http_response { + GMappedFile* file; + char* content_type; + int status; +} TestHttpResponse; + struct test_http { gint ref_count; SoupServer* server; - GMappedFile* resp_file; - GBytes* req_bytes; - int resp_status; - char* resp_content_type; + GPtrArray* responses; + GPtrArray* post_data; gboolean disconnected; + guint current_resp; }; +static +void +test_http_post_data_free( + gpointer data) +{ + soup_buffer_free((SoupBuffer*)data); +} + static void test_http_callback( @@ -39,6 +52,7 @@ test_http_callback( SoupClientContext* context, gpointer data) { + TestHttp* http = data; char* uri = soup_uri_to_string(soup_message_get_uri (msg), FALSE); MMS_VERBOSE("%s %s HTTP/1.%d", msg->method, uri, soup_message_get_http_version(msg)); @@ -46,29 +60,34 @@ test_http_callback( if (msg->method == SOUP_METHOD_CONNECT) { soup_message_set_status(msg, SOUP_STATUS_NOT_IMPLEMENTED); } else { - TestHttp* http = data; if (msg->request_body->length) { - SoupBuffer* request = soup_message_body_flatten(msg->request_body); - if (http->req_bytes) g_bytes_unref(http->req_bytes); - http->req_bytes = g_bytes_new_with_free_func(request->data, - request->length, (GDestroyNotify)soup_buffer_free, request); + SoupBuffer* post = soup_message_body_flatten(msg->request_body); + g_ptr_array_add(http->post_data, + g_bytes_new_with_free_func(post->data, post->length, + test_http_post_data_free, post)); } - soup_message_set_status(msg, http->resp_status); - soup_message_headers_set_content_type(msg->response_headers, - http->resp_content_type ? http->resp_content_type : "text/plain", - NULL); - soup_message_headers_append(msg->response_headers, - "Accept-Ranges", "bytes"); - soup_message_headers_append(msg->response_headers, - "Connection", "close"); - if (http->resp_file) { - soup_message_headers_set_content_length(msg->response_headers, - g_mapped_file_get_length(http->resp_file)); - soup_message_body_append(msg->response_body, SOUP_MEMORY_TEMPORARY, - g_mapped_file_get_contents(http->resp_file), - g_mapped_file_get_length(http->resp_file)); + if (http->current_resp >= http->responses->len) { + soup_message_set_status(msg, SOUP_STATUS_NOT_FOUND); } else { - soup_message_headers_set_content_length(msg->response_headers, 0); + const TestHttpResponse* resp = + http->responses->pdata[(http->current_resp)++]; + soup_message_set_status(msg, resp->status); + soup_message_headers_set_content_type(msg->response_headers, + resp->content_type ? resp->content_type : "text/plain", NULL); + soup_message_headers_append(msg->response_headers, + "Accept-Ranges", "bytes"); + soup_message_headers_append(msg->response_headers, + "Connection", "close"); + if (resp->file) { + soup_message_headers_set_content_length(msg->response_headers, + g_mapped_file_get_length(resp->file)); + soup_message_body_append(msg->response_body, + SOUP_MEMORY_TEMPORARY, + g_mapped_file_get_contents(resp->file), + g_mapped_file_get_length(resp->file)); + } else { + soup_message_headers_set_content_length(msg->response_headers,0); + } } } soup_message_body_complete(msg->request_body); @@ -81,11 +100,27 @@ test_http_get_port( return soup_server_get_port(http->server); } +guint +test_http_get_post_count( + TestHttp* http) +{ + return http ? http->post_data->len : 0; +} + +GBytes* +test_http_get_post_data_at( + TestHttp* http, + guint index) +{ + return (http && index < http->post_data->len) ? + http->post_data->pdata[index] : NULL; +} + GBytes* test_http_get_post_data( TestHttp* http) { - return http ? http->req_bytes : NULL; + return (http && http->post_data->len) ? http->post_data->pdata[0] : NULL; } void @@ -98,23 +133,60 @@ test_http_close( } } +static +void +test_http_post_data_bytes_free( + gpointer data) +{ + g_bytes_unref(data); +} + +static +void +test_http_response_free( + gpointer data) +{ + TestHttpResponse* resp = data; + if (resp->file) { + g_mapped_file_unref(resp->file); + g_free(resp->content_type); + } + g_free(resp); +} + +void +test_http_add_response( + TestHttp* http, + GMappedFile* file, + const char* content_type, + int status) +{ + TestHttpResponse* resp = g_new0(TestHttpResponse, 1); + if (file) { + resp->file = g_mapped_file_ref(file); + resp->content_type = g_strdup(content_type); + } + resp->status = status; + g_ptr_array_add(http->responses, resp); +} + TestHttp* test_http_new( - GMappedFile* resp_file, + GMappedFile* get_file, const char* resp_content_type, int resp_status) { TestHttp* http = g_new0(TestHttp, 1); http->ref_count = 1; - if (resp_file) { - http->resp_file = g_mapped_file_ref(resp_file); - http->resp_content_type = g_strdup(resp_content_type); - } - http->resp_status = resp_status; + http->responses = g_ptr_array_new_full(0, test_http_response_free); + http->post_data = g_ptr_array_new_full(0, test_http_post_data_bytes_free); http->server = g_object_new(SOUP_TYPE_SERVER, NULL); MMS_DEBUG("Listening on port %hu", soup_server_get_port(http->server)); soup_server_add_handler(http->server, NULL, test_http_callback, http, NULL); soup_server_run_async(http->server); + if (get_file || resp_content_type || resp_status) { + test_http_add_response(http, get_file, resp_content_type, resp_status); + } return http; } @@ -137,10 +209,9 @@ test_http_unref( MMS_ASSERT(http->ref_count > 0); if (g_atomic_int_dec_and_test(&http->ref_count)) { test_http_close(http); - if (http->resp_file) g_mapped_file_unref(http->resp_file); - if (http->req_bytes) g_bytes_unref(http->req_bytes); + g_ptr_array_unref(http->responses); + g_ptr_array_unref(http->post_data); g_object_unref(http->server); - g_free(http->resp_content_type); g_free(http); } } diff --git a/mms-lib/test/common/test_http.h b/mms-lib/test/common/test_http.h index c0af890..cb65320 100644 --- a/mms-lib/test/common/test_http.h +++ b/mms-lib/test/common/test_http.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2014 Jolla Ltd. + * Copyright (C) 2013-2016 Jolla Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -38,6 +38,22 @@ guint test_http_get_port( TestHttp* http); +void +test_http_add_response( + TestHttp* http, + GMappedFile* file, + const char* content_type, + int status); + +guint +test_http_get_post_count( + TestHttp* http); + +GBytes* +test_http_get_post_data_at( + TestHttp* http, + guint index); + GBytes* test_http_get_post_data( TestHttp* http); diff --git a/mms-lib/test/coverage/run b/mms-lib/test/coverage/run index 92e1a0b..9c67556 100755 --- a/mms-lib/test/coverage/run +++ b/mms-lib/test/coverage/run @@ -5,7 +5,8 @@ TESTS="test_media_type test_mms_codec test_delivery_ind \ test_read_ind test_read_report test_resize test_retrieve \ -test_retrieve_cancel test_retrieve_no_proxy test_send" +test_retrieve_cancel test_retrieve_no_proxy test_retrieve_order \ +test_send" FLAVOR="release" pushd `dirname $0` > /dev/null diff --git a/mms-lib/test/test_retrieve/test_retrieve.c b/mms-lib/test/test_retrieve/test_retrieve.c index 1be15af..db0a25b 100644 --- a/mms-lib/test/test_retrieve/test_retrieve.c +++ b/mms-lib/test/test_retrieve/test_retrieve.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2015 Jolla Ltd. + * Copyright (C) 2013-2016 Jolla Ltd. * Contact: Slava Monich * * This program is free software; you can redistribute it and/or modify @@ -76,6 +76,7 @@ typedef struct test { GMappedFile* retrieve_conf; GMainLoop* loop; guint timeout_id; + gulong msgreceived_id; TestHttp* http; int ret; } Test; @@ -500,6 +501,7 @@ test_finish( } MMS_INFO("%s: %s", (test->ret == RET_OK) ? "OK" : "FAILED", name); mms_handler_test_reset(test->handler); + g_signal_handler_disconnect(test->handler, test->msgreceived_id); g_main_loop_quit(test->loop); } @@ -627,8 +629,9 @@ test_init( mms_handler_test_defer_receive(test->handler, test->disp); } mms_handler_test_set_prenotify_fn(test->handler, test_notify, test); - mms_handler_test_set_msgreceived_fn(test->handler, - test_msgreceived, test); + test->msgreceived_id = + mms_handler_test_add_msgreceived_fn(test->handler, + test_msgreceived, test); mms_settings_unref(settings); test->ret = RET_ERR; ok = TRUE; diff --git a/mms-lib/test/test_retrieve_order/Makefile b/mms-lib/test/test_retrieve_order/Makefile new file mode 100644 index 0000000..41cad99 --- /dev/null +++ b/mms-lib/test/test_retrieve_order/Makefile @@ -0,0 +1,7 @@ +# -*- Mode: makefile-gmake -*- + +EXE = test_retrieve_order +SRC = $(EXE).c +COMMON_SRC = test_connection.c test_connman.c test_handler.c test_http.c + +include ../common/Makefile diff --git a/mms-lib/test/test_retrieve_order/data/Order/m-notification1.ind b/mms-lib/test/test_retrieve_order/data/Order/m-notification1.ind new file mode 100644 index 0000000..820e689 Binary files /dev/null and b/mms-lib/test/test_retrieve_order/data/Order/m-notification1.ind differ diff --git a/mms-lib/test/test_retrieve_order/data/Order/m-notification2.ind b/mms-lib/test/test_retrieve_order/data/Order/m-notification2.ind new file mode 100644 index 0000000..38b8604 Binary files /dev/null and b/mms-lib/test/test_retrieve_order/data/Order/m-notification2.ind differ diff --git a/mms-lib/test/test_retrieve_order/data/Order/m-retrieve1.conf b/mms-lib/test/test_retrieve_order/data/Order/m-retrieve1.conf new file mode 100644 index 0000000..20271e7 Binary files /dev/null and b/mms-lib/test/test_retrieve_order/data/Order/m-retrieve1.conf differ diff --git a/mms-lib/test/test_retrieve_order/data/Order/m-retrieve2.conf b/mms-lib/test/test_retrieve_order/data/Order/m-retrieve2.conf new file mode 100644 index 0000000..b2b637a Binary files /dev/null and b/mms-lib/test/test_retrieve_order/data/Order/m-retrieve2.conf differ diff --git a/mms-lib/test/test_retrieve_order/test_retrieve_order.c b/mms-lib/test/test_retrieve_order/test_retrieve_order.c new file mode 100644 index 0000000..83651d6 --- /dev/null +++ b/mms-lib/test/test_retrieve_order/test_retrieve_order.c @@ -0,0 +1,435 @@ +/* + * Copyright (C) 2016 Jolla Ltd. + * Contact: Slava Monich + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "test_connman.h" +#include "test_handler.h" +#include "test_http.h" + +#include "mms_codec.h" +#include "mms_file_util.h" +#include "mms_lib_log.h" +#include "mms_lib_util.h" +#include "mms_settings.h" +#include "mms_dispatcher.h" + +#include + +#define RET_OK (0) +#define RET_ERR (1) +#define RET_TIMEOUT (2) + +#define DATA_DIR "data/" + +#define TEST_TIMEOUT (10) /* seconds */ + +#define TEST_ARRAY_AND_COUNT(a) a, G_N_ELEMENTS(a) + +typedef struct test_receive_state { + const char* id; + MMS_RECEIVE_STATE state; +} TestReceiveState; + +typedef struct test_receive_state_event { + char* id; + MMS_RECEIVE_STATE state; +} TestReceiveStateEvent; + +typedef struct test_message_files { + const char* notification_ind; + const char* retrieve_conf; +} TestMessageFiles; + +typedef struct test_mapped_files { + GMappedFile* notification_ind; + GMappedFile* retrieve_conf; +} TestMappedFiles; + +typedef struct test_desc { + const char* name; + const TestMessageFiles* message_files; + unsigned int num_message_files; + const TestReceiveState* receive_states; + unsigned int num_receive_states; + int flags; +} TestDesc; + +typedef struct test { + const TestDesc* desc; + const MMSConfig* config; + MMSDispatcherDelegate delegate; + MMSConnMan* cm; + MMSHandler* handler; + MMSDispatcher* disp; + GMainLoop* loop; + GPtrArray* files; + GPtrArray* receive_states; + guint timeout_id; + gulong receive_state_event_id; + TestHttp* http; + int ret; +} Test; + +static const TestMessageFiles test1_files[] = { + { "m-notification1.ind", "m-retrieve1.conf" }, + { "m-notification2.ind", "m-retrieve2.conf" } +}; + +static const TestReceiveState test1_receive_states[] = { + { "1", MMS_RECEIVE_STATE_RECEIVING }, + { "1", MMS_RECEIVE_STATE_DECODING }, + { "2", MMS_RECEIVE_STATE_RECEIVING }, + { "2", MMS_RECEIVE_STATE_DECODING } +}; + +static const TestDesc retrieve_order_tests[] = { + { + "Order", + TEST_ARRAY_AND_COUNT(test1_files), + TEST_ARRAY_AND_COUNT(test1_receive_states) + } +}; + +static +void +test_free_receive_state( + gpointer data) +{ + TestReceiveStateEvent* event = data; + g_free(event->id); + g_free(event); +} + +static +void +test_finish( + Test* test) +{ + const TestDesc* desc = test->desc; + const char* name = desc->name; + if (test->ret == RET_OK) { + guint n = test->receive_states->len; + if (n != desc->num_receive_states) { + MMS_ERR("Unexpected number of state changes %u", n); + test->ret = RET_ERR; + } else { + guint i; + for (i=0; ireceive_states->pdata[i]; + const TestReceiveState* expected = desc->receive_states + i; + if (g_strcmp0(event->id, expected->id)) { + MMS_ERR("Unexpected task id %s at %u", event->id, i); + test->ret = RET_ERR; + } + if (event->state != expected->state) { + MMS_ERR("Unexpected state %d at %u", event->state, i); + test->ret = RET_ERR; + } + } + } + } + MMS_INFO("%s: %s", (test->ret == RET_OK) ? "OK" : "FAILED", name); + mms_handler_test_reset(test->handler); + g_signal_handler_disconnect(test->handler, test->receive_state_event_id); + g_main_loop_quit(test->loop); +} + +static +void +test_done( + MMSDispatcherDelegate* delegate, + MMSDispatcher* dispatcher) +{ + Test* test = MMS_CAST(delegate,Test,delegate); + if (!mms_handler_test_receive_pending(test->handler, NULL)) { + test_finish(test); + } +} + +static +gboolean +test_timeout( + gpointer data) +{ + Test* test = data; + test->timeout_id = 0; + test->ret = RET_TIMEOUT; + MMS_INFO("%s TIMEOUT", test->desc->name); + if (test->http) test_http_close(test->http); + mms_connman_test_close_connection(test->cm); + mms_dispatcher_cancel(test->disp, NULL); + return FALSE; +} + +static +void +test_receive_state_changed( + MMSHandler* handler, + const char* id, + MMS_RECEIVE_STATE state, + void* user_data) +{ + Test* test = user_data; + TestReceiveStateEvent* event = g_new0(TestReceiveStateEvent, 1); + event->id = g_strdup(id); + event->state = state; + g_ptr_array_add(test->receive_states, event); +} + +static +void +test_free_mapped_files( + gpointer data) +{ + TestMappedFiles* files = data; + g_mapped_file_unref(files->notification_ind); + g_mapped_file_unref(files->retrieve_conf); + g_free(files); +} + +static +gboolean +test_init( + Test* test, + const MMSConfig* config, + const TestDesc* desc, + gboolean debug) +{ + guint i; + MMSSettings* settings = mms_settings_default_new(config); + + MMS_DEBUG(">>>>>>>>>> %s <<<<<<<<<<", desc->name); + memset(test, 0, sizeof(*test)); + test->config = config; + test->files = g_ptr_array_new_full(0, test_free_mapped_files); + test->receive_states = g_ptr_array_new_full(0, test_free_receive_state); + test->http = test_http_new(NULL, NULL, SOUP_STATUS_NONE); + + /* Open files */ + for (i=0; inum_message_files; i++) { + GError* err = NULL; + const char* subdir = desc->name; + char* ni = g_strconcat(DATA_DIR, subdir, "/", + desc->message_files[i].notification_ind, NULL); + char* rc = g_strconcat(DATA_DIR, subdir, "/", + desc->message_files[i].retrieve_conf, NULL); + TestMappedFiles* files = g_new0(TestMappedFiles, 1); + files->notification_ind = g_mapped_file_new(ni, FALSE, &err); + if (err) { + MMS_ERR("%s", MMS_ERRMSG(err)); + g_error_free(err); + err = NULL; + } + files->retrieve_conf = g_mapped_file_new(rc, FALSE, &err); + test_http_add_response(test->http, files->retrieve_conf, + MMS_CONTENT_TYPE, SOUP_STATUS_OK); + /* Add empty responses for ack */ + test_http_add_response(test->http, NULL, NULL, SOUP_STATUS_OK); + if (err) { + MMS_ERR("%s", MMS_ERRMSG(err)); + g_error_free(err); + err = NULL; + } + g_ptr_array_add(test->files, files); + g_free(ni); + g_free(rc); + } + + test->desc = desc; + test->cm = mms_connman_test_new(); + test->handler = mms_handler_test_new(); + test->disp = mms_dispatcher_new(settings, test->cm, test->handler); + test->loop = g_main_loop_new(NULL, FALSE); + if (!debug) { + test->timeout_id = g_timeout_add_seconds(TEST_TIMEOUT, + test_timeout, test); + } + test->delegate.fn_done = test_done; + mms_dispatcher_set_delegate(test->disp, &test->delegate); + mms_connman_test_set_port(test->cm, test_http_get_port(test->http), TRUE); + + test->receive_state_event_id = + mms_handler_test_add_receive_state_fn(test->handler, + test_receive_state_changed, test); + + test->ret = RET_OK; + return TRUE; +} + +static +void +test_finalize( + Test* test) +{ + if (test->timeout_id) { + g_source_remove(test->timeout_id); + test->timeout_id = 0; + } + if (test->http) { + test_http_close(test->http); + test_http_unref(test->http); + } + mms_connman_test_close_connection(test->cm); + mms_connman_unref(test->cm); + mms_handler_unref(test->handler); + mms_dispatcher_unref(test->disp); + g_main_loop_unref(test->loop); + g_ptr_array_unref(test->files); + g_ptr_array_unref(test->receive_states); +} + +static +int +test_order_once( + const MMSConfig* config, + const TestDesc* desc, + gboolean debug) +{ + Test test; + if (test_init(&test, config, desc, debug)) { + guint i; + for (i=0; ilen && test.ret == RET_OK; i++) { + TestMappedFiles* files = test.files->pdata[i]; + GError* error = NULL; + GBytes* push = g_bytes_new_static( + g_mapped_file_get_contents(files->notification_ind), + g_mapped_file_get_length(files->notification_ind)); + if (!mms_dispatcher_handle_push(test.disp, "TestConnection", + push, &error)) { + g_error_free(error); + test.ret = RET_ERR; + } + g_bytes_unref(push); + } + if (test.ret == RET_OK) { + if (mms_dispatcher_start(test.disp)) { + g_main_loop_run(test.loop); + } else { + test.ret = RET_ERR; + } + } + if (test.ret != RET_OK) { + MMS_INFO("FAILED: %s", desc->name); + } + test_finalize(&test); + return test.ret; + } else { + return RET_ERR; + } +} + +static +int +test_order( + const MMSConfig* config, + const char* name, + gboolean debug) +{ + int i, ret; + if (name) { + const TestDesc* found = NULL; + for (i=0, ret = RET_ERR; iname, name)) { + ret = test_order_once(config, test, debug); + found = test; + break; + } + } + if (!found) MMS_ERR("No such test: %s", name); + } else { + for (i=0, ret = RET_OK; i