/*
 * Copyright (c) 2010-2021 Belledonne Communications SARL.
 *
 * This file is part of Liblinphone.
 *
 * 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 3 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/>.
 */
#include <list>
#include <string>
#include <algorithm>

#include "c-wrapper/c-wrapper.h"
#include "c-wrapper/internal/c-tools.h"
#include "linphone/core.h"
#include "call/call.h"
#include "conference/session/media-session-p.h"
#include "liblinphone_tester.h"
#include "tester_utils.h"
#include "shared_tester_functions.h"
#include "capability_negotiation_tester.h"

void get_expected_encryption_from_call_params(LinphoneCall *offererCall, LinphoneCall *answererCall, LinphoneMediaEncryption* expectedEncryption, bool* potentialConfigurationChosen) {
	const LinphoneCallParams *offerer_params = linphone_call_get_params(offererCall);
	const LinphoneCallParams *answerer_params = linphone_call_get_params(answererCall);
	bool_t offerer_enc_mandatory = linphone_call_params_mandatory_media_encryption_enabled(offerer_params);
	bool_t answerer_enc_mandatory = linphone_call_params_mandatory_media_encryption_enabled(answerer_params);
	const LinphoneMediaEncryption offerer_encryption = linphone_call_params_get_media_encryption(offerer_params);
	const LinphoneMediaEncryption answerer_encryption = linphone_call_params_get_media_encryption(answerer_params);
	const bool_t offerer_capability_negotiations = linphone_call_params_capability_negotiations_enabled(offerer_params);
	const bool_t answerer_capability_negotiations = linphone_call_params_capability_negotiations_enabled(answerer_params);

	if (offerer_enc_mandatory) {
		*expectedEncryption = offerer_encryption;
		// reINVITE is not sent because the call should not offer potential configurations as it must enforce an encryption that will be stored in the actual configuration
		*potentialConfigurationChosen = false;
	} else if (answerer_enc_mandatory) {
		*expectedEncryption = answerer_encryption;

		// reINVITE is only sent if offerer and answerer support capability negotiations enabled and the expected encryption is listed in one potential configuration offered by the offerer
		*potentialConfigurationChosen = (offerer_capability_negotiations && answerer_capability_negotiations && linphone_call_params_is_media_encryption_supported(answerer_params, *expectedEncryption));
	} else if (answerer_capability_negotiations && offerer_capability_negotiations) {

		bctbx_list_t* offerer_supported_encs = linphone_call_params_get_supported_encryptions (offerer_params);
		bool_t enc_check_result = FALSE;
		// Find first encryption listed in the list of supported encryptions of the offerer that is supported by the answerer
		for(bctbx_list_t * enc = offerer_supported_encs;enc!=NULL;enc=enc->next){
			*expectedEncryption = static_cast<LinphoneMediaEncryption>(LINPHONE_PTR_TO_INT(bctbx_list_get_data(enc)));
			enc_check_result |= (linphone_call_params_is_media_encryption_supported (answerer_params, *expectedEncryption) || (linphone_call_params_get_media_encryption(answerer_params) == *expectedEncryption));
			if (enc_check_result) {
				break;
			}
		}

		if (!enc_check_result) {
			*expectedEncryption = linphone_call_params_get_media_encryption(offerer_params);
		}
		// reINVITE is always sent
		*potentialConfigurationChosen = linphone_call_params_is_media_encryption_supported (offerer_params, *expectedEncryption) && (linphone_call_params_get_media_encryption(offerer_params) != *expectedEncryption);

		if (offerer_supported_encs) {
			bctbx_list_free(offerer_supported_encs);
		}

		if (*potentialConfigurationChosen && (*expectedEncryption == LinphoneMediaEncryptionSRTP)) {
			const bool srtpSuiteMatch = search_matching_srtp_suite(get_manager(linphone_call_get_core(offererCall)), get_manager(linphone_call_get_core(answererCall)));
			if (!srtpSuiteMatch) {
				*potentialConfigurationChosen = false;
				*expectedEncryption = linphone_call_params_get_media_encryption(offerer_params);
			}
		}

	} else {
		*expectedEncryption = linphone_call_params_get_media_encryption(offerer_params);
		// reINVITE is not sent because either parts of the call doesn't support capability negotiations
		*potentialConfigurationChosen = false;
	}
}

std::list<LinphoneMediaEncryption> set_encryption_preference(const bool_t encryption_preferred) {
	std::list<LinphoneMediaEncryption> preferences;
	for (int idx = 0; idx <= LinphoneMediaEncryptionDTLS; idx++) {
		LinphoneMediaEncryption candidateEncryption = static_cast<LinphoneMediaEncryption>(idx);
		if (candidateEncryption != LinphoneMediaEncryptionNone) {
			preferences.push_back(candidateEncryption);
		}
	}

	if (encryption_preferred) {
		preferences.push_back(LinphoneMediaEncryptionNone); /**< No media encryption is used */
	} else {
		preferences.push_front(LinphoneMediaEncryptionNone); /**< No media encryption is used */
	}
	return preferences;
}

std::list<LinphoneMediaEncryption> set_encryption_preference_with_priority(const LinphoneMediaEncryption encryption, const bool append) {
	std::list<LinphoneMediaEncryption> preferences;
	for (int idx = 0; idx <= LinphoneMediaEncryptionDTLS; idx++) {
		LinphoneMediaEncryption candidateEncryption = static_cast<LinphoneMediaEncryption>(idx);
		if (candidateEncryption != encryption) {
			if (candidateEncryption == LinphoneMediaEncryptionNone) {
				// No encryption should be added last
				preferences.push_back(candidateEncryption);
			} else {
				preferences.push_front(candidateEncryption);
			}
		}
	}
	if (append) {
		preferences.push_back(encryption);
	} else {
		preferences.push_front(encryption);
	}
	return preferences;
}

bctbx_list_t * create_confg_encryption_preference_list_except(const LinphoneMediaEncryption encryption) {
	bctbx_list_t * encryption_list = NULL;
	for (int idx = 0; idx <= LinphoneMediaEncryptionDTLS; idx++) {
		if (static_cast<LinphoneMediaEncryption>(idx) != encryption) {
			encryption_list = bctbx_list_append(encryption_list, LINPHONE_INT_TO_PTR(idx));
		}
	}
	return encryption_list;
}

bctbx_list_t * create_confg_encryption_preference_list_from_param_preferences(const std::list<LinphoneMediaEncryption> & preferences) {
	bctbx_list_t * encryption_list = NULL;
	for (const auto & enc : preferences) {
		encryption_list = bctbx_list_append(encryption_list, LINPHONE_INT_TO_PTR(enc));
	}
	return encryption_list;
}

LinphoneCoreManager * create_core_mgr_with_capability_negotiation_setup(const char * rc_file, const encryption_params enc_params, const bool_t enable_capability_negotiations, const bool_t enable_ice, const bool_t enable_video) {
	LinphoneCoreManager* mgr = linphone_core_manager_new(rc_file);
	linphone_core_enable_capability_negociation(mgr->lc, enable_capability_negotiations);

	const LinphoneMediaEncryption encryption = enc_params.encryption;
	if (linphone_core_media_encryption_supported(mgr->lc,encryption)) {
		linphone_core_set_media_encryption_mandatory(mgr->lc,(enc_params.level == E_MANDATORY));

		if ((enc_params.level == E_MANDATORY) || (enc_params.level == E_OPTIONAL)) {
			linphone_core_set_media_encryption(mgr->lc,encryption);
			BC_ASSERT_EQUAL(linphone_core_get_media_encryption(mgr->lc), encryption, int, "%i");
		} else {
			linphone_core_set_media_encryption(mgr->lc,LinphoneMediaEncryptionNone);
			BC_ASSERT_EQUAL(linphone_core_get_media_encryption(mgr->lc), LinphoneMediaEncryptionNone, int, "%i");
		}

		if (!enc_params.preferences.empty()) {
			bctbx_list_t * cfg_enc = create_confg_encryption_preference_list_from_param_preferences(enc_params.preferences);
			linphone_core_set_supported_media_encryptions(mgr->lc,cfg_enc);
			bctbx_list_free(cfg_enc);
		}
	}

#ifdef VIDEO_ENABLED
	if (enable_video) {
		// important: VP8 has really poor performances with the mire camera, at least
		// on iOS - so when ever h264 is available, let's use it instead
		if (linphone_core_get_payload_type(mgr->lc,"h264", -1, -1)!=NULL) {
			disable_all_video_codecs_except_one(mgr->lc,"h264");
		}

		linphone_core_set_video_device(mgr->lc,liblinphone_tester_mire_id);

		LinphoneVideoActivationPolicy * pol = linphone_factory_create_video_activation_policy(linphone_factory_get());
		linphone_video_activation_policy_set_automatically_accept(pol, TRUE);
		linphone_core_set_video_activation_policy(mgr->lc, pol);
		linphone_video_activation_policy_unref(pol);

		linphone_core_set_video_device(mgr->lc, liblinphone_tester_mire_id);

		linphone_core_enable_video_capture(mgr->lc, TRUE);
		linphone_core_enable_video_display(mgr->lc, TRUE);
	}
#endif // VIDEO_ENABLED

	if (enable_ice){
		enable_stun_in_core(mgr, enable_ice);
		linphone_core_manager_wait_for_stun_resolution(mgr);
	}

	return mgr;
}

void encrypted_call_with_params_base(LinphoneCoreManager* caller, LinphoneCoreManager* callee, const LinphoneMediaEncryption encryption, const LinphoneCallParams *caller_params, LinphoneCallParams *callee_params, const bool_t enable_video) {

	reset_counters(&caller->stat);
	reset_counters(&callee->stat);
	linphone_core_reset_tone_manager_stats(caller->lc);
	linphone_core_reset_tone_manager_stats(callee->lc);

	bool_t caller_enc_mandatory = linphone_call_params_mandatory_media_encryption_enabled(caller_params);
	bool_t callee_enc_mandatory = linphone_call_params_mandatory_media_encryption_enabled(callee_params);
	const LinphoneMediaEncryption caller_encryption = linphone_call_params_get_media_encryption(caller_params);
	const LinphoneMediaEncryption callee_encryption = linphone_call_params_get_media_encryption(callee_params);
	if (caller_enc_mandatory && callee_enc_mandatory && (caller_encryption != callee_encryption)) {
		BC_ASSERT_FALSE(call_with_params(caller, callee, caller_params, callee_params));
	} else {

		const bool_t caller_capability_negotiations = linphone_call_params_capability_negotiations_enabled(caller_params);
		const bool_t callee_capability_negotiations = linphone_call_params_capability_negotiations_enabled(callee_params);

		char *path = bc_tester_file("certificates-marie");
		linphone_core_set_user_certificates_path(callee->lc, path);
		bc_free(path);
		path = bc_tester_file("certificates-pauline");
		linphone_core_set_user_certificates_path(caller->lc, path);
		bc_free(path);
		belle_sip_mkdir(linphone_core_get_user_certificates_path(callee->lc));
		belle_sip_mkdir(linphone_core_get_user_certificates_path(caller->lc));

		stats caller_stat = caller->stat;
		stats callee_stat = callee->stat;

		BC_ASSERT_TRUE(call_with_params(caller, callee, caller_params, callee_params));

		LinphoneCall *callerCall = linphone_core_get_current_call(caller->lc);
		BC_ASSERT_PTR_NOT_NULL(callerCall);
		LinphoneCall *calleeCall = linphone_core_get_current_call(callee->lc);
		BC_ASSERT_PTR_NOT_NULL(calleeCall);

		// Find expected call encryption as well as if a reinvite following capability negotiation is required
		LinphoneMediaEncryption expectedEncryption =  LinphoneMediaEncryptionNone;
		bool potentialConfigurationChosen = false;
		if (caller_enc_mandatory) {
			expectedEncryption = caller_encryption;
			// reINVITE is not sent because the call should not offer potential configurations as it must enforce an encryption that will be stored in the actual configuration
			potentialConfigurationChosen = false;
		} else if (callee_enc_mandatory) {
			expectedEncryption = callee_encryption;

			// reINVITE is only sent if caller and callee support capability negotiations enabled and the expected encryption is listed in one potential configuration offered by the caller
			potentialConfigurationChosen = (callee_capability_negotiations && caller_capability_negotiations && linphone_call_params_is_media_encryption_supported(caller_params,expectedEncryption) && (linphone_call_params_get_media_encryption(caller_params) != expectedEncryption));
		} else if (callee_capability_negotiations && caller_capability_negotiations && (linphone_call_params_is_media_encryption_supported (caller_params, encryption)) && (linphone_call_params_is_media_encryption_supported (callee_params, encryption))) {
			expectedEncryption = encryption;
			// reINVITE is always sent
			potentialConfigurationChosen = linphone_call_params_is_media_encryption_supported (caller_params, encryption) && (linphone_call_params_get_media_encryption(caller_params) != encryption);
			if (potentialConfigurationChosen && (expectedEncryption == LinphoneMediaEncryptionSRTP)) {
				const bool srtpSuiteMatch = search_matching_srtp_suite(caller, callee);
				if (!srtpSuiteMatch) {
					potentialConfigurationChosen = false;
					BC_ASSERT_EQUAL(expectedEncryption, linphone_call_params_get_media_encryption(caller_params), int, "%i");
				}
			}
		} else {
			expectedEncryption = linphone_call_params_get_media_encryption(caller_params);
			// reINVITE is not sent because either parts of the call doesn't support capability negotiations
			potentialConfigurationChosen = false;
		}

		LinphoneNatPolicy *caller_nat_policy = linphone_core_get_nat_policy(caller->lc);
		const bool_t caller_ice_enabled = linphone_nat_policy_ice_enabled(caller_nat_policy);
		LinphoneNatPolicy *callee_nat_policy = linphone_core_get_nat_policy(callee->lc);
		const bool_t callee_ice_enabled = linphone_nat_policy_ice_enabled(callee_nat_policy);

		const bool_t capabilityNegotiationReinviteEnabled = linphone_core_sdp_200_ack_enabled(caller->lc) ? linphone_call_params_is_capability_negotiation_reinvite_enabled(callee_params) : linphone_call_params_is_capability_negotiation_reinvite_enabled(caller_params);
		bool sendReInvite = (potentialConfigurationChosen && capabilityNegotiationReinviteEnabled) || (caller_ice_enabled && callee_ice_enabled);
		const int expectedStreamsRunning = 1 + ((sendReInvite) ? 1 : 0);

		/*wait for reINVITEs to complete*/
		BC_ASSERT_TRUE(wait_for(callee->lc,caller->lc,&callee->stat.number_of_LinphoneCallStreamsRunning,(callee_stat.number_of_LinphoneCallStreamsRunning+expectedStreamsRunning)));
		BC_ASSERT_TRUE(wait_for(callee->lc,caller->lc,&caller->stat.number_of_LinphoneCallStreamsRunning,(caller_stat.number_of_LinphoneCallStreamsRunning+expectedStreamsRunning)));

		if (callee_ice_enabled && caller_ice_enabled) {
			BC_ASSERT_TRUE(check_ice(caller, callee, LinphoneIceStateHostConnection));
			BC_ASSERT_TRUE(check_ice(callee, caller, LinphoneIceStateHostConnection));
		}

		int dummy=0;
		wait_for_until(caller->lc,callee->lc,&dummy,1,3000); /*just to sleep while iterating 1s*/

		liblinphone_tester_check_rtcp(caller, callee);

		BC_ASSERT_GREATER(linphone_core_manager_get_max_audio_down_bw(caller),70,int,"%i");
		LinphoneCallStats *calleeStats = linphone_call_get_audio_stats(linphone_core_get_current_call(callee->lc));
		BC_ASSERT_GREATER((int)linphone_call_stats_get_download_bandwidth(calleeStats),70,int,"%i");
		linphone_call_stats_unref(calleeStats);
		calleeStats = NULL;

		// Check that no reINVITE is sent while checking streams
		BC_ASSERT_EQUAL(callee->stat.number_of_LinphoneCallStreamsRunning, (callee_stat.number_of_LinphoneCallStreamsRunning+expectedStreamsRunning), int, "%i");
		BC_ASSERT_EQUAL(caller->stat.number_of_LinphoneCallStreamsRunning, (caller_stat.number_of_LinphoneCallStreamsRunning+expectedStreamsRunning), int, "%i");

		if (callerCall) {
			check_stream_encryption(callerCall);
			BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(callerCall)), expectedEncryption, int, "%i");
		}
		if (calleeCall) {
			check_stream_encryption(calleeCall);
			BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(calleeCall)), expectedEncryption, int, "%i");
		}

		if (!enable_video) {
			BC_ASSERT_FALSE(linphone_call_params_video_enabled(linphone_call_get_current_params(calleeCall)));
			BC_ASSERT_FALSE(linphone_call_params_video_enabled(linphone_call_get_current_params(callerCall)));

			BC_ASSERT_FALSE(linphone_call_log_video_enabled(linphone_call_get_call_log(calleeCall)));
			BC_ASSERT_FALSE(linphone_call_log_video_enabled(linphone_call_get_call_log(callerCall)));
		}
#ifdef VIDEO_ENABLED
		else {
			reset_counters(&caller->stat);
			reset_counters(&callee->stat);
			stats caller_stat = caller->stat;
			stats callee_stat = callee->stat;
			LinphoneCallParams * params = linphone_core_create_call_params(callee->lc, calleeCall);
			linphone_call_params_enable_video(params, TRUE);
			linphone_call_update(calleeCall, params);
			linphone_call_params_unref(params);
			BC_ASSERT_TRUE( wait_for(callee->lc,caller->lc,&callee->stat.number_of_LinphoneCallUpdating,(callee_stat.number_of_LinphoneCallUpdating+1)));
			BC_ASSERT_TRUE( wait_for(callee->lc,caller->lc,&caller->stat.number_of_LinphoneCallUpdatedByRemote,(caller_stat.number_of_LinphoneCallUpdatedByRemote+1)));

			BC_ASSERT_TRUE( wait_for(callee->lc,caller->lc,&callee->stat.number_of_LinphoneCallStreamsRunning,(callee_stat.number_of_LinphoneCallStreamsRunning+1)));
			BC_ASSERT_TRUE( wait_for(callee->lc,caller->lc,&caller->stat.number_of_LinphoneCallStreamsRunning,(caller_stat.number_of_LinphoneCallStreamsRunning+1)));

			// Update expected encryotion
			get_expected_encryption_from_call_params(calleeCall, callerCall, &expectedEncryption, &potentialConfigurationChosen);

			const bool_t capabilityNegotiationReinviteEnabledAfterUpdate = linphone_core_sdp_200_ack_enabled(callee->lc) ? linphone_call_params_is_capability_negotiation_reinvite_enabled(linphone_call_get_params(callerCall)) : linphone_call_params_is_capability_negotiation_reinvite_enabled(linphone_call_get_params(calleeCall));
			bool sendReInviteAfterUpdate = (potentialConfigurationChosen && capabilityNegotiationReinviteEnabledAfterUpdate) || (caller_ice_enabled && callee_ice_enabled);

			const int expectedStreamsRunningAfterUpdate = 1 + ((sendReInviteAfterUpdate) ? 1 : 0);

			BC_ASSERT_TRUE( wait_for(callee->lc,caller->lc,&callee->stat.number_of_LinphoneCallStreamsRunning,(callee_stat.number_of_LinphoneCallStreamsRunning+expectedStreamsRunningAfterUpdate)));
			BC_ASSERT_TRUE( wait_for(callee->lc,caller->lc,&caller->stat.number_of_LinphoneCallStreamsRunning,(caller_stat.number_of_LinphoneCallStreamsRunning+expectedStreamsRunningAfterUpdate)));
			liblinphone_tester_set_next_video_frame_decoded_cb(callerCall);
			liblinphone_tester_set_next_video_frame_decoded_cb(calleeCall);

			BC_ASSERT_TRUE( wait_for(callee->lc,caller->lc,&callee->stat.number_of_IframeDecoded,(callee_stat.number_of_IframeDecoded+1)));
			BC_ASSERT_TRUE( wait_for(callee->lc,caller->lc,&caller->stat.number_of_IframeDecoded,(caller_stat.number_of_IframeDecoded+1)));

			BC_ASSERT_TRUE(linphone_call_params_video_enabled(linphone_call_get_current_params(calleeCall)));
			BC_ASSERT_TRUE(linphone_call_params_video_enabled(linphone_call_get_current_params(callerCall)));

			BC_ASSERT_TRUE(linphone_call_log_video_enabled(linphone_call_get_call_log(calleeCall)));
			BC_ASSERT_TRUE(linphone_call_log_video_enabled(linphone_call_get_call_log(callerCall)));

			int dummy=0;
			wait_for_until(caller->lc,callee->lc,&dummy,1,3000); /*just to sleep while iterating 1s*/

			liblinphone_tester_check_rtcp(caller, callee);

			BC_ASSERT_GREATER(linphone_core_manager_get_max_audio_down_bw(caller),70,int,"%i");
			calleeStats = linphone_call_get_audio_stats(linphone_core_get_current_call(callee->lc));
			BC_ASSERT_GREATER((int)linphone_call_stats_get_download_bandwidth(calleeStats),70,int,"%i");
			linphone_call_stats_unref(calleeStats);
			calleeStats = NULL;
		}
