quality_reporting_tester.c 23.4 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/*
	liblinphone_tester - liblinphone test suite
	Copyright (C) 2013  Belledonne Communications SARL

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 2 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

19
#include "linphone/core.h"
20
#include "liblinphone_tester.h"
Benjamin REIS's avatar
Benjamin REIS committed
21
#include "tester_utils.h"
22
#include "quality_reporting.h"
23

24
/* Avoid crash if x is NULL on libc versions <4.5.26 */
25 26
#define __strstr(x, y) ((x==NULL)?NULL:strstr(x,y))

27
static void on_report_send_mandatory (const LinphoneCall *call, SalStreamType stream_type, const LinphoneContent *content) {
28
	const char *body = linphone_content_get_string_buffer(content);
29 30 31 32
	char *remote_metrics_start = __strstr(body, "RemoteMetrics:");
	BC_ASSERT_TRUE((__strstr(body, "VQIntervalReport\r\n") == body)
		|| (__strstr(body, "VQSessionReport\r\n") == body)
		|| (__strstr(body, "VQSessionReport: CallTerm\r\n") == body)
33
	);
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
	BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "CallID:"));
	BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "LocalID:"));
	BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "RemoteID:"));
	BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "OrigID:"));
	BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "LocalGroup:"));
	BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "RemoteGroup:"));
	BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "LocalAddr:"));
	BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "IP="));
	BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "PORT="));
	BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "SSRC="));
	BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "RemoteAddr:"));
	BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "IP="));
	BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "PORT="));
	BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "SSRC="));
	BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "LocalMetrics:"));
	BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "Timestamps:"));
	BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "START="));
	BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "STOP="));

	BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "SessionDesc:"));
	BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "PT="));
	BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "PD="));
	BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "SR="));
57 58

	/* We should have not reached RemoteMetrics section yet */
59
	BC_ASSERT_TRUE(!remote_metrics_start || body < remote_metrics_start);
60

61
	BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "DialogID:"));
62 63
}

64
static const char *on_report_send_verify_metrics (const reporting_content_metrics_t *metrics, const char *body) {
65 66 67 68
	if (metrics->rtcp_xr_count) {
		BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "SessionDesc:"));
		BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "JitterBuffer:"));
		BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "PacketLoss:"));
69
	}
70
	if (metrics->rtcp_sr_count + metrics->rtcp_xr_count > 0)
71
		BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "Delay:"));
72
	if (metrics->rtcp_xr_count)
73
		BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "QualityEst:"));
74 75 76 77

	return body;
}

78
#if VIDEO_ENABLED
79
static void on_report_send_with_rtcp_xr_local (const LinphoneCall *call, SalStreamType stream_type, const LinphoneContent *content) {
80 81 82
	const char *body = NULL;
	const char *local_metrics_start = NULL;
	const char *remote_metrics_start = NULL;
83 84 85
	reporting_session_report_t *report = linphone_quality_reporting_get_reports(linphone_call_log_get_quality_reporting(linphone_call_get_log(call)))[stream_type];
	on_report_send_mandatory(call, stream_type, content);

86 87 88 89
	body = linphone_content_get_string_buffer(content);
	local_metrics_start = __strstr(body, "LocalMetrics:");
	remote_metrics_start = __strstr(body, "RemoteMetrics:");
	BC_ASSERT_PTR_NOT_NULL(local_metrics_start);
90
	BC_ASSERT_TRUE(!remote_metrics_start || on_report_send_verify_metrics(&report->local_metrics, body) < remote_metrics_start);
91
}
92
#endif
93

94 95 96
static void on_report_send_with_rtcp_xr_remote (const LinphoneCall *call, SalStreamType stream_type, const LinphoneContent *content) {
	char *body = (char *)linphone_content_get_buffer(content);
	reporting_session_report_t *report = linphone_quality_reporting_get_reports(linphone_call_log_get_quality_reporting(linphone_call_get_log(call)))[stream_type];
97

98 99 100 101 102
	on_report_send_mandatory(call, stream_type, content);
	if ((report->remote_metrics.rtcp_sr_count + report->remote_metrics.rtcp_xr_count) > 0) {
		BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "RemoteMetrics:"));
		BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "Timestamps:"));
		on_report_send_verify_metrics(&report->remote_metrics, body);
