presence_tester.c 30.6 KB
Newer Older
jehan's avatar
jehan committed
1
/*
Simon Morlat's avatar
Simon Morlat committed
2 3
    liblinphone_tester - liblinphone test suite
    Copyright (C) 2013  Belledonne Communications SARL
jehan's avatar
jehan committed
4 5 6

    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
Simon Morlat's avatar
Simon Morlat committed
7
    the Free Software Foundation, either version 2 of the License, or
jehan's avatar
jehan committed
8 9 10 11 12 13 14 15 16 17
    (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/>.
*/
18

19

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

24 25
static LinphoneCoreManager* presence_linphone_core_manager_new_with_rc_name(char* username, char * rc_name) {
	LinphoneCoreManager* mgr= linphone_core_manager_new2( rc_name, FALSE);
jehan's avatar
jehan committed
26 27 28 29 30
	char* identity_char;
	mgr->identity= linphone_core_get_primary_contact_parsed(mgr->lc);
	linphone_address_set_username(mgr->identity,username);
	identity_char=linphone_address_as_string(mgr->identity);
	linphone_core_set_primary_contact(mgr->lc,identity_char);
31
	ms_free(identity_char);
jehan's avatar
jehan committed
32 33
	return mgr;
}
34 35 36 37
static LinphoneCoreManager* presence_linphone_core_manager_new(char* username) {
	return presence_linphone_core_manager_new_with_rc_name(username, "empty_rc");
}

38

39
void new_subscription_requested(LinphoneCore *lc, LinphoneFriend *lf, const char *url){
40
	stats* counters;
41
	const LinphoneAddress *addr = linphone_friend_get_address(lf);
42 43 44 45 46
	if (addr != NULL) {
		char* from=linphone_address_as_string(addr);
		ms_message("New subscription request from [%s] url [%s]",from,url);
		ms_free(from);
	}
47
	counters = get_stats(lc);
jehan's avatar
jehan committed
48 49 50
	counters->number_of_NewSubscriptionRequest++;
	linphone_core_add_friend(lc,lf); /*accept subscription*/
}
51

jehan's avatar
jehan committed
52
void notify_presence_received(LinphoneCore *lc, LinphoneFriend * lf) {
53
	stats* counters;
54
	unsigned int i;
55
	const LinphoneAddress *addr = linphone_friend_get_address(lf);
56 57 58 59 60
	if (addr != NULL) {
		char* from=linphone_address_as_string(addr);
		ms_message("New Notify request from [%s] ",from);
		ms_free(from);
	}
61
	counters = get_stats(lc);
Ghislain MARY's avatar
Ghislain MARY committed
62
	counters->number_of_NotifyPresenceReceived++;
63
	counters->last_received_presence = linphone_friend_get_presence_model(lf);
64 65 66 67 68
	if (linphone_presence_model_get_basic_status(counters->last_received_presence) == LinphonePresenceBasicStatusOpen) {
		counters->number_of_LinphonePresenceBasicStatusOpen++;
	} else if (linphone_presence_model_get_basic_status(counters->last_received_presence) == LinphonePresenceBasicStatusClosed) {
		counters->number_of_LinphonePresenceBasicStatusClosed++;
	} else {
Ghislain MARY's avatar
Ghislain MARY committed
69
		ms_error("Unexpected basic status [%i]",linphone_presence_model_get_basic_status(counters->last_received_presence));
70
	}
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
	if (linphone_presence_model_get_nb_activities(counters->last_received_presence) > 0) {
		for (i=0;counters->last_received_presence&&i<linphone_presence_model_get_nb_activities(counters->last_received_presence); i++) {
			LinphonePresenceActivity *activity = linphone_presence_model_get_nth_activity(counters->last_received_presence, i);
			switch (linphone_presence_activity_get_type(activity)) {
				case LinphonePresenceActivityAppointment:
					counters->number_of_LinphonePresenceActivityAppointment++; break;
				case LinphonePresenceActivityAway:
					counters->number_of_LinphonePresenceActivityAway++; break;
				case LinphonePresenceActivityBreakfast:
					counters->number_of_LinphonePresenceActivityBreakfast++; break;
				case LinphonePresenceActivityBusy:
					counters->number_of_LinphonePresenceActivityBusy++; break;
				case LinphonePresenceActivityDinner:
					counters->number_of_LinphonePresenceActivityDinner++; break;
				case LinphonePresenceActivityHoliday:
					counters->number_of_LinphonePresenceActivityHoliday++; break;
				case LinphonePresenceActivityInTransit:
					counters->number_of_LinphonePresenceActivityInTransit++; break;
				case LinphonePresenceActivityLookingForWork:
					counters->number_of_LinphonePresenceActivityLookingForWork++; break;
				case LinphonePresenceActivityLunch:
					counters->number_of_LinphonePresenceActivityLunch++; break;
				case LinphonePresenceActivityMeal:
					counters->number_of_LinphonePresenceActivityMeal++; break;
				case LinphonePresenceActivityMeeting:
					counters->number_of_LinphonePresenceActivityMeeting++; break;
				case LinphonePresenceActivityOnThePhone:
					counters->number_of_LinphonePresenceActivityOnThePhone++; break;
				case LinphonePresenceActivityOther:
					counters->number_of_LinphonePresenceActivityOther++; break;
				case LinphonePresenceActivityPerformance:
					counters->number_of_LinphonePresenceActivityPerformance++; break;
				case LinphonePresenceActivityPermanentAbsence:
					counters->number_of_LinphonePresenceActivityPermanentAbsence++; break;
				case LinphonePresenceActivityPlaying:
					counters->number_of_LinphonePresenceActivityPlaying++; break;
				case LinphonePresenceActivityPresentation:
					counters->number_of_LinphonePresenceActivityPresentation++; break;
				case LinphonePresenceActivityShopping:
					counters->number_of_LinphonePresenceActivityShopping++; break;
				case LinphonePresenceActivitySleeping:
					counters->number_of_LinphonePresenceActivitySleeping++; break;
				case LinphonePresenceActivitySpectator:
					counters->number_of_LinphonePresenceActivitySpectator++; break;
				case LinphonePresenceActivitySteering:
					counters->number_of_LinphonePresenceActivitySteering++; break;
				case LinphonePresenceActivityTravel:
					counters->number_of_LinphonePresenceActivityTravel++; break;
				case LinphonePresenceActivityTV:
					counters->number_of_LinphonePresenceActivityTV++; break;
				case LinphonePresenceActivityUnknown:
					counters->number_of_LinphonePresenceActivityUnknown++; break;
				case LinphonePresenceActivityVacation:
					counters->number_of_LinphonePresenceActivityVacation++; break;
				case LinphonePresenceActivityWorking:
					counters->number_of_LinphonePresenceActivityWorking++; break;
				case LinphonePresenceActivityWorship:
					counters->number_of_LinphonePresenceActivityWorship++; break;
			}
130
		}
131 132 133 134 135
	} else {
		if (linphone_presence_model_get_basic_status(counters->last_received_presence) == LinphonePresenceBasicStatusOpen)
			counters->number_of_LinphonePresenceActivityOnline++;
		else
			counters->number_of_LinphonePresenceActivityOffline++;
jehan's avatar
jehan committed
136
	}
jehan's avatar
jehan committed
137 138
}