#endif // VIDEO_ENABLED

		// Check that encryption has not changed after sending update
		if (callerCall) {
			check_stream_encryption(callerCall);
			BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(callerCall)), expectedEncryption, int, "%i");
		}
		if (calleeCall) {
			check_stream_encryption(calleeCall);
			BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(calleeCall)), expectedEncryption, int, "%i");
		}
	}

}

void encrypted_call_base(LinphoneCoreManager* caller, LinphoneCoreManager* callee, const LinphoneMediaEncryption encryption, const bool_t enable_caller_capability_negotiations, const bool_t enable_callee_capability_negotiations, const bool_t enable_video) {

	LinphoneCallParams *caller_params = linphone_core_create_call_params(caller->lc, NULL);
	linphone_call_params_enable_capability_negotiations (caller_params, enable_caller_capability_negotiations);
	LinphoneCallParams *callee_params = linphone_core_create_call_params(callee->lc, NULL);
	linphone_call_params_enable_capability_negotiations (callee_params, enable_callee_capability_negotiations);

	encrypted_call_with_params_base(caller, callee, encryption, caller_params, callee_params, enable_video);

	linphone_call_params_unref(caller_params);
	linphone_call_params_unref(callee_params);

}

void pause_resume_calls(LinphoneCoreManager* caller, LinphoneCoreManager* callee) {
	LinphoneCall * callerCall = linphone_core_get_current_call(caller->lc);
	BC_ASSERT_PTR_NOT_NULL(callerCall);
	LinphoneCall * calleeCall = linphone_core_get_current_call(callee->lc);
	BC_ASSERT_PTR_NOT_NULL(calleeCall);

	if (calleeCall && callerCall) {
		LinphoneMediaEncryption calleeEncryption = linphone_call_params_get_media_encryption(linphone_call_get_current_params(calleeCall));
		LinphoneMediaEncryption callerEncryption = linphone_call_params_get_media_encryption(linphone_call_get_current_params(callerCall));

		// Pause callee call
		BC_ASSERT_TRUE(pause_call_1(callee,calleeCall,caller,callerCall));
		wait_for_until(callee->lc, caller->lc, NULL, 5, 10000);

		// Resume callee call
		reset_counters(&caller->stat);
		reset_counters(&callee->stat);
		stats caller_stat = caller->stat;
		stats callee_stat = callee->stat;

		linphone_call_resume(calleeCall);
		BC_ASSERT_TRUE(wait_for(callee->lc,caller->lc,&callee->stat.number_of_LinphoneCallStreamsRunning,callee_stat.number_of_LinphoneCallStreamsRunning + 1));
		BC_ASSERT_TRUE(wait_for(callee->lc,caller->lc,&caller->stat.number_of_LinphoneCallStreamsRunning,caller_stat.number_of_LinphoneCallStreamsRunning + 1));

		// Verify that encryption didn't change
		BC_ASSERT_EQUAL(calleeEncryption, callerEncryption, int, "%i");
		BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(callerCall)), callerEncryption, int, "%i");
		BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(calleeCall)), calleeEncryption, int, "%i");

		wait_for_until(callee->lc, caller->lc, NULL, 5, 10000);

		liblinphone_tester_check_rtcp(caller, callee);

		BC_ASSERT_GREATER(linphone_core_manager_get_max_audio_down_bw(caller),70,int,"%i");
		LinphoneCallStats *calleeStats = linphone_call_get_audio_stats(linphone_core_get_current_call(callee->lc));
		BC_ASSERT_GREATER((int)linphone_call_stats_get_download_bandwidth(calleeStats),70,int,"%i");
		linphone_call_stats_unref(calleeStats);
		calleeStats = NULL;

		check_stream_encryption(callerCall);
		check_stream_encryption(calleeCall);

		// Pause caller call
		BC_ASSERT_TRUE(pause_call_1(caller,callerCall,callee,calleeCall));
		wait_for_until(callee->lc, caller->lc, NULL, 5, 10000);

		// Resume caller call
		reset_counters(&caller->stat);
		reset_counters(&callee->stat);
		caller_stat = caller->stat;
		callee_stat = callee->stat;

		linphone_call_resume(callerCall);
		BC_ASSERT_TRUE(wait_for(callee->lc,caller->lc,&callee->stat.number_of_LinphoneCallStreamsRunning,callee_stat.number_of_LinphoneCallStreamsRunning + 1));
		BC_ASSERT_TRUE(wait_for(callee->lc,caller->lc,&caller->stat.number_of_LinphoneCallStreamsRunning,caller_stat.number_of_LinphoneCallStreamsRunning + 1));

		// Verify that encryption didn't change
		BC_ASSERT_EQUAL(calleeEncryption, callerEncryption, int, "%i");
		BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(callerCall)), callerEncryption, int, "%i");
		BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(calleeCall)), calleeEncryption, int, "%i");

		wait_for_until(callee->lc, caller->lc, NULL, 5, 10000);

		liblinphone_tester_check_rtcp(caller, callee);

		BC_ASSERT_GREATER(linphone_core_manager_get_max_audio_down_bw(callee),70,int,"%i");
		LinphoneCallStats *callerStats = linphone_call_get_audio_stats(linphone_core_get_current_call(caller->lc));
		BC_ASSERT_GREATER((int)linphone_call_stats_get_download_bandwidth(callerStats),70,int,"%i");
		linphone_call_stats_unref(callerStats);
		callerStats = NULL;

		check_stream_encryption(callerCall);
		check_stream_encryption(calleeCall);

	}
}

void call_with_update_and_incompatible_encs_in_call_params_base (const bool_t enable_ice) {
	const LinphoneMediaEncryption encryption = LinphoneMediaEncryptionSRTP; // Desired encryption
	std::list<LinphoneMediaEncryption> marie_enc_list;
	if (encryption != LinphoneMediaEncryptionZRTP) {
		marie_enc_list.push_back(LinphoneMediaEncryptionZRTP);
	}
	if (encryption != LinphoneMediaEncryptionDTLS) {
		marie_enc_list.push_back(LinphoneMediaEncryptionDTLS);
	}
	if (encryption != LinphoneMediaEncryptionSRTP) {
		marie_enc_list.push_back(LinphoneMediaEncryptionSRTP);
	}
	if (encryption != LinphoneMediaEncryptionNone) {
		marie_enc_list.push_back(LinphoneMediaEncryptionNone);
	}

	encryption_params marie_enc_mgr_params;
	marie_enc_mgr_params.encryption = LinphoneMediaEncryptionNone;
	marie_enc_mgr_params.level = E_OPTIONAL;
	marie_enc_mgr_params.preferences = marie_enc_list;

	LinphoneCoreManager * marie = create_core_mgr_with_capability_negotiation_setup("marie_rc", marie_enc_mgr_params, TRUE, enable_ice, TRUE);

	std::list<LinphoneMediaEncryption> pauline_enc_list;
	if (encryption != LinphoneMediaEncryptionSRTP) {
		pauline_enc_list.push_back(LinphoneMediaEncryptionSRTP);
	}
	if (encryption != LinphoneMediaEncryptionZRTP) {
		pauline_enc_list.push_back(LinphoneMediaEncryptionZRTP);
	}
	if (encryption != LinphoneMediaEncryptionNone) {
		pauline_enc_list.push_back(LinphoneMediaEncryptionNone);
	}
	if (encryption != LinphoneMediaEncryptionDTLS) {
		pauline_enc_list.push_back(LinphoneMediaEncryptionDTLS);
	}

	encryption_params pauline_enc_mgr_params;
	pauline_enc_mgr_params.encryption = LinphoneMediaEncryptionNone;
	pauline_enc_mgr_params.level = E_OPTIONAL;
	pauline_enc_mgr_params.preferences = pauline_enc_list;

	LinphoneCoreManager * pauline = create_core_mgr_with_capability_negotiation_setup((transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"), pauline_enc_mgr_params, TRUE, enable_ice, TRUE);

	bctbx_list_t * marie_call_enc = NULL;
	marie_call_enc = bctbx_list_append(marie_call_enc, LINPHONE_INT_TO_PTR(encryption));

	LinphoneCallParams *marie_params = linphone_core_create_call_params(marie->lc, NULL);
	linphone_call_params_enable_capability_negotiations (marie_params, 1);
	linphone_call_params_set_supported_encryptions (marie_params, marie_call_enc);
	linphone_call_params_set_media_encryption (marie_params, LinphoneMediaEncryptionDTLS);
	bctbx_list_free(marie_call_enc);

	bctbx_list_t * pauline_call_enc = NULL;
	pauline_call_enc = bctbx_list_append(pauline_call_enc, LINPHONE_INT_TO_PTR(LinphoneMediaEncryptionZRTP));
	LinphoneCallParams *pauline_params = linphone_core_create_call_params(pauline->lc, NULL);
	linphone_call_params_enable_capability_negotiations (pauline_params, 1);
	linphone_call_params_set_media_encryption (pauline_params, encryption);
	linphone_call_params_set_supported_encryptions (pauline_params, pauline_call_enc);
	bctbx_list_free(pauline_call_enc);

	// Offerer media description:
	// - actual configuration: DTLS
	// - potential configuration: SRTP
	// Answerer media description:
	// - actual configuration: SRTP
	// - potential configuration: ZRTP
	// Result: potential configuration is chosen (encryption SRTP)
	BC_ASSERT_TRUE(call_with_params(marie, pauline, marie_params, pauline_params));

	LinphoneCall *marieCall = linphone_core_get_current_call(marie->lc);
	BC_ASSERT_PTR_NOT_NULL(marieCall);
	LinphoneCall *paulineCall = linphone_core_get_current_call(pauline->lc);
	BC_ASSERT_PTR_NOT_NULL(paulineCall);

	liblinphone_tester_check_rtcp(marie, pauline);

	BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneCallStreamsRunning, 2, int, "%d");
	BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallStreamsRunning, 2, int, "%d");

	// Check that encryption has not changed after sending update
	if (marieCall) {
		check_stream_encryption(marieCall);
		BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(marieCall)), encryption, int, "%i");
	}
	if (paulineCall) {
		check_stream_encryption(paulineCall);
		BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(paulineCall)), encryption, int, "%i");
	}

	stats marie_stat = marie->stat; 
	stats pauline_stat = pauline->stat; 
	LinphoneCallParams * params = linphone_core_create_call_params(pauline->lc, paulineCall);
	linphone_call_params_enable_video(params, TRUE);
	// Offerer media description:
	// - actual configuration: SRTP
	// - potential configuration: ZRTP
	// Answerer media description:
	// - actual configuration: DTLS
	// - potential configuration: SRTP
	// Result: actual configuration is chosen (encryption SRTP)
	linphone_call_update(paulineCall, params);
	linphone_call_params_unref(params);
	BC_ASSERT_TRUE( wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallUpdating,(pauline_stat.number_of_LinphoneCallUpdating+1)));
	BC_ASSERT_TRUE( wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallUpdatedByRemote,(marie_stat.number_of_LinphoneCallUpdatedByRemote+1)));

	LinphoneNatPolicy *marie_nat_policy = linphone_core_get_nat_policy(marie->lc);
	const bool_t marie_ice_enabled = linphone_nat_policy_ice_enabled(marie_nat_policy);
	LinphoneNatPolicy *pauline_nat_policy = linphone_core_get_nat_policy(pauline->lc);
	const bool_t pauline_ice_enabled = linphone_nat_policy_ice_enabled(pauline_nat_policy);
	const int expectedStreamsRunning = 1 + ((pauline_ice_enabled && marie_ice_enabled) ? 1 : 0);

	/*wait for reINVITEs to complete*/
	BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallStreamsRunning,(pauline_stat.number_of_LinphoneCallStreamsRunning+expectedStreamsRunning)));
	BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallStreamsRunning,(marie_stat.number_of_LinphoneCallStreamsRunning+expectedStreamsRunning)));

	if (pauline_ice_enabled && marie_ice_enabled) {
		BC_ASSERT_TRUE(check_ice(marie, pauline, LinphoneIceStateHostConnection));
		BC_ASSERT_TRUE(check_ice(pauline, marie, LinphoneIceStateHostConnection));
	}

	liblinphone_tester_set_next_video_frame_decoded_cb(marieCall);
	liblinphone_tester_set_next_video_frame_decoded_cb(paulineCall);

	BC_ASSERT_TRUE( wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_IframeDecoded,(pauline_stat.number_of_IframeDecoded+1)));
	BC_ASSERT_TRUE( wait_for(pauline->lc,marie->lc,&marie->stat.number_of_IframeDecoded,(marie_stat.number_of_IframeDecoded+1)));

	BC_ASSERT_TRUE(linphone_call_params_video_enabled(linphone_call_get_current_params(paulineCall)));
	BC_ASSERT_TRUE(linphone_call_params_video_enabled(linphone_call_get_current_params(marieCall)));

	BC_ASSERT_TRUE(linphone_call_log_video_enabled(linphone_call_get_call_log(paulineCall)));
	BC_ASSERT_TRUE(linphone_call_log_video_enabled(linphone_call_get_call_log(marieCall)));

	liblinphone_tester_check_rtcp(marie, pauline);

	// Check that encryption has not changed after sending update
	if (marieCall) {
		check_stream_encryption(marieCall);
		BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(marieCall)), encryption, int, "%i");
	}
	if (paulineCall) {
		check_stream_encryption(paulineCall);
		BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(paulineCall)), encryption, int, "%i");
	}

	BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneCallStreamsRunning, (pauline_stat.number_of_LinphoneCallStreamsRunning+expectedStreamsRunning), int, "%d");
	BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallStreamsRunning, (marie_stat.number_of_LinphoneCallStreamsRunning+expectedStreamsRunning), int, "%d");

	end_call(pauline, marie);

	linphone_call_params_unref(marie_params);
	linphone_call_params_unref(pauline_params);

	linphone_core_manager_destroy(marie);
	linphone_core_manager_destroy(pauline);
}