103 104
	}
}
105

Simon Morlat's avatar
Simon Morlat committed
106
/*
107 108 109 110
static void on_report_send_with_rtcp_xr_both (const LinphoneCall *call, SalStreamType stream_type, const LinphoneContent *content) {
	on_report_send_with_rtcp_xr_local(call, stream_type, content);
	on_report_send_with_rtcp_xr_remote(call, stream_type, content);
}
Simon Morlat's avatar
Simon Morlat committed
111
*/
112

113 114 115 116 117 118 119 120 121
static bool_t create_call_for_quality_reporting_tests (
	LinphoneCoreManager *marie,
	LinphoneCoreManager *pauline,
	LinphoneCall **call_marie,
	LinphoneCall **call_pauline,
	LinphoneCallParams *params_marie,
	LinphoneCallParams *params_pauline
) {
	bool_t call_succeeded = call_with_params(marie, pauline, params_marie, params_pauline);
122
	BC_ASSERT_TRUE(call_succeeded);
123 124 125
	if (call_succeeded) {
		if (call_marie) {
			*call_marie = linphone_core_get_current_call(marie->lc);
126
			BC_ASSERT_PTR_NOT_NULL(*call_marie);
127 128 129
		}
		if (call_pauline) {
			*call_pauline = linphone_core_get_current_call(pauline->lc);
130
			BC_ASSERT_PTR_NOT_NULL(*call_pauline);
131 132 133
		}
	}
	return call_succeeded;
134 135
}

136 137 138 139 140
static void quality_reporting_not_used_without_config (void) {
	LinphoneCoreManager *marie = linphone_core_manager_new("marie_quality_reporting_rc");
	LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_tcp_rc");
	LinphoneCall *call_marie = NULL;
	LinphoneCall *call_pauline = NULL;
141
	reporting_session_report_t **quality_reports = NULL;
Benjamin REIS's avatar
Benjamin REIS committed
142

143 144
	if (create_call_for_quality_reporting_tests(marie, pauline, &call_marie, &call_pauline, NULL, NULL)) {
		// Marie has stats collection enabled but Pauline has not
145 146
		BC_ASSERT_TRUE(linphone_proxy_config_quality_reporting_enabled(linphone_call_get_dest_proxy(call_marie)));
		BC_ASSERT_FALSE(linphone_proxy_config_quality_reporting_enabled(linphone_call_get_dest_proxy(call_pauline)));
147

148
		// This field should be already filled
149 150
		quality_reports = linphone_quality_reporting_get_reports(linphone_call_log_get_quality_reporting(linphone_call_get_log(call_marie)));
		BC_ASSERT_PTR_NOT_NULL(quality_reports[0]->info.local_addr.ip);
151

152
		// But not this one since it is updated at the end of call
153
		BC_ASSERT_PTR_NULL(quality_reports[0]->dialog_id);
Simon Morlat's avatar
Simon Morlat committed
154
		end_call(marie, pauline);
155
	}
156

157 158 159
	linphone_core_manager_destroy(marie);
	linphone_core_manager_destroy(pauline);
}
160

161 162 163 164 165
static void quality_reporting_not_sent_if_call_not_started (void) {
	LinphoneCoreManager *marie = linphone_core_manager_new("marie_quality_reporting_rc");
	LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_tcp_rc");
	LinphoneCallLog *out_call_log;
	LinphoneCall *out_call;
166

167 168
	linphone_core_set_max_calls(pauline->lc, 0);
	out_call = linphone_core_invite(marie->lc, "pauline");
169
	BC_ASSERT_PTR_NOT_NULL(out_call);
170 171
	if (!out_call)
		goto end;
172 173
	linphone_call_ref(out_call);

174 175
	BC_ASSERT_TRUE(wait_for_until(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallError, 1, 10000));
	BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallError, 1, int, "%d");
176