139 140 141 142 143 144
void notify_presence_received_for_uri_or_tel(LinphoneCore *lc, LinphoneFriend *lf, const char *uri_or_tel, const LinphonePresenceModel *presence) {
	stats *counters = get_stats(lc);
	ms_message("Presence notification for URI or phone number [%s]", uri_or_tel);
	counters->number_of_NotifyPresenceReceivedForUriOrTel++;
}

145
static void simple_publish_with_expire(int expires) {
Simon Morlat's avatar
Simon Morlat committed
146
	LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
jehan's avatar
jehan committed
147
	LinphoneProxyConfig* proxy;
148
	LinphonePresenceModel* presence;
149
	LinphoneCoreCbs *cbs = linphone_factory_create_core_cbs(linphone_factory_get());
Benjamin REIS's avatar
Benjamin REIS committed
150

151 152 153
	linphone_core_cbs_set_publish_state_changed(cbs, linphone_publish_state_changed);
	_linphone_core_add_callbacks(marie->lc, cbs, TRUE);
	linphone_core_cbs_unref(cbs);
154

155
	proxy = linphone_core_get_default_proxy_config(marie->lc);
jehan's avatar
jehan committed
156
	linphone_proxy_config_edit(proxy);
Simon Morlat's avatar
Simon Morlat committed
157
	if (expires > 0) {
158 159
		linphone_proxy_config_set_publish_expires(proxy,expires);
	}
jehan's avatar
jehan committed
160 161
	linphone_proxy_config_enable_publish(proxy,TRUE);
	linphone_proxy_config_done(proxy);
162

163 164
	BC_ASSERT_TRUE(wait_for(marie->lc,marie->lc,&marie->stat.number_of_LinphonePublishProgress,1));
	BC_ASSERT_TRUE(wait_for(marie->lc,marie->lc,&marie->stat.number_of_LinphonePublishOk,1));
165

166 167
	presence = linphone_presence_model_new();
	linphone_presence_model_set_basic_status(presence, LinphonePresenceBasicStatusClosed);
168
	linphone_core_set_presence_model(marie->lc,presence);
169
	linphone_presence_model_unref(presence);
170

171 172
	BC_ASSERT_TRUE(wait_for(marie->lc,marie->lc,&marie->stat.number_of_LinphonePublishProgress,2));
	BC_ASSERT_TRUE(wait_for(marie->lc,marie->lc,&marie->stat.number_of_LinphonePublishOk,2));
173

174 175 176
	linphone_proxy_config_edit(proxy);
	linphone_proxy_config_done(proxy);
	/*make sure no publish is sent*/
177
	BC_ASSERT_FALSE(wait_for_until(marie->lc,marie->lc,&marie->stat.number_of_LinphonePublishProgress,3,2000));
178 179 180 181

	linphone_proxy_config_edit(proxy);
	linphone_proxy_config_enable_publish(proxy,FALSE);
	linphone_proxy_config_done(proxy);
182

183

jehan's avatar
jehan committed
184
	/*fixme PUBLISH state machine is too simple, clear state should only be propagated at API level  when 200ok is received*/
185
	/*BC_ASSERT_TRUE(wait_for(marie->lc,marie->lc,&marie->stat.number_of_LinphonePublishProgress,3));*/
jehan's avatar
jehan committed
186
	wait_for_until(marie->lc,marie->lc,NULL,0,2000);
187
	BC_ASSERT_TRUE(wait_for(marie->lc,marie->lc,&marie->stat.number_of_LinphonePublishCleared,1));
188

189 190 191 192 193 194 195 196 197 198 199 200
	linphone_proxy_config_edit(proxy);
	linphone_proxy_config_enable_publish(proxy,TRUE);
	linphone_proxy_config_done(proxy);
	BC_ASSERT_TRUE(wait_for(marie->lc,marie->lc,&marie->stat.number_of_LinphonePublishProgress,3));
	BC_ASSERT_TRUE(wait_for(marie->lc,marie->lc,&marie->stat.number_of_LinphonePublishOk,3));

	linphone_proxy_config_edit(proxy);
	linphone_proxy_config_set_publish_expires(proxy, linphone_proxy_config_get_publish_expires(proxy)+1);
	linphone_proxy_config_done(proxy);
	BC_ASSERT_TRUE(wait_for(marie->lc,marie->lc,&marie->stat.number_of_LinphonePublishProgress,4));
	BC_ASSERT_TRUE(wait_for(marie->lc,marie->lc,&marie->stat.number_of_LinphonePublishOk,4));

201
	linphone_core_manager_stop(marie);
Simon Morlat's avatar
Simon Morlat committed
202
	BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishCleared,3,int,"%i"); /*yes it is 3 because when we change the expires, a new LinphoneEvent is created*/
