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