177 178
	if (bctbx_list_size(linphone_core_get_call_logs(marie->lc)) > 0) {
		out_call_log = (LinphoneCallLog *)(linphone_core_get_call_logs(marie->lc)->data);
179
		BC_ASSERT_PTR_NOT_NULL(out_call_log);
180
		BC_ASSERT_EQUAL(linphone_call_log_get_status(out_call_log), LinphoneCallAborted, int, "%d");
181 182 183
	}
	linphone_call_unref(out_call);

184 185 186 187 188 189
	// Wait a few time...
	wait_for_until(marie->lc, NULL, NULL, 0, 1000);

	// Since the callee was busy, there should be no publish to do
	BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishProgress, 0, int, "%d");
	BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishOk, 0, int, "%d");
190

191
end:
192 193 194
	linphone_core_manager_destroy(marie);
	linphone_core_manager_destroy(pauline);
}
195

196 197 198 199 200
static void quality_reporting_not_sent_if_low_bandwidth (void) {
	LinphoneCoreManager *marie = linphone_core_manager_new("marie_quality_reporting_rc");
	LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_tcp_rc");
	LinphoneCallParams *marie_params = linphone_core_create_call_params(marie->lc, NULL);
	linphone_call_params_enable_low_bandwidth(marie_params, TRUE);
201

202
	if (create_call_for_quality_reporting_tests(marie, pauline, NULL, NULL, marie_params, NULL)) {
Simon Morlat's avatar
Simon Morlat committed
203
		end_call(marie, pauline);
204

205 206
		BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishProgress, 0, int, "%d");
		BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishOk, 0, int, "%d");
207
	}
Simon Morlat's avatar
Simon Morlat committed
208
	linphone_call_params_unref(marie_params);
209 210 211 212
	linphone_core_manager_destroy(marie);
	linphone_core_manager_destroy(pauline);
}

213 214 215
static void on_report_send_remove_fields (const LinphoneCall *call, SalStreamType stream_type, const LinphoneContent *content) {
	char *body = bctbx_strdup(linphone_content_get_string_buffer(content));
	/* Corrupt start of the report */
216 217
	const char *corrupted_str = "corrupted report is corrupted";
	size_t corrupted_len = strlen(corrupted_str);
218
	strncpy(body, corrupted_str, corrupted_len + 1);
219 220
	linphone_content_set_string_buffer((LinphoneContent *)content, body);
	bctbx_free(body);
221 222
}

223 224 225 226 227
static void quality_reporting_invalid_report (void) {
	LinphoneCoreManager *marie = linphone_core_manager_new("marie_quality_reporting_rc");
	LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_tcp_rc");
	LinphoneCall *call_marie = NULL;
	LinphoneCall *call_pauline = NULL;
228

229 230
	if (create_call_for_quality_reporting_tests(marie, pauline, &call_marie, &call_pauline, NULL, NULL)) {
		linphone_reporting_set_on_report_send(call_marie, on_report_send_remove_fields);
231

Simon Morlat's avatar
Simon Morlat committed
232
		end_call(marie, pauline);
233

234 235 236 237
		BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphonePublishProgress, 1));
		BC_ASSERT_TRUE(wait_for_until(marie->lc, pauline->lc, &marie->stat.number_of_LinphonePublishError, 1, 3000));
		BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishError, 1, int, "%d");
		BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishOk, 0, int, "%d");
238
	}
239

240 241 242 243
	linphone_core_manager_destroy(marie);
	linphone_core_manager_destroy(pauline);
}