203
	BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishOk,4,int,"%i");
204
	linphone_core_manager_destroy(marie);
jehan's avatar
jehan committed
205 206
}

207
static void simple_publish(void) {
208 209 210
	simple_publish_with_expire(-1);
}

211
static void publish_with_expires(void) {
212
	simple_publish_with_expire(2);
213 214
}

215 216 217 218
static void publish_with_dual_identity(void) {
	LinphoneCoreManager* pauline = linphone_core_manager_new("multi_account_rc");
	const bctbx_list_t* proxies;
	LinphoneCoreCbs *cbs = linphone_factory_create_core_cbs(linphone_factory_get());
Benjamin REIS's avatar
Benjamin REIS committed
219

220 221 222
	linphone_core_cbs_set_publish_state_changed(cbs, linphone_publish_state_changed);
	_linphone_core_add_callbacks(pauline->lc, cbs, TRUE);
	linphone_core_cbs_unref(cbs);
Benjamin REIS's avatar
Benjamin REIS committed
223

224 225 226 227 228 229
	for (proxies = linphone_core_get_proxy_config_list(pauline->lc); proxies!=NULL; proxies = proxies->next) {
		LinphoneProxyConfig *proxy = (LinphoneProxyConfig *) proxies->data;
		linphone_proxy_config_edit(proxy);
		linphone_proxy_config_enable_publish(proxy,TRUE);
		linphone_proxy_config_done(proxy);
	}
Benjamin REIS's avatar
Benjamin REIS committed
230

231 232
	BC_ASSERT_TRUE(wait_for(pauline->lc,pauline->lc,&pauline->stat.number_of_LinphonePublishProgress,4));
	BC_ASSERT_TRUE(wait_for(pauline->lc,pauline->lc,&pauline->stat.number_of_LinphonePublishOk,4));
Benjamin REIS's avatar
Benjamin REIS committed
233

234 235 236 237
	linphone_core_manager_stop(pauline);
	BC_ASSERT_EQUAL(pauline->stat.number_of_LinphonePublishCleared,4,int,"%i");
	BC_ASSERT_EQUAL(pauline->stat.number_of_LinphonePublishOk,4,int,"%i");
	linphone_core_manager_destroy(pauline);
Benjamin REIS's avatar
Benjamin REIS committed
238

239
}
jehan's avatar
jehan committed
240 241 242 243
static bool_t subscribe_to_callee_presence(LinphoneCoreManager* caller_mgr,LinphoneCoreManager* callee_mgr) {
	stats initial_caller=caller_mgr->stat;
	stats initial_callee=callee_mgr->stat;
	bool_t result=FALSE;
jehan's avatar
jehan committed
244
	char* identity=linphone_address_as_string_uri_only(callee_mgr->identity);
jehan's avatar
jehan committed
245 246


jehan's avatar
jehan committed
247
	LinphoneFriend* friend=linphone_core_create_friend_with_address(caller_mgr->lc,identity);
jehan's avatar
jehan committed
248 249 250 251 252
	linphone_friend_edit(friend);
	linphone_friend_enable_subscribes(friend,TRUE);
	linphone_friend_done(friend);

	linphone_core_add_friend(caller_mgr->lc,friend);
253
	linphone_friend_unref(friend);
jehan's avatar
jehan committed
254

jehan's avatar
jehan committed
255 256 257 258
	result=wait_for(caller_mgr->lc,callee_mgr->lc,&caller_mgr->stat.number_of_LinphonePresenceActivityOnline,initial_caller.number_of_LinphonePresenceActivityOnline+1);
	/*without proxy, callee cannot subscribe to caller
	result&=wait_for(caller_mgr->lc,callee_mgr->lc,&callee_mgr->stat.number_of_LinphonePresenceActivityOnline,initial_callee.number_of_LinphonePresenceActivityOnline+1);
	*/
jehan's avatar
jehan committed
259

260
	BC_ASSERT_EQUAL(callee_mgr->stat.number_of_NewSubscriptionRequest,initial_callee.number_of_NewSubscriptionRequest+1, int, "%d");
jehan's avatar
jehan committed
261
	/*without proxy, callee cannot subscribe to caller
Ghislain MARY's avatar
Ghislain MARY committed
262
	BC_ASSERT_EQUAL(callee_mgr->stat.number_of_NotifyPresenceReceived,initial_callee.number_of_NotifyPresenceReceived+1, int, "%d");
jehan's avatar
jehan committed
263
	*/
Ghislain MARY's avatar
Ghislain MARY committed
264
	BC_ASSERT_EQUAL(caller_mgr->stat.number_of_NotifyPresenceReceived,initial_caller.number_of_NotifyPresenceReceived+1, int, "%d");
jehan's avatar
jehan committed
265

jehan's avatar
jehan committed
266
	ms_free(identity);
jehan's avatar
jehan committed
267 268 269
	return result;

}
270 271

