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