244 245 246 247 248
static void quality_reporting_at_call_termination (void) {
	LinphoneCoreManager *marie = linphone_core_manager_new("marie_quality_reporting_rc");
	LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_rc_rtcp_xr");
	LinphoneCall *call_marie = NULL;
	LinphoneCall *call_pauline = NULL;
249
	reporting_session_report_t **quality_reports = NULL;
250

251 252
	if (create_call_for_quality_reporting_tests(marie, pauline, &call_marie, &call_pauline, NULL, NULL)) {
		linphone_reporting_set_on_report_send(call_marie, on_report_send_with_rtcp_xr_remote);
253

254
		linphone_core_terminate_all_calls(marie->lc);
255

256
		// Now dialog id should be filled
257 258
		quality_reports = linphone_quality_reporting_get_reports(linphone_call_log_get_quality_reporting(linphone_call_get_log(call_marie)));
		BC_ASSERT_PTR_NOT_NULL(quality_reports[0]->dialog_id);
259

260 261
		BC_ASSERT_TRUE(wait_for_until(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallReleased, 1, 10000));
		BC_ASSERT_TRUE(wait_for_until(pauline->lc, NULL, &pauline->stat.number_of_LinphoneCallReleased, 1, 10000));
262

263 264
		BC_ASSERT_PTR_NULL(linphone_core_get_current_call(marie->lc));
		BC_ASSERT_PTR_NULL(linphone_core_get_current_call(pauline->lc));
265

266
		// PUBLISH submission to the collector should be ok
267 268 269
		BC_ASSERT_TRUE(wait_for(marie->lc, NULL, &marie->stat.number_of_LinphonePublishProgress, 1));
		BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishProgress, 1, int, "%d");
		BC_ASSERT_TRUE(wait_for(marie->lc, NULL, &marie->stat.number_of_LinphonePublishOk, 1));
270
	}
271

272 273 274 275
	linphone_core_manager_destroy(marie);
	linphone_core_manager_destroy(pauline);
}

276 277 278 279 280
static void quality_reporting_interval_report (void) {
	LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc_rtcp_xr");
	LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_rc_rtcp_xr");
	LinphoneCall *call_marie = NULL;
	LinphoneCall *call_pauline = NULL;
281

282
	if (create_call_for_quality_reporting_tests(marie, pauline, &call_marie, &call_pauline, NULL, NULL)) {
283
		linphone_reporting_set_on_report_send(call_marie, on_report_send_mandatory);
284
		linphone_proxy_config_set_quality_reporting_interval(linphone_call_get_dest_proxy(call_marie), 1);
285

286 287
		BC_ASSERT_PTR_NOT_NULL(linphone_core_get_current_call(marie->lc));
		BC_ASSERT_PTR_NOT_NULL(linphone_core_get_current_call(pauline->lc));
288

289
		// PUBLISH submission to the collector should be ok
290 291
		BC_ASSERT_TRUE(wait_for_until(marie->lc, pauline->lc, &marie->stat.number_of_LinphonePublishProgress, 1, 60000));
		BC_ASSERT_TRUE(wait_for_until(marie->lc, pauline->lc, &marie->stat.number_of_LinphonePublishOk, 1, 60000));
Simon Morlat's avatar
Simon Morlat committed
292
		end_call(marie, pauline);
293
	}
294

295 296 297 298
	linphone_core_manager_destroy(marie);
	linphone_core_manager_destroy(pauline);
}

299
#ifdef VIDEO_ENABLED
300 301 302 303 304 305 306
static void quality_reporting_session_report_if_video_stopped (void) {
	LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc_rtcp_xr");
	LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_tcp_rc");
	LinphoneCall *call_pauline = NULL;
	LinphoneCall *call_marie = NULL;
	LinphoneCallParams *pauline_params;
	LinphoneCallParams *marie_params;
307 308 309 310 311

	linphone_core_enable_video_capture(marie->lc, TRUE);
	linphone_core_enable_video_display(marie->lc, FALSE);
	linphone_core_enable_video_capture(pauline->lc, TRUE);
	linphone_core_enable_video_display(pauline->lc, FALSE);
312 313 314 315
	marie_params = linphone_core_create_call_params(marie->lc, NULL);
	linphone_call_params_enable_video(marie_params, TRUE);
	pauline_params = linphone_core_create_call_params(pauline->lc, NULL);
	linphone_call_params_enable_video(pauline_params, TRUE);
316

317 318
	if (create_call_for_quality_reporting_tests(marie, pauline, &call_marie, &call_pauline, marie_params, pauline_params)) {
		linphone_reporting_set_on_report_send(call_marie, on_report_send_with_rtcp_xr_local);
319

320 321
		BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishProgress, 0, int, "%d");
		BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishOk, 0, int, "%d");
322

323
		BC_ASSERT_TRUE(wait_for_until(marie->lc, pauline->lc, NULL, 0, 3000));
