1 /* GStreamer
2  *
3  * Unit tests for webrtcbin
4  *
5  * Copyright (C) 2017 Matthew Waters <matthew@centricular.com>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  */
22 
23 
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27 
28 #include <gst/gst.h>
29 #include <gst/check/gstcheck.h>
30 #include <gst/check/gstharness.h>
31 #include <gst/webrtc/webrtc.h>
32 #include "../../../ext/webrtc/webrtcsdp.h"
33 #include "../../../ext/webrtc/webrtcsdp.c"
34 #include "../../../ext/webrtc/utils.h"
35 #include "../../../ext/webrtc/utils.c"
36 
37 #define OPUS_RTP_CAPS(pt) "application/x-rtp,payload=" G_STRINGIFY(pt) ",encoding-name=OPUS,media=audio,clock-rate=48000,ssrc=(uint)3384078950"
38 #define VP8_RTP_CAPS(pt) "application/x-rtp,payload=" G_STRINGIFY(pt) ",encoding-name=VP8,media=video,clock-rate=90000,ssrc=(uint)3484078950"
39 
40 typedef enum
41 {
42   STATE_NEW,
43   STATE_NEGOTATION_NEEDED,
44   STATE_OFFER_CREATED,
45   STATE_ANSWER_CREATED,
46   STATE_EOS,
47   STATE_ERROR,
48   STATE_CUSTOM,
49 } TestState;
50 
51 /* basic premise of this is that webrtc1 and webrtc2 are attempting to connect
52  * to each other in various configurations */
53 struct test_webrtc;
54 struct test_webrtc
55 {
56   GList *harnesses;
57   GThread *thread;
58   GMainLoop *loop;
59   GstBus *bus1;
60   GstBus *bus2;
61   GstElement *webrtc1;
62   GstElement *webrtc2;
63   GMutex lock;
64   GCond cond;
65   TestState state;
66   guint offerror;
67   gpointer user_data;
68   GDestroyNotify data_notify;
69 /* *INDENT-OFF* */
70   void      (*on_negotiation_needed)    (struct test_webrtc * t,
71                                          GstElement * element,
72                                          gpointer user_data);
73   gpointer negotiation_data;
74   GDestroyNotify negotiation_notify;
75   void      (*on_ice_candidate)         (struct test_webrtc * t,
76                                          GstElement * element,
77                                          guint mlineindex,
78                                          gchar * candidate,
79                                          GstElement * other,
80                                          gpointer user_data);
81   gpointer ice_candidate_data;
82   GDestroyNotify ice_candidate_notify;
83   GstWebRTCSessionDescription * (*on_offer_created)     (struct test_webrtc * t,
84                                                          GstElement * element,
85                                                          GstPromise * promise,
86                                                          gpointer user_data);
87   gpointer offer_data;
88   GDestroyNotify offer_notify;
89   GstWebRTCSessionDescription * (*on_answer_created)    (struct test_webrtc * t,
90                                                          GstElement * element,
91                                                          GstPromise * promise,
92                                                          gpointer user_data);
93   gpointer data_channel_data;
94   GDestroyNotify data_channel_notify;
95   void       (*on_data_channel)                         (struct test_webrtc * t,
96                                                          GstElement * element,
97                                                          GObject *data_channel,
98                                                          gpointer user_data);
99   gpointer answer_data;
100   GDestroyNotify answer_notify;
101   void      (*on_pad_added)             (struct test_webrtc * t,
102                                          GstElement * element,
103                                          GstPad * pad,
104                                          gpointer user_data);
105   gpointer pad_added_data;
106   GDestroyNotify pad_added_notify;
107   void      (*bus_message)              (struct test_webrtc * t,
108                                          GstBus * bus,
109                                          GstMessage * msg,
110                                          gpointer user_data);
111   gpointer bus_data;
112   GDestroyNotify bus_notify;
113 /* *INDENT-ON* */
114 };
115 
116 static void
_on_answer_received(GstPromise * promise,gpointer user_data)117 _on_answer_received (GstPromise * promise, gpointer user_data)
118 {
119   struct test_webrtc *t = user_data;
120   GstElement *offeror = t->offerror == 1 ? t->webrtc1 : t->webrtc2;
121   GstElement *answerer = t->offerror == 2 ? t->webrtc1 : t->webrtc2;
122   const GstStructure *reply;
123   GstWebRTCSessionDescription *answer = NULL;
124   gchar *desc;
125 
126   reply = gst_promise_get_reply (promise);
127   gst_structure_get (reply, "answer",
128       GST_TYPE_WEBRTC_SESSION_DESCRIPTION, &answer, NULL);
129   desc = gst_sdp_message_as_text (answer->sdp);
130   GST_INFO ("Created Answer: %s", desc);
131   g_free (desc);
132 
133   g_mutex_lock (&t->lock);
134   if (t->on_answer_created) {
135     gst_webrtc_session_description_free (answer);
136     answer = t->on_answer_created (t, answerer, promise, t->answer_data);
137   }
138   gst_promise_unref (promise);
139 
140   g_signal_emit_by_name (answerer, "set-local-description", answer, NULL);
141   g_signal_emit_by_name (offeror, "set-remote-description", answer, NULL);
142 
143   t->state = STATE_ANSWER_CREATED;
144   g_cond_broadcast (&t->cond);
145   g_mutex_unlock (&t->lock);
146 
147   gst_webrtc_session_description_free (answer);
148 }
149 
150 static void
_on_offer_received(GstPromise * promise,gpointer user_data)151 _on_offer_received (GstPromise * promise, gpointer user_data)
152 {
153   struct test_webrtc *t = user_data;
154   GstElement *offeror = t->offerror == 1 ? t->webrtc1 : t->webrtc2;
155   GstElement *answerer = t->offerror == 2 ? t->webrtc1 : t->webrtc2;
156   const GstStructure *reply;
157   GstWebRTCSessionDescription *offer = NULL;
158   gchar *desc;
159 
160   reply = gst_promise_get_reply (promise);
161   gst_structure_get (reply, "offer",
162       GST_TYPE_WEBRTC_SESSION_DESCRIPTION, &offer, NULL);
163   desc = gst_sdp_message_as_text (offer->sdp);
164   GST_INFO ("Created offer: %s", desc);
165   g_free (desc);
166 
167   g_mutex_lock (&t->lock);
168   if (t->on_offer_created) {
169     gst_webrtc_session_description_free (offer);
170     offer = t->on_offer_created (t, offeror, promise, t->offer_data);
171   }
172   gst_promise_unref (promise);
173 
174   g_signal_emit_by_name (offeror, "set-local-description", offer, NULL);
175   g_signal_emit_by_name (answerer, "set-remote-description", offer, NULL);
176 
177   promise = gst_promise_new_with_change_func (_on_answer_received, t, NULL);
178   g_signal_emit_by_name (answerer, "create-answer", NULL, promise);
179 
180   t->state = STATE_OFFER_CREATED;
181   g_cond_broadcast (&t->cond);
182   g_mutex_unlock (&t->lock);
183 
184   gst_webrtc_session_description_free (offer);
185 }
186 
187 static gboolean
_bus_watch(GstBus * bus,GstMessage * msg,struct test_webrtc * t)188 _bus_watch (GstBus * bus, GstMessage * msg, struct test_webrtc *t)
189 {
190   g_mutex_lock (&t->lock);
191   switch (GST_MESSAGE_TYPE (msg)) {
192     case GST_MESSAGE_STATE_CHANGED:
193       if (GST_ELEMENT (msg->src) == t->webrtc1
194           || GST_ELEMENT (msg->src) == t->webrtc2) {
195         GstState old, new, pending;
196 
197         gst_message_parse_state_changed (msg, &old, &new, &pending);
198 
199         {
200           gchar *dump_name = g_strconcat ("%s-state_changed-",
201               GST_OBJECT_NAME (msg->src), gst_element_state_get_name (old), "_",
202               gst_element_state_get_name (new), NULL);
203           GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (msg->src),
204               GST_DEBUG_GRAPH_SHOW_ALL, dump_name);
205           g_free (dump_name);
206         }
207       }
208       break;
209     case GST_MESSAGE_ERROR:{
210       GError *err = NULL;
211       gchar *dbg_info = NULL;
212 
213       {
214         gchar *dump_name;
215         dump_name =
216             g_strconcat ("%s-error", GST_OBJECT_NAME (t->webrtc1), NULL);
217         GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (t->webrtc1),
218             GST_DEBUG_GRAPH_SHOW_ALL, dump_name);
219         g_free (dump_name);
220         dump_name =
221             g_strconcat ("%s-error", GST_OBJECT_NAME (t->webrtc2), NULL);
222         GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (t->webrtc2),
223             GST_DEBUG_GRAPH_SHOW_ALL, dump_name);
224         g_free (dump_name);
225       }
226 
227       gst_message_parse_error (msg, &err, &dbg_info);
228       GST_WARNING ("ERROR from element %s: %s\n",
229           GST_OBJECT_NAME (msg->src), err->message);
230       GST_WARNING ("Debugging info: %s\n", (dbg_info) ? dbg_info : "none");
231       g_error_free (err);
232       g_free (dbg_info);
233       t->state = STATE_ERROR;
234       g_cond_broadcast (&t->cond);
235       break;
236     }
237     case GST_MESSAGE_EOS:{
238       {
239         gchar *dump_name;
240         dump_name = g_strconcat ("%s-eos", GST_OBJECT_NAME (t->webrtc1), NULL);
241         GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (t->webrtc1),
242             GST_DEBUG_GRAPH_SHOW_ALL, dump_name);
243         g_free (dump_name);
244         dump_name = g_strconcat ("%s-eos", GST_OBJECT_NAME (t->webrtc2), NULL);
245         GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (t->webrtc2),
246             GST_DEBUG_GRAPH_SHOW_ALL, dump_name);
247         g_free (dump_name);
248       }
249       GST_INFO ("EOS received\n");
250       t->state = STATE_EOS;
251       g_cond_broadcast (&t->cond);
252       break;
253     }
254     default:
255       break;
256   }
257 
258   if (t->bus_message)
259     t->bus_message (t, bus, msg, t->bus_data);
260   g_mutex_unlock (&t->lock);
261 
262   return TRUE;
263 }
264 
265 static void
_on_negotiation_needed(GstElement * webrtc,struct test_webrtc * t)266 _on_negotiation_needed (GstElement * webrtc, struct test_webrtc *t)
267 {
268   g_mutex_lock (&t->lock);
269   if (t->on_negotiation_needed)
270     t->on_negotiation_needed (t, webrtc, t->negotiation_data);
271   if (t->state == STATE_NEW)
272     t->state = STATE_NEGOTATION_NEEDED;
273   g_cond_broadcast (&t->cond);
274   g_mutex_unlock (&t->lock);
275 }
276 
277 static void
_on_ice_candidate(GstElement * webrtc,guint mlineindex,gchar * candidate,struct test_webrtc * t)278 _on_ice_candidate (GstElement * webrtc, guint mlineindex, gchar * candidate,
279     struct test_webrtc *t)
280 {
281   GstElement *other;
282 
283   g_mutex_lock (&t->lock);
284   other = webrtc == t->webrtc1 ? t->webrtc2 : t->webrtc1;
285 
286   if (t->on_ice_candidate)
287     t->on_ice_candidate (t, webrtc, mlineindex, candidate, other,
288         t->ice_candidate_data);
289 
290   g_signal_emit_by_name (other, "add-ice-candidate", mlineindex, candidate);
291   g_mutex_unlock (&t->lock);
292 }
293 
294 static void
_on_pad_added(GstElement * webrtc,GstPad * new_pad,struct test_webrtc * t)295 _on_pad_added (GstElement * webrtc, GstPad * new_pad, struct test_webrtc *t)
296 {
297   g_mutex_lock (&t->lock);
298   if (t->on_pad_added)
299     t->on_pad_added (t, webrtc, new_pad, t->pad_added_data);
300   g_mutex_unlock (&t->lock);
301 }
302 
303 static void
_on_data_channel(GstElement * webrtc,GObject * data_channel,struct test_webrtc * t)304 _on_data_channel (GstElement * webrtc, GObject * data_channel,
305     struct test_webrtc *t)
306 {
307   g_mutex_lock (&t->lock);
308   if (t->on_data_channel)
309     t->on_data_channel (t, webrtc, data_channel, t->data_channel_data);
310   g_mutex_unlock (&t->lock);
311 }
312 
313 static void
_pad_added_not_reached(struct test_webrtc * t,GstElement * element,GstPad * pad,gpointer user_data)314 _pad_added_not_reached (struct test_webrtc *t, GstElement * element,
315     GstPad * pad, gpointer user_data)
316 {
317   g_assert_not_reached ();
318 }
319 
320 static void
_ice_candidate_not_reached(struct test_webrtc * t,GstElement * element,guint mlineindex,gchar * candidate,GstElement * other,gpointer user_data)321 _ice_candidate_not_reached (struct test_webrtc *t, GstElement * element,
322     guint mlineindex, gchar * candidate, GstElement * other, gpointer user_data)
323 {
324   g_assert_not_reached ();
325 }
326 
327 static void
_negotiation_not_reached(struct test_webrtc * t,GstElement * element,gpointer user_data)328 _negotiation_not_reached (struct test_webrtc *t, GstElement * element,
329     gpointer user_data)
330 {
331   g_assert_not_reached ();
332 }
333 
334 static void
_bus_no_errors(struct test_webrtc * t,GstBus * bus,GstMessage * msg,gpointer user_data)335 _bus_no_errors (struct test_webrtc *t, GstBus * bus, GstMessage * msg,
336     gpointer user_data)
337 {
338   switch (GST_MESSAGE_TYPE (msg)) {
339     case GST_MESSAGE_ERROR:{
340       g_assert_not_reached ();
341       break;
342     }
343     default:
344       break;
345   }
346 }
347 
348 static GstWebRTCSessionDescription *
_offer_answer_not_reached(struct test_webrtc * t,GstElement * element,GstPromise * promise,gpointer user_data)349 _offer_answer_not_reached (struct test_webrtc *t, GstElement * element,
350     GstPromise * promise, gpointer user_data)
351 {
352   g_assert_not_reached ();
353 }
354 
355 static void
_on_data_channel_not_reached(struct test_webrtc * t,GstElement * element,GObject * data_channel,gpointer user_data)356 _on_data_channel_not_reached (struct test_webrtc *t, GstElement * element,
357     GObject * data_channel, gpointer user_data)
358 {
359   g_assert_not_reached ();
360 }
361 
362 static void
_broadcast(struct test_webrtc * t)363 _broadcast (struct test_webrtc *t)
364 {
365   g_mutex_lock (&t->lock);
366   g_cond_broadcast (&t->cond);
367   g_mutex_unlock (&t->lock);
368 }
369 
370 static gboolean
_unlock_create_thread(GMutex * lock)371 _unlock_create_thread (GMutex * lock)
372 {
373   g_mutex_unlock (lock);
374   return G_SOURCE_REMOVE;
375 }
376 
377 static gpointer
_bus_thread(struct test_webrtc * t)378 _bus_thread (struct test_webrtc *t)
379 {
380   g_mutex_lock (&t->lock);
381   t->loop = g_main_loop_new (NULL, FALSE);
382   g_idle_add ((GSourceFunc) _unlock_create_thread, &t->lock);
383   g_cond_broadcast (&t->cond);
384 
385   g_main_loop_run (t->loop);
386 
387   g_mutex_lock (&t->lock);
388   g_main_loop_unref (t->loop);
389   t->loop = NULL;
390   g_cond_broadcast (&t->cond);
391   g_mutex_unlock (&t->lock);
392 
393   return NULL;
394 }
395 
396 static void
element_added_disable_sync(GstBin * bin,GstBin * sub_bin,GstElement * element,gpointer user_data)397 element_added_disable_sync (GstBin * bin, GstBin * sub_bin,
398     GstElement * element, gpointer user_data)
399 {
400   GObjectClass *class = G_OBJECT_GET_CLASS (element);
401   if (g_object_class_find_property (class, "async"))
402     g_object_set (element, "async", FALSE, NULL);
403   if (g_object_class_find_property (class, "sync"))
404     g_object_set (element, "sync", FALSE, NULL);
405 }
406 
407 static struct test_webrtc *
test_webrtc_new(void)408 test_webrtc_new (void)
409 {
410   struct test_webrtc *ret = g_new0 (struct test_webrtc, 1);
411 
412   ret->on_negotiation_needed = _negotiation_not_reached;
413   ret->on_ice_candidate = _ice_candidate_not_reached;
414   ret->on_pad_added = _pad_added_not_reached;
415   ret->on_offer_created = _offer_answer_not_reached;
416   ret->on_answer_created = _offer_answer_not_reached;
417   ret->on_data_channel = _on_data_channel_not_reached;
418   ret->bus_message = _bus_no_errors;
419 
420   g_mutex_init (&ret->lock);
421   g_cond_init (&ret->cond);
422 
423   ret->bus1 = gst_bus_new ();
424   ret->bus2 = gst_bus_new ();
425   gst_bus_add_watch (ret->bus1, (GstBusFunc) _bus_watch, ret);
426   gst_bus_add_watch (ret->bus2, (GstBusFunc) _bus_watch, ret);
427   ret->webrtc1 = gst_element_factory_make ("webrtcbin", NULL);
428   ret->webrtc2 = gst_element_factory_make ("webrtcbin", NULL);
429   fail_unless (ret->webrtc1 != NULL && ret->webrtc2 != NULL);
430 
431   gst_element_set_bus (ret->webrtc1, ret->bus1);
432   gst_element_set_bus (ret->webrtc2, ret->bus2);
433 
434   g_signal_connect (ret->webrtc1, "deep-element-added",
435       G_CALLBACK (element_added_disable_sync), NULL);
436   g_signal_connect (ret->webrtc2, "deep-element-added",
437       G_CALLBACK (element_added_disable_sync), NULL);
438   g_signal_connect (ret->webrtc1, "on-negotiation-needed",
439       G_CALLBACK (_on_negotiation_needed), ret);
440   g_signal_connect (ret->webrtc2, "on-negotiation-needed",
441       G_CALLBACK (_on_negotiation_needed), ret);
442   g_signal_connect (ret->webrtc1, "on-ice-candidate",
443       G_CALLBACK (_on_ice_candidate), ret);
444   g_signal_connect (ret->webrtc2, "on-ice-candidate",
445       G_CALLBACK (_on_ice_candidate), ret);
446   g_signal_connect (ret->webrtc1, "on-data-channel",
447       G_CALLBACK (_on_data_channel), ret);
448   g_signal_connect (ret->webrtc2, "on-data-channel",
449       G_CALLBACK (_on_data_channel), ret);
450   g_signal_connect (ret->webrtc1, "pad-added", G_CALLBACK (_on_pad_added), ret);
451   g_signal_connect (ret->webrtc2, "pad-added", G_CALLBACK (_on_pad_added), ret);
452   g_signal_connect_swapped (ret->webrtc1, "notify::ice-gathering-state",
453       G_CALLBACK (_broadcast), ret);
454   g_signal_connect_swapped (ret->webrtc2, "notify::ice-gathering-state",
455       G_CALLBACK (_broadcast), ret);
456   g_signal_connect_swapped (ret->webrtc1, "notify::ice-connection-state",
457       G_CALLBACK (_broadcast), ret);
458   g_signal_connect_swapped (ret->webrtc2, "notify::ice-connection-state",
459       G_CALLBACK (_broadcast), ret);
460 
461   ret->thread = g_thread_new ("test-webrtc", (GThreadFunc) _bus_thread, ret);
462 
463   g_mutex_lock (&ret->lock);
464   while (!ret->loop)
465     g_cond_wait (&ret->cond, &ret->lock);
466   g_mutex_unlock (&ret->lock);
467 
468   return ret;
469 }
470 
471 static void
test_webrtc_free(struct test_webrtc * t)472 test_webrtc_free (struct test_webrtc *t)
473 {
474   /* Otherwise while one webrtcbin is being destroyed, the other could
475    * generate a signal that calls into the destroyed webrtcbin */
476   g_signal_handlers_disconnect_by_data (t->webrtc1, t);
477   g_signal_handlers_disconnect_by_data (t->webrtc2, t);
478 
479   g_main_loop_quit (t->loop);
480   g_mutex_lock (&t->lock);
481   while (t->loop)
482     g_cond_wait (&t->cond, &t->lock);
483   g_mutex_unlock (&t->lock);
484 
485   g_thread_join (t->thread);
486 
487   gst_bus_remove_watch (t->bus1);
488   gst_bus_remove_watch (t->bus2);
489 
490   gst_bus_set_flushing (t->bus1, TRUE);
491   gst_bus_set_flushing (t->bus2, TRUE);
492 
493   gst_object_unref (t->bus1);
494   gst_object_unref (t->bus2);
495 
496   g_list_free_full (t->harnesses, (GDestroyNotify) gst_harness_teardown);
497 
498   if (t->data_notify)
499     t->data_notify (t->user_data);
500   if (t->negotiation_notify)
501     t->negotiation_notify (t->negotiation_data);
502   if (t->ice_candidate_notify)
503     t->ice_candidate_notify (t->ice_candidate_data);
504   if (t->offer_notify)
505     t->offer_notify (t->offer_data);
506   if (t->answer_notify)
507     t->answer_notify (t->answer_data);
508   if (t->pad_added_notify)
509     t->pad_added_notify (t->pad_added_data);
510   if (t->data_channel_notify)
511     t->data_channel_notify (t->data_channel_data);
512 
513   fail_unless_equals_int (GST_STATE_CHANGE_SUCCESS,
514       gst_element_set_state (t->webrtc1, GST_STATE_NULL));
515   fail_unless_equals_int (GST_STATE_CHANGE_SUCCESS,
516       gst_element_set_state (t->webrtc2, GST_STATE_NULL));
517 
518   gst_object_unref (t->webrtc1);
519   gst_object_unref (t->webrtc2);
520 
521   g_mutex_clear (&t->lock);
522   g_cond_clear (&t->cond);
523 
524   g_free (t);
525 }
526 
527 static void
test_webrtc_create_offer(struct test_webrtc * t,GstElement * webrtc)528 test_webrtc_create_offer (struct test_webrtc *t, GstElement * webrtc)
529 {
530   GstPromise *promise;
531 
532   t->offerror = webrtc == t->webrtc1 ? 1 : 2;
533   promise = gst_promise_new_with_change_func (_on_offer_received, t, NULL);
534   g_signal_emit_by_name (webrtc, "create-offer", NULL, promise);
535 }
536 
537 static void
test_webrtc_wait_for_state_mask(struct test_webrtc * t,TestState state)538 test_webrtc_wait_for_state_mask (struct test_webrtc *t, TestState state)
539 {
540   g_mutex_lock (&t->lock);
541   while (((1 << t->state) & state) == 0) {
542     GST_INFO ("test state 0x%x, current 0x%x", state, (1 << t->state));
543     g_cond_wait (&t->cond, &t->lock);
544   }
545   GST_INFO ("have test state 0x%x, current 0x%x", state, 1 << t->state);
546   g_mutex_unlock (&t->lock);
547 }
548 
549 static void
test_webrtc_wait_for_answer_error_eos(struct test_webrtc * t)550 test_webrtc_wait_for_answer_error_eos (struct test_webrtc *t)
551 {
552   TestState states = 0;
553   states |= (1 << STATE_ANSWER_CREATED);
554   states |= (1 << STATE_EOS);
555   states |= (1 << STATE_ERROR);
556   test_webrtc_wait_for_state_mask (t, states);
557 }
558 
559 static void
test_webrtc_signal_state_unlocked(struct test_webrtc * t,TestState state)560 test_webrtc_signal_state_unlocked (struct test_webrtc *t, TestState state)
561 {
562   t->state = state;
563   g_cond_broadcast (&t->cond);
564 }
565 
566 static void
test_webrtc_signal_state(struct test_webrtc * t,TestState state)567 test_webrtc_signal_state (struct test_webrtc *t, TestState state)
568 {
569   g_mutex_lock (&t->lock);
570   test_webrtc_signal_state_unlocked (t, state);
571   g_mutex_unlock (&t->lock);
572 }
573 
574 #if 0
575 static void
576 test_webrtc_wait_for_ice_gathering_complete (struct test_webrtc *t)
577 {
578   GstWebRTCICEGatheringState ice_state1, ice_state2;
579   g_mutex_lock (&t->lock);
580   g_object_get (t->webrtc1, "ice-gathering-state", &ice_state1, NULL);
581   g_object_get (t->webrtc2, "ice-gathering-state", &ice_state2, NULL);
582   while (ice_state1 != GST_WEBRTC_ICE_GATHERING_STATE_COMPLETE &&
583       ice_state2 != GST_WEBRTC_ICE_GATHERING_STATE_COMPLETE) {
584     g_cond_wait (&t->cond, &t->lock);
585     g_object_get (t->webrtc1, "ice-gathering-state", &ice_state1, NULL);
586     g_object_get (t->webrtc2, "ice-gathering-state", &ice_state2, NULL);
587   }
588   g_mutex_unlock (&t->lock);
589 }
590 
591 static void
592 test_webrtc_wait_for_ice_connection (struct test_webrtc *t,
593     GstWebRTCICEConnectionState states)
594 {
595   GstWebRTCICEConnectionState ice_state1, ice_state2, current;
596   g_mutex_lock (&t->lock);
597   g_object_get (t->webrtc1, "ice-connection-state", &ice_state1, NULL);
598   g_object_get (t->webrtc2, "ice-connection-state", &ice_state2, NULL);
599   current = (1 << ice_state1) | (1 << ice_state2);
600   while ((current & states) == 0 || (current & ~states)) {
601     g_cond_wait (&t->cond, &t->lock);
602     g_object_get (t->webrtc1, "ice-connection-state", &ice_state1, NULL);
603     g_object_get (t->webrtc2, "ice-connection-state", &ice_state2, NULL);
604     current = (1 << ice_state1) | (1 << ice_state2);
605   }
606   g_mutex_unlock (&t->lock);
607 }
608 #endif
609 static void
_pad_added_fakesink(struct test_webrtc * t,GstElement * element,GstPad * pad,gpointer user_data)610 _pad_added_fakesink (struct test_webrtc *t, GstElement * element,
611     GstPad * pad, gpointer user_data)
612 {
613   GstHarness *h;
614 
615   if (GST_PAD_DIRECTION (pad) != GST_PAD_SRC)
616     return;
617 
618   h = gst_harness_new_with_element (element, NULL, "src_%u");
619   gst_harness_add_sink_parse (h, "fakesink async=false sync=false");
620 
621   t->harnesses = g_list_prepend (t->harnesses, h);
622 }
623 
624 static GstWebRTCSessionDescription *
_count_num_sdp_media(struct test_webrtc * t,GstElement * element,GstPromise * promise,gpointer user_data)625 _count_num_sdp_media (struct test_webrtc *t, GstElement * element,
626     GstPromise * promise, gpointer user_data)
627 {
628   GstWebRTCSessionDescription *offer = NULL;
629   guint expected = GPOINTER_TO_UINT (user_data);
630   const GstStructure *reply;
631   const gchar *field;
632 
633   field = t->offerror == 1 && t->webrtc1 == element ? "offer" : "answer";
634 
635   reply = gst_promise_get_reply (promise);
636   gst_structure_get (reply, field,
637       GST_TYPE_WEBRTC_SESSION_DESCRIPTION, &offer, NULL);
638 
639   fail_unless_equals_int (gst_sdp_message_medias_len (offer->sdp), expected);
640 
641   return offer;
642 }
643 
GST_START_TEST(test_sdp_no_media)644 GST_START_TEST (test_sdp_no_media)
645 {
646   struct test_webrtc *t = test_webrtc_new ();
647 
648   /* check that a no stream connection creates 0 media sections */
649 
650   t->on_negotiation_needed = NULL;
651   t->offer_data = GUINT_TO_POINTER (0);
652   t->on_offer_created = _count_num_sdp_media;
653   t->answer_data = GUINT_TO_POINTER (0);
654   t->on_answer_created = _count_num_sdp_media;
655 
656   fail_if (gst_element_set_state (t->webrtc1,
657           GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
658   fail_if (gst_element_set_state (t->webrtc2,
659           GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
660 
661   test_webrtc_create_offer (t, t->webrtc1);
662 
663   test_webrtc_wait_for_answer_error_eos (t);
664   fail_unless (t->state == STATE_ANSWER_CREATED);
665   test_webrtc_free (t);
666 }
667 
668 GST_END_TEST;
669 
670 static void
add_fake_audio_src_harness(GstHarness * h,gint pt)671 add_fake_audio_src_harness (GstHarness * h, gint pt)
672 {
673   GstCaps *caps = gst_caps_from_string (OPUS_RTP_CAPS (pt));
674   GstStructure *s = gst_caps_get_structure (caps, 0);
675   gst_structure_set (s, "payload", G_TYPE_INT, pt, NULL);
676   gst_harness_set_src_caps (h, caps);
677   gst_harness_add_src_parse (h, "fakesrc is-live=true", TRUE);
678 }
679 
680 static void
add_fake_video_src_harness(GstHarness * h,gint pt)681 add_fake_video_src_harness (GstHarness * h, gint pt)
682 {
683   GstCaps *caps = gst_caps_from_string (VP8_RTP_CAPS (pt));
684   GstStructure *s = gst_caps_get_structure (caps, 0);
685   gst_structure_set (s, "payload", G_TYPE_INT, pt, NULL);
686   gst_harness_set_src_caps (h, caps);
687   gst_harness_add_src_parse (h, "fakesrc is-live=true", TRUE);
688 }
689 
690 static struct test_webrtc *
create_audio_test(void)691 create_audio_test (void)
692 {
693   struct test_webrtc *t = test_webrtc_new ();
694   GstHarness *h;
695 
696   t->on_negotiation_needed = NULL;
697   t->on_pad_added = _pad_added_fakesink;
698 
699   h = gst_harness_new_with_element (t->webrtc1, "sink_0", NULL);
700   add_fake_audio_src_harness (h, 96);
701   t->harnesses = g_list_prepend (t->harnesses, h);
702 
703   return t;
704 }
705 
GST_START_TEST(test_audio)706 GST_START_TEST (test_audio)
707 {
708   struct test_webrtc *t = create_audio_test ();
709 
710   /* check that a single stream connection creates the associated number
711    * of media sections */
712 
713   t->on_negotiation_needed = NULL;
714   t->offer_data = GUINT_TO_POINTER (1);
715   t->on_offer_created = _count_num_sdp_media;
716   t->answer_data = GUINT_TO_POINTER (1);
717   t->on_answer_created = _count_num_sdp_media;
718   t->on_ice_candidate = NULL;
719 
720   fail_if (gst_element_set_state (t->webrtc1,
721           GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
722   fail_if (gst_element_set_state (t->webrtc2,
723           GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
724 
725   test_webrtc_create_offer (t, t->webrtc1);
726 
727   test_webrtc_wait_for_answer_error_eos (t);
728   fail_unless_equals_int (STATE_ANSWER_CREATED, t->state);
729   test_webrtc_free (t);
730 }
731 
732 GST_END_TEST;
733 
734 static struct test_webrtc *
create_audio_video_test(void)735 create_audio_video_test (void)
736 {
737   struct test_webrtc *t = test_webrtc_new ();
738   GstHarness *h;
739 
740   t->on_negotiation_needed = NULL;
741   t->on_pad_added = _pad_added_fakesink;
742 
743   h = gst_harness_new_with_element (t->webrtc1, "sink_0", NULL);
744   add_fake_audio_src_harness (h, 96);
745   t->harnesses = g_list_prepend (t->harnesses, h);
746 
747   h = gst_harness_new_with_element (t->webrtc1, "sink_1", NULL);
748   add_fake_video_src_harness (h, 97);
749   t->harnesses = g_list_prepend (t->harnesses, h);
750 
751   return t;
752 }
753 
GST_START_TEST(test_audio_video)754 GST_START_TEST (test_audio_video)
755 {
756   struct test_webrtc *t = create_audio_video_test ();
757 
758   /* check that a dual stream connection creates the associated number
759    * of media sections */
760 
761   t->on_negotiation_needed = NULL;
762   t->offer_data = GUINT_TO_POINTER (2);
763   t->on_offer_created = _count_num_sdp_media;
764   t->answer_data = GUINT_TO_POINTER (2);
765   t->on_answer_created = _count_num_sdp_media;
766   t->on_ice_candidate = NULL;
767 
768   fail_if (gst_element_set_state (t->webrtc1,
769           GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
770   fail_if (gst_element_set_state (t->webrtc2,
771           GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
772 
773   test_webrtc_create_offer (t, t->webrtc1);
774 
775   test_webrtc_wait_for_answer_error_eos (t);
776   fail_unless_equals_int (STATE_ANSWER_CREATED, t->state);
777   test_webrtc_free (t);
778 }
779 
780 GST_END_TEST;
781 
782 typedef void (*ValidateSDPFunc) (struct test_webrtc * t, GstElement * element,
783     GstWebRTCSessionDescription * desc, gpointer user_data);
784 
785 struct validate_sdp
786 {
787   ValidateSDPFunc validate;
788   gpointer user_data;
789 };
790 
791 static GstWebRTCSessionDescription *
_check_validate_sdp(struct test_webrtc * t,GstElement * element,GstPromise * promise,gpointer user_data)792 _check_validate_sdp (struct test_webrtc *t, GstElement * element,
793     GstPromise * promise, gpointer user_data)
794 {
795   struct validate_sdp *validate = user_data;
796   GstWebRTCSessionDescription *offer = NULL;
797   const GstStructure *reply;
798   const gchar *field;
799 
800   field = t->offerror == 1 && t->webrtc1 == element ? "offer" : "answer";
801 
802   reply = gst_promise_get_reply (promise);
803   gst_structure_get (reply, field,
804       GST_TYPE_WEBRTC_SESSION_DESCRIPTION, &offer, NULL);
805 
806   validate->validate (t, element, offer, validate->user_data);
807 
808   return offer;
809 }
810 
811 static void
on_sdp_media_direction(struct test_webrtc * t,GstElement * element,GstWebRTCSessionDescription * desc,gpointer user_data)812 on_sdp_media_direction (struct test_webrtc *t, GstElement * element,
813     GstWebRTCSessionDescription * desc, gpointer user_data)
814 {
815   gchar **expected_directions = user_data;
816   int i;
817 
818   for (i = 0; i < gst_sdp_message_medias_len (desc->sdp); i++) {
819     const GstSDPMedia *media = gst_sdp_message_get_media (desc->sdp, i);
820     gboolean have_direction = FALSE;
821     int j;
822 
823     for (j = 0; j < gst_sdp_media_attributes_len (media); j++) {
824       const GstSDPAttribute *attr = gst_sdp_media_get_attribute (media, j);
825 
826       if (g_strcmp0 (attr->key, "inactive") == 0) {
827         fail_unless (have_direction == FALSE,
828             "duplicate/multiple directions for media %u", j);
829         have_direction = TRUE;
830         fail_unless (g_strcmp0 (attr->key, expected_directions[i]) == 0);
831       } else if (g_strcmp0 (attr->key, "sendonly") == 0) {
832         fail_unless (have_direction == FALSE,
833             "duplicate/multiple directions for media %u", j);
834         have_direction = TRUE;
835         fail_unless (g_strcmp0 (attr->key, expected_directions[i]) == 0);
836       } else if (g_strcmp0 (attr->key, "recvonly") == 0) {
837         fail_unless (have_direction == FALSE,
838             "duplicate/multiple directions for media %u", j);
839         have_direction = TRUE;
840         fail_unless (g_strcmp0 (attr->key, expected_directions[i]) == 0);
841       } else if (g_strcmp0 (attr->key, "sendrecv") == 0) {
842         fail_unless (have_direction == FALSE,
843             "duplicate/multiple directions for media %u", j);
844         have_direction = TRUE;
845         fail_unless (g_strcmp0 (attr->key, expected_directions[i]) == 0);
846       }
847     }
848     fail_unless (have_direction, "no direction attribute in media %u", j);
849   }
850 }
851 
GST_START_TEST(test_media_direction)852 GST_START_TEST (test_media_direction)
853 {
854   struct test_webrtc *t = create_audio_video_test ();
855   const gchar *expected_offer[] = { "sendrecv", "sendrecv" };
856   const gchar *expected_answer[] = { "sendrecv", "recvonly" };
857   struct validate_sdp offer = { on_sdp_media_direction, expected_offer };
858   struct validate_sdp answer = { on_sdp_media_direction, expected_answer };
859   GstHarness *h;
860 
861   /* check the default media directions for transceivers */
862 
863   h = gst_harness_new_with_element (t->webrtc2, "sink_0", NULL);
864   add_fake_audio_src_harness (h, 96);
865   t->harnesses = g_list_prepend (t->harnesses, h);
866 
867   t->on_negotiation_needed = NULL;
868   t->offer_data = &offer;
869   t->on_offer_created = _check_validate_sdp;
870   t->answer_data = &answer;
871   t->on_answer_created = _check_validate_sdp;
872   t->on_ice_candidate = NULL;
873 
874   fail_if (gst_element_set_state (t->webrtc1,
875           GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
876   fail_if (gst_element_set_state (t->webrtc2,
877           GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
878 
879   test_webrtc_create_offer (t, t->webrtc1);
880 
881   test_webrtc_wait_for_answer_error_eos (t);
882   fail_unless_equals_int (STATE_ANSWER_CREATED, t->state);
883   test_webrtc_free (t);
884 }
885 
886 GST_END_TEST;
887 
888 static void
on_sdp_media_payload_types(struct test_webrtc * t,GstElement * element,GstWebRTCSessionDescription * desc,gpointer user_data)889 on_sdp_media_payload_types (struct test_webrtc *t, GstElement * element,
890     GstWebRTCSessionDescription * desc, gpointer user_data)
891 {
892   const GstSDPMedia *vmedia;
893   guint j;
894 
895   fail_unless_equals_int (gst_sdp_message_medias_len (desc->sdp), 2);
896 
897   vmedia = gst_sdp_message_get_media (desc->sdp, 1);
898 
899   for (j = 0; j < gst_sdp_media_attributes_len (vmedia); j++) {
900     const GstSDPAttribute *attr = gst_sdp_media_get_attribute (vmedia, j);
901 
902     if (!g_strcmp0 (attr->key, "rtpmap")) {
903       if (g_str_has_prefix (attr->value, "97")) {
904         fail_unless_equals_string (attr->value, "97 VP8/90000");
905       } else if (g_str_has_prefix (attr->value, "96")) {
906         fail_unless_equals_string (attr->value, "96 red/90000");
907       } else if (g_str_has_prefix (attr->value, "98")) {
908         fail_unless_equals_string (attr->value, "98 ulpfec/90000");
909       } else if (g_str_has_prefix (attr->value, "99")) {
910         fail_unless_equals_string (attr->value, "99 rtx/90000");
911       } else if (g_str_has_prefix (attr->value, "100")) {
912         fail_unless_equals_string (attr->value, "100 rtx/90000");
913       }
914     }
915   }
916 }
917 
918 /* In this test we verify that webrtcbin will pick available payload
919  * types when it needs to, in that example for RTX and FEC */
GST_START_TEST(test_payload_types)920 GST_START_TEST (test_payload_types)
921 {
922   struct test_webrtc *t = create_audio_video_test ();
923   struct validate_sdp offer = { on_sdp_media_payload_types, NULL };
924   GstWebRTCRTPTransceiver *trans;
925   GArray *transceivers;
926 
927   t->on_negotiation_needed = NULL;
928   t->offer_data = &offer;
929   t->on_offer_created = _check_validate_sdp;
930   t->on_ice_candidate = NULL;
931   /* We don't really care about the answer here */
932   t->on_answer_created = NULL;
933 
934   g_signal_emit_by_name (t->webrtc1, "get-transceivers", &transceivers);
935   fail_unless_equals_int (transceivers->len, 2);
936   trans = g_array_index (transceivers, GstWebRTCRTPTransceiver *, 1);
937   g_object_set (trans, "fec-type", GST_WEBRTC_FEC_TYPE_ULP_RED, "do-nack", TRUE,
938       NULL);
939   g_array_unref (transceivers);
940 
941   fail_if (gst_element_set_state (t->webrtc1,
942           GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
943   fail_if (gst_element_set_state (t->webrtc2,
944           GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
945 
946   test_webrtc_create_offer (t, t->webrtc1);
947 
948   test_webrtc_wait_for_answer_error_eos (t);
949   fail_unless_equals_int (STATE_ANSWER_CREATED, t->state);
950   test_webrtc_free (t);
951 }
952 
953 GST_END_TEST;
954 
955 static void
on_sdp_media_setup(struct test_webrtc * t,GstElement * element,GstWebRTCSessionDescription * desc,gpointer user_data)956 on_sdp_media_setup (struct test_webrtc *t, GstElement * element,
957     GstWebRTCSessionDescription * desc, gpointer user_data)
958 {
959   gchar **expected_setup = user_data;
960   int i;
961 
962   for (i = 0; i < gst_sdp_message_medias_len (desc->sdp); i++) {
963     const GstSDPMedia *media = gst_sdp_message_get_media (desc->sdp, i);
964     gboolean have_setup = FALSE;
965     int j;
966 
967     for (j = 0; j < gst_sdp_media_attributes_len (media); j++) {
968       const GstSDPAttribute *attr = gst_sdp_media_get_attribute (media, j);
969 
970       if (g_strcmp0 (attr->key, "setup") == 0) {
971         fail_unless (have_setup == FALSE,
972             "duplicate/multiple setup for media %u", j);
973         have_setup = TRUE;
974         fail_unless (g_strcmp0 (attr->value, expected_setup[i]) == 0);
975       }
976     }
977     fail_unless (have_setup, "no setup attribute in media %u", j);
978   }
979 }
980 
GST_START_TEST(test_media_setup)981 GST_START_TEST (test_media_setup)
982 {
983   struct test_webrtc *t = create_audio_test ();
984   const gchar *expected_offer[] = { "actpass" };
985   const gchar *expected_answer[] = { "active" };
986   struct validate_sdp offer = { on_sdp_media_setup, expected_offer };
987   struct validate_sdp answer = { on_sdp_media_setup, expected_answer };
988 
989   /* check the default dtls setup negotiation values */
990 
991   t->on_negotiation_needed = NULL;
992   t->offer_data = &offer;
993   t->on_offer_created = _check_validate_sdp;
994   t->answer_data = &answer;
995   t->on_answer_created = _check_validate_sdp;
996   t->on_ice_candidate = NULL;
997 
998   fail_if (gst_element_set_state (t->webrtc1,
999           GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
1000   fail_if (gst_element_set_state (t->webrtc2,
1001           GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
1002 
1003   test_webrtc_create_offer (t, t->webrtc1);
1004 
1005   test_webrtc_wait_for_answer_error_eos (t);
1006   fail_unless_equals_int (STATE_ANSWER_CREATED, t->state);
1007   test_webrtc_free (t);
1008 }
1009 
1010 GST_END_TEST;
1011 
GST_START_TEST(test_no_nice_elements_request_pad)1012 GST_START_TEST (test_no_nice_elements_request_pad)
1013 {
1014   struct test_webrtc *t = test_webrtc_new ();
1015   GstPluginFeature *nicesrc, *nicesink;
1016   GstRegistry *registry;
1017   GstPad *pad;
1018 
1019   /* check that the absence of libnice elements posts an error on the bus
1020    * when requesting a pad */
1021 
1022   registry = gst_registry_get ();
1023   nicesrc = gst_registry_lookup_feature (registry, "nicesrc");
1024   nicesink = gst_registry_lookup_feature (registry, "nicesink");
1025 
1026   if (nicesrc)
1027     gst_registry_remove_feature (registry, nicesrc);
1028   if (nicesink)
1029     gst_registry_remove_feature (registry, nicesink);
1030 
1031   t->bus_message = NULL;
1032 
1033   pad = gst_element_get_request_pad (t->webrtc1, "sink_0");
1034   fail_unless (pad == NULL);
1035 
1036   test_webrtc_wait_for_answer_error_eos (t);
1037   fail_unless_equals_int (STATE_ERROR, t->state);
1038   test_webrtc_free (t);
1039 
1040   if (nicesrc)
1041     gst_registry_add_feature (registry, nicesrc);
1042   if (nicesink)
1043     gst_registry_add_feature (registry, nicesink);
1044 }
1045 
1046 GST_END_TEST;
1047 
GST_START_TEST(test_no_nice_elements_state_change)1048 GST_START_TEST (test_no_nice_elements_state_change)
1049 {
1050   struct test_webrtc *t = test_webrtc_new ();
1051   GstPluginFeature *nicesrc, *nicesink;
1052   GstRegistry *registry;
1053 
1054   /* check that the absence of libnice elements posts an error on the bus */
1055 
1056   registry = gst_registry_get ();
1057   nicesrc = gst_registry_lookup_feature (registry, "nicesrc");
1058   nicesink = gst_registry_lookup_feature (registry, "nicesink");
1059 
1060   if (nicesrc)
1061     gst_registry_remove_feature (registry, nicesrc);
1062   if (nicesink)
1063     gst_registry_remove_feature (registry, nicesink);
1064 
1065   t->bus_message = NULL;
1066   gst_element_set_state (t->webrtc1, GST_STATE_READY);
1067 
1068   test_webrtc_wait_for_answer_error_eos (t);
1069   fail_unless_equals_int (STATE_ERROR, t->state);
1070   test_webrtc_free (t);
1071 
1072   if (nicesrc)
1073     gst_registry_add_feature (registry, nicesrc);
1074   if (nicesink)
1075     gst_registry_add_feature (registry, nicesink);
1076 }
1077 
1078 GST_END_TEST;
1079 
1080 static void
validate_rtc_stats(const GstStructure * s)1081 validate_rtc_stats (const GstStructure * s)
1082 {
1083   GstWebRTCStatsType type = 0;
1084   double ts = 0.;
1085   gchar *id = NULL;
1086 
1087   fail_unless (gst_structure_get (s, "type", GST_TYPE_WEBRTC_STATS_TYPE, &type,
1088           NULL));
1089   fail_unless (gst_structure_get (s, "id", G_TYPE_STRING, &id, NULL));
1090   fail_unless (gst_structure_get (s, "timestamp", G_TYPE_DOUBLE, &ts, NULL));
1091   fail_unless (type != 0);
1092   fail_unless (ts != 0.);
1093   fail_unless (id != NULL);
1094 
1095   g_free (id);
1096 }
1097 
1098 static void
validate_codec_stats(const GstStructure * s)1099 validate_codec_stats (const GstStructure * s)
1100 {
1101   guint pt = 0, clock_rate = 0;
1102 
1103   fail_unless (gst_structure_get (s, "payload-type", G_TYPE_UINT, &pt, NULL));
1104   fail_unless (gst_structure_get (s, "clock-rate", G_TYPE_UINT, &clock_rate,
1105           NULL));
1106   fail_unless (pt >= 0 && pt <= 127);
1107   fail_unless (clock_rate >= 0);
1108 }
1109 
1110 static void
validate_rtc_stream_stats(const GstStructure * s,const GstStructure * stats)1111 validate_rtc_stream_stats (const GstStructure * s, const GstStructure * stats)
1112 {
1113   gchar *codec_id, *transport_id;
1114   GstStructure *codec, *transport;
1115 
1116   fail_unless (gst_structure_get (s, "codec-id", G_TYPE_STRING, &codec_id,
1117           NULL));
1118   fail_unless (gst_structure_get (s, "transport-id", G_TYPE_STRING,
1119           &transport_id, NULL));
1120 
1121   fail_unless (gst_structure_get (stats, codec_id, GST_TYPE_STRUCTURE, &codec,
1122           NULL));
1123   fail_unless (gst_structure_get (stats, transport_id, GST_TYPE_STRUCTURE,
1124           &transport, NULL));
1125 
1126   fail_unless (codec != NULL);
1127   fail_unless (transport != NULL);
1128 
1129   gst_structure_free (transport);
1130   gst_structure_free (codec);
1131 
1132   g_free (codec_id);
1133   g_free (transport_id);
1134 }
1135 
1136 static void
validate_inbound_rtp_stats(const GstStructure * s,const GstStructure * stats)1137 validate_inbound_rtp_stats (const GstStructure * s, const GstStructure * stats)
1138 {
1139   guint ssrc, fir, pli, nack;
1140   gint packets_lost;
1141   guint64 packets_received, bytes_received;
1142   double jitter;
1143   gchar *remote_id;
1144   GstStructure *remote;
1145 
1146   validate_rtc_stream_stats (s, stats);
1147 
1148   fail_unless (gst_structure_get (s, "ssrc", G_TYPE_UINT, &ssrc, NULL));
1149   fail_unless (gst_structure_get (s, "fir-count", G_TYPE_UINT, &fir, NULL));
1150   fail_unless (gst_structure_get (s, "pli-count", G_TYPE_UINT, &pli, NULL));
1151   fail_unless (gst_structure_get (s, "nack-count", G_TYPE_UINT, &nack, NULL));
1152   fail_unless (gst_structure_get (s, "packets-received", G_TYPE_UINT64,
1153           &packets_received, NULL));
1154   fail_unless (gst_structure_get (s, "bytes-received", G_TYPE_UINT64,
1155           &bytes_received, NULL));
1156   fail_unless (gst_structure_get (s, "jitter", G_TYPE_DOUBLE, &jitter, NULL));
1157   fail_unless (gst_structure_get (s, "packets-lost", G_TYPE_INT, &packets_lost,
1158           NULL));
1159   fail_unless (gst_structure_get (s, "remote-id", G_TYPE_STRING, &remote_id,
1160           NULL));
1161   fail_unless (gst_structure_get (stats, remote_id, GST_TYPE_STRUCTURE, &remote,
1162           NULL));
1163   fail_unless (remote != NULL);
1164 
1165   gst_structure_free (remote);
1166   g_free (remote_id);
1167 }
1168 
1169 static void
validate_remote_inbound_rtp_stats(const GstStructure * s,const GstStructure * stats)1170 validate_remote_inbound_rtp_stats (const GstStructure * s,
1171     const GstStructure * stats)
1172 {
1173   guint ssrc;
1174   gint packets_lost;
1175   double jitter, rtt;
1176   gchar *local_id;
1177   GstStructure *local;
1178 
1179   validate_rtc_stream_stats (s, stats);
1180 
1181   fail_unless (gst_structure_get (s, "ssrc", G_TYPE_UINT, &ssrc, NULL));
1182   fail_unless (gst_structure_get (s, "jitter", G_TYPE_DOUBLE, &jitter, NULL));
1183   fail_unless (gst_structure_get (s, "packets-lost", G_TYPE_INT, &packets_lost,
1184           NULL));
1185   fail_unless (gst_structure_get (s, "round-trip-time", G_TYPE_DOUBLE, &rtt,
1186           NULL));
1187   fail_unless (gst_structure_get (s, "local-id", G_TYPE_STRING, &local_id,
1188           NULL));
1189   fail_unless (gst_structure_get (stats, local_id, GST_TYPE_STRUCTURE, &local,
1190           NULL));
1191   fail_unless (local != NULL);
1192 
1193   gst_structure_free (local);
1194   g_free (local_id);
1195 }
1196 
1197 static void
validate_outbound_rtp_stats(const GstStructure * s,const GstStructure * stats)1198 validate_outbound_rtp_stats (const GstStructure * s, const GstStructure * stats)
1199 {
1200   guint ssrc, fir, pli, nack;
1201   guint64 packets_sent, bytes_sent;
1202   gchar *remote_id;
1203   GstStructure *remote;
1204 
1205   validate_rtc_stream_stats (s, stats);
1206 
1207   fail_unless (gst_structure_get (s, "ssrc", G_TYPE_UINT, &ssrc, NULL));
1208   fail_unless (gst_structure_get (s, "fir-count", G_TYPE_UINT, &fir, NULL));
1209   fail_unless (gst_structure_get (s, "pli-count", G_TYPE_UINT, &pli, NULL));
1210   fail_unless (gst_structure_get (s, "nack-count", G_TYPE_UINT, &nack, NULL));
1211   fail_unless (gst_structure_get (s, "packets-sent", G_TYPE_UINT64,
1212           &packets_sent, NULL));
1213   fail_unless (gst_structure_get (s, "bytes-sent", G_TYPE_UINT64, &bytes_sent,
1214           NULL));
1215   fail_unless (gst_structure_get (s, "remote-id", G_TYPE_STRING, &remote_id,
1216           NULL));
1217   fail_unless (gst_structure_get (stats, remote_id, GST_TYPE_STRUCTURE, &remote,
1218           NULL));
1219   fail_unless (remote != NULL);
1220 
1221   gst_structure_free (remote);
1222   g_free (remote_id);
1223 }
1224 
1225 static void
validate_remote_outbound_rtp_stats(const GstStructure * s,const GstStructure * stats)1226 validate_remote_outbound_rtp_stats (const GstStructure * s,
1227     const GstStructure * stats)
1228 {
1229   guint ssrc;
1230   gchar *local_id;
1231   GstStructure *local;
1232 
1233   validate_rtc_stream_stats (s, stats);
1234 
1235   fail_unless (gst_structure_get (s, "ssrc", G_TYPE_UINT, &ssrc, NULL));
1236   fail_unless (gst_structure_get (s, "local-id", G_TYPE_STRING, &local_id,
1237           NULL));
1238   fail_unless (gst_structure_get (stats, local_id, GST_TYPE_STRUCTURE, &local,
1239           NULL));
1240   fail_unless (local != NULL);
1241 
1242   gst_structure_free (local);
1243   g_free (local_id);
1244 }
1245 
1246 static gboolean
validate_stats_foreach(GQuark field_id,const GValue * value,const GstStructure * stats)1247 validate_stats_foreach (GQuark field_id, const GValue * value,
1248     const GstStructure * stats)
1249 {
1250   const gchar *field = g_quark_to_string (field_id);
1251   GstWebRTCStatsType type;
1252   const GstStructure *s;
1253 
1254   fail_unless (GST_VALUE_HOLDS_STRUCTURE (value));
1255 
1256   s = gst_value_get_structure (value);
1257 
1258   GST_INFO ("validating field %s %" GST_PTR_FORMAT, field, s);
1259 
1260   validate_rtc_stats (s);
1261   gst_structure_get (s, "type", GST_TYPE_WEBRTC_STATS_TYPE, &type, NULL);
1262   if (type == GST_WEBRTC_STATS_CODEC) {
1263     validate_codec_stats (s);
1264   } else if (type == GST_WEBRTC_STATS_INBOUND_RTP) {
1265     validate_inbound_rtp_stats (s, stats);
1266   } else if (type == GST_WEBRTC_STATS_OUTBOUND_RTP) {
1267     validate_outbound_rtp_stats (s, stats);
1268   } else if (type == GST_WEBRTC_STATS_REMOTE_INBOUND_RTP) {
1269     validate_remote_inbound_rtp_stats (s, stats);
1270   } else if (type == GST_WEBRTC_STATS_REMOTE_OUTBOUND_RTP) {
1271     validate_remote_outbound_rtp_stats (s, stats);
1272   } else if (type == GST_WEBRTC_STATS_CSRC) {
1273   } else if (type == GST_WEBRTC_STATS_PEER_CONNECTION) {
1274   } else if (type == GST_WEBRTC_STATS_DATA_CHANNEL) {
1275   } else if (type == GST_WEBRTC_STATS_STREAM) {
1276   } else if (type == GST_WEBRTC_STATS_TRANSPORT) {
1277   } else if (type == GST_WEBRTC_STATS_CANDIDATE_PAIR) {
1278   } else if (type == GST_WEBRTC_STATS_LOCAL_CANDIDATE) {
1279   } else if (type == GST_WEBRTC_STATS_REMOTE_CANDIDATE) {
1280   } else if (type == GST_WEBRTC_STATS_CERTIFICATE) {
1281   } else {
1282     g_assert_not_reached ();
1283   }
1284 
1285   return TRUE;
1286 }
1287 
1288 static void
validate_stats(const GstStructure * stats)1289 validate_stats (const GstStructure * stats)
1290 {
1291   gst_structure_foreach (stats,
1292       (GstStructureForeachFunc) validate_stats_foreach, (gpointer) stats);
1293 }
1294 
1295 static void
_on_stats(GstPromise * promise,gpointer user_data)1296 _on_stats (GstPromise * promise, gpointer user_data)
1297 {
1298   struct test_webrtc *t = user_data;
1299   const GstStructure *reply = gst_promise_get_reply (promise);
1300   int i;
1301 
1302   validate_stats (reply);
1303   i = GPOINTER_TO_INT (t->user_data);
1304   i++;
1305   t->user_data = GINT_TO_POINTER (i);
1306   if (i >= 2)
1307     test_webrtc_signal_state (t, STATE_CUSTOM);
1308 
1309   gst_promise_unref (promise);
1310 }
1311 
GST_START_TEST(test_session_stats)1312 GST_START_TEST (test_session_stats)
1313 {
1314   struct test_webrtc *t = test_webrtc_new ();
1315   GstPromise *p;
1316 
1317   /* test that the stats generated without any streams are sane */
1318 
1319   t->on_negotiation_needed = NULL;
1320   t->on_offer_created = NULL;
1321   t->on_answer_created = NULL;
1322 
1323   fail_if (gst_element_set_state (t->webrtc1,
1324           GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
1325   fail_if (gst_element_set_state (t->webrtc2,
1326           GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
1327 
1328   test_webrtc_create_offer (t, t->webrtc1);
1329 
1330   test_webrtc_wait_for_answer_error_eos (t);
1331   fail_unless_equals_int (STATE_ANSWER_CREATED, t->state);
1332 
1333   p = gst_promise_new_with_change_func (_on_stats, t, NULL);
1334   g_signal_emit_by_name (t->webrtc1, "get-stats", NULL, p);
1335   p = gst_promise_new_with_change_func (_on_stats, t, NULL);
1336   g_signal_emit_by_name (t->webrtc2, "get-stats", NULL, p);
1337 
1338   test_webrtc_wait_for_state_mask (t, 1 << STATE_CUSTOM);
1339 
1340   test_webrtc_free (t);
1341 }
1342 
1343 GST_END_TEST;
1344 
GST_START_TEST(test_add_transceiver)1345 GST_START_TEST (test_add_transceiver)
1346 {
1347   struct test_webrtc *t = test_webrtc_new ();
1348   GstWebRTCRTPTransceiverDirection direction;
1349   GstWebRTCRTPTransceiver *trans;
1350 
1351   direction = GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_SENDRECV;
1352   g_signal_emit_by_name (t->webrtc1, "add-transceiver", direction, NULL,
1353       &trans);
1354   fail_unless (trans != NULL);
1355   fail_unless_equals_int (direction, trans->direction);
1356 
1357   gst_object_unref (trans);
1358 
1359   test_webrtc_free (t);
1360 }
1361 
1362 GST_END_TEST;
1363 
GST_START_TEST(test_get_transceivers)1364 GST_START_TEST (test_get_transceivers)
1365 {
1366   struct test_webrtc *t = create_audio_test ();
1367   GstWebRTCRTPTransceiver *trans;
1368   GArray *transceivers;
1369 
1370   g_signal_emit_by_name (t->webrtc1, "get-transceivers", &transceivers);
1371   fail_unless (transceivers != NULL);
1372   fail_unless_equals_int (1, transceivers->len);
1373 
1374   trans = g_array_index (transceivers, GstWebRTCRTPTransceiver *, 0);
1375   fail_unless (trans != NULL);
1376 
1377   g_array_unref (transceivers);
1378 
1379   test_webrtc_free (t);
1380 }
1381 
1382 GST_END_TEST;
1383 
GST_START_TEST(test_add_recvonly_transceiver)1384 GST_START_TEST (test_add_recvonly_transceiver)
1385 {
1386   struct test_webrtc *t = test_webrtc_new ();
1387   GstWebRTCRTPTransceiverDirection direction;
1388   GstWebRTCRTPTransceiver *trans;
1389   const gchar *expected_offer[] = { "recvonly" };
1390   const gchar *expected_answer[] = { "sendonly" };
1391   struct validate_sdp offer = { on_sdp_media_direction, expected_offer };
1392   struct validate_sdp answer = { on_sdp_media_direction, expected_answer };
1393   GstCaps *caps;
1394   GstHarness *h;
1395 
1396   /* add a transceiver that will only receive an opus stream and check that
1397    * the created offer is marked as recvonly */
1398 
1399   t->on_negotiation_needed = NULL;
1400   t->on_pad_added = _pad_added_fakesink;
1401   t->on_negotiation_needed = NULL;
1402   t->offer_data = &offer;
1403   t->on_offer_created = _check_validate_sdp;
1404   t->answer_data = &answer;
1405   t->on_answer_created = _check_validate_sdp;
1406   t->on_ice_candidate = NULL;
1407 
1408   /* setup recvonly transceiver */
1409   caps = gst_caps_from_string (OPUS_RTP_CAPS (96));
1410   direction = GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_RECVONLY;
1411   g_signal_emit_by_name (t->webrtc1, "add-transceiver", direction, caps,
1412       &trans);
1413   gst_caps_unref (caps);
1414   fail_unless (trans != NULL);
1415   gst_object_unref (trans);
1416 
1417   /* setup sendonly peer */
1418   h = gst_harness_new_with_element (t->webrtc2, "sink_0", NULL);
1419   add_fake_audio_src_harness (h, 96);
1420   t->harnesses = g_list_prepend (t->harnesses, h);
1421 
1422   fail_if (gst_element_set_state (t->webrtc1,
1423           GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
1424   fail_if (gst_element_set_state (t->webrtc2,
1425           GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
1426 
1427   test_webrtc_create_offer (t, t->webrtc1);
1428 
1429   test_webrtc_wait_for_answer_error_eos (t);
1430   fail_unless_equals_int (STATE_ANSWER_CREATED, t->state);
1431   test_webrtc_free (t);
1432 }
1433 
1434 GST_END_TEST;
1435 
GST_START_TEST(test_recvonly_sendonly)1436 GST_START_TEST (test_recvonly_sendonly)
1437 {
1438   struct test_webrtc *t = test_webrtc_new ();
1439   GstWebRTCRTPTransceiverDirection direction;
1440   GstWebRTCRTPTransceiver *trans;
1441   const gchar *expected_offer[] = { "recvonly", "sendonly" };
1442   const gchar *expected_answer[] = { "sendonly", "recvonly" };
1443   struct validate_sdp offer = { on_sdp_media_direction, expected_offer };
1444   struct validate_sdp answer = { on_sdp_media_direction, expected_answer };
1445   GstCaps *caps;
1446   GstHarness *h;
1447   GArray *transceivers;
1448 
1449   /* add a transceiver that will only receive an opus stream and check that
1450    * the created offer is marked as recvonly */
1451 
1452   t->on_negotiation_needed = NULL;
1453   t->on_pad_added = _pad_added_fakesink;
1454   t->on_negotiation_needed = NULL;
1455   t->offer_data = &offer;
1456   t->on_offer_created = _check_validate_sdp;
1457   t->answer_data = &answer;
1458   t->on_answer_created = _check_validate_sdp;
1459   t->on_ice_candidate = NULL;
1460 
1461   /* setup recvonly transceiver */
1462   caps = gst_caps_from_string (OPUS_RTP_CAPS (96));
1463   direction = GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_RECVONLY;
1464   g_signal_emit_by_name (t->webrtc1, "add-transceiver", direction, caps,
1465       &trans);
1466   gst_caps_unref (caps);
1467   fail_unless (trans != NULL);
1468   gst_object_unref (trans);
1469 
1470   /* setup sendonly stream */
1471   h = gst_harness_new_with_element (t->webrtc1, "sink_1", NULL);
1472   add_fake_audio_src_harness (h, 96);
1473   t->harnesses = g_list_prepend (t->harnesses, h);
1474   g_signal_emit_by_name (t->webrtc1, "get-transceivers", &transceivers);
1475   fail_unless (transceivers != NULL);
1476   trans = g_array_index (transceivers, GstWebRTCRTPTransceiver *, 1);
1477   trans->direction = GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_SENDONLY;
1478 
1479   g_array_unref (transceivers);
1480 
1481   /* setup sendonly peer */
1482   h = gst_harness_new_with_element (t->webrtc2, "sink_0", NULL);
1483   add_fake_audio_src_harness (h, 96);
1484   t->harnesses = g_list_prepend (t->harnesses, h);
1485 
1486   fail_if (gst_element_set_state (t->webrtc1,
1487           GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
1488   fail_if (gst_element_set_state (t->webrtc2,
1489           GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
1490 
1491   test_webrtc_create_offer (t, t->webrtc1);
1492 
1493   test_webrtc_wait_for_answer_error_eos (t);
1494   fail_unless_equals_int (STATE_ANSWER_CREATED, t->state);
1495   test_webrtc_free (t);
1496 }
1497 
1498 GST_END_TEST;
1499 
1500 static void
on_sdp_has_datachannel(struct test_webrtc * t,GstElement * element,GstWebRTCSessionDescription * desc,gpointer user_data)1501 on_sdp_has_datachannel (struct test_webrtc *t, GstElement * element,
1502     GstWebRTCSessionDescription * desc, gpointer user_data)
1503 {
1504   gboolean have_data_channel = FALSE;
1505   int i;
1506 
1507   for (i = 0; i < gst_sdp_message_medias_len (desc->sdp); i++) {
1508     if (_message_media_is_datachannel (desc->sdp, i)) {
1509       /* there should only be one data channel m= section */
1510       fail_unless_equals_int (FALSE, have_data_channel);
1511       have_data_channel = TRUE;
1512     }
1513   }
1514 
1515   fail_unless_equals_int (TRUE, have_data_channel);
1516 }
1517 
1518 static void
on_channel_error_not_reached(GObject * channel,GError * error,gpointer user_data)1519 on_channel_error_not_reached (GObject * channel, GError * error,
1520     gpointer user_data)
1521 {
1522   g_assert_not_reached ();
1523 }
1524 
GST_START_TEST(test_data_channel_create)1525 GST_START_TEST (test_data_channel_create)
1526 {
1527   struct test_webrtc *t = test_webrtc_new ();
1528   GObject *channel = NULL;
1529   struct validate_sdp offer = { on_sdp_has_datachannel, NULL };
1530   struct validate_sdp answer = { on_sdp_has_datachannel, NULL };
1531   gchar *label;
1532 
1533   t->on_negotiation_needed = NULL;
1534   t->offer_data = &offer;
1535   t->on_offer_created = _check_validate_sdp;
1536   t->answer_data = &answer;
1537   t->on_answer_created = _check_validate_sdp;
1538   t->on_ice_candidate = NULL;
1539 
1540   fail_if (gst_element_set_state (t->webrtc1,
1541           GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
1542   fail_if (gst_element_set_state (t->webrtc2,
1543           GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
1544 
1545   g_signal_emit_by_name (t->webrtc1, "create-data-channel", "label", NULL,
1546       &channel);
1547   g_assert_nonnull (channel);
1548   g_object_get (channel, "label", &label, NULL);
1549   g_assert_cmpstr (label, ==, "label");
1550   g_signal_connect (channel, "on-error",
1551       G_CALLBACK (on_channel_error_not_reached), NULL);
1552 
1553   test_webrtc_create_offer (t, t->webrtc1);
1554 
1555   test_webrtc_wait_for_answer_error_eos (t);
1556   fail_unless_equals_int (STATE_ANSWER_CREATED, t->state);
1557   g_object_unref (channel);
1558   g_free (label);
1559   test_webrtc_free (t);
1560 }
1561 
1562 GST_END_TEST;
1563 
1564 static void
have_data_channel(struct test_webrtc * t,GstElement * element,GObject * our,gpointer user_data)1565 have_data_channel (struct test_webrtc *t, GstElement * element,
1566     GObject * our, gpointer user_data)
1567 {
1568   GObject *other = user_data;
1569   gchar *our_label, *other_label;
1570 
1571   g_signal_connect (our, "on-error", G_CALLBACK (on_channel_error_not_reached),
1572       NULL);
1573 
1574   g_object_get (our, "label", &our_label, NULL);
1575   g_object_get (other, "label", &other_label, NULL);
1576 
1577   g_assert_cmpstr (our_label, ==, other_label);
1578 
1579   g_free (our_label);
1580   g_free (other_label);
1581 
1582   test_webrtc_signal_state_unlocked (t, STATE_CUSTOM);
1583 }
1584 
GST_START_TEST(test_data_channel_remote_notify)1585 GST_START_TEST (test_data_channel_remote_notify)
1586 {
1587   struct test_webrtc *t = test_webrtc_new ();
1588   GObject *channel = NULL;
1589   struct validate_sdp offer = { on_sdp_has_datachannel, NULL };
1590   struct validate_sdp answer = { on_sdp_has_datachannel, NULL };
1591 
1592   t->on_negotiation_needed = NULL;
1593   t->offer_data = &offer;
1594   t->on_offer_created = _check_validate_sdp;
1595   t->answer_data = &answer;
1596   t->on_answer_created = _check_validate_sdp;
1597   t->on_ice_candidate = NULL;
1598   t->on_data_channel = have_data_channel;
1599 
1600   fail_if (gst_element_set_state (t->webrtc1,
1601           GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
1602   fail_if (gst_element_set_state (t->webrtc2,
1603           GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
1604 
1605   g_signal_emit_by_name (t->webrtc1, "create-data-channel", "label", NULL,
1606       &channel);
1607   g_assert_nonnull (channel);
1608   t->data_channel_data = channel;
1609   g_signal_connect (channel, "on-error",
1610       G_CALLBACK (on_channel_error_not_reached), NULL);
1611 
1612   fail_if (gst_element_set_state (t->webrtc1,
1613           GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE);
1614   fail_if (gst_element_set_state (t->webrtc2,
1615           GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE);
1616 
1617   test_webrtc_create_offer (t, t->webrtc1);
1618 
1619   test_webrtc_wait_for_state_mask (t, 1 << STATE_CUSTOM);
1620 
1621   g_object_unref (channel);
1622   test_webrtc_free (t);
1623 }
1624 
1625 GST_END_TEST;
1626 
1627 static const gchar *test_string = "GStreamer WebRTC is awesome!";
1628 
1629 static void
on_message_string(GObject * channel,const gchar * str,struct test_webrtc * t)1630 on_message_string (GObject * channel, const gchar * str, struct test_webrtc *t)
1631 {
1632   gchar *expected = g_object_steal_data (channel, "expected");
1633   g_assert_cmpstr (expected, ==, str);
1634   g_free (expected);
1635 
1636   test_webrtc_signal_state (t, STATE_CUSTOM);
1637 }
1638 
1639 static void
have_data_channel_transfer_string(struct test_webrtc * t,GstElement * element,GObject * our,gpointer user_data)1640 have_data_channel_transfer_string (struct test_webrtc *t, GstElement * element,
1641     GObject * our, gpointer user_data)
1642 {
1643   GObject *other = user_data;
1644   GstWebRTCDataChannelState state;
1645 
1646   g_object_get (our, "ready-state", &state, NULL);
1647   fail_unless_equals_int (GST_WEBRTC_DATA_CHANNEL_STATE_OPEN, state);
1648   g_object_get (other, "ready-state", &state, NULL);
1649   fail_unless_equals_int (GST_WEBRTC_DATA_CHANNEL_STATE_OPEN, state);
1650 
1651   g_object_set_data_full (our, "expected", g_strdup (test_string), g_free);
1652   g_signal_connect (our, "on-message-string", G_CALLBACK (on_message_string),
1653       t);
1654 
1655   g_signal_connect (other, "on-error",
1656       G_CALLBACK (on_channel_error_not_reached), NULL);
1657   g_signal_emit_by_name (other, "send-string", test_string);
1658 }
1659 
GST_START_TEST(test_data_channel_transfer_string)1660 GST_START_TEST (test_data_channel_transfer_string)
1661 {
1662   struct test_webrtc *t = test_webrtc_new ();
1663   GObject *channel = NULL;
1664   struct validate_sdp offer = { on_sdp_has_datachannel, NULL };
1665   struct validate_sdp answer = { on_sdp_has_datachannel, NULL };
1666 
1667   t->on_negotiation_needed = NULL;
1668   t->offer_data = &offer;
1669   t->on_offer_created = _check_validate_sdp;
1670   t->answer_data = &answer;
1671   t->on_answer_created = _check_validate_sdp;
1672   t->on_ice_candidate = NULL;
1673   t->on_data_channel = have_data_channel_transfer_string;
1674 
1675   fail_if (gst_element_set_state (t->webrtc1,
1676           GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
1677   fail_if (gst_element_set_state (t->webrtc2,
1678           GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
1679 
1680   g_signal_emit_by_name (t->webrtc1, "create-data-channel", "label", NULL,
1681       &channel);
1682   g_assert_nonnull (channel);
1683   t->data_channel_data = channel;
1684   g_signal_connect (channel, "on-error",
1685       G_CALLBACK (on_channel_error_not_reached), NULL);
1686 
1687   fail_if (gst_element_set_state (t->webrtc1,
1688           GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE);
1689   fail_if (gst_element_set_state (t->webrtc2,
1690           GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE);
1691 
1692   test_webrtc_create_offer (t, t->webrtc1);
1693 
1694   test_webrtc_wait_for_state_mask (t, 1 << STATE_CUSTOM);
1695 
1696   g_object_unref (channel);
1697   test_webrtc_free (t);
1698 }
1699 
1700 GST_END_TEST;
1701 
1702 #define g_assert_cmpbytes(b1, b2)                       \
1703     G_STMT_START {                                      \
1704       gsize l1, l2;                                     \
1705       const guint8 *d1 = g_bytes_get_data (b1, &l1);    \
1706       const guint8 *d2 = g_bytes_get_data (b2, &l2);    \
1707       g_assert_cmpmem (d1, l1, d2, l2);                 \
1708     } G_STMT_END;
1709 
1710 static void
on_message_data(GObject * channel,GBytes * data,struct test_webrtc * t)1711 on_message_data (GObject * channel, GBytes * data, struct test_webrtc *t)
1712 {
1713   GBytes *expected = g_object_steal_data (channel, "expected");
1714   g_assert_cmpbytes (data, expected);
1715   g_bytes_unref (expected);
1716 
1717   test_webrtc_signal_state (t, STATE_CUSTOM);
1718 }
1719 
1720 static void
have_data_channel_transfer_data(struct test_webrtc * t,GstElement * element,GObject * our,gpointer user_data)1721 have_data_channel_transfer_data (struct test_webrtc *t, GstElement * element,
1722     GObject * our, gpointer user_data)
1723 {
1724   GObject *other = user_data;
1725   GBytes *data = g_bytes_new_static (test_string, strlen (test_string));
1726   GstWebRTCDataChannelState state;
1727 
1728   g_object_get (our, "ready-state", &state, NULL);
1729   fail_unless_equals_int (GST_WEBRTC_DATA_CHANNEL_STATE_OPEN, state);
1730   g_object_get (other, "ready-state", &state, NULL);
1731   fail_unless_equals_int (GST_WEBRTC_DATA_CHANNEL_STATE_OPEN, state);
1732 
1733   g_object_set_data_full (our, "expected", g_bytes_ref (data),
1734       (GDestroyNotify) g_bytes_unref);
1735   g_signal_connect (our, "on-message-data", G_CALLBACK (on_message_data), t);
1736 
1737   g_signal_connect (other, "on-error",
1738       G_CALLBACK (on_channel_error_not_reached), NULL);
1739   g_signal_emit_by_name (other, "send-data", data);
1740 }
1741 
GST_START_TEST(test_data_channel_transfer_data)1742 GST_START_TEST (test_data_channel_transfer_data)
1743 {
1744   struct test_webrtc *t = test_webrtc_new ();
1745   GObject *channel = NULL;
1746   struct validate_sdp offer = { on_sdp_has_datachannel, NULL };
1747   struct validate_sdp answer = { on_sdp_has_datachannel, NULL };
1748 
1749   t->on_negotiation_needed = NULL;
1750   t->offer_data = &offer;
1751   t->on_offer_created = _check_validate_sdp;
1752   t->answer_data = &answer;
1753   t->on_answer_created = _check_validate_sdp;
1754   t->on_ice_candidate = NULL;
1755   t->on_data_channel = have_data_channel_transfer_data;
1756 
1757   fail_if (gst_element_set_state (t->webrtc1,
1758           GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
1759   fail_if (gst_element_set_state (t->webrtc2,
1760           GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
1761 
1762   g_signal_emit_by_name (t->webrtc1, "create-data-channel", "label", NULL,
1763       &channel);
1764   g_assert_nonnull (channel);
1765   t->data_channel_data = channel;
1766   g_signal_connect (channel, "on-error",
1767       G_CALLBACK (on_channel_error_not_reached), NULL);
1768 
1769   fail_if (gst_element_set_state (t->webrtc1,
1770           GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE);
1771   fail_if (gst_element_set_state (t->webrtc2,
1772           GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE);
1773 
1774   test_webrtc_create_offer (t, t->webrtc1);
1775 
1776   test_webrtc_wait_for_state_mask (t, 1 << STATE_CUSTOM);
1777 
1778   g_object_unref (channel);
1779   test_webrtc_free (t);
1780 }
1781 
1782 GST_END_TEST;
1783 
1784 static void
have_data_channel_create_data_channel(struct test_webrtc * t,GstElement * element,GObject * our,gpointer user_data)1785 have_data_channel_create_data_channel (struct test_webrtc *t,
1786     GstElement * element, GObject * our, gpointer user_data)
1787 {
1788   GObject *another;
1789 
1790   t->on_data_channel = have_data_channel_transfer_string;
1791 
1792   g_signal_emit_by_name (t->webrtc1, "create-data-channel", "label", NULL,
1793       &another);
1794   g_assert_nonnull (another);
1795   t->data_channel_data = another;
1796   g_signal_connect (another, "on-error",
1797       G_CALLBACK (on_channel_error_not_reached), NULL);
1798 }
1799 
GST_START_TEST(test_data_channel_create_after_negotiate)1800 GST_START_TEST (test_data_channel_create_after_negotiate)
1801 {
1802   struct test_webrtc *t = test_webrtc_new ();
1803   GObject *channel = NULL;
1804   struct validate_sdp offer = { on_sdp_has_datachannel, NULL };
1805   struct validate_sdp answer = { on_sdp_has_datachannel, NULL };
1806 
1807   t->on_negotiation_needed = NULL;
1808   t->offer_data = &offer;
1809   t->on_offer_created = _check_validate_sdp;
1810   t->answer_data = &answer;
1811   t->on_answer_created = _check_validate_sdp;
1812   t->on_ice_candidate = NULL;
1813   t->on_data_channel = have_data_channel_create_data_channel;
1814 
1815   fail_if (gst_element_set_state (t->webrtc1,
1816           GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
1817   fail_if (gst_element_set_state (t->webrtc2,
1818           GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
1819 
1820   g_signal_emit_by_name (t->webrtc1, "create-data-channel", "prev-label", NULL,
1821       &channel);
1822   g_assert_nonnull (channel);
1823   t->data_channel_data = channel;
1824   g_signal_connect (channel, "on-error",
1825       G_CALLBACK (on_channel_error_not_reached), NULL);
1826 
1827   fail_if (gst_element_set_state (t->webrtc1,
1828           GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE);
1829   fail_if (gst_element_set_state (t->webrtc2,
1830           GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE);
1831 
1832   test_webrtc_create_offer (t, t->webrtc1);
1833 
1834   test_webrtc_wait_for_state_mask (t, 1 << STATE_CUSTOM);
1835 
1836   g_object_unref (channel);
1837   test_webrtc_free (t);
1838 }
1839 
1840 GST_END_TEST;
1841 
1842 static void
on_buffered_amount_low_emitted(GObject * channel,struct test_webrtc * t)1843 on_buffered_amount_low_emitted (GObject * channel, struct test_webrtc *t)
1844 {
1845   test_webrtc_signal_state (t, STATE_CUSTOM);
1846 }
1847 
1848 static void
have_data_channel_check_low_threshold_emitted(struct test_webrtc * t,GstElement * element,GObject * our,gpointer user_data)1849 have_data_channel_check_low_threshold_emitted (struct test_webrtc *t,
1850     GstElement * element, GObject * our, gpointer user_data)
1851 {
1852   g_signal_connect (our, "on-buffered-amount-low",
1853       G_CALLBACK (on_buffered_amount_low_emitted), t);
1854   g_object_set (our, "buffered-amount-low-threshold", 1, NULL);
1855 
1856   g_signal_connect (our, "on-error", G_CALLBACK (on_channel_error_not_reached),
1857       NULL);
1858   g_signal_emit_by_name (our, "send-string", "DATA");
1859 }
1860 
GST_START_TEST(test_data_channel_low_threshold)1861 GST_START_TEST (test_data_channel_low_threshold)
1862 {
1863   struct test_webrtc *t = test_webrtc_new ();
1864   GObject *channel = NULL;
1865   struct validate_sdp offer = { on_sdp_has_datachannel, NULL };
1866   struct validate_sdp answer = { on_sdp_has_datachannel, NULL };
1867 
1868   t->on_negotiation_needed = NULL;
1869   t->offer_data = &offer;
1870   t->on_offer_created = _check_validate_sdp;
1871   t->answer_data = &answer;
1872   t->on_answer_created = _check_validate_sdp;
1873   t->on_ice_candidate = NULL;
1874   t->on_data_channel = have_data_channel_check_low_threshold_emitted;
1875 
1876   fail_if (gst_element_set_state (t->webrtc1,
1877           GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
1878   fail_if (gst_element_set_state (t->webrtc2,
1879           GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
1880 
1881   g_signal_emit_by_name (t->webrtc1, "create-data-channel", "label", NULL,
1882       &channel);
1883   g_assert_nonnull (channel);
1884   t->data_channel_data = channel;
1885   g_signal_connect (channel, "on-error",
1886       G_CALLBACK (on_channel_error_not_reached), NULL);
1887 
1888   fail_if (gst_element_set_state (t->webrtc1,
1889           GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE);
1890   fail_if (gst_element_set_state (t->webrtc2,
1891           GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE);
1892 
1893   test_webrtc_create_offer (t, t->webrtc1);
1894 
1895   test_webrtc_wait_for_state_mask (t, 1 << STATE_CUSTOM);
1896 
1897   g_object_unref (channel);
1898   test_webrtc_free (t);
1899 }
1900 
1901 GST_END_TEST;
1902 
1903 static void
on_channel_error(GObject * channel,GError * error,struct test_webrtc * t)1904 on_channel_error (GObject * channel, GError * error, struct test_webrtc *t)
1905 {
1906   g_assert_nonnull (error);
1907 
1908   test_webrtc_signal_state (t, STATE_CUSTOM);
1909 }
1910 
1911 static void
have_data_channel_transfer_large_data(struct test_webrtc * t,GstElement * element,GObject * our,gpointer user_data)1912 have_data_channel_transfer_large_data (struct test_webrtc *t,
1913     GstElement * element, GObject * our, gpointer user_data)
1914 {
1915   GObject *other = user_data;
1916   const gsize size = 1024 * 1024;
1917   guint8 *random_data = g_new (guint8, size);
1918   GBytes *data;
1919   gsize i;
1920 
1921   for (i = 0; i < size; i++)
1922     random_data[i] = (guint8) (i & 0xff);
1923 
1924   data = g_bytes_new_static (random_data, size);
1925 
1926   g_object_set_data_full (our, "expected", g_bytes_ref (data),
1927       (GDestroyNotify) g_bytes_unref);
1928   g_signal_connect (our, "on-message-data", G_CALLBACK (on_message_data), t);
1929 
1930   g_signal_connect (other, "on-error", G_CALLBACK (on_channel_error), t);
1931   g_signal_emit_by_name (other, "send-data", data);
1932 }
1933 
GST_START_TEST(test_data_channel_max_message_size)1934 GST_START_TEST (test_data_channel_max_message_size)
1935 {
1936   struct test_webrtc *t = test_webrtc_new ();
1937   GObject *channel = NULL;
1938   struct validate_sdp offer = { on_sdp_has_datachannel, NULL };
1939   struct validate_sdp answer = { on_sdp_has_datachannel, NULL };
1940 
1941   t->on_negotiation_needed = NULL;
1942   t->offer_data = &offer;
1943   t->on_offer_created = _check_validate_sdp;
1944   t->answer_data = &answer;
1945   t->on_answer_created = _check_validate_sdp;
1946   t->on_ice_candidate = NULL;
1947   t->on_data_channel = have_data_channel_transfer_large_data;
1948 
1949   fail_if (gst_element_set_state (t->webrtc1,
1950           GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
1951   fail_if (gst_element_set_state (t->webrtc2,
1952           GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
1953 
1954   g_signal_emit_by_name (t->webrtc1, "create-data-channel", "label", NULL,
1955       &channel);
1956   g_assert_nonnull (channel);
1957   t->data_channel_data = channel;
1958 
1959   fail_if (gst_element_set_state (t->webrtc1,
1960           GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE);
1961   fail_if (gst_element_set_state (t->webrtc2,
1962           GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE);
1963 
1964   test_webrtc_create_offer (t, t->webrtc1);
1965 
1966   test_webrtc_wait_for_state_mask (t, 1 << STATE_CUSTOM);
1967 
1968   g_object_unref (channel);
1969   test_webrtc_free (t);
1970 }
1971 
1972 GST_END_TEST;
1973 
1974 static void
_on_ready_state_notify(GObject * channel,GParamSpec * pspec,struct test_webrtc * t)1975 _on_ready_state_notify (GObject * channel, GParamSpec * pspec,
1976     struct test_webrtc *t)
1977 {
1978   gint *n_ready = t->data_channel_data;
1979   GstWebRTCDataChannelState ready_state;
1980 
1981   g_object_get (channel, "ready-state", &ready_state, NULL);
1982 
1983   if (ready_state == GST_WEBRTC_DATA_CHANNEL_STATE_OPEN) {
1984     if (++(*n_ready) >= 2)
1985       test_webrtc_signal_state (t, STATE_CUSTOM);
1986   }
1987 }
1988 
GST_START_TEST(test_data_channel_pre_negotiated)1989 GST_START_TEST (test_data_channel_pre_negotiated)
1990 {
1991   struct test_webrtc *t = test_webrtc_new ();
1992   GObject *channel1 = NULL, *channel2 = NULL;
1993   struct validate_sdp offer = { on_sdp_has_datachannel, NULL };
1994   struct validate_sdp answer = { on_sdp_has_datachannel, NULL };
1995   GstStructure *s;
1996   gint n_ready = 0;
1997 
1998   t->on_negotiation_needed = NULL;
1999   t->offer_data = &offer;
2000   t->on_offer_created = _check_validate_sdp;
2001   t->answer_data = &answer;
2002   t->on_answer_created = _check_validate_sdp;
2003   t->on_ice_candidate = NULL;
2004 
2005   fail_if (gst_element_set_state (t->webrtc1,
2006           GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
2007   fail_if (gst_element_set_state (t->webrtc2,
2008           GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
2009 
2010   s = gst_structure_new ("application/data-channel", "negotiated",
2011       G_TYPE_BOOLEAN, TRUE, "id", G_TYPE_INT, 1, NULL);
2012 
2013   g_signal_emit_by_name (t->webrtc1, "create-data-channel", "label", s,
2014       &channel1);
2015   g_assert_nonnull (channel1);
2016   g_signal_emit_by_name (t->webrtc2, "create-data-channel", "label", s,
2017       &channel2);
2018   g_assert_nonnull (channel2);
2019 
2020   fail_if (gst_element_set_state (t->webrtc1,
2021           GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE);
2022   fail_if (gst_element_set_state (t->webrtc2,
2023           GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE);
2024 
2025   test_webrtc_create_offer (t, t->webrtc1);
2026   test_webrtc_wait_for_answer_error_eos (t);
2027   fail_unless (t->state == STATE_ANSWER_CREATED);
2028 
2029   t->data_channel_data = &n_ready;
2030 
2031   g_signal_connect (channel1, "notify::ready-state",
2032       G_CALLBACK (_on_ready_state_notify), t);
2033   g_signal_connect (channel2, "notify::ready-state",
2034       G_CALLBACK (_on_ready_state_notify), t);
2035 
2036   test_webrtc_wait_for_state_mask (t, 1 << STATE_CUSTOM);
2037   test_webrtc_signal_state (t, STATE_NEW);
2038 
2039   have_data_channel_transfer_string (t, t->webrtc1, channel1, channel2);
2040 
2041   test_webrtc_wait_for_state_mask (t, 1 << STATE_CUSTOM);
2042 
2043   g_object_unref (channel1);
2044   g_object_unref (channel2);
2045   gst_structure_free (s);
2046   test_webrtc_free (t);
2047 }
2048 
2049 GST_END_TEST;
2050 
2051 typedef struct
2052 {
2053   guint num_media;
2054   guint num_active_media;
2055   const gchar **bundled;
2056   const gchar **bundled_only;
2057 } BundleCheckData;
2058 
2059 static void
_check_bundled_sdp_media(struct test_webrtc * t,GstElement * element,GstWebRTCSessionDescription * sd,gpointer user_data)2060 _check_bundled_sdp_media (struct test_webrtc *t, GstElement * element,
2061     GstWebRTCSessionDescription * sd, gpointer user_data)
2062 {
2063   gchar **bundled = NULL;
2064   BundleCheckData *data = (BundleCheckData *) user_data;
2065   guint i;
2066   guint active_media;
2067 
2068   fail_unless_equals_int (gst_sdp_message_medias_len (sd->sdp),
2069       data->num_media);
2070 
2071   fail_unless (_parse_bundle (sd->sdp, &bundled));
2072 
2073   if (!bundled) {
2074     fail_unless_equals_int (g_strv_length ((GStrv) data->bundled), 0);
2075   } else {
2076     fail_unless_equals_int (g_strv_length (bundled),
2077         g_strv_length ((GStrv) data->bundled));
2078   }
2079 
2080   for (i = 0; data->bundled[i]; i++) {
2081     fail_unless (g_strv_contains ((const gchar **) bundled, data->bundled[i]));
2082   }
2083 
2084   active_media = 0;
2085 
2086   for (i = 0; i < gst_sdp_message_medias_len (sd->sdp); i++) {
2087     const GstSDPMedia *media = gst_sdp_message_get_media (sd->sdp, i);
2088     const gchar *mid = gst_sdp_media_get_attribute_val (media, "mid");
2089 
2090     if (g_strv_contains ((const gchar **) data->bundled_only, mid))
2091       fail_unless (_media_has_attribute_key (media, "bundle-only"));
2092 
2093     if (gst_sdp_media_get_port (media) != 0)
2094       active_media += 1;
2095   }
2096 
2097   fail_unless_equals_int (active_media, data->num_active_media);
2098 
2099   if (bundled)
2100     g_strfreev (bundled);
2101 }
2102 
GST_START_TEST(test_bundle_audio_video_max_bundle_max_bundle)2103 GST_START_TEST (test_bundle_audio_video_max_bundle_max_bundle)
2104 {
2105   struct test_webrtc *t = create_audio_video_test ();
2106   const gchar *bundle[] = { "audio0", "video1", NULL };
2107   const gchar *offer_bundle_only[] = { "video1", NULL };
2108   const gchar *answer_bundle_only[] = { NULL };
2109   /* We set a max-bundle policy on the offering webrtcbin,
2110    * this means that all the offered medias should be part
2111    * of the group:BUNDLE attribute, and they should be marked
2112    * as bundle-only
2113    */
2114   BundleCheckData offer_data = {
2115     2,
2116     1,
2117     bundle,
2118     offer_bundle_only,
2119   };
2120   /* We also set a max-bundle policy on the answering webrtcbin,
2121    * this means that all the offered medias should be part
2122    * of the group:BUNDLE attribute, but need not be marked
2123    * as bundle-only.
2124    */
2125   BundleCheckData answer_data = {
2126     2,
2127     2,
2128     bundle,
2129     answer_bundle_only,
2130   };
2131   struct validate_sdp offer = { _check_bundled_sdp_media, &offer_data };
2132   struct validate_sdp answer = { _check_bundled_sdp_media, &answer_data };
2133 
2134   gst_util_set_object_arg (G_OBJECT (t->webrtc1), "bundle-policy",
2135       "max-bundle");
2136   gst_util_set_object_arg (G_OBJECT (t->webrtc2), "bundle-policy",
2137       "max-bundle");
2138 
2139   t->on_negotiation_needed = NULL;
2140   t->offer_data = &offer;
2141   t->on_offer_created = _check_validate_sdp;
2142   t->answer_data = &answer;
2143   t->on_answer_created = _check_validate_sdp;
2144   t->on_ice_candidate = NULL;
2145 
2146   fail_if (gst_element_set_state (t->webrtc1,
2147           GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
2148   fail_if (gst_element_set_state (t->webrtc2,
2149           GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
2150 
2151   test_webrtc_create_offer (t, t->webrtc1);
2152 
2153   test_webrtc_wait_for_answer_error_eos (t);
2154   fail_unless_equals_int (STATE_ANSWER_CREATED, t->state);
2155 
2156   test_webrtc_free (t);
2157 }
2158 
2159 GST_END_TEST;
2160 
GST_START_TEST(test_bundle_audio_video_max_compat_max_bundle)2161 GST_START_TEST (test_bundle_audio_video_max_compat_max_bundle)
2162 {
2163   struct test_webrtc *t = create_audio_video_test ();
2164   const gchar *bundle[] = { "audio0", "video1", NULL };
2165   const gchar *bundle_only[] = { NULL };
2166   /* We set a max-compat policy on the offering webrtcbin,
2167    * this means that all the offered medias should be part
2168    * of the group:BUNDLE attribute, and they should *not* be marked
2169    * as bundle-only
2170    */
2171   BundleCheckData offer_data = {
2172     2,
2173     2,
2174     bundle,
2175     bundle_only,
2176   };
2177   /* We set a max-bundle policy on the answering webrtcbin,
2178    * this means that all the offered medias should be part
2179    * of the group:BUNDLE attribute, but need not be marked
2180    * as bundle-only.
2181    */
2182   BundleCheckData answer_data = {
2183     2,
2184     2,
2185     bundle,
2186     bundle_only,
2187   };
2188   struct validate_sdp offer = { _check_bundled_sdp_media, &offer_data };
2189   struct validate_sdp answer = { _check_bundled_sdp_media, &answer_data };
2190 
2191   gst_util_set_object_arg (G_OBJECT (t->webrtc1), "bundle-policy",
2192       "max-compat");
2193   gst_util_set_object_arg (G_OBJECT (t->webrtc2), "bundle-policy",
2194       "max-bundle");
2195 
2196   t->on_negotiation_needed = NULL;
2197   t->offer_data = &offer;
2198   t->on_offer_created = _check_validate_sdp;
2199   t->answer_data = &answer;
2200   t->on_answer_created = _check_validate_sdp;
2201   t->on_ice_candidate = NULL;
2202 
2203   fail_if (gst_element_set_state (t->webrtc1,
2204           GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
2205   fail_if (gst_element_set_state (t->webrtc2,
2206           GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
2207 
2208   test_webrtc_create_offer (t, t->webrtc1);
2209 
2210   test_webrtc_wait_for_answer_error_eos (t);
2211   fail_unless_equals_int (STATE_ANSWER_CREATED, t->state);
2212 
2213   test_webrtc_free (t);
2214 }
2215 
2216 GST_END_TEST;
2217 
GST_START_TEST(test_bundle_audio_video_max_bundle_none)2218 GST_START_TEST (test_bundle_audio_video_max_bundle_none)
2219 {
2220   struct test_webrtc *t = create_audio_video_test ();
2221   const gchar *offer_bundle[] = { "audio0", "video1", NULL };
2222   const gchar *offer_bundle_only[] = { "video1", NULL };
2223   const gchar *answer_bundle[] = { NULL };
2224   const gchar *answer_bundle_only[] = { NULL };
2225   /* We set a max-bundle policy on the offering webrtcbin,
2226    * this means that all the offered medias should be part
2227    * of the group:BUNDLE attribute, and they should be marked
2228    * as bundle-only
2229    */
2230   BundleCheckData offer_data = {
2231     2,
2232     1,
2233     offer_bundle,
2234     offer_bundle_only,
2235   };
2236   /* We set a none policy on the answering webrtcbin,
2237    * this means that the answer should contain no bundled
2238    * medias, and as the bundle-policy of the offering webrtcbin
2239    * is set to max-bundle, only one media should be active.
2240    */
2241   BundleCheckData answer_data = {
2242     2,
2243     1,
2244     answer_bundle,
2245     answer_bundle_only,
2246   };
2247   struct validate_sdp offer = { _check_bundled_sdp_media, &offer_data };
2248   struct validate_sdp answer = { _check_bundled_sdp_media, &answer_data };
2249 
2250   gst_util_set_object_arg (G_OBJECT (t->webrtc1), "bundle-policy",
2251       "max-bundle");
2252   gst_util_set_object_arg (G_OBJECT (t->webrtc2), "bundle-policy", "none");
2253 
2254   t->on_negotiation_needed = NULL;
2255   t->offer_data = &offer;
2256   t->on_offer_created = _check_validate_sdp;
2257   t->answer_data = &answer;
2258   t->on_answer_created = _check_validate_sdp;
2259   t->on_ice_candidate = NULL;
2260 
2261   fail_if (gst_element_set_state (t->webrtc1,
2262           GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
2263   fail_if (gst_element_set_state (t->webrtc2,
2264           GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
2265 
2266   test_webrtc_create_offer (t, t->webrtc1);
2267 
2268   test_webrtc_wait_for_answer_error_eos (t);
2269   fail_unless_equals_int (STATE_ANSWER_CREATED, t->state);
2270 
2271   test_webrtc_free (t);
2272 }
2273 
2274 GST_END_TEST;
2275 
GST_START_TEST(test_bundle_audio_video_data)2276 GST_START_TEST (test_bundle_audio_video_data)
2277 {
2278   struct test_webrtc *t = create_audio_video_test ();
2279   const gchar *bundle[] = { "audio0", "video1", "application2", NULL };
2280   const gchar *offer_bundle_only[] = { "video1", "application2", NULL };
2281   const gchar *answer_bundle_only[] = { NULL };
2282   GObject *channel = NULL;
2283   /* We set a max-bundle policy on the offering webrtcbin,
2284    * this means that all the offered medias should be part
2285    * of the group:BUNDLE attribute, and they should be marked
2286    * as bundle-only
2287    */
2288   BundleCheckData offer_data = {
2289     3,
2290     1,
2291     bundle,
2292     offer_bundle_only,
2293   };
2294   /* We also set a max-bundle policy on the answering webrtcbin,
2295    * this means that all the offered medias should be part
2296    * of the group:BUNDLE attribute, but need not be marked
2297    * as bundle-only.
2298    */
2299   BundleCheckData answer_data = {
2300     3,
2301     3,
2302     bundle,
2303     answer_bundle_only,
2304   };
2305   struct validate_sdp offer = { _check_bundled_sdp_media, &offer_data };
2306   struct validate_sdp answer = { _check_bundled_sdp_media, &answer_data };
2307 
2308   gst_util_set_object_arg (G_OBJECT (t->webrtc1), "bundle-policy",
2309       "max-bundle");
2310   gst_util_set_object_arg (G_OBJECT (t->webrtc2), "bundle-policy",
2311       "max-bundle");
2312 
2313   t->on_negotiation_needed = NULL;
2314   t->offer_data = &offer;
2315   t->on_offer_created = _check_validate_sdp;
2316   t->answer_data = &answer;
2317   t->on_answer_created = _check_validate_sdp;
2318   t->on_ice_candidate = NULL;
2319 
2320   fail_if (gst_element_set_state (t->webrtc1,
2321           GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
2322   fail_if (gst_element_set_state (t->webrtc2,
2323           GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
2324 
2325   g_signal_emit_by_name (t->webrtc1, "create-data-channel", "label", NULL,
2326       &channel);
2327 
2328   test_webrtc_create_offer (t, t->webrtc1);
2329 
2330   test_webrtc_wait_for_answer_error_eos (t);
2331   fail_unless_equals_int (STATE_ANSWER_CREATED, t->state);
2332 
2333   g_object_unref (channel);
2334   test_webrtc_free (t);
2335 }
2336 
2337 GST_END_TEST;
2338 
2339 static Suite *
webrtcbin_suite(void)2340 webrtcbin_suite (void)
2341 {
2342   Suite *s = suite_create ("webrtcbin");
2343   TCase *tc = tcase_create ("general");
2344   GstPluginFeature *nicesrc, *nicesink, *dtlssrtpdec, *dtlssrtpenc;
2345   GstPluginFeature *sctpenc, *sctpdec;
2346   GstRegistry *registry;
2347 
2348   registry = gst_registry_get ();
2349   nicesrc = gst_registry_lookup_feature (registry, "nicesrc");
2350   nicesink = gst_registry_lookup_feature (registry, "nicesink");
2351   dtlssrtpenc = gst_registry_lookup_feature (registry, "dtlssrtpenc");
2352   dtlssrtpdec = gst_registry_lookup_feature (registry, "dtlssrtpdec");
2353   sctpenc = gst_registry_lookup_feature (registry, "sctpenc");
2354   sctpdec = gst_registry_lookup_feature (registry, "sctpdec");
2355 
2356   tcase_add_test (tc, test_no_nice_elements_request_pad);
2357   tcase_add_test (tc, test_no_nice_elements_state_change);
2358   if (nicesrc && nicesink && dtlssrtpenc && dtlssrtpdec) {
2359     tcase_add_test (tc, test_sdp_no_media);
2360     tcase_add_test (tc, test_session_stats);
2361     tcase_add_test (tc, test_audio);
2362     tcase_add_test (tc, test_audio_video);
2363     tcase_add_test (tc, test_media_direction);
2364     tcase_add_test (tc, test_media_setup);
2365     tcase_add_test (tc, test_add_transceiver);
2366     tcase_add_test (tc, test_get_transceivers);
2367     tcase_add_test (tc, test_add_recvonly_transceiver);
2368     tcase_add_test (tc, test_recvonly_sendonly);
2369     tcase_add_test (tc, test_payload_types);
2370     tcase_add_test (tc, test_bundle_audio_video_max_bundle_max_bundle);
2371     tcase_add_test (tc, test_bundle_audio_video_max_bundle_none);
2372     tcase_add_test (tc, test_bundle_audio_video_max_compat_max_bundle);
2373     if (sctpenc && sctpdec) {
2374       tcase_add_test (tc, test_data_channel_create);
2375       tcase_add_test (tc, test_data_channel_remote_notify);
2376       tcase_add_test (tc, test_data_channel_transfer_string);
2377       tcase_add_test (tc, test_data_channel_transfer_data);
2378       tcase_add_test (tc, test_data_channel_create_after_negotiate);
2379       tcase_add_test (tc, test_data_channel_low_threshold);
2380       tcase_add_test (tc, test_data_channel_max_message_size);
2381       tcase_add_test (tc, test_data_channel_pre_negotiated);
2382       tcase_add_test (tc, test_bundle_audio_video_data);
2383     } else {
2384       GST_WARNING ("Some required elements were not found. "
2385           "All datachannel are disabled. sctpenc %p, sctpdec %p", sctpenc,
2386           sctpdec);
2387     }
2388   } else {
2389     GST_WARNING ("Some required elements were not found. "
2390         "All media tests are disabled. nicesrc %p, nicesink %p, "
2391         "dtlssrtpenc %p, dtlssrtpdec %p", nicesrc, nicesink, dtlssrtpenc,
2392         dtlssrtpdec);
2393   }
2394 
2395   if (nicesrc)
2396     gst_object_unref (nicesrc);
2397   if (nicesink)
2398     gst_object_unref (nicesink);
2399   if (dtlssrtpdec)
2400     gst_object_unref (dtlssrtpdec);
2401   if (dtlssrtpenc)
2402     gst_object_unref (dtlssrtpenc);
2403   if (sctpenc)
2404     gst_object_unref (sctpenc);
2405   if (sctpdec)
2406     gst_object_unref (sctpdec);
2407 
2408   suite_add_tcase (s, tc);
2409 
2410   return s;
2411 }
2412 
2413 GST_CHECK_MAIN (webrtcbin);
2414