[Spice-commits] cfg.mk server/tests
Frediano Ziglio
fziglio at kemper.freedesktop.org
Fri Nov 25 13:53:06 UTC 2016
cfg.mk | 2
server/tests/Makefile.am | 78 +-
server/tests/basic-event-loop.c | 137 +++
server/tests/basic-event-loop.h | 29
server/tests/basic_event_loop.c | 137 ---
server/tests/basic_event_loop.h | 29
server/tests/regression-test.py | 25
server/tests/regression_test.py | 25
server/tests/replay.c | 2
server/tests/spice-codecs-parsing-test.c | 131 ---
server/tests/spice-options-test.c | 61 -
server/tests/stat-file-test.c | 105 --
server/tests/stream-test.c | 157 ----
server/tests/test-codecs-parsing.c | 131 +++
server/tests/test-display-base.c | 932 ++++++++++++++++++++++++
server/tests/test-display-base.h | 146 +++
server/tests/test-display-no-ssl.c | 72 +
server/tests/test-display-resolution-changes.c | 86 ++
server/tests/test-display-streaming.c | 253 ++++++
server/tests/test-display-width-stride.c | 121 +++
server/tests/test-empty-success.c | 93 ++
server/tests/test-fail-on-null-core-interface.c | 30
server/tests/test-just-sockets-no-ssl.c | 35
server/tests/test-loop.c | 2
server/tests/test-multiple.py | 121 +++
server/tests/test-options.c | 61 +
server/tests/test-playback.c | 126 +++
server/tests/test-stat-file.c | 105 ++
server/tests/test-stream.c | 157 ++++
server/tests/test-two-servers.c | 54 +
server/tests/test-vdagent.c | 75 +
server/tests/test_display_base.c | 932 ------------------------
server/tests/test_display_base.h | 146 ---
server/tests/test_display_no_ssl.c | 72 -
server/tests/test_display_resolution_changes.c | 86 --
server/tests/test_display_streaming.c | 253 ------
server/tests/test_display_width_stride.c | 121 ---
server/tests/test_empty_success.c | 93 --
server/tests/test_fail_on_null_core_interface.c | 30
server/tests/test_just_sockets_no_ssl.c | 35
server/tests/test_multiple.py | 121 ---
server/tests/test_playback.c | 126 ---
server/tests/test_two_servers.c | 54 -
server/tests/test_vdagent.c | 75 -
44 files changed, 2831 insertions(+), 2831 deletions(-)
New commits:
commit e05cf93a01501e8dd9325255a07c29ab529374fe
Author: Frediano Ziglio <fziglio at redhat.com>
Date: Fri Nov 25 13:11:18 2016 +0000
tests: Normalize test names
Use dash instead of underscores for file names. This is coherent
with rest of file names.
Rename all tests to test-XXX and remove the spice- prefix when
present. This is coherent with most of the tests.
Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
Acked-by: Pavel Grunt <pgrunt at redhat.com>
diff --git a/cfg.mk b/cfg.mk
index 3e5d345..4068309 100644
--- a/cfg.mk
+++ b/cfg.mk
@@ -142,7 +142,7 @@ exclude_file_name_regexp--sc_prohibit_have_config_h = ^*/.*(c|cpp|h)
exclude_file_name_regexp--sc_unmarked_diagnostics = ^.*\.(c|py|h)
-exclude_file_name_regexp--sc_prohibit_path_max_allocation = server/tests/test_display_base.c
+exclude_file_name_regexp--sc_prohibit_path_max_allocation = server/tests/test-display-base.c
exclude_file_name_regexp--sc_cast_of_argument_to_free = server/red-replay-qxl.c
diff --git a/server/tests/Makefile.am b/server/tests/Makefile.am
index 626cd81..c55d21d 100644
--- a/server/tests/Makefile.am
+++ b/server/tests/Makefile.am
@@ -21,10 +21,10 @@ endif
noinst_LIBRARIES = libtest.a
libtest_a_SOURCES = \
- basic_event_loop.c \
- basic_event_loop.h \
- test_display_base.c \
- test_display_base.h \
+ basic-event-loop.c \
+ basic-event-loop.h \
+ test-display-base.c \
+ test-display-base.h \
$(NULL)
LDADD = \
@@ -37,27 +37,27 @@ LDADD = \
$(NULL)
check_PROGRAMS = \
- spice-codecs-parsing-test \
- spice-options-test \
- stat_test \
- stream-test \
+ test-codecs-parsing \
+ test-options \
+ test-stat \
+ test-stream \
test-agent-msg-filter \
test-loop \
test-qxl-parsing \
- stat-file-test \
+ test-stat-file \
$(NULL)
noinst_PROGRAMS = \
- test_display_no_ssl \
- test_display_streaming \
- test_empty_success \
- test_fail_on_null_core_interface \
- test_just_sockets_no_ssl \
- test_playback \
- test_display_resolution_changes \
- test_two_servers \
- test_vdagent \
- test_display_width_stride \
+ test-display-no-ssl \
+ test-display-streaming \
+ test-empty-success \
+ test-fail-on-null-core-interface \
+ test-just-sockets-no-ssl \
+ test-playback \
+ test-display-resolution-changes \
+ test-two-servers \
+ test-vdagent \
+ test-display-width-stride \
spice-server-replay \
$(check_PROGRAMS) \
$(NULL)
@@ -66,16 +66,16 @@ TESTS = $(check_PROGRAMS) \
$(NULL)
noinst_LIBRARIES += \
- libstat_test1.a \
- libstat_test2.a \
- libstat_test3.a \
- libstat_test4.a \
+ libtest-stat1.a \
+ libtest-stat2.a \
+ libtest-stat3.a \
+ libtest-stat4.a \
$(NULL)
spice_server_replay_SOURCES = replay.c \
../event-loop.c \
- basic_event_loop.c \
- basic_event_loop.h
+ basic-event-loop.c \
+ basic-event-loop.h
spice_server_replay_LDADD = \
$(top_builddir)/spice-common/common/libspice-common.la \
@@ -85,25 +85,25 @@ spice_server_replay_LDADD = \
$(SPICE_NONPKGCONFIG_LIBS) \
$(NULL)
-stat_test_SOURCES = stat-main.c
-stat_test_LDADD = \
- libstat_test1.a \
- libstat_test2.a \
- libstat_test3.a \
- libstat_test4.a \
+test_stat_SOURCES = stat-main.c
+test_stat_LDADD = \
+ libtest-stat1.a \
+ libtest-stat2.a \
+ libtest-stat3.a \
+ libtest-stat4.a \
$(LDADD) \
$(NULL)
-libstat_test1_a_SOURCES = stat-test.c
-libstat_test1_a_CPPFLAGS = $(AM_CPPFLAGS) -DTEST_COMPRESS_STAT=0 -DTEST_RED_WORKER_STAT=0 -DTEST_NAME=stat_test1
+libtest_stat1_a_SOURCES = stat-test.c
+libtest_stat1_a_CPPFLAGS = $(AM_CPPFLAGS) -DTEST_COMPRESS_STAT=0 -DTEST_RED_WORKER_STAT=0 -DTEST_NAME=stat_test1
-libstat_test2_a_SOURCES = stat-test.c
-libstat_test2_a_CPPFLAGS = $(AM_CPPFLAGS) -DTEST_COMPRESS_STAT=0 -DTEST_RED_WORKER_STAT=1 -DTEST_NAME=stat_test2
+libtest_stat2_a_SOURCES = stat-test.c
+libtest_stat2_a_CPPFLAGS = $(AM_CPPFLAGS) -DTEST_COMPRESS_STAT=0 -DTEST_RED_WORKER_STAT=1 -DTEST_NAME=stat_test2
-libstat_test3_a_SOURCES = stat-test.c
-libstat_test3_a_CPPFLAGS = $(AM_CPPFLAGS) -DTEST_COMPRESS_STAT=1 -DTEST_RED_WORKER_STAT=0 -DTEST_NAME=stat_test3
+libtest_stat3_a_SOURCES = stat-test.c
+libtest_stat3_a_CPPFLAGS = $(AM_CPPFLAGS) -DTEST_COMPRESS_STAT=1 -DTEST_RED_WORKER_STAT=0 -DTEST_NAME=stat_test3
-libstat_test4_a_SOURCES = stat-test.c
-libstat_test4_a_CPPFLAGS = $(AM_CPPFLAGS) -DTEST_COMPRESS_STAT=1 -DTEST_RED_WORKER_STAT=1 -DTEST_NAME=stat_test4
+libtest_stat4_a_SOURCES = stat-test.c
+libtest_stat4_a_CPPFLAGS = $(AM_CPPFLAGS) -DTEST_COMPRESS_STAT=1 -DTEST_RED_WORKER_STAT=1 -DTEST_NAME=stat_test4
test_qxl_parsing_LDADD = ../libserver.la $(LDADD)
diff --git a/server/tests/basic-event-loop.c b/server/tests/basic-event-loop.c
new file mode 100644
index 0000000..4cc797b
--- /dev/null
+++ b/server/tests/basic-event-loop.c
@@ -0,0 +1,137 @@
+/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ Copyright (C) 2009-2015 Red Hat, Inc.
+
+ 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, see <http://www.gnu.org/licenses/>.
+*/
+#include <config.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/time.h>
+#include <signal.h>
+#include <string.h>
+
+#include "red-common.h"
+#include "spice/macros.h"
+#include <common/ring.h>
+#include <common/mem.h>
+#include "basic-event-loop.h"
+
+int debug = 0;
+
+#define DPRINTF(x, format, ...) { \
+ if (x <= debug) { \
+ printf("%s: " format "\n" , __FUNCTION__, ## __VA_ARGS__); \
+ } \
+}
+
+static SpiceCoreInterfaceInternal base_core_interface;
+static GMainContext *main_context = NULL;
+
+GMainContext *basic_event_loop_get_context(void)
+{
+ return main_context;
+}
+
+static void event_loop_channel_event(int event, SpiceChannelEventInfo *info)
+{
+ DPRINTF(0, "channel event con, type, id, event: %d, %d, %d, %d",
+ info->connection_id, info->type, info->id, event);
+}
+
+void basic_event_loop_mainloop(void)
+{
+ GMainLoop *loop = g_main_loop_new(main_context, FALSE);
+
+ g_main_loop_run(loop);
+ g_main_loop_unref(loop);
+}
+
+static void ignore_sigpipe(void)
+{
+ struct sigaction act;
+
+ memset(&act, 0, sizeof(act));
+ sigfillset(&act.sa_mask);
+ act.sa_handler = SIG_IGN;
+ sigaction(SIGPIPE, &act, NULL);
+}
+
+static SpiceTimer* base_timer_add(SpiceTimerFunc func, void *opaque)
+{
+ return base_core_interface.timer_add(&base_core_interface, func, opaque);
+}
+
+static void base_timer_start(SpiceTimer *timer, uint32_t ms)
+{
+ base_core_interface.timer_start(&base_core_interface, timer, ms);
+}
+
+static void base_timer_cancel(SpiceTimer *timer)
+{
+ base_core_interface.timer_cancel(&base_core_interface, timer);
+}
+
+static void base_timer_remove(SpiceTimer *timer)
+{
+ base_core_interface.timer_remove(&base_core_interface, timer);
+}
+
+static SpiceWatch *base_watch_add(int fd, int event_mask, SpiceWatchFunc func, void *opaque)
+{
+ return base_core_interface.watch_add(&base_core_interface, fd, event_mask, func, opaque);
+}
+
+static void base_watch_update_mask(SpiceWatch *watch, int event_mask)
+{
+ base_core_interface.watch_update_mask(&base_core_interface, watch, event_mask);
+}
+
+static void base_watch_remove(SpiceWatch *watch)
+{
+ base_core_interface.watch_remove(&base_core_interface, watch);
+}
+
+static SpiceCoreInterface core = {
+ .base = {
+ .major_version = SPICE_INTERFACE_CORE_MAJOR,
+ .minor_version = SPICE_INTERFACE_CORE_MINOR,
+ },
+ .timer_add = base_timer_add,
+ .timer_start = base_timer_start,
+ .timer_cancel = base_timer_cancel,
+ .timer_remove = base_timer_remove,
+ .watch_add = base_watch_add,
+ .watch_update_mask = base_watch_update_mask,
+ .watch_remove = base_watch_remove,
+ .channel_event = event_loop_channel_event,
+};
+
+SpiceCoreInterface *basic_event_loop_init(void)
+{
+ ignore_sigpipe();
+ spice_assert(main_context == NULL);
+ main_context = g_main_context_new();
+ base_core_interface = event_loop_core;
+ base_core_interface.main_context = main_context;
+
+ return &core;
+}
+
+void basic_event_loop_destroy(void)
+{
+ spice_assert(main_context != NULL);
+ g_main_context_unref(main_context);
+ main_context = NULL;
+}
diff --git a/server/tests/basic-event-loop.h b/server/tests/basic-event-loop.h
new file mode 100644
index 0000000..593532b
--- /dev/null
+++ b/server/tests/basic-event-loop.h
@@ -0,0 +1,29 @@
+/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ Copyright (C) 2009-2015 Red Hat, Inc.
+
+ 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, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef __BASIC_EVENT_LOOP_H__
+#define __BASIC_EVENT_LOOP_H__
+
+#include <spice.h>
+#include <glib.h>
+
+GMainContext *basic_event_loop_get_context(void);
+SpiceCoreInterface *basic_event_loop_init(void);
+void basic_event_loop_destroy(void);
+void basic_event_loop_mainloop(void);
+
+#endif // __BASIC_EVENT_LOOP_H__
diff --git a/server/tests/basic_event_loop.c b/server/tests/basic_event_loop.c
deleted file mode 100644
index 2029424..0000000
--- a/server/tests/basic_event_loop.c
+++ /dev/null
@@ -1,137 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2009-2015 Red Hat, Inc.
-
- 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, see <http://www.gnu.org/licenses/>.
-*/
-#include <config.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <sys/time.h>
-#include <signal.h>
-#include <string.h>
-
-#include "red-common.h"
-#include "spice/macros.h"
-#include <common/ring.h>
-#include <common/mem.h>
-#include "basic_event_loop.h"
-
-int debug = 0;
-
-#define DPRINTF(x, format, ...) { \
- if (x <= debug) { \
- printf("%s: " format "\n" , __FUNCTION__, ## __VA_ARGS__); \
- } \
-}
-
-static SpiceCoreInterfaceInternal base_core_interface;
-static GMainContext *main_context = NULL;
-
-GMainContext *basic_event_loop_get_context(void)
-{
- return main_context;
-}
-
-static void event_loop_channel_event(int event, SpiceChannelEventInfo *info)
-{
- DPRINTF(0, "channel event con, type, id, event: %d, %d, %d, %d",
- info->connection_id, info->type, info->id, event);
-}
-
-void basic_event_loop_mainloop(void)
-{
- GMainLoop *loop = g_main_loop_new(main_context, FALSE);
-
- g_main_loop_run(loop);
- g_main_loop_unref(loop);
-}
-
-static void ignore_sigpipe(void)
-{
- struct sigaction act;
-
- memset(&act, 0, sizeof(act));
- sigfillset(&act.sa_mask);
- act.sa_handler = SIG_IGN;
- sigaction(SIGPIPE, &act, NULL);
-}
-
-static SpiceTimer* base_timer_add(SpiceTimerFunc func, void *opaque)
-{
- return base_core_interface.timer_add(&base_core_interface, func, opaque);
-}
-
-static void base_timer_start(SpiceTimer *timer, uint32_t ms)
-{
- base_core_interface.timer_start(&base_core_interface, timer, ms);
-}
-
-static void base_timer_cancel(SpiceTimer *timer)
-{
- base_core_interface.timer_cancel(&base_core_interface, timer);
-}
-
-static void base_timer_remove(SpiceTimer *timer)
-{
- base_core_interface.timer_remove(&base_core_interface, timer);
-}
-
-static SpiceWatch *base_watch_add(int fd, int event_mask, SpiceWatchFunc func, void *opaque)
-{
- return base_core_interface.watch_add(&base_core_interface, fd, event_mask, func, opaque);
-}
-
-static void base_watch_update_mask(SpiceWatch *watch, int event_mask)
-{
- base_core_interface.watch_update_mask(&base_core_interface, watch, event_mask);
-}
-
-static void base_watch_remove(SpiceWatch *watch)
-{
- base_core_interface.watch_remove(&base_core_interface, watch);
-}
-
-static SpiceCoreInterface core = {
- .base = {
- .major_version = SPICE_INTERFACE_CORE_MAJOR,
- .minor_version = SPICE_INTERFACE_CORE_MINOR,
- },
- .timer_add = base_timer_add,
- .timer_start = base_timer_start,
- .timer_cancel = base_timer_cancel,
- .timer_remove = base_timer_remove,
- .watch_add = base_watch_add,
- .watch_update_mask = base_watch_update_mask,
- .watch_remove = base_watch_remove,
- .channel_event = event_loop_channel_event,
-};
-
-SpiceCoreInterface *basic_event_loop_init(void)
-{
- ignore_sigpipe();
- spice_assert(main_context == NULL);
- main_context = g_main_context_new();
- base_core_interface = event_loop_core;
- base_core_interface.main_context = main_context;
-
- return &core;
-}
-
-void basic_event_loop_destroy(void)
-{
- spice_assert(main_context != NULL);
- g_main_context_unref(main_context);
- main_context = NULL;
-}
diff --git a/server/tests/basic_event_loop.h b/server/tests/basic_event_loop.h
deleted file mode 100644
index 593532b..0000000
--- a/server/tests/basic_event_loop.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2009-2015 Red Hat, Inc.
-
- 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, see <http://www.gnu.org/licenses/>.
-*/
-#ifndef __BASIC_EVENT_LOOP_H__
-#define __BASIC_EVENT_LOOP_H__
-
-#include <spice.h>
-#include <glib.h>
-
-GMainContext *basic_event_loop_get_context(void);
-SpiceCoreInterface *basic_event_loop_init(void);
-void basic_event_loop_destroy(void);
-void basic_event_loop_mainloop(void);
-
-#endif // __BASIC_EVENT_LOOP_H__
diff --git a/server/tests/regression-test.py b/server/tests/regression-test.py
new file mode 100755
index 0000000..5aad1a7
--- /dev/null
+++ b/server/tests/regression-test.py
@@ -0,0 +1,25 @@
+#!/usr/bin/python
+from subprocess import PIPE, Popen
+import Image
+import ImageChops
+
+
+def spicy_screenshot():
+ cmd = "spicy-screenshot -h localhost -p 5912 -o output.ppm"
+ p = Popen(cmd, shell=True)
+ p.wait()
+
+def verify():
+ base = Image.open("base_test.ppm")
+ output = Image.open("output.ppm")
+ return ImageChops.difference(base, output).getbbox()
+
+if __name__ == "__main__":
+ spicy_screenshot()
+ diff = verify()
+
+ if diff is None:
+ print("\033[1;32mSUCCESS: No regressions were found!\033[1;m")
+ else:
+ print("\033[1;31mFAIL: Regressions were found!\n\033[1;m"
+ "\033[1;31m Please, take a look in your code and go fix it!\033[1;m")
diff --git a/server/tests/regression_test.py b/server/tests/regression_test.py
deleted file mode 100755
index 5aad1a7..0000000
--- a/server/tests/regression_test.py
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/usr/bin/python
-from subprocess import PIPE, Popen
-import Image
-import ImageChops
-
-
-def spicy_screenshot():
- cmd = "spicy-screenshot -h localhost -p 5912 -o output.ppm"
- p = Popen(cmd, shell=True)
- p.wait()
-
-def verify():
- base = Image.open("base_test.ppm")
- output = Image.open("output.ppm")
- return ImageChops.difference(base, output).getbbox()
-
-if __name__ == "__main__":
- spicy_screenshot()
- diff = verify()
-
- if diff is None:
- print("\033[1;32mSUCCESS: No regressions were found!\033[1;m")
- else:
- print("\033[1;31mFAIL: Regressions were found!\n\033[1;m"
- "\033[1;31m Please, take a look in your code and go fix it!\033[1;m")
diff --git a/server/tests/replay.c b/server/tests/replay.c
index 6c6e01e..f32fa2f 100644
--- a/server/tests/replay.c
+++ b/server/tests/replay.c
@@ -36,7 +36,7 @@
#include <pthread.h>
#include <spice/macros.h>
-#include "test_display_base.h"
+#include "test-display-base.h"
#include <common/log.h>
static SpiceCoreInterface *core;
diff --git a/server/tests/spice-codecs-parsing-test.c b/server/tests/spice-codecs-parsing-test.c
deleted file mode 100644
index 0e23553..0000000
--- a/server/tests/spice-codecs-parsing-test.c
+++ /dev/null
@@ -1,131 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2016 Red Hat, Inc.
-
- 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, see <http://www.gnu.org/licenses/>.
-*/
-#include <config.h>
-#include <glib.h>
-#include <spice.h>
-
-/* GLIB_CHECK_VERSION(2, 40, 0) */
-#ifndef g_assert_nonnull
-#define g_assert_nonnull g_assert
-#endif
-
-static void codecs_good(void)
-{
- guint i;
- const gchar *codecs[] = {
- "",
- ";",
- ";;;;",
- "spice:mjpeg",
- "spice:mjpeg;;;",
- "spice:mjpeg;;spice:mjpeg;;;",
- ";;spice:mjpeg;;spice:mjpeg;;;",
-#if defined(HAVE_GSTREAMER_1_0) || defined(HAVE_GSTREAMER_0_10)
- "gstreamer:mjpeg;gstreamer:h264;gstreamer:vp8;",
- ";;spice:mjpeg;;gstreamer:mjpeg;gstreamer:h264;gstreamer:vp8;",
-#endif
- };
-
- SpiceServer *server = spice_server_new();
-
- g_assert_nonnull(server);
-
- for (i = 0; i < G_N_ELEMENTS(codecs); ++i) {
- g_assert_cmpint(spice_server_set_video_codecs(server, codecs[i]), ==, 0);
- }
-
- spice_server_destroy(server);
-}
-
-/* g_test_expect_message is available since Glib 2.34 */
-#if GLIB_CHECK_VERSION(2, 34, 0)
-static void codecs_bad(void)
-{
- guint i;
- const struct {
- const gchar *codecs;
- const GLogLevelFlags log_level;
- const gchar *error_message;
- } test_cases[] = {
- {
- NULL,
- G_LOG_LEVEL_CRITICAL,
- "*assertion 'codecs != NULL' failed"
- },{
- ";:;",
- G_LOG_LEVEL_WARNING,
- "*spice: invalid encoder:codec value*",
- },{
- "::::",
- G_LOG_LEVEL_WARNING,
- "*spice: invalid encoder:codec value*",
- },{
- "missingcolon",
- G_LOG_LEVEL_WARNING,
- "*spice: invalid encoder:codec value*",
- },{
- ":missing_encoder",
- G_LOG_LEVEL_WARNING,
- "*spice: invalid encoder:codec value*",
- },{
- "missing_value:;",
- G_LOG_LEVEL_WARNING,
- "*spice: invalid encoder:codec value*",
- },{
- "unknown_encoder:mjpeg",
- G_LOG_LEVEL_WARNING,
- "*spice: unknown video encoder unknown_encoder",
- },{
- "spice:unknown_codec",
- G_LOG_LEVEL_WARNING,
- "*spice: unknown video codec unknown_codec",
- },
-#if !defined(HAVE_GSTREAMER_1_0) && !defined(HAVE_GSTREAMER_0_10)
- {
- "gstreamer:mjpeg",
- G_LOG_LEVEL_WARNING,
- "*spice: unsupported video encoder gstreamer",
- }
-#endif
- };
-
- SpiceServer *server = spice_server_new();
-
- g_assert_nonnull(server);
-
- for (i = 0; i < G_N_ELEMENTS(test_cases); ++i) {
- g_test_expect_message(G_LOG_DOMAIN, test_cases[i].log_level, test_cases[i].error_message);
- g_assert_cmpint(spice_server_set_video_codecs(server, test_cases[i].codecs), ==, 0);
- g_test_assert_expected_messages();
- }
-
- spice_server_destroy(server);
-}
-#endif
-
-int main(int argc, char *argv[])
-{
- g_test_init(&argc, &argv, NULL);
-
- g_test_add_func("/server/codecs-good", codecs_good);
-#if GLIB_CHECK_VERSION(2, 34, 0)
- g_test_add_func("/server/codecs-bad", codecs_bad);
-#endif
-
- return g_test_run();
-}
diff --git a/server/tests/spice-options-test.c b/server/tests/spice-options-test.c
deleted file mode 100644
index 72ec215..0000000
--- a/server/tests/spice-options-test.c
+++ /dev/null
@@ -1,61 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2016 Red Hat, Inc.
-
- 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, see <http://www.gnu.org/licenses/>.
-*/
-#include <config.h>
-#include <glib.h>
-#include <spice.h>
-
-#include "basic_event_loop.h"
-
-/* GLIB_CHECK_VERSION(2, 40, 0) */
-#ifndef g_assert_nonnull
-#define g_assert_nonnull g_assert
-#endif
-
-static void agent_options(void)
-{
- SpiceCoreInterface *core ;
- SpiceServer *server = spice_server_new();
-
- g_assert_nonnull(server);
-
- core = basic_event_loop_init();
- g_assert_nonnull(core);
-
- /* test before init */
- spice_server_set_agent_mouse(server, 0);
- spice_server_set_agent_copypaste(server, 0);
- spice_server_set_agent_file_xfer(server, 0);
-
- g_assert_cmpint(spice_server_init(server, core), ==, 0);
-
- /* test after init */
- spice_server_set_agent_mouse(server, 0);
- spice_server_set_agent_copypaste(server, 0);
- spice_server_set_agent_file_xfer(server, 0);
-
- spice_server_destroy(server);
-}
-
-int main(int argc, char *argv[])
-{
- g_test_init(&argc, &argv, NULL);
-
- g_test_add_func("/server/agent options", agent_options);
-
- return g_test_run();
-}
diff --git a/server/tests/stat-file-test.c b/server/tests/stat-file-test.c
deleted file mode 100644
index 09b0c7a..0000000
--- a/server/tests/stat-file-test.c
+++ /dev/null
@@ -1,105 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2016 Red Hat, Inc.
-
- 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, see <http://www.gnu.org/licenses/>.
-*/
-#include <config.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <glib.h>
-#include <spice.h>
-
-#include "stat-file.h"
-
-/* GLIB_CHECK_VERSION(2, 40, 0) */
-#ifndef g_assert_nonnull
-#define g_assert_nonnull g_assert
-#endif
-#ifndef g_assert_null
-#define g_assert_null(ptr) g_assert((ptr) == NULL)
-#endif
-
-static void stat_file(void)
-{
- RedStatFile *stat_file;
- StatNodeRef ref, refs[10];
- uint64_t *counter, *counters[10] SPICE_GNUC_UNUSED;
- int i;
- char *filename = NULL;
- char name[20];
-
- /* create */
- stat_file = stat_file_new(10);
-
- g_assert_nonnull(stat_file);
- g_assert_nonnull(stat_file_get_shm_name(stat_file));
- filename = strdup(stat_file_get_shm_name(stat_file));
- g_assert(access(filename, R_OK));
-
- /* fill all nodes */
- for (i = 0; i < 10; ++i) {
- sprintf(name, "node %d", i);
- ref = stat_file_add_node(stat_file, INVALID_STAT_REF, name, TRUE);
- refs[i] = ref;
- g_assert_cmpuint(ref,!=,INVALID_STAT_REF);
- }
-
- /* should fail */
- ref = stat_file_add_node(stat_file, INVALID_STAT_REF, "invalid", TRUE);
- g_assert_cmpuint(ref,==,INVALID_STAT_REF);
-
- /* we should find already present nodes */
- for (i = 0; i < 10; ++i) {
- /* the formula used here is to take nodes here and there.
- * As 17 and 10 are coprime numbers you'll get the same numbers
- * after 10 iterations */
- sprintf(name, "node %d", (i * 17 + 5) % 10);
- ref = stat_file_add_node(stat_file, INVALID_STAT_REF, name, TRUE);
- g_assert_cmpuint(ref,!=,INVALID_STAT_REF);
- }
-
- /* delete some nodes */
- for (i = 0; i < 6; ++i) {
- /* see above why the formula is used */
- int n = (i * 23 + 3) % 10;
- stat_file_remove_node(stat_file, refs[n]);
- refs[n] = INVALID_STAT_REF;
- }
-
- /* now there should be some place for some counters */
- for (i = 0; i < 6; ++i) {
- sprintf(name, "counter %d", i);
- counter = stat_file_add_counter(stat_file, INVALID_STAT_REF, name, TRUE);
- counters[i] = counter;
- g_assert_nonnull(counter);
- }
- counter = stat_file_add_counter(stat_file, INVALID_STAT_REF, "invalid", TRUE);
- g_assert_null(counter);
-
- stat_file_unlink(stat_file);
- g_assert_null(stat_file_get_shm_name(stat_file));
- g_assert_cmpint(access(filename, F_OK),==,-1);
- free(filename);
-}
-
-int main(int argc, char *argv[])
-{
- g_test_init(&argc, &argv, NULL);
-
- g_test_add_func("/server/stat-file", stat_file);
-
- return g_test_run();
-}
diff --git a/server/tests/stream-test.c b/server/tests/stream-test.c
deleted file mode 100644
index 8a34a0d..0000000
--- a/server/tests/stream-test.c
+++ /dev/null
@@ -1,157 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2016 Red Hat, Inc.
-
- 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, see <http://www.gnu.org/licenses/>.
-*/
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <errno.h>
-#include <unistd.h>
-
-#include <common/log.h>
-#include "reds-stream.h"
-#include "basic_event_loop.h"
-
-static SpiceServer *server = NULL;
-
-static int server_init(void)
-{
- SpiceCoreInterface *core = basic_event_loop_init();
- server = spice_server_new();
-
- return spice_server_init(server, core);
-}
-
-
-/*
- * Based on code from Keith Packard:
- * http://keithp.com/blogs/fd-passing/
- */
-static ssize_t
-sock_fd_read(int sock, void *buf, ssize_t bufsize, int *fd)
-{
- ssize_t size;
-
- if (fd) {
- struct msghdr msg;
- struct iovec iov;
- union {
- struct cmsghdr cmsghdr;
- char control[CMSG_SPACE(sizeof (int))];
- } cmsgu;
- struct cmsghdr *cmsg;
-
- iov.iov_base = buf;
- iov.iov_len = bufsize;
-
- msg.msg_name = NULL;
- msg.msg_namelen = 0;
- msg.msg_iov = &iov;
- msg.msg_iovlen = 1;
- msg.msg_control = cmsgu.control;
- msg.msg_controllen = sizeof(cmsgu.control);
- size = recvmsg(sock, &msg, 0);
- if (size < 0) {
- perror ("recvmsg");
- exit(1);
- }
- cmsg = CMSG_FIRSTHDR(&msg);
- if (cmsg && cmsg->cmsg_len == CMSG_LEN(sizeof(int))) {
- if (cmsg->cmsg_level != SOL_SOCKET) {
- fprintf(stderr, "invalid cmsg_level %d\n",
- cmsg->cmsg_level);
- exit(1);
- }
- if (cmsg->cmsg_type != SCM_RIGHTS) {
- fprintf(stderr, "invalid cmsg_type %d\n",
- cmsg->cmsg_type);
- exit(1);
- }
-
- memcpy(fd, CMSG_DATA(cmsg), sizeof(*fd));
- } else
- *fd = -1;
- } else {
- size = read(sock, buf, bufsize);
- if (size < 0) {
- perror("read");
- exit(1);
- }
- }
-
- return size;
-}
-
-int main(int argc, char *argv[])
-{
- RedsStream *st[2];
- int sv[2];
- int ret, fd = -1;
- char c;
-
- spice_return_val_if_fail(server_init() == 0, -1);
-
- if (socketpair(AF_LOCAL, SOCK_STREAM, 0, sv) == -1) {
- spice_error("socketpair failed %s", strerror(errno));
- return -1;
- }
-
- st[0] = reds_stream_new(server, sv[0]);
- spice_assert(reds_stream_is_plain_unix(st[0]));
- st[1] = reds_stream_new(server, sv[1]);
- spice_assert(reds_stream_is_plain_unix(st[1]));
-
- /* send stdin, for the fun of it */
- ret = reds_stream_send_msgfd(st[0], 0);
- spice_assert(ret == 1);
- ret = sock_fd_read(sv[1], &c, 1, &fd);
- spice_assert(c == '@');
- spice_assert(ret == 1);
- spice_assert(fd != -1);
- close(fd);
-
- /* send invalid fd behaviour */
- ret = reds_stream_send_msgfd(st[0], -1);
- spice_assert(ret == 1);
- ret = sock_fd_read(sv[1], &c, 1, &fd);
- spice_assert(c == '@');
- spice_assert(ret == 1);
- spice_assert(fd == -1);
-
- /* batch test */
- ret = reds_stream_send_msgfd(st[0], 0);
- spice_assert(ret == 1);
- ret = reds_stream_send_msgfd(st[0], 0);
- spice_assert(ret == 1);
- ret = sock_fd_read(sv[1], &c, 1, &fd);
- spice_assert(c == '@');
- spice_assert(ret == 1);
- spice_assert(fd != -1);
- close(fd);
- ret = sock_fd_read(sv[1], &c, 1, &fd);
- spice_assert(c == '@');
- spice_assert(ret == 1);
- spice_assert(fd != -1);
- close(fd);
-
- reds_stream_free(st[0]);
- reds_stream_free(st[1]);
-
- return 0;
-}
diff --git a/server/tests/test-codecs-parsing.c b/server/tests/test-codecs-parsing.c
new file mode 100644
index 0000000..0e23553
--- /dev/null
+++ b/server/tests/test-codecs-parsing.c
@@ -0,0 +1,131 @@
+/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ Copyright (C) 2016 Red Hat, Inc.
+
+ 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, see <http://www.gnu.org/licenses/>.
+*/
+#include <config.h>
+#include <glib.h>
+#include <spice.h>
+
+/* GLIB_CHECK_VERSION(2, 40, 0) */
+#ifndef g_assert_nonnull
+#define g_assert_nonnull g_assert
+#endif
+
+static void codecs_good(void)
+{
+ guint i;
+ const gchar *codecs[] = {
+ "",
+ ";",
+ ";;;;",
+ "spice:mjpeg",
+ "spice:mjpeg;;;",
+ "spice:mjpeg;;spice:mjpeg;;;",
+ ";;spice:mjpeg;;spice:mjpeg;;;",
+#if defined(HAVE_GSTREAMER_1_0) || defined(HAVE_GSTREAMER_0_10)
+ "gstreamer:mjpeg;gstreamer:h264;gstreamer:vp8;",
+ ";;spice:mjpeg;;gstreamer:mjpeg;gstreamer:h264;gstreamer:vp8;",
+#endif
+ };
+
+ SpiceServer *server = spice_server_new();
+
+ g_assert_nonnull(server);
+
+ for (i = 0; i < G_N_ELEMENTS(codecs); ++i) {
+ g_assert_cmpint(spice_server_set_video_codecs(server, codecs[i]), ==, 0);
+ }
+
+ spice_server_destroy(server);
+}
+
+/* g_test_expect_message is available since Glib 2.34 */
+#if GLIB_CHECK_VERSION(2, 34, 0)
+static void codecs_bad(void)
+{
+ guint i;
+ const struct {
+ const gchar *codecs;
+ const GLogLevelFlags log_level;
+ const gchar *error_message;
+ } test_cases[] = {
+ {
+ NULL,
+ G_LOG_LEVEL_CRITICAL,
+ "*assertion 'codecs != NULL' failed"
+ },{
+ ";:;",
+ G_LOG_LEVEL_WARNING,
+ "*spice: invalid encoder:codec value*",
+ },{
+ "::::",
+ G_LOG_LEVEL_WARNING,
+ "*spice: invalid encoder:codec value*",
+ },{
+ "missingcolon",
+ G_LOG_LEVEL_WARNING,
+ "*spice: invalid encoder:codec value*",
+ },{
+ ":missing_encoder",
+ G_LOG_LEVEL_WARNING,
+ "*spice: invalid encoder:codec value*",
+ },{
+ "missing_value:;",
+ G_LOG_LEVEL_WARNING,
+ "*spice: invalid encoder:codec value*",
+ },{
+ "unknown_encoder:mjpeg",
+ G_LOG_LEVEL_WARNING,
+ "*spice: unknown video encoder unknown_encoder",
+ },{
+ "spice:unknown_codec",
+ G_LOG_LEVEL_WARNING,
+ "*spice: unknown video codec unknown_codec",
+ },
+#if !defined(HAVE_GSTREAMER_1_0) && !defined(HAVE_GSTREAMER_0_10)
+ {
+ "gstreamer:mjpeg",
+ G_LOG_LEVEL_WARNING,
+ "*spice: unsupported video encoder gstreamer",
+ }
+#endif
+ };
+
+ SpiceServer *server = spice_server_new();
+
+ g_assert_nonnull(server);
+
+ for (i = 0; i < G_N_ELEMENTS(test_cases); ++i) {
+ g_test_expect_message(G_LOG_DOMAIN, test_cases[i].log_level, test_cases[i].error_message);
+ g_assert_cmpint(spice_server_set_video_codecs(server, test_cases[i].codecs), ==, 0);
+ g_test_assert_expected_messages();
+ }
+
+ spice_server_destroy(server);
+}
+#endif
+
+int main(int argc, char *argv[])
+{
+ g_test_init(&argc, &argv, NULL);
+
+ g_test_add_func("/server/codecs-good", codecs_good);
+#if GLIB_CHECK_VERSION(2, 34, 0)
+ g_test_add_func("/server/codecs-bad", codecs_bad);
+#endif
+
+ return g_test_run();
+}
diff --git a/server/tests/test-display-base.c b/server/tests/test-display-base.c
new file mode 100644
index 0000000..bf1475d
--- /dev/null
+++ b/server/tests/test-display-base.c
@@ -0,0 +1,932 @@
+/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ Copyright (C) 2009-2015 Red Hat, Inc.
+
+ 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, see <http://www.gnu.org/licenses/>.
+*/
+#include <config.h>
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <signal.h>
+#include <wait.h>
+#include <sys/select.h>
+#include <sys/types.h>
+#include <getopt.h>
+
+#include "spice.h"
+#include <spice/qxl_dev.h>
+
+#include "test-display-base.h"
+#include "red-channel.h"
+
+#ifndef PATH_MAX
+#define PATH_MAX 4096
+#endif
+
+#define MEM_SLOT_GROUP_ID 0
+
+#define NOTIFY_DISPLAY_BATCH (SINGLE_PART/2)
+#define NOTIFY_CURSOR_BATCH 10
+
+/* Parts cribbed from spice-display.h/.c/qxl.c */
+
+typedef struct SimpleSpiceUpdate {
+ QXLCommandExt ext; // first
+ QXLDrawable drawable;
+ QXLImage image;
+ uint8_t *bitmap;
+} SimpleSpiceUpdate;
+
+typedef struct SimpleSurfaceCmd {
+ QXLCommandExt ext; // first
+ QXLSurfaceCmd surface_cmd;
+} SimpleSurfaceCmd;
+
+static void test_spice_destroy_update(SimpleSpiceUpdate *update)
+{
+ if (!update) {
+ return;
+ }
+ if (update->drawable.clip.type != SPICE_CLIP_TYPE_NONE) {
+ uint8_t *ptr = (uint8_t*)update->drawable.clip.data;
+ free(ptr);
+ }
+ free(update->bitmap);
+ free(update);
+}
+
+#define DEFAULT_WIDTH 640
+#define DEFAULT_HEIGHT 320
+
+#define SINGLE_PART 4
+static const int angle_parts = 64 / SINGLE_PART;
+static int unique = 1;
+static int color = -1;
+static int c_i = 0;
+
+/* Used for automated tests */
+static int control = 3; //used to know when we can take a screenshot
+static int rects = 16; //number of rects that will be draw
+static int has_automated_tests = 0; //automated test flag
+
+__attribute__((noreturn))
+static void sigchld_handler(SPICE_GNUC_UNUSED int signal_num) // wait for the child process and exit
+{
+ int status;
+ wait(&status);
+ exit(0);
+}
+
+static void regression_test(void)
+{
+ pid_t pid;
+
+ if (--rects != 0) {
+ return;
+ }
+
+ rects = 16;
+
+ if (--control != 0) {
+ return;
+ }
+
+ pid = fork();
+ if (pid == 0) {
+ char buf[PATH_MAX];
+ char *argv[] = { NULL };
+ char *envp[] = {buf, NULL};
+
+ snprintf(buf, sizeof(buf), "PATH=%s", getenv("PATH"));
+ execve("regression-test.py", argv, envp);
+ } else if (pid > 0) {
+ return;
+ }
+}
+
+static void set_cmd(QXLCommandExt *ext, uint32_t type, QXLPHYSICAL data)
+{
+ ext->cmd.type = type;
+ ext->cmd.data = data;
+ ext->cmd.padding = 0;
+ ext->group_id = MEM_SLOT_GROUP_ID;
+ ext->flags = 0;
+}
+
+static void simple_set_release_info(QXLReleaseInfo *info, intptr_t ptr)
+{
+ info->id = ptr;
+ //info->group_id = MEM_SLOT_GROUP_ID;
+}
+
+typedef struct Path {
+ int t;
+ int min_t;
+ int max_t;
+} Path;
+
+static void path_init(Path *path, int min, int max)
+{
+ path->t = min;
+ path->min_t = min;
+ path->max_t = max;
+}
+
+static void path_progress(Path *path)
+{
+ path->t = (path->t+1)% (path->max_t - path->min_t) + path->min_t;
+}
+
+Path path;
+
+static void draw_pos(Test *test, int t, int *x, int *y)
+{
+#ifdef CIRCLE
+ *y = test->primary_height/2 + (test->primary_height/3)*cos(t*2*M_PI/angle_parts);
+ *x = test->primary_width/2 + (test->primary_width/3)*sin(t*2*M_PI/angle_parts);
+#else
+ *y = test->primary_height*(t % SINGLE_PART)/SINGLE_PART;
+ *x = ((test->primary_width/SINGLE_PART)*(t / SINGLE_PART)) % test->primary_width;
+#endif
+}
+
+/* bitmap and rects are freed, so they must be allocated with malloc */
+SimpleSpiceUpdate *test_spice_create_update_from_bitmap(uint32_t surface_id,
+ QXLRect bbox,
+ uint8_t *bitmap,
+ uint32_t num_clip_rects,
+ QXLRect *clip_rects)
+{
+ SimpleSpiceUpdate *update;
+ QXLDrawable *drawable;
+ QXLImage *image;
+ uint32_t bw, bh;
+
+ bh = bbox.bottom - bbox.top;
+ bw = bbox.right - bbox.left;
+
+ update = calloc(sizeof(*update), 1);
+ update->bitmap = bitmap;
+ drawable = &update->drawable;
+ image = &update->image;
+
+ drawable->surface_id = surface_id;
+
+ drawable->bbox = bbox;
+ if (num_clip_rects == 0) {
+ drawable->clip.type = SPICE_CLIP_TYPE_NONE;
+ } else {
+ QXLClipRects *cmd_clip;
+
+ cmd_clip = calloc(sizeof(QXLClipRects) + num_clip_rects*sizeof(QXLRect), 1);
+ cmd_clip->num_rects = num_clip_rects;
+ cmd_clip->chunk.data_size = num_clip_rects*sizeof(QXLRect);
+ cmd_clip->chunk.prev_chunk = cmd_clip->chunk.next_chunk = 0;
+ memcpy(cmd_clip + 1, clip_rects, cmd_clip->chunk.data_size);
+
+ drawable->clip.type = SPICE_CLIP_TYPE_RECTS;
+ drawable->clip.data = (intptr_t)cmd_clip;
+
+ free(clip_rects);
+ }
+ drawable->effect = QXL_EFFECT_OPAQUE;
+ simple_set_release_info(&drawable->release_info, (intptr_t)update);
+ drawable->type = QXL_DRAW_COPY;
+ drawable->surfaces_dest[0] = -1;
+ drawable->surfaces_dest[1] = -1;
+ drawable->surfaces_dest[2] = -1;
+
+ drawable->u.copy.rop_descriptor = SPICE_ROPD_OP_PUT;
+ drawable->u.copy.src_bitmap = (intptr_t)image;
+ drawable->u.copy.src_area.right = bw;
+ drawable->u.copy.src_area.bottom = bh;
+
+ QXL_SET_IMAGE_ID(image, QXL_IMAGE_GROUP_DEVICE, unique);
+ image->descriptor.type = SPICE_IMAGE_TYPE_BITMAP;
+ image->bitmap.flags = QXL_BITMAP_DIRECT | QXL_BITMAP_TOP_DOWN;
+ image->bitmap.stride = bw * 4;
+ image->descriptor.width = image->bitmap.x = bw;
+ image->descriptor.height = image->bitmap.y = bh;
+ image->bitmap.data = (intptr_t)bitmap;
+ image->bitmap.palette = 0;
+ image->bitmap.format = SPICE_BITMAP_FMT_32BIT;
+
+ set_cmd(&update->ext, QXL_CMD_DRAW, (intptr_t)drawable);
+
+ return update;
+}
+
+static SimpleSpiceUpdate *test_spice_create_update_solid(uint32_t surface_id, QXLRect bbox, uint32_t color)
+{
+ uint8_t *bitmap;
+ uint32_t *dst;
+ uint32_t bw;
+ uint32_t bh;
+ uint32_t i;
+
+ bw = bbox.right - bbox.left;
+ bh = bbox.bottom - bbox.top;
+
+ bitmap = malloc(bw * bh * 4);
+ dst = (uint32_t *)bitmap;
+
+ for (i = 0 ; i < bh * bw ; ++i, ++dst) {
+ *dst = color;
+ }
+
+ return test_spice_create_update_from_bitmap(surface_id, bbox, bitmap, 0, NULL);
+}
+
+static SimpleSpiceUpdate *test_spice_create_update_draw(Test *test, uint32_t surface_id, int t)
+{
+ int top, left;
+ uint8_t *dst;
+ uint8_t *bitmap;
+ int bw, bh;
+ int i;
+ QXLRect bbox;
+
+ draw_pos(test, t, &left, &top);
+ if ((t % angle_parts) == 0) {
+ c_i++;
+ }
+
+ if (surface_id != 0) {
+ color = (color + 1) % 2;
+ } else {
+ color = surface_id;
+ }
+
+ unique++;
+
+ bw = test->primary_width/SINGLE_PART;
+ bh = 48;
+
+ bitmap = dst = malloc(bw * bh * 4);
+ //printf("allocated %p\n", dst);
+
+ for (i = 0 ; i < bh * bw ; ++i, dst+=4) {
+ *dst = (color+i % 255);
+ *(dst+((1+c_i)%3)) = 255 - color;
+ *(dst+((2+c_i)%3)) = (color * (color + i)) & 0xff;
+ *(dst+((3+c_i)%3)) = 0;
+ }
+
+ bbox.left = left; bbox.top = top;
+ bbox.right = left + bw; bbox.bottom = top + bh;
+ return test_spice_create_update_from_bitmap(surface_id, bbox, bitmap, 0, NULL);
+}
+
+static SimpleSpiceUpdate *test_spice_create_update_copy_bits(Test *test, uint32_t surface_id)
+{
+ SimpleSpiceUpdate *update;
+ QXLDrawable *drawable;
+ int bw, bh;
+ QXLRect bbox = {
+ .left = 10,
+ .top = 0,
+ };
+
+ update = calloc(sizeof(*update), 1);
+ drawable = &update->drawable;
+
+ bw = test->primary_width/SINGLE_PART;
+ bh = 48;
+ bbox.right = bbox.left + bw;
+ bbox.bottom = bbox.top + bh;
+ //printf("allocated %p, %p\n", update, update->bitmap);
+
+ drawable->surface_id = surface_id;
+
+ drawable->bbox = bbox;
+ drawable->clip.type = SPICE_CLIP_TYPE_NONE;
+ drawable->effect = QXL_EFFECT_OPAQUE;
+ simple_set_release_info(&drawable->release_info, (intptr_t)update);
+ drawable->type = QXL_COPY_BITS;
+ drawable->surfaces_dest[0] = -1;
+ drawable->surfaces_dest[1] = -1;
+ drawable->surfaces_dest[2] = -1;
+
+ drawable->u.copy_bits.src_pos.x = 0;
+ drawable->u.copy_bits.src_pos.y = 0;
+
+ set_cmd(&update->ext, QXL_CMD_DRAW, (intptr_t)drawable);
+
+ return update;
+}
+
+static int format_to_bpp(int format)
+{
+ switch (format) {
+ case SPICE_SURFACE_FMT_8_A:
+ return 1;
+ case SPICE_SURFACE_FMT_16_555:
+ case SPICE_SURFACE_FMT_16_565:
+ return 2;
+ case SPICE_SURFACE_FMT_32_xRGB:
+ case SPICE_SURFACE_FMT_32_ARGB:
+ return 4;
+ }
+ abort();
+}
+
+static SimpleSurfaceCmd *create_surface(int surface_id, int format, int width, int height, uint8_t *data)
+{
+ SimpleSurfaceCmd *simple_cmd = calloc(sizeof(SimpleSurfaceCmd), 1);
+ QXLSurfaceCmd *surface_cmd = &simple_cmd->surface_cmd;
+ int bpp = format_to_bpp(format);
+
+ set_cmd(&simple_cmd->ext, QXL_CMD_SURFACE, (intptr_t)surface_cmd);
+ simple_set_release_info(&surface_cmd->release_info, (intptr_t)simple_cmd);
+ surface_cmd->type = QXL_SURFACE_CMD_CREATE;
+ surface_cmd->flags = 0; // ?
+ surface_cmd->surface_id = surface_id;
+ surface_cmd->u.surface_create.format = format;
+ surface_cmd->u.surface_create.width = width;
+ surface_cmd->u.surface_create.height = height;
+ surface_cmd->u.surface_create.stride = -width * bpp;
+ surface_cmd->u.surface_create.data = (intptr_t)data;
+ return simple_cmd;
+}
+
+static SimpleSurfaceCmd *destroy_surface(int surface_id)
+{
+ SimpleSurfaceCmd *simple_cmd = calloc(sizeof(SimpleSurfaceCmd), 1);
+ QXLSurfaceCmd *surface_cmd = &simple_cmd->surface_cmd;
+
+ set_cmd(&simple_cmd->ext, QXL_CMD_SURFACE, (intptr_t)surface_cmd);
+ simple_set_release_info(&surface_cmd->release_info, (intptr_t)simple_cmd);
+ surface_cmd->type = QXL_SURFACE_CMD_DESTROY;
+ surface_cmd->flags = 0; // ?
+ surface_cmd->surface_id = surface_id;
+ return simple_cmd;
+}
+
+static void create_primary_surface(Test *test, uint32_t width,
+ uint32_t height)
+{
+ QXLDevSurfaceCreate surface = { 0, };
+
+ spice_assert(height <= MAX_HEIGHT);
+ spice_assert(width <= MAX_WIDTH);
+ spice_assert(height > 0);
+ spice_assert(width > 0);
+
+ surface.format = SPICE_SURFACE_FMT_32_xRGB;
+ surface.width = test->primary_width = width;
+ surface.height = test->primary_height = height;
+ surface.stride = -width * 4; /* negative? */
+ surface.mouse_mode = TRUE; /* unused by red_worker */
+ surface.flags = 0;
+ surface.type = 0; /* unused by red_worker */
+ surface.position = 0; /* unused by red_worker */
+ surface.mem = (uint64_t)&test->primary_surface;
+ surface.group_id = MEM_SLOT_GROUP_ID;
+
+ test->width = width;
+ test->height = height;
+
+ spice_qxl_create_primary_surface(&test->qxl_instance, 0, &surface);
+}
+
+QXLDevMemSlot slot = {
+.slot_group_id = MEM_SLOT_GROUP_ID,
+.slot_id = 0,
+.generation = 0,
+.virt_start = 0,
+.virt_end = ~0,
+.addr_delta = 0,
+.qxl_ram_size = ~0,
+};
+
+static void attache_worker(QXLInstance *qin, QXLWorker *_qxl_worker)
+{
+ Test *test = SPICE_CONTAINEROF(qin, Test, qxl_instance);
+
+ if (test->qxl_worker) {
+ if (test->qxl_worker != _qxl_worker)
+ printf("%s ignored, %p is set, ignoring new %p\n", __func__,
+ test->qxl_worker, _qxl_worker);
+ else
+ printf("%s ignored, redundant\n", __func__);
+ return;
+ }
+ printf("%s\n", __func__);
+ test->qxl_worker = _qxl_worker;
+ spice_qxl_add_memslot(&test->qxl_instance, &slot);
+ create_primary_surface(test, DEFAULT_WIDTH, DEFAULT_HEIGHT);
+ spice_server_vm_start(test->server);
+}
+
+static void set_compression_level(SPICE_GNUC_UNUSED QXLInstance *qin,
+ SPICE_GNUC_UNUSED int level)
+{
+ printf("%s\n", __func__);
+}
+
+static void set_mm_time(SPICE_GNUC_UNUSED QXLInstance *qin,
+ SPICE_GNUC_UNUSED uint32_t mm_time)
+{
+}
+
+// we now have a secondary surface
+#define MAX_SURFACE_NUM 2
+
+static void get_init_info(SPICE_GNUC_UNUSED QXLInstance *qin,
+ QXLDevInitInfo *info)
+{
+ memset(info, 0, sizeof(*info));
+ info->num_memslots = 1;
+ info->num_memslots_groups = 1;
+ info->memslot_id_bits = 1;
+ info->memslot_gen_bits = 1;
+ info->n_surfaces = MAX_SURFACE_NUM;
+}
+
+// We shall now have a ring of commands, so that we can update
+// it from a separate thread - since get_command is called from
+// the worker thread, and we need to sometimes do an update_area,
+// which cannot be done from red_worker context (not via dispatcher,
+// since you get a deadlock, and it isn't designed to be done
+// any other way, so no point testing that).
+int commands_end = 0;
+int commands_start = 0;
+struct QXLCommandExt* commands[1024];
+
+#define COMMANDS_SIZE COUNT(commands)
+
+static void push_command(QXLCommandExt *ext)
+{
+ spice_assert(commands_end - commands_start < (int) COMMANDS_SIZE);
+ commands[commands_end % COMMANDS_SIZE] = ext;
+ commands_end++;
+}
+
+static struct QXLCommandExt *get_simple_command(void)
+{
+ struct QXLCommandExt *ret = commands[commands_start % COMMANDS_SIZE];
+ spice_assert(commands_start < commands_end);
+ commands_start++;
+ return ret;
+}
+
+static int get_num_commands(void)
+{
+ return commands_end - commands_start;
+}
+
+// called from spice_server thread (i.e. red_worker thread)
+static int get_command(SPICE_GNUC_UNUSED QXLInstance *qin,
+ struct QXLCommandExt *ext)
+{
+ if (get_num_commands() == 0) {
+ return FALSE;
+ }
+ *ext = *get_simple_command();
+ return TRUE;
+}
+
+static void produce_command(Test *test)
+{
+ Command *command;
+ QXLWorker *qxl_worker = test->qxl_worker;
+
+ spice_assert(qxl_worker);
+
+ if (test->has_secondary)
+ test->target_surface = 1;
+
+ if (!test->num_commands) {
+ usleep(1000);
+ return;
+ }
+
+ command = &test->commands[test->cmd_index];
+ if (command->cb) {
+ command->cb(test, command);
+ }
+ switch (command->command) {
+ case SLEEP:
+ printf("sleep %u seconds\n", command->sleep.secs);
+ sleep(command->sleep.secs);
+ break;
+ case PATH_PROGRESS:
+ path_progress(&path);
+ break;
+ case SIMPLE_UPDATE: {
+ QXLRect rect = {
+ .left = 0,
+ .right = (test->target_surface == 0 ? test->primary_width : test->width),
+ .top = 0,
+ .bottom = (test->target_surface == 0 ? test->primary_height : test->height)
+ };
+ if (rect.right > 0 && rect.bottom > 0) {
+ spice_qxl_update_area(&test->qxl_instance, test->target_surface, &rect, NULL, 0, 1);
+ }
+ break;
+ }
+
+ /* Drawing commands, they all push a command to the command ring */
+ case SIMPLE_COPY_BITS:
+ case SIMPLE_DRAW_SOLID:
+ case SIMPLE_DRAW_BITMAP:
+ case SIMPLE_DRAW: {
+ SimpleSpiceUpdate *update;
+
+ if (has_automated_tests)
+ {
+ if (control == 0) {
+ return;
+ }
+
+ regression_test();
+ }
+
+ switch (command->command) {
+ case SIMPLE_COPY_BITS:
+ update = test_spice_create_update_copy_bits(test, 0);
+ break;
+ case SIMPLE_DRAW:
+ update = test_spice_create_update_draw(test, 0, path.t);
+ break;
+ case SIMPLE_DRAW_BITMAP:
+ update = test_spice_create_update_from_bitmap(command->bitmap.surface_id,
+ command->bitmap.bbox, command->bitmap.bitmap,
+ command->bitmap.num_clip_rects, command->bitmap.clip_rects);
+ break;
+ case SIMPLE_DRAW_SOLID:
+ update = test_spice_create_update_solid(command->solid.surface_id,
+ command->solid.bbox, command->solid.color);
+ break;
+ default: /* Just to shut up GCC warning (-Wswitch) */
+ break;
+ }
+ push_command(&update->ext);
+ break;
+ }
+
+ case SIMPLE_CREATE_SURFACE: {
+ SimpleSurfaceCmd *update;
+ if (command->create_surface.data) {
+ spice_assert(command->create_surface.surface_id > 0);
+ spice_assert(command->create_surface.surface_id < MAX_SURFACE_NUM);
+ spice_assert(command->create_surface.surface_id == 1);
+ update = create_surface(command->create_surface.surface_id,
+ command->create_surface.format,
+ command->create_surface.width,
+ command->create_surface.height,
+ command->create_surface.data);
+ } else {
+ update = create_surface(test->target_surface, SPICE_SURFACE_FMT_32_xRGB,
+ SURF_WIDTH, SURF_HEIGHT,
+ test->secondary_surface);
+ }
+ push_command(&update->ext);
+ test->has_secondary = 1;
+ break;
+ }
+
+ case SIMPLE_DESTROY_SURFACE: {
+ SimpleSurfaceCmd *update;
+ test->has_secondary = 0;
+ update = destroy_surface(test->target_surface);
+ test->target_surface = 0;
+ push_command(&update->ext);
+ break;
+ }
+
+ case DESTROY_PRIMARY:
+ spice_qxl_destroy_primary_surface(&test->qxl_instance, 0);
+ break;
+
+ case CREATE_PRIMARY:
+ create_primary_surface(test,
+ command->create_primary.width, command->create_primary.height);
+ break;
+ }
+ test->cmd_index = (test->cmd_index + 1) % test->num_commands;
+}
+
+static int req_cmd_notification(QXLInstance *qin)
+{
+ Test *test = SPICE_CONTAINEROF(qin, Test, qxl_instance);
+
+ test->core->timer_start(test->wakeup_timer, test->wakeup_ms);
+ return TRUE;
+}
+
+static void do_wakeup(void *opaque)
+{
+ Test *test = opaque;
+ int notify;
+
+ test->cursor_notify = NOTIFY_CURSOR_BATCH;
+ for (notify = NOTIFY_DISPLAY_BATCH; notify > 0;--notify) {
+ produce_command(test);
+ }
+
+ test->core->timer_start(test->wakeup_timer, test->wakeup_ms);
+ spice_qxl_wakeup(&test->qxl_instance);
+}
+
+static void release_resource(SPICE_GNUC_UNUSED QXLInstance *qin,
+ struct QXLReleaseInfoExt release_info)
+{
+ QXLCommandExt *ext = (QXLCommandExt*)(unsigned long)release_info.info->id;
+ //printf("%s\n", __func__);
+ spice_assert(release_info.group_id == MEM_SLOT_GROUP_ID);
+ switch (ext->cmd.type) {
+ case QXL_CMD_DRAW:
+ test_spice_destroy_update((void*)ext);
+ break;
+ case QXL_CMD_SURFACE:
+ free(ext);
+ break;
+ case QXL_CMD_CURSOR: {
+ QXLCursorCmd *cmd = (QXLCursorCmd *)(unsigned long)ext->cmd.data;
+ if (cmd->type == QXL_CURSOR_SET) {
+ free(cmd);
+ }
+ free(ext);
+ break;
+ }
+ default:
+ abort();
+ }
+}
+
+#define CURSOR_WIDTH 32
+#define CURSOR_HEIGHT 32
+
+static struct {
+ QXLCursor cursor;
+ uint8_t data[CURSOR_WIDTH * CURSOR_HEIGHT * 4]; // 32bit per pixel
+} cursor;
+
+static void cursor_init()
+{
+ cursor.cursor.header.unique = 0;
+ cursor.cursor.header.type = SPICE_CURSOR_TYPE_COLOR32;
+ cursor.cursor.header.width = CURSOR_WIDTH;
+ cursor.cursor.header.height = CURSOR_HEIGHT;
+ cursor.cursor.header.hot_spot_x = 0;
+ cursor.cursor.header.hot_spot_y = 0;
+ cursor.cursor.data_size = CURSOR_WIDTH * CURSOR_HEIGHT * 4;
+
+ // X drivers addes it to the cursor size because it could be
+ // cursor data information or another cursor related stuffs.
+ // Otherwise, the code will break in client/cursor.cpp side,
+ // that expect the data_size plus cursor information.
+ // Blame cursor protocol for this. :-)
+ cursor.cursor.data_size += 128;
+ cursor.cursor.chunk.data_size = cursor.cursor.data_size;
+ cursor.cursor.chunk.prev_chunk = cursor.cursor.chunk.next_chunk = 0;
+}
+
+static int get_cursor_command(QXLInstance *qin, struct QXLCommandExt *ext)
+{
+ Test *test = SPICE_CONTAINEROF(qin, Test, qxl_instance);
+ static int set = 1;
+ static int x = 0, y = 0;
+ QXLCursorCmd *cursor_cmd;
+ QXLCommandExt *cmd;
+
+ if (!test->cursor_notify) {
+ return FALSE;
+ }
+
+ test->cursor_notify--;
+ cmd = calloc(sizeof(QXLCommandExt), 1);
+ cursor_cmd = calloc(sizeof(QXLCursorCmd), 1);
+
+ cursor_cmd->release_info.id = (unsigned long)cmd;
+
+ if (set) {
+ cursor_cmd->type = QXL_CURSOR_SET;
+ cursor_cmd->u.set.position.x = 0;
+ cursor_cmd->u.set.position.y = 0;
+ cursor_cmd->u.set.visible = TRUE;
+ cursor_cmd->u.set.shape = (unsigned long)&cursor;
+ // Only a white rect (32x32) as cursor
+ memset(cursor.data, 255, sizeof(cursor.data));
+ set = 0;
+ } else {
+ cursor_cmd->type = QXL_CURSOR_MOVE;
+ cursor_cmd->u.position.x = x++ % test->primary_width;
+ cursor_cmd->u.position.y = y++ % test->primary_height;
+ }
+
+ cmd->cmd.data = (unsigned long)cursor_cmd;
+ cmd->cmd.type = QXL_CMD_CURSOR;
+ cmd->group_id = MEM_SLOT_GROUP_ID;
+ cmd->flags = 0;
+ *ext = *cmd;
+ //printf("%s\n", __func__);
+ return TRUE;
+}
+
+static int req_cursor_notification(SPICE_GNUC_UNUSED QXLInstance *qin)
+{
+ printf("%s\n", __func__);
+ return TRUE;
+}
+
+static void notify_update(SPICE_GNUC_UNUSED QXLInstance *qin,
+ SPICE_GNUC_UNUSED uint32_t update_id)
+{
+ printf("%s\n", __func__);
+}
+
+static int flush_resources(SPICE_GNUC_UNUSED QXLInstance *qin)
+{
+ printf("%s\n", __func__);
+ return TRUE;
+}
+
+static int client_monitors_config(SPICE_GNUC_UNUSED QXLInstance *qin,
+ VDAgentMonitorsConfig *monitors_config)
+{
+ if (!monitors_config) {
+ printf("%s: NULL monitors_config\n", __func__);
+ } else {
+ printf("%s: %d\n", __func__, monitors_config->num_of_monitors);
+ }
+ return 0;
+}
+
+static void set_client_capabilities(QXLInstance *qin,
+ uint8_t client_present,
+ uint8_t caps[58])
+{
+ Test *test = SPICE_CONTAINEROF(qin, Test, qxl_instance);
+
+ printf("%s: present %d caps %d\n", __func__, client_present, caps[0]);
+ if (test->on_client_connected && client_present) {
+ test->on_client_connected(test);
+ }
+ if (test->on_client_disconnected && !client_present) {
+ test->on_client_disconnected(test);
+ }
+}
+
+QXLInterface display_sif = {
+ .base = {
+ .type = SPICE_INTERFACE_QXL,
+ .description = "test",
+ .major_version = SPICE_INTERFACE_QXL_MAJOR,
+ .minor_version = SPICE_INTERFACE_QXL_MINOR
+ },
+ .attache_worker = attache_worker,
+ .set_compression_level = set_compression_level,
+ .set_mm_time = set_mm_time,
+ .get_init_info = get_init_info,
+
+ /* the callbacks below are called from spice server thread context */
+ .get_command = get_command,
+ .req_cmd_notification = req_cmd_notification,
+ .release_resource = release_resource,
+ .get_cursor_command = get_cursor_command,
+ .req_cursor_notification = req_cursor_notification,
+ .notify_update = notify_update,
+ .flush_resources = flush_resources,
+ .client_monitors_config = client_monitors_config,
+ .set_client_capabilities = set_client_capabilities,
+};
+
+/* interface for tests */
+void test_add_display_interface(Test* test)
+{
+ spice_server_add_interface(test->server, &test->qxl_instance.base);
+}
+
+static SpiceBaseInterface base = {
+ .type = SPICE_INTERFACE_CHAR_DEVICE,
+ .description = "test spice virtual channel char device",
+ .major_version = SPICE_INTERFACE_CHAR_DEVICE_MAJOR,
+ .minor_version = SPICE_INTERFACE_CHAR_DEVICE_MINOR,
+};
+
+SpiceCharDeviceInstance vdagent_sin = {
+ .base = {
+ .sif = &base,
+ },
+ .subtype = "vdagent",
+};
+
+void test_add_agent_interface(SpiceServer *server)
+{
+ spice_server_add_interface(server, &vdagent_sin.base);
+}
+
+void test_set_simple_command_list(Test *test, int *simple_commands, int num_commands)
+{
+ int i;
+
+ /* FIXME: leaks */
+ test->commands = malloc(sizeof(*test->commands) * num_commands);
+ memset(test->commands, 0, sizeof(*test->commands) * num_commands);
+ test->num_commands = num_commands;
+ for (i = 0 ; i < num_commands; ++i) {
+ test->commands[i].command = simple_commands[i];
+ }
+}
+
+void test_set_command_list(Test *test, Command *commands, int num_commands)
+{
+ test->commands = commands;
+ test->num_commands = num_commands;
+}
+
+
+Test *test_new(SpiceCoreInterface *core)
+{
+ int port = 5912;
+ Test *test = spice_new0(Test, 1);
+ SpiceServer* server = spice_server_new();
+
+ test->qxl_instance.base.sif = &display_sif.base;
+ test->qxl_instance.id = 0;
+
+ test->core = core;
+ test->server = server;
+ test->wakeup_ms = 1;
+ test->cursor_notify = NOTIFY_CURSOR_BATCH;
+ // some common initialization for all display tests
+ printf("TESTER: listening on port %d (unsecure)\n", port);
+ spice_server_set_port(server, port);
+ spice_server_set_noauth(server);
+ spice_server_init(server, core);
+
+ cursor_init();
+ path_init(&path, 0, angle_parts);
+ test->has_secondary = 0;
+ test->wakeup_timer = core->timer_add(do_wakeup, test);
+ return test;
+}
+
+void init_automated()
+{
+ struct sigaction sa;
+
+ memset(&sa, 0, sizeof sa);
+ sa.sa_handler = &sigchld_handler;
+ sigaction(SIGCHLD, &sa, NULL);
+}
+
+__attribute__((noreturn))
+void usage(const char *argv0, const int exitcode)
+{
+#ifdef AUTOMATED_TESTS
+ const char *autoopt=" [--automated-tests]";
+#else
+ const char *autoopt="";
+#endif
+
+ printf("usage: %s%s\n", argv0, autoopt);
+ exit(exitcode);
+}
+
+void spice_test_config_parse_args(int argc, char **argv)
+{
+ struct option options[] = {
+#ifdef AUTOMATED_TESTS
+ {"automated-tests", no_argument, &has_automated_tests, 1},
+#endif
+ {NULL, 0, NULL, 0},
+ };
+ int option_index;
+ int val;
+
+ while ((val = getopt_long(argc, argv, "", options, &option_index)) != -1) {
+ switch (val) {
+ case '?':
+ printf("unrecognized option '%s'\n", argv[optind - 1]);
+ usage(argv[0], EXIT_FAILURE);
+ case 0:
+ break;
+ }
+ }
+
+ if (argc > optind) {
+ printf("unknown argument '%s'\n", argv[optind]);
+ usage(argv[0], EXIT_FAILURE);
+ }
+ if (has_automated_tests) {
+ init_automated();
+ }
+ return;
+}
diff --git a/server/tests/test-display-base.h b/server/tests/test-display-base.h
new file mode 100644
index 0000000..7b5b509
--- /dev/null
+++ b/server/tests/test-display-base.h
@@ -0,0 +1,146 @@
+/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ Copyright (C) 2009-2015 Red Hat, Inc.
+
+ 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, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef __TEST_DISPLAY_BASE_H__
+#define __TEST_DISPLAY_BASE_H__
+
+#include <spice.h>
+#include "basic-event-loop.h"
+
+#define COUNT(x) ((sizeof(x)/sizeof(x[0])))
+
+/*
+ * simple queue for commands.
+ * each command can have up to two parameters (grow as needed)
+ *
+ * TODO: switch to gtk main loop. Then add gobject-introspection. then
+ * write tests in python/guile/whatever.
+ */
+typedef enum {
+ PATH_PROGRESS,
+ SIMPLE_CREATE_SURFACE,
+ SIMPLE_DRAW,
+ SIMPLE_DRAW_BITMAP,
+ SIMPLE_DRAW_SOLID,
+ SIMPLE_COPY_BITS,
+ SIMPLE_DESTROY_SURFACE,
+ SIMPLE_UPDATE,
+ DESTROY_PRIMARY,
+ CREATE_PRIMARY,
+ SLEEP
+} CommandType;
+
+typedef struct CommandCreatePrimary {
+ uint32_t width;
+ uint32_t height;
+} CommandCreatePrimary;
+
+typedef struct CommandCreateSurface {
+ uint32_t surface_id;
+ uint32_t format;
+ uint32_t width;
+ uint32_t height;
+ uint8_t *data;
+} CommandCreateSurface;
+
+typedef struct CommandDrawBitmap {
+ QXLRect bbox;
+ uint8_t *bitmap;
+ uint32_t surface_id;
+ uint32_t num_clip_rects;
+ QXLRect *clip_rects;
+} CommandDrawBitmap;
+
+typedef struct CommandDrawSolid {
+ QXLRect bbox;
+ uint32_t color;
+ uint32_t surface_id;
+} CommandDrawSolid;
+
+typedef struct CommandSleep {
+ uint32_t secs;
+} CommandSleep;
+
+typedef struct Command Command;
+typedef struct Test Test;
+
+struct Command {
+ CommandType command;
+ void (*cb)(Test *test, Command *command);
+ void *cb_opaque;
+ union {
+ CommandCreatePrimary create_primary;
+ CommandDrawBitmap bitmap;
+ CommandDrawSolid solid;
+ CommandSleep sleep;
+ CommandCreateSurface create_surface;
+ };
+};
+
+#define MAX_HEIGHT 2048
+#define MAX_WIDTH 2048
+
+#define SURF_WIDTH 320
+#define SURF_HEIGHT 240
+
+struct Test {
+ SpiceCoreInterface *core;
+ SpiceServer *server;
+
+ QXLInstance qxl_instance;
+ QXLWorker *qxl_worker;
+
+ uint8_t primary_surface[MAX_HEIGHT * MAX_WIDTH * 4];
+ int primary_height;
+ int primary_width;
+
+ SpiceTimer *wakeup_timer;
+ int wakeup_ms;
+
+ int cursor_notify;
+
+ uint8_t secondary_surface[SURF_WIDTH * SURF_HEIGHT * 4];
+ int has_secondary;
+
+ // Current mode (set by create_primary)
+ int width;
+ int height;
+
+ // qxl scripted rendering commands and io
+ Command *commands;
+ int num_commands;
+ int cmd_index;
+
+ int target_surface;
+
+ // callbacks
+ void (*on_client_connected)(Test *test);
+ void (*on_client_disconnected)(Test *test);
+};
+
+void test_set_simple_command_list(Test *test, int *command, int num_commands);
+void test_set_command_list(Test *test, Command *command, int num_commands);
+void test_add_display_interface(Test *test);
+void test_add_agent_interface(SpiceServer *server); // TODO - Test *test
+Test* test_new(SpiceCoreInterface* core);
+
+uint32_t test_get_width(void);
+uint32_t test_get_height(void);
+
+void spice_test_config_parse_args(int argc, char **argv);
+
+#endif /* __TEST_DISPLAY_BASE_H__ */
diff --git a/server/tests/test-display-no-ssl.c b/server/tests/test-display-no-ssl.c
new file mode 100644
index 0000000..8b3a09b
--- /dev/null
+++ b/server/tests/test-display-no-ssl.c
@@ -0,0 +1,72 @@
+/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ Copyright (C) 2009-2015 Red Hat, Inc.
+
+ 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * Test ground for developing specific tests.
+ *
+ * Any specific test can start of from here and set the server to the
+ * specific required state, and create specific operations or reuse
+ * existing ones in the test_display_base supplied queue.
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include "test-display-base.h"
+
+SpiceCoreInterface *core;
+SpiceTimer *ping_timer;
+
+void show_channels(SpiceServer *server);
+
+int ping_ms = 100;
+
+void pinger(SPICE_GNUC_UNUSED void *opaque)
+{
+ // show_channels is not thread safe - fails if disconnections / connections occur
+ //show_channels(server);
+
+ core->timer_start(ping_timer, ping_ms);
+}
+
+int simple_commands[] = {
+ //SIMPLE_CREATE_SURFACE,
+ //SIMPLE_DRAW,
+ //SIMPLE_DESTROY_SURFACE,
+ //PATH_PROGRESS,
+ SIMPLE_DRAW,
+ //SIMPLE_COPY_BITS,
+ SIMPLE_UPDATE,
+};
+
+int main(void)
+{
+ Test *test;
+
+ core = basic_event_loop_init();
+ test = test_new(core);
+ //spice_server_set_image_compression(server, SPICE_IMAGE_COMPRESSION_OFF);
+ test_add_display_interface(test);
+ test_add_agent_interface(test->server);
+ test_set_simple_command_list(test, simple_commands, COUNT(simple_commands));
+
+ ping_timer = core->timer_add(pinger, NULL);
+ core->timer_start(ping_timer, ping_ms);
+
+ basic_event_loop_mainloop();
+
+ return 0;
+}
diff --git a/server/tests/test-display-resolution-changes.c b/server/tests/test-display-resolution-changes.c
new file mode 100644
index 0000000..b68a648
--- /dev/null
+++ b/server/tests/test-display-resolution-changes.c
@@ -0,0 +1,86 @@
+/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ Copyright (C) 2009-2015 Red Hat, Inc.
+
+ 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * Recreate the primary surface endlessly.
+ */
+
+#include <config.h>
+#include <math.h>
+#include <stdlib.h>
+#include "test-display-base.h"
+
+SpiceTimer *ping_timer;
+
+void show_channels(SpiceServer *server);
+
+int ping_ms = 100;
+
+void pinger(void *opaque)
+{
+ Test *test = opaque;
+ // show_channels is not thread safe - fails if disconnections / connections occur
+ //show_channels(server);
+
+ test->core->timer_start(ping_timer, ping_ms);
+}
+
+void set_primary_params(SPICE_GNUC_UNUSED Test *test,
+ Command *command)
+{
+#if 0
+ static int toggle = 0;
+
+ if (toggle) {
+ *arg1 = 800;
+ *arg2 = 600;
+ } else {
+ *arg1 = 1024;
+ *arg2 = 768;
+ }
+ toggle = 1 - toggle;
+#endif
+ static int count = 0;
+
+ command->create_primary.width = 800 + sin((float)count / 6) * 200;
+ command->create_primary.height = 600 + cos((float)count / 6) * 200;
+ count++;
+}
+
+static Command commands[] = {
+ {DESTROY_PRIMARY, NULL, .cb_opaque = NULL,},
+ {CREATE_PRIMARY, set_primary_params, .cb_opaque = NULL},
+};
+
+int main(void)
+{
+ SpiceCoreInterface *core;
+ Test *test;
+
+ core = basic_event_loop_init();
+ test = test_new(core);
+ //spice_server_set_image_compression(server, SPICE_IMAGE_COMPRESSION_OFF);
+ test_add_display_interface(test);
+ test_set_command_list(test, commands, COUNT(commands));
+
+ ping_timer = core->timer_add(pinger, test);
+ core->timer_start(ping_timer, ping_ms);
+
+ basic_event_loop_mainloop();
+
+ return 0;
+}
diff --git a/server/tests/test-display-streaming.c b/server/tests/test-display-streaming.c
new file mode 100644
index 0000000..6e945fd
--- /dev/null
+++ b/server/tests/test-display-streaming.c
@@ -0,0 +1,253 @@
+/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ Copyright (C) 2009-2015 Red Hat, Inc.
+
+ 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, see <http://www.gnu.org/licenses/>.
+*/
+/* Do repeated updates to the same rectangle to trigger stream creation.
+ *
+ * TODO: check that stream actually starts programatically (maybe stap?)
+ * TODO: stop updating same rect, check (prog) that stream stops
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include <glib.h>
+
+#include "test-display-base.h"
+
+static int sized;
+static int render_last_frame;
+
+static void create_overlay(Command *command , int width, int height)
+{
+ CommandDrawBitmap *cmd = &command->bitmap;
+ uint32_t *dst;
+
+ cmd->surface_id = 0;
+
+ cmd->bbox.left = 0;
+ cmd->bbox.top = 0;
+ cmd->bbox.right = width;
+ cmd->bbox.bottom = height;
+
+ cmd->num_clip_rects = 0;
+ cmd->bitmap = g_malloc(width * height * 4 );
+ dst = (uint32_t *)cmd->bitmap;
+ for (int i = 0; i < width * height; i++, dst++) {
+ *dst = 0x8B008B;
+ }
+
+}
+
+#define NUM_COMMANDS 2000
+#define SIZED_INTERVAL 100
+#define OVERLAY_FRAME 500
+#define OVERLAY_WIDTH 200
+#define OVERLAY_HEIGHT 200
+
+/*
+ * Create a frame in a stream that displays a row that moves
+ * from the top to the bottom repeatedly.
+ * Upon the OVERLAY_FRAME-th, a drawable is created on top of a part of the stream,
+ * and from then on, all the stream frames has a clipping that keeps this drawable
+ * visible, and in addition a clipping_factor is subtracted from the right limit of their clipping.
+ * If sized=TRUE, a higher and wider frame than the original stream is created every SIZED_INTERVAL.
+ * The sized frames can be distinguished by a change in the color of the top and bottom limits of the
+ * surface.
+ */
+static void create_clipped_frame(Test *test, Command *command, int clipping_factor)
+{
+ static int count = 0;
+ CommandDrawBitmap *cmd = &command->bitmap;
+ int max_height = test->height;
+ int max_width = test->width;
+ int width;
+ int height;
+ int cur_line, end_line;
+ uint32_t *dst;
+
+ count++;
+ if (count == NUM_COMMANDS) {
+ count = 0;
+ }
+ if (count == OVERLAY_FRAME) {
+ create_overlay(command, OVERLAY_WIDTH, OVERLAY_HEIGHT);
+ return;
+ }
+
+ cmd->surface_id = 0;
+
+ cmd->bbox.left = 0;
+ cmd->bbox.right = max_width - 50;
+ assert(max_height > 600);
+ cmd->bbox.top = 50;
+ cmd->bbox.bottom = max_height - 50;
+ height = cmd->bbox.bottom - cmd->bbox.top;
+ width = cmd->bbox.right - cmd->bbox.left;
+ cur_line = (height/30)*(count % 30);
+ end_line = cur_line + (height/30);
+ if (end_line >= height || height - end_line < 8) {
+ end_line = height;
+ }
+
+ if (sized && count % SIZED_INTERVAL == 0) {
+
+ cmd->bbox.top = 0;
+ cmd->bbox.bottom = max_height;
+ cmd->bbox.left = 0;
+ cmd->bbox.right = max_width;
+ height = max_height;
+ width = max_width;
+ cur_line += 50;
+ end_line += 50;
+ }
+
+ cmd->bitmap = g_malloc(width*height*4);
+ memset(cmd->bitmap, 0xff, width*height*4);
+ dst = (uint32_t *)(cmd->bitmap + cur_line*width*4);
+ for (; cur_line < end_line; cur_line++) {
+ int col;
+ for (col = 0; col < width; col++, dst++) {
+ *dst = 0x00FF00;
+ }
+ }
+ if (sized && count % SIZED_INTERVAL == 0) {
+ int i;
+ uint32_t color = 0xffffff & rand();
+
+ dst = (uint32_t *)cmd->bitmap;
+
+ for (i = 0; i < 50*width; i++, dst++) {
+ *dst = color;
+ }
+
+ dst = ((uint32_t *)(cmd->bitmap + (height - 50)*4*width));
+
+ for (i = 0; i < 50*width; i++, dst++) {
+ *dst = color;
+ }
+ }
+
+ if (count < OVERLAY_FRAME) {
+ cmd->num_clip_rects = 0;
+ } else {
+ cmd->num_clip_rects = 2;
+ cmd->clip_rects = calloc(sizeof(QXLRect), 2);
+ cmd->clip_rects[0].left = OVERLAY_WIDTH;
+ cmd->clip_rects[0].top = cmd->bbox.top;
+ cmd->clip_rects[0].right = cmd->bbox.right - clipping_factor;
+ cmd->clip_rects[0].bottom = OVERLAY_HEIGHT;
+ cmd->clip_rects[1].left = cmd->bbox.left;
+ cmd->clip_rects[1].top = OVERLAY_HEIGHT;
+ cmd->clip_rects[1].right = cmd->bbox.right - clipping_factor;
+ cmd->clip_rects[1].bottom = cmd->bbox.bottom;
+ }
+}
+
+static void create_frame1(Test *test, Command *command)
+{
+ create_clipped_frame(test, command, 0);
+}
+
+void create_frame2(Test *test, Command *command)
+{
+ create_clipped_frame(test, command, 200);
+}
+
+typedef void (*create_frame_cb)(Test *test, Command *command);
+
+
+/*
+ * The test contains two types of streams. The first stream doesn't
+ * have a clipping besides the on that the display the overlay drawable.
+ * Expected result: If render_last_frame=false, the last frame should
+ * be sent losslessly. Otherwise, red_update_area should be called, and the
+ * stream is upgraded by a screenshot.
+ *
+ * In the second test, the stream clip changes in the middle (becomes smaller).
+ * Expected result: red_update_area should is, and the
+ * stream is upgraded by a screenshot (including lossy areas that belong to old frames
+ * and were never covered by a lossless drawable).
+ *
+ */
+static void get_stream_commands(Command *commands, int num_commands,
+ create_frame_cb cb)
+{
+ int i;
+
+ commands[0].command = DESTROY_PRIMARY;
+ commands[1].command = CREATE_PRIMARY;
+ commands[1].create_primary.width = 1280;
+ commands[1].create_primary.height = 1024;
+ commands[num_commands - 1].command = SLEEP;
+ commands[num_commands - 1].sleep.secs = 20;
+
+ for (i = 2; i < num_commands - 1; i++) {
+ commands[i].command = SIMPLE_DRAW_BITMAP;
+ commands[i].cb = cb;
+ }
+ if (render_last_frame) {
+ commands[num_commands - 2].command = SIMPLE_UPDATE;
+ }
+}
+
+static void get_commands(Command **commands, int *num_commands)
+{
+ *num_commands = NUM_COMMANDS * 2;
+ *commands = calloc(sizeof(Command), *num_commands);
+
+ get_stream_commands(*commands, NUM_COMMANDS, create_frame1);
+ get_stream_commands((*commands) + NUM_COMMANDS, NUM_COMMANDS, create_frame2);
+}
+
+
+int main(int argc, char **argv)
+{
+ SpiceCoreInterface *core;
+ Command *commands;
+ int num_commands;
+ int i;
+ Test *test;
+
+ spice_test_config_parse_args(argc, argv);
+ sized = 0;
+ for (i = 1 ; i < argc; ++i) {
+ if (strcmp(argv[i], "sized") == 0) {
+ sized = 1;
+ }
+ /* render last frame */
+ if (strcmp(argv[i], "render") == 0) {
+ render_last_frame = 1;
+ }
+ }
+ srand(time(NULL));
+ // todo: add args list of test numbers with explenations
+ core = basic_event_loop_init();
+ test = test_new(core);
+ spice_server_set_streaming_video(test->server, SPICE_STREAM_VIDEO_ALL);
+ test_add_display_interface(test);
+ get_commands(&commands, &num_commands);
+ test_set_command_list(test, commands, num_commands);
+ basic_event_loop_mainloop();
+ free(commands);
+ return 0;
+}
diff --git a/server/tests/test-display-width-stride.c b/server/tests/test-display-width-stride.c
new file mode 100644
index 0000000..dc44282
--- /dev/null
+++ b/server/tests/test-display-width-stride.c
@@ -0,0 +1,121 @@
+/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ Copyright (C) 2009-2015 Red Hat, Inc.
+
+ 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * Recreate the primary surface endlessly.
+ */
+
+#include <config.h>
+#include <math.h>
+#include <stdlib.h>
+#include "test-display-base.h"
+
+SpiceTimer *ping_timer;
+
+void show_channels(SpiceServer *server);
+
+int ping_ms = 100;
+
+void pinger(void *opaque)
+{
+ Test *test = opaque;
+ // show_channels is not thread safe - fails if disconnections / connections occur
+ //show_channels(server);
+
+ test->core->timer_start(ping_timer, ping_ms);
+}
+
+static int g_surface_id = 1;
+static uint8_t *g_surface_data;
+
+void set_draw_parameters(SPICE_GNUC_UNUSED Test *test,
+ Command *command)
+{
+ static int count = 17;
+ CommandDrawSolid *solid = &command->solid;
+
+ solid->bbox.top = 0;
+ solid->bbox.left = 0;
+ solid->bbox.bottom = 20;
+ solid->bbox.right = count;
+ solid->surface_id = g_surface_id;
+ count++;
+}
+
+void set_surface_params(SPICE_GNUC_UNUSED Test *test,
+ Command *command)
+{
+ CommandCreateSurface *create = &command->create_surface;
+
+ // UGLY
+ if (g_surface_data) {
+ exit(0);
+ }
+ create->format = SPICE_SURFACE_FMT_8_A;
+ create->width = 128;
+ create->height = 128;
+ g_surface_data = realloc(g_surface_data, create->width * create->height * 1);
+ create->surface_id = g_surface_id;
+ create->data = g_surface_data;
+}
+
+void set_destroy_parameters(SPICE_GNUC_UNUSED Test *test,
+ SPICE_GNUC_UNUSED Command *command)
+{
+ if (g_surface_data) {
+ free(g_surface_data);
+ g_surface_data = NULL;
+ }
+}
+
+static Command commands[] = {
+ {SIMPLE_CREATE_SURFACE, set_surface_params, .cb_opaque = NULL},
+ {SIMPLE_DRAW_SOLID, set_draw_parameters, .cb_opaque = NULL},
+ {SIMPLE_DRAW_SOLID, set_draw_parameters, .cb_opaque = NULL},
+ {SIMPLE_DRAW_SOLID, set_draw_parameters, .cb_opaque = NULL},
+ {SIMPLE_DRAW_SOLID, set_draw_parameters, .cb_opaque = NULL},
+ {SIMPLE_DRAW_SOLID, set_draw_parameters, .cb_opaque = NULL},
+ {SIMPLE_DRAW_SOLID, set_draw_parameters, .cb_opaque = NULL},
+ {SIMPLE_DRAW_SOLID, set_draw_parameters, .cb_opaque = NULL},
+ {SIMPLE_DRAW_SOLID, set_draw_parameters, .cb_opaque = NULL},
+ {SIMPLE_DRAW_SOLID, set_draw_parameters, .cb_opaque = NULL},
+ {SIMPLE_DESTROY_SURFACE, set_destroy_parameters, .cb_opaque = NULL},
+};
+
+void on_client_connected(Test *test)
+{
+ test_set_command_list(test, commands, COUNT(commands));
+}
+
+int main(void)
+{
+ SpiceCoreInterface *core;
+ Test *test;
+
+ core = basic_event_loop_init();
+ test = test_new(core);
+ test->on_client_connected = on_client_connected;
+ //spice_server_set_image_compression(server, SPICE_IMAGE_COMPRESSION_OFF);
+ test_add_display_interface(test);
+
+ ping_timer = core->timer_add(pinger, test);
+ core->timer_start(ping_timer, ping_ms);
+
+ basic_event_loop_mainloop();
+
+ return 0;
+}
diff --git a/server/tests/test-empty-success.c b/server/tests/test-empty-success.c
new file mode 100644
index 0000000..da98488
--- /dev/null
+++ b/server/tests/test-empty-success.c
@@ -0,0 +1,93 @@
+/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ Copyright (C) 2009-2015 Red Hat, Inc.
+
+ 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, see <http://www.gnu.org/licenses/>.
+*/
+#include <config.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <spice.h>
+
+struct SpiceTimer {
+ int a,b;
+};
+
+SpiceTimer* timer_add(SPICE_GNUC_UNUSED SpiceTimerFunc func,
+ SPICE_GNUC_UNUSED void *opaque)
+{
+ static struct SpiceTimer t = {0,};
+
+ return &t;
+}
+
+void timer_start(SPICE_GNUC_UNUSED SpiceTimer *timer,
+ SPICE_GNUC_UNUSED uint32_t ms)
+{
+}
+
+void timer_cancel(SPICE_GNUC_UNUSED SpiceTimer *timer)
+{
+}
+
+void timer_remove(SPICE_GNUC_UNUSED SpiceTimer *timer)
+{
+}
+
+SpiceWatch *watch_add(SPICE_GNUC_UNUSED int fd,
+ SPICE_GNUC_UNUSED int event_mask,
+ SPICE_GNUC_UNUSED SpiceWatchFunc func,
+ SPICE_GNUC_UNUSED void *opaque)
+{
+ return NULL;
+}
+
+void watch_update_mask(SPICE_GNUC_UNUSED SpiceWatch *watch,
+ SPICE_GNUC_UNUSED int event_mask)
+{
+}
+
+void watch_remove(SPICE_GNUC_UNUSED SpiceWatch *watch)
+{
+}
+
+void channel_event(SPICE_GNUC_UNUSED int event,
+ SPICE_GNUC_UNUSED SpiceChannelEventInfo *info)
+{
+}
+
+int main(void)
+{
+ SpiceServer *server = spice_server_new();
+ SpiceCoreInterface core;
+
+ memset(&core, 0, sizeof(core));
+ core.base.major_version = SPICE_INTERFACE_CORE_MAJOR;
+ core.timer_add = timer_add;
+ core.timer_start = timer_start;
+ core.timer_cancel = timer_cancel;
+ core.timer_remove = timer_remove;
+ core.watch_add = watch_add;
+ core.watch_update_mask = watch_update_mask;
+ core.watch_remove = watch_remove;
+ core.channel_event = channel_event;
+
+ spice_server_set_port(server, 5911);
+ spice_server_init(server, &core);
+
+ spice_server_destroy(server);
+
+ return 0;
+}
diff --git a/server/tests/test-fail-on-null-core-interface.c b/server/tests/test-fail-on-null-core-interface.c
new file mode 100644
index 0000000..48e92db
--- /dev/null
+++ b/server/tests/test-fail-on-null-core-interface.c
@@ -0,0 +1,30 @@
+/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ Copyright (C) 2009-2015 Red Hat, Inc.
+
+ 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, see <http://www.gnu.org/licenses/>.
+*/
+#include <config.h>
+#include <spice.h>
+
+int main(void)
+{
+ SpiceServer *server = spice_server_new();
+ SpiceCoreInterface core;
+
+ spice_server_init(server, &core);
+ spice_server_set_port(server, 5911);
+
+ return 0;
+}
diff --git a/server/tests/test-just-sockets-no-ssl.c b/server/tests/test-just-sockets-no-ssl.c
new file mode 100644
index 0000000..98def5a
--- /dev/null
+++ b/server/tests/test-just-sockets-no-ssl.c
@@ -0,0 +1,35 @@
+/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ Copyright (C) 2009-2015 Red Hat, Inc.
+
+ 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, see <http://www.gnu.org/licenses/>.
+*/
+#include <config.h>
+#include <sys/select.h>
+#include <spice.h>
+#include "basic-event-loop.h"
+
+int main(void)
+{
+ SpiceServer *server = spice_server_new();
+ SpiceCoreInterface *core = basic_event_loop_init();
+
+ spice_server_set_port(server, 5912);
+ spice_server_set_noauth(server);
+ spice_server_init(server, core);
+
+ basic_event_loop_mainloop();
+
+ return 0;
+}
diff --git a/server/tests/test-loop.c b/server/tests/test-loop.c
index c8d3fb1..1e3b39e 100644
--- a/server/tests/test-loop.c
+++ b/server/tests/test-loop.c
@@ -30,7 +30,7 @@
#include <spice/macros.h>
#include <common/log.h>
-#include "basic_event_loop.h"
+#include "basic-event-loop.h"
static SpiceCoreInterface *core = NULL;
static GMainLoop *loop = NULL;
diff --git a/server/tests/test-multiple.py b/server/tests/test-multiple.py
new file mode 100755
index 0000000..2497d93
--- /dev/null
+++ b/server/tests/test-multiple.py
@@ -0,0 +1,121 @@
+#!/usr/bin/python
+
+"""
+Example usage:
+./test-multiple.py test-display-no-ssl --log test.log
+
+Resulting test.log file (single test, stopped with Ctrl-C with 15 clients):
+
+0 162212
+1 154156
+2 154424
+3 154952
+4 155352
+5 155616
+6 156280
+7 222084
+8 222612
+9 230820
+10 230820
+11 230820
+12 230820
+13 296356
+14 296356
+
+"""
+
+import argparse
+import os
+import sys
+import subprocess
+import atexit
+import socket
+import time
+
+def killall(procs):
+ for p in procs:
+ print "killing %d" % p.pid
+ p.kill()
+ p.wait()
+
+def cleanup():
+ killall(clients + [test_process])
+
+def wait_for_port(port):
+ if not port:
+ return
+ # TODO: do this without actually opening the port - maybe just look at /proc/qemu_process_id/fd?
+ s = socket.socket(socket.AF_INET)
+ while True:
+ try:
+ s.connect(('localhost', port))
+ s.close()
+ break
+ except:
+ time.sleep(1)
+ pass
+
+def get_vm_size(pid):
+ """ read from /proc/<pid>/status, VmSize, in KiloBytes """
+ return int([x for x in open('/proc/%s/status' % pid).readlines() if 'VmSize' in x][0].split()[1])
+
+parser = argparse.ArgumentParser()
+parser.add_argument('--client', default='spicy')
+parser.add_argument('--start-count', default=1, type=int)
+parser.add_argument('--end-count', default=50, type=int)
+parser.add_argument('--log', default='-')
+parser.add_argument('--sleep', default=3, type=int)
+args, rest = parser.parse_known_args(sys.argv[1:])
+client = os.popen('which %s' % args.client).read().strip()
+if not os.path.exists(client):
+ print "supply a valid client. %s does not exist" % (args.client)
+ sys.exit(1)
+
+if not rest or len(rest) < 1 or not os.path.exists(rest[0]):
+ print "supply one argument that is the tester you wish to run"
+ sys.exit(1)
+
+prog = rest[0]
+port = {
+'test_display_no_ssl': 5912,
+'test_display_streaming': 5912,
+'test_just_sockets_no_ssl': 5912,
+'test_playback': 5701,
+}.get(prog, None)
+
+if args.log == '-':
+ log = sys.stdout
+else:
+ log = open(args.log, 'a+')
+
+log.write('#%s\n' % time.time())
+
+# kill leftovers from previous invocation
+os.system('killall lt-%s' % prog)
+
+if prog[0] != '/':
+ prog = os.path.join('.', prog)
+
+if not port:
+ print "unknown port for %r" % prog
+
+print "prog = %r" % prog
+print "client = %r" % client
+print "range = %d..%d" % (args.start_count, args.end_count)
+atexit.register(cleanup)
+os.environ['SPICE_DEBUG_ALLOW_MC'] = '1'
+test_process = subprocess.Popen([prog], executable=prog)
+wait_for_port(port)
+for count in xrange(args.start_count, args.end_count):
+ print "starting %d clients" % count
+ clients = [subprocess.Popen(args=[client, '-h', 'localhost', '-p', str(port)],
+ executable=client) for i in xrange(count)]
+ print "sleeping %d" % (args.sleep * count)
+ time.sleep(args.sleep * count)
+ vmsize = "%d %d" % (i, get_vm_size(test_process.pid))
+ print vmsize
+ log.write(vmsize + '\n')
+ log.flush()
+ killall(clients)
+
+test_process.wait()
diff --git a/server/tests/test-options.c b/server/tests/test-options.c
new file mode 100644
index 0000000..0cfd4b3
--- /dev/null
+++ b/server/tests/test-options.c
@@ -0,0 +1,61 @@
+/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ Copyright (C) 2016 Red Hat, Inc.
+
+ 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, see <http://www.gnu.org/licenses/>.
+*/
+#include <config.h>
+#include <glib.h>
+#include <spice.h>
+
+#include "basic-event-loop.h"
+
+/* GLIB_CHECK_VERSION(2, 40, 0) */
+#ifndef g_assert_nonnull
+#define g_assert_nonnull g_assert
+#endif
+
+static void agent_options(void)
+{
+ SpiceCoreInterface *core ;
+ SpiceServer *server = spice_server_new();
+
+ g_assert_nonnull(server);
+
+ core = basic_event_loop_init();
+ g_assert_nonnull(core);
+
+ /* test before init */
+ spice_server_set_agent_mouse(server, 0);
+ spice_server_set_agent_copypaste(server, 0);
+ spice_server_set_agent_file_xfer(server, 0);
+
+ g_assert_cmpint(spice_server_init(server, core), ==, 0);
+
+ /* test after init */
+ spice_server_set_agent_mouse(server, 0);
+ spice_server_set_agent_copypaste(server, 0);
+ spice_server_set_agent_file_xfer(server, 0);
+
+ spice_server_destroy(server);
+}
+
+int main(int argc, char *argv[])
+{
+ g_test_init(&argc, &argv, NULL);
+
+ g_test_add_func("/server/agent options", agent_options);
+
+ return g_test_run();
+}
diff --git a/server/tests/test-playback.c b/server/tests/test-playback.c
new file mode 100644
index 0000000..7dab278
--- /dev/null
+++ b/server/tests/test-playback.c
@@ -0,0 +1,126 @@
+/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ Copyright (C) 2009-2015 Red Hat, Inc.
+
+ 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, see <http://www.gnu.org/licenses/>.
+*/
+#include <config.h>
+#include <stdio.h>
+#include <sys/select.h>
+#include <sys/time.h>
+#include <math.h>
+
+#include <spice.h>
+#include "basic-event-loop.h"
+
+/* test the audio playback interface. Really basic no frils test - create
+ * a single tone sinus sound (easy to hear clicks if it is generated badly
+ * or is transmitted badly).
+ *
+ * TODO: Was going to do white noise to test compression too.
+ *
+ * TODO: gstreamer based test (could be used to play music files so
+ * it has actual merit. Also possibly to simulate network effects?)
+ * */
+
+SpicePlaybackInstance playback_instance;
+
+static const SpiceBaseInterface base = {
+ .type = SPICE_INTERFACE_PLAYBACK,
+ .description = "test playback",
+ .major_version = SPICE_INTERFACE_PLAYBACK_MAJOR,
+ .minor_version = SPICE_INTERFACE_PLAYBACK_MINOR,
+};
+
+uint32_t *frame;
+uint32_t num_samples;
+SpiceTimer *playback_timer;
+int playback_timer_ms;
+SpiceCoreInterface *core;
+
+static void get_frame(void)
+{
+ if (frame) {
+ return;
+ }
+ spice_server_playback_get_buffer(&playback_instance, &frame, &num_samples);
+ playback_timer_ms = num_samples
+ ? 1000 * num_samples / SPICE_INTERFACE_PLAYBACK_FREQ
+ : 100;
+}
+
+void playback_timer_cb(SPICE_GNUC_UNUSED void *opaque)
+{
+ static int t = 0;
+ static uint64_t last_sent_usec = 0;
+ static uint64_t samples_to_send;
+ uint32_t i;
+ struct timeval cur;
+ uint64_t cur_usec;
+
+ get_frame();
+ if (!frame) {
+ /* continue waiting until there is a channel */
+ core->timer_start(playback_timer, 100);
+ return;
+ }
+
+ /* we have a channel */
+ gettimeofday(&cur, NULL);
+ cur_usec = cur.tv_usec + cur.tv_sec * 1e6;
+ if (last_sent_usec == 0) {
+ samples_to_send = num_samples;
+ } else {
+ samples_to_send += (cur_usec - last_sent_usec) * SPICE_INTERFACE_PLAYBACK_FREQ / 1e6;
+ }
+ last_sent_usec = cur_usec;
+ while (samples_to_send > num_samples && frame) {
+#if 0
+ printf("samples_to_send = %d\n", samples_to_send);
+#endif
+ samples_to_send -= num_samples;
+ for (i = 0 ; i < num_samples; ++i) {
+ frame[i] = (((uint16_t)((1<<14)*sin((t+i)/10))) << 16) + (((uint16_t)((1<<14)*sin((t+i)/10))));
+ }
+ t += num_samples;
+ if (frame) {
+ spice_server_playback_put_samples(&playback_instance, frame);
+ frame = NULL;
+ }
+ get_frame();
+ }
+ core->timer_start(playback_timer, playback_timer_ms);
+}
+
+int main(void)
+{
+ SpiceServer *server = spice_server_new();
+ core = basic_event_loop_init();
+
+ spice_server_set_port(server, 5701);
+ spice_server_set_noauth(server);
+ spice_server_init(server, core);
+
+ playback_instance.base.sif = &base;
+ spice_server_add_interface(server, &playback_instance.base);
+ spice_server_playback_start(&playback_instance);
+
+ playback_timer_ms = 100;
+ playback_timer = core->timer_add(playback_timer_cb, NULL);
+ core->timer_start(playback_timer, playback_timer_ms);
+
+ basic_event_loop_mainloop();
+
+ return 0;
+}
diff --git a/server/tests/test-stat-file.c b/server/tests/test-stat-file.c
new file mode 100644
index 0000000..09b0c7a
--- /dev/null
+++ b/server/tests/test-stat-file.c
@@ -0,0 +1,105 @@
+/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ Copyright (C) 2016 Red Hat, Inc.
+
+ 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, see <http://www.gnu.org/licenses/>.
+*/
+#include <config.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <glib.h>
+#include <spice.h>
+
+#include "stat-file.h"
+
+/* GLIB_CHECK_VERSION(2, 40, 0) */
+#ifndef g_assert_nonnull
+#define g_assert_nonnull g_assert
+#endif
+#ifndef g_assert_null
+#define g_assert_null(ptr) g_assert((ptr) == NULL)
+#endif
+
+static void stat_file(void)
+{
+ RedStatFile *stat_file;
+ StatNodeRef ref, refs[10];
+ uint64_t *counter, *counters[10] SPICE_GNUC_UNUSED;
+ int i;
+ char *filename = NULL;
+ char name[20];
+
+ /* create */
+ stat_file = stat_file_new(10);
+
+ g_assert_nonnull(stat_file);
+ g_assert_nonnull(stat_file_get_shm_name(stat_file));
+ filename = strdup(stat_file_get_shm_name(stat_file));
+ g_assert(access(filename, R_OK));
+
+ /* fill all nodes */
+ for (i = 0; i < 10; ++i) {
+ sprintf(name, "node %d", i);
+ ref = stat_file_add_node(stat_file, INVALID_STAT_REF, name, TRUE);
+ refs[i] = ref;
+ g_assert_cmpuint(ref,!=,INVALID_STAT_REF);
+ }
+
+ /* should fail */
+ ref = stat_file_add_node(stat_file, INVALID_STAT_REF, "invalid", TRUE);
+ g_assert_cmpuint(ref,==,INVALID_STAT_REF);
+
+ /* we should find already present nodes */
+ for (i = 0; i < 10; ++i) {
+ /* the formula used here is to take nodes here and there.
+ * As 17 and 10 are coprime numbers you'll get the same numbers
+ * after 10 iterations */
+ sprintf(name, "node %d", (i * 17 + 5) % 10);
+ ref = stat_file_add_node(stat_file, INVALID_STAT_REF, name, TRUE);
+ g_assert_cmpuint(ref,!=,INVALID_STAT_REF);
+ }
+
+ /* delete some nodes */
+ for (i = 0; i < 6; ++i) {
+ /* see above why the formula is used */
+ int n = (i * 23 + 3) % 10;
+ stat_file_remove_node(stat_file, refs[n]);
+ refs[n] = INVALID_STAT_REF;
+ }
+
+ /* now there should be some place for some counters */
+ for (i = 0; i < 6; ++i) {
+ sprintf(name, "counter %d", i);
+ counter = stat_file_add_counter(stat_file, INVALID_STAT_REF, name, TRUE);
+ counters[i] = counter;
+ g_assert_nonnull(counter);
+ }
+ counter = stat_file_add_counter(stat_file, INVALID_STAT_REF, "invalid", TRUE);
+ g_assert_null(counter);
+
+ stat_file_unlink(stat_file);
+ g_assert_null(stat_file_get_shm_name(stat_file));
+ g_assert_cmpint(access(filename, F_OK),==,-1);
+ free(filename);
+}
+
+int main(int argc, char *argv[])
+{
+ g_test_init(&argc, &argv, NULL);
+
+ g_test_add_func("/server/stat-file", stat_file);
+
+ return g_test_run();
+}
diff --git a/server/tests/test-stream.c b/server/tests/test-stream.c
new file mode 100644
index 0000000..8f653b2
--- /dev/null
+++ b/server/tests/test-stream.c
@@ -0,0 +1,157 @@
+/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ Copyright (C) 2016 Red Hat, Inc.
+
+ 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, see <http://www.gnu.org/licenses/>.
+*/
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include <common/log.h>
+#include "reds-stream.h"
+#include "basic-event-loop.h"
+
+static SpiceServer *server = NULL;
+
+static int server_init(void)
+{
+ SpiceCoreInterface *core = basic_event_loop_init();
+ server = spice_server_new();
+
+ return spice_server_init(server, core);
+}
+
+
+/*
+ * Based on code from Keith Packard:
+ * http://keithp.com/blogs/fd-passing/
+ */
+static ssize_t
+sock_fd_read(int sock, void *buf, ssize_t bufsize, int *fd)
+{
+ ssize_t size;
+
+ if (fd) {
+ struct msghdr msg;
+ struct iovec iov;
+ union {
+ struct cmsghdr cmsghdr;
+ char control[CMSG_SPACE(sizeof (int))];
+ } cmsgu;
+ struct cmsghdr *cmsg;
+
+ iov.iov_base = buf;
+ iov.iov_len = bufsize;
+
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = cmsgu.control;
+ msg.msg_controllen = sizeof(cmsgu.control);
+ size = recvmsg(sock, &msg, 0);
+ if (size < 0) {
+ perror ("recvmsg");
+ exit(1);
+ }
+ cmsg = CMSG_FIRSTHDR(&msg);
+ if (cmsg && cmsg->cmsg_len == CMSG_LEN(sizeof(int))) {
+ if (cmsg->cmsg_level != SOL_SOCKET) {
+ fprintf(stderr, "invalid cmsg_level %d\n",
+ cmsg->cmsg_level);
+ exit(1);
+ }
+ if (cmsg->cmsg_type != SCM_RIGHTS) {
+ fprintf(stderr, "invalid cmsg_type %d\n",
+ cmsg->cmsg_type);
+ exit(1);
+ }
+
+ memcpy(fd, CMSG_DATA(cmsg), sizeof(*fd));
+ } else
+ *fd = -1;
+ } else {
+ size = read(sock, buf, bufsize);
+ if (size < 0) {
+ perror("read");
+ exit(1);
+ }
+ }
+
+ return size;
+}
+
+int main(int argc, char *argv[])
+{
+ RedsStream *st[2];
+ int sv[2];
+ int ret, fd = -1;
+ char c;
+
+ spice_return_val_if_fail(server_init() == 0, -1);
+
+ if (socketpair(AF_LOCAL, SOCK_STREAM, 0, sv) == -1) {
+ spice_error("socketpair failed %s", strerror(errno));
+ return -1;
+ }
+
+ st[0] = reds_stream_new(server, sv[0]);
+ spice_assert(reds_stream_is_plain_unix(st[0]));
+ st[1] = reds_stream_new(server, sv[1]);
+ spice_assert(reds_stream_is_plain_unix(st[1]));
+
+ /* send stdin, for the fun of it */
+ ret = reds_stream_send_msgfd(st[0], 0);
+ spice_assert(ret == 1);
+ ret = sock_fd_read(sv[1], &c, 1, &fd);
+ spice_assert(c == '@');
+ spice_assert(ret == 1);
+ spice_assert(fd != -1);
+ close(fd);
+
+ /* send invalid fd behaviour */
+ ret = reds_stream_send_msgfd(st[0], -1);
+ spice_assert(ret == 1);
+ ret = sock_fd_read(sv[1], &c, 1, &fd);
+ spice_assert(c == '@');
+ spice_assert(ret == 1);
+ spice_assert(fd == -1);
+
+ /* batch test */
+ ret = reds_stream_send_msgfd(st[0], 0);
+ spice_assert(ret == 1);
+ ret = reds_stream_send_msgfd(st[0], 0);
+ spice_assert(ret == 1);
+ ret = sock_fd_read(sv[1], &c, 1, &fd);
+ spice_assert(c == '@');
+ spice_assert(ret == 1);
+ spice_assert(fd != -1);
+ close(fd);
+ ret = sock_fd_read(sv[1], &c, 1, &fd);
+ spice_assert(c == '@');
+ spice_assert(ret == 1);
+ spice_assert(fd != -1);
+ close(fd);
+
+ reds_stream_free(st[0]);
+ reds_stream_free(st[1]);
+
+ return 0;
+}
diff --git a/server/tests/test-two-servers.c b/server/tests/test-two-servers.c
new file mode 100644
index 0000000..4cf451a
--- /dev/null
+++ b/server/tests/test-two-servers.c
@@ -0,0 +1,54 @@
+/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ Copyright (C) 2009-2015 Red Hat, Inc.
+
+ 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * Test two servers on one main loop.
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include "test-display-base.h"
+
+SpiceCoreInterface *core;
+
+int simple_commands[] = {
+ //SIMPLE_CREATE_SURFACE,
+ //SIMPLE_DRAW,
+ //SIMPLE_DESTROY_SURFACE,
+ //PATH_PROGRESS,
+ SIMPLE_DRAW,
+ //SIMPLE_COPY_BITS,
+ SIMPLE_UPDATE,
+};
+
+int main(void)
+{
+ Test *t1;
+ Test *t2;
+
+ core = basic_event_loop_init();
+ t1 = test_new(core);
+ t2 = test_new(core);
+ //spice_server_set_image_compression(server, SPICE_IMAGE_COMPRESSION_OFF);
+ test_add_display_interface(t1);
+ test_add_display_interface(t2);
+ test_set_simple_command_list(t1, simple_commands, COUNT(simple_commands));
+ test_set_simple_command_list(t2, simple_commands, COUNT(simple_commands));
+
+ basic_event_loop_mainloop();
+ return 0;
+}
diff --git a/server/tests/test-vdagent.c b/server/tests/test-vdagent.c
new file mode 100644
index 0000000..a3fa345
--- /dev/null
+++ b/server/tests/test-vdagent.c
@@ -0,0 +1,75 @@
+/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ Copyright (C) 2009-2015 Red Hat, Inc.
+
+ 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, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * Test vdagent guest to server messages
+ */
+
+#include <config.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <spice/vd_agent.h>
+
+#include "test-display-base.h"
+
+SpiceCoreInterface *core;
+SpiceTimer *ping_timer;
+
+int ping_ms = 100;
+
+#ifndef MIN
+#define MIN(a, b) ((a) > (b) ? (b) : (a))
+#endif
+
+void pinger(SPICE_GNUC_UNUSED void *opaque)
+{
+ // show_channels is not thread safe - fails if disconnections / connections occur
+ //show_channels(server);
+
+ core->timer_start(ping_timer, ping_ms);
+}
+
+static SpiceBaseInterface base = {
+ .type = SPICE_INTERFACE_CHAR_DEVICE,
+ .description = "test spice virtual channel char device",
+ .major_version = SPICE_INTERFACE_CHAR_DEVICE_MAJOR,
+ .minor_version = SPICE_INTERFACE_CHAR_DEVICE_MINOR,
+};
+
+SpiceCharDeviceInstance vmc_instance = {
+ .subtype = "vdagent",
+};
+
+int main(void)
+{
+ Test *test;
+
+ core = basic_event_loop_init();
+ test = test_new(core);
+
+ vmc_instance.base.sif = &base;
+ spice_server_add_interface(test->server, &vmc_instance.base);
+
+ ping_timer = core->timer_add(pinger, NULL);
+ core->timer_start(ping_timer, ping_ms);
+
+ basic_event_loop_mainloop();
+
+ return 0;
+}
diff --git a/server/tests/test_display_base.c b/server/tests/test_display_base.c
deleted file mode 100644
index 8e577c9..0000000
--- a/server/tests/test_display_base.c
+++ /dev/null
@@ -1,932 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2009-2015 Red Hat, Inc.
-
- 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, see <http://www.gnu.org/licenses/>.
-*/
-#include <config.h>
-#include <stdlib.h>
-#include <math.h>
-#include <string.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <signal.h>
-#include <wait.h>
-#include <sys/select.h>
-#include <sys/types.h>
-#include <getopt.h>
-
-#include "spice.h"
-#include <spice/qxl_dev.h>
-
-#include "test_display_base.h"
-#include "red-channel.h"
-
-#ifndef PATH_MAX
-#define PATH_MAX 4096
-#endif
-
-#define MEM_SLOT_GROUP_ID 0
-
-#define NOTIFY_DISPLAY_BATCH (SINGLE_PART/2)
-#define NOTIFY_CURSOR_BATCH 10
-
-/* Parts cribbed from spice-display.h/.c/qxl.c */
-
-typedef struct SimpleSpiceUpdate {
- QXLCommandExt ext; // first
- QXLDrawable drawable;
- QXLImage image;
- uint8_t *bitmap;
-} SimpleSpiceUpdate;
-
-typedef struct SimpleSurfaceCmd {
- QXLCommandExt ext; // first
- QXLSurfaceCmd surface_cmd;
-} SimpleSurfaceCmd;
-
-static void test_spice_destroy_update(SimpleSpiceUpdate *update)
-{
- if (!update) {
- return;
- }
- if (update->drawable.clip.type != SPICE_CLIP_TYPE_NONE) {
- uint8_t *ptr = (uint8_t*)update->drawable.clip.data;
- free(ptr);
- }
- free(update->bitmap);
- free(update);
-}
-
-#define DEFAULT_WIDTH 640
-#define DEFAULT_HEIGHT 320
-
-#define SINGLE_PART 4
-static const int angle_parts = 64 / SINGLE_PART;
-static int unique = 1;
-static int color = -1;
-static int c_i = 0;
-
-/* Used for automated tests */
-static int control = 3; //used to know when we can take a screenshot
-static int rects = 16; //number of rects that will be draw
-static int has_automated_tests = 0; //automated test flag
-
-__attribute__((noreturn))
-static void sigchld_handler(SPICE_GNUC_UNUSED int signal_num) // wait for the child process and exit
-{
- int status;
- wait(&status);
- exit(0);
-}
-
-static void regression_test(void)
-{
- pid_t pid;
-
- if (--rects != 0) {
- return;
- }
-
- rects = 16;
-
- if (--control != 0) {
- return;
- }
-
- pid = fork();
- if (pid == 0) {
- char buf[PATH_MAX];
- char *argv[] = { NULL };
- char *envp[] = {buf, NULL};
-
- snprintf(buf, sizeof(buf), "PATH=%s", getenv("PATH"));
- execve("regression_test.py", argv, envp);
- } else if (pid > 0) {
- return;
- }
-}
-
-static void set_cmd(QXLCommandExt *ext, uint32_t type, QXLPHYSICAL data)
-{
- ext->cmd.type = type;
- ext->cmd.data = data;
- ext->cmd.padding = 0;
- ext->group_id = MEM_SLOT_GROUP_ID;
- ext->flags = 0;
-}
-
-static void simple_set_release_info(QXLReleaseInfo *info, intptr_t ptr)
-{
- info->id = ptr;
- //info->group_id = MEM_SLOT_GROUP_ID;
-}
-
-typedef struct Path {
- int t;
- int min_t;
- int max_t;
-} Path;
-
-static void path_init(Path *path, int min, int max)
-{
- path->t = min;
- path->min_t = min;
- path->max_t = max;
-}
-
-static void path_progress(Path *path)
-{
- path->t = (path->t+1)% (path->max_t - path->min_t) + path->min_t;
-}
-
-Path path;
-
-static void draw_pos(Test *test, int t, int *x, int *y)
-{
-#ifdef CIRCLE
- *y = test->primary_height/2 + (test->primary_height/3)*cos(t*2*M_PI/angle_parts);
- *x = test->primary_width/2 + (test->primary_width/3)*sin(t*2*M_PI/angle_parts);
-#else
- *y = test->primary_height*(t % SINGLE_PART)/SINGLE_PART;
- *x = ((test->primary_width/SINGLE_PART)*(t / SINGLE_PART)) % test->primary_width;
-#endif
-}
-
-/* bitmap and rects are freed, so they must be allocated with malloc */
-SimpleSpiceUpdate *test_spice_create_update_from_bitmap(uint32_t surface_id,
- QXLRect bbox,
- uint8_t *bitmap,
- uint32_t num_clip_rects,
- QXLRect *clip_rects)
-{
- SimpleSpiceUpdate *update;
- QXLDrawable *drawable;
- QXLImage *image;
- uint32_t bw, bh;
-
- bh = bbox.bottom - bbox.top;
- bw = bbox.right - bbox.left;
-
- update = calloc(sizeof(*update), 1);
- update->bitmap = bitmap;
- drawable = &update->drawable;
- image = &update->image;
-
- drawable->surface_id = surface_id;
-
- drawable->bbox = bbox;
- if (num_clip_rects == 0) {
- drawable->clip.type = SPICE_CLIP_TYPE_NONE;
- } else {
- QXLClipRects *cmd_clip;
-
- cmd_clip = calloc(sizeof(QXLClipRects) + num_clip_rects*sizeof(QXLRect), 1);
- cmd_clip->num_rects = num_clip_rects;
- cmd_clip->chunk.data_size = num_clip_rects*sizeof(QXLRect);
- cmd_clip->chunk.prev_chunk = cmd_clip->chunk.next_chunk = 0;
- memcpy(cmd_clip + 1, clip_rects, cmd_clip->chunk.data_size);
-
- drawable->clip.type = SPICE_CLIP_TYPE_RECTS;
- drawable->clip.data = (intptr_t)cmd_clip;
-
- free(clip_rects);
- }
- drawable->effect = QXL_EFFECT_OPAQUE;
- simple_set_release_info(&drawable->release_info, (intptr_t)update);
- drawable->type = QXL_DRAW_COPY;
- drawable->surfaces_dest[0] = -1;
- drawable->surfaces_dest[1] = -1;
- drawable->surfaces_dest[2] = -1;
-
- drawable->u.copy.rop_descriptor = SPICE_ROPD_OP_PUT;
- drawable->u.copy.src_bitmap = (intptr_t)image;
- drawable->u.copy.src_area.right = bw;
- drawable->u.copy.src_area.bottom = bh;
-
- QXL_SET_IMAGE_ID(image, QXL_IMAGE_GROUP_DEVICE, unique);
- image->descriptor.type = SPICE_IMAGE_TYPE_BITMAP;
- image->bitmap.flags = QXL_BITMAP_DIRECT | QXL_BITMAP_TOP_DOWN;
- image->bitmap.stride = bw * 4;
- image->descriptor.width = image->bitmap.x = bw;
- image->descriptor.height = image->bitmap.y = bh;
- image->bitmap.data = (intptr_t)bitmap;
- image->bitmap.palette = 0;
- image->bitmap.format = SPICE_BITMAP_FMT_32BIT;
-
- set_cmd(&update->ext, QXL_CMD_DRAW, (intptr_t)drawable);
-
- return update;
-}
-
-static SimpleSpiceUpdate *test_spice_create_update_solid(uint32_t surface_id, QXLRect bbox, uint32_t color)
-{
- uint8_t *bitmap;
- uint32_t *dst;
- uint32_t bw;
- uint32_t bh;
- uint32_t i;
-
- bw = bbox.right - bbox.left;
- bh = bbox.bottom - bbox.top;
-
- bitmap = malloc(bw * bh * 4);
- dst = (uint32_t *)bitmap;
-
- for (i = 0 ; i < bh * bw ; ++i, ++dst) {
- *dst = color;
- }
-
- return test_spice_create_update_from_bitmap(surface_id, bbox, bitmap, 0, NULL);
-}
-
-static SimpleSpiceUpdate *test_spice_create_update_draw(Test *test, uint32_t surface_id, int t)
-{
- int top, left;
- uint8_t *dst;
- uint8_t *bitmap;
- int bw, bh;
- int i;
- QXLRect bbox;
-
- draw_pos(test, t, &left, &top);
- if ((t % angle_parts) == 0) {
- c_i++;
- }
-
- if (surface_id != 0) {
- color = (color + 1) % 2;
- } else {
- color = surface_id;
- }
-
- unique++;
-
- bw = test->primary_width/SINGLE_PART;
- bh = 48;
-
- bitmap = dst = malloc(bw * bh * 4);
- //printf("allocated %p\n", dst);
-
- for (i = 0 ; i < bh * bw ; ++i, dst+=4) {
- *dst = (color+i % 255);
- *(dst+((1+c_i)%3)) = 255 - color;
- *(dst+((2+c_i)%3)) = (color * (color + i)) & 0xff;
- *(dst+((3+c_i)%3)) = 0;
- }
-
- bbox.left = left; bbox.top = top;
- bbox.right = left + bw; bbox.bottom = top + bh;
- return test_spice_create_update_from_bitmap(surface_id, bbox, bitmap, 0, NULL);
-}
-
-static SimpleSpiceUpdate *test_spice_create_update_copy_bits(Test *test, uint32_t surface_id)
-{
- SimpleSpiceUpdate *update;
- QXLDrawable *drawable;
- int bw, bh;
- QXLRect bbox = {
- .left = 10,
- .top = 0,
- };
-
- update = calloc(sizeof(*update), 1);
- drawable = &update->drawable;
-
- bw = test->primary_width/SINGLE_PART;
- bh = 48;
- bbox.right = bbox.left + bw;
- bbox.bottom = bbox.top + bh;
- //printf("allocated %p, %p\n", update, update->bitmap);
-
- drawable->surface_id = surface_id;
-
- drawable->bbox = bbox;
- drawable->clip.type = SPICE_CLIP_TYPE_NONE;
- drawable->effect = QXL_EFFECT_OPAQUE;
- simple_set_release_info(&drawable->release_info, (intptr_t)update);
- drawable->type = QXL_COPY_BITS;
- drawable->surfaces_dest[0] = -1;
- drawable->surfaces_dest[1] = -1;
- drawable->surfaces_dest[2] = -1;
-
- drawable->u.copy_bits.src_pos.x = 0;
- drawable->u.copy_bits.src_pos.y = 0;
-
- set_cmd(&update->ext, QXL_CMD_DRAW, (intptr_t)drawable);
-
- return update;
-}
-
-static int format_to_bpp(int format)
-{
- switch (format) {
- case SPICE_SURFACE_FMT_8_A:
- return 1;
- case SPICE_SURFACE_FMT_16_555:
- case SPICE_SURFACE_FMT_16_565:
- return 2;
- case SPICE_SURFACE_FMT_32_xRGB:
- case SPICE_SURFACE_FMT_32_ARGB:
- return 4;
- }
- abort();
-}
-
-static SimpleSurfaceCmd *create_surface(int surface_id, int format, int width, int height, uint8_t *data)
-{
- SimpleSurfaceCmd *simple_cmd = calloc(sizeof(SimpleSurfaceCmd), 1);
- QXLSurfaceCmd *surface_cmd = &simple_cmd->surface_cmd;
- int bpp = format_to_bpp(format);
-
- set_cmd(&simple_cmd->ext, QXL_CMD_SURFACE, (intptr_t)surface_cmd);
- simple_set_release_info(&surface_cmd->release_info, (intptr_t)simple_cmd);
- surface_cmd->type = QXL_SURFACE_CMD_CREATE;
- surface_cmd->flags = 0; // ?
- surface_cmd->surface_id = surface_id;
- surface_cmd->u.surface_create.format = format;
- surface_cmd->u.surface_create.width = width;
- surface_cmd->u.surface_create.height = height;
- surface_cmd->u.surface_create.stride = -width * bpp;
- surface_cmd->u.surface_create.data = (intptr_t)data;
- return simple_cmd;
-}
-
-static SimpleSurfaceCmd *destroy_surface(int surface_id)
-{
- SimpleSurfaceCmd *simple_cmd = calloc(sizeof(SimpleSurfaceCmd), 1);
- QXLSurfaceCmd *surface_cmd = &simple_cmd->surface_cmd;
-
- set_cmd(&simple_cmd->ext, QXL_CMD_SURFACE, (intptr_t)surface_cmd);
- simple_set_release_info(&surface_cmd->release_info, (intptr_t)simple_cmd);
- surface_cmd->type = QXL_SURFACE_CMD_DESTROY;
- surface_cmd->flags = 0; // ?
- surface_cmd->surface_id = surface_id;
- return simple_cmd;
-}
-
-static void create_primary_surface(Test *test, uint32_t width,
- uint32_t height)
-{
- QXLDevSurfaceCreate surface = { 0, };
-
- spice_assert(height <= MAX_HEIGHT);
- spice_assert(width <= MAX_WIDTH);
- spice_assert(height > 0);
- spice_assert(width > 0);
-
- surface.format = SPICE_SURFACE_FMT_32_xRGB;
- surface.width = test->primary_width = width;
- surface.height = test->primary_height = height;
- surface.stride = -width * 4; /* negative? */
- surface.mouse_mode = TRUE; /* unused by red_worker */
- surface.flags = 0;
- surface.type = 0; /* unused by red_worker */
- surface.position = 0; /* unused by red_worker */
- surface.mem = (uint64_t)&test->primary_surface;
- surface.group_id = MEM_SLOT_GROUP_ID;
-
- test->width = width;
- test->height = height;
-
- spice_qxl_create_primary_surface(&test->qxl_instance, 0, &surface);
-}
-
-QXLDevMemSlot slot = {
-.slot_group_id = MEM_SLOT_GROUP_ID,
-.slot_id = 0,
-.generation = 0,
-.virt_start = 0,
-.virt_end = ~0,
-.addr_delta = 0,
-.qxl_ram_size = ~0,
-};
-
-static void attache_worker(QXLInstance *qin, QXLWorker *_qxl_worker)
-{
- Test *test = SPICE_CONTAINEROF(qin, Test, qxl_instance);
-
- if (test->qxl_worker) {
- if (test->qxl_worker != _qxl_worker)
- printf("%s ignored, %p is set, ignoring new %p\n", __func__,
- test->qxl_worker, _qxl_worker);
- else
- printf("%s ignored, redundant\n", __func__);
- return;
- }
- printf("%s\n", __func__);
- test->qxl_worker = _qxl_worker;
- spice_qxl_add_memslot(&test->qxl_instance, &slot);
- create_primary_surface(test, DEFAULT_WIDTH, DEFAULT_HEIGHT);
- spice_server_vm_start(test->server);
-}
-
-static void set_compression_level(SPICE_GNUC_UNUSED QXLInstance *qin,
- SPICE_GNUC_UNUSED int level)
-{
- printf("%s\n", __func__);
-}
-
-static void set_mm_time(SPICE_GNUC_UNUSED QXLInstance *qin,
- SPICE_GNUC_UNUSED uint32_t mm_time)
-{
-}
-
-// we now have a secondary surface
-#define MAX_SURFACE_NUM 2
-
-static void get_init_info(SPICE_GNUC_UNUSED QXLInstance *qin,
- QXLDevInitInfo *info)
-{
- memset(info, 0, sizeof(*info));
- info->num_memslots = 1;
- info->num_memslots_groups = 1;
- info->memslot_id_bits = 1;
- info->memslot_gen_bits = 1;
- info->n_surfaces = MAX_SURFACE_NUM;
-}
-
-// We shall now have a ring of commands, so that we can update
-// it from a separate thread - since get_command is called from
-// the worker thread, and we need to sometimes do an update_area,
-// which cannot be done from red_worker context (not via dispatcher,
-// since you get a deadlock, and it isn't designed to be done
-// any other way, so no point testing that).
-int commands_end = 0;
-int commands_start = 0;
-struct QXLCommandExt* commands[1024];
-
-#define COMMANDS_SIZE COUNT(commands)
-
-static void push_command(QXLCommandExt *ext)
-{
- spice_assert(commands_end - commands_start < (int) COMMANDS_SIZE);
- commands[commands_end % COMMANDS_SIZE] = ext;
- commands_end++;
-}
-
-static struct QXLCommandExt *get_simple_command(void)
-{
- struct QXLCommandExt *ret = commands[commands_start % COMMANDS_SIZE];
- spice_assert(commands_start < commands_end);
- commands_start++;
- return ret;
-}
-
-static int get_num_commands(void)
-{
- return commands_end - commands_start;
-}
-
-// called from spice_server thread (i.e. red_worker thread)
-static int get_command(SPICE_GNUC_UNUSED QXLInstance *qin,
- struct QXLCommandExt *ext)
-{
- if (get_num_commands() == 0) {
- return FALSE;
- }
- *ext = *get_simple_command();
- return TRUE;
-}
-
-static void produce_command(Test *test)
-{
- Command *command;
- QXLWorker *qxl_worker = test->qxl_worker;
-
- spice_assert(qxl_worker);
-
- if (test->has_secondary)
- test->target_surface = 1;
-
- if (!test->num_commands) {
- usleep(1000);
- return;
- }
-
- command = &test->commands[test->cmd_index];
- if (command->cb) {
- command->cb(test, command);
- }
- switch (command->command) {
- case SLEEP:
- printf("sleep %u seconds\n", command->sleep.secs);
- sleep(command->sleep.secs);
- break;
- case PATH_PROGRESS:
- path_progress(&path);
- break;
- case SIMPLE_UPDATE: {
- QXLRect rect = {
- .left = 0,
- .right = (test->target_surface == 0 ? test->primary_width : test->width),
- .top = 0,
- .bottom = (test->target_surface == 0 ? test->primary_height : test->height)
- };
- if (rect.right > 0 && rect.bottom > 0) {
- spice_qxl_update_area(&test->qxl_instance, test->target_surface, &rect, NULL, 0, 1);
- }
- break;
- }
-
- /* Drawing commands, they all push a command to the command ring */
- case SIMPLE_COPY_BITS:
- case SIMPLE_DRAW_SOLID:
- case SIMPLE_DRAW_BITMAP:
- case SIMPLE_DRAW: {
- SimpleSpiceUpdate *update;
-
- if (has_automated_tests)
- {
- if (control == 0) {
- return;
- }
-
- regression_test();
- }
-
- switch (command->command) {
- case SIMPLE_COPY_BITS:
- update = test_spice_create_update_copy_bits(test, 0);
- break;
- case SIMPLE_DRAW:
- update = test_spice_create_update_draw(test, 0, path.t);
- break;
- case SIMPLE_DRAW_BITMAP:
- update = test_spice_create_update_from_bitmap(command->bitmap.surface_id,
- command->bitmap.bbox, command->bitmap.bitmap,
- command->bitmap.num_clip_rects, command->bitmap.clip_rects);
- break;
- case SIMPLE_DRAW_SOLID:
- update = test_spice_create_update_solid(command->solid.surface_id,
- command->solid.bbox, command->solid.color);
- break;
- default: /* Just to shut up GCC warning (-Wswitch) */
- break;
- }
- push_command(&update->ext);
- break;
- }
-
- case SIMPLE_CREATE_SURFACE: {
- SimpleSurfaceCmd *update;
- if (command->create_surface.data) {
- spice_assert(command->create_surface.surface_id > 0);
- spice_assert(command->create_surface.surface_id < MAX_SURFACE_NUM);
- spice_assert(command->create_surface.surface_id == 1);
- update = create_surface(command->create_surface.surface_id,
- command->create_surface.format,
- command->create_surface.width,
- command->create_surface.height,
- command->create_surface.data);
- } else {
- update = create_surface(test->target_surface, SPICE_SURFACE_FMT_32_xRGB,
- SURF_WIDTH, SURF_HEIGHT,
- test->secondary_surface);
- }
- push_command(&update->ext);
- test->has_secondary = 1;
- break;
- }
-
- case SIMPLE_DESTROY_SURFACE: {
- SimpleSurfaceCmd *update;
- test->has_secondary = 0;
- update = destroy_surface(test->target_surface);
- test->target_surface = 0;
- push_command(&update->ext);
- break;
- }
-
- case DESTROY_PRIMARY:
- spice_qxl_destroy_primary_surface(&test->qxl_instance, 0);
- break;
-
- case CREATE_PRIMARY:
- create_primary_surface(test,
- command->create_primary.width, command->create_primary.height);
- break;
- }
- test->cmd_index = (test->cmd_index + 1) % test->num_commands;
-}
-
-static int req_cmd_notification(QXLInstance *qin)
-{
- Test *test = SPICE_CONTAINEROF(qin, Test, qxl_instance);
-
- test->core->timer_start(test->wakeup_timer, test->wakeup_ms);
- return TRUE;
-}
-
-static void do_wakeup(void *opaque)
-{
- Test *test = opaque;
- int notify;
-
- test->cursor_notify = NOTIFY_CURSOR_BATCH;
- for (notify = NOTIFY_DISPLAY_BATCH; notify > 0;--notify) {
- produce_command(test);
- }
-
- test->core->timer_start(test->wakeup_timer, test->wakeup_ms);
- spice_qxl_wakeup(&test->qxl_instance);
-}
-
-static void release_resource(SPICE_GNUC_UNUSED QXLInstance *qin,
- struct QXLReleaseInfoExt release_info)
-{
- QXLCommandExt *ext = (QXLCommandExt*)(unsigned long)release_info.info->id;
- //printf("%s\n", __func__);
- spice_assert(release_info.group_id == MEM_SLOT_GROUP_ID);
- switch (ext->cmd.type) {
- case QXL_CMD_DRAW:
- test_spice_destroy_update((void*)ext);
- break;
- case QXL_CMD_SURFACE:
- free(ext);
- break;
- case QXL_CMD_CURSOR: {
- QXLCursorCmd *cmd = (QXLCursorCmd *)(unsigned long)ext->cmd.data;
- if (cmd->type == QXL_CURSOR_SET) {
- free(cmd);
- }
- free(ext);
- break;
- }
- default:
- abort();
- }
-}
-
-#define CURSOR_WIDTH 32
-#define CURSOR_HEIGHT 32
-
-static struct {
- QXLCursor cursor;
- uint8_t data[CURSOR_WIDTH * CURSOR_HEIGHT * 4]; // 32bit per pixel
-} cursor;
-
-static void cursor_init()
-{
- cursor.cursor.header.unique = 0;
- cursor.cursor.header.type = SPICE_CURSOR_TYPE_COLOR32;
- cursor.cursor.header.width = CURSOR_WIDTH;
- cursor.cursor.header.height = CURSOR_HEIGHT;
- cursor.cursor.header.hot_spot_x = 0;
- cursor.cursor.header.hot_spot_y = 0;
- cursor.cursor.data_size = CURSOR_WIDTH * CURSOR_HEIGHT * 4;
-
- // X drivers addes it to the cursor size because it could be
- // cursor data information or another cursor related stuffs.
- // Otherwise, the code will break in client/cursor.cpp side,
- // that expect the data_size plus cursor information.
- // Blame cursor protocol for this. :-)
- cursor.cursor.data_size += 128;
- cursor.cursor.chunk.data_size = cursor.cursor.data_size;
- cursor.cursor.chunk.prev_chunk = cursor.cursor.chunk.next_chunk = 0;
-}
-
-static int get_cursor_command(QXLInstance *qin, struct QXLCommandExt *ext)
-{
- Test *test = SPICE_CONTAINEROF(qin, Test, qxl_instance);
- static int set = 1;
- static int x = 0, y = 0;
- QXLCursorCmd *cursor_cmd;
- QXLCommandExt *cmd;
-
- if (!test->cursor_notify) {
- return FALSE;
- }
-
- test->cursor_notify--;
- cmd = calloc(sizeof(QXLCommandExt), 1);
- cursor_cmd = calloc(sizeof(QXLCursorCmd), 1);
-
- cursor_cmd->release_info.id = (unsigned long)cmd;
-
- if (set) {
- cursor_cmd->type = QXL_CURSOR_SET;
- cursor_cmd->u.set.position.x = 0;
- cursor_cmd->u.set.position.y = 0;
- cursor_cmd->u.set.visible = TRUE;
- cursor_cmd->u.set.shape = (unsigned long)&cursor;
- // Only a white rect (32x32) as cursor
- memset(cursor.data, 255, sizeof(cursor.data));
- set = 0;
- } else {
- cursor_cmd->type = QXL_CURSOR_MOVE;
- cursor_cmd->u.position.x = x++ % test->primary_width;
- cursor_cmd->u.position.y = y++ % test->primary_height;
- }
-
- cmd->cmd.data = (unsigned long)cursor_cmd;
- cmd->cmd.type = QXL_CMD_CURSOR;
- cmd->group_id = MEM_SLOT_GROUP_ID;
- cmd->flags = 0;
- *ext = *cmd;
- //printf("%s\n", __func__);
- return TRUE;
-}
-
-static int req_cursor_notification(SPICE_GNUC_UNUSED QXLInstance *qin)
-{
- printf("%s\n", __func__);
- return TRUE;
-}
-
-static void notify_update(SPICE_GNUC_UNUSED QXLInstance *qin,
- SPICE_GNUC_UNUSED uint32_t update_id)
-{
- printf("%s\n", __func__);
-}
-
-static int flush_resources(SPICE_GNUC_UNUSED QXLInstance *qin)
-{
- printf("%s\n", __func__);
- return TRUE;
-}
-
-static int client_monitors_config(SPICE_GNUC_UNUSED QXLInstance *qin,
- VDAgentMonitorsConfig *monitors_config)
-{
- if (!monitors_config) {
- printf("%s: NULL monitors_config\n", __func__);
- } else {
- printf("%s: %d\n", __func__, monitors_config->num_of_monitors);
- }
- return 0;
-}
-
-static void set_client_capabilities(QXLInstance *qin,
- uint8_t client_present,
- uint8_t caps[58])
-{
- Test *test = SPICE_CONTAINEROF(qin, Test, qxl_instance);
-
- printf("%s: present %d caps %d\n", __func__, client_present, caps[0]);
- if (test->on_client_connected && client_present) {
- test->on_client_connected(test);
- }
- if (test->on_client_disconnected && !client_present) {
- test->on_client_disconnected(test);
- }
-}
-
-QXLInterface display_sif = {
- .base = {
- .type = SPICE_INTERFACE_QXL,
- .description = "test",
- .major_version = SPICE_INTERFACE_QXL_MAJOR,
- .minor_version = SPICE_INTERFACE_QXL_MINOR
- },
- .attache_worker = attache_worker,
- .set_compression_level = set_compression_level,
- .set_mm_time = set_mm_time,
- .get_init_info = get_init_info,
-
- /* the callbacks below are called from spice server thread context */
- .get_command = get_command,
- .req_cmd_notification = req_cmd_notification,
- .release_resource = release_resource,
- .get_cursor_command = get_cursor_command,
- .req_cursor_notification = req_cursor_notification,
- .notify_update = notify_update,
- .flush_resources = flush_resources,
- .client_monitors_config = client_monitors_config,
- .set_client_capabilities = set_client_capabilities,
-};
-
-/* interface for tests */
-void test_add_display_interface(Test* test)
-{
- spice_server_add_interface(test->server, &test->qxl_instance.base);
-}
-
-static SpiceBaseInterface base = {
- .type = SPICE_INTERFACE_CHAR_DEVICE,
- .description = "test spice virtual channel char device",
- .major_version = SPICE_INTERFACE_CHAR_DEVICE_MAJOR,
- .minor_version = SPICE_INTERFACE_CHAR_DEVICE_MINOR,
-};
-
-SpiceCharDeviceInstance vdagent_sin = {
- .base = {
- .sif = &base,
- },
- .subtype = "vdagent",
-};
-
-void test_add_agent_interface(SpiceServer *server)
-{
- spice_server_add_interface(server, &vdagent_sin.base);
-}
-
-void test_set_simple_command_list(Test *test, int *simple_commands, int num_commands)
-{
- int i;
-
- /* FIXME: leaks */
- test->commands = malloc(sizeof(*test->commands) * num_commands);
- memset(test->commands, 0, sizeof(*test->commands) * num_commands);
- test->num_commands = num_commands;
- for (i = 0 ; i < num_commands; ++i) {
- test->commands[i].command = simple_commands[i];
- }
-}
-
-void test_set_command_list(Test *test, Command *commands, int num_commands)
-{
- test->commands = commands;
- test->num_commands = num_commands;
-}
-
-
-Test *test_new(SpiceCoreInterface *core)
-{
- int port = 5912;
- Test *test = spice_new0(Test, 1);
- SpiceServer* server = spice_server_new();
-
- test->qxl_instance.base.sif = &display_sif.base;
- test->qxl_instance.id = 0;
-
- test->core = core;
- test->server = server;
- test->wakeup_ms = 1;
- test->cursor_notify = NOTIFY_CURSOR_BATCH;
- // some common initialization for all display tests
- printf("TESTER: listening on port %d (unsecure)\n", port);
- spice_server_set_port(server, port);
- spice_server_set_noauth(server);
- spice_server_init(server, core);
-
- cursor_init();
- path_init(&path, 0, angle_parts);
- test->has_secondary = 0;
- test->wakeup_timer = core->timer_add(do_wakeup, test);
- return test;
-}
-
-void init_automated()
-{
- struct sigaction sa;
-
- memset(&sa, 0, sizeof sa);
- sa.sa_handler = &sigchld_handler;
- sigaction(SIGCHLD, &sa, NULL);
-}
-
-__attribute__((noreturn))
-void usage(const char *argv0, const int exitcode)
-{
-#ifdef AUTOMATED_TESTS
- const char *autoopt=" [--automated-tests]";
-#else
- const char *autoopt="";
-#endif
-
- printf("usage: %s%s\n", argv0, autoopt);
- exit(exitcode);
-}
-
-void spice_test_config_parse_args(int argc, char **argv)
-{
- struct option options[] = {
-#ifdef AUTOMATED_TESTS
- {"automated-tests", no_argument, &has_automated_tests, 1},
-#endif
- {NULL, 0, NULL, 0},
- };
- int option_index;
- int val;
-
- while ((val = getopt_long(argc, argv, "", options, &option_index)) != -1) {
- switch (val) {
- case '?':
- printf("unrecognized option '%s'\n", argv[optind - 1]);
- usage(argv[0], EXIT_FAILURE);
- case 0:
- break;
- }
- }
-
- if (argc > optind) {
- printf("unknown argument '%s'\n", argv[optind]);
- usage(argv[0], EXIT_FAILURE);
- }
- if (has_automated_tests) {
- init_automated();
- }
- return;
-}
diff --git a/server/tests/test_display_base.h b/server/tests/test_display_base.h
deleted file mode 100644
index e5d7965..0000000
--- a/server/tests/test_display_base.h
+++ /dev/null
@@ -1,146 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2009-2015 Red Hat, Inc.
-
- 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, see <http://www.gnu.org/licenses/>.
-*/
-#ifndef __TEST_DISPLAY_BASE_H__
-#define __TEST_DISPLAY_BASE_H__
-
-#include <spice.h>
-#include "basic_event_loop.h"
-
-#define COUNT(x) ((sizeof(x)/sizeof(x[0])))
-
-/*
- * simple queue for commands.
- * each command can have up to two parameters (grow as needed)
- *
- * TODO: switch to gtk main loop. Then add gobject-introspection. then
- * write tests in python/guile/whatever.
- */
-typedef enum {
- PATH_PROGRESS,
- SIMPLE_CREATE_SURFACE,
- SIMPLE_DRAW,
- SIMPLE_DRAW_BITMAP,
- SIMPLE_DRAW_SOLID,
- SIMPLE_COPY_BITS,
- SIMPLE_DESTROY_SURFACE,
- SIMPLE_UPDATE,
- DESTROY_PRIMARY,
- CREATE_PRIMARY,
- SLEEP
-} CommandType;
-
-typedef struct CommandCreatePrimary {
- uint32_t width;
- uint32_t height;
-} CommandCreatePrimary;
-
-typedef struct CommandCreateSurface {
- uint32_t surface_id;
- uint32_t format;
- uint32_t width;
- uint32_t height;
- uint8_t *data;
-} CommandCreateSurface;
-
-typedef struct CommandDrawBitmap {
- QXLRect bbox;
- uint8_t *bitmap;
- uint32_t surface_id;
- uint32_t num_clip_rects;
- QXLRect *clip_rects;
-} CommandDrawBitmap;
-
-typedef struct CommandDrawSolid {
- QXLRect bbox;
- uint32_t color;
- uint32_t surface_id;
-} CommandDrawSolid;
-
-typedef struct CommandSleep {
- uint32_t secs;
-} CommandSleep;
-
-typedef struct Command Command;
-typedef struct Test Test;
-
-struct Command {
- CommandType command;
- void (*cb)(Test *test, Command *command);
- void *cb_opaque;
- union {
- CommandCreatePrimary create_primary;
- CommandDrawBitmap bitmap;
- CommandDrawSolid solid;
- CommandSleep sleep;
- CommandCreateSurface create_surface;
- };
-};
-
-#define MAX_HEIGHT 2048
-#define MAX_WIDTH 2048
-
-#define SURF_WIDTH 320
-#define SURF_HEIGHT 240
-
-struct Test {
- SpiceCoreInterface *core;
- SpiceServer *server;
-
- QXLInstance qxl_instance;
- QXLWorker *qxl_worker;
-
- uint8_t primary_surface[MAX_HEIGHT * MAX_WIDTH * 4];
- int primary_height;
- int primary_width;
-
- SpiceTimer *wakeup_timer;
- int wakeup_ms;
-
- int cursor_notify;
-
- uint8_t secondary_surface[SURF_WIDTH * SURF_HEIGHT * 4];
- int has_secondary;
-
- // Current mode (set by create_primary)
- int width;
- int height;
-
- // qxl scripted rendering commands and io
- Command *commands;
- int num_commands;
- int cmd_index;
-
- int target_surface;
-
- // callbacks
- void (*on_client_connected)(Test *test);
- void (*on_client_disconnected)(Test *test);
-};
-
-void test_set_simple_command_list(Test *test, int *command, int num_commands);
-void test_set_command_list(Test *test, Command *command, int num_commands);
-void test_add_display_interface(Test *test);
-void test_add_agent_interface(SpiceServer *server); // TODO - Test *test
-Test* test_new(SpiceCoreInterface* core);
-
-uint32_t test_get_width(void);
-uint32_t test_get_height(void);
-
-void spice_test_config_parse_args(int argc, char **argv);
-
-#endif /* __TEST_DISPLAY_BASE_H__ */
diff --git a/server/tests/test_display_no_ssl.c b/server/tests/test_display_no_ssl.c
deleted file mode 100644
index d861128..0000000
--- a/server/tests/test_display_no_ssl.c
+++ /dev/null
@@ -1,72 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2009-2015 Red Hat, Inc.
-
- 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, see <http://www.gnu.org/licenses/>.
-*/
-/**
- * Test ground for developing specific tests.
- *
- * Any specific test can start of from here and set the server to the
- * specific required state, and create specific operations or reuse
- * existing ones in the test_display_base supplied queue.
- */
-
-#include <config.h>
-#include <stdlib.h>
-#include "test_display_base.h"
-
-SpiceCoreInterface *core;
-SpiceTimer *ping_timer;
-
-void show_channels(SpiceServer *server);
-
-int ping_ms = 100;
-
-void pinger(SPICE_GNUC_UNUSED void *opaque)
-{
- // show_channels is not thread safe - fails if disconnections / connections occur
- //show_channels(server);
-
- core->timer_start(ping_timer, ping_ms);
-}
-
-int simple_commands[] = {
- //SIMPLE_CREATE_SURFACE,
- //SIMPLE_DRAW,
- //SIMPLE_DESTROY_SURFACE,
- //PATH_PROGRESS,
- SIMPLE_DRAW,
- //SIMPLE_COPY_BITS,
- SIMPLE_UPDATE,
-};
-
-int main(void)
-{
- Test *test;
-
- core = basic_event_loop_init();
- test = test_new(core);
- //spice_server_set_image_compression(server, SPICE_IMAGE_COMPRESSION_OFF);
- test_add_display_interface(test);
- test_add_agent_interface(test->server);
- test_set_simple_command_list(test, simple_commands, COUNT(simple_commands));
-
- ping_timer = core->timer_add(pinger, NULL);
- core->timer_start(ping_timer, ping_ms);
-
- basic_event_loop_mainloop();
-
- return 0;
-}
diff --git a/server/tests/test_display_resolution_changes.c b/server/tests/test_display_resolution_changes.c
deleted file mode 100644
index 069f460..0000000
--- a/server/tests/test_display_resolution_changes.c
+++ /dev/null
@@ -1,86 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2009-2015 Red Hat, Inc.
-
- 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, see <http://www.gnu.org/licenses/>.
-*/
-/**
- * Recreate the primary surface endlessly.
- */
-
-#include <config.h>
-#include <math.h>
-#include <stdlib.h>
-#include "test_display_base.h"
-
-SpiceTimer *ping_timer;
-
-void show_channels(SpiceServer *server);
-
-int ping_ms = 100;
-
-void pinger(void *opaque)
-{
- Test *test = opaque;
- // show_channels is not thread safe - fails if disconnections / connections occur
- //show_channels(server);
-
- test->core->timer_start(ping_timer, ping_ms);
-}
-
-void set_primary_params(SPICE_GNUC_UNUSED Test *test,
- Command *command)
-{
-#if 0
- static int toggle = 0;
-
- if (toggle) {
- *arg1 = 800;
- *arg2 = 600;
- } else {
- *arg1 = 1024;
- *arg2 = 768;
- }
- toggle = 1 - toggle;
-#endif
- static int count = 0;
-
- command->create_primary.width = 800 + sin((float)count / 6) * 200;
- command->create_primary.height = 600 + cos((float)count / 6) * 200;
- count++;
-}
-
-static Command commands[] = {
- {DESTROY_PRIMARY, NULL, .cb_opaque = NULL,},
- {CREATE_PRIMARY, set_primary_params, .cb_opaque = NULL},
-};
-
-int main(void)
-{
- SpiceCoreInterface *core;
- Test *test;
-
- core = basic_event_loop_init();
- test = test_new(core);
- //spice_server_set_image_compression(server, SPICE_IMAGE_COMPRESSION_OFF);
- test_add_display_interface(test);
- test_set_command_list(test, commands, COUNT(commands));
-
- ping_timer = core->timer_add(pinger, test);
- core->timer_start(ping_timer, ping_ms);
-
- basic_event_loop_mainloop();
-
- return 0;
-}
diff --git a/server/tests/test_display_streaming.c b/server/tests/test_display_streaming.c
deleted file mode 100644
index 446bbf3..0000000
--- a/server/tests/test_display_streaming.c
+++ /dev/null
@@ -1,253 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2009-2015 Red Hat, Inc.
-
- 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, see <http://www.gnu.org/licenses/>.
-*/
-/* Do repeated updates to the same rectangle to trigger stream creation.
- *
- * TODO: check that stream actually starts programatically (maybe stap?)
- * TODO: stop updating same rect, check (prog) that stream stops
- */
-
-#include <config.h>
-
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <time.h>
-
-#include <glib.h>
-
-#include "test_display_base.h"
-
-static int sized;
-static int render_last_frame;
-
-static void create_overlay(Command *command , int width, int height)
-{
- CommandDrawBitmap *cmd = &command->bitmap;
- uint32_t *dst;
-
- cmd->surface_id = 0;
-
- cmd->bbox.left = 0;
- cmd->bbox.top = 0;
- cmd->bbox.right = width;
- cmd->bbox.bottom = height;
-
- cmd->num_clip_rects = 0;
- cmd->bitmap = g_malloc(width * height * 4 );
- dst = (uint32_t *)cmd->bitmap;
- for (int i = 0; i < width * height; i++, dst++) {
- *dst = 0x8B008B;
- }
-
-}
-
-#define NUM_COMMANDS 2000
-#define SIZED_INTERVAL 100
-#define OVERLAY_FRAME 500
-#define OVERLAY_WIDTH 200
-#define OVERLAY_HEIGHT 200
-
-/*
- * Create a frame in a stream that displays a row that moves
- * from the top to the bottom repeatedly.
- * Upon the OVERLAY_FRAME-th, a drawable is created on top of a part of the stream,
- * and from then on, all the stream frames has a clipping that keeps this drawable
- * visible, and in addition a clipping_factor is subtracted from the right limit of their clipping.
- * If sized=TRUE, a higher and wider frame than the original stream is created every SIZED_INTERVAL.
- * The sized frames can be distinguished by a change in the color of the top and bottom limits of the
- * surface.
- */
-static void create_clipped_frame(Test *test, Command *command, int clipping_factor)
-{
- static int count = 0;
- CommandDrawBitmap *cmd = &command->bitmap;
- int max_height = test->height;
- int max_width = test->width;
- int width;
- int height;
- int cur_line, end_line;
- uint32_t *dst;
-
- count++;
- if (count == NUM_COMMANDS) {
- count = 0;
- }
- if (count == OVERLAY_FRAME) {
- create_overlay(command, OVERLAY_WIDTH, OVERLAY_HEIGHT);
- return;
- }
-
- cmd->surface_id = 0;
-
- cmd->bbox.left = 0;
- cmd->bbox.right = max_width - 50;
- assert(max_height > 600);
- cmd->bbox.top = 50;
- cmd->bbox.bottom = max_height - 50;
- height = cmd->bbox.bottom - cmd->bbox.top;
- width = cmd->bbox.right - cmd->bbox.left;
- cur_line = (height/30)*(count % 30);
- end_line = cur_line + (height/30);
- if (end_line >= height || height - end_line < 8) {
- end_line = height;
- }
-
- if (sized && count % SIZED_INTERVAL == 0) {
-
- cmd->bbox.top = 0;
- cmd->bbox.bottom = max_height;
- cmd->bbox.left = 0;
- cmd->bbox.right = max_width;
- height = max_height;
- width = max_width;
- cur_line += 50;
- end_line += 50;
- }
-
- cmd->bitmap = g_malloc(width*height*4);
- memset(cmd->bitmap, 0xff, width*height*4);
- dst = (uint32_t *)(cmd->bitmap + cur_line*width*4);
- for (; cur_line < end_line; cur_line++) {
- int col;
- for (col = 0; col < width; col++, dst++) {
- *dst = 0x00FF00;
- }
- }
- if (sized && count % SIZED_INTERVAL == 0) {
- int i;
- uint32_t color = 0xffffff & rand();
-
- dst = (uint32_t *)cmd->bitmap;
-
- for (i = 0; i < 50*width; i++, dst++) {
- *dst = color;
- }
-
- dst = ((uint32_t *)(cmd->bitmap + (height - 50)*4*width));
-
- for (i = 0; i < 50*width; i++, dst++) {
- *dst = color;
- }
- }
-
- if (count < OVERLAY_FRAME) {
- cmd->num_clip_rects = 0;
- } else {
- cmd->num_clip_rects = 2;
- cmd->clip_rects = calloc(sizeof(QXLRect), 2);
- cmd->clip_rects[0].left = OVERLAY_WIDTH;
- cmd->clip_rects[0].top = cmd->bbox.top;
- cmd->clip_rects[0].right = cmd->bbox.right - clipping_factor;
- cmd->clip_rects[0].bottom = OVERLAY_HEIGHT;
- cmd->clip_rects[1].left = cmd->bbox.left;
- cmd->clip_rects[1].top = OVERLAY_HEIGHT;
- cmd->clip_rects[1].right = cmd->bbox.right - clipping_factor;
- cmd->clip_rects[1].bottom = cmd->bbox.bottom;
- }
-}
-
-static void create_frame1(Test *test, Command *command)
-{
- create_clipped_frame(test, command, 0);
-}
-
-void create_frame2(Test *test, Command *command)
-{
- create_clipped_frame(test, command, 200);
-}
-
-typedef void (*create_frame_cb)(Test *test, Command *command);
-
-
-/*
- * The test contains two types of streams. The first stream doesn't
- * have a clipping besides the on that the display the overlay drawable.
- * Expected result: If render_last_frame=false, the last frame should
- * be sent losslessly. Otherwise, red_update_area should be called, and the
- * stream is upgraded by a screenshot.
- *
- * In the second test, the stream clip changes in the middle (becomes smaller).
- * Expected result: red_update_area should is, and the
- * stream is upgraded by a screenshot (including lossy areas that belong to old frames
- * and were never covered by a lossless drawable).
- *
- */
-static void get_stream_commands(Command *commands, int num_commands,
- create_frame_cb cb)
-{
- int i;
-
- commands[0].command = DESTROY_PRIMARY;
- commands[1].command = CREATE_PRIMARY;
- commands[1].create_primary.width = 1280;
- commands[1].create_primary.height = 1024;
- commands[num_commands - 1].command = SLEEP;
- commands[num_commands - 1].sleep.secs = 20;
-
- for (i = 2; i < num_commands - 1; i++) {
- commands[i].command = SIMPLE_DRAW_BITMAP;
- commands[i].cb = cb;
- }
- if (render_last_frame) {
- commands[num_commands - 2].command = SIMPLE_UPDATE;
- }
-}
-
-static void get_commands(Command **commands, int *num_commands)
-{
- *num_commands = NUM_COMMANDS * 2;
- *commands = calloc(sizeof(Command), *num_commands);
-
- get_stream_commands(*commands, NUM_COMMANDS, create_frame1);
- get_stream_commands((*commands) + NUM_COMMANDS, NUM_COMMANDS, create_frame2);
-}
-
-
-int main(int argc, char **argv)
-{
- SpiceCoreInterface *core;
- Command *commands;
- int num_commands;
- int i;
- Test *test;
-
- spice_test_config_parse_args(argc, argv);
- sized = 0;
- for (i = 1 ; i < argc; ++i) {
- if (strcmp(argv[i], "sized") == 0) {
- sized = 1;
- }
- /* render last frame */
- if (strcmp(argv[i], "render") == 0) {
- render_last_frame = 1;
- }
- }
- srand(time(NULL));
- // todo: add args list of test numbers with explenations
- core = basic_event_loop_init();
- test = test_new(core);
- spice_server_set_streaming_video(test->server, SPICE_STREAM_VIDEO_ALL);
- test_add_display_interface(test);
- get_commands(&commands, &num_commands);
- test_set_command_list(test, commands, num_commands);
- basic_event_loop_mainloop();
- free(commands);
- return 0;
-}
diff --git a/server/tests/test_display_width_stride.c b/server/tests/test_display_width_stride.c
deleted file mode 100644
index bd27e60..0000000
--- a/server/tests/test_display_width_stride.c
+++ /dev/null
@@ -1,121 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2009-2015 Red Hat, Inc.
-
- 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, see <http://www.gnu.org/licenses/>.
-*/
-/**
- * Recreate the primary surface endlessly.
- */
-
-#include <config.h>
-#include <math.h>
-#include <stdlib.h>
-#include "test_display_base.h"
-
-SpiceTimer *ping_timer;
-
-void show_channels(SpiceServer *server);
-
-int ping_ms = 100;
-
-void pinger(void *opaque)
-{
- Test *test = opaque;
- // show_channels is not thread safe - fails if disconnections / connections occur
- //show_channels(server);
-
- test->core->timer_start(ping_timer, ping_ms);
-}
-
-static int g_surface_id = 1;
-static uint8_t *g_surface_data;
-
-void set_draw_parameters(SPICE_GNUC_UNUSED Test *test,
- Command *command)
-{
- static int count = 17;
- CommandDrawSolid *solid = &command->solid;
-
- solid->bbox.top = 0;
- solid->bbox.left = 0;
- solid->bbox.bottom = 20;
- solid->bbox.right = count;
- solid->surface_id = g_surface_id;
- count++;
-}
-
-void set_surface_params(SPICE_GNUC_UNUSED Test *test,
- Command *command)
-{
- CommandCreateSurface *create = &command->create_surface;
-
- // UGLY
- if (g_surface_data) {
- exit(0);
- }
- create->format = SPICE_SURFACE_FMT_8_A;
- create->width = 128;
- create->height = 128;
- g_surface_data = realloc(g_surface_data, create->width * create->height * 1);
- create->surface_id = g_surface_id;
- create->data = g_surface_data;
-}
-
-void set_destroy_parameters(SPICE_GNUC_UNUSED Test *test,
- SPICE_GNUC_UNUSED Command *command)
-{
- if (g_surface_data) {
- free(g_surface_data);
- g_surface_data = NULL;
- }
-}
-
-static Command commands[] = {
- {SIMPLE_CREATE_SURFACE, set_surface_params, .cb_opaque = NULL},
- {SIMPLE_DRAW_SOLID, set_draw_parameters, .cb_opaque = NULL},
- {SIMPLE_DRAW_SOLID, set_draw_parameters, .cb_opaque = NULL},
- {SIMPLE_DRAW_SOLID, set_draw_parameters, .cb_opaque = NULL},
- {SIMPLE_DRAW_SOLID, set_draw_parameters, .cb_opaque = NULL},
- {SIMPLE_DRAW_SOLID, set_draw_parameters, .cb_opaque = NULL},
- {SIMPLE_DRAW_SOLID, set_draw_parameters, .cb_opaque = NULL},
- {SIMPLE_DRAW_SOLID, set_draw_parameters, .cb_opaque = NULL},
- {SIMPLE_DRAW_SOLID, set_draw_parameters, .cb_opaque = NULL},
- {SIMPLE_DRAW_SOLID, set_draw_parameters, .cb_opaque = NULL},
- {SIMPLE_DESTROY_SURFACE, set_destroy_parameters, .cb_opaque = NULL},
-};
-
-void on_client_connected(Test *test)
-{
- test_set_command_list(test, commands, COUNT(commands));
-}
-
-int main(void)
-{
- SpiceCoreInterface *core;
- Test *test;
-
- core = basic_event_loop_init();
- test = test_new(core);
- test->on_client_connected = on_client_connected;
- //spice_server_set_image_compression(server, SPICE_IMAGE_COMPRESSION_OFF);
- test_add_display_interface(test);
-
- ping_timer = core->timer_add(pinger, test);
- core->timer_start(ping_timer, ping_ms);
-
- basic_event_loop_mainloop();
-
- return 0;
-}
diff --git a/server/tests/test_empty_success.c b/server/tests/test_empty_success.c
deleted file mode 100644
index da98488..0000000
--- a/server/tests/test_empty_success.c
+++ /dev/null
@@ -1,93 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2009-2015 Red Hat, Inc.
-
- 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, see <http://www.gnu.org/licenses/>.
-*/
-#include <config.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <spice.h>
-
-struct SpiceTimer {
- int a,b;
-};
-
-SpiceTimer* timer_add(SPICE_GNUC_UNUSED SpiceTimerFunc func,
- SPICE_GNUC_UNUSED void *opaque)
-{
- static struct SpiceTimer t = {0,};
-
- return &t;
-}
-
-void timer_start(SPICE_GNUC_UNUSED SpiceTimer *timer,
- SPICE_GNUC_UNUSED uint32_t ms)
-{
-}
-
-void timer_cancel(SPICE_GNUC_UNUSED SpiceTimer *timer)
-{
-}
-
-void timer_remove(SPICE_GNUC_UNUSED SpiceTimer *timer)
-{
-}
-
-SpiceWatch *watch_add(SPICE_GNUC_UNUSED int fd,
- SPICE_GNUC_UNUSED int event_mask,
- SPICE_GNUC_UNUSED SpiceWatchFunc func,
- SPICE_GNUC_UNUSED void *opaque)
-{
- return NULL;
-}
-
-void watch_update_mask(SPICE_GNUC_UNUSED SpiceWatch *watch,
- SPICE_GNUC_UNUSED int event_mask)
-{
-}
-
-void watch_remove(SPICE_GNUC_UNUSED SpiceWatch *watch)
-{
-}
-
-void channel_event(SPICE_GNUC_UNUSED int event,
- SPICE_GNUC_UNUSED SpiceChannelEventInfo *info)
-{
-}
-
-int main(void)
-{
- SpiceServer *server = spice_server_new();
- SpiceCoreInterface core;
-
- memset(&core, 0, sizeof(core));
- core.base.major_version = SPICE_INTERFACE_CORE_MAJOR;
- core.timer_add = timer_add;
- core.timer_start = timer_start;
- core.timer_cancel = timer_cancel;
- core.timer_remove = timer_remove;
- core.watch_add = watch_add;
- core.watch_update_mask = watch_update_mask;
- core.watch_remove = watch_remove;
- core.channel_event = channel_event;
-
- spice_server_set_port(server, 5911);
- spice_server_init(server, &core);
-
- spice_server_destroy(server);
-
- return 0;
-}
diff --git a/server/tests/test_fail_on_null_core_interface.c b/server/tests/test_fail_on_null_core_interface.c
deleted file mode 100644
index 48e92db..0000000
--- a/server/tests/test_fail_on_null_core_interface.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2009-2015 Red Hat, Inc.
-
- 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, see <http://www.gnu.org/licenses/>.
-*/
-#include <config.h>
-#include <spice.h>
-
-int main(void)
-{
- SpiceServer *server = spice_server_new();
- SpiceCoreInterface core;
-
- spice_server_init(server, &core);
- spice_server_set_port(server, 5911);
-
- return 0;
-}
diff --git a/server/tests/test_just_sockets_no_ssl.c b/server/tests/test_just_sockets_no_ssl.c
deleted file mode 100644
index 570903c..0000000
--- a/server/tests/test_just_sockets_no_ssl.c
+++ /dev/null
@@ -1,35 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2009-2015 Red Hat, Inc.
-
- 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, see <http://www.gnu.org/licenses/>.
-*/
-#include <config.h>
-#include <sys/select.h>
-#include <spice.h>
-#include "basic_event_loop.h"
-
-int main(void)
-{
- SpiceServer *server = spice_server_new();
- SpiceCoreInterface *core = basic_event_loop_init();
-
- spice_server_set_port(server, 5912);
- spice_server_set_noauth(server);
- spice_server_init(server, core);
-
- basic_event_loop_mainloop();
-
- return 0;
-}
diff --git a/server/tests/test_multiple.py b/server/tests/test_multiple.py
deleted file mode 100755
index ce03c94..0000000
--- a/server/tests/test_multiple.py
+++ /dev/null
@@ -1,121 +0,0 @@
-#!/usr/bin/python
-
-"""
-Example usage:
-./test_multiple.py test_display_no_ssl --log test.log
-
-Resulting test.log file (single test, stopped with Ctrl-C with 15 clients):
-
-0 162212
-1 154156
-2 154424
-3 154952
-4 155352
-5 155616
-6 156280
-7 222084
-8 222612
-9 230820
-10 230820
-11 230820
-12 230820
-13 296356
-14 296356
-
-"""
-
-import argparse
-import os
-import sys
-import subprocess
-import atexit
-import socket
-import time
-
-def killall(procs):
- for p in procs:
- print "killing %d" % p.pid
- p.kill()
- p.wait()
-
-def cleanup():
- killall(clients + [test_process])
-
-def wait_for_port(port):
- if not port:
- return
- # TODO: do this without actually opening the port - maybe just look at /proc/qemu_process_id/fd?
- s = socket.socket(socket.AF_INET)
- while True:
- try:
- s.connect(('localhost', port))
- s.close()
- break
- except:
- time.sleep(1)
- pass
-
-def get_vm_size(pid):
- """ read from /proc/<pid>/status, VmSize, in KiloBytes """
- return int([x for x in open('/proc/%s/status' % pid).readlines() if 'VmSize' in x][0].split()[1])
-
-parser = argparse.ArgumentParser()
-parser.add_argument('--client', default='spicy')
-parser.add_argument('--start-count', default=1, type=int)
-parser.add_argument('--end-count', default=50, type=int)
-parser.add_argument('--log', default='-')
-parser.add_argument('--sleep', default=3, type=int)
-args, rest = parser.parse_known_args(sys.argv[1:])
-client = os.popen('which %s' % args.client).read().strip()
-if not os.path.exists(client):
- print "supply a valid client. %s does not exist" % (args.client)
- sys.exit(1)
-
-if not rest or len(rest) < 1 or not os.path.exists(rest[0]):
- print "supply one argument that is the tester you wish to run"
- sys.exit(1)
-
-prog = rest[0]
-port = {
-'test_display_no_ssl': 5912,
-'test_display_streaming': 5912,
-'test_just_sockets_no_ssl': 5912,
-'test_playback': 5701,
-}.get(prog, None)
-
-if args.log == '-':
- log = sys.stdout
-else:
- log = open(args.log, 'a+')
-
-log.write('#%s\n' % time.time())
-
-# kill leftovers from previous invocation
-os.system('killall lt-%s' % prog)
-
-if prog[0] != '/':
- prog = os.path.join('.', prog)
-
-if not port:
- print "unknown port for %r" % prog
-
-print "prog = %r" % prog
-print "client = %r" % client
-print "range = %d..%d" % (args.start_count, args.end_count)
-atexit.register(cleanup)
-os.environ['SPICE_DEBUG_ALLOW_MC'] = '1'
-test_process = subprocess.Popen([prog], executable=prog)
-wait_for_port(port)
-for count in xrange(args.start_count, args.end_count):
- print "starting %d clients" % count
- clients = [subprocess.Popen(args=[client, '-h', 'localhost', '-p', str(port)],
- executable=client) for i in xrange(count)]
- print "sleeping %d" % (args.sleep * count)
- time.sleep(args.sleep * count)
- vmsize = "%d %d" % (i, get_vm_size(test_process.pid))
- print vmsize
- log.write(vmsize + '\n')
- log.flush()
- killall(clients)
-
-test_process.wait()
diff --git a/server/tests/test_playback.c b/server/tests/test_playback.c
deleted file mode 100644
index 1283427..0000000
--- a/server/tests/test_playback.c
+++ /dev/null
@@ -1,126 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2009-2015 Red Hat, Inc.
-
- 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, see <http://www.gnu.org/licenses/>.
-*/
-#include <config.h>
-#include <stdio.h>
-#include <sys/select.h>
-#include <sys/time.h>
-#include <math.h>
-
-#include <spice.h>
-#include "basic_event_loop.h"
-
-/* test the audio playback interface. Really basic no frils test - create
- * a single tone sinus sound (easy to hear clicks if it is generated badly
- * or is transmitted badly).
- *
- * TODO: Was going to do white noise to test compression too.
- *
- * TODO: gstreamer based test (could be used to play music files so
- * it has actual merit. Also possibly to simulate network effects?)
- * */
-
-SpicePlaybackInstance playback_instance;
-
-static const SpiceBaseInterface base = {
- .type = SPICE_INTERFACE_PLAYBACK,
- .description = "test playback",
- .major_version = SPICE_INTERFACE_PLAYBACK_MAJOR,
- .minor_version = SPICE_INTERFACE_PLAYBACK_MINOR,
-};
-
-uint32_t *frame;
-uint32_t num_samples;
-SpiceTimer *playback_timer;
-int playback_timer_ms;
-SpiceCoreInterface *core;
-
-static void get_frame(void)
-{
- if (frame) {
- return;
- }
- spice_server_playback_get_buffer(&playback_instance, &frame, &num_samples);
- playback_timer_ms = num_samples
- ? 1000 * num_samples / SPICE_INTERFACE_PLAYBACK_FREQ
- : 100;
-}
-
-void playback_timer_cb(SPICE_GNUC_UNUSED void *opaque)
-{
- static int t = 0;
- static uint64_t last_sent_usec = 0;
- static uint64_t samples_to_send;
- uint32_t i;
- struct timeval cur;
- uint64_t cur_usec;
-
- get_frame();
- if (!frame) {
- /* continue waiting until there is a channel */
- core->timer_start(playback_timer, 100);
- return;
- }
-
- /* we have a channel */
- gettimeofday(&cur, NULL);
- cur_usec = cur.tv_usec + cur.tv_sec * 1e6;
- if (last_sent_usec == 0) {
- samples_to_send = num_samples;
- } else {
- samples_to_send += (cur_usec - last_sent_usec) * SPICE_INTERFACE_PLAYBACK_FREQ / 1e6;
- }
- last_sent_usec = cur_usec;
- while (samples_to_send > num_samples && frame) {
-#if 0
- printf("samples_to_send = %d\n", samples_to_send);
-#endif
- samples_to_send -= num_samples;
- for (i = 0 ; i < num_samples; ++i) {
- frame[i] = (((uint16_t)((1<<14)*sin((t+i)/10))) << 16) + (((uint16_t)((1<<14)*sin((t+i)/10))));
- }
- t += num_samples;
- if (frame) {
- spice_server_playback_put_samples(&playback_instance, frame);
- frame = NULL;
- }
- get_frame();
- }
- core->timer_start(playback_timer, playback_timer_ms);
-}
-
-int main(void)
-{
- SpiceServer *server = spice_server_new();
- core = basic_event_loop_init();
-
- spice_server_set_port(server, 5701);
- spice_server_set_noauth(server);
- spice_server_init(server, core);
-
- playback_instance.base.sif = &base;
- spice_server_add_interface(server, &playback_instance.base);
- spice_server_playback_start(&playback_instance);
-
- playback_timer_ms = 100;
- playback_timer = core->timer_add(playback_timer_cb, NULL);
- core->timer_start(playback_timer, playback_timer_ms);
-
- basic_event_loop_mainloop();
-
- return 0;
-}
diff --git a/server/tests/test_two_servers.c b/server/tests/test_two_servers.c
deleted file mode 100644
index e89909c..0000000
--- a/server/tests/test_two_servers.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2009-2015 Red Hat, Inc.
-
- 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, see <http://www.gnu.org/licenses/>.
-*/
-/**
- * Test two servers on one main loop.
- */
-
-#include <config.h>
-#include <stdlib.h>
-#include "test_display_base.h"
-
-SpiceCoreInterface *core;
-
-int simple_commands[] = {
- //SIMPLE_CREATE_SURFACE,
- //SIMPLE_DRAW,
- //SIMPLE_DESTROY_SURFACE,
- //PATH_PROGRESS,
- SIMPLE_DRAW,
- //SIMPLE_COPY_BITS,
- SIMPLE_UPDATE,
-};
-
-int main(void)
-{
- Test *t1;
- Test *t2;
-
- core = basic_event_loop_init();
- t1 = test_new(core);
- t2 = test_new(core);
- //spice_server_set_image_compression(server, SPICE_IMAGE_COMPRESSION_OFF);
- test_add_display_interface(t1);
- test_add_display_interface(t2);
- test_set_simple_command_list(t1, simple_commands, COUNT(simple_commands));
- test_set_simple_command_list(t2, simple_commands, COUNT(simple_commands));
-
- basic_event_loop_mainloop();
- return 0;
-}
diff --git a/server/tests/test_vdagent.c b/server/tests/test_vdagent.c
deleted file mode 100644
index bba3e64..0000000
--- a/server/tests/test_vdagent.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- Copyright (C) 2009-2015 Red Hat, Inc.
-
- 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, see <http://www.gnu.org/licenses/>.
-*/
-/**
- * Test vdagent guest to server messages
- */
-
-#include <config.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-#include <spice/vd_agent.h>
-
-#include "test_display_base.h"
-
-SpiceCoreInterface *core;
-SpiceTimer *ping_timer;
-
-int ping_ms = 100;
-
-#ifndef MIN
-#define MIN(a, b) ((a) > (b) ? (b) : (a))
-#endif
-
-void pinger(SPICE_GNUC_UNUSED void *opaque)
-{
- // show_channels is not thread safe - fails if disconnections / connections occur
- //show_channels(server);
-
- core->timer_start(ping_timer, ping_ms);
-}
-
-static SpiceBaseInterface base = {
- .type = SPICE_INTERFACE_CHAR_DEVICE,
- .description = "test spice virtual channel char device",
- .major_version = SPICE_INTERFACE_CHAR_DEVICE_MAJOR,
- .minor_version = SPICE_INTERFACE_CHAR_DEVICE_MINOR,
-};
-
-SpiceCharDeviceInstance vmc_instance = {
- .subtype = "vdagent",
-};
-
-int main(void)
-{
- Test *test;
-
- core = basic_event_loop_init();
- test = test_new(core);
-
- vmc_instance.base.sif = &base;
- spice_server_add_interface(test->server, &vmc_instance.base);
-
- ping_timer = core->timer_add(pinger, NULL);
- core->timer_start(ping_timer, ping_ms);
-
- basic_event_loop_mainloop();
-
- return 0;
-}
More information about the Spice-commits
mailing list