void call_with_encryption_test_base(const encryption_params marie_enc_params, const bool_t enable_marie_capability_negotiations, const bool_t enable_marie_ice, const encryption_params pauline_enc_params, const bool_t enable_pauline_capability_negotiations, const bool_t enable_pauline_ice, const bool_t enable_video) {

	LinphoneCoreManager * marie = create_core_mgr_with_capability_negotiation_setup("marie_rc", marie_enc_params, enable_marie_capability_negotiations, enable_marie_ice, enable_video);
	LinphoneCoreManager * pauline = create_core_mgr_with_capability_negotiation_setup((transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"), pauline_enc_params, enable_pauline_capability_negotiations, enable_pauline_ice, enable_video);

	LinphoneMediaEncryption expectedEncryption = LinphoneMediaEncryptionNone;
	if (marie_enc_params.level == E_MANDATORY) {
		expectedEncryption = marie_enc_params.encryption;
	} else if (pauline_enc_params.level == E_MANDATORY) {
		expectedEncryption = pauline_enc_params.encryption;
	} else if ((enable_marie_capability_negotiations == TRUE) && (enable_pauline_capability_negotiations == TRUE)) {
		for (const auto & enc : marie_enc_params.preferences) {
			if ((std::find(pauline_enc_params.preferences.cbegin(), pauline_enc_params.preferences.cend(), enc) != pauline_enc_params.preferences.cend()) || (pauline_enc_params.encryption == enc)) {
				expectedEncryption = enc;
				break;
			}
		}
	} else if (enable_marie_capability_negotiations == TRUE) {
		expectedEncryption = pauline_enc_params.encryption;
	} else {
		expectedEncryption = marie_enc_params.encryption;
	}

	encrypted_call_base(marie, pauline, expectedEncryption, enable_marie_capability_negotiations, enable_pauline_capability_negotiations, enable_video);
	if (linphone_core_get_current_call(marie->lc) && linphone_core_get_current_call(pauline->lc)) {
		end_call(marie, pauline);
	}

	linphone_core_manager_destroy(marie);
	linphone_core_manager_destroy(pauline);
}

static bool_t call_with_params_and_encryption_negotiation_failure_base(LinphoneCoreManager* caller, LinphoneCoreManager* callee, LinphoneCallParams * caller_params, LinphoneCallParams * callee_params, bool_t expSdpSuccess) {

	const bctbx_list_t *initLogs = linphone_core_get_call_logs(callee->lc);
	int initLogsSize = (int)bctbx_list_size(initLogs);
	stats initial_callee=callee->stat;
	stats initial_caller=callee->stat;

	LinphoneCallTestParams caller_test_params = {0}, callee_test_params =  {0};
	caller_test_params.base = (LinphoneCallParams*)caller_params;
	callee_test_params.base = (LinphoneCallParams*)callee_params;
	callee_test_params.sdp_simulate_error = !expSdpSuccess;

	bool_t ret = call_with_params2(caller, callee, &caller_test_params, &callee_test_params, FALSE);

	LinphoneCall * callee_call = linphone_core_get_current_call(callee->lc);
	if (!expSdpSuccess) {
		BC_ASSERT_PTR_NULL(callee_call);
		BC_ASSERT_EQUAL(caller->stat.number_of_LinphoneCallError,(initial_caller.number_of_LinphoneCallError + 1), int, "%d");
		BC_ASSERT_EQUAL(caller->stat.number_of_LinphoneCallReleased,(initial_caller.number_of_LinphoneCallReleased + 1), int, "%d");
		// actually callee does not receive error because it replies to the INVITE with a 488 Not Acceptable Here
		BC_ASSERT_EQUAL(callee->stat.number_of_LinphoneCallIncomingReceived, (initial_callee.number_of_LinphoneCallIncomingReceived), int, "%d");

		const bctbx_list_t *logs = linphone_core_get_call_logs(callee->lc);
		BC_ASSERT_EQUAL((int)bctbx_list_size(logs), (initLogsSize+1), int, "%i");
		// Forward logs pointer to the element desired
		for (int i = 0; i < initLogsSize; i++) logs=logs->next;
		if (logs){
			const LinphoneErrorInfo *ei;
			LinphoneCallLog *cl = (LinphoneCallLog*)logs->data;
			BC_ASSERT_TRUE(linphone_call_log_get_start_date(cl) != 0);
			ei = linphone_call_log_get_error_info(cl);
			BC_ASSERT_PTR_NOT_NULL(ei);
			if (ei){
				BC_ASSERT_EQUAL(linphone_error_info_get_reason(ei), LinphoneReasonNotAcceptable, int, "%d");
			}
		}

		BC_ASSERT_EQUAL(linphone_core_get_calls_nb(caller->lc), 0, int, "%d");
		BC_ASSERT_EQUAL(linphone_core_get_calls_nb(callee->lc), 0, int, "%d");

		return FALSE;

	}

	return ret;
}

static bool_t call_with_encryption_negotiation_failure_base(LinphoneCoreManager* caller, LinphoneCoreManager* callee, bool_t expSdpSuccess) {
	return call_with_params_and_encryption_negotiation_failure_base(caller, callee, NULL, NULL, expSdpSuccess);
}

static void call_from_enc_to_different_enc_base(const LinphoneMediaEncryption mandatory_encryption, const LinphoneMediaEncryption non_mandatory_encryption, const bool_t enable_mandatory_enc_mgr_capability_negotiations, const bool_t enable_non_mandatory_enc_mgr_capability_negotiations, bool_t mandatory_to_non_mandatory) {
	LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
	linphone_core_enable_capability_negociation(marie->lc, enable_non_mandatory_enc_mgr_capability_negotiations);
	linphone_core_set_media_encryption_mandatory(marie->lc,FALSE);
	linphone_core_set_media_encryption(marie->lc,non_mandatory_encryption);
	bctbx_list_t * cfg_enc = create_confg_encryption_preference_list_except(mandatory_encryption);
	linphone_core_set_supported_media_encryptions(marie->lc,cfg_enc);
	BC_ASSERT_FALSE(linphone_core_is_media_encryption_supported(marie->lc, mandatory_encryption));
	bctbx_list_free(cfg_enc);

	LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
	linphone_core_enable_capability_negociation(pauline->lc, enable_mandatory_enc_mgr_capability_negotiations);
	if (linphone_core_media_encryption_supported(pauline->lc,mandatory_encryption)) {
		linphone_core_set_media_encryption_mandatory(pauline->lc,TRUE);
		linphone_core_set_media_encryption(pauline->lc,mandatory_encryption);
	}
	BC_ASSERT_TRUE(linphone_core_is_media_encryption_supported(pauline->lc, mandatory_encryption));

	if (mandatory_to_non_mandatory) {
		ms_message("Core with mandatory encryption calls core with non mandatory encryption");
		BC_ASSERT_FALSE(call_with_encryption_negotiation_failure_base(pauline, marie, FALSE));
	} else {
		ms_message("Core with non mandatory encryption calls core with mandatory encryption");
		BC_ASSERT_FALSE(call_with_encryption_negotiation_failure_base(marie, pauline, FALSE));
	}

	linphone_core_manager_destroy(marie);
	linphone_core_manager_destroy(pauline);
}

void call_from_enc_to_no_enc_base(const LinphoneMediaEncryption encryption, const bool_t enable_mandatory_enc_mgr_capability_negotiations, const bool_t enable_non_mandatory_enc_mgr_capability_negotiations, bool_t mandatory_to_non_mandatory) {
	call_from_enc_to_different_enc_base(encryption, LinphoneMediaEncryptionNone, enable_mandatory_enc_mgr_capability_negotiations, enable_non_mandatory_enc_mgr_capability_negotiations, mandatory_to_non_mandatory);
}

void call_from_enc_to_dtls_enc_base(const LinphoneMediaEncryption encryption, const bool_t enable_mandatory_enc_mgr_capability_negotiations, const bool_t enable_non_mandatory_enc_mgr_capability_negotiations, bool_t mandatory_to_non_mandatory) {
	call_from_enc_to_different_enc_base(encryption, LinphoneMediaEncryptionDTLS, enable_mandatory_enc_mgr_capability_negotiations, enable_non_mandatory_enc_mgr_capability_negotiations, mandatory_to_non_mandatory);
}

static void call_with_capability_negotiation_failure(void) {
	LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
	linphone_core_enable_capability_negociation(marie->lc, 1);

	LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
	linphone_core_enable_capability_negociation(pauline->lc, 1);

	const LinphoneMediaEncryption paulineOptionalEncryption = LinphoneMediaEncryptionSRTP;
	BC_ASSERT_TRUE(linphone_core_media_encryption_supported(pauline->lc,paulineOptionalEncryption));
	if (linphone_core_media_encryption_supported(pauline->lc,paulineOptionalEncryption)) {
		bctbx_list_t * encryption_list = NULL;
		encryption_list = bctbx_list_append(encryption_list, LINPHONE_INT_TO_PTR(paulineOptionalEncryption));
		linphone_core_set_media_encryption_mandatory(pauline->lc,0);
		linphone_core_set_media_encryption(pauline->lc,LinphoneMediaEncryptionNone);
		linphone_core_set_supported_media_encryptions(pauline->lc,encryption_list);
		BC_ASSERT_TRUE(linphone_core_is_media_encryption_supported(pauline->lc, paulineOptionalEncryption));
		if (encryption_list) {
			bctbx_list_free(encryption_list);
		}
	}

	const LinphoneMediaEncryption marieOptionalEncryption = LinphoneMediaEncryptionDTLS;
	BC_ASSERT_TRUE(linphone_core_media_encryption_supported(marie->lc,marieOptionalEncryption));
	if (linphone_core_media_encryption_supported(marie->lc,marieOptionalEncryption)) {
		bctbx_list_t * encryption_list = NULL;
		encryption_list = bctbx_list_append(encryption_list, LINPHONE_INT_TO_PTR(marieOptionalEncryption));
		linphone_core_set_media_encryption_mandatory(marie->lc,0);
		linphone_core_set_media_encryption(marie->lc,LinphoneMediaEncryptionNone);
		linphone_core_set_supported_media_encryptions(marie->lc,encryption_list);
		BC_ASSERT_TRUE(linphone_core_is_media_encryption_supported(marie->lc, marieOptionalEncryption));
		if (encryption_list) {
			bctbx_list_free(encryption_list);
		}
	}

	BC_ASSERT_TRUE(linphone_core_is_media_encryption_supported(marie->lc, marieOptionalEncryption));
	BC_ASSERT_FALSE(linphone_core_is_media_encryption_supported(pauline->lc, marieOptionalEncryption));

	BC_ASSERT_TRUE(linphone_core_is_media_encryption_supported(pauline->lc, paulineOptionalEncryption));
	BC_ASSERT_FALSE(linphone_core_is_media_encryption_supported(pauline->lc, marieOptionalEncryption));

	encrypted_call_base(marie, pauline, marieOptionalEncryption, TRUE, TRUE, FALSE);
	if (linphone_core_get_current_call(marie->lc) && linphone_core_get_current_call(pauline->lc)) {
		end_call(marie, pauline);
	}

	linphone_core_manager_destroy(marie);
	linphone_core_manager_destroy(pauline);
}

static void call_with_capability_negotiation_failure_multiple_potential_configurations (void) {
	LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
	linphone_core_enable_capability_negociation(marie->lc, 1);

	LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
	linphone_core_enable_capability_negociation(pauline->lc, 1);

	const LinphoneMediaEncryption paulineOptionalEncryption = LinphoneMediaEncryptionSRTP;
	BC_ASSERT_TRUE(linphone_core_media_encryption_supported(pauline->lc,paulineOptionalEncryption));
	if (linphone_core_media_encryption_supported(pauline->lc,paulineOptionalEncryption)) {
		bctbx_list_t * encryption_list = NULL;
		encryption_list = bctbx_list_append(encryption_list, LINPHONE_INT_TO_PTR(paulineOptionalEncryption));
		linphone_core_set_media_encryption_mandatory(pauline->lc,0);
		linphone_core_set_media_encryption(pauline->lc,LinphoneMediaEncryptionNone);
		linphone_core_set_supported_media_encryptions(pauline->lc,encryption_list);
		BC_ASSERT_TRUE(linphone_core_is_media_encryption_supported(pauline->lc, paulineOptionalEncryption));
		if (encryption_list) {
			bctbx_list_free(encryption_list);
		}
	}

	bctbx_list_t * encryption_list = NULL;
	const LinphoneMediaEncryption marieOptionalEncryption0 = LinphoneMediaEncryptionDTLS;
	BC_ASSERT_TRUE(linphone_core_media_encryption_supported(marie->lc,marieOptionalEncryption0));
	if (linphone_core_media_encryption_supported(marie->lc,marieOptionalEncryption0)) {
		encryption_list = bctbx_list_append(encryption_list, LINPHONE_INT_TO_PTR(marieOptionalEncryption0));
	}

	const LinphoneMediaEncryption marieOptionalEncryption1 = LinphoneMediaEncryptionZRTP;
	BC_ASSERT_TRUE(linphone_core_media_encryption_supported(marie->lc,marieOptionalEncryption1));
	if (linphone_core_media_encryption_supported(marie->lc,marieOptionalEncryption1)) {
		encryption_list = bctbx_list_append(encryption_list, LINPHONE_INT_TO_PTR(marieOptionalEncryption1));
	}

	linphone_core_set_media_encryption_mandatory(marie->lc,0);
	linphone_core_set_media_encryption(marie->lc,LinphoneMediaEncryptionNone);
	linphone_core_set_supported_media_encryptions(marie->lc,encryption_list);
	if (encryption_list) {
		bctbx_list_free(encryption_list);
	}

	BC_ASSERT_FALSE(linphone_core_is_media_encryption_supported(marie->lc, paulineOptionalEncryption));
	BC_ASSERT_TRUE(linphone_core_is_media_encryption_supported(marie->lc, marieOptionalEncryption0));
	BC_ASSERT_TRUE(linphone_core_is_media_encryption_supported(marie->lc, marieOptionalEncryption1));

	BC_ASSERT_TRUE(linphone_core_is_media_encryption_supported(pauline->lc, paulineOptionalEncryption));
	BC_ASSERT_FALSE(linphone_core_is_media_encryption_supported(pauline->lc, marieOptionalEncryption0));
	BC_ASSERT_FALSE(linphone_core_is_media_encryption_supported(pauline->lc, marieOptionalEncryption1));

	encrypted_call_base(marie, pauline, marieOptionalEncryption0, TRUE, TRUE, FALSE);
	if (linphone_core_get_current_call(marie->lc) && linphone_core_get_current_call(pauline->lc)) {
		end_call(marie, pauline);
	}

	linphone_core_manager_destroy(marie);
	linphone_core_manager_destroy(pauline);
}

static void call_with_capability_negotiation_disable_call_level(void) {
	LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
	linphone_core_enable_capability_negociation(marie->lc, 1);
	linphone_core_set_media_encryption_mandatory(marie->lc,0);
	linphone_core_set_media_encryption(marie->lc,LinphoneMediaEncryptionNone);
	bctbx_list_t * cfg_enc = create_confg_encryption_preference_list_except(LinphoneMediaEncryptionNone);
	linphone_core_set_supported_media_encryptions(marie->lc,cfg_enc);

	LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
	linphone_core_enable_capability_negociation(pauline->lc, 1);
	linphone_core_set_media_encryption_mandatory(pauline->lc,0);
	linphone_core_set_media_encryption(pauline->lc,LinphoneMediaEncryptionNone);
	linphone_core_set_supported_media_encryptions(pauline->lc,cfg_enc);
	bctbx_list_free(cfg_enc);

	encrypted_call_base(marie, pauline, LinphoneMediaEncryptionNone, FALSE, FALSE, FALSE);
	if (linphone_core_get_current_call(marie->lc) && linphone_core_get_current_call(pauline->lc)) {
		end_call(marie, pauline);
	}

	linphone_core_manager_destroy(marie);
	linphone_core_manager_destroy(pauline);
}

static void call_with_capability_negotiation_disable_core_level(void) {
	LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
	linphone_core_enable_capability_negociation(marie->lc, 0);
	linphone_core_set_media_encryption_mandatory(marie->lc,0);
	linphone_core_set_media_encryption(marie->lc,LinphoneMediaEncryptionNone);
	bctbx_list_t * cfg_enc = create_confg_encryption_preference_list_except(LinphoneMediaEncryptionNone);
	linphone_core_set_supported_media_encryptions(marie->lc,cfg_enc);

	LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
	linphone_core_enable_capability_negociation(pauline->lc, 0);
	linphone_core_set_media_encryption_mandatory(pauline->lc,0);
	linphone_core_set_media_encryption(pauline->lc,LinphoneMediaEncryptionNone);
	linphone_core_set_supported_media_encryptions(pauline->lc,cfg_enc);

	LinphoneMediaEncryption chosenMediaEnc = static_cast<LinphoneMediaEncryption>(LINPHONE_PTR_TO_INT(bctbx_list_get_data(cfg_enc)));

	encrypted_call_base(marie, pauline, chosenMediaEnc, TRUE, TRUE, FALSE);
	bctbx_list_free(cfg_enc);
	if (linphone_core_get_current_call(marie->lc) && linphone_core_get_current_call(pauline->lc)) {
		end_call(marie, pauline);
	}

	linphone_core_manager_destroy(marie);
	linphone_core_manager_destroy(pauline);

}

static void call_with_incompatible_encs_in_call_params(void) {
	const LinphoneMediaEncryption defaultEncryption = LinphoneMediaEncryptionNone;
	const LinphoneMediaEncryption marieEncryption = LinphoneMediaEncryptionDTLS; // Desired encryption
	const LinphoneMediaEncryption paulineEncryption = LinphoneMediaEncryptionSRTP; // Desired encryption
	std::list<LinphoneMediaEncryption> marie_enc_list;
	if ((paulineEncryption != LinphoneMediaEncryptionZRTP) && (marieEncryption != LinphoneMediaEncryptionZRTP)) {
		marie_enc_list.push_back(LinphoneMediaEncryptionZRTP);
	}
	if ((paulineEncryption != LinphoneMediaEncryptionDTLS) && (marieEncryption != LinphoneMediaEncryptionDTLS)) {
		marie_enc_list.push_back(LinphoneMediaEncryptionDTLS);
	}
	if ((paulineEncryption != LinphoneMediaEncryptionSRTP) && (marieEncryption != LinphoneMediaEncryptionSRTP)) {
		marie_enc_list.push_back(LinphoneMediaEncryptionSRTP);
	}
	if ((paulineEncryption != LinphoneMediaEncryptionNone) && (marieEncryption != LinphoneMediaEncryptionNone)) {
		marie_enc_list.push_back(LinphoneMediaEncryptionNone);
	}

	encryption_params marie_enc_mgr_params;
	marie_enc_mgr_params.encryption = LinphoneMediaEncryptionNone;
	marie_enc_mgr_params.level = E_OPTIONAL;
	marie_enc_mgr_params.preferences = marie_enc_list;

	LinphoneCoreManager * marie = create_core_mgr_with_capability_negotiation_setup("marie_rc", marie_enc_mgr_params, TRUE, FALSE, FALSE);
	BC_ASSERT_FALSE(linphone_core_media_encryption_supported(marie->lc, marieEncryption));
	BC_ASSERT_FALSE(linphone_core_media_encryption_supported(marie->lc, paulineEncryption));

	std::list<LinphoneMediaEncryption> pauline_enc_list;
	if ((paulineEncryption != LinphoneMediaEncryptionSRTP) && (marieEncryption != LinphoneMediaEncryptionSRTP)) {
		pauline_enc_list.push_back(LinphoneMediaEncryptionSRTP);
	}
	if ((paulineEncryption != LinphoneMediaEncryptionZRTP) && (marieEncryption != LinphoneMediaEncryptionZRTP)) {
		pauline_enc_list.push_back(LinphoneMediaEncryptionZRTP);
	}
	if ((paulineEncryption != LinphoneMediaEncryptionNone) && (marieEncryption != LinphoneMediaEncryptionNone)) {
		pauline_enc_list.push_back(LinphoneMediaEncryptionNone);
	}
	if ((paulineEncryption != LinphoneMediaEncryptionDTLS) && (marieEncryption != LinphoneMediaEncryptionDTLS)) {
		pauline_enc_list.push_back(LinphoneMediaEncryptionDTLS);
	}

	encryption_params pauline_enc_mgr_params;
	pauline_enc_mgr_params.encryption = LinphoneMediaEncryptionNone;
	pauline_enc_mgr_params.level = E_OPTIONAL;
	pauline_enc_mgr_params.preferences = pauline_enc_list;

	LinphoneCoreManager * pauline = create_core_mgr_with_capability_negotiation_setup((transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"), pauline_enc_mgr_params, TRUE, FALSE, FALSE);
	BC_ASSERT_FALSE(linphone_core_media_encryption_supported(pauline->lc, marieEncryption));
	BC_ASSERT_FALSE(linphone_core_media_encryption_supported(pauline->lc, paulineEncryption));

	bctbx_list_t * marie_call_enc = NULL;
	marie_call_enc = bctbx_list_append(marie_call_enc, LINPHONE_INT_TO_PTR(marieEncryption));
	LinphoneCallParams *marie_params = linphone_core_create_call_params(marie->lc, NULL);
	linphone_call_params_enable_capability_negotiations (marie_params, 1);
	linphone_call_params_set_supported_encryptions (marie_params, marie_call_enc);
	bctbx_list_free(marie_call_enc);

	bctbx_list_t * pauline_call_enc = NULL;
	pauline_call_enc = bctbx_list_append(pauline_call_enc, LINPHONE_INT_TO_PTR(paulineEncryption));
	LinphoneCallParams *pauline_params = linphone_core_create_call_params(pauline->lc, NULL);
	linphone_call_params_enable_capability_negotiations (pauline_params, 1);
	linphone_call_params_set_supported_encryptions (pauline_params, pauline_call_enc);
	bctbx_list_free(pauline_call_enc);

	// Check requirements for this test:
	// - encryption of Marie and Pauline should be different
	// - Marie and Pauline encryption list in the call params must be equal to 1
	BC_ASSERT_NOT_EQUAL(paulineEncryption, marieEncryption, int, "%i");

	bctbx_list_t* pauline_supported_encs = linphone_call_params_get_supported_encryptions (pauline_params);
	BC_ASSERT_EQUAL((int)bctbx_list_size(pauline_supported_encs), 1, int, "%d");
	if (pauline_supported_encs) {
		bctbx_list_free(pauline_supported_encs);
	}

	bctbx_list_t* marie_supported_encs = linphone_call_params_get_supported_encryptions (marie_params);
	BC_ASSERT_EQUAL((int)bctbx_list_size(marie_supported_encs), 1, int, "%d");
	if (marie_supported_encs) {
		bctbx_list_free(marie_supported_encs);
	}

	BC_ASSERT_TRUE(call_with_params_and_encryption_negotiation_failure_base(marie, pauline, marie_params, pauline_params, TRUE));

	LinphoneCall *marieCall = linphone_core_get_current_call(marie->lc);
	BC_ASSERT_PTR_NOT_NULL(marieCall);
	LinphoneCall *paulineCall = linphone_core_get_current_call(pauline->lc);
	BC_ASSERT_PTR_NOT_NULL(paulineCall);

	liblinphone_tester_check_rtcp(marie, pauline);

	if (marieCall) {
		check_stream_encryption(marieCall);
		BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(marieCall)), defaultEncryption, int, "%i");
	}
	if (paulineCall) {
		check_stream_encryption(paulineCall);
		BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(paulineCall)), defaultEncryption, int, "%i");
	}

	end_call(pauline, marie);

	linphone_call_params_unref(marie_params);
	linphone_call_params_unref(pauline_params);

	linphone_core_manager_destroy(marie);
	linphone_core_manager_destroy(pauline);

}

void call_with_video_and_capability_negotiation_base(const LinphoneMediaEncryption encryption) {

	std::list<LinphoneMediaEncryption> marie_enc_list;
	if (encryption != LinphoneMediaEncryptionZRTP) {
		marie_enc_list.push_back(LinphoneMediaEncryptionZRTP);
	}
	if (encryption != LinphoneMediaEncryptionDTLS) {
		marie_enc_list.push_back(LinphoneMediaEncryptionDTLS);
	}
	if (encryption != LinphoneMediaEncryptionSRTP) {
		marie_enc_list.push_back(LinphoneMediaEncryptionSRTP);
	}
	if (encryption != LinphoneMediaEncryptionNone) {
		marie_enc_list.push_back(LinphoneMediaEncryptionNone);
	}

	encryption_params marie_enc_mgr_params;
	marie_enc_mgr_params.encryption = LinphoneMediaEncryptionNone;
	marie_enc_mgr_params.level = E_OPTIONAL;
	marie_enc_mgr_params.preferences = marie_enc_list;

	LinphoneCoreManager * marie = create_core_mgr_with_capability_negotiation_setup("marie_rc", marie_enc_mgr_params, TRUE, FALSE, TRUE);
	BC_ASSERT_FALSE(linphone_core_media_encryption_supported(marie->lc, encryption));

	std::list<LinphoneMediaEncryption> pauline_enc_list;
	if (encryption != LinphoneMediaEncryptionSRTP) {
		pauline_enc_list.push_back(LinphoneMediaEncryptionSRTP);
	}
	if (encryption != LinphoneMediaEncryptionZRTP) {
		pauline_enc_list.push_back(LinphoneMediaEncryptionZRTP);
	}
	if (encryption != LinphoneMediaEncryptionNone) {
		pauline_enc_list.push_back(LinphoneMediaEncryptionNone);
	}
	if (encryption != LinphoneMediaEncryptionDTLS) {
		pauline_enc_list.push_back(LinphoneMediaEncryptionDTLS);
	}

	encryption_params pauline_enc_mgr_params;
	pauline_enc_mgr_params.encryption = LinphoneMediaEncryptionNone;
	pauline_enc_mgr_params.level = E_OPTIONAL;
	pauline_enc_mgr_params.preferences = pauline_enc_list;

	LinphoneCoreManager * pauline = create_core_mgr_with_capability_negotiation_setup((transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"), pauline_enc_mgr_params, TRUE, FALSE, TRUE);
	BC_ASSERT_FALSE(linphone_core_media_encryption_supported(pauline->lc, encryption));

	bctbx_list_t * call_enc = NULL;
	call_enc = bctbx_list_append(call_enc, LINPHONE_INT_TO_PTR(encryption));

	LinphoneCallParams *marie_params = linphone_core_create_call_params(marie->lc, NULL);
	linphone_call_params_enable_video(marie_params, 1);
	linphone_call_params_enable_capability_negotiations (marie_params, 1);
	linphone_call_params_set_supported_encryptions (marie_params, call_enc);
	LinphoneCallParams *pauline_params = linphone_core_create_call_params(pauline->lc, NULL);
	linphone_call_params_enable_video(pauline_params, 1);
	linphone_call_params_enable_capability_negotiations (pauline_params, 1);
	linphone_call_params_set_supported_encryptions (pauline_params, call_enc);

	bctbx_list_free(call_enc);

	BC_ASSERT_TRUE(call_with_params(marie, pauline, marie_params, pauline_params));

	LinphoneCall *marieCall = linphone_core_get_current_call(marie->lc);
	BC_ASSERT_PTR_NOT_NULL(marieCall);
	LinphoneCall *paulineCall = linphone_core_get_current_call(pauline->lc);
	BC_ASSERT_PTR_NOT_NULL(paulineCall);

	const int expectedStreamsRunning = 2;
	BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneCallStreamsRunning, expectedStreamsRunning, int, "%i");
	BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallStreamsRunning, expectedStreamsRunning, int, "%i");

	if (marieCall) {
		check_stream_encryption(marieCall);
		BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(marieCall)), encryption, int, "%i");
	}
	if (paulineCall) {
		check_stream_encryption(paulineCall);
		BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(paulineCall)), encryption, int, "%i");
	}

	if (marieCall && paulineCall ) {
		BC_ASSERT_TRUE(linphone_call_log_video_enabled(linphone_call_get_call_log(marieCall)));
		BC_ASSERT_TRUE(linphone_call_log_video_enabled(linphone_call_get_call_log(paulineCall)));

		BC_ASSERT_TRUE(linphone_call_params_video_enabled(linphone_call_get_current_params(marieCall)));
		BC_ASSERT_TRUE(linphone_call_params_video_enabled(linphone_call_get_current_params(paulineCall)));

		/*check video path*/
		liblinphone_tester_set_next_video_frame_decoded_cb(paulineCall);
		liblinphone_tester_set_next_video_frame_decoded_cb(marieCall);
		linphone_call_send_vfu_request(paulineCall);
		BC_ASSERT_TRUE( wait_for(marie->lc,pauline->lc,&pauline->stat.number_of_IframeDecoded,1));
		BC_ASSERT_TRUE( wait_for(marie->lc,pauline->lc,&marie->stat.number_of_IframeDecoded,1));
	}

	liblinphone_tester_check_rtcp(pauline,marie);

	end_call(pauline, marie);

	linphone_call_params_unref(marie_params);
	linphone_call_params_unref(pauline_params);

	linphone_core_manager_destroy(marie);
	linphone_core_manager_destroy(pauline);
}