/* BEWARE this test will fail if the machine it is run on is behind an active firewall not sending ICMP errors on incoming connections! */
272
/* It will create a leak of NOTIFY because during marie error after network switch off, Pauline will never received the acknowledgement of the notify ...*/
273 274
static void subscribe_failure_handle_by_app(void) {
	LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
275
	LinphoneCoreManager* pauline = linphone_core_manager_new("pauline_tcp_rc");
276 277 278
	LinphoneProxyConfig* config;
	LinphoneFriend* lf;
	char* lf_identity=linphone_address_as_string_uri_only(pauline->identity);
279

280
	config = linphone_core_get_default_proxy_config(marie->lc);
281

282
	BC_ASSERT_TRUE(subscribe_to_callee_presence(marie,pauline));
283 284
	wait_for(marie->lc,pauline->lc,&pauline->stat.number_of_NewSubscriptionRequest,1); /*just to wait for unsubscription even if not notified*/

285
	sal_set_recv_error(linphone_core_get_sal(marie->lc), 0); /*simulate an error*/
286

287 288
	BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneRegistrationProgress,2));
	BC_ASSERT_EQUAL(linphone_proxy_config_get_error(config),LinphoneReasonIOError, int, "%d");
289
	sal_set_recv_error(linphone_core_get_sal(marie->lc), 1);
290 291

	lf = linphone_core_get_friend_by_address(marie->lc,lf_identity);
Ghislain MARY's avatar
Ghislain MARY committed
292
	ms_free(lf_identity);
293
	BC_ASSERT_PTR_NOT_NULL(lf);
294 295 296
	linphone_friend_edit(lf);
	linphone_friend_enable_subscribes(lf,FALSE); /*disable subscription*/
	linphone_friend_done(lf);
297
	BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneRegistrationOk,2)); /*wait for register ok*/
298 299 300
	linphone_friend_edit(lf);
	linphone_friend_enable_subscribes(lf,TRUE);
	linphone_friend_done(lf);
301
	BC_ASSERT_FALSE(wait_for(marie->lc,pauline->lc,&pauline->stat.number_of_NewSubscriptionRequest,2)); /*just to wait for unsubscription even if not notified*/
302 303

	linphone_core_manager_destroy(marie);
304
	BC_ASSERT_FALSE(wait_for(NULL,pauline->lc,&pauline->stat.number_of_NewSubscriptionRequest,3)); /*just to wait for unsubscription even if not notified*/
305 306 307 308

	linphone_core_manager_destroy(pauline);
}

309 310 311 312
static void publish_with_network_state_changes(void) {
	LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
	LinphoneProxyConfig* proxy;
	LinphoneCoreCbs *cbs = linphone_factory_create_core_cbs(linphone_factory_get());
Benjamin REIS's avatar
Benjamin REIS committed
313

314 315 316
	linphone_core_cbs_set_publish_state_changed(cbs, linphone_publish_state_changed);
	_linphone_core_add_callbacks(marie->lc, cbs,TRUE);
	linphone_core_cbs_unref(cbs);
Benjamin REIS's avatar
Benjamin REIS committed
317

318 319 320 321
	proxy = linphone_core_get_default_proxy_config(marie->lc);
	linphone_proxy_config_edit(proxy);
	linphone_proxy_config_enable_publish(proxy,TRUE);
	linphone_proxy_config_done(proxy);
Benjamin REIS's avatar
Benjamin REIS committed
322

323 324
	BC_ASSERT_TRUE(wait_for(marie->lc,marie->lc,&marie->stat.number_of_LinphonePublishProgress,1));
	BC_ASSERT_TRUE(wait_for(marie->lc,marie->lc,&marie->stat.number_of_LinphonePublishOk,1));
Benjamin REIS's avatar
Benjamin REIS committed
325

326 327 328 329 330
	linphone_core_set_network_reachable(marie->lc, FALSE);
	BC_ASSERT_TRUE(wait_for(marie->lc,marie->lc,&marie->stat.number_of_LinphoneRegistrationNone,1));
	BC_ASSERT_FALSE(wait_for_until(marie->lc,marie->lc,&marie->stat.number_of_LinphonePublishProgress,2,1000));
	BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishOk,1,int,"%i");
	BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishError,0,int,"%i");