324
		BC_ASSERT_TRUE(linphone_call_params_video_enabled(linphone_call_get_current_params(call_pauline)));
325

326
		/* Remove video */
327
		linphone_call_params_unref(pauline_params);
328 329 330
		pauline_params = linphone_core_create_call_params(pauline->lc, call_pauline);
		linphone_call_params_enable_video(pauline_params, FALSE);
		linphone_call_update(call_pauline, pauline_params);
331
		linphone_call_params_unref(pauline_params);
332
		BC_ASSERT_TRUE(wait_for_until(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallStreamsRunning, 2, 10000));
333

334 335
		BC_ASSERT_TRUE(wait_for_until(marie->lc, pauline->lc, &marie->stat.number_of_LinphonePublishProgress, 1, 10000));
		BC_ASSERT_TRUE(wait_for_until(marie->lc, pauline->lc, &marie->stat.number_of_LinphonePublishOk, 1, 10000));
336

337
		BC_ASSERT_FALSE(linphone_call_params_video_enabled(linphone_call_get_current_params(call_pauline)));
338

Simon Morlat's avatar
Simon Morlat committed
339
		end_call(marie, pauline);
340

341 342
		BC_ASSERT_TRUE(wait_for_until(marie->lc, pauline->lc, &marie->stat.number_of_LinphonePublishProgress, 2, 5000));
		BC_ASSERT_TRUE(wait_for_until(marie->lc, pauline->lc, &marie->stat.number_of_LinphonePublishOk, 2, 5000));
343
	}
Simon Morlat's avatar
Simon Morlat committed
344
	linphone_call_params_unref(marie_params);
Benjamin REIS's avatar
Benjamin REIS committed
345

346 347 348
	linphone_core_manager_destroy(marie);
	linphone_core_manager_destroy(pauline);
}
349
#endif
350

351
static void publish_report_with_route_state_changed (LinphoneCore *lc, LinphoneEvent *ev, LinphonePublishState state) {
352
	if (state == LinphonePublishProgress) {
353 354 355
		char *uri = linphone_address_as_string(linphone_event_get_resource(ev));
		BC_ASSERT_STRING_EQUAL(uri, linphone_proxy_config_get_quality_reporting_collector(linphone_core_get_default_proxy_config(lc)));
		bctbx_free(uri);
356 357 358
	}
}

359
static void quality_reporting_sent_using_custom_route(void) {
360 361 362 363
	LinphoneCoreManager *marie = linphone_core_manager_new("marie_quality_reporting_rc");
	LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_tcp_rc");
	LinphoneCall *call_marie = NULL;
	LinphoneCall *call_pauline = NULL;
364

365 366 367 368
	LinphoneCoreCbs *cbs = linphone_factory_create_core_cbs(linphone_factory_get());
	linphone_core_cbs_set_publish_state_changed(cbs, publish_report_with_route_state_changed);
	linphone_core_add_callbacks(marie->lc, cbs);
	linphone_core_cbs_unref(cbs);
369

370
	// INVALID collector: sip.linphone.org do not collect reports, so it will throw a 404 Not Found error
371 372 373
	linphone_proxy_config_set_quality_reporting_collector(linphone_core_get_default_proxy_config(marie->lc), "sip:sip.linphone.org");

	if (create_call_for_quality_reporting_tests(marie, pauline, &call_marie, &call_pauline, NULL, NULL)) {
Simon Morlat's avatar
Simon Morlat committed
374
		end_call(marie, pauline);
375 376

		// PUBLISH submission to the collector should be ERROR since route is not valid
377 378 379 380
		BC_ASSERT_TRUE(wait_for(marie->lc, NULL, &marie->stat.number_of_LinphonePublishProgress, 1));
		BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishProgress, 1, int, "%d");
		BC_ASSERT_TRUE(wait_for_until(marie->lc, NULL, &marie->stat.number_of_LinphonePublishError, 1, 10000));
		BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishOk, 0, int, "%d");
381
	}
382

383 384 385 386
	linphone_core_manager_destroy(marie);
	linphone_core_manager_destroy(pauline);
}

