1 /*
2 	liblinphone_tester - liblinphone test suite
3 	Copyright (C) 2013  Belledonne Communications SARL
4 
5 	This program is free software: you can redistribute it and/or modify
6 	it under the terms of the GNU General Public License as published by
7 	the Free Software Foundation, either version 2 of the License, or
8 	(at your option) any later version.
9 
10 	This program is distributed in the hope that it will be useful,
11 	but WITHOUT ANY WARRANTY; without even the implied warranty of
12 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 	GNU General Public License for more details.
14 
15 	You should have received a copy of the GNU General Public License
16 	along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18 
19 #include <stdio.h>
20 #include "linphone/core.h"
21 #include "private.h"
22 #include "liblinphone_tester.h"
23 
24 /*avoid crash if x is NULL on libc versions <4.5.26 */
25 #define __strstr(x, y) ((x==NULL)?NULL:strstr(x,y))
26 
on_report_send_mandatory(const LinphoneCall * call,SalStreamType stream_type,const LinphoneContent * content)27 void on_report_send_mandatory(const LinphoneCall *call, SalStreamType stream_type, const LinphoneContent *content){
28 	char * body = (char *)linphone_content_get_buffer(content);
29 	char * remote_metrics_start = __strstr(body, "RemoteMetrics:");
30 	BC_ASSERT_TRUE(
31 			__strstr(body, "VQIntervalReport\r\n")			== body ||
32 			__strstr(body, "VQSessionReport\r\n")			== body ||
33 			__strstr(body, "VQSessionReport: CallTerm\r\n") == body
34 	);
35 	BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "CallID:"));
36 	BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "LocalID:"));
37 	BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "RemoteID:"));
38 	BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "OrigID:"));
39 	BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "LocalGroup:"));
40 	BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "RemoteGroup:"));
41 	BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "LocalAddr:"));
42 		BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "IP="));
43 		BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "PORT="));
44 		BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "SSRC="));
45 	BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "RemoteAddr:"));
46 		BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "IP="));
47 		BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "PORT="));
48 		BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "SSRC="));
49 	BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "LocalMetrics:"));
50 	BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "Timestamps:"));
51 		BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "START="));
52 		BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "STOP="));
53 
54 	BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "SessionDesc:"));
55 		BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "PT="));
56 		BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "PD="));
57 		BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "SR="));
58 
59 	/* We should have not reached RemoteMetrics section yet */
60 	BC_ASSERT_TRUE(!remote_metrics_start || body < remote_metrics_start);
61 
62 	BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "DialogID:"));
63 }
64 
on_report_send_verify_metrics(const reporting_content_metrics_t * metrics,char * body)65 char * on_report_send_verify_metrics(const reporting_content_metrics_t *metrics, char * body){
66 	if (metrics->rtcp_xr_count){
67 		BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "SessionDesc:"));
68 		BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "JitterBuffer:"));
69 		BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "PacketLoss:"));
70 	}
71 	if (metrics->rtcp_sr_count+metrics->rtcp_xr_count>0){
72 		BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "Delay:"));
73 	}
74 	if (metrics->rtcp_xr_count){
75 		BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "QualityEst:"));
76 	}
77 
78 	return body;
79 }
80 
on_report_send_with_rtcp_xr_local(const LinphoneCall * call,SalStreamType stream_type,const LinphoneContent * content)81 void on_report_send_with_rtcp_xr_local(const LinphoneCall *call, SalStreamType stream_type, const LinphoneContent *content){
82 	char * body = (char*)linphone_content_get_buffer(content);
83 	char * remote_metrics_start = __strstr(body, "RemoteMetrics:");
84 	reporting_session_report_t * report = call->log->reporting.reports[stream_type];
85 	on_report_send_mandatory(call,stream_type,content);
86 	BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "LocalMetrics:"));
87 	BC_ASSERT_TRUE(!remote_metrics_start || on_report_send_verify_metrics(&report->local_metrics,body) < remote_metrics_start);
88 }
on_report_send_with_rtcp_xr_remote(const LinphoneCall * call,SalStreamType stream_type,const LinphoneContent * content)89 void on_report_send_with_rtcp_xr_remote(const LinphoneCall *call, SalStreamType stream_type, const LinphoneContent *content){
90 	char * body = (char*)linphone_content_get_buffer(content);
91 	reporting_session_report_t * report = call->log->reporting.reports[stream_type];
92 
93 	on_report_send_mandatory(call,stream_type,content);
94 	if (report->remote_metrics.rtcp_sr_count+report->remote_metrics.rtcp_xr_count>0){
95 		BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "RemoteMetrics:"));
96 		BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "Timestamps:"));
97 		on_report_send_verify_metrics(&report->remote_metrics,body);
98 	}
99 }
on_report_send_with_rtcp_xr_both(const LinphoneCall * call,SalStreamType stream_type,const LinphoneContent * content)100 void on_report_send_with_rtcp_xr_both(const LinphoneCall *call, SalStreamType stream_type, const LinphoneContent *content){
101 	on_report_send_with_rtcp_xr_local(call,stream_type,content);
102 	on_report_send_with_rtcp_xr_remote(call,stream_type,content);
103 }
104 
create_call_for_quality_reporting_tests(LinphoneCoreManager * marie,LinphoneCoreManager * pauline,LinphoneCall ** call_marie,LinphoneCall ** call_pauline,LinphoneCallParams * params_marie,LinphoneCallParams * params_pauline)105 bool_t create_call_for_quality_reporting_tests(
106 		LinphoneCoreManager* marie,
107 		LinphoneCoreManager* pauline,
108 		LinphoneCall** call_marie,
109 		LinphoneCall** call_pauline,
110 		LinphoneCallParams * params_marie,
111 		LinphoneCallParams * params_pauline
112 		) {
113 
114 
115 	bool_t call_succeeded = call_with_params(marie,pauline,params_marie,params_pauline);
116 	BC_ASSERT_TRUE(call_succeeded);
117 	if (call_succeeded) {
118 		if (call_marie) {
119 			*call_marie = linphone_core_get_current_call(marie->lc);
120 			BC_ASSERT_PTR_NOT_NULL(*call_marie);
121 		}
122 		if (call_pauline) {
123 			*call_pauline = linphone_core_get_current_call(pauline->lc);
124 			BC_ASSERT_PTR_NOT_NULL(*call_pauline);
125 		}
126 	}
127 	return call_succeeded;
128 }
129 
quality_reporting_not_used_without_config(void)130 static void quality_reporting_not_used_without_config(void) {
131 	LinphoneCoreManager* marie = linphone_core_manager_new( "marie_quality_reporting_rc");
132 	LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc");
133 	LinphoneCall* call_marie = NULL;
134 	LinphoneCall* call_pauline = NULL;
135 
136 	if (create_call_for_quality_reporting_tests(marie, pauline, &call_marie, &call_pauline, NULL, NULL))  {
137 		// marie has stats collection enabled but pauline has not
138 		BC_ASSERT_TRUE(linphone_proxy_config_quality_reporting_enabled(call_marie->dest_proxy));
139 		BC_ASSERT_FALSE(linphone_proxy_config_quality_reporting_enabled(call_pauline->dest_proxy));
140 
141 		// this field should be already filled
142 		BC_ASSERT_PTR_NOT_NULL(call_marie->log->reporting.reports[0]->info.local_addr.ip);
143 
144 		// but not this one since it is updated at the end of call
145 		BC_ASSERT_PTR_NULL(call_marie->log->reporting.reports[0]->dialog_id);
146 		end_call(marie, pauline);
147 	}
148 
149 	linphone_core_manager_destroy(marie);
150 	linphone_core_manager_destroy(pauline);
151 }
152 
quality_reporting_not_sent_if_call_not_started(void)153 static void quality_reporting_not_sent_if_call_not_started(void) {
154 	LinphoneCoreManager* marie = linphone_core_manager_new( "marie_quality_reporting_rc");
155 	LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc");
156 	LinphoneCallLog* out_call_log;
157 	LinphoneCall* out_call;
158 
159 	linphone_core_set_max_calls(pauline->lc,0);
160 	out_call = linphone_core_invite(marie->lc,"pauline");
161 	BC_ASSERT_PTR_NOT_NULL(out_call);
162 	if(out_call == NULL) goto end;
163 	linphone_call_ref(out_call);
164 
165 	BC_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallError,1, 10000));
166 	BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallError,1, int, "%d");
167 
168 	if (bctbx_list_size(linphone_core_get_call_logs(marie->lc))>0) {
169 		out_call_log=(LinphoneCallLog*)(linphone_core_get_call_logs(marie->lc)->data);
170 		BC_ASSERT_PTR_NOT_NULL(out_call_log);
171 		BC_ASSERT_EQUAL(linphone_call_log_get_status(out_call_log),LinphoneCallAborted, int, "%d");
172 	}
173 	linphone_call_unref(out_call);
174 
175 	// wait a few time...
176 	wait_for_until(marie->lc,NULL,NULL,0,1000);
177 
178 	// since the callee was busy, there should be no publish to do
179 	BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishProgress,0, int, "%d");
180 	BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishOk,0, int, "%d");
181 end:
182 	linphone_core_manager_destroy(marie);
183 	linphone_core_manager_destroy(pauline);
184 }
185 
quality_reporting_not_sent_if_low_bandwidth(void)186 static void quality_reporting_not_sent_if_low_bandwidth(void) {
187 	LinphoneCoreManager* marie = linphone_core_manager_new( "marie_quality_reporting_rc");
188 	LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc");
189 	LinphoneCallParams* marie_params;
190 
191 	marie_params=linphone_core_create_call_params(marie->lc, NULL);
192 	linphone_call_params_enable_low_bandwidth(marie_params,TRUE);
193 
194 	if (create_call_for_quality_reporting_tests(marie, pauline, NULL, NULL, marie_params, NULL)) {
195 		end_call(marie, pauline);
196 
197 		BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishProgress,0, int, "%d");
198 		BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishOk,0, int, "%d");
199 	}
200 	linphone_call_params_unref(marie_params);
201 	linphone_core_manager_destroy(marie);
202 	linphone_core_manager_destroy(pauline);
203 }
204 
on_report_send_remove_fields(const LinphoneCall * call,SalStreamType stream_type,const LinphoneContent * content)205 void on_report_send_remove_fields(const LinphoneCall *call, SalStreamType stream_type, const LinphoneContent *content){
206 	char *body = (char*)linphone_content_get_buffer(content);
207 	/*corrupt start of the report*/
208 	strncpy(body, "corrupted report is corrupted", strlen("corrupted report is corrupted"));
209 }
210 
quality_reporting_invalid_report(void)211 static void quality_reporting_invalid_report(void) {
212 	LinphoneCoreManager* marie = linphone_core_manager_new( "marie_quality_reporting_rc");
213 	LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc");
214 	LinphoneCall* call_marie = NULL;
215 	LinphoneCall* call_pauline = NULL;
216 
217 	if (create_call_for_quality_reporting_tests(marie, pauline, &call_marie, &call_pauline, NULL, NULL)) {
218 		linphone_reporting_set_on_report_send(call_marie, on_report_send_remove_fields);
219 
220 		end_call(marie, pauline);
221 
222 		BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePublishProgress,1));
223 		BC_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePublishError,1,3000));
224 		BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishError,1, int, "%d");
225 		BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishOk,0, int, "%d");
226 	}
227 	linphone_core_manager_destroy(marie);
228 	linphone_core_manager_destroy(pauline);
229 }
230 
quality_reporting_at_call_termination(void)231 static void quality_reporting_at_call_termination(void) {
232 	LinphoneCoreManager* marie = linphone_core_manager_new( "marie_quality_reporting_rc");
233 	LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc_rtcp_xr");
234 	LinphoneCall* call_marie = NULL;
235 	LinphoneCall* call_pauline = NULL;
236 
237 	if (create_call_for_quality_reporting_tests(marie, pauline, &call_marie, &call_pauline, NULL, NULL)) {
238 		linphone_reporting_set_on_report_send(call_marie, on_report_send_with_rtcp_xr_remote);
239 
240 		linphone_core_terminate_all_calls(marie->lc);
241 
242 		// now dialog id should be filled
243 		BC_ASSERT_PTR_NOT_NULL(call_marie->log->reporting.reports[0]->dialog_id);
244 
245 		BC_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallReleased,1, 10000));
246 		BC_ASSERT_TRUE(wait_for_until(pauline->lc,NULL,&pauline->stat.number_of_LinphoneCallReleased,1, 10000));
247 
248 		BC_ASSERT_PTR_NULL(linphone_core_get_current_call(marie->lc));
249 		BC_ASSERT_PTR_NULL(linphone_core_get_current_call(pauline->lc));
250 
251 		// PUBLISH submission to the collector should be ok
252 		BC_ASSERT_TRUE(wait_for(marie->lc,NULL,&marie->stat.number_of_LinphonePublishProgress,1));
253 		BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishProgress,1, int, "%d");
254 		BC_ASSERT_TRUE(wait_for(marie->lc,NULL,&marie->stat.number_of_LinphonePublishOk,1));
255 	}
256 	linphone_core_manager_destroy(marie);
257 	linphone_core_manager_destroy(pauline);
258 }
259 
quality_reporting_interval_report(void)260 static void quality_reporting_interval_report(void) {
261 	LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc_rtcp_xr");
262 	LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc_rtcp_xr");
263 	LinphoneCall* call_marie = NULL;
264 	LinphoneCall* call_pauline = NULL;
265 
266 	if (create_call_for_quality_reporting_tests(marie, pauline, &call_marie, &call_pauline, NULL, NULL))  {
267 		linphone_reporting_set_on_report_send(call_marie, on_report_send_mandatory);
268 		linphone_proxy_config_set_quality_reporting_interval(call_marie->dest_proxy, 1);
269 
270 		BC_ASSERT_PTR_NOT_NULL(linphone_core_get_current_call(marie->lc));
271 		BC_ASSERT_PTR_NOT_NULL(linphone_core_get_current_call(pauline->lc));
272 
273 		// PUBLISH submission to the collector should be ok
274 		BC_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePublishProgress,1,60000));
275 		BC_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePublishOk,1,60000));
276 		end_call(marie, pauline);
277 	}
278 	linphone_core_manager_destroy(marie);
279 	linphone_core_manager_destroy(pauline);
280 }
281 
282 #ifdef VIDEO_ENABLED
quality_reporting_session_report_if_video_stopped(void)283 static void quality_reporting_session_report_if_video_stopped(void) {
284 	LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc_rtcp_xr");
285 	LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc");
286 	LinphoneCall* call_pauline = NULL;
287 	LinphoneCall* call_marie = NULL;
288 	LinphoneCallParams* pauline_params;
289 	LinphoneCallParams* marie_params;
290 
291 	linphone_core_enable_video_capture(marie->lc, TRUE);
292 	linphone_core_enable_video_display(marie->lc, FALSE);
293 	linphone_core_enable_video_capture(pauline->lc, TRUE);
294 	linphone_core_enable_video_display(pauline->lc, FALSE);
295 	marie_params=linphone_core_create_call_params(marie->lc, NULL);
296 	linphone_call_params_enable_video(marie_params,TRUE);
297 	pauline_params=linphone_core_create_call_params(pauline->lc, NULL);
298 	linphone_call_params_enable_video(pauline_params,TRUE);
299 
300 	if (create_call_for_quality_reporting_tests(marie, pauline, &call_marie, &call_pauline, marie_params, pauline_params)) {
301 		linphone_reporting_set_on_report_send(call_marie, on_report_send_with_rtcp_xr_local);
302 
303 		BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishProgress,0, int, "%d");
304 		BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishOk,0, int, "%d");
305 
306 		BC_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,NULL,0,3000));
307 		BC_ASSERT_TRUE(linphone_call_params_video_enabled(linphone_call_get_current_params(call_pauline)));
308 
309 		/*remove video*/
310 		linphone_call_params_unref(pauline_params);
311 		pauline_params=linphone_core_create_call_params(pauline->lc, call_pauline);
312 		linphone_call_params_enable_video(pauline_params,FALSE);
313 		linphone_call_update(call_pauline,pauline_params);
314 		linphone_call_params_unref(pauline_params);
315 
316 		BC_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePublishProgress,1,10000));
317 		BC_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePublishOk,1,10000));
318 
319 		BC_ASSERT_FALSE(linphone_call_params_video_enabled(linphone_call_get_current_params(call_pauline)));
320 
321 		end_call(marie, pauline);
322 
323 		BC_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePublishProgress,2,5000));
324 		BC_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePublishOk,2,5000));
325 	}
326 	linphone_call_params_unref(marie_params);
327 
328 
329 	linphone_core_manager_destroy(marie);
330 	linphone_core_manager_destroy(pauline);
331 }
332 #endif
333 
publish_report_with_route_state_changed(LinphoneCore * lc,LinphoneEvent * ev,LinphonePublishState state)334 void publish_report_with_route_state_changed(LinphoneCore *lc, LinphoneEvent *ev, LinphonePublishState state){
335 	if (state == LinphonePublishProgress) {
336 		BC_ASSERT_STRING_EQUAL(linphone_address_as_string(linphone_event_get_resource(ev)), linphone_proxy_config_get_quality_reporting_collector(linphone_core_get_default_proxy_config(lc)));
337 	}
338 }
339 
quality_reporting_sent_using_custom_route(void)340 static void quality_reporting_sent_using_custom_route(void) {
341 	LinphoneCoreManager* marie = linphone_core_manager_new( "marie_quality_reporting_rc");
342 	LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc");
343 	LinphoneCall* call_marie = NULL;
344 	LinphoneCall* call_pauline = NULL;
345 
346 	LinphoneCoreCbs *cbs = linphone_factory_create_core_cbs(linphone_factory_get());
347 	linphone_core_cbs_set_publish_state_changed(cbs, publish_report_with_route_state_changed);
348 	linphone_core_add_callbacks(marie->lc, cbs);
349 	linphone_core_cbs_unref(cbs);
350 
351 	//INVALID collector: sip.linphone.org do not collect reports, so it will throw a 404 Not Found error
352 	linphone_proxy_config_set_quality_reporting_collector(linphone_core_get_default_proxy_config(marie->lc), "sip:sip.linphone.org");
353 
354 	if (create_call_for_quality_reporting_tests(marie, pauline, &call_marie, &call_pauline, NULL, NULL)) {
355 		end_call(marie, pauline);
356 
357 		// PUBLISH submission to the collector should be ERROR since route is not valid
358 		BC_ASSERT_TRUE(wait_for(marie->lc,NULL,&marie->stat.number_of_LinphonePublishProgress,1));
359 		BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishProgress,1, int, "%d");
360 		BC_ASSERT_TRUE(wait_for_until(marie->lc,NULL,&marie->stat.number_of_LinphonePublishError,1,10000));
361 		BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishOk,0,int, "%d");
362 	}
363 	linphone_core_manager_destroy(marie);
364 	linphone_core_manager_destroy(pauline);
365 }
366 
367 #ifdef VIDEO_ENABLED
quality_reporting_interval_report_video_and_rtt(void)368 static void quality_reporting_interval_report_video_and_rtt(void) {
369 	LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc_rtcp_xr");
370 	LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc_rtcp_xr");
371 	LinphoneCall* call_marie = NULL;
372 	LinphoneCall* call_pauline = NULL;
373 	LinphoneCallParams* pauline_params;
374 	LinphoneCallParams* marie_params;
375  	LinphoneChatRoom *pauline_chat_room;
376 
377 	linphone_core_enable_video_capture(marie->lc, TRUE);
378 	linphone_core_enable_video_display(marie->lc, FALSE);
379 	linphone_core_enable_video_capture(pauline->lc, TRUE);
380 	linphone_core_enable_video_display(pauline->lc, FALSE);
381 	marie_params=linphone_core_create_call_params(marie->lc, NULL);
382 	linphone_call_params_enable_video(marie_params,TRUE);
383 	linphone_call_params_enable_realtime_text(marie_params,TRUE);
384 	pauline_params=linphone_core_create_call_params(pauline->lc, NULL);
385 	linphone_call_params_enable_video(pauline_params,TRUE);
386 	linphone_call_params_enable_realtime_text(pauline_params,TRUE);
387 
388 	if (create_call_for_quality_reporting_tests(marie, pauline, &call_marie, &call_pauline, marie_params, pauline_params))  {
389 		linphone_reporting_set_on_report_send(call_marie, on_report_send_mandatory);
390 		linphone_proxy_config_set_quality_reporting_interval(call_marie->dest_proxy, 3);
391 
392 		BC_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,NULL,0,3000));
393 		BC_ASSERT_TRUE(linphone_call_params_video_enabled(linphone_call_get_current_params(call_pauline)));
394 		BC_ASSERT_TRUE(linphone_call_params_realtime_text_enabled(linphone_call_get_current_params(call_pauline)));
395 
396 		BC_ASSERT_PTR_NOT_NULL(linphone_core_get_current_call(marie->lc));
397 		BC_ASSERT_PTR_NOT_NULL(linphone_core_get_current_call(pauline->lc));
398 
399 		// PUBLISH submission to the collector should be ok
400 		BC_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePublishProgress,1,5000));
401 		BC_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePublishOk,1,10000));
402 
403 		pauline_chat_room = linphone_call_get_chat_room(call_pauline);
404 		BC_ASSERT_PTR_NOT_NULL(pauline_chat_room);
405 		if (pauline_chat_room) {
406 			const char* message = "Lorem Ipsum Belledonnum Communicatum";
407 			size_t i;
408 			LinphoneChatMessage* rtt_message = linphone_chat_room_create_message(pauline_chat_room,NULL);
409 			LinphoneChatRoom *marie_chat_room = linphone_call_get_chat_room(call_marie);
410 
411 			for (i = 0; i < strlen(message); i++) {
412 				linphone_chat_message_put_char(rtt_message, message[i]);
413 				BC_ASSERT_TRUE(wait_for_until(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneIsComposingActiveReceived, (int)i+1, 1000));
414 				BC_ASSERT_EQUAL(linphone_chat_room_get_char(marie_chat_room), message[i], char, "%c");
415 			}
416 			linphone_chat_room_send_chat_message(pauline_chat_room, rtt_message);
417 		}
418 
419 		end_call(marie, pauline);
420 		/*wait that all publish complete*/
421 		BC_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePublishOk,marie->stat.number_of_LinphonePublishProgress,60000));
422 	}
423 
424 	linphone_call_params_unref(marie_params);
425 	linphone_call_params_unref(pauline_params);
426 
427 	linphone_core_manager_destroy(marie);
428 	linphone_core_manager_destroy(pauline);
429 }
430 #endif
431 
video_bandwidth_estimation(void)432 static void video_bandwidth_estimation(void){
433 	LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc");
434 	LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_rc");
435 	LinphoneVideoPolicy pol = {0};
436 	OrtpNetworkSimulatorParams simparams = { 0 };
437 
438 	linphone_core_set_video_device(marie->lc, "Mire: Mire (synthetic moving picture)");
439 	linphone_core_enable_video_capture(marie->lc, TRUE);
440 	linphone_core_enable_video_display(marie->lc, TRUE);
441 	linphone_core_enable_video_capture(pauline->lc, TRUE);
442 	linphone_core_enable_video_display(pauline->lc, TRUE);
443 
444 	pol.automatically_accept = TRUE;
445 	pol.automatically_initiate = TRUE;
446 	linphone_core_set_video_policy(marie->lc, &pol);
447 	linphone_core_set_video_policy(pauline->lc, &pol);
448 
449 	linphone_core_set_preferred_video_size_by_name(marie->lc, "vga");
450 	simparams.mode = OrtpNetworkSimulatorOutbound;
451 	simparams.enabled = TRUE;
452 	simparams.max_bandwidth = 300000;
453 	linphone_core_set_network_simulator_params(marie->lc, &simparams);
454 
455 	if (BC_ASSERT_TRUE(call(marie, pauline))){
456 		/*wait for the first TMMBR*/
457 		BC_ASSERT_TRUE(wait_for_until(marie->lc, pauline->lc, &marie->stat.number_of_tmmbr_received, 1, 50000));
458 		BC_ASSERT_GREATER((float)marie->stat.last_tmmbr_value_received, 270000.f, float, "%f");
459 		BC_ASSERT_LOWER((float)marie->stat.last_tmmbr_value_received, 330000.f, float, "%f");
460 
461 		end_call(marie, pauline);
462 	}
463 	linphone_core_manager_destroy(marie);
464 	linphone_core_manager_destroy(pauline);
465 }
466 
467 test_t quality_reporting_tests[] = {
468 	TEST_NO_TAG("Not used if no config", quality_reporting_not_used_without_config),
469 	TEST_NO_TAG("Call term session report not sent if call did not start", quality_reporting_not_sent_if_call_not_started),
470 	TEST_NO_TAG("Call term session report not sent if low bandwidth", quality_reporting_not_sent_if_low_bandwidth),
471 	TEST_NO_TAG("Call term session report invalid if missing mandatory fields", quality_reporting_invalid_report),
472 	TEST_NO_TAG("Call term session report sent if call ended normally", quality_reporting_at_call_termination),
473 	TEST_NO_TAG("Interval report if interval is configured", quality_reporting_interval_report),
474 	#ifdef VIDEO_ENABLED
475 	TEST_NO_TAG("Interval report if interval is configured with video and realtime text", quality_reporting_interval_report_video_and_rtt),
476 	TEST_NO_TAG("Session report sent if video stopped during call", quality_reporting_session_report_if_video_stopped),
477 	#endif
478 	TEST_NO_TAG("Sent using custom route", quality_reporting_sent_using_custom_route),
479 	TEST_NO_TAG("Video bandwidth estimation", video_bandwidth_estimation)
480 };
481 
482 test_suite_t quality_reporting_test_suite = {"QualityReporting", NULL, NULL, liblinphone_tester_before_each, liblinphone_tester_after_each,
483 											 sizeof(quality_reporting_tests) / sizeof(quality_reporting_tests[0]),
484 											 quality_reporting_tests};
485