Benjamin REIS's avatar
Benjamin REIS committed
331

332 333 334
	linphone_core_set_network_reachable(marie->lc, TRUE);
	BC_ASSERT_TRUE(wait_for(marie->lc,marie->lc,&marie->stat.number_of_LinphonePublishProgress,2));
	BC_ASSERT_TRUE(wait_for(marie->lc,marie->lc,&marie->stat.number_of_LinphonePublishOk,2));
Benjamin REIS's avatar
Benjamin REIS committed
335 336


337 338 339 340 341 342
	linphone_core_manager_stop(marie);
	BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishCleared,1,int,"%i"); /*yes it is 3 because when we change the expires, a new LinphoneEvent is created*/
	BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishOk,2,int,"%i");
	linphone_core_manager_destroy(marie);
}

343
static void simple_subscribe(void) {
jehan's avatar
jehan committed
344 345
	LinphoneCoreManager* marie = presence_linphone_core_manager_new("marie");
	LinphoneCoreManager* pauline = presence_linphone_core_manager_new("pauline");
jehan's avatar
jehan committed
346

347
	BC_ASSERT_TRUE(subscribe_to_callee_presence(marie,pauline));
jehan's avatar
jehan committed
348

349

jehan's avatar
jehan committed
350
	linphone_core_manager_destroy(marie);
jehan's avatar
jehan committed
351
	/*unsubscribe is not reported ?*/
352
	BC_ASSERT_FALSE(wait_for(NULL,pauline->lc,&pauline->stat.number_of_NewSubscriptionRequest,2)); /*just to wait for unsubscription even if not notified*/
jehan's avatar
jehan committed
353 354 355

	linphone_core_manager_destroy(pauline);
}
356
static void simple_subscribe_with_early_notify(void) {
357

358 359 360 361
	LinphoneCoreManager* marie = presence_linphone_core_manager_new("marie");
	LinphoneCoreManager* pauline = presence_linphone_core_manager_new("pauline");
	LinphoneAddress *marie_identity_addr = linphone_address_clone(marie->identity);
	LpConfig *pauline_lp;
362

363 364
	char* pauline_identity=linphone_address_as_string_uri_only(pauline->identity);
	char* marie_identity;
365

366 367
	LinphoneFriend* pauline_s_friend;
	LinphoneFriend* marie_s_friend=linphone_core_create_friend_with_address(marie->lc,pauline_identity);
368

Sylvain Berfini's avatar
Sylvain Berfini committed
369 370
	pauline_lp = linphone_core_get_config(pauline->lc);
	lp_config_set_int(pauline_lp,"sip","notify_pending_state",1);
371

372 373 374 375 376
	linphone_friend_edit(marie_s_friend);
	linphone_friend_enable_subscribes(marie_s_friend,TRUE);
	linphone_friend_done(marie_s_friend);
	linphone_core_add_friend(marie->lc,marie_s_friend);
	ms_free(pauline_identity);
377 378


379 380 381 382 383 384
	/*to simulate pending state.*/

	linphone_address_set_port(marie_identity_addr,0);
	marie_identity=linphone_address_as_string_uri_only(marie_identity_addr);
	pauline_s_friend=linphone_core_create_friend_with_address(pauline->lc,marie_identity);
	linphone_core_add_friend(pauline->lc,pauline_s_friend);
385

386 387 388 389
	ms_free(marie_identity);

	BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_NotifyPresenceReceived,1));
	BC_ASSERT_EQUAL(linphone_friend_get_subscription_state(marie_s_friend), LinphoneSubscriptionPending,int, "%d");
390

Sylvain Berfini's avatar
Sylvain Berfini committed
391
	wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePresenceActivityOnline,marie->stat.number_of_LinphonePresenceActivityOnline+1);
392

393
	BC_ASSERT_EQUAL(marie->stat.number_of_NotifyPresenceReceived,2, int, "%d");
394

395 396 397 398
	linphone_friend_unref(marie_s_friend);
	linphone_friend_unref(pauline_s_friend);
	linphone_address_unref(marie_identity_addr);
	linphone_core_manager_destroy(marie);
399

400 401 402
	linphone_core_manager_destroy(pauline);
}

403 404