387
#ifdef VIDEO_ENABLED
388 389 390 391 392 393 394
static void quality_reporting_interval_report_video_and_rtt (void) {
	LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc_rtcp_xr");
	LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_rc_rtcp_xr");
	LinphoneCall *call_marie = NULL;
	LinphoneCall *call_pauline = NULL;
	LinphoneCallParams *pauline_params;
	LinphoneCallParams *marie_params;
395
	LinphoneChatRoom *pauline_chat_room;
396

397 398 399 400
	linphone_core_enable_video_capture(marie->lc, TRUE);
	linphone_core_enable_video_display(marie->lc, FALSE);
	linphone_core_enable_video_capture(pauline->lc, TRUE);
	linphone_core_enable_video_display(pauline->lc, FALSE);
401 402 403 404 405 406 407 408
	marie_params = linphone_core_create_call_params(marie->lc, NULL);
	linphone_call_params_enable_video(marie_params, TRUE);
	linphone_call_params_enable_realtime_text(marie_params, TRUE);
	pauline_params = linphone_core_create_call_params(pauline->lc, NULL);
	linphone_call_params_enable_video(pauline_params, TRUE);
	linphone_call_params_enable_realtime_text(pauline_params, TRUE);

	if (create_call_for_quality_reporting_tests(marie, pauline, &call_marie, &call_pauline, marie_params, pauline_params)) {
409
		linphone_reporting_set_on_report_send(call_marie, on_report_send_mandatory);
410
		linphone_proxy_config_set_quality_reporting_interval(linphone_call_get_dest_proxy(call_marie), 3);
411

412
		BC_ASSERT_TRUE(wait_for_until(marie->lc, pauline->lc, NULL, 0, 3000));
413 414 415 416 417 418 419
		BC_ASSERT_TRUE(linphone_call_params_video_enabled(linphone_call_get_current_params(call_pauline)));
		BC_ASSERT_TRUE(linphone_call_params_realtime_text_enabled(linphone_call_get_current_params(call_pauline)));

		BC_ASSERT_PTR_NOT_NULL(linphone_core_get_current_call(marie->lc));
		BC_ASSERT_PTR_NOT_NULL(linphone_core_get_current_call(pauline->lc));

		// PUBLISH submission to the collector should be ok
420 421
		BC_ASSERT_TRUE(wait_for_until(marie->lc, pauline->lc, &marie->stat.number_of_LinphonePublishProgress, 1, 5000));
		BC_ASSERT_TRUE(wait_for_until(marie->lc, pauline->lc, &marie->stat.number_of_LinphonePublishOk, 1, 10000));
422

423 424
		pauline_chat_room = linphone_call_get_chat_room(call_pauline);
		BC_ASSERT_PTR_NOT_NULL(pauline_chat_room);
Sylvain Berfini's avatar
Sylvain Berfini committed
425
		LinphoneChatMessage *rtt_message = NULL;
426
		if (pauline_chat_room) {
427
			const char *message = "Lorem Ipsum Belledonnum Communicatum";
428
			size_t i;
429
			rtt_message = linphone_chat_room_create_message(pauline_chat_room, NULL);
430 431 432 433
			LinphoneChatRoom *marie_chat_room = linphone_call_get_chat_room(call_marie);

			for (i = 0; i < strlen(message); i++) {
				linphone_chat_message_put_char(rtt_message, message[i]);
434
				BC_ASSERT_TRUE(wait_for_until(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneIsComposingActiveReceived, (int)(i + 1), 1000));
435 436
				BC_ASSERT_EQUAL(linphone_chat_room_get_char(marie_chat_room), message[i], char, "%c");
			}
437
			linphone_chat_message_send(rtt_message);
438
		}
Benjamin REIS's avatar
Benjamin REIS committed
439

440
		end_call(marie, pauline);
441 442
		/* Wait that all publish complete */
		BC_ASSERT_TRUE(wait_for_until(marie->lc, pauline->lc, &marie->stat.number_of_LinphonePublishOk, marie->stat.number_of_LinphonePublishProgress, 60000));
443 444 445

		if (rtt_message)
			linphone_chat_message_unref(rtt_message);
446
	}
447

Simon Morlat's avatar
Simon Morlat committed
448 449
	linphone_call_params_unref(marie_params);
	linphone_call_params_unref(pauline_params);
450

451 452 453
	linphone_core_manager_destroy(marie);
	linphone_core_manager_destroy(pauline);
}
454
#endif
455