static void call_with_tcap_line_merge_base(const bool_t caller_tcap_merge, const bool_t callee_tcap_merge) {
	encryption_params caller_enc_mgr_params;
	caller_enc_mgr_params.encryption = LinphoneMediaEncryptionZRTP;
	caller_enc_mgr_params.level = E_OPTIONAL;
	caller_enc_mgr_params.preferences = set_encryption_preference(TRUE);

	encryption_params callee_enc_mgr_params;
	callee_enc_mgr_params.encryption = LinphoneMediaEncryptionDTLS;
	callee_enc_mgr_params.level = E_OPTIONAL;
	callee_enc_mgr_params.preferences = set_encryption_preference(FALSE);

	LinphoneCoreManager * caller = create_core_mgr_with_capability_negotiation_setup("marie_rc", caller_enc_mgr_params, TRUE, FALSE, TRUE);
	LinphoneCoreManager * callee = create_core_mgr_with_capability_negotiation_setup((transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"), callee_enc_mgr_params, TRUE, FALSE, TRUE);

	// Caller call params:
	// - RFC5939 is supported
	// - Merge tcap lines
	// - Default encryption SRTP
	// - No mandatory encryption
	// - Supported optional encryptions: DTLS, ZRTP
	LinphoneCallParams *caller_params = linphone_core_create_call_params(caller->lc, NULL);
	linphone_call_params_enable_capability_negotiations (caller_params, TRUE);
	bctbx_list_t * caller_cfg_enc = NULL;
	caller_cfg_enc = bctbx_list_append(caller_cfg_enc, LINPHONE_INT_TO_PTR(LinphoneMediaEncryptionDTLS));
	caller_cfg_enc = bctbx_list_append(caller_cfg_enc, LINPHONE_INT_TO_PTR(LinphoneMediaEncryptionZRTP));
	linphone_call_params_set_supported_encryptions(caller_params,caller_cfg_enc);
	bctbx_list_free(caller_cfg_enc);
	linphone_call_params_set_media_encryption (caller_params, LinphoneMediaEncryptionSRTP);
	linphone_call_params_enable_mandatory_media_encryption(caller_params,0);
	linphone_call_params_enable_tcap_line_merging(caller_params, TRUE);

	// Callee call params:
	// - RFC5939 is supported
	// - Merge tcap lines
	// - Default encryption SRTP
	// - No mandatory encryption
	// - Supported optional encryptions: SRTP, ZRTP, DTLS
	LinphoneCallParams *callee_params = linphone_core_create_call_params(callee->lc, NULL);
	linphone_call_params_enable_capability_negotiations (callee_params, TRUE);
	bctbx_list_t * callee_cfg_enc = NULL;
	callee_cfg_enc = bctbx_list_append(callee_cfg_enc, LINPHONE_INT_TO_PTR(LinphoneMediaEncryptionSRTP));
	callee_cfg_enc = bctbx_list_append(callee_cfg_enc, LINPHONE_INT_TO_PTR(LinphoneMediaEncryptionZRTP));
	callee_cfg_enc = bctbx_list_append(callee_cfg_enc, LINPHONE_INT_TO_PTR(LinphoneMediaEncryptionDTLS));
	linphone_call_params_set_supported_encryptions(callee_params,callee_cfg_enc);
	bctbx_list_free(callee_cfg_enc);
	linphone_call_params_set_media_encryption (callee_params, LinphoneMediaEncryptionNone);
	linphone_call_params_enable_mandatory_media_encryption(callee_params,0);
	linphone_call_params_enable_tcap_line_merging(callee_params, TRUE);

	const LinphoneMediaEncryption expectedEncryption = LinphoneMediaEncryptionDTLS;
	encrypted_call_with_params_base(caller, callee, expectedEncryption, caller_params, callee_params, TRUE);
	if (linphone_core_get_current_call(caller->lc)) {
		end_call(caller, callee);
	}

	linphone_call_params_unref(caller_params);
	linphone_call_params_unref(callee_params);

	linphone_core_manager_destroy(caller);
	linphone_core_manager_destroy(callee);
}

static void call_with_tcap_line_merge_on_caller(void) {
	call_with_tcap_line_merge_base(TRUE, FALSE);
}

static void call_with_tcap_line_merge_on_callee(void) {
	call_with_tcap_line_merge_base(FALSE, TRUE);
}

static void call_with_tcap_line_merge_on_both_sides(void) {
	call_with_tcap_line_merge_base(TRUE, TRUE);
}

static void call_with_no_sdp_on_update_base (const bool_t caller_cap_neg, const bool_t callee_cap_neg, const bool_t caller_cap_neg_reinvite, const bool_t callee_cap_neg_reinvite) {
	const LinphoneMediaEncryption encryption = LinphoneMediaEncryptionSRTP; // Desired encryption
	const LinphoneMediaEncryption encryption1 = LinphoneMediaEncryptionNone; // Desired encryption after first update
	const LinphoneMediaEncryption encryption2 = LinphoneMediaEncryptionZRTP; // Desired encryption after Marie's update

	LinphoneMediaEncryption marieEncryption = LinphoneMediaEncryptionNone;
	if (caller_cap_neg && callee_cap_neg) {
		marieEncryption = LinphoneMediaEncryptionDTLS;
	} else {
		marieEncryption = encryption;
	}

	std::list<LinphoneMediaEncryption> marie_enc_list;
	if (encryption != LinphoneMediaEncryptionZRTP) {
		marie_enc_list.push_back(LinphoneMediaEncryptionZRTP);
	}
	if (encryption != LinphoneMediaEncryptionDTLS) {
		marie_enc_list.push_back(LinphoneMediaEncryptionDTLS);
	}
	if (encryption != LinphoneMediaEncryptionSRTP) {
		marie_enc_list.push_back(LinphoneMediaEncryptionSRTP);
	}
	if (encryption != LinphoneMediaEncryptionNone) {
		marie_enc_list.push_back(LinphoneMediaEncryptionNone);
	}

	encryption_params marie_enc_mgr_params;
	marie_enc_mgr_params.encryption = LinphoneMediaEncryptionNone;
	marie_enc_mgr_params.level = E_OPTIONAL;
	marie_enc_mgr_params.preferences = marie_enc_list;

	LinphoneCoreManager * marie = create_core_mgr_with_capability_negotiation_setup("marie_rc", marie_enc_mgr_params, caller_cap_neg, FALSE, TRUE);
	linphone_core_enable_capability_negotiation_reinvite(marie->lc, caller_cap_neg_reinvite);

	std::list<LinphoneMediaEncryption> pauline_enc_list;
	if (encryption != LinphoneMediaEncryptionSRTP) {
		pauline_enc_list.push_back(LinphoneMediaEncryptionSRTP);
	}
	if (encryption != LinphoneMediaEncryptionZRTP) {
		pauline_enc_list.push_back(LinphoneMediaEncryptionZRTP);
	}
	if (encryption != LinphoneMediaEncryptionNone) {
		pauline_enc_list.push_back(LinphoneMediaEncryptionNone);
	}
	if (encryption != LinphoneMediaEncryptionDTLS) {
		pauline_enc_list.push_back(LinphoneMediaEncryptionDTLS);
	}

	encryption_params pauline_enc_mgr_params;
	pauline_enc_mgr_params.encryption = LinphoneMediaEncryptionNone;
	pauline_enc_mgr_params.level = E_OPTIONAL;
	pauline_enc_mgr_params.preferences = pauline_enc_list;

	LinphoneCoreManager * pauline = create_core_mgr_with_capability_negotiation_setup((transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"), pauline_enc_mgr_params, callee_cap_neg, FALSE, TRUE);
	linphone_core_enable_capability_negotiation_reinvite(pauline->lc, callee_cap_neg_reinvite);

	bctbx_list_t * marie_call_enc = NULL;
	marie_call_enc = bctbx_list_append(marie_call_enc, LINPHONE_INT_TO_PTR(encryption));
	marie_call_enc = bctbx_list_append(marie_call_enc, LINPHONE_INT_TO_PTR(encryption1));

	LinphoneCallParams *marie_params = linphone_core_create_call_params(marie->lc, NULL);
	linphone_call_params_enable_capability_negotiations (marie_params, caller_cap_neg);
	linphone_call_params_set_supported_encryptions (marie_params, marie_call_enc);
	linphone_call_params_set_media_encryption (marie_params, marieEncryption);

	bctbx_list_free(marie_call_enc);

	bctbx_list_t * pauline_call_enc = NULL;
	pauline_call_enc = bctbx_list_append(pauline_call_enc, LINPHONE_INT_TO_PTR(LinphoneMediaEncryptionZRTP));
	LinphoneCallParams *pauline_params = linphone_core_create_call_params(pauline->lc, NULL);
	linphone_call_params_enable_capability_negotiations (pauline_params, callee_cap_neg);
	linphone_call_params_set_media_encryption (pauline_params, encryption);
	linphone_call_params_set_supported_encryptions (pauline_params, pauline_call_enc);

	bctbx_list_free(pauline_call_enc);

	// Different scenarios:
	// ==================== OFFERER =====================
	// If offerer and answerer supports capability negotiations:
	// - actual configuration: DTLS
	// - potential configuration: SRTP
	// If offerer only supports capability negotiations:
	// - actual configuration: SRTP
	// - potential configuration: SRTP
	// If offerer doesn't support capability negotiations:
	// - actual configuration: SRTP
	// ==================== ANSWERER =====================
	// If answerer supports capability negotiations:
	// - actual configuration: SRTP
	// - potential configuration: ZRTP
	// If answerer doesn't support capability negotiations:
	// - actual configuration: SRTP
	// ==================== RESULT =====================
	// Result: encryption SRTP is chosen
	BC_ASSERT_TRUE(call_with_params(marie, pauline, marie_params, pauline_params));

	LinphoneCall *marieCall = linphone_core_get_current_call(marie->lc);
	BC_ASSERT_PTR_NOT_NULL(marieCall);
	LinphoneCall *paulineCall = linphone_core_get_current_call(pauline->lc);
	BC_ASSERT_PTR_NOT_NULL(paulineCall);

	liblinphone_tester_check_rtcp(marie, pauline);

	LinphoneNatPolicy *marie_nat_policy = linphone_core_get_nat_policy(marie->lc);
	const bool_t marie_ice_enabled = linphone_nat_policy_ice_enabled(marie_nat_policy);
	LinphoneNatPolicy *pauline_nat_policy = linphone_core_get_nat_policy(pauline->lc);
	const bool_t pauline_ice_enabled = linphone_nat_policy_ice_enabled(pauline_nat_policy);

	bool potentialConfigurationChosen = (caller_cap_neg && callee_cap_neg);
	bool_t capabilityNegotiationReinviteEnabled = linphone_call_params_is_capability_negotiation_reinvite_enabled(linphone_call_get_params(marieCall));
	bool sendReInvite = (potentialConfigurationChosen && capabilityNegotiationReinviteEnabled) || (marie_ice_enabled && pauline_ice_enabled);
	int expectedStreamsRunning = 1 + ((sendReInvite) ? 1 : 0);

	BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneCallStreamsRunning, expectedStreamsRunning, int, "%d");
	BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallStreamsRunning, expectedStreamsRunning, int, "%d");

	// Check that encryption has not changed after sending update
	if (marieCall) {
		check_stream_encryption(marieCall);
		BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(marieCall)), encryption, int, "%i");
	}
	if (paulineCall) {
		check_stream_encryption(paulineCall);
		BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(paulineCall)), encryption, int, "%i");
	}

	ms_message("Pauline sends a reINVITE without SDP");
	// Pauline send an empty SDP for the update
	linphone_core_enable_sdp_200_ack(pauline->lc,TRUE);


	stats marie_stat = marie->stat; 
	stats pauline_stat = pauline->stat; 
	LinphoneCallParams * params0 = linphone_core_create_call_params(pauline->lc, paulineCall);
	if (caller_cap_neg && callee_cap_neg) {
		linphone_call_params_set_media_encryption (params0, encryption1);
	}
	bctbx_list_t * encs0 = NULL;
	encs0 = bctbx_list_append(encs0, LINPHONE_INT_TO_PTR(encryption1));
	encs0 = bctbx_list_append(encs0, LINPHONE_INT_TO_PTR(encryption2));
	linphone_call_params_set_supported_encryptions (params0, encs0);
	bctbx_list_free(encs0);

	BC_ASSERT_TRUE(linphone_core_sdp_200_ack_enabled(pauline->lc));
	linphone_call_update(paulineCall, params0);
	linphone_call_params_unref(params0);
	BC_ASSERT_TRUE( wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallUpdating,(pauline_stat.number_of_LinphoneCallUpdating+1)));
	BC_ASSERT_TRUE( wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallUpdatedByRemote,(marie_stat.number_of_LinphoneCallUpdatedByRemote+1)));

	BC_ASSERT_TRUE( wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallStreamsRunning,(pauline_stat.number_of_LinphoneCallStreamsRunning+1)));
	BC_ASSERT_TRUE( wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallStreamsRunning,(marie_stat.number_of_LinphoneCallStreamsRunning+1)));

	LinphoneMediaEncryption encryptionAfterUpdate = (caller_cap_neg && callee_cap_neg) ? encryption1 : encryption;
	LinphoneMediaEncryption expectedEncryption =  LinphoneMediaEncryptionNone;
	bool dummyPotentialConfigurationChosen = false;
	get_expected_encryption_from_call_params(paulineCall, marieCall, &expectedEncryption, &dummyPotentialConfigurationChosen);
	// As Pauline sends a reINVITE without SDP, Marie replies with the same SDP as she previously sent hence it has the same capability negotiation flags as the previous answer to the INVITE.
	// A reINVITE is sent again if capability negotiations are sent
	capabilityNegotiationReinviteEnabled = linphone_call_params_is_capability_negotiation_reinvite_enabled(linphone_call_get_params(marieCall));
	sendReInvite = (potentialConfigurationChosen && capabilityNegotiationReinviteEnabled) || (marie_ice_enabled && pauline_ice_enabled);
	expectedStreamsRunning = 1 + ((sendReInvite) ? 1 : 0);

	/*wait for reINVITEs to complete*/
	BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallStreamsRunning,(pauline_stat.number_of_LinphoneCallStreamsRunning+expectedStreamsRunning)));
	BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallStreamsRunning,(marie_stat.number_of_LinphoneCallStreamsRunning+expectedStreamsRunning)));

	linphone_core_enable_sdp_200_ack(pauline->lc,FALSE);

	liblinphone_tester_check_rtcp(marie, pauline);

	wait_for_until(marie->lc, pauline->lc, NULL, 5, 2000);

	// Check that encryption has not changed after sending update
	BC_ASSERT_EQUAL(expectedEncryption, encryptionAfterUpdate, int, "%i");
	if (marieCall) {
		check_stream_encryption(marieCall);
		BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(marieCall)), expectedEncryption, int, "%i");
	}
	if (paulineCall) {
		check_stream_encryption(paulineCall);
		BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(paulineCall)), expectedEncryption, int, "%i");
	}

	BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneCallStreamsRunning, (pauline_stat.number_of_LinphoneCallStreamsRunning+expectedStreamsRunning), int, "%d");
	BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallStreamsRunning, (marie_stat.number_of_LinphoneCallStreamsRunning+expectedStreamsRunning), int, "%d");

	marie_stat = marie->stat; 
	pauline_stat = pauline->stat; 
	LinphoneCallParams * params1 = linphone_core_create_call_params(pauline->lc, paulineCall);
	linphone_call_params_enable_video(params1, TRUE);
	BC_ASSERT_FALSE(linphone_core_sdp_200_ack_enabled(pauline->lc));
	ms_message("Pauline enables video");
	linphone_call_update(paulineCall, params1);
	linphone_call_params_unref(params1);
	BC_ASSERT_TRUE( wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallUpdating,(pauline_stat.number_of_LinphoneCallUpdating+1)));
	BC_ASSERT_TRUE( wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallUpdatedByRemote,(marie_stat.number_of_LinphoneCallUpdatedByRemote+1)));

	BC_ASSERT_TRUE( wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallStreamsRunning,(pauline_stat.number_of_LinphoneCallStreamsRunning+1)));
	BC_ASSERT_TRUE( wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallStreamsRunning,(marie_stat.number_of_LinphoneCallStreamsRunning+1)));

	get_expected_encryption_from_call_params(paulineCall, marieCall, &expectedEncryption, &potentialConfigurationChosen);
	capabilityNegotiationReinviteEnabled = linphone_call_params_is_capability_negotiation_reinvite_enabled(linphone_call_get_params(paulineCall));
	sendReInvite = (potentialConfigurationChosen && capabilityNegotiationReinviteEnabled);
	expectedStreamsRunning = 1 + ((sendReInvite) ? 1 : 0);

	// wait for reINVITEs to complete
	BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallStreamsRunning,(pauline_stat.number_of_LinphoneCallStreamsRunning+expectedStreamsRunning)));
	BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallStreamsRunning,(marie_stat.number_of_LinphoneCallStreamsRunning+expectedStreamsRunning)));

	if (pauline_ice_enabled && marie_ice_enabled) {
		BC_ASSERT_TRUE(check_ice(marie, pauline, LinphoneIceStateHostConnection));
		BC_ASSERT_TRUE(check_ice(pauline, marie, LinphoneIceStateHostConnection));
	}

	liblinphone_tester_set_next_video_frame_decoded_cb(marieCall);
	liblinphone_tester_set_next_video_frame_decoded_cb(paulineCall);

	BC_ASSERT_TRUE( wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_IframeDecoded,(pauline_stat.number_of_IframeDecoded+1)));
	BC_ASSERT_TRUE( wait_for(pauline->lc,marie->lc,&marie->stat.number_of_IframeDecoded,(marie_stat.number_of_IframeDecoded+1)));

	BC_ASSERT_TRUE(linphone_call_params_video_enabled(linphone_call_get_current_params(paulineCall)));
	BC_ASSERT_TRUE(linphone_call_params_video_enabled(linphone_call_get_current_params(marieCall)));

	BC_ASSERT_TRUE(linphone_call_log_video_enabled(linphone_call_get_call_log(paulineCall)));
	BC_ASSERT_TRUE(linphone_call_log_video_enabled(linphone_call_get_call_log(marieCall)));

	liblinphone_tester_check_rtcp(marie, pauline);

	wait_for_until(marie->lc, pauline->lc, NULL, 5, 2000);

	// Check that encryption has not changed after sending update
	BC_ASSERT_EQUAL(expectedEncryption, encryptionAfterUpdate, int, "%i");
	if (marieCall) {
		check_stream_encryption(marieCall);
		BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(marieCall)), expectedEncryption, int, "%i");
	}
	if (paulineCall) {
		check_stream_encryption(paulineCall);
		BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(paulineCall)), expectedEncryption, int, "%i");
	}

	BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneCallStreamsRunning, (pauline_stat.number_of_LinphoneCallStreamsRunning+expectedStreamsRunning), int, "%d");
	BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallStreamsRunning, (marie_stat.number_of_LinphoneCallStreamsRunning+expectedStreamsRunning), int, "%d");

	// Marie send an empty SDP for the update
	linphone_core_enable_sdp_200_ack(marie->lc,TRUE);

	marie_stat = marie->stat; 
	pauline_stat = pauline->stat; 
	LinphoneCallParams * params2 = linphone_core_create_call_params(marie->lc, marieCall);
	linphone_call_params_set_media_encryption (params2, marieEncryption);
	bctbx_list_t * encs2 = NULL;
	encs2 = bctbx_list_append(encs2, LINPHONE_INT_TO_PTR(encryption2));
	encs2 = bctbx_list_append(encs2, LINPHONE_INT_TO_PTR(encryption));
	linphone_call_params_set_supported_encryptions (params2, encs2);
	bctbx_list_free(encs2);
	BC_ASSERT_TRUE(linphone_core_sdp_200_ack_enabled(marie->lc));
	ms_message("Marie sends a reINVITE without SDP");
	linphone_call_update(marieCall, params2);
	linphone_call_params_unref(params2);
	BC_ASSERT_TRUE( wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallUpdating,(marie_stat.number_of_LinphoneCallUpdating+1)));
	BC_ASSERT_TRUE( wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallUpdatedByRemote,(pauline_stat.number_of_LinphoneCallUpdatedByRemote+1)));

	BC_ASSERT_TRUE( wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallStreamsRunning,(pauline_stat.number_of_LinphoneCallStreamsRunning+1)));
	BC_ASSERT_TRUE( wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallStreamsRunning,(marie_stat.number_of_LinphoneCallStreamsRunning+1)));

	encryptionAfterUpdate = (caller_cap_neg && callee_cap_neg) ? encryption2 : encryption;
	get_expected_encryption_from_call_params(marieCall, paulineCall, &expectedEncryption, &potentialConfigurationChosen);
	capabilityNegotiationReinviteEnabled = linphone_call_params_is_capability_negotiation_reinvite_enabled(linphone_call_get_params(paulineCall));
	sendReInvite = (potentialConfigurationChosen && capabilityNegotiationReinviteEnabled);
	expectedStreamsRunning = 1 + ((sendReInvite) ? 1 : 0);

	// wait for reINVITEs to complete
	BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallStreamsRunning,(marie_stat.number_of_LinphoneCallStreamsRunning+expectedStreamsRunning)));
	BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallStreamsRunning,(pauline_stat.number_of_LinphoneCallStreamsRunning+expectedStreamsRunning)));

	linphone_core_enable_sdp_200_ack(marie->lc,FALSE);

	liblinphone_tester_set_next_video_frame_decoded_cb(marieCall);
	liblinphone_tester_set_next_video_frame_decoded_cb(paulineCall);

	BC_ASSERT_TRUE( wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_IframeDecoded,(pauline_stat.number_of_IframeDecoded+1)));
	BC_ASSERT_TRUE( wait_for(pauline->lc,marie->lc,&marie->stat.number_of_IframeDecoded,(marie_stat.number_of_IframeDecoded+1)));

	BC_ASSERT_TRUE(linphone_call_params_video_enabled(linphone_call_get_current_params(paulineCall)));
	BC_ASSERT_TRUE(linphone_call_params_video_enabled(linphone_call_get_current_params(marieCall)));

	BC_ASSERT_TRUE(linphone_call_log_video_enabled(linphone_call_get_call_log(paulineCall)));
	BC_ASSERT_TRUE(linphone_call_log_video_enabled(linphone_call_get_call_log(marieCall)));

	liblinphone_tester_check_rtcp(marie, pauline);

	wait_for_until(marie->lc, pauline->lc, NULL, 5, 2000);

	// Check that encryption has not changed after sending update
	BC_ASSERT_EQUAL(expectedEncryption, encryptionAfterUpdate, int, "%i");
	if (marieCall) {
		check_stream_encryption(marieCall);
		BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(marieCall)), expectedEncryption, int, "%i");
	}
	if (paulineCall) {
		check_stream_encryption(paulineCall);
		BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(paulineCall)), expectedEncryption, int, "%i");
	}

	BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneCallStreamsRunning, (pauline_stat.number_of_LinphoneCallStreamsRunning+expectedStreamsRunning), int, "%d");
	BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallStreamsRunning, (marie_stat.number_of_LinphoneCallStreamsRunning+expectedStreamsRunning), int, "%d");

	end_call(pauline, marie);

	linphone_call_params_unref(marie_params);
	linphone_call_params_unref(pauline_params);

	linphone_core_manager_destroy(marie);
	linphone_core_manager_destroy(pauline);
}