static void unsubscribe_while_subscribing(void) {
Simon Morlat's avatar
Simon Morlat committed
405
	LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
406
	LinphoneFriend* friend = linphone_core_create_friend_with_address(marie->lc, "sip:toto@git.linphone.org"); /*any unexisting address*/
jehan's avatar
jehan committed
407 408 409 410
	linphone_friend_edit(friend);
	linphone_friend_enable_subscribes(friend,TRUE);
	linphone_friend_done(friend);
	linphone_core_add_friend(marie->lc,friend);
411
	linphone_friend_unref(friend);
jehan's avatar
jehan committed
412 413 414 415
	linphone_core_iterate(marie->lc);
	linphone_core_manager_destroy(marie);
}

416 417
#if 0
/* the core no longer changes the presence status when a call is ongoing, this is left to the application*/
jehan's avatar
jehan committed
418
static void call_with_presence(void) {
jehan's avatar
jehan committed
419 420
	LinphoneCoreManager* marie = presence_linphone_core_manager_new("marie");
	LinphoneCoreManager* pauline = presence_linphone_core_manager_new("pauline");
421 422
	LinphoneVideoPolicy pol={0};
	linphone_core_set_video_policy(marie->lc,&pol);
423 424
	BC_ASSERT_TRUE(subscribe_to_callee_presence(marie,pauline));
	BC_ASSERT_TRUE(subscribe_to_callee_presence(pauline,marie));
jehan's avatar
jehan committed
425

426 427 428
	BC_ASSERT_TRUE(call(marie,pauline));
	BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePresenceActivityOnThePhone,1));
	BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&pauline->stat.number_of_LinphonePresenceActivityOnThePhone,1));
jehan's avatar
jehan committed
429 430 431 432

	reset_counters(&marie->stat);
	reset_counters(&pauline->stat);
	linphone_core_terminate_all_calls(marie->lc);
433 434
	BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&pauline->stat.number_of_LinphonePresenceActivityOnline,1));
	BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePresenceActivityOnline,1));
jehan's avatar
jehan committed
435 436 437
	linphone_core_manager_destroy(marie);
	linphone_core_manager_destroy(pauline);
}
438

439 440
#endif

441 442 443 444
static void presence_information(void) {
	const char *bike_description = "Riding my bike";
	const char *vacation_note = "I'm on vacation until July 4th";
	const char *vacation_lang = "en";
445
	const char *contact = "sip:toto@example.com";
446 447 448
	LinphoneCoreManager *marie = presence_linphone_core_manager_new("marie");
	LinphoneCoreManager *pauline = presence_linphone_core_manager_new("pauline");
	LinphonePresenceModel *presence;
449 450 451 452
	LinphonePresenceActivity *activity = NULL;
	LinphonePresenceNote *note = NULL;
	const char *description = NULL;
	const char *note_content = NULL;
453
	char *contact2;
454
	time_t current_timestamp, presence_timestamp;
455

456
	BC_ASSERT_TRUE(subscribe_to_callee_presence(marie, pauline));
457 458 459

	/* Presence activity without description. */
	presence = linphone_presence_model_new_with_activity(LinphonePresenceActivityDinner, NULL);
460
	linphone_core_set_presence_model(pauline->lc, presence);
461
	linphone_presence_model_unref(presence);
jehan's avatar
jehan committed
462
	wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePresenceActivityDinner,1);
463
	BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePresenceActivityDinner, 1, int, "%d");
464
	activity = linphone_presence_model_get_activity(marie->stat.last_received_presence);
465 466
	BC_ASSERT_PTR_NOT_NULL(activity);
	BC_ASSERT_EQUAL(linphone_presence_activity_get_type(activity), LinphonePresenceActivityDinner, int, "%d");
467
	description = linphone_presence_activity_get_description(activity);
468
	BC_ASSERT_PTR_NULL(description);
469 470 471

	/* Presence activity with description. */
	presence = linphone_presence_model_new_with_activity(LinphonePresenceActivitySteering, bike_description);
472
	linphone_core_set_presence_model(pauline->lc, presence);
473
	linphone_presence_model_unref(presence);
jehan's avatar
jehan committed
474
	wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePresenceActivitySteering,1);
475
	BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePresenceActivitySteering, 1, int, "%d");
476
	activity = linphone_presence_model_get_activity(marie->stat.last_received_presence);
477 478
	BC_ASSERT_PTR_NOT_NULL(activity);
	BC_ASSERT_EQUAL(linphone_presence_activity_get_type(activity), LinphonePresenceActivitySteering, int, "%d");
479
	description = linphone_presence_activity_get_description(activity);
480
	BC_ASSERT_PTR_NOT_NULL(description);
481
	if (description != NULL) BC_ASSERT_STRING_EQUAL(description, bike_description);
482 483 484

	/* Presence activity with description and note. */
	presence = linphone_presence_model_new_with_activity_and_note(LinphonePresenceActivityVacation, NULL, vacation_note, vacation_lang);
485
	linphone_core_set_presence_model(pauline->lc, presence);
486
	linphone_presence_model_unref(presence);
jehan's avatar
jehan committed
487
	wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePresenceActivityVacation,1);
488
	BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePresenceActivityVacation, 1, int, "%d");
489
	activity = linphone_presence_model_get_activity(marie->stat.last_received_presence);
490 491
	BC_ASSERT_PTR_NOT_NULL(activity);
	BC_ASSERT_EQUAL(linphone_presence_activity_get_type(activity), LinphonePresenceActivityVacation, int, "%d");