456
static void video_bandwidth_estimation (void) {
457 458
	LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc");
	LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_rc");
459
	LinphoneVideoPolicy pol = { 0 };
460
	OrtpNetworkSimulatorParams simparams = { 0 };
Benjamin REIS's avatar
Benjamin REIS committed
461

462 463 464 465 466
	linphone_core_set_video_device(marie->lc, "Mire: Mire (synthetic moving picture)");
	linphone_core_enable_video_capture(marie->lc, TRUE);
	linphone_core_enable_video_display(marie->lc, TRUE);
	linphone_core_enable_video_capture(pauline->lc, TRUE);
	linphone_core_enable_video_display(pauline->lc, TRUE);
Benjamin REIS's avatar
Benjamin REIS committed
467

468 469 470 471
	pol.automatically_accept = TRUE;
	pol.automatically_initiate = TRUE;
	linphone_core_set_video_policy(marie->lc, &pol);
	linphone_core_set_video_policy(pauline->lc, &pol);
Benjamin REIS's avatar
Benjamin REIS committed
472

473 474 475 476 477
	linphone_core_set_preferred_video_size_by_name(marie->lc, "vga");
	simparams.mode = OrtpNetworkSimulatorOutbound;
	simparams.enabled = TRUE;
	simparams.max_bandwidth = 300000;
	linphone_core_set_network_simulator_params(marie->lc, &simparams);
Benjamin REIS's avatar
Benjamin REIS committed
478

479 480
	if (BC_ASSERT_TRUE(call(marie, pauline))) {
		/* Wait for the first TMMBR */
481 482 483
		BC_ASSERT_TRUE(wait_for_until(marie->lc, pauline->lc, &marie->stat.number_of_tmmbr_received, 1, 50000));
		BC_ASSERT_GREATER((float)marie->stat.last_tmmbr_value_received, 270000.f, float, "%f");
		BC_ASSERT_LOWER((float)marie->stat.last_tmmbr_value_received, 330000.f, float, "%f");
Benjamin REIS's avatar
Benjamin REIS committed
484

485 486
		end_call(marie, pauline);
	}
487

488 489 490 491
	linphone_core_manager_destroy(marie);
	linphone_core_manager_destroy(pauline);
}

492
test_t quality_reporting_tests[] = {
493 494 495 496 497 498
	TEST_NO_TAG("Not used if no config", quality_reporting_not_used_without_config),
	TEST_NO_TAG("Call term session report not sent if call did not start", quality_reporting_not_sent_if_call_not_started),
	TEST_NO_TAG("Call term session report not sent if low bandwidth", quality_reporting_not_sent_if_low_bandwidth),
	TEST_NO_TAG("Call term session report invalid if missing mandatory fields", quality_reporting_invalid_report),
	TEST_NO_TAG("Call term session report sent if call ended normally", quality_reporting_at_call_termination),
	TEST_NO_TAG("Interval report if interval is configured", quality_reporting_interval_report),
499
	#ifdef VIDEO_ENABLED
500 501 502
		TEST_NO_TAG("Interval report if interval is configured with video and realtime text", quality_reporting_interval_report_video_and_rtt),
		TEST_NO_TAG("Session report sent if video stopped during call", quality_reporting_session_report_if_video_stopped),
	#endif // ifdef VIDEO_ENABLED
503 504
	TEST_NO_TAG("Sent using custom route", quality_reporting_sent_using_custom_route),
	TEST_NO_TAG("Video bandwidth estimation", video_bandwidth_estimation)
505 506
};

507 508 509 510 511
test_suite_t quality_reporting_test_suite = {
	"QualityReporting", NULL, NULL, liblinphone_tester_before_each, liblinphone_tester_after_each,
	sizeof(quality_reporting_tests) / sizeof(quality_reporting_tests[0]),
	quality_reporting_tests
};