static void call_with_no_sdp_on_update_cap_neg_caller (void) {
	call_with_no_sdp_on_update_base (TRUE, FALSE, TRUE, TRUE);
}

static void call_with_no_sdp_on_update_cap_neg_callee (void) {
	call_with_no_sdp_on_update_base (FALSE, TRUE, TRUE, TRUE);
}

static void call_with_no_sdp_on_update_cap_neg_both_sides_with_reinvite (void) {
	call_with_no_sdp_on_update_base (TRUE, TRUE, TRUE, TRUE);
}

static void call_with_no_sdp_on_update_cap_neg_both_sides_without_reinvite_on_caller (void) {
	call_with_no_sdp_on_update_base (TRUE, TRUE, FALSE, TRUE);
}

static void call_with_no_sdp_on_update_cap_neg_both_sides_without_reinvite_on_callee (void) {
	call_with_no_sdp_on_update_base (TRUE, TRUE, TRUE, FALSE);
}

static void call_with_no_sdp_on_update_cap_neg_both_sides_without_reinvite (void) {
	call_with_no_sdp_on_update_base (TRUE, TRUE, FALSE, FALSE);
}

static void call_changes_enc_on_update_base (const bool_t caller_cap_neg, const bool_t callee_cap_neg, const bool_t caller_cap_neg_reinvite, const bool_t callee_cap_neg_reinvite) {
	const LinphoneMediaEncryption encryption = LinphoneMediaEncryptionSRTP; // Desired encryption
	LinphoneMediaEncryption expectedEncryption = encryption; // Expected encryption

	LinphoneMediaEncryption marieEncryption = LinphoneMediaEncryptionNone;
	if (caller_cap_neg && callee_cap_neg) {
		marieEncryption = LinphoneMediaEncryptionDTLS;
	} else {
		marieEncryption = encryption;
	}

	std::list<LinphoneMediaEncryption> marie_enc_list;
	if (encryption != LinphoneMediaEncryptionZRTP) {
		marie_enc_list.push_back(LinphoneMediaEncryptionZRTP);
	}
	if (encryption != LinphoneMediaEncryptionDTLS) {
		marie_enc_list.push_back(LinphoneMediaEncryptionDTLS);
	}
	if (encryption != LinphoneMediaEncryptionSRTP) {
		marie_enc_list.push_back(LinphoneMediaEncryptionSRTP);
	}
	if (encryption != LinphoneMediaEncryptionNone) {
		marie_enc_list.push_back(LinphoneMediaEncryptionNone);
	}

	encryption_params marie_enc_mgr_params;
	marie_enc_mgr_params.encryption = LinphoneMediaEncryptionNone;
	marie_enc_mgr_params.level = E_OPTIONAL;
	marie_enc_mgr_params.preferences = marie_enc_list;

	LinphoneCoreManager * marie = create_core_mgr_with_capability_negotiation_setup("marie_rc", marie_enc_mgr_params, caller_cap_neg, FALSE, TRUE);
	linphone_core_enable_capability_negotiation_reinvite(marie->lc, caller_cap_neg_reinvite);

	std::list<LinphoneMediaEncryption> pauline_enc_list;
	if (encryption != LinphoneMediaEncryptionSRTP) {
		pauline_enc_list.push_back(LinphoneMediaEncryptionSRTP);
	}
	if (encryption != LinphoneMediaEncryptionZRTP) {
		pauline_enc_list.push_back(LinphoneMediaEncryptionZRTP);
	}
	if (encryption != LinphoneMediaEncryptionNone) {
		pauline_enc_list.push_back(LinphoneMediaEncryptionNone);
	}
	if (encryption != LinphoneMediaEncryptionDTLS) {
		pauline_enc_list.push_back(LinphoneMediaEncryptionDTLS);
	}

	encryption_params pauline_enc_mgr_params;
	pauline_enc_mgr_params.encryption = LinphoneMediaEncryptionNone;
	pauline_enc_mgr_params.level = E_OPTIONAL;
	pauline_enc_mgr_params.preferences = pauline_enc_list;

	LinphoneCoreManager * pauline = create_core_mgr_with_capability_negotiation_setup((transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"), pauline_enc_mgr_params, callee_cap_neg, FALSE, TRUE);
	linphone_core_enable_capability_negotiation_reinvite(pauline->lc, callee_cap_neg_reinvite);

	bctbx_list_t * marie_call_enc = NULL;
	marie_call_enc = bctbx_list_append(marie_call_enc, LINPHONE_INT_TO_PTR(encryption));
	marie_call_enc = bctbx_list_append(marie_call_enc, LINPHONE_INT_TO_PTR(LinphoneMediaEncryptionDTLS));

	LinphoneCallParams *marie_params = linphone_core_create_call_params(marie->lc, NULL);
	linphone_call_params_enable_capability_negotiations (marie_params, caller_cap_neg);
	linphone_call_params_set_supported_encryptions (marie_params, marie_call_enc);
	bctbx_list_free(marie_call_enc);

	linphone_call_params_set_media_encryption (marie_params, marieEncryption);

	bctbx_list_t * pauline_call_enc = NULL;
	pauline_call_enc = bctbx_list_append(pauline_call_enc, LINPHONE_INT_TO_PTR(LinphoneMediaEncryptionZRTP));
	LinphoneCallParams *pauline_params = linphone_core_create_call_params(pauline->lc, NULL);
	linphone_call_params_enable_capability_negotiations (pauline_params, callee_cap_neg);
	linphone_call_params_set_media_encryption (pauline_params, encryption);
	linphone_call_params_set_supported_encryptions (pauline_params, pauline_call_enc);
	bctbx_list_free(pauline_call_enc);

	// Different scenarios:
	// ==================== OFFERER =====================
	// If offerer and answerer supports capability negotiations:
	// - actual configuration: DTLS
	// - potential configuration: SRTP and DTLS
	// If offerer only supports capability negotiations:
	// - actual configuration: SRTP
	// - potential configuration: SRTP and DTLS
	// If offerer doesn't support capability negotiations:
	// - actual configuration: SRTP
	// ==================== ANSWERER =====================
	// If answerer supports capability negotiations:
	// - actual configuration: SRTP
	// - potential configuration: ZRTP
	// If answerer doesn't support capability negotiations:
	// - actual configuration: SRTP
	// ==================== RESULT =====================
	// Result: encryption SRTP is chosen
	ms_message("SRTP Call from Marie to Pauline");
	BC_ASSERT_TRUE(call_with_params(marie, pauline, marie_params, pauline_params));

	LinphoneCall *marieCall = linphone_core_get_current_call(marie->lc);
	BC_ASSERT_PTR_NOT_NULL(marieCall);
	LinphoneCall *paulineCall = linphone_core_get_current_call(pauline->lc);
	BC_ASSERT_PTR_NOT_NULL(paulineCall);

	liblinphone_tester_check_rtcp(marie, pauline);

	LinphoneNatPolicy *marie_nat_policy = linphone_core_get_nat_policy(marie->lc);
	const bool_t marie_ice_enabled = linphone_nat_policy_ice_enabled(marie_nat_policy);
	LinphoneNatPolicy *pauline_nat_policy = linphone_core_get_nat_policy(pauline->lc);
	const bool_t pauline_ice_enabled = linphone_nat_policy_ice_enabled(pauline_nat_policy);

	bool capabilityNegotiationReinviteEnabled = linphone_call_params_is_capability_negotiation_reinvite_enabled(linphone_call_get_params(marieCall));
	bool sendReInvite = ((caller_cap_neg && callee_cap_neg && capabilityNegotiationReinviteEnabled) || (marie_ice_enabled && pauline_ice_enabled));
	int expectedStreamsRunning = 1 + ((sendReInvite) ? 1 : 0);

	BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneCallStreamsRunning, expectedStreamsRunning, int, "%d");
	BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallStreamsRunning, expectedStreamsRunning, int, "%d");

	// Check that encryption has not changed after sending update
	if (marieCall) {
		check_stream_encryption(marieCall);
		BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(marieCall)), expectedEncryption, int, "%i");
	}
	if (paulineCall) {
		check_stream_encryption(paulineCall);
		BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(paulineCall)), expectedEncryption, int, "%i");
	}

	// If capability negotiation is enabled on both sides, DTLS is chosen
	// Callee:
	// Optional encryptions: DTLS and ZRTP
	// Default: SRTP
	// Caller:
	// Optional encryptions: SRTP and DTLS
	// Default: SRTP if capability negotiation is disabled, DTLS otherwise
	stats marie_stat = marie->stat; 
	stats pauline_stat = pauline->stat; 
	LinphoneCallParams * params0 = linphone_core_create_call_params(pauline->lc, paulineCall);
	linphone_call_params_set_media_encryption (params0, encryption);
	linphone_call_params_enable_video(params0, TRUE);
	bctbx_list_t * pauline_call_enc0 = NULL;
	if (caller_cap_neg && callee_cap_neg) {
		expectedEncryption = LinphoneMediaEncryptionDTLS;
	}
	ms_message("Pauline changes encryption to %s", linphone_media_encryption_to_string(expectedEncryption));
	pauline_call_enc0 = bctbx_list_append(pauline_call_enc0, LINPHONE_INT_TO_PTR(LinphoneMediaEncryptionDTLS));
	pauline_call_enc0 = bctbx_list_append(pauline_call_enc0, LINPHONE_INT_TO_PTR(LinphoneMediaEncryptionZRTP));
	linphone_call_params_set_supported_encryptions (params0, pauline_call_enc0);
	bctbx_list_free(pauline_call_enc0);
	linphone_call_update(paulineCall, params0);
	linphone_call_params_unref(params0);
	BC_ASSERT_TRUE( wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallUpdating,(pauline_stat.number_of_LinphoneCallUpdating+1)));
	BC_ASSERT_TRUE( wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallUpdatedByRemote,(marie_stat.number_of_LinphoneCallUpdatedByRemote+1)));

	capabilityNegotiationReinviteEnabled = linphone_call_params_is_capability_negotiation_reinvite_enabled(linphone_call_get_params(paulineCall));
	sendReInvite = (caller_cap_neg && callee_cap_neg && capabilityNegotiationReinviteEnabled);
	expectedStreamsRunning = 1 + ((sendReInvite) ? 1 : 0);

	/*wait for reINVITEs to complete*/
	BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallStreamsRunning,(pauline_stat.number_of_LinphoneCallStreamsRunning+expectedStreamsRunning)));
	BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallStreamsRunning,(marie_stat.number_of_LinphoneCallStreamsRunning+expectedStreamsRunning)));

	if (pauline_ice_enabled && marie_ice_enabled) {
		BC_ASSERT_TRUE(check_ice(marie, pauline, LinphoneIceStateHostConnection));
		BC_ASSERT_TRUE(check_ice(pauline, marie, LinphoneIceStateHostConnection));
	}

	liblinphone_tester_set_next_video_frame_decoded_cb(marieCall);
	liblinphone_tester_set_next_video_frame_decoded_cb(paulineCall);

	BC_ASSERT_TRUE( wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_IframeDecoded,(pauline_stat.number_of_IframeDecoded+1)));
	BC_ASSERT_TRUE( wait_for(pauline->lc,marie->lc,&marie->stat.number_of_IframeDecoded,(marie_stat.number_of_IframeDecoded+1)));

	BC_ASSERT_TRUE(linphone_call_params_video_enabled(linphone_call_get_current_params(paulineCall)));
	BC_ASSERT_TRUE(linphone_call_params_video_enabled(linphone_call_get_current_params(marieCall)));

	BC_ASSERT_TRUE(linphone_call_log_video_enabled(linphone_call_get_call_log(paulineCall)));
	BC_ASSERT_TRUE(linphone_call_log_video_enabled(linphone_call_get_call_log(marieCall)));

	liblinphone_tester_check_rtcp(marie, pauline);

	// Check that encryption has not changed after sending update
	if (marieCall) {
		check_stream_encryption(marieCall);
		BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(marieCall)), expectedEncryption, int, "%i");
	}
	if (paulineCall) {
		check_stream_encryption(paulineCall);
		BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(paulineCall)), expectedEncryption, int, "%i");
	}

	BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneCallStreamsRunning, (pauline_stat.number_of_LinphoneCallStreamsRunning+expectedStreamsRunning), int, "%d");
	BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallStreamsRunning, (marie_stat.number_of_LinphoneCallStreamsRunning+expectedStreamsRunning), int, "%d");

	// If capability negotiation is enabled on both sides, DTLS is chosen
	// Callee:
	// Optional encryptions: DTLS and ZRTP
	// Default: SRTP
	// Caller:
	// Optional encryptions: ZRTP and DTLS
	// Default: SRTP if capability negotiation is disabled, DTLS otherwise
	marie_stat = marie->stat; 
	pauline_stat = pauline->stat; 
	LinphoneCallParams * params1 = linphone_core_create_call_params(marie->lc, marieCall);
	linphone_call_params_set_media_encryption (params1, marieEncryption);
	bctbx_list_t * marie_call_enc1 = NULL;
	if (caller_cap_neg && callee_cap_neg) {
		expectedEncryption = LinphoneMediaEncryptionZRTP;
	}
	ms_message("Marie changes encryption to %s", linphone_media_encryption_to_string(expectedEncryption));
	marie_call_enc1 = bctbx_list_append(marie_call_enc1, LINPHONE_INT_TO_PTR(LinphoneMediaEncryptionZRTP));
	marie_call_enc1 = bctbx_list_append(marie_call_enc1, LINPHONE_INT_TO_PTR(LinphoneMediaEncryptionDTLS));
	linphone_call_params_set_supported_encryptions (params1, marie_call_enc1);
	bctbx_list_free(marie_call_enc1);
	linphone_call_update(marieCall, params1);
	linphone_call_params_unref(params1);
	BC_ASSERT_TRUE( wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallUpdating,(marie_stat.number_of_LinphoneCallUpdating+1)));
	BC_ASSERT_TRUE( wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallUpdatedByRemote,(pauline_stat.number_of_LinphoneCallUpdatedByRemote+1)));

	capabilityNegotiationReinviteEnabled = linphone_call_params_is_capability_negotiation_reinvite_enabled(linphone_call_get_params(marieCall));
	sendReInvite = (caller_cap_neg && callee_cap_neg && capabilityNegotiationReinviteEnabled);
	expectedStreamsRunning = 1 + ((sendReInvite) ? 1 : 0);

	/*wait for reINVITEs to complete*/
	BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallStreamsRunning,(marie_stat.number_of_LinphoneCallStreamsRunning+expectedStreamsRunning)));
	BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallStreamsRunning,(pauline_stat.number_of_LinphoneCallStreamsRunning+expectedStreamsRunning)));

	liblinphone_tester_set_next_video_frame_decoded_cb(marieCall);
	liblinphone_tester_set_next_video_frame_decoded_cb(paulineCall);

	BC_ASSERT_TRUE( wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_IframeDecoded,(pauline_stat.number_of_IframeDecoded+1)));
	BC_ASSERT_TRUE( wait_for(pauline->lc,marie->lc,&marie->stat.number_of_IframeDecoded,(marie_stat.number_of_IframeDecoded+1)));

	BC_ASSERT_TRUE(linphone_call_params_video_enabled(linphone_call_get_current_params(paulineCall)));
	BC_ASSERT_TRUE(linphone_call_params_video_enabled(linphone_call_get_current_params(marieCall)));

	BC_ASSERT_TRUE(linphone_call_log_video_enabled(linphone_call_get_call_log(paulineCall)));
	BC_ASSERT_TRUE(linphone_call_log_video_enabled(linphone_call_get_call_log(marieCall)));

	if ((expectedEncryption == LinphoneMediaEncryptionDTLS) || (expectedEncryption == LinphoneMediaEncryptionZRTP)) {
		BC_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallEncryptedOn,marie_stat.number_of_LinphoneCallEncryptedOn+1,10000));
		BC_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallEncryptedOn,pauline_stat.number_of_LinphoneCallEncryptedOn+1,10000));
	}

	liblinphone_tester_check_rtcp(marie, pauline);

	// Check that encryption has not changed after sending update
	if (marieCall) {
		check_stream_encryption(marieCall);
		BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(marieCall)), expectedEncryption, int, "%i");
	}
	if (paulineCall) {
		check_stream_encryption(paulineCall);
		BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(paulineCall)), expectedEncryption, int, "%i");
	}

	BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneCallStreamsRunning, (pauline_stat.number_of_LinphoneCallStreamsRunning+expectedStreamsRunning), int, "%d");
	BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallStreamsRunning, (marie_stat.number_of_LinphoneCallStreamsRunning+expectedStreamsRunning), int, "%d");

	end_call(pauline, marie);

	linphone_call_params_unref(marie_params);
	linphone_call_params_unref(pauline_params);

	linphone_core_manager_destroy(marie);
	linphone_core_manager_destroy(pauline);
}

static void call_changes_enc_on_update_cap_neg_caller (void) {
	call_changes_enc_on_update_base (TRUE, FALSE, TRUE, TRUE);
}

static void call_changes_enc_on_update_cap_neg_callee (void) {
	call_changes_enc_on_update_base (FALSE, TRUE, TRUE, TRUE);
}

static void call_changes_enc_on_update_cap_neg_both_sides_with_reinvite (void) {
	call_changes_enc_on_update_base (TRUE, TRUE, TRUE, TRUE);
}

static void call_changes_enc_on_update_cap_neg_both_sides_without_reinvite (void) {
	call_changes_enc_on_update_base (TRUE, TRUE, FALSE, FALSE);
}