492
	description = linphone_presence_activity_get_description(activity);
493
	BC_ASSERT_PTR_NULL(description);
494
	note = linphone_presence_model_get_note(marie->stat.last_received_presence, NULL);
495
	BC_ASSERT_PTR_NOT_NULL(note);
496
	if (note != NULL) {
497
		note_content = linphone_presence_note_get_content(note);
498
		BC_ASSERT_PTR_NOT_NULL(note_content);
499
		if (note_content != NULL) {
500
			BC_ASSERT_STRING_EQUAL(note_content, vacation_note);
501
		}
502 503
	}

504 505 506 507
	/* Presence contact. */
	presence = linphone_presence_model_new_with_activity(LinphonePresenceActivityOnThePhone, NULL);
	linphone_presence_model_set_contact(presence, contact);
	linphone_core_set_presence_model(pauline->lc, presence);
508
	linphone_presence_model_unref(presence);
jehan's avatar
jehan committed
509
	wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePresenceActivityOnThePhone,1);
510
	BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePresenceActivityOnThePhone, 1, int, "%d");
511
	contact2 = linphone_presence_model_get_contact(presence);
512
	BC_ASSERT_PTR_NOT_NULL(contact2);
513
	if (contact2 != NULL) {
514
		BC_ASSERT_STRING_EQUAL(contact, contact2);
515 516 517
		ms_free(contact2);
	}

518
	/* Presence timestamp. */
519
	current_timestamp = ms_time(NULL);
520 521
	presence = linphone_presence_model_new_with_activity(LinphonePresenceActivityShopping, NULL);
	linphone_core_set_presence_model(pauline->lc, presence);
jehan's avatar
jehan committed
522
	wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePresenceActivityShopping,1);
523
	BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePresenceActivityShopping, 1, int, "%d");
524
	presence_timestamp = linphone_presence_model_get_timestamp(presence);
525
	BC_ASSERT_GREATER((unsigned)presence_timestamp , (unsigned)current_timestamp, unsigned, "%u");
526
	linphone_presence_model_unref(presence);
527

528 529 530
	linphone_core_manager_destroy(marie);
	linphone_core_manager_destroy(pauline);
}
531 532


533
static void subscribe_presence_forked(void){
534
	LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
535 536
	LinphoneCoreManager* pauline1 = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_tcp_rc" : "pauline_tcp_rc");
	LinphoneCoreManager* pauline2 = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_tcp_rc" : "pauline_tcp_rc");
537
	LinphoneFriend *lf;
538
	bctbx_list_t *lcs = NULL;
539

540 541 542
	lcs = bctbx_list_append(lcs, marie->lc);
	lcs = bctbx_list_append(lcs, pauline1->lc);
	lcs = bctbx_list_append(lcs, pauline2->lc);
543

544 545 546
	lf = linphone_core_create_friend(marie->lc);
	linphone_friend_set_address(lf, pauline1->identity);
	linphone_friend_enable_subscribes(lf, TRUE);
547

548 549
	linphone_core_add_friend(marie->lc, lf);
	linphone_friend_unref(lf);
550

551 552
	BC_ASSERT_TRUE(wait_for_list(lcs,&pauline1->stat.number_of_NewSubscriptionRequest,1, 10000));
	BC_ASSERT_TRUE(wait_for_list(lcs,&pauline2->stat.number_of_NewSubscriptionRequest,1, 2000));
553

554 555 556
	/*we should get only one notify*/
	BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphonePresenceActivityOnline,1, 10000));
	BC_ASSERT_FALSE(wait_for_list(lcs,&marie->stat.number_of_LinphonePresenceActivityOnline,2, 2000));
557 558

	/*marie also shall receive two SUBSCRIBEs from the two paulines, but won't be notified to the app since
559 560 561 562 563
	 Marie set Pauline as a friend.*/
	BC_ASSERT_EQUAL(marie->stat.number_of_NewSubscriptionRequest, 0, int, "%d");
	/*and the two paulines shall be notified of marie's presence*/
	BC_ASSERT_TRUE(wait_for_list(lcs,&pauline1->stat.number_of_LinphonePresenceActivityOnline,1, 3000));
	BC_ASSERT_TRUE(wait_for_list(lcs,&pauline2->stat.number_of_LinphonePresenceActivityOnline,1, 2000));
564

565 566 567
	linphone_core_manager_destroy(marie);
	linphone_core_manager_destroy(pauline1);
	linphone_core_manager_destroy(pauline2);
568

569
	bctbx_list_free(lcs);
570 571
}

572
static void subscribe_presence_expired(void){
573 574
	LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
	LinphoneCoreManager* pauline1 = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
Simon Morlat's avatar
Simon Morlat committed
575
	LinphoneFriend *lf;
576
	bctbx_list_t *lcs = NULL;
577

578 579
	lcs = bctbx_list_append(lcs, marie->lc);
	lcs = bctbx_list_append(lcs, pauline1->lc);
580

581
	lp_config_set_int(linphone_core_get_config(marie->lc), "sip", "subscribe_expires", 10);
582

Simon Morlat's avatar
Simon Morlat committed
583 584 585
	lf = linphone_core_create_friend(marie->lc);
	linphone_friend_set_address(lf, pauline1->identity);
	linphone_friend_enable_subscribes(lf, TRUE);
586

Simon Morlat's avatar
Simon Morlat committed
587 588 589 590
	linphone_core_add_friend(marie->lc, lf);
	linphone_friend_unref(lf);
	BC_ASSERT_TRUE(wait_for_list(lcs,&pauline1->stat.number_of_NewSubscriptionRequest,1, 5000));
	BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphonePresenceActivityOnline,1, 2000));
591

592
	lf = linphone_core_find_friend(pauline1->lc, marie->identity);
593 594
	BC_ASSERT_PTR_NOT_NULL(lf);
	if (lf) {
595
		BC_ASSERT_PTR_NOT_NULL(linphone_friend_get_insubs(lf));
596 597 598 599 600

		/*marie comes offline suddenly*/
		linphone_core_set_network_reachable(marie->lc, FALSE);
		/*after a certain time, pauline shall see the incoming SUBSCRIBE expired*/
		wait_for_list(lcs,NULL, 0, 11000);
601
		BC_ASSERT_PTR_NULL(linphone_friend_get_insubs(lf));
602 603 604 605 606

		/*just make network reachable so that marie can unregister properly*/
		linphone_core_set_network_reachable(marie->lc, TRUE);
		BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneRegistrationOk,2, 10000));
	}
Simon Morlat's avatar
Simon Morlat committed
607 608
	linphone_core_manager_destroy(marie);
	linphone_core_manager_destroy(pauline1);
609

610
	bctbx_list_free(lcs);
Simon Morlat's avatar
Simon Morlat committed
611 612
}

613 614 615 616
static void simple_subscribe_with_friend_from_rc(void) {
	LinphoneCoreManager* pauline = presence_linphone_core_manager_new("pauline");
	LinphoneCoreManager *marie = presence_linphone_core_manager_new_with_rc_name("marie", "pauline_as_friend_rc");
	LinphoneFriend *pauline_as_friend;
617

618
	BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(linphone_core_get_friend_list(marie->lc)), 1, unsigned int , "%u");
619

620
	if (bctbx_list_size(linphone_core_get_friend_list(marie->lc))>0) {
621
		pauline_as_friend = (LinphoneFriend*)linphone_core_get_friend_list(marie->lc)->data;
622
		linphone_friend_edit(pauline_as_friend);
623
		linphone_friend_set_address(pauline_as_friend, pauline->identity); /*hack to update addr with port number*/
624
		linphone_friend_done(pauline_as_friend);
625
	}
626

627
	BC_ASSERT_TRUE (wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePresenceActivityOnline,1));
628

629 630
	BC_ASSERT_EQUAL(pauline->stat.number_of_NewSubscriptionRequest,1, int, "%d");
	BC_ASSERT_EQUAL(marie->stat.number_of_NotifyPresenceReceived,1, int, "%d");
631

632 633 634
	linphone_core_manager_destroy(marie);
	/*unsubscribe is not reported ?*/
	BC_ASSERT_FALSE(wait_for(NULL,pauline->lc,&pauline->stat.number_of_NewSubscriptionRequest,2)); /*just to wait for unsubscription even if not notified*/
635 636 637 638

	linphone_core_manager_destroy(pauline);
}

639
test_t presence_tests[] = {
jehan's avatar
jehan committed
640
	TEST_ONE_TAG("Simple Subscribe", simple_subscribe,"presence"),
641
	TEST_ONE_TAG("Simple Subscribe with early NOTIFY", simple_subscribe_with_early_notify,"presence"),
642
	TEST_NO_TAG("Simple Subscribe with friend from rc", simple_subscribe_with_friend_from_rc),
Simon Morlat's avatar
Simon Morlat committed
643
	TEST_NO_TAG("Simple Publish", simple_publish),
644
	TEST_NO_TAG("Publish with 2 identities", publish_with_dual_identity),
Simon Morlat's avatar
Simon Morlat committed
645
	TEST_NO_TAG("Simple Publish with expires", publish_with_expires),
646
	TEST_ONE_TAG("Publish with network state changes", publish_with_network_state_changes, "presence"),
647
	/*TEST_ONE_TAG("Call with presence", call_with_presence, "LeaksMemory"),*/
648
	TEST_NO_TAG("Unsubscribe while subscribing", unsubscribe_while_subscribing),
649
	TEST_NO_TAG("Presence information", presence_information),
Ghislain MARY's avatar
Ghislain MARY committed
650
	TEST_NO_TAG("App managed presence failure", subscribe_failure_handle_by_app),
651 652
	TEST_NO_TAG("Presence SUBSCRIBE forked", subscribe_presence_forked),
	TEST_NO_TAG("Presence SUBSCRIBE expired", subscribe_presence_expired),
653 654
};

655
test_suite_t presence_test_suite = {"Presence", NULL, NULL, liblinphone_tester_before_each, liblinphone_tester_after_each,
656
									sizeof(presence_tests) / sizeof(presence_tests[0]), presence_tests};