[Spice-devel] [spice-gtk v4 21/24] tests: file-transfer include simple tests
Jonathon Jongsma
jjongsma at redhat.com
Tue Jun 28 16:09:43 UTC 2016
On Thu, 2016-06-23 at 19:37 +0200, Victor Toso wrote:
> This only includes a simple test for file-transfer with a small
> summary of the possible situations of the test.
>
> As the test is specifically for SpiceFileTransferTask, we don't create
> a SpiceMainChannel. That could cause a simple crash on CHANNEL_DEBUG
> which this patch addresses.
> ---
> tests/Makefile.am | 2 +
> tests/file-transfer.c | 183
> ++++++++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 185 insertions(+)
> create mode 100644 tests/file-transfer.c
>
> diff --git a/tests/Makefile.am b/tests/Makefile.am
> index 1a8b768..6d9cfeb 100644
> --- a/tests/Makefile.am
> +++ b/tests/Makefile.am
> @@ -5,6 +5,7 @@ TESTS = coroutine \
> util \
> session \
> test-spice-uri \
> + test-file-transfer \
> $(NULL)
>
> if WITH_PHODAV
> @@ -38,6 +39,7 @@ coroutine_SOURCES = coroutine.c
> session_SOURCES = session.c
> pipe_SOURCES = pipe.c
> test_spice_uri_SOURCES = uri.c
> +test_file_transfer_SOURCES = file-transfer.c
> usb_acl_helper_SOURCES = usb-acl-helper.c
> usb_acl_helper_CFLAGS = -DTESTDIR=\"$(abs_builddir)\"
> mock_acl_helper_SOURCES = mock-acl-helper.c
> diff --git a/tests/file-transfer.c b/tests/file-transfer.c
> new file mode 100644
> index 0000000..6ef178b
> --- /dev/null
> +++ b/tests/file-transfer.c
> @@ -0,0 +1,183 @@
> +#include <gio/gio.h>
> +
> +#include "spice-file-transfer-task-priv.h"
> +
> +typedef struct _Fixture {
> + GFile **files;
> + guint num_files;
> + guint num_files_done;
> + GCancellable *cancellable;
> + GMainLoop *loop;
> + GHashTable *xfer_task_ht;
I think I said this in an earlier patch, but I don't really like "embedding" the
type into the variable name. So something like xfer_tasks would be better than
xfer_task_ht, in my opinion.
> +} Fixture;
> +
> +typedef struct _AgentAsync {
> + SpiceFileTransferTask *xfer_task;
> + VDAgentFileXferStatusMessage msg;
> +} AgentAsync;
> +
> +#define SINGLE_FILE 1
> +#define MULTIPLE_FILES 10
> +
> +#define T10ns (G_TIME_SPAN_MILLISECOND / 100)
> +
> +const gchar content[] = "0123456789_spice-file-transfer-task";
> +
> +static void
> +f_setup(Fixture *f, gconstpointer user_data)
> +{
> + gint i;
> + GError *err = NULL;
> +
> + f->loop = g_main_loop_new(NULL, FALSE);
> + f->num_files = GPOINTER_TO_UINT(user_data);
> + f->num_files_done = 0;
> + f->files = g_new0(GFile *, f->num_files + 1);
> + f->cancellable = g_cancellable_new();
> + for (i = 0; i < f->num_files; i++) {
> + gboolean success;
> + GFileIOStream *iostream;
> +
> + f->files[i] = g_file_new_tmp("spice-file-transfer-XXXXXX", &iostream,
> &err);
> + g_assert_no_error(err);
> + g_assert_nonnull(iostream);
> + g_clear_object(&iostream);
> +
> + success = g_file_replace_contents (f->files[i], content,
> strlen(content), NULL, FALSE,
> + G_FILE_CREATE_NONE, NULL, f-
> >cancellable, &err);
> + g_assert_no_error(err);
> + g_assert_true(success);
> + }
> +}
> +
> +static void
> +f_teardown(Fixture *f, gconstpointer user_data)
> +{
> + gint i;
> + GError *err = NULL;
> +
> + g_main_loop_unref(f->loop);
> + g_clear_object(&f->cancellable);
> + g_clear_pointer(&f->xfer_task_ht, g_hash_table_unref);
> +
> + for (i = 0; i < f->num_files; i++) {
> + g_file_delete(f->files[i], NULL, &err);
> + g_assert_no_error(err);
> + g_object_unref(f->files[i]);
> + }
> + g_clear_pointer(&f->files, g_free);
> +}
> +
> +/****************************************************************************
> ***
> + * TEST SIMPLE TRANSFER
> +
> ******************************************************************************
> /
> +static void
> +transfer_xfer_task_on_finished(SpiceFileTransferTask *xfer_task,
> + GError *error,
> + gpointer user_data)
> +{
> + Fixture *f = user_data;
> +
> + f->num_files_done++;
> + if (f->num_files == f->num_files_done)
> + g_main_loop_quit(f->loop);
> +}
> +
> +static void
> +transfer_read_async_cb(GObject *source_object,
> + GAsyncResult *res,
> + gpointer user_data)
> +{
> + SpiceFileTransferTask *xfer_task;
> + gssize count;
> + char *buffer;
> + GError *error = NULL;
> +
> + xfer_task = SPICE_FILE_TRANSFER_TASK(source_object);
> + count = spice_file_transfer_task_read_finish(xfer_task, res, &buffer,
> &error);
> + g_assert_no_error(error);
> +
> + if (count == 0) {
> + spice_file_transfer_task_completed(xfer_task, NULL);
> + return;
> + }
> +
> + spice_file_transfer_task_read_async(xfer_task, transfer_read_async_cb,
> NULL);
> +}
> +
> +static void
> +transfer_init_async_cb(GObject *obj, GAsyncResult *res, gpointer data)
> +{
> + GFileInfo *info;
> + SpiceFileTransferTask *xfer_task;
> + GError *error = NULL;
> +
> + xfer_task = SPICE_FILE_TRANSFER_TASK(obj);
> + info = spice_file_transfer_task_init_task_finish(xfer_task, res, &error);
> + g_assert_no_error(error);
> + g_assert_nonnull(info);
> +
> + /* read file loop */
> + spice_file_transfer_task_read_async(xfer_task, transfer_read_async_cb,
> NULL);
> +}
> +
> +static void
> +test_simple_transfer(Fixture *f, gconstpointer user_data)
> +{
> + GHashTableIter iter;
> + gpointer key, value;
> +
> + f->xfer_task_ht = spice_file_transfer_task_create_tasks(f->files, NULL,
> G_FILE_COPY_NONE, f->cancellable);
> + g_hash_table_iter_init(&iter, f->xfer_task_ht);
> + while (g_hash_table_iter_next(&iter, &key, &value)) {
> + SpiceFileTransferTask *xfer_task = SPICE_FILE_TRANSFER_TASK(value);
> + g_signal_connect(xfer_task, "finished",
> G_CALLBACK(transfer_xfer_task_on_finished), f);
> + spice_file_transfer_task_init_task_async(xfer_task,
> transfer_init_async_cb, NULL);
> + }
> + g_main_loop_run (f->loop);
> +}
> +
> +/* Tests summary:
Most of the following description appears to be from an earlier version of the
patch series and probably needs a bit of an update
> + *
> + * This tests are specific to SpiceFileTransferTask and how it handles the
> + * Cancelation from the client and Cancelation/Error that it can receive from
> + * the agent.
> + *
> + * Thanks to the helper spice_file_transfer_task_handle_status, we can
> simulate
> + * the agent responde fairly easy by calling this function with the expected
type: "responde"
> + * message from agent in the test case.
> + *
> + * Small overview of how File Transfer works.
> + *
> + * 1.) User calls spice_main_file_copy_async with a list of files to send to
> the
> + * guest
> + * 2.) Channel-Main creates a SpiceFileTransferTask per File, with a
> + * flush_callback() function which is used to send data to the Agent.
> + * 3.) Channel-Main attach handlers to SpiceFileTransferTask signals such as
> + * - "file-info": needed to retrieve file information and to send this
> + * information to the Agent. The file-transfer protocol starts here
> with
> + * VD_AGENT_FILE_XFER_START message;
> + * - "finalized": needed to finalize the operation and resources used;
> + * 4-) Channel-Main start each task by calling
> spice_file_transfer_task_start_task()
> + * which starts the async IO read from the file.
> + * 5-) SpiceFileTransferTask calls flush_callback() everytime data is ready
> + * 6-) Channel-Main sends data to the agent and waits for
> + * VD_AGENT_FILE_XFER_STATUS_CAN_SEND_DATA (to send more data) or
> + * VD_AGENT_FILE_XFER_STATUS_SUCCESS in case transfer of specific file is
> over.
> + * 7-) SpiceFileTransferTask only finalizes its operation when receives
> success,
> + * error or cancel from Agent or upon cancel from client.
> + */
> +int main(int argc, char* argv[])
> +{
> + g_test_init(&argc, &argv, NULL);
> +
> + g_test_add("/spice-file-transfer-task/single/simple-transfer",
> + Fixture, GUINT_TO_POINTER(SINGLE_FILE),
> + f_setup, test_simple_transfer, f_teardown);
> +
> + g_test_add("/spice-file-transfer-task/multiple/simple-transfer",
> + Fixture, GUINT_TO_POINTER(MULTIPLE_FILES),
> + f_setup, test_simple_transfer, f_teardown);
> +
> + return g_test_run();
> +}
So, at the moment, this only tests that we can read the files via the
SpiceFileTransferTask interface. That's not super useful by itself, but I guess
following patches will add to it.
Reviewed-by: Jonathon Jongsma <jjongsma at redhat.com>
More information about the Spice-devel
mailing list