static void back_to_back_calls_cap_neg_base(bool_t enable_cap_neg_both_sides) {
	std::list<LinphoneMediaEncryption> marie_enc_list;
	marie_enc_list.push_back(LinphoneMediaEncryptionNone);

	encryption_params marie_enc_mgr_params;
	marie_enc_mgr_params.encryption = LinphoneMediaEncryptionZRTP;
	marie_enc_mgr_params.level = E_OPTIONAL;
	marie_enc_mgr_params.preferences = marie_enc_list;

	LinphoneCoreManager * marie = create_core_mgr_with_capability_negotiation_setup("marie_rc", marie_enc_mgr_params, TRUE, FALSE, TRUE);

	std::list<LinphoneMediaEncryption> pauline_enc_list;
	pauline_enc_list.push_back(LinphoneMediaEncryptionNone);

	encryption_params pauline_enc_mgr_params;
	pauline_enc_mgr_params.encryption = LinphoneMediaEncryptionSRTP;
	pauline_enc_mgr_params.level = E_OPTIONAL;
	pauline_enc_mgr_params.preferences = pauline_enc_list;

	LinphoneCoreManager * pauline = create_core_mgr_with_capability_negotiation_setup((transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"), pauline_enc_mgr_params, TRUE, FALSE, TRUE);

	LinphoneMediaEncryption encryption = LinphoneMediaEncryptionDTLS; // Expected encryption
	LinphoneCallParams *marie_params = linphone_core_create_call_params(marie->lc, NULL);
	linphone_call_params_enable_capability_negotiations (marie_params, 1);
	linphone_call_params_set_media_encryption(marie_params, encryption);
	bctbx_list_t * marie_call_enc = NULL;
	marie_call_enc = bctbx_list_append(marie_call_enc, LINPHONE_INT_TO_PTR(LinphoneMediaEncryptionSRTP));
	marie_call_enc = bctbx_list_append(marie_call_enc, LINPHONE_INT_TO_PTR(encryption));
	linphone_call_params_set_supported_encryptions (marie_params, marie_call_enc);
	bctbx_list_free(marie_call_enc);
	marie_call_enc = NULL;

	LinphoneCallParams *pauline_params = linphone_core_create_call_params(pauline->lc, NULL);
	linphone_call_params_enable_capability_negotiations (pauline_params, enable_cap_neg_both_sides);
	linphone_call_params_set_media_encryption(pauline_params, encryption);
	bctbx_list_t * pauline_call_enc = NULL;
	pauline_call_enc = bctbx_list_append(pauline_call_enc, LINPHONE_INT_TO_PTR(LinphoneMediaEncryptionZRTP));
	pauline_call_enc = bctbx_list_append(pauline_call_enc, LINPHONE_INT_TO_PTR(LinphoneMediaEncryptionNone));
	pauline_call_enc = bctbx_list_append(pauline_call_enc, LINPHONE_INT_TO_PTR(encryption));
	linphone_call_params_set_supported_encryptions (pauline_params, pauline_call_enc);
	bctbx_list_free(pauline_call_enc);
	pauline_call_enc = NULL;

	// TODO: Delete the following 2 lines when relying only on call params to check validity of SDP
	linphone_core_set_media_encryption(pauline->lc,encryption);
	linphone_core_set_media_encryption(marie->lc,encryption);

	// Caller (Marie) supports SRTP and DTLS as potential configurations and DTLS as default one
	// Callee (Pauline) supports ZRTP, no encryption and DTLS as potential configurations and DTLS as default one
	// DTLS is expected to be chosen
	encrypted_call_with_params_base(marie, pauline, encryption, marie_params, pauline_params, TRUE);
	if (linphone_core_get_current_call(marie->lc)) {
		end_call(marie, pauline);
	}

	encryption = LinphoneMediaEncryptionSRTP;
	if (marie_params) {
		linphone_call_params_unref(marie_params);
		marie_params = NULL;
	}
	marie_params = linphone_core_create_call_params(marie->lc, NULL);
	linphone_call_params_enable_capability_negotiations (marie_params, 1);
	linphone_call_params_set_media_encryption(marie_params, encryption);
	if (marie_call_enc) {
		bctbx_list_free(marie_call_enc);
		marie_call_enc = NULL;
	}
	marie_call_enc = bctbx_list_append(marie_call_enc, LINPHONE_INT_TO_PTR(LinphoneMediaEncryptionZRTP));
	marie_call_enc = bctbx_list_append(marie_call_enc, LINPHONE_INT_TO_PTR(encryption));
	linphone_call_params_set_supported_encryptions (marie_params, marie_call_enc);
	bctbx_list_free(marie_call_enc);
	marie_call_enc = NULL;

	if (pauline_params) {
		linphone_call_params_unref(pauline_params);
		pauline_params = NULL;
	}
	pauline_params = linphone_core_create_call_params(pauline->lc, NULL);
	linphone_call_params_enable_capability_negotiations (pauline_params, enable_cap_neg_both_sides);
	linphone_call_params_set_media_encryption(pauline_params, encryption);
	if (pauline_call_enc) {
		bctbx_list_free(pauline_call_enc);
		pauline_call_enc = NULL;
	}
	pauline_call_enc = bctbx_list_append(pauline_call_enc, LINPHONE_INT_TO_PTR(LinphoneMediaEncryptionDTLS));
	pauline_call_enc = bctbx_list_append(pauline_call_enc, LINPHONE_INT_TO_PTR(LinphoneMediaEncryptionNone));
	pauline_call_enc = bctbx_list_append(pauline_call_enc, LINPHONE_INT_TO_PTR(encryption));
	linphone_call_params_set_supported_encryptions (pauline_params, pauline_call_enc);
	bctbx_list_free(pauline_call_enc);
	pauline_call_enc = NULL;

	// TODO: Delete the following 2 lines when relying only on call params to check validity of SDP
	linphone_core_set_media_encryption(pauline->lc,encryption);
	linphone_core_set_media_encryption(marie->lc,encryption);

	// Caller (Pauline) supports DTLS, no encryption and SRTP as potential configurations and SRTP as default one
	// Callee (Marie) supports ZRTP and SRTP as potential configurations and SRTP as default one
	// DTLS is expected to be chosen
	encrypted_call_with_params_base(pauline, marie, encryption, marie_params, pauline_params, TRUE);
	if (linphone_core_get_current_call(pauline->lc)) {
		end_call(pauline, marie);
	}

	encryption = LinphoneMediaEncryptionZRTP;
	if (marie_params) {
		linphone_call_params_unref(marie_params);
		marie_params = NULL;
	}
	marie_params = linphone_core_create_call_params(marie->lc, NULL);
	linphone_call_params_enable_capability_negotiations (marie_params, 1);
	linphone_call_params_set_media_encryption(marie_params, encryption);
	if (marie_call_enc) {
		bctbx_list_free(marie_call_enc);
		marie_call_enc = NULL;
	}
	marie_call_enc = bctbx_list_append(marie_call_enc, LINPHONE_INT_TO_PTR(LinphoneMediaEncryptionNone));
	marie_call_enc = bctbx_list_append(marie_call_enc, LINPHONE_INT_TO_PTR(LinphoneMediaEncryptionZRTP));
	marie_call_enc = bctbx_list_append(marie_call_enc, LINPHONE_INT_TO_PTR(encryption));
	linphone_call_params_set_supported_encryptions (marie_params, marie_call_enc);
	bctbx_list_free(marie_call_enc);
	marie_call_enc = NULL;

	if (pauline_params) {
		linphone_call_params_unref(pauline_params);
		pauline_params = NULL;
	}
	pauline_params = linphone_core_create_call_params(pauline->lc, NULL);
	linphone_call_params_enable_capability_negotiations (pauline_params, enable_cap_neg_both_sides);
	linphone_call_params_set_media_encryption(pauline_params, encryption);
	if (pauline_call_enc) {
		bctbx_list_free(pauline_call_enc);
		pauline_call_enc = NULL;
	}
	pauline_call_enc = bctbx_list_append(pauline_call_enc, LINPHONE_INT_TO_PTR(LinphoneMediaEncryptionDTLS));
	pauline_call_enc = bctbx_list_append(pauline_call_enc, LINPHONE_INT_TO_PTR(encryption));
	linphone_call_params_set_supported_encryptions (pauline_params, pauline_call_enc);
	bctbx_list_free(pauline_call_enc);
	pauline_call_enc = NULL;

	// TODO: Delete the following 2 lines when relying only on call params to check validity of SDP
	linphone_core_set_media_encryption(pauline->lc,encryption);
	linphone_core_set_media_encryption(marie->lc,encryption);

	// Caller (Marie) supports SRTP, DTLS and ZRTP as potential configurations and ZRTP as default one
	// Callee (Pauline) supports no encryption and ZRTP as potential configurations and ZRTP as default one
	// DTLS is expected to be chosen
	encrypted_call_with_params_base(pauline, marie, encryption, marie_params, pauline_params, TRUE);
	if (linphone_core_get_current_call(pauline->lc)) {
		end_call(pauline, marie);
	}

	if (marie_call_enc) {
		bctbx_list_free(marie_call_enc);
		marie_call_enc = NULL;
	}
	if (pauline_call_enc) {
		bctbx_list_free(pauline_call_enc);
		pauline_call_enc = NULL;
	}
	if (marie_params) {
		linphone_call_params_unref(marie_params);
		marie_params = NULL;
	}
	if (pauline_params) {
		linphone_call_params_unref(pauline_params);
		pauline_params = NULL;
	}

	linphone_core_manager_destroy(marie);
	linphone_core_manager_destroy(pauline);

}

static void back_to_back_calls_cap_neg_one_side(void) {
	back_to_back_calls_cap_neg_base(FALSE);
}

static void back_to_back_calls_cap_neg_both_sides(void) {
	back_to_back_calls_cap_neg_base(TRUE);
}

static void call_with_update_and_incompatible_encs_in_call_params (void) {
	call_with_update_and_incompatible_encs_in_call_params_base (FALSE);
}

void call_with_encryption_supported_in_call_params_only_base(const LinphoneMediaEncryption encryption) {
	std::list<LinphoneMediaEncryption> marie_enc_list;
	if (encryption != LinphoneMediaEncryptionZRTP) {
		marie_enc_list.push_back(LinphoneMediaEncryptionZRTP);
	}
	if (encryption != LinphoneMediaEncryptionDTLS) {
		marie_enc_list.push_back(LinphoneMediaEncryptionDTLS);
	}
	if (encryption != LinphoneMediaEncryptionSRTP) {
		marie_enc_list.push_back(LinphoneMediaEncryptionSRTP);
	}
	if (encryption != LinphoneMediaEncryptionNone) {
		marie_enc_list.push_back(LinphoneMediaEncryptionNone);
	}

	encryption_params marie_enc_mgr_params;
	marie_enc_mgr_params.encryption = LinphoneMediaEncryptionNone;
	marie_enc_mgr_params.level = E_OPTIONAL;
	marie_enc_mgr_params.preferences = marie_enc_list;

	LinphoneCoreManager * marie = create_core_mgr_with_capability_negotiation_setup("marie_rc", marie_enc_mgr_params, TRUE, FALSE, FALSE);
	BC_ASSERT_FALSE(linphone_core_media_encryption_supported(marie->lc, encryption));

	std::list<LinphoneMediaEncryption> pauline_enc_list;
	if (encryption != LinphoneMediaEncryptionSRTP) {
		pauline_enc_list.push_back(LinphoneMediaEncryptionSRTP);
	}
	if (encryption != LinphoneMediaEncryptionZRTP) {
		pauline_enc_list.push_back(LinphoneMediaEncryptionZRTP);
	}
	if (encryption != LinphoneMediaEncryptionNone) {
		pauline_enc_list.push_back(LinphoneMediaEncryptionNone);
	}
	if (encryption != LinphoneMediaEncryptionDTLS) {
		pauline_enc_list.push_back(LinphoneMediaEncryptionDTLS);
	}

	encryption_params pauline_enc_mgr_params;
	pauline_enc_mgr_params.encryption = LinphoneMediaEncryptionNone;
	pauline_enc_mgr_params.level = E_OPTIONAL;
	pauline_enc_mgr_params.preferences = pauline_enc_list;

	LinphoneCoreManager * pauline = create_core_mgr_with_capability_negotiation_setup((transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"), pauline_enc_mgr_params, TRUE, FALSE, FALSE);
	BC_ASSERT_FALSE(linphone_core_media_encryption_supported(pauline->lc, encryption));

	bctbx_list_t * call_enc = NULL;
	call_enc = bctbx_list_append(call_enc, LINPHONE_INT_TO_PTR(encryption));

	LinphoneCallParams *marie_params = linphone_core_create_call_params(marie->lc, NULL);
	linphone_call_params_enable_capability_negotiations (marie_params, 1);
	linphone_call_params_set_supported_encryptions (marie_params, call_enc);
	LinphoneCallParams *pauline_params = linphone_core_create_call_params(pauline->lc, NULL);
	linphone_call_params_enable_capability_negotiations (pauline_params, 1);
	linphone_call_params_set_supported_encryptions (pauline_params, call_enc);

	bctbx_list_free(call_enc);

	BC_ASSERT_TRUE(call_with_params(marie, pauline, marie_params, pauline_params));

	LinphoneCall *marieCall = linphone_core_get_current_call(marie->lc);
	BC_ASSERT_PTR_NOT_NULL(marieCall);
	LinphoneCall *paulineCall = linphone_core_get_current_call(pauline->lc);
	BC_ASSERT_PTR_NOT_NULL(paulineCall);

	liblinphone_tester_check_rtcp(marie, pauline);

	const int expectedStreamsRunning = 2;
	BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneCallStreamsRunning, expectedStreamsRunning, int, "%i");
	BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallStreamsRunning, expectedStreamsRunning, int, "%i");

	if (marieCall) {
		check_stream_encryption(marieCall);
		BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(marieCall)), encryption, int, "%i");
	}
	if (paulineCall) {
		check_stream_encryption(paulineCall);
		BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(paulineCall)), encryption, int, "%i");
	}

	end_call(pauline, marie);

	linphone_call_params_unref(marie_params);
	linphone_call_params_unref(pauline_params);

	linphone_core_manager_destroy(marie);
	linphone_core_manager_destroy(pauline);

}

void call_with_default_encryption(const LinphoneMediaEncryption encryption) {

	std::list<LinphoneMediaEncryption> marie_enc_list;
	if (encryption != LinphoneMediaEncryptionZRTP) {
		marie_enc_list.push_back(LinphoneMediaEncryptionZRTP);
	}
	if (encryption != LinphoneMediaEncryptionDTLS) {
		marie_enc_list.push_back(LinphoneMediaEncryptionDTLS);
	}
	if (encryption != LinphoneMediaEncryptionSRTP) {
		marie_enc_list.push_back(LinphoneMediaEncryptionSRTP);
	}
	if (encryption != LinphoneMediaEncryptionNone) {
		marie_enc_list.push_back(LinphoneMediaEncryptionNone);
	}

	encryption_params marie_enc_mgr_params;
	marie_enc_mgr_params.encryption = LinphoneMediaEncryptionNone;
	marie_enc_mgr_params.level = E_OPTIONAL;
	marie_enc_mgr_params.preferences = marie_enc_list;

	LinphoneCoreManager * marie = create_core_mgr_with_capability_negotiation_setup("marie_rc", marie_enc_mgr_params, TRUE, FALSE, TRUE);
	BC_ASSERT_FALSE(linphone_core_media_encryption_supported(marie->lc, encryption));

	std::list<LinphoneMediaEncryption> pauline_enc_list;
	if (encryption != LinphoneMediaEncryptionSRTP) {
		pauline_enc_list.push_back(LinphoneMediaEncryptionSRTP);
	}
	if (encryption != LinphoneMediaEncryptionZRTP) {
		pauline_enc_list.push_back(LinphoneMediaEncryptionZRTP);
	}
	if (encryption != LinphoneMediaEncryptionNone) {
		pauline_enc_list.push_back(LinphoneMediaEncryptionNone);
	}
	if (encryption != LinphoneMediaEncryptionDTLS) {
		pauline_enc_list.push_back(LinphoneMediaEncryptionDTLS);
	}

	encryption_params pauline_enc_mgr_params;
	pauline_enc_mgr_params.encryption = LinphoneMediaEncryptionNone;
	pauline_enc_mgr_params.level = E_OPTIONAL;
	pauline_enc_mgr_params.preferences = pauline_enc_list;

	LinphoneCoreManager * pauline = create_core_mgr_with_capability_negotiation_setup((transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"), pauline_enc_mgr_params, TRUE, FALSE, TRUE);
	BC_ASSERT_FALSE(linphone_core_media_encryption_supported(pauline->lc, encryption));

	LinphoneCallParams *marie_params = linphone_core_create_call_params(marie->lc, NULL);
	linphone_call_params_enable_capability_negotiations (marie_params, 1);
	linphone_call_params_set_media_encryption(marie_params, encryption);
	LinphoneCallParams *pauline_params = linphone_core_create_call_params(pauline->lc, NULL);
	linphone_call_params_enable_capability_negotiations (pauline_params, 1);
	linphone_call_params_set_media_encryption(pauline_params, encryption);

	encrypted_call_with_params_base(marie, pauline, marie_enc_list.front(), marie_params, pauline_params, TRUE);
	if (linphone_core_get_current_call(marie->lc)) {
		end_call(marie, pauline);
	}

	linphone_call_params_unref(marie_params);
	linphone_call_params_unref(pauline_params);

	linphone_core_manager_destroy(marie);
	linphone_core_manager_destroy(pauline);

}

void call_with_potential_configuration_same_as_actual_configuration_base (const LinphoneMediaEncryption encryption) {
	LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
	linphone_core_enable_capability_negociation(marie->lc, 1);

	LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
	linphone_core_enable_capability_negociation(pauline->lc, 1);

	BC_ASSERT_TRUE(linphone_core_media_encryption_supported(pauline->lc,encryption));
	if (linphone_core_media_encryption_supported(pauline->lc,encryption)) {
		bctbx_list_t * encryption_list = NULL;
		encryption_list = bctbx_list_append(encryption_list, LINPHONE_INT_TO_PTR(encryption));
		linphone_core_set_media_encryption_mandatory(pauline->lc,0);
		linphone_core_set_media_encryption(pauline->lc,encryption);
		linphone_core_set_supported_media_encryptions(pauline->lc,encryption_list);
		BC_ASSERT_TRUE(linphone_core_is_media_encryption_supported(pauline->lc, encryption));
		if (encryption_list) {
			bctbx_list_free(encryption_list);
		}
	}

	linphone_core_set_media_encryption_mandatory(marie->lc,0);
	linphone_core_set_media_encryption(marie->lc,encryption);
	// Desired encryption is put last
	bctbx_list_t * encryption_list = create_confg_encryption_preference_list_from_param_preferences(set_encryption_preference_with_priority(encryption, true));
	linphone_core_set_supported_media_encryptions(marie->lc,encryption_list);
	if (encryption_list) {
		bctbx_list_free(encryption_list);
	}

	BC_ASSERT_TRUE(linphone_core_is_media_encryption_supported(marie->lc, encryption));
	BC_ASSERT_TRUE(linphone_core_get_media_encryption(marie->lc) == encryption);
	BC_ASSERT_TRUE(linphone_core_is_media_encryption_supported(pauline->lc, encryption));
	BC_ASSERT_TRUE(linphone_core_get_media_encryption(pauline->lc) == encryption);

	encrypted_call_base(marie, pauline, encryption, TRUE, TRUE, FALSE);
	if (linphone_core_get_current_call(marie->lc) && linphone_core_get_current_call(pauline->lc)) {
		end_call(marie, pauline);
	}

	linphone_core_manager_destroy(marie);
	linphone_core_manager_destroy(pauline);
}

static void unencrypted_call_with_potential_configuration_same_as_actual_configuration(void) {
	call_with_potential_configuration_same_as_actual_configuration_base(LinphoneMediaEncryptionNone);
}

void simple_call_with_capability_negotiations_removed_after_update(LinphoneCoreManager* caller, LinphoneCoreManager* callee, const LinphoneMediaEncryption optionalEncryption) {
	linphone_core_enable_capability_negociation(caller->lc, 1);
	linphone_core_enable_capability_negociation(callee->lc, 1);
	bctbx_list_t * encryption_list = NULL;
	encryption_list = bctbx_list_append(encryption_list, LINPHONE_INT_TO_PTR(optionalEncryption));

	BC_ASSERT_TRUE(linphone_core_media_encryption_supported(callee->lc,optionalEncryption));
	if (linphone_core_media_encryption_supported(callee->lc,optionalEncryption)) {
		linphone_core_set_media_encryption_mandatory(callee->lc,0);
		linphone_core_set_media_encryption(callee->lc,LinphoneMediaEncryptionNone);
		linphone_core_set_supported_media_encryptions(callee->lc,encryption_list);
		BC_ASSERT_TRUE(linphone_core_is_media_encryption_supported(callee->lc, optionalEncryption));
	}

	BC_ASSERT_TRUE(linphone_core_media_encryption_supported(caller->lc,optionalEncryption));
	if (linphone_core_media_encryption_supported(caller->lc,optionalEncryption)) {
		linphone_core_set_media_encryption_mandatory(caller->lc,0);
		linphone_core_set_media_encryption(caller->lc,LinphoneMediaEncryptionNone);
		linphone_core_set_supported_media_encryptions(caller->lc,encryption_list);
		BC_ASSERT_TRUE(linphone_core_is_media_encryption_supported(caller->lc, optionalEncryption));
	}

	if (encryption_list) {
		bctbx_list_free(encryption_list);
	}

	encrypted_call_base(caller, callee, optionalEncryption, TRUE, TRUE, FALSE);

	LinphoneCall *callerCall = linphone_core_get_current_call(caller->lc);
	BC_ASSERT_PTR_NOT_NULL(callerCall);
	LinphoneCall *calleeCall = linphone_core_get_current_call(callee->lc);
	BC_ASSERT_PTR_NOT_NULL(calleeCall);

	stats caller_stat = caller->stat; 
	stats callee_stat = callee->stat; 
	LinphoneCallParams * params0 = linphone_core_create_call_params(callee->lc, calleeCall);
	linphone_call_params_enable_capability_negotiations (params0, FALSE);
	linphone_call_update(calleeCall, params0);
	linphone_call_params_unref(params0);
	BC_ASSERT_TRUE( wait_for(callee->lc,caller->lc,&callee->stat.number_of_LinphoneCallUpdating,(callee_stat.number_of_LinphoneCallUpdating+1)));
	BC_ASSERT_TRUE( wait_for(callee->lc,caller->lc,&caller->stat.number_of_LinphoneCallUpdatedByRemote,(caller_stat.number_of_LinphoneCallUpdatedByRemote+1)));

	BC_ASSERT_TRUE( wait_for(callee->lc,caller->lc,&callee->stat.number_of_LinphoneCallStreamsRunning,(callee_stat.number_of_LinphoneCallStreamsRunning+1)));
	BC_ASSERT_TRUE( wait_for(callee->lc,caller->lc,&caller->stat.number_of_LinphoneCallStreamsRunning,(caller_stat.number_of_LinphoneCallStreamsRunning+1)));

	LinphoneMediaEncryption encryptionAfterUpdate = LinphoneMediaEncryptionNone;
	LinphoneMediaEncryption expectedEncryption =  LinphoneMediaEncryptionNone;
	bool dummyPotentialConfigurationChosen = false;
	get_expected_encryption_from_call_params(calleeCall, callerCall, &expectedEncryption, &dummyPotentialConfigurationChosen);
	int expectedStreamsRunning = 1;

	BC_ASSERT_EQUAL(callee->stat.number_of_LinphoneCallStreamsRunning, (callee_stat.number_of_LinphoneCallStreamsRunning+expectedStreamsRunning), int, "%d");
	BC_ASSERT_EQUAL(caller->stat.number_of_LinphoneCallStreamsRunning, (caller_stat.number_of_LinphoneCallStreamsRunning+expectedStreamsRunning), int, "%d");

	liblinphone_tester_check_rtcp(caller, callee);

	// Check that encryption has not changed after sending update
	BC_ASSERT_EQUAL(expectedEncryption, encryptionAfterUpdate, int, "%i");
	if (callerCall) {
		check_stream_encryption(callerCall);
		BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(callerCall)), expectedEncryption, int, "%i");
	}
	if (calleeCall) {
		check_stream_encryption(calleeCall);
		BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(calleeCall)), expectedEncryption, int, "%i");
	}

	wait_for_until(callee->lc, caller->lc, NULL, 5, 2000);

	caller_stat = caller->stat; 
	callee_stat = callee->stat; 
	LinphoneCallParams * params1 = linphone_core_create_call_params(caller->lc, callerCall);
	linphone_call_update(callerCall, params1);
	linphone_call_params_unref(params1);
	BC_ASSERT_TRUE( wait_for(callee->lc,caller->lc,&caller->stat.number_of_LinphoneCallUpdating,(caller_stat.number_of_LinphoneCallUpdating+1)));
	BC_ASSERT_TRUE( wait_for(callee->lc,caller->lc,&callee->stat.number_of_LinphoneCallUpdatedByRemote,(callee_stat.number_of_LinphoneCallUpdatedByRemote+1)));

	BC_ASSERT_TRUE( wait_for(callee->lc,caller->lc,&callee->stat.number_of_LinphoneCallStreamsRunning,(callee_stat.number_of_LinphoneCallStreamsRunning+1)));
	BC_ASSERT_TRUE( wait_for(callee->lc,caller->lc,&caller->stat.number_of_LinphoneCallStreamsRunning,(caller_stat.number_of_LinphoneCallStreamsRunning+1)));

	get_expected_encryption_from_call_params(calleeCall, callerCall, &expectedEncryption, &dummyPotentialConfigurationChosen);

	liblinphone_tester_check_rtcp(caller, callee);

	// Check that encryption has not changed after sending update
	BC_ASSERT_EQUAL(expectedEncryption, encryptionAfterUpdate, int, "%i");
	if (callerCall) {
		check_stream_encryption(callerCall);
		BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(callerCall)), expectedEncryption, int, "%i");
	}
	if (calleeCall) {
		check_stream_encryption(calleeCall);
		BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(calleeCall)), expectedEncryption, int, "%i");
	}

	wait_for_until(callee->lc, caller->lc, NULL, 5, 2000);

	BC_ASSERT_EQUAL(callee->stat.number_of_LinphoneCallStreamsRunning, (callee_stat.number_of_LinphoneCallStreamsRunning+expectedStreamsRunning), int, "%d");
	BC_ASSERT_EQUAL(caller->stat.number_of_LinphoneCallStreamsRunning, (caller_stat.number_of_LinphoneCallStreamsRunning+expectedStreamsRunning), int, "%d");

	if (callerCall && calleeCall) {
		end_call(caller, callee);
	}
}

void simple_call_with_capability_negotiations(LinphoneCoreManager* caller, LinphoneCoreManager* callee, const LinphoneMediaEncryption optionalEncryption, const LinphoneMediaEncryption expectedEncryption) {
	linphone_core_enable_capability_negociation(caller->lc, 1);
	linphone_core_enable_capability_negociation(callee->lc, 1);
	bctbx_list_t * encryption_list = NULL;
	encryption_list = bctbx_list_append(encryption_list, LINPHONE_INT_TO_PTR(optionalEncryption));

	BC_ASSERT_TRUE(linphone_core_media_encryption_supported(callee->lc,optionalEncryption));
	if (linphone_core_media_encryption_supported(callee->lc,optionalEncryption)) {
		linphone_core_set_media_encryption_mandatory(callee->lc,0);
		linphone_core_set_media_encryption(callee->lc,LinphoneMediaEncryptionNone);
		linphone_core_set_supported_media_encryptions(callee->lc,encryption_list);
		BC_ASSERT_TRUE(linphone_core_is_media_encryption_supported(callee->lc, optionalEncryption));
	}

	BC_ASSERT_TRUE(linphone_core_media_encryption_supported(caller->lc,optionalEncryption));
	if (linphone_core_media_encryption_supported(caller->lc,optionalEncryption)) {
		linphone_core_set_media_encryption_mandatory(caller->lc,0);
		linphone_core_set_media_encryption(caller->lc,LinphoneMediaEncryptionNone);
		linphone_core_set_supported_media_encryptions(caller->lc,encryption_list);
		BC_ASSERT_TRUE(linphone_core_is_media_encryption_supported(caller->lc, optionalEncryption));
	}

	if (encryption_list) {
		bctbx_list_free(encryption_list);
	}

	encrypted_call_base(caller, callee, expectedEncryption, TRUE, TRUE, FALSE);
	pause_resume_calls(caller, callee);

	if (linphone_core_get_current_call(caller->lc) && linphone_core_get_current_call(callee->lc)) {
		end_call(caller, callee);
	}
}

static void call_with_no_sdp_cap_neg_on_caller(void) {
	LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
	linphone_core_enable_sdp_200_ack(marie->lc,TRUE);
	LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
	simple_call_with_capability_negotiations(marie, pauline, LinphoneMediaEncryptionSRTP, LinphoneMediaEncryptionSRTP);
	linphone_core_manager_destroy(marie);
	linphone_core_manager_destroy(pauline);
}

static void call_with_no_sdp_cap_neg_on_callee(void) {
	LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
	LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
	linphone_core_enable_sdp_200_ack(pauline->lc,TRUE);
	simple_call_with_capability_negotiations(marie, pauline, LinphoneMediaEncryptionSRTP, LinphoneMediaEncryptionSRTP);
	linphone_core_manager_destroy(marie);
	linphone_core_manager_destroy(pauline);
}

static void call_with_no_sdp_cap_neg_on_both_sides(void) {
	LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
	linphone_core_enable_sdp_200_ack(marie->lc,TRUE);
	LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
	linphone_core_enable_sdp_200_ack(pauline->lc,TRUE);
	simple_call_with_capability_negotiations(marie, pauline, LinphoneMediaEncryptionSRTP, LinphoneMediaEncryptionSRTP);
	linphone_core_manager_destroy(marie);
	linphone_core_manager_destroy(pauline);
}

static void call_with_avpf_and_cap_neg_on_caller(void) {
	LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
	linphone_core_set_avpf_mode(marie->lc, LinphoneAVPFEnabled);
	LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
	simple_call_with_capability_negotiations(marie, pauline, LinphoneMediaEncryptionSRTP, LinphoneMediaEncryptionSRTP);
	linphone_core_manager_destroy(marie);
	linphone_core_manager_destroy(pauline);
}

static void call_with_avpf_and_cap_neg_on_callee(void) {
	LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
	LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
	linphone_core_set_avpf_mode(pauline->lc, LinphoneAVPFEnabled);
	simple_call_with_capability_negotiations(marie, pauline, LinphoneMediaEncryptionSRTP, LinphoneMediaEncryptionSRTP);
	linphone_core_manager_destroy(marie);
	linphone_core_manager_destroy(pauline);
}

static void call_with_avpf_and_cap_neg_on_both_sides(void) {
	LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
	linphone_core_set_avpf_mode(marie->lc, LinphoneAVPFEnabled);
	LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
	linphone_core_enable_sdp_200_ack(pauline->lc,TRUE);
	linphone_core_set_avpf_mode(pauline->lc, LinphoneAVPFEnabled);
	simple_call_with_capability_negotiations(marie, pauline, LinphoneMediaEncryptionSRTP, LinphoneMediaEncryptionSRTP);
	linphone_core_manager_destroy(marie);
	linphone_core_manager_destroy(pauline);
}

void simple_call_with_capability_negotiations_with_different_encryption_after_resume(LinphoneCoreManager* caller, LinphoneCoreManager* callee, const LinphoneMediaEncryption optionalEncryption, const LinphoneMediaEncryption encryptionAfterResume) {
	linphone_core_enable_capability_negociation(caller->lc, 1);
	linphone_core_enable_capability_negociation(callee->lc, 1);
	bctbx_list_t * encryption_list = NULL;
	encryption_list = bctbx_list_append(encryption_list, LINPHONE_INT_TO_PTR(optionalEncryption));

	BC_ASSERT_TRUE(linphone_core_media_encryption_supported(callee->lc,optionalEncryption));
	if (linphone_core_media_encryption_supported(callee->lc,optionalEncryption)) {
		linphone_core_set_media_encryption_mandatory(callee->lc,0);
		linphone_core_set_media_encryption(callee->lc,encryptionAfterResume);
		linphone_core_set_supported_media_encryptions(callee->lc,encryption_list);
		BC_ASSERT_TRUE(linphone_core_is_media_encryption_supported(callee->lc, optionalEncryption));
	}


	BC_ASSERT_TRUE(linphone_core_media_encryption_supported(caller->lc,optionalEncryption));
	if (linphone_core_media_encryption_supported(caller->lc,optionalEncryption)) {
		linphone_core_set_media_encryption_mandatory(caller->lc,0);
		if (optionalEncryption == LinphoneMediaEncryptionZRTP) {
			linphone_core_set_media_encryption(caller->lc,(encryptionAfterResume == LinphoneMediaEncryptionDTLS) ? LinphoneMediaEncryptionSRTP : LinphoneMediaEncryptionDTLS);
		} else {
			linphone_core_set_media_encryption(caller->lc,LinphoneMediaEncryptionNone);
		}
		linphone_core_set_supported_media_encryptions(caller->lc,encryption_list);
		BC_ASSERT_TRUE(linphone_core_is_media_encryption_supported(caller->lc, optionalEncryption));
	}

	if (encryption_list) {
		bctbx_list_free(encryption_list);
		encryption_list = NULL;
	}

	encrypted_call_base(caller, callee, optionalEncryption, TRUE, TRUE, FALSE);

	LinphoneCall * callerCall = linphone_core_get_current_call(caller->lc);
	BC_ASSERT_PTR_NOT_NULL(callerCall);
	LinphoneCall * calleeCall = linphone_core_get_current_call(callee->lc);
	BC_ASSERT_PTR_NOT_NULL(calleeCall);

	if (calleeCall && callerCall) {

		// Pause callee call
		BC_ASSERT_TRUE(pause_call_1(callee,calleeCall,caller,callerCall));
		wait_for_until(callee->lc, caller->lc, NULL, 5, 10000);

		// Resume callee call
		reset_counters(&caller->stat);
		reset_counters(&callee->stat);
		stats caller_stat = caller->stat;
		stats callee_stat = callee->stat;

		// Update call params before resuming call
		LinphoneCallParams * callerParams = linphone_core_create_call_params(caller->lc, callerCall);
		encryption_list = bctbx_list_append(NULL, LINPHONE_INT_TO_PTR(encryptionAfterResume));
		linphone_call_params_set_supported_encryptions(callerParams,encryption_list);
		if (encryption_list) {
			bctbx_list_free(encryption_list);
			encryption_list = NULL;
		}
		L_GET_PRIVATE(std::static_pointer_cast<LinphonePrivate::MediaSession>(LinphonePrivate::Call::toCpp(callerCall)->getActiveSession()))->setParams(new LinphonePrivate::MediaSessionParams(*L_GET_CPP_PTR_FROM_C_OBJECT(callerParams)));
		linphone_call_params_unref(callerParams);
		linphone_call_resume(calleeCall);
		LinphoneMediaEncryption encryption =  LinphoneMediaEncryptionNone;
		BC_ASSERT_TRUE(wait_for(callee->lc,caller->lc,&callee->stat.number_of_LinphoneCallResuming,callee_stat.number_of_LinphoneCallResuming+1));
		if (encryptionAfterResume == optionalEncryption) {
			BC_ASSERT_TRUE(wait_for(callee->lc,caller->lc,&callee->stat.number_of_LinphoneCallStreamsRunning,callee_stat.number_of_LinphoneCallStreamsRunning + 1));
			BC_ASSERT_TRUE(wait_for(callee->lc,caller->lc,&caller->stat.number_of_LinphoneCallStreamsRunning,caller_stat.number_of_LinphoneCallStreamsRunning + 1));

			bool potentialConfigurationChosen = false;

			get_expected_encryption_from_call_params(calleeCall, callerCall, &encryption, &potentialConfigurationChosen);

			int expectedStreamsRunning = 1 + ((potentialConfigurationChosen) ? 1 : 0);

			/*wait for reINVITEs to complete*/
			BC_ASSERT_TRUE(wait_for(caller->lc,callee->lc,&caller->stat.number_of_LinphoneCallStreamsRunning,(caller_stat.number_of_LinphoneCallStreamsRunning+expectedStreamsRunning)));
			BC_ASSERT_TRUE(wait_for(caller->lc,callee->lc,&callee->stat.number_of_LinphoneCallStreamsRunning,(callee_stat.number_of_LinphoneCallStreamsRunning+expectedStreamsRunning)));

			BC_ASSERT_EQUAL(encryptionAfterResume, encryption, int, "%i");

			wait_for_until(callee->lc, caller->lc, NULL, 5, 10000);

			liblinphone_tester_check_rtcp(caller, callee);

			BC_ASSERT_GREATER(linphone_core_manager_get_max_audio_down_bw(caller),70,int,"%i");
			LinphoneCallStats *calleeStats = linphone_call_get_audio_stats(linphone_core_get_current_call(callee->lc));
			BC_ASSERT_GREATER((int)linphone_call_stats_get_download_bandwidth(calleeStats),70,int,"%i");
			linphone_call_stats_unref(calleeStats);
			calleeStats = NULL;

			if ((encryption == LinphoneMediaEncryptionDTLS) || (encryption == LinphoneMediaEncryptionZRTP)) {
				BC_ASSERT_TRUE(wait_for_until(caller->lc,callee->lc,&caller->stat.number_of_LinphoneCallEncryptedOn,caller_stat.number_of_LinphoneCallEncryptedOn+1,10000));
				BC_ASSERT_TRUE(wait_for_until(caller->lc,callee->lc,&callee->stat.number_of_LinphoneCallEncryptedOn,callee_stat.number_of_LinphoneCallEncryptedOn+1,10000));
			}

		} else {
			encryption = optionalEncryption;
			// Resume fails because requested encryption is not supported
			BC_ASSERT_TRUE(wait_for(callee->lc,caller->lc,&callee->stat.number_of_LinphoneCallPaused,callee_stat.number_of_LinphoneCallPaused+1));

			wait_for_until(callee->lc, caller->lc, NULL, 5, 10000);

			BC_ASSERT_LOWER(caller->stat.number_of_rtcp_received, 5, int, "%d");
			BC_ASSERT_LOWER(callee->stat.number_of_rtcp_received, 5, int, "%d");

			BC_ASSERT_GREATER(linphone_core_manager_get_max_audio_down_bw(caller),0,int,"%i");
			LinphoneCall * calleeCall2 = linphone_core_get_current_call(callee->lc);
			BC_ASSERT_PTR_NOT_NULL(calleeCall2);
			if (calleeCall2) {
				LinphoneCallStats *calleeStats = linphone_call_get_audio_stats(calleeCall2);
				BC_ASSERT_EQUAL((int)linphone_call_stats_get_download_bandwidth(calleeStats),0,int,"%d");
				linphone_call_stats_unref(calleeStats);
				calleeStats = NULL;
			}

		}

		if (calleeCall) {
			check_stream_encryption(calleeCall);
			BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(calleeCall)), encryption, int, "%i");
		}
		if (callerCall) {
			check_stream_encryption(callerCall);
			BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(callerCall)), encryption, int, "%i");
		}

		/*since RTCP streams are reset when call is paused/resumed, there should be no loss at all*/
		const rtp_stats_t * stats = rtp_session_get_stats(linphone_call_get_stream(calleeCall, LinphoneStreamTypeAudio)->sessions.rtp_session);
		BC_ASSERT_LOWER((int)stats->cum_packet_loss, 7, int, "%d");

		end_call(caller, callee);
	}

}

void simple_call_with_capability_negotiations_with_resume_and_media_change_base(LinphoneCoreManager* caller, LinphoneCoreManager* callee, const LinphoneMediaEncryption optionalEncryption, const LinphoneMediaEncryption encryptionAfterResume) {
	linphone_core_enable_capability_negociation(caller->lc, 1);
	linphone_core_enable_capability_negociation(callee->lc, 1);
	bctbx_list_t * encryption_list = NULL;
	encryption_list = bctbx_list_append(encryption_list, LINPHONE_INT_TO_PTR(optionalEncryption));

	BC_ASSERT_TRUE(linphone_core_media_encryption_supported(callee->lc,optionalEncryption));
	if (linphone_core_media_encryption_supported(callee->lc,optionalEncryption)) {
		linphone_core_set_media_encryption_mandatory(callee->lc,0);
		linphone_core_set_media_encryption(callee->lc,encryptionAfterResume);
		linphone_core_set_supported_media_encryptions(callee->lc,encryption_list);
		BC_ASSERT_TRUE(linphone_core_is_media_encryption_supported(callee->lc, optionalEncryption));
	}

	BC_ASSERT_TRUE(linphone_core_media_encryption_supported(caller->lc,optionalEncryption));
	if (linphone_core_media_encryption_supported(caller->lc,optionalEncryption)) {
		linphone_core_set_media_encryption_mandatory(caller->lc,0);
		linphone_core_set_media_encryption(caller->lc,LinphoneMediaEncryptionNone);
		linphone_core_set_supported_media_encryptions(caller->lc,encryption_list);
		BC_ASSERT_TRUE(linphone_core_is_media_encryption_supported(caller->lc, optionalEncryption));
	}

	if (encryption_list) {
		bctbx_list_free(encryption_list);
		encryption_list = NULL;
	}

	encrypted_call_base(caller, callee, optionalEncryption, TRUE, TRUE, FALSE);

	LinphoneCall * callerCall = linphone_core_get_current_call(caller->lc);
	BC_ASSERT_PTR_NOT_NULL(callerCall);
	LinphoneCall * calleeCall = linphone_core_get_current_call(callee->lc);
	BC_ASSERT_PTR_NOT_NULL(calleeCall);

	if (calleeCall && callerCall) {

		// Pause callee call
		BC_ASSERT_TRUE(pause_call_1(callee,calleeCall,caller,callerCall));
		wait_for_until(callee->lc, caller->lc, NULL, 5, 10000);

		// Resume callee call
		reset_counters(&caller->stat);
		reset_counters(&callee->stat);
		stats caller_stat = caller->stat;
		stats callee_stat = callee->stat;

		linphone_call_resume(calleeCall);
		BC_ASSERT_TRUE(wait_for(callee->lc,caller->lc,&callee->stat.number_of_LinphoneCallResuming,callee_stat.number_of_LinphoneCallResuming+1));
		BC_ASSERT_TRUE(wait_for(callee->lc,caller->lc,&callee->stat.number_of_LinphoneCallStreamsRunning,callee_stat.number_of_LinphoneCallStreamsRunning + 1));
		BC_ASSERT_TRUE(wait_for(callee->lc,caller->lc,&caller->stat.number_of_LinphoneCallStreamsRunning,caller_stat.number_of_LinphoneCallStreamsRunning + 1));

		caller_stat = caller->stat;
		callee_stat = callee->stat;

		LinphoneCallParams * callerParams = linphone_core_create_call_params(caller->lc, callerCall);
		encryption_list = bctbx_list_append(NULL, LINPHONE_INT_TO_PTR(encryptionAfterResume));
		linphone_call_params_set_supported_encryptions(callerParams,encryption_list);
		if (encryption_list) {
			bctbx_list_free(encryption_list);
			encryption_list = NULL;
		}
		linphone_call_update(callerCall, callerParams);
		linphone_call_params_unref(callerParams);
		BC_ASSERT_TRUE( wait_for(callee->lc,caller->lc,&caller->stat.number_of_LinphoneCallUpdating,(caller_stat.number_of_LinphoneCallUpdating+1)));
		BC_ASSERT_TRUE( wait_for(callee->lc,caller->lc,&callee->stat.number_of_LinphoneCallUpdatedByRemote,(callee_stat.number_of_LinphoneCallUpdatedByRemote+1)));

		BC_ASSERT_TRUE( wait_for(callee->lc,caller->lc,&callee->stat.number_of_LinphoneCallStreamsRunning,(callee_stat.number_of_LinphoneCallStreamsRunning+1)));
		BC_ASSERT_TRUE( wait_for(callee->lc,caller->lc,&caller->stat.number_of_LinphoneCallStreamsRunning,(caller_stat.number_of_LinphoneCallStreamsRunning+1)));

		bool potentialConfigurationChosen = false;
		LinphoneMediaEncryption encryption =  LinphoneMediaEncryptionNone;
		get_expected_encryption_from_call_params(calleeCall, callerCall, &encryption, &potentialConfigurationChosen);

		int expectedStreamsRunning = 1 + ((potentialConfigurationChosen) ? 1 : 0);

		/*wait for reINVITEs to complete*/
		BC_ASSERT_TRUE(wait_for(caller->lc,callee->lc,&caller->stat.number_of_LinphoneCallStreamsRunning,(caller_stat.number_of_LinphoneCallStreamsRunning+expectedStreamsRunning)));
		BC_ASSERT_TRUE(wait_for(caller->lc,callee->lc,&callee->stat.number_of_LinphoneCallStreamsRunning,(callee_stat.number_of_LinphoneCallStreamsRunning+expectedStreamsRunning)));

		BC_ASSERT_EQUAL(encryptionAfterResume, encryption, int, "%i");

		wait_for_until(callee->lc, caller->lc, NULL, 5, 10000);

		liblinphone_tester_check_rtcp(caller, callee);

		BC_ASSERT_GREATER(linphone_core_manager_get_max_audio_down_bw(caller),70,int,"%i");
		LinphoneCallStats *calleeStats = linphone_call_get_audio_stats(linphone_core_get_current_call(callee->lc));
		BC_ASSERT_GREATER((int)linphone_call_stats_get_download_bandwidth(calleeStats),70,int,"%i");
		linphone_call_stats_unref(calleeStats);
		calleeStats = NULL;

		BC_ASSERT_EQUAL(encryptionAfterResume, encryption, int, "%i");
		if (calleeCall) {
			check_stream_encryption(calleeCall);
			BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(calleeCall)), encryption, int, "%i");
		}
		if (callerCall) {
			check_stream_encryption(callerCall);
			BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(callerCall)), encryption, int, "%i");
		}

		/*since RTCP streams are reset when call is paused/resumed, there should be no loss at all*/
		const rtp_stats_t * stats = rtp_session_get_stats(linphone_call_get_stream(calleeCall, LinphoneStreamTypeAudio)->sessions.rtp_session);
		BC_ASSERT_LOWER((int)stats->cum_packet_loss, 10, int, "%d");

		end_call(caller, callee);
	}

}

static void call_with_no_encryption(void) {
	encryption_params marie_enc_params;
	marie_enc_params.encryption = LinphoneMediaEncryptionNone;
	marie_enc_params.level = E_DISABLED;

	encryption_params pauline_enc_params;
	pauline_enc_params.encryption = LinphoneMediaEncryptionNone;
	pauline_enc_params.level = E_DISABLED;
	call_with_encryption_test_base(marie_enc_params, FALSE, FALSE, pauline_enc_params, FALSE, FALSE, FALSE);
}

void call_with_mandatory_encryption_base(const LinphoneMediaEncryption encryption, const bool_t caller_capability_negotiation, const bool_t callee_capability_negotiation) {
	encryption_params marie_enc_params;
	marie_enc_params.encryption = encryption;
	marie_enc_params.level = E_MANDATORY;

	encryption_params pauline_enc_params;
	pauline_enc_params.encryption = encryption;
	pauline_enc_params.level = E_MANDATORY;
	call_with_encryption_test_base(marie_enc_params, caller_capability_negotiation, FALSE, pauline_enc_params, callee_capability_negotiation, FALSE, FALSE);
}

void call_from_opt_enc_to_enc_base(const LinphoneMediaEncryption encryption, bool_t opt_enc_to_enc) {
	encryption_params optional_enc_mgr_params;
	// Avoid setting the actual configuration with the same encryption as the desired one
	if (encryption == LinphoneMediaEncryptionSRTP) {
		optional_enc_mgr_params.encryption = LinphoneMediaEncryptionDTLS;
	} else {
		optional_enc_mgr_params.encryption = LinphoneMediaEncryptionSRTP;
	}
	optional_enc_mgr_params.level = E_OPTIONAL;
	optional_enc_mgr_params.preferences = set_encryption_preference(TRUE);

	encryption_params mandatory_enc_mgr_params;
	mandatory_enc_mgr_params.encryption = encryption;
	mandatory_enc_mgr_params.level = E_MANDATORY;
	if (opt_enc_to_enc) {
		call_with_encryption_test_base(optional_enc_mgr_params, TRUE, FALSE, mandatory_enc_mgr_params, TRUE, FALSE, FALSE);
	} else {
		call_with_encryption_test_base(mandatory_enc_mgr_params, TRUE, FALSE, optional_enc_mgr_params, TRUE, FALSE, FALSE);
	}
}

void call_from_opt_enc_to_none_base(const LinphoneMediaEncryption encryption, bool_t opt_enc_to_none, const bool_t enable_video) {
	encryption_params no_enc_mgr_params;
	no_enc_mgr_params.encryption = LinphoneMediaEncryptionNone;
	no_enc_mgr_params.level = E_DISABLED;

	encryption_params enc_mgr_params;
	enc_mgr_params.encryption = LinphoneMediaEncryptionNone;
	enc_mgr_params.level = E_OPTIONAL;
	enc_mgr_params.preferences = set_encryption_preference_with_priority(encryption, false);
	if (opt_enc_to_none) {
		call_with_encryption_test_base(enc_mgr_params, TRUE, FALSE, no_enc_mgr_params, FALSE, FALSE, enable_video);
	} else {
		call_with_encryption_test_base(no_enc_mgr_params, FALSE, FALSE, enc_mgr_params, TRUE, FALSE, enable_video);
	}
}

void call_with_optional_encryption_on_both_sides_base(const LinphoneMediaEncryption encryption, const bool_t enable_video) {
	encryption_params marie_enc_params;
	// Avoid setting the actual configuration with the same encryption as the desired one
	if (encryption == LinphoneMediaEncryptionSRTP) {
		marie_enc_params.encryption = LinphoneMediaEncryptionDTLS;
	} else {
		marie_enc_params.encryption = LinphoneMediaEncryptionSRTP;
	}
	marie_enc_params.level = E_OPTIONAL;
	marie_enc_params.preferences = set_encryption_preference_with_priority(encryption, false);

	encryption_params pauline_enc_params;
	pauline_enc_params.encryption = encryption;
	pauline_enc_params.level = E_OPTIONAL;
	pauline_enc_params.preferences = set_encryption_preference_with_priority(encryption, true);

	call_with_encryption_test_base(marie_enc_params, TRUE, FALSE, pauline_enc_params, TRUE, FALSE, enable_video);
}

void call_with_toggling_encryption_base(const LinphoneMediaEncryption encryption) {
#if 0
	std::list<LinphoneMediaEncryption> enc_list {encryption};

	encryption_params marie_enc_params;
	marie_enc_params.encryption = LinphoneMediaEncryptionNone;
	marie_enc_params.level = E_OPTIONAL;
	marie_enc_params.preferences = enc_list;

	encryption_params pauline_enc_params;
	pauline_enc_params.encryption = LinphoneMediaEncryptionNone;
	pauline_enc_params.level = E_OPTIONAL;
	pauline_enc_params.preferences = enc_list;

	LinphoneCoreManager * marie = create_core_mgr_with_capability_negotiation_setup("marie_rc", marie_enc_params, TRUE, FALSE, TRUE);
	LinphoneCoreManager * pauline = create_core_mgr_with_capability_negotiation_setup((transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"), pauline_enc_params, TRUE, FALSE, TRUE);

	encrypted_call_base(marie, pauline, encryption, TRUE, TRUE, TRUE);

	LinphoneCall *marieCall = linphone_core_get_current_call(marie->lc);
	BC_ASSERT_PTR_NOT_NULL(marieCall);
	LinphoneCall *paulineCall = linphone_core_get_current_call(pauline->lc);
	BC_ASSERT_PTR_NOT_NULL(paulineCall);

	if (marieCall && paulineCall) {
		stats marie_stat = marie->stat;
		stats pauline_stat = pauline->stat;
		LinphoneCallParams * params0 = linphone_core_create_call_params(pauline->lc, paulineCall);
		bctbx_list_t * encs0 = NULL;
		encs0 = bctbx_list_append(encs0, LINPHONE_INT_TO_PTR(LinphoneMediaEncryptionNone));
		linphone_call_params_set_supported_encryptions (params0, encs0);
		bctbx_list_free(encs0);

		linphone_call_update(paulineCall, params0);
		linphone_call_params_unref(params0);
		BC_ASSERT_TRUE( wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallUpdating,(pauline_stat.number_of_LinphoneCallUpdating+1)));
		BC_ASSERT_TRUE( wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallUpdatedByRemote,(marie_stat.number_of_LinphoneCallUpdatedByRemote+1)));

		BC_ASSERT_TRUE( wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallStreamsRunning,(pauline_stat.number_of_LinphoneCallStreamsRunning+1)));
		BC_ASSERT_TRUE( wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallStreamsRunning,(marie_stat.number_of_LinphoneCallStreamsRunning+1)));

		LinphoneMediaEncryption encryptionAfterUpdate = LinphoneMediaEncryptionNone;
		LinphoneMediaEncryption expectedEncryption =  LinphoneMediaEncryptionNone;
		bool potentialConfigurationChosen = false;
		get_expected_encryption_from_call_params(paulineCall, marieCall, &expectedEncryption, &potentialConfigurationChosen);
		BC_ASSERT_FALSE(potentialConfigurationChosen);
		int expectedStreamsRunning = 1;

		/*wait for reINVITEs to complete*/
		BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallStreamsRunning,(pauline_stat.number_of_LinphoneCallStreamsRunning+expectedStreamsRunning)));
		BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallStreamsRunning,(marie_stat.number_of_LinphoneCallStreamsRunning+expectedStreamsRunning)));

		liblinphone_tester_check_rtcp(marie, pauline);

		wait_for_until(marie->lc, pauline->lc, NULL, 5, 2000);

		// Check that encryption has not changed after sending update
		BC_ASSERT_EQUAL(expectedEncryption, encryptionAfterUpdate, int, "%i");
		if (marieCall) {
			check_stream_encryption(marieCall);
			BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(marieCall)), expectedEncryption, int, "%i");
		}
		if (paulineCall) {
			check_stream_encryption(paulineCall);
			BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(paulineCall)), expectedEncryption, int, "%i");
		}

		BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneCallStreamsRunning, (pauline_stat.number_of_LinphoneCallStreamsRunning+expectedStreamsRunning), int, "%d");
		BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallStreamsRunning, (marie_stat.number_of_LinphoneCallStreamsRunning+expectedStreamsRunning), int, "%d");

		pause_resume_calls(marie, pauline);

		marie_stat = marie->stat;
		pauline_stat = pauline->stat;

		LinphoneCallParams * params1 = linphone_core_create_call_params(pauline->lc, paulineCall);
		bctbx_list_t * encs1 = NULL;
		encs1 = bctbx_list_append(encs1, LINPHONE_INT_TO_PTR(encryption));
		linphone_call_params_set_supported_encryptions (params1, encs1);
		bctbx_list_free(encs1);

		linphone_call_update(paulineCall, params1);
		linphone_call_params_unref(params1);
		BC_ASSERT_TRUE( wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallUpdating,(pauline_stat.number_of_LinphoneCallUpdating+1)));
		BC_ASSERT_TRUE( wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallUpdatedByRemote,(marie_stat.number_of_LinphoneCallUpdatedByRemote+1)));

		BC_ASSERT_TRUE( wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallStreamsRunning,(pauline_stat.number_of_LinphoneCallStreamsRunning+1)));
		BC_ASSERT_TRUE( wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallStreamsRunning,(marie_stat.number_of_LinphoneCallStreamsRunning+1)));

		encryptionAfterUpdate = encryption;
		get_expected_encryption_from_call_params(paulineCall, marieCall, &expectedEncryption, &potentialConfigurationChosen);
		BC_ASSERT_TRUE(potentialConfigurationChosen);
		bool_t capabilityNegotiationReinviteEnabled = linphone_call_params_is_capability_negotiation_reinvite_enabled(linphone_call_get_params(paulineCall));
		bool sendReInvite = (potentialConfigurationChosen && capabilityNegotiationReinviteEnabled);
		expectedStreamsRunning = 1 + ((sendReInvite) ? 1 : 0);

		/*wait for reINVITEs to complete*/
		BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallStreamsRunning,(pauline_stat.number_of_LinphoneCallStreamsRunning+expectedStreamsRunning)));
		BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallStreamsRunning,(marie_stat.number_of_LinphoneCallStreamsRunning+expectedStreamsRunning)));

		liblinphone_tester_check_rtcp(marie, pauline);

		wait_for_until(marie->lc, pauline->lc, NULL, 5, 2000);

		// Check that encryption has not changed after sending update
		BC_ASSERT_EQUAL(expectedEncryption, encryptionAfterUpdate, int, "%i");

		if ((expectedEncryption == LinphoneMediaEncryptionDTLS) || (expectedEncryption == LinphoneMediaEncryptionZRTP)) {
			BC_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallEncryptedOn,marie_stat.number_of_LinphoneCallEncryptedOn+1,10000));
			BC_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&pauline->stat.number_of_LinphoneCallEncryptedOn,pauline_stat.number_of_LinphoneCallEncryptedOn+1,10000));
		}

		if (marieCall) {
			check_stream_encryption(marieCall);
			BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(marieCall)), expectedEncryption, int, "%i");
		}
		if (paulineCall) {
			check_stream_encryption(paulineCall);
			BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(paulineCall)), expectedEncryption, int, "%i");
		}

		BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneCallStreamsRunning, (pauline_stat.number_of_LinphoneCallStreamsRunning+expectedStreamsRunning), int, "%d");
		BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallStreamsRunning, (marie_stat.number_of_LinphoneCallStreamsRunning+expectedStreamsRunning), int, "%d");

		pause_resume_calls(marie, pauline);

		end_call(marie, pauline);
	}

	linphone_core_manager_destroy(marie);
	linphone_core_manager_destroy(pauline);
#endif

	BC_PASS("Test temporarely disabled");
}

static void call_with_ack_not_sent(void) {
	LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
	linphone_core_enable_capability_negociation(marie->lc, TRUE);
	LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
	linphone_core_set_media_encryption(pauline->lc,LinphoneMediaEncryptionSRTP);

	LinphoneCall* in_call = NULL;
	LinphoneCall* out_call = linphone_core_invite_address(pauline->lc,marie->identity);
	BC_ASSERT_PTR_NOT_NULL(out_call);

	BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallOutgoingInit,1));
	BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallOutgoingProgress,1));

	BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallIncomingReceived,1));
	BC_ASSERT_PTR_NOT_NULL(in_call=linphone_core_get_current_call(marie->lc));

	BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallOutgoingRinging,1));
	BC_ASSERT_PTR_NOT_NULL(in_call=linphone_core_get_current_call(marie->lc));

	linphone_call_accept(in_call);

	// Pauline goes offline so that it cannot send the ACK
	linphone_core_set_network_reachable(pauline->lc,FALSE);

	BC_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallStreamsRunning,1,5000));
	BC_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallEnd,1,60000));

	check_media_stream(in_call, TRUE);
	BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(in_call)), LinphoneMediaEncryptionSRTP, int, "%i");

	// Pauline comes back online to answer the BYE
	linphone_core_set_network_reachable(pauline->lc,TRUE);

	// Check that Pauline never went to the streams running state
	BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneCallStreamsRunning, 0, int, "%d");

	BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallReleased,1));
	BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallReleased,1));

	linphone_core_manager_destroy(marie);
	linphone_core_manager_destroy(pauline);
}

test_t capability_negotiation_tests[] = {
	TEST_NO_TAG("Call with no encryption", call_with_no_encryption),
	TEST_NO_TAG("Call with ACK not sent", call_with_ack_not_sent),
	TEST_NO_TAG("Call with capability negotiation failure", call_with_capability_negotiation_failure),
	TEST_NO_TAG("Call with capability negotiation failure and multiple potential configurations", call_with_capability_negotiation_failure_multiple_potential_configurations),
	TEST_NO_TAG("Call with capability negotiation disabled at call level", call_with_capability_negotiation_disable_call_level),
	TEST_NO_TAG("Call with capability negotiation disabled at core level", call_with_capability_negotiation_disable_core_level),
	TEST_NO_TAG("Call with incompatible encryptions in call params", call_with_incompatible_encs_in_call_params),
	TEST_NO_TAG("Call with update and incompatible encryptions in call params", call_with_update_and_incompatible_encs_in_call_params),
	TEST_NO_TAG("Call with tcap line merge on caller", call_with_tcap_line_merge_on_caller),
	TEST_NO_TAG("Call with tcap line merge on callee", call_with_tcap_line_merge_on_callee),
	TEST_NO_TAG("Call with tcap line merge on both sides", call_with_tcap_line_merge_on_both_sides),
	TEST_NO_TAG("Call with AVPF and capability negotiations on caller", call_with_avpf_and_cap_neg_on_caller),
	TEST_NO_TAG("Call with AVPF and capability negotiations on callee", call_with_avpf_and_cap_neg_on_callee),
	TEST_NO_TAG("Call with AVPF and capability negotiations on both sides", call_with_avpf_and_cap_neg_on_both_sides),
	TEST_NO_TAG("Call changes encryption with update and capability negotiations on caller", call_changes_enc_on_update_cap_neg_caller),
	TEST_NO_TAG("Call changes encryption with update and capability negotiations on callee", call_changes_enc_on_update_cap_neg_callee),
	TEST_NO_TAG("Call changes encryption with update and capability negotiations on both sides with reINVITE", call_changes_enc_on_update_cap_neg_both_sides_with_reinvite),
	TEST_NO_TAG("Call changes encryption with update and capability negotiations on both sides without reINVITE", call_changes_enc_on_update_cap_neg_both_sides_without_reinvite),
	TEST_NO_TAG("Unencrypted call with potential configuration same as actual one", unencrypted_call_with_potential_configuration_same_as_actual_configuration),
	TEST_NO_TAG("Back to back call with capability negotiations on one side", back_to_back_calls_cap_neg_one_side),
	TEST_NO_TAG("Back to back call with capability negotiations on both sides", back_to_back_calls_cap_neg_both_sides)
};

test_t capability_negotiation_tests_no_sdp[] = {
	TEST_NO_TAG("Call with no SDP and capability negotiations on caller", call_with_no_sdp_cap_neg_on_caller),
	TEST_NO_TAG("Call with no SDP and capability negotiations on callee", call_with_no_sdp_cap_neg_on_callee),
	TEST_NO_TAG("Call with no SDP and capability negotiations on both sides", call_with_no_sdp_cap_neg_on_both_sides),
	TEST_NO_TAG("Call with no SDP on update and capability negotiations on caller", call_with_no_sdp_on_update_cap_neg_caller),
	TEST_NO_TAG("Call with no SDP on update and capability negotiations on callee", call_with_no_sdp_on_update_cap_neg_callee),
	TEST_NO_TAG("Call with no SDP on update and capability negotiations on both sides with reINVITE", call_with_no_sdp_on_update_cap_neg_both_sides_with_reinvite),
	TEST_NO_TAG("Call with no SDP on update and capability negotiations on both sides without reINVITE on caller", call_with_no_sdp_on_update_cap_neg_both_sides_without_reinvite_on_caller),
	TEST_NO_TAG("Call with no SDP on update and capability negotiations on both sides without reINVITE on callee", call_with_no_sdp_on_update_cap_neg_both_sides_without_reinvite_on_callee),
	TEST_NO_TAG("Call with no SDP on update and capability negotiations on both sides without reINVITE", call_with_no_sdp_on_update_cap_neg_both_sides_without_reinvite)
};

test_suite_t capability_negotiation_test_suite = {"Capability Negotiation (SDP)", NULL, NULL, liblinphone_tester_before_each, liblinphone_tester_after_each,
								sizeof(capability_negotiation_tests) / sizeof(capability_negotiation_tests[0]), capability_negotiation_tests};

test_suite_t capability_negotiation_no_sdp_test_suite = {"Capability Negotiation (No SDP)", NULL, NULL, liblinphone_tester_before_each, liblinphone_tester_after_each,
								sizeof(capability_negotiation_tests_no_sdp) / sizeof(capability_negotiation_tests_no_sdp[0]), capability_negotiation_tests_no_sdp};
