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