1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4 
5 #include <stdio.h>
6 #include <unistd.h>
7 #include <string.h>
8 
9 #include <glib.h>
10 
11 #include <wocky/wocky.h>
12 
13 #include "wocky-test-stream.h"
14 #include "wocky-test-helper.h"
15 
16 #define TEST_NODE1 "http://test.com/node1"
17 #define TEST_NODE2 "http://test.com/node2"
18 
19 /* Test to instantiate a WockyPepService object */
20 static void
test_instantiation(void)21 test_instantiation (void)
22 {
23   WockyPepService *pep;
24 
25   pep = wocky_pep_service_new ("http://test.com/badger", FALSE);
26   g_assert (pep != NULL);
27 
28   g_object_unref (pep);
29 }
30 
31 /* Test that the 'changed' signal is properly fired */
32 gboolean event_received;
33 
34 static void
test_changed_signal_cb(WockyPepService * pep,WockyBareContact * contact,WockyStanza * stanza,WockyNode * item,test_data_t * test)35 test_changed_signal_cb (WockyPepService *pep,
36     WockyBareContact *contact,
37     WockyStanza *stanza,
38     WockyNode *item,
39     test_data_t *test)
40 {
41   const gchar *id = wocky_node_get_attribute (
42       wocky_stanza_get_top_node (stanza), "id");
43 
44   g_assert_cmpstr (wocky_bare_contact_get_jid (contact), ==,
45         "alice@example.org");
46 
47   /* the id happens to hold the number of <item> children; we expect to get the
48    * first one if there is more than one. */
49   if (wocky_strdiff (id, "0"))
50     {
51       g_assert (item != NULL);
52       g_assert_cmpstr (item->name, ==, "item");
53       g_assert_cmpstr (wocky_node_get_attribute (item, "id"), ==, "1");
54     }
55   else
56     {
57       g_assert (item == NULL);
58     }
59 
60   test->outstanding--;
61   g_main_loop_quit (test->loop);
62   event_received = TRUE;
63 }
64 
65 static void
send_pep_event(WockyPorter * porter,const gchar * node,guint n_items)66 send_pep_event (WockyPorter *porter,
67     const gchar *node,
68     guint n_items)
69 {
70   WockyStanza *stanza;
71   WockyNode *items;
72   gchar *n_items_str = g_strdup_printf ("%d", n_items);
73   guint i;
74 
75   stanza = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE,
76       WOCKY_STANZA_SUB_TYPE_NONE,
77       "alice@example.org", NULL,
78       /* This is a hint for test_changed_signal_cb. */
79       '@', "id", n_items_str,
80       '(', "event",
81         ':', WOCKY_XMPP_NS_PUBSUB_EVENT,
82         '(', "items",
83           '@', "node", node,
84           '*', &items,
85         ')',
86       ')',
87       NULL);
88 
89   for (i = 1; i <= n_items; i++)
90     {
91       gchar *i_str = g_strdup_printf ("%d", i);
92       wocky_node_add_build (items,
93           '(', "item",
94           '@', "id", i_str,
95             '(', "payload", ')',
96           ')', NULL);
97       g_free (i_str);
98     }
99 
100   wocky_porter_send (porter, stanza);
101   g_object_unref (stanza);
102   g_free (n_items_str);
103 }
104 
105 static void
test_changed_signal(void)106 test_changed_signal (void)
107 {
108   test_data_t *test = setup_test ();
109   WockyPepService *pep;
110 
111   pep = wocky_pep_service_new (TEST_NODE1, FALSE);
112   test_open_both_connections (test);
113 
114   g_signal_connect (pep, "changed", G_CALLBACK (test_changed_signal_cb), test);
115 
116   wocky_pep_service_start (pep, test->session_out);
117   wocky_porter_start (test->sched_out);
118   wocky_porter_start (test->sched_in);
119 
120   /* send events on the right node */
121   event_received = FALSE;
122   send_pep_event (test->sched_in, TEST_NODE1, 0);
123   send_pep_event (test->sched_in, TEST_NODE1, 1);
124   send_pep_event (test->sched_in, TEST_NODE1, 2);
125 
126   test->outstanding += 3;
127   test_wait_pending (test);
128   g_assert (event_received);
129   event_received = FALSE;
130 
131   /* send event on the wrong node */
132   send_pep_event (test->sched_in, TEST_NODE2, 1);
133 
134   g_object_unref (pep);
135 
136   /* send event to the right node after the PEP service has been destroyed */
137   send_pep_event (test->sched_in, TEST_NODE1, 1);
138 
139   test_close_both_porters (test);
140   teardown_test (test);
141   g_assert (!event_received);
142 }
143 
144 /* Test wocky_pep_service_get_async */
145 static void
test_send_query_cb(GObject * source_object,GAsyncResult * res,gpointer user_data)146 test_send_query_cb (GObject *source_object,
147     GAsyncResult *res,
148     gpointer user_data)
149 {
150   test_data_t *test = (test_data_t *) user_data;
151   WockyStanza *reply;
152   WockyNode *item;
153   WockyStanzaType type;
154   WockyStanzaSubType sub_type;
155 
156   reply = wocky_pep_service_get_finish (WOCKY_PEP_SERVICE (source_object), res,
157       &item, NULL);
158   g_assert (reply != NULL);
159 
160   wocky_stanza_get_type_info (reply, &type, &sub_type);
161   g_assert (type == WOCKY_STANZA_TYPE_IQ);
162   g_assert (sub_type == WOCKY_STANZA_SUB_TYPE_RESULT);
163 
164   g_assert (item != NULL);
165   g_assert_cmpstr (item->name, ==, "item");
166   g_assert_cmpstr (wocky_node_get_attribute (item, "id"), ==, "1");
167 
168   g_object_unref (reply);
169 
170   test->outstanding--;
171   g_main_loop_quit (test->loop);
172 }
173 
174 static gboolean
test_send_query_stanza_received_cb(WockyPorter * porter,WockyStanza * stanza,gpointer user_data)175 test_send_query_stanza_received_cb (WockyPorter *porter,
176     WockyStanza *stanza,
177     gpointer user_data)
178 {
179   test_data_t *test = (test_data_t *) user_data;
180   WockyStanza *reply;
181 
182   reply = wocky_stanza_build_iq_result (stanza,
183       '(', "pubsub",
184         ':', WOCKY_XMPP_NS_PUBSUB,
185         '(', "items",
186           '@', "node", "node1",
187           '(', "item",
188             '@', "id", "1",
189             '(', "payload", ')',
190           ')',
191         ')',
192       ')',
193       NULL);
194 
195   wocky_porter_send (porter, reply);
196   g_object_unref (reply);
197 
198   test->outstanding--;
199   g_main_loop_quit (test->loop);
200   return TRUE;
201 }
202 
203 static void
test_send_query_failed_cb(GObject * source_object,GAsyncResult * res,gpointer user_data)204 test_send_query_failed_cb (GObject *source_object,
205     GAsyncResult *res,
206     gpointer user_data)
207 {
208   test_data_t *test = (test_data_t *) user_data;
209   WockyStanza *reply;
210   GError *error = NULL;
211 
212   reply = wocky_pep_service_get_finish (WOCKY_PEP_SERVICE (source_object), res,
213       NULL, &error);
214   g_assert (reply == NULL);
215   g_assert_error (error, WOCKY_XMPP_CONNECTION_ERROR,
216       WOCKY_XMPP_CONNECTION_ERROR_CLOSED);
217   g_clear_error (&error);
218 
219   test->outstanding--;
220   g_main_loop_quit (test->loop);
221 }
222 
223 static void
test_get(void)224 test_get (void)
225 {
226   test_data_t *test = setup_test ();
227   WockyPepService *pep;
228   WockyContactFactory *contact_factory;
229   WockyBareContact *contact;
230   guint handler_id;
231 
232   pep = wocky_pep_service_new (TEST_NODE1, FALSE);
233   test_open_both_connections (test);
234 
235   wocky_pep_service_start (pep, test->session_in);
236   wocky_porter_start (test->sched_out);
237   wocky_porter_start (test->sched_in);
238 
239   handler_id = wocky_porter_register_handler_from_anyone (test->sched_out,
240       WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET,
241       WOCKY_PORTER_HANDLER_PRIORITY_MAX,
242       test_send_query_stanza_received_cb, test, NULL);
243 
244   contact_factory = wocky_session_get_contact_factory (test->session_in);
245   contact = wocky_contact_factory_ensure_bare_contact (contact_factory,
246       "juliet@example.org");
247 
248   wocky_pep_service_get_async (pep, contact, NULL, test_send_query_cb, test);
249 
250   test->outstanding += 2;
251   test_wait_pending (test);
252 
253   /* Regression test for a bug where wocky_pep_service_get_async's callback
254    * would crash if sending the IQ failed.
255    */
256   wocky_porter_unregister_handler (test->sched_out, handler_id);
257   wocky_pep_service_get_async (pep, contact, NULL, test_send_query_failed_cb,
258       test);
259   test->outstanding += 1;
260   test_close_both_porters (test);
261 
262   g_object_unref (contact);
263   g_object_unref (pep);
264   teardown_test (test);
265 }
266 
267 /* Test wocky_pep_service_make_publish_stanza */
268 static void
test_make_publish_stanza(void)269 test_make_publish_stanza (void)
270 {
271   WockyPepService *pep;
272   WockyStanza *stanza;
273   WockyNode *item = NULL, *n;
274   WockyStanzaType type;
275   WockyStanzaSubType sub_type;
276 
277   pep = wocky_pep_service_new (TEST_NODE1, FALSE);
278 
279   stanza = wocky_pep_service_make_publish_stanza (pep, &item);
280 
281   g_assert (stanza != NULL);
282 
283   wocky_stanza_get_type_info (stanza, &type, &sub_type);
284   g_assert (type == WOCKY_STANZA_TYPE_IQ);
285   g_assert (sub_type == WOCKY_STANZA_SUB_TYPE_SET);
286 
287   n = wocky_node_get_child_ns (wocky_stanza_get_top_node (stanza),
288       "pubsub", WOCKY_XMPP_NS_PUBSUB);
289   g_assert (n != NULL);
290 
291   n = wocky_node_get_child (n, "publish");
292   g_assert (n != NULL);
293   g_assert (!wocky_strdiff (wocky_node_get_attribute (n, "node"),
294         TEST_NODE1));
295 
296   n = wocky_node_get_child (n, "item");
297   g_assert (n != NULL);
298   g_assert (n == item);
299 
300   g_object_unref (stanza);
301   g_object_unref (pep);
302 }
303 
304 int
main(int argc,char ** argv)305 main (int argc, char **argv)
306 {
307   int result;
308 
309   test_init (argc, argv);
310 
311   g_test_add_func ("/pep-service/instantiation", test_instantiation);
312   g_test_add_func ("/pep-service/changed-signal", test_changed_signal);
313   g_test_add_func ("/pep-service/get", test_get);
314   g_test_add_func ("/pep-service/make-publish-stanza",
315       test_make_publish_stanza);
316 
317   result = g_test_run ();
318   test_deinit ();
319   return result;
320 }
321