Merge lp:~attente/content-hub/content-hub-glib-2 into lp:content-hub

Proposed by William Hua on 2016-11-23
Status: Merged
Approved by: Ken VanDine on 2016-12-02
Approved revision: 311
Merged at revision: 311
Proposed branch: lp:~attente/content-hub/content-hub-glib-2
Merge into: lp:content-hub
Diff against target: 541 lines (+428/-6)
11 files modified
CMakeLists.txt (+7/-1)
debian/control (+23/-0)
debian/libcontent-hub-dev.install (+2/-2)
debian/libcontent-hub-glib-dev.install (+3/-0)
debian/libcontent-hub-glib0.install (+1/-0)
debian/libcontent-hub0.install (+1/-1)
libcontent-hub-glib.pc.in (+11/-0)
src/com/ubuntu/content/CMakeLists.txt (+62/-2)
tests/CMakeLists.txt (+1/-0)
tests/acceptance-tests/CMakeLists.txt (+3/-0)
tests/acceptance-tests/glib_test.cpp (+314/-0)
To merge this branch: bzr merge lp:~attente/content-hub/content-hub-glib-2
Reviewer Review Type Date Requested Status
Ken VanDine 2016-11-23 Approve on 2016-12-02
Review via email: mp+311621@code.launchpad.net

This proposal supersedes a proposal from 2016-11-21.

Commit Message

Add GLib bindings (LP: #1624437)

Description of the Change

Add GLib bindings (LP: #1624437)

There's a GTK branch (wip/attente/mir-content-hub) that needs this for copy-paste support.

To post a comment you must log in.
310. By William Hua on 2016-12-01

Fix build failure on zesty due to googletest 1.8. Also refactored
tests/acceptance-tests/CMakeLists.txt to make adding tests less
cumbersome. (LP: #1644062)

311. By William Hua on 2016-12-01

Group the commands better

Ken VanDine (ken-vandine) wrote :

Thanks, looks great

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CMakeLists.txt'
2--- CMakeLists.txt 2016-11-28 17:34:27 +0000
3+++ CMakeLists.txt 2016-12-01 18:19:18 +0000
4@@ -116,8 +116,14 @@
5 set(exec_prefix ${prefix}/bin)
6 set(libdir ${prefix}/${CMAKE_INSTALL_LIBDIR})
7 set(pkg-name "libcontent-hub")
8+set(glib-pkg-name "libcontent-hub-glib")
9 configure_file(libcontent-hub.pc.in libcontent-hub.pc @ONLY)
10-install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libcontent-hub.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
11+configure_file(libcontent-hub-glib.pc.in libcontent-hub-glib.pc @ONLY)
12+install(FILES
13+ ${CMAKE_CURRENT_BINARY_DIR}/libcontent-hub.pc
14+ ${CMAKE_CURRENT_BINARY_DIR}/libcontent-hub-glib.pc
15+ DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig
16+)
17
18 # There's no nice way to format this. Thanks CMake.
19 add_test(LGPL-required
20
21=== modified file 'debian/control'
22--- debian/control 2016-10-25 18:45:11 +0000
23+++ debian/control 2016-12-01 18:19:18 +0000
24@@ -59,6 +59,20 @@
25 securely and efficiently exchange content.
26 This package includes the content sharing libraries.
27
28+Package: libcontent-hub-glib0
29+Section: libs
30+Architecture: any
31+Multi-Arch: same
32+Pre-Depends: ${misc:Pre-Depends},
33+Depends: ${misc:Depends},
34+ ${shlibs:Depends},
35+Suggests: content-hub
36+Description: content sharing/picking library - GLib bindings
37+ Content sharing/picking infrastructure and service, designed to allow apps to
38+ securely and efficiently exchange content.
39+ .
40+ This package includes GLib bindings of the content sharing libraries.
41+
42 Package: libcontent-hub-dev
43 Section: libdevel
44 Architecture: any
45@@ -68,6 +82,15 @@
46 Description: content sharing development files
47 All the development headers and libraries for the content hub
48
49+Package: libcontent-hub-glib-dev
50+Section: libdevel
51+Architecture: any
52+Multi-Arch: same
53+Depends: libcontent-hub-glib0 (= ${binary:Version}),
54+ ${misc:Depends},
55+Description: content sharing development files - GLib bindings
56+ GLib bindings of the development headers and libraries for the content hub
57+
58 Package: qtdeclarative5-ubuntu-content1
59 Section: libs
60 Architecture: any
61
62=== modified file 'debian/libcontent-hub-dev.install'
63--- debian/libcontent-hub-dev.install 2013-09-30 21:28:46 +0000
64+++ debian/libcontent-hub-dev.install 2016-12-01 18:19:18 +0000
65@@ -1,3 +1,3 @@
66-usr/include
67+usr/include/com/ubuntu/content/*.h
68 usr/lib/*/libcontent-hub.so
69-usr/lib/*/pkgconfig
70+usr/lib/*/pkgconfig/libcontent-hub.pc
71
72=== added file 'debian/libcontent-hub-glib-dev.install'
73--- debian/libcontent-hub-glib-dev.install 1970-01-01 00:00:00 +0000
74+++ debian/libcontent-hub-glib-dev.install 2016-12-01 18:19:18 +0000
75@@ -0,0 +1,3 @@
76+usr/include/com/ubuntu/content/glib/*
77+usr/lib/*/libcontent-hub-glib.so
78+usr/lib/*/pkgconfig/libcontent-hub-glib.pc
79
80=== added file 'debian/libcontent-hub-glib0.install'
81--- debian/libcontent-hub-glib0.install 1970-01-01 00:00:00 +0000
82+++ debian/libcontent-hub-glib0.install 2016-12-01 18:19:18 +0000
83@@ -0,0 +1,1 @@
84+usr/lib/*/libcontent-hub-glib.so.*
85
86=== modified file 'debian/libcontent-hub0.install'
87--- debian/libcontent-hub0.install 2013-08-26 21:58:01 +0000
88+++ debian/libcontent-hub0.install 2016-12-01 18:19:18 +0000
89@@ -1,1 +1,1 @@
90-usr/lib/*/lib*.so.*
91+usr/lib/*/libcontent-hub.so.*
92
93=== added file 'libcontent-hub-glib.pc.in'
94--- libcontent-hub-glib.pc.in 1970-01-01 00:00:00 +0000
95+++ libcontent-hub-glib.pc.in 2016-12-01 18:19:18 +0000
96@@ -0,0 +1,11 @@
97+prefix=@prefix@
98+exec_prefix=@exec_prefix@
99+libdir=@libdir@
100+includedir=${prefix}/include
101+
102+Name: @glib-pkg-name@
103+Description: content sharing/picking library - GLib bindings
104+Version: @CONTENT_HUB_VERSION@
105+Libs: -L${libdir} -lcontent-hub-glib
106+Cflags: -I${includedir}
107+Requires: gio-2.0
108
109=== modified file 'src/com/ubuntu/content/CMakeLists.txt'
110--- src/com/ubuntu/content/CMakeLists.txt 2016-09-22 18:10:11 +0000
111+++ src/com/ubuntu/content/CMakeLists.txt 2016-12-01 18:19:18 +0000
112@@ -28,6 +28,8 @@
113 ${UBUNTU_DOWNLOAD_MANAGER_INCLUDE_DIRS}
114 ${NOTIFY_INCLUDE_DIRS}
115 ${APPARMOR_INCLUDE_DIRS}
116+ ${GLIB_INCLUDE_DIRS}
117+ ${GIO_INCLUDE_DIRS}
118 )
119
120 qt5_add_dbus_interface(
121@@ -120,8 +122,66 @@
122 ${APPARMOR_LDFLAGS}
123 )
124
125-install(
126- TARGETS content-hub
127+find_program(
128+ GDBUS_CODEGEN
129+ gdbus-codegen
130+)
131+
132+set(
133+ DBUS_XML
134+ ${CMAKE_CURRENT_SOURCE_DIR}/detail/com.ubuntu.content.Handler.xml
135+ ${CMAKE_CURRENT_SOURCE_DIR}/detail/com.ubuntu.content.Paste.xml
136+ ${CMAKE_CURRENT_SOURCE_DIR}/detail/com.ubuntu.content.Service.xml
137+ ${CMAKE_CURRENT_SOURCE_DIR}/detail/com.ubuntu.content.Transfer.xml
138+)
139+
140+set(
141+ DBUS_ANNOTATIONS
142+ --annotate com.ubuntu.content.dbus.Paste.Charge\(\)[mimeData] org.gtk.GDBus.C.ForceGVariant true
143+ --annotate com.ubuntu.content.dbus.Paste.MimeData\(\)[mimeData] org.gtk.GDBus.C.ForceGVariant true
144+ --annotate com.ubuntu.content.dbus.Service.CreatePaste\(\)[mimeData] org.gtk.GDBus.C.ForceGVariant true
145+ --annotate com.ubuntu.content.dbus.Service.GetLatestPasteData\(\)[mimeData] org.gtk.GDBus.C.ForceGVariant true
146+ --annotate com.ubuntu.content.dbus.Service.GetPasteData\(\)[mimeData] org.gtk.GDBus.C.ForceGVariant true
147+)
148+
149+add_custom_command(
150+ OUTPUT glib/content-hub-glib.h glib/content-hub-glib.c
151+ COMMAND ${CMAKE_COMMAND} -E make_directory glib
152+ COMMAND ${GDBUS_CODEGEN}
153+ --interface-prefix com.ubuntu.content.dbus
154+ --generate-c-code glib/content-hub-glib
155+ --c-namespace ContentHub
156+ ${DBUS_ANNOTATIONS}
157+ ${DBUS_XML}
158+ DEPENDS ${DBUS_XML}
159+ VERBATIM
160+)
161+
162+add_library(
163+ content-hub-glib SHARED
164+ glib/content-hub-glib.h
165+ glib/content-hub-glib.c
166+)
167+
168+target_link_libraries(
169+ content-hub-glib
170+ ${GIO_LIBRARIES}
171+)
172+
173+set_target_properties(
174+ content-hub-glib
175+ PROPERTIES
176+ VERSION ${CONTENT_HUB_VERSION_MAJOR}.${CONTENT_HUB_VERSION_MINOR}.${CONTENT_HUB_VERSION_PATCH}
177+ SOVERSION ${CONTENT_HUB_VERSION_MAJOR}
178+)
179+
180+install(
181+ FILES ${CMAKE_CURRENT_BINARY_DIR}/glib/content-hub-glib.h
182+ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/com/ubuntu/content/glib
183+)
184+
185+install(
186+ TARGETS content-hub content-hub-glib
187 LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
188 ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
189 )
190
191=== modified file 'tests/CMakeLists.txt'
192--- tests/CMakeLists.txt 2016-11-28 17:34:27 +0000
193+++ tests/CMakeLists.txt 2016-12-01 18:19:18 +0000
194@@ -23,6 +23,7 @@
195 ${LIBERTINE_INCLUDE_DIRS}
196 ${UBUNTU_LAUNCH_INCLUDE_DIRS}
197 ${CMAKE_BINARY_DIR}/src
198+ ${CMAKE_BINARY_DIR}/src/com/ubuntu/content
199 ${GMOCK_INCLUDE_DIR}
200 ${GTEST_INCLUDE_DIR}
201 )
202
203=== modified file 'tests/acceptance-tests/CMakeLists.txt'
204--- tests/acceptance-tests/CMakeLists.txt 2016-11-28 17:34:27 +0000
205+++ tests/acceptance-tests/CMakeLists.txt 2016-12-01 18:19:18 +0000
206@@ -27,6 +27,7 @@
207 test_utils
208 test_types
209 mimedata_test
210+ glib_test
211 )
212
213 set(TEST_LIBS
214@@ -87,6 +88,8 @@
215
216 file(COPY good.json bad.json source_all.json DESTINATION .)
217
218+target_link_libraries(glib_test content-hub-glib)
219+
220 add_custom_command(
221 OUTPUT transfer_files
222 COMMAND cmake -E touch file1 file2 file3
223
224=== added file 'tests/acceptance-tests/glib_test.cpp'
225--- tests/acceptance-tests/glib_test.cpp 1970-01-01 00:00:00 +0000
226+++ tests/acceptance-tests/glib_test.cpp 2016-12-01 18:19:18 +0000
227@@ -0,0 +1,314 @@
228+/*
229+ * Copyright © 2016 Canonical Ltd.
230+ *
231+ * This program is free software: you can redistribute it and/or modify
232+ * it under the terms of the GNU General Public License version 3 as
233+ * published by the Free Software Foundation.
234+ *
235+ * This program is distributed in the hope that it will be useful,
236+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
237+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
238+ * GNU Lesser General Public License for more details.
239+ *
240+ * You should have received a copy of the GNU Lesser General Public License
241+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
242+ *
243+ * Authored by: William Hua <william.hua@canonical.com>
244+ */
245+
246+/* modified from app_hub_communication_paste.cpp */
247+
248+#include "app_manager_mock.h"
249+#include "test_harness.h"
250+#include "../cross_process_sync.h"
251+#include "../fork_and_run.h"
252+
253+#include <com/ubuntu/content/hub.h>
254+#include <com/ubuntu/content/item.h>
255+#include <com/ubuntu/content/paste.h>
256+
257+#include "com/ubuntu/content/detail/peer_registry.h"
258+#include "com/ubuntu/content/detail/service.h"
259+#include "com/ubuntu/content/serviceadaptor.h"
260+
261+#include <gmock/gmock.h>
262+#include <gtest/gtest.h>
263+
264+#include <QCoreApplication>
265+#include <QtDBus/QDBusConnection>
266+#include <QStandardPaths>
267+#include <QTemporaryDir>
268+#include <QtTest/QTest>
269+
270+#include <thread>
271+
272+#include <cstring>
273+#include <gio/gio.h>
274+
275+#include "glib/content-hub-glib.h"
276+
277+namespace cua = com::ubuntu::ApplicationManager;
278+namespace cuc = com::ubuntu::content;
279+namespace cucd = com::ubuntu::content::detail;
280+
281+QString service_name{"com.ubuntu.content.dbus.Service"};
282+
283+struct MockedPeerRegistry : public cucd::PeerRegistry
284+{
285+ MockedPeerRegistry() : cucd::PeerRegistry()
286+ {
287+ using namespace ::testing;
288+
289+ ON_CALL(*this, default_source_for_type(_)).WillByDefault(Return(cuc::Peer::unknown()));
290+ ON_CALL(*this, install_default_source_for_type(_,_)).WillByDefault(Return(false));
291+ ON_CALL(*this, install_source_for_type(_,_)).WillByDefault(Return(false));
292+ }
293+
294+ MOCK_METHOD1(default_source_for_type, cuc::Peer(cuc::Type t));
295+ MOCK_METHOD1(enumerate_known_peers, void(const std::function<void(const cuc::Peer&)>&));
296+ MOCK_METHOD2(enumerate_known_sources_for_type, void(cuc::Type, const std::function<void(const cuc::Peer&)>&));
297+ MOCK_METHOD2(enumerate_known_destinations_for_type, void(cuc::Type, const std::function<void(const cuc::Peer&)>&));
298+ MOCK_METHOD2(enumerate_known_shares_for_type, void(cuc::Type, const std::function<void(const cuc::Peer&)>&));
299+ MOCK_METHOD2(install_default_source_for_type, bool(cuc::Type, cuc::Peer));
300+ MOCK_METHOD2(install_source_for_type, bool(cuc::Type, cuc::Peer));
301+ MOCK_METHOD2(install_destination_for_type, bool(cuc::Type, cuc::Peer));
302+ MOCK_METHOD2(install_share_for_type, bool(cuc::Type, cuc::Peer));
303+ MOCK_METHOD1(remove_peer, bool(cuc::Peer));
304+ MOCK_METHOD1(peer_is_legacy, bool(QString));
305+};
306+
307+static const gchar *SERVICE_NAME = "com.ubuntu.content.dbus.Service";
308+static const gchar *SERVICE_PATH = "/";
309+static const gchar *APPLICATION_ID = "com.ubuntu.content.glib_test";
310+static const gchar *HANDLER_PATH = "/com/ubuntu/content/handler";
311+static const gchar *SURFACE_ID = "01234567-0123-0123-0123-0123456789ab";
312+
313+static const gchar * const PASTE_FORMATS[] =
314+{
315+ "text/plain",
316+ "text/html",
317+ NULL
318+};
319+
320+static const gint N_PASTE_FORMATS = sizeof (PASTE_FORMATS) / sizeof (PASTE_FORMATS[0]) - 1;
321+
322+static const gchar PASTE_DATA[] =
323+ "text/plain"
324+ "plain text"
325+ "text/html"
326+ "<p>html text</p>";
327+
328+static const gint N_PASTE_DATA = sizeof (PASTE_DATA) / sizeof (PASTE_DATA[0]) - 1;
329+
330+static gboolean pasteboard_changed;
331+
332+static void
333+pasteboard_changed_cb (ContentHubService *service,
334+ gpointer user_data)
335+{
336+ GMainLoop *main_loop = (GMainLoop *) user_data;
337+
338+ pasteboard_changed = TRUE;
339+
340+ g_main_loop_quit (main_loop);
341+}
342+
343+static gboolean
344+timed_out_cb (gpointer user_data)
345+{
346+ GMainLoop *main_loop = (GMainLoop *) user_data;
347+
348+ g_main_loop_quit (main_loop);
349+
350+ return G_SOURCE_CONTINUE;
351+}
352+
353+static void
354+set_paste (ContentHubService *service)
355+{
356+ GMainLoop *main_loop;
357+ guint timeout_id;
358+
359+ g_assert_false (pasteboard_changed);
360+
361+ main_loop = g_main_loop_new (NULL, FALSE);
362+ timeout_id = g_timeout_add (1000, timed_out_cb, main_loop);
363+
364+ g_signal_connect (
365+ service,
366+ "pasteboard-changed",
367+ G_CALLBACK (pasteboard_changed_cb),
368+ main_loop);
369+
370+ g_assert_true (
371+ content_hub_service_call_create_paste_sync (
372+ service,
373+ APPLICATION_ID,
374+ SURFACE_ID,
375+ g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, PASTE_DATA, sizeof (PASTE_DATA) - 1, sizeof (guchar)),
376+ PASTE_FORMATS,
377+ NULL,
378+ NULL,
379+ NULL));
380+
381+ g_main_loop_run (main_loop);
382+ g_source_remove (timeout_id);
383+ g_clear_pointer (&main_loop, g_main_loop_unref);
384+
385+ g_assert_true (pasteboard_changed);
386+
387+ pasteboard_changed = FALSE;
388+}
389+
390+static void
391+get_paste (ContentHubService *service)
392+{
393+ gchar **formats;
394+ GVariant *variant;
395+ gconstpointer data;
396+ gsize size;
397+ gint i;
398+
399+ g_assert_true (
400+ content_hub_service_call_paste_formats_sync (
401+ service,
402+ &formats,
403+ NULL,
404+ NULL));
405+
406+ g_assert_cmpint (g_strv_length (formats), ==, N_PASTE_FORMATS);
407+
408+ for (i = 0; i < N_PASTE_FORMATS; i++)
409+ g_assert_cmpstr (formats[i], ==, PASTE_FORMATS[i]);
410+
411+ g_strfreev (formats);
412+
413+ g_assert_true (
414+ content_hub_service_call_get_latest_paste_data_sync (
415+ service,
416+ SURFACE_ID,
417+ &variant,
418+ NULL,
419+ NULL));
420+
421+ data = g_variant_get_fixed_array (variant, &size, sizeof (guchar));
422+
423+ g_assert_cmpint (size, ==, N_PASTE_DATA);
424+ g_assert_cmpint (memcmp (data, PASTE_DATA, N_PASTE_DATA), ==, 0);
425+}
426+
427+int
428+glib_test (int argc,
429+ char *argv[])
430+{
431+ GDBusConnection *session;
432+ ContentHubService *service;
433+ ContentHubHandler *handler;
434+
435+ session = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
436+
437+ service = content_hub_service_proxy_new_sync (
438+ session,
439+ G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES,
440+ SERVICE_NAME,
441+ SERVICE_PATH,
442+ NULL,
443+ NULL);
444+
445+ g_assert_nonnull (service);
446+
447+ handler = content_hub_handler_skeleton_new ();
448+
449+ g_assert_true (
450+ g_dbus_interface_skeleton_export (
451+ G_DBUS_INTERFACE_SKELETON (handler),
452+ session,
453+ HANDLER_PATH,
454+ NULL));
455+
456+ g_object_unref (session);
457+
458+ g_assert_true (
459+ content_hub_service_call_register_import_export_handler_sync (
460+ service,
461+ APPLICATION_ID,
462+ HANDLER_PATH,
463+ NULL,
464+ NULL));
465+
466+ g_assert_true (
467+ content_hub_service_call_handler_active_sync (
468+ service,
469+ APPLICATION_ID,
470+ NULL,
471+ NULL));
472+
473+ set_paste (service);
474+ get_paste (service);
475+
476+ g_assert_true (
477+ content_hub_service_call_quit_sync (
478+ service,
479+ NULL,
480+ NULL));
481+
482+ g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (handler));
483+ g_object_unref (handler);
484+ g_object_unref (service);
485+
486+ return 0;
487+}
488+
489+/* modified from app_hub_communication_paste.cpp */
490+
491+TEST(GLib, glib_test)
492+{
493+ using namespace ::testing;
494+
495+ test::CrossProcessSync sync;
496+
497+ auto parent = [&sync]()
498+ {
499+ int argc = 0;
500+ QCoreApplication app{argc, nullptr};
501+
502+ QDBusConnection connection = QDBusConnection::sessionBus();
503+
504+ auto mock = new ::testing::NiceMock<MockedPeerRegistry>{};
505+
506+ QSharedPointer<cucd::PeerRegistry> registry{mock};
507+ auto app_manager = QSharedPointer<cua::ApplicationManager>(new MockedAppManager());
508+ cucd::Service implementation(connection, registry, app_manager, &app);
509+ new ServiceAdaptor(std::addressof(implementation));
510+
511+ ASSERT_TRUE(connection.registerService(service_name));
512+ ASSERT_TRUE(connection.registerObject("/", std::addressof(implementation)));
513+
514+ sync.signal_ready();
515+
516+ app.exec();
517+
518+ connection.unregisterObject("/");
519+ connection.unregisterService(service_name);
520+ };
521+
522+ auto child = [&sync]()
523+ {
524+ int argc = 0;
525+ QCoreApplication app(argc, nullptr);
526+
527+ sync.wait_for_signal_ready();
528+
529+ test::TestHarness harness;
530+ harness.add_test_case([]()
531+ {
532+ char arg0[] = "glib_test";
533+ char *argv[] = { arg0 };
534+
535+ EXPECT_EQ(0, glib_test(1, argv));
536+ });
537+ EXPECT_EQ(0, QTest::qExec(std::addressof(harness)));
538+ };
539+
540+ EXPECT_EQ(EXIT_SUCCESS, test::fork_and_run(child, parent));
541+}

Subscribers

People subscribed via source and target branches