[asterisk-commits] rmudgett: branch rmudgett/parking r330704 - /team/rmudgett/parking/main/

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Aug 2 18:27:38 CDT 2011


Author: rmudgett
Date: Tue Aug  2 18:27:34 2011
New Revision: 330704

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=330704
Log:
* Write unit test for dialplan parking space usage map.

* Move features unit test code to better place to eliminate forward
references.

* Fix dialplan usage extension removal.  Must be sure that the extension
is present before removing it or get a warning.

Modified:
    team/rmudgett/parking/main/features.c

Modified: team/rmudgett/parking/main/features.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/parking/main/features.c?view=diff&rev=330704&r1=330703&r2=330704
==============================================================================
--- team/rmudgett/parking/main/features.c (original)
+++ team/rmudgett/parking/main/features.c Tue Aug  2 18:27:34 2011
@@ -1463,211 +1463,6 @@
 	return masq_park_call(rchan, peer, 0, NULL, 1, args);
 }
 
-#ifdef TEST_FRAMEWORK
-static int fake_fixup(struct ast_channel *clonechan, struct ast_channel *original)
-{
-	return 0;
-}
-
-static struct ast_channel *create_test_channel(const struct ast_channel_tech *fake_tech)
-{
-	struct ast_channel *test_channel1;
-
-	if (!(test_channel1 = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL,
-        NULL, NULL, 0, 0, "TestChannel1"))) {
-		ast_log(LOG_WARNING, "Whoa, test channel creation failed.\n");
-		return NULL;
-	}
-
-	/* normally this is done in the channel driver */
-	test_channel1->nativeformats = AST_FORMAT_GSM;
-	test_channel1->writeformat = AST_FORMAT_GSM;
-	test_channel1->rawwriteformat = AST_FORMAT_GSM;
-	test_channel1->readformat = AST_FORMAT_GSM;
-	test_channel1->rawreadformat = AST_FORMAT_GSM;
-	test_channel1->tech = fake_tech;
-
-	return test_channel1;
-}
-
-static int unpark_test_channel(struct ast_channel *toremove, struct ast_park_call_args *args)
-{
-	struct ast_context *con;
-	struct parkeduser *pu_toremove;
-	int res = 0;
-
-	args->pu->notquiteyet = 1; /* go ahead and stop processing the test parking */
-
-	AST_LIST_LOCK(&args->pu->parkinglot->parkings);
-	AST_LIST_TRAVERSE_SAFE_BEGIN(&args->pu->parkinglot->parkings, pu_toremove, list) {
-		if (pu_toremove == args->pu) {
-			AST_LIST_REMOVE_CURRENT(list);
-			break;
-		}
-	}
-	AST_LIST_TRAVERSE_SAFE_END;
-	AST_LIST_UNLOCK(&args->pu->parkinglot->parkings);
-
-	if (!pu_toremove) {
-		ast_log(LOG_WARNING, "Whoa, could not find parking test call!\n");
-		return -1;
-	}
-
-	con = ast_context_find(args->pu->parkinglot->cfg.parking_con);
-	if (con) {
-		if (ast_context_remove_extension2(con, args->pu->parkingexten, 1, NULL, 0)) {
-			ast_log(LOG_WARNING, "Whoa, failed to remove the parking extension!\n");
-			res = -1;
-		} else {
-			notify_metermaids(args->pu->parkingexten,
-				pu_toremove->parkinglot->cfg.parking_con, AST_DEVICE_NOT_INUSE);
-		}
-	} else {
-		ast_log(LOG_WARNING, "Whoa, no parking context?\n");
-		res = -1;
-	}
-
-	parkinglot_unref(pu_toremove->parkinglot);
-	ast_free(pu_toremove);
-	args->pu = NULL;
-
-	if (!res && toremove) {
-		ast_hangup(toremove);
-	}
-	return res;
-}
-
-/* BUGBUG need to reexamine tests for reference leaks and locking issues. */
-/* BUGBUG this internal test is rubbish. */
-AST_TEST_DEFINE(features_test)
-{
-	struct ast_channel *test_channel1 = NULL;
-	struct ast_channel *parked_chan = NULL;
-	struct ast_parkinglot *dynlot;
-	struct ast_park_call_args args = {
-		.timeout = DEFAULT_PARK_TIME,
-	};
-
-	int res = 0;
-
-	static const struct ast_channel_tech fake_tech = {
-		.fixup = fake_fixup, /* silence warning from masquerade */
-	};
-
-	static const char unique_parkinglot[] = "myuniquetestparkinglot3141592654";
-	static const char parkinglot_range[] = "750-760";
-
-	switch (cmd) {
-	case TEST_INIT:
-		info->name = "features_test";
-		info->category = "/main/features/";
-		info->summary = "Features unit test";
-		info->description =
-			"Tests whether parking respects PARKINGLOT settings";
-		return AST_TEST_NOT_RUN;
-	case TEST_EXECUTE:
-		break;
-	}
-
-	/* changing a config option is a bad practice, but must be done in this case */
-	parkeddynamic = 1;
-
-
-	ast_test_status_update(test, "Test parking functionality with defaults\n");
-	if (!(test_channel1 = create_test_channel(&fake_tech))) {
-		res = -1;
-		goto exit_features_test;
-	}
-	if (park_call_full(test_channel1, NULL, &args)) {
-		res = -1;
-		goto exit_features_test;
-	}
-	if (unpark_test_channel(test_channel1, &args)) {
-		res = -1;
-		goto exit_features_test;
-	}
-
-
-	ast_test_status_update(test, "Check that certain parking options are respected\n");
-	if (!(test_channel1 = create_test_channel(&fake_tech))) {
-		res = -1;
-		goto exit_features_test;
-	}
-	pbx_builtin_setvar_helper(test_channel1, "PARKINGLOT", unique_parkinglot);
-	pbx_builtin_setvar_helper(test_channel1, "PARKINGDYNPOS", parkinglot_range);
-	if (park_call_full(test_channel1, NULL, &args)) {
-		res = -1;
-		goto exit_features_test;
-	}
-	/* grab newly created parking lot for destruction in the end */
-	dynlot = args.pu->parkinglot;
-	if (args.pu->parkingnum != 750
-		|| strcasecmp(dynlot->name, unique_parkinglot)
-		|| dynlot->cfg.parking_start != 750
-		|| dynlot->cfg.parking_stop != 760) {
-		ast_test_status_update(test, "Parking settings were not respected\n");
-		if (!unpark_test_channel(test_channel1, &args)) {
-			test_channel1 = NULL;
-		}
-		res = -1;
-		goto exit_features_test;
-	} else {
-		ast_test_status_update(test, "Parking settings for non-masquerading park verified\n");
-	}
-	if (unpark_test_channel(test_channel1, &args)) {
-		res = -1;
-		goto exit_features_test;
-	}
-
-
-	ast_test_status_update(test, "Check #2 that certain parking options are respected\n");
-	if (!(test_channel1 = create_test_channel(&fake_tech))) {
-		res = -1;
-		goto exit_features_test;
-	}
-	pbx_builtin_setvar_helper(test_channel1, "PARKINGLOT", unique_parkinglot);
-	pbx_builtin_setvar_helper(test_channel1, "PARKINGDYNPOS", parkinglot_range);
-	if (masq_park_call(test_channel1, NULL, 0, NULL, 0, &args)) {
-		res = -1;
-		goto exit_features_test;
-	}
-	/* hangup zombie channel */
-	ast_hangup(test_channel1);
-	test_channel1 = NULL;
-
-	dynlot = args.pu->parkinglot;
-	if (args.pu->parkingnum != 750
-		|| strcasecmp(dynlot->name, unique_parkinglot)
-		|| dynlot->cfg.parking_start != 750
-		|| dynlot->cfg.parking_stop != 760) {
-		ast_test_status_update(test, "Parking settings were not respected\n");
-		res = -1;
-	} else {
-		ast_test_status_update(test, "Parking settings for masquerading park verified\n");
-	}
-
-	/* find the real channel */
-	parked_chan = ast_channel_get_by_name("TestChannel1");
-	if (unpark_test_channel(parked_chan, &args)) {
-		if (parked_chan) {
-			ast_hangup(parked_chan);
-		}
-		res = -1;
-	}
-
-
-exit_features_test:
-
-	if (test_channel1) {
-		ast_hangup(test_channel1);
-	}
-
-	ast_features_reload();
-	return res ? AST_TEST_FAIL : AST_TEST_PASS;
-}
-#endif
-
-
 /*!
  * \brief set caller and callee according to the direction
  * \param caller, callee, peer, chan, sense
@@ -4332,7 +4127,6 @@
 {
 	struct parkeduser *pu;
 	int res = 0;
-	char parkingslot[AST_MAX_EXTENSION];
 
 	/* Lock parking list */
 	AST_LIST_LOCK(&curlot->parkings);
@@ -4408,6 +4202,8 @@
 					if (comebacktoorigin) {
 						set_c_e_p(chan, parking_con_dial, peername_flat, 1);
 					} else {
+						char parkingslot[AST_MAX_EXTENSION];
+
 						snprintf(parkingslot, sizeof(parkingslot), "%d", pu->parkingnum);
 						pbx_builtin_setvar_helper(chan, "PARKINGSLOT", parkingslot);
 						set_c_e_p(chan, "parkedcallstimeout", peername_flat, 1);
@@ -5814,9 +5610,29 @@
 
 /*!
  * \internal
+ * \brief Remove the given extension if it exists.
+ *
+ * \param context Dialplan database context name.
+ * \param exten Extension to remove.
+ * \param priority Extension priority to remove.
+ *
+ * \return Nothing
+ */
+static void remove_exten_if_exist(const char *context, const char *exten, int priority)
+{
+	struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */
+
+	if (pbx_find_extension(NULL, NULL, &q, context, exten, priority, NULL, NULL,
+		E_MATCH)) {
+		ast_context_remove_extension(context, exten, priority, registrar);
+	}
+}
+
+/*!
+ * \internal
  * \brief Remove unused parking lot access ramp items.
  *
- * \param con Dialplan database context.
+ * \param context Dialplan database context name.
  * \param old_ramps Before configuration reload access ramp usage map.
  * \param new_ramps After configuration reload access ramp usage map.
  *
@@ -5826,7 +5642,7 @@
  *
  * \return Nothing
  */
-static void remove_dead_ramp_usage(struct ast_context *con, struct parking_dp_ramp_map *old_ramps, struct parking_dp_ramp_map *new_ramps)
+static void remove_dead_ramp_usage(const char *context, struct parking_dp_ramp_map *old_ramps, struct parking_dp_ramp_map *new_ramps)
 {
 	struct parking_dp_ramp *old_ramp;
 	struct parking_dp_ramp *new_ramp;
@@ -5843,7 +5659,7 @@
 		cmp = strcmp(old_ramp->exten, new_ramp->exten);
 		if (cmp < 0) {
 			/* New map does not have old ramp. */
-			ast_context_remove_extension2(con, old_ramp->exten, 0, registrar, 0);
+			remove_exten_if_exist(context, old_ramp->exten, 1);
 			old_ramp = AST_LIST_NEXT(old_ramp, node);
 			continue;
 		}
@@ -5858,7 +5674,7 @@
 
 	/* Any old ramps left must be dead. */
 	for (; old_ramp; old_ramp = AST_LIST_NEXT(old_ramp, node)) {
-		ast_context_remove_extension2(con, old_ramp->exten, 0, registrar, 0);
+		remove_exten_if_exist(context, old_ramp->exten, 1);
 	}
 }
 
@@ -5866,25 +5682,26 @@
  * \internal
  * \brief Destroy the given parking space.
  *
- * \param con Dialplan database context.
+ * \param context Dialplan database context name.
  * \param space Parking space.
  *
  * \return Nothing
  */
-static void destroy_space(struct ast_context *con, int space)
+static void destroy_space(const char *context, int space)
 {
 	char exten[AST_MAX_EXTENSION];
 
-	/* Destroy all priorities of the parking space that we registered. */
+	/* Destroy priorities of the parking space that we registered. */
 	snprintf(exten, sizeof(exten), "%d", space);
-	ast_context_remove_extension2(con, exten, 0, registrar, 0);
+	remove_exten_if_exist(context, exten, PRIORITY_HINT);
+	remove_exten_if_exist(context, exten, 1);
 }
 
 /*!
  * \internal
  * \brief Remove unused parking lot space items.
  *
- * \param con Dialplan database context.
+ * \param context Dialplan database context name.
  * \param old_spaces Before configuration reload parking space usage map.
  * \param new_spaces After configuration reload parking space usage map.
  * \param destroy_space Function to destroy parking space item.
@@ -5895,9 +5712,9 @@
  *
  * \return Nothing
  */
-static void remove_dead_spaces_usage(struct ast_context *con,
+static void remove_dead_spaces_usage(const char *context,
 	struct parking_dp_space_map *old_spaces, struct parking_dp_space_map *new_spaces,
-	void (*destroy_space)(struct ast_context *con, int space))
+	void (*destroy_space)(const char *context, int space))
 {
 	struct parking_dp_spaces *old_range;
 	struct parking_dp_spaces *new_range;
@@ -5947,7 +5764,7 @@
 
 		/* Destroy dead parking spaces. */
 		for (; space <= stop; ++space) {
-			destroy_space(con, space);
+			destroy_space(context, space);
 		}
 	}
 }
@@ -5956,7 +5773,7 @@
  * \internal
  * \brief Remove unused parking lot context items.
  *
- * \param con Dialplan database context.
+ * \param context Dialplan database context name.
  * \param old_ctx Before configuration reload context usage map.
  * \param new_ctx After configuration reload context usage map.
  *
@@ -5966,13 +5783,13 @@
  *
  * \return Nothing
  */
-static void remove_dead_context_usage(struct ast_context *con, struct parking_dp_context *old_ctx, struct parking_dp_context *new_ctx)
-{
-	remove_dead_ramp_usage(con, &old_ctx->access_extens, &new_ctx->access_extens);
-	remove_dead_spaces_usage(con, &old_ctx->spaces, &new_ctx->spaces, destroy_space);
+static void remove_dead_context_usage(const char *context, struct parking_dp_context *old_ctx, struct parking_dp_context *new_ctx)
+{
+	remove_dead_ramp_usage(context, &old_ctx->access_extens, &new_ctx->access_extens);
+	remove_dead_spaces_usage(context, &old_ctx->spaces, &new_ctx->spaces, destroy_space);
 #if 0
 	/* I don't think we should destroy hints if the parking space still exists. */
-	remove_dead_spaces_usage(con, &old_ctx->hints, &new_ctx->hints, destroy_space_hint);
+	remove_dead_spaces_usage(context, &old_ctx->hints, &new_ctx->hints, destroy_space_hint);
 #endif
 }
 
@@ -6007,23 +5824,16 @@
 		cmp = strcmp(old_ctx->context, new_ctx->context);
 		if (cmp < 0) {
 			/* New map does not have old map context. */
-			ast_wrlock_contexts();
 			con = ast_context_find(old_ctx->context);
 			if (con) {
 				ast_context_destroy(con, registrar);
 			}
-			ast_unlock_contexts();
 			old_ctx = AST_LIST_NEXT(old_ctx, node);
 			continue;
 		}
 		if (cmp == 0) {
 			/* Old and new map have this context. */
-			ast_wrlock_contexts();
-			con = ast_context_find(old_ctx->context);
-			if (con) {
-				remove_dead_context_usage(con, old_ctx, new_ctx);
-			}
-			ast_unlock_contexts();
+			remove_dead_context_usage(old_ctx->context, old_ctx, new_ctx);
 			old_ctx = AST_LIST_NEXT(old_ctx, node);
 		} else {
 			/* Old map does not have new map context. */
@@ -6033,12 +5843,10 @@
 
 	/* Any old contexts left must be dead. */
 	for (; old_ctx; old_ctx = AST_LIST_NEXT(old_ctx, node)) {
-		ast_wrlock_contexts();
 		con = ast_context_find(old_ctx->context);
 		if (con) {
 			ast_context_destroy(con, registrar);
 		}
-		ast_unlock_contexts();
 	}
 }
 
@@ -7112,6 +6920,445 @@
 	return 0;
 }
 
+#if defined(TEST_FRAMEWORK)
+/*!
+ * \internal
+ * \brief Convert parking spaces map list to a comma separated string.
+ *
+ * \param str String buffer to fill.
+ * \param spaces Parking spaces map list to convert.
+ *
+ * \return Nothing
+ */
+static void create_spaces_str(struct ast_str **str, struct parking_dp_space_map *spaces)
+{
+	const char *comma;
+	struct parking_dp_spaces *cur;
+
+	ast_str_reset(*str);
+	comma = "";
+	AST_LIST_TRAVERSE(spaces, cur, node) {
+		if (cur->start == cur->stop) {
+			ast_str_append(str, 0, "%s%d", comma, cur->start);
+		} else {
+			ast_str_append(str, 0, "%s%d-%d", comma, cur->start, cur->stop);
+		}
+		comma = ",";
+	}
+}
+#endif	/* defined(TEST_FRAMEWORK) */
+
+#if defined(TEST_FRAMEWORK)
+/*!
+ * \internal
+ * \brief Compare parking spaces map to what is expected.
+ *
+ * \param test Unit test context.
+ * \param spaces Parking spaces map list to check.
+ * \param expected String to compare with.
+ * \param what What is being compared.
+ *
+ * \retval 0 successful compare.
+ * \retval nonzero if failed to compare.
+ */
+static int check_spaces(struct ast_test *test, struct parking_dp_space_map *spaces, const char *expected, const char *what)
+{
+	int cmp;
+	struct ast_str *str = ast_str_alloca(1024);
+
+	create_spaces_str(&str, spaces);
+	cmp = strcmp(expected, ast_str_buffer(str));
+	if (cmp) {
+		ast_test_status_update(test,
+			"Unexpected parking space map for %s. Expect:'%s' Got:'%s'\n",
+			what, expected, ast_str_buffer(str));
+	}
+	return cmp;
+}
+#endif	/* defined(TEST_FRAMEWORK) */
+
+#if defined(TEST_FRAMEWORK)
+/*!
+ * \internal
+ * \brief Add a dead space to the dead spaces list.
+ *
+ * \param context Dead spaces list ptr pretending to be a context name ptr.
+ * \param space Dead space to add to the list.
+ *
+ * \return Nothing
+ */
+static void test_add_dead_space(const char *context, int space)
+{
+	struct parking_dp_space_map *dead_spaces = (struct parking_dp_space_map *) context;
+
+	usage_context_add_spaces(dead_spaces, space, space, NULL);
+}
+#endif	/* defined(TEST_FRAMEWORK) */
+
+#if defined(TEST_FRAMEWORK)
+struct test_map {
+	const char *ramp;
+	int start;
+	int stop;
+	const char *expect;
+};
+
+/*!
+ * \internal
+ * \brief Build a parking lot dialplan usage test map from a table.
+ *
+ * \param test Unit test context.
+ * \param lot Parking lot to use to build test usage map.
+ * \param table_name Name of passed in table.
+ * \param table Usage information to put in the usage map.
+ * \param num_entries Number of entries in the table.
+ *
+ * \retval Created context node on success.
+ * \retval NULL on error.
+ */
+static struct parking_dp_context *test_build_maps(struct ast_test *test,
+	struct ast_parkinglot *lot, const char *table_name, const struct test_map *table,
+	size_t num_entries)
+{
+	struct parking_dp_context *ctx_node;
+	int cur_index = 0;
+	char what[40];
+
+	snprintf(what, sizeof(what), "%s[%d]", table_name, cur_index);
+	ast_copy_string(lot->cfg.parkext, table->ramp, sizeof(lot->cfg.parkext));
+	lot->cfg.parking_start = table->start;
+	lot->cfg.parking_stop = table->stop;
+	ctx_node = build_dialplan_useage_context(lot);
+	if (!ctx_node) {
+		ast_test_status_update(test, "Failed to create parking lot context map for %s\n",
+			what);
+		return NULL;
+	}
+	if (check_spaces(test, &ctx_node->spaces, table->expect, what)) {
+		destroy_dialplan_usage_context(ctx_node);
+		return NULL;
+	}
+	while (--num_entries) {
+		++cur_index;
+		++table;
+		snprintf(what, sizeof(what), "%s[%d]", table_name, cur_index);
+		ast_copy_string(lot->cfg.parkext, table->ramp, sizeof(lot->cfg.parkext));
+		lot->cfg.parking_start = table->start;
+		lot->cfg.parking_stop = table->stop;
+		if (dialplan_usage_add_parkinglot_data(ctx_node, lot)) {
+			ast_test_status_update(test, "Failed to add parking lot data for %s\n", what);
+			destroy_dialplan_usage_context(ctx_node);
+			return NULL;
+		}
+		if (check_spaces(test, &ctx_node->spaces, table->expect, what)) {
+			destroy_dialplan_usage_context(ctx_node);
+			return NULL;
+		}
+	}
+	return ctx_node;
+}
+
+static const struct test_map test_old_ctx[] = {
+	/* The following order of building ctx is important to test adding items to the lists. */
+	{ "702", 14, 15, "14-15" },
+	{ "700", 10, 11, "10-11,14-15" },
+	{ "701", 18, 19, "10-11,14-15,18-19" },
+	{ "703", 12, 13, "10-15,18-19" },
+	{ "704", 16, 17, "10-19" },
+	{ "704", 10, 19, "10-19" },
+
+	/* Add more spaces to ctx to test removing dead parking spaces. */
+	{ "705", 21, 23, "10-19,21-23" },
+	{ "706", 26, 29, "10-19,21-23,26-29" },
+	{ "707", 31, 32, "10-19,21-23,26-29,31-32" },
+	{ "708", 36, 38, "10-19,21-23,26-29,31-32,36-38" },
+	{ "708", 40, 41, "10-19,21-23,26-29,31-32,36-38,40-41" },
+};
+
+static const struct test_map test_new_ctx[] = {
+	{ "702", 4, 5, "4-5" },
+	{ "704", 22, 24, "4-5,22-24" },
+	{ "709", 27, 28, "4-5,22-24,27-28" },
+	{ "710", 30, 33, "4-5,22-24,27-28,30-33" },
+	{ "711", 35, 37, "4-5,22-24,27-28,30-33,35-37" },
+};
+#endif	/* defined(TEST_FRAMEWORK) */
+
+#if defined(TEST_FRAMEWORK)
+/*!
+ * \internal
+ * \brief Test parking dialplan usage map code.
+ *
+ * \param test Unit test context.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+static int test_dialplan_usage_map(struct ast_test *test)
+{
+	struct parking_dp_context *old_ctx;
+	struct parking_dp_context *new_ctx;
+	struct ast_parkinglot *lot;
+	struct parking_dp_space_map dead_spaces = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
+	int res;
+
+	ast_test_status_update(test, "Test parking dialplan usage map code\n");
+
+	lot = create_parkinglot("test_lot");
+	if (!lot) {
+		return -1;
+	}
+	ast_copy_string(lot->cfg.parking_con, "test-ctx", sizeof(lot->cfg.parking_con));
+
+	ast_test_status_update(test, "Build old_ctx map\n");
+	old_ctx = test_build_maps(test, lot, "test_old_ctx", test_old_ctx,
+		ARRAY_LEN(test_old_ctx));
+	if (!old_ctx) {
+		ao2_ref(lot, -1);
+		return -1;
+	}
+
+	ast_test_status_update(test, "Build new_ctx map\n");
+	new_ctx = test_build_maps(test, lot, "test_new_ctx", test_new_ctx,
+		ARRAY_LEN(test_new_ctx));
+	if (!new_ctx) {
+		res = -1;
+		goto fail_old_ctx;
+	}
+
+	ast_test_status_update(test, "Test removing dead parking spaces\n");
+	remove_dead_spaces_usage((void *) &dead_spaces, &old_ctx->spaces,
+		&new_ctx->spaces, test_add_dead_space);
+	if (check_spaces(test, &dead_spaces, "10-19,21,26,29,38,40-41", "dead_spaces")) {
+		res = -1;
+		goto fail_new_ctx;
+	}
+
+	res = 0;
+
+fail_new_ctx:
+	destroy_dialplan_usage_context(new_ctx);
+
+fail_old_ctx:
+	destroy_dialplan_usage_context(old_ctx);
+	ao2_ref(lot, -1);
+	return res;
+}
+#endif	/* defined(TEST_FRAMEWORK) */
+
+#if defined(TEST_FRAMEWORK)
+static int fake_fixup(struct ast_channel *clonechan, struct ast_channel *original)
+{
+	return 0;
+}
+#endif	/* defined(TEST_FRAMEWORK) */
+
+#if defined(TEST_FRAMEWORK)
+static struct ast_channel *create_test_channel(const struct ast_channel_tech *fake_tech)
+{
+	struct ast_channel *test_channel1;
+
+	if (!(test_channel1 = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL,
+        NULL, NULL, 0, 0, "TestChannel1"))) {
+		ast_log(LOG_WARNING, "Whoa, test channel creation failed.\n");
+		return NULL;
+	}
+
+	/* normally this is done in the channel driver */
+	test_channel1->nativeformats = AST_FORMAT_GSM;
+	test_channel1->writeformat = AST_FORMAT_GSM;
+	test_channel1->rawwriteformat = AST_FORMAT_GSM;
+	test_channel1->readformat = AST_FORMAT_GSM;
+	test_channel1->rawreadformat = AST_FORMAT_GSM;
+	test_channel1->tech = fake_tech;
+
+	return test_channel1;
+}
+#endif	/* defined(TEST_FRAMEWORK) */
+
+#if defined(TEST_FRAMEWORK)
+static int unpark_test_channel(struct ast_channel *toremove, struct ast_park_call_args *args)
+{
+	struct ast_context *con;
+	struct parkeduser *pu_toremove;
+	int res = 0;
+
+	args->pu->notquiteyet = 1; /* go ahead and stop processing the test parking */
+
+	AST_LIST_LOCK(&args->pu->parkinglot->parkings);
+	AST_LIST_TRAVERSE_SAFE_BEGIN(&args->pu->parkinglot->parkings, pu_toremove, list) {
+		if (pu_toremove == args->pu) {
+			AST_LIST_REMOVE_CURRENT(list);
+			break;
+		}
+	}
+	AST_LIST_TRAVERSE_SAFE_END;
+	AST_LIST_UNLOCK(&args->pu->parkinglot->parkings);
+
+	if (!pu_toremove) {
+		ast_log(LOG_WARNING, "Whoa, could not find parking test call!\n");
+		return -1;
+	}
+
+	con = ast_context_find(args->pu->parkinglot->cfg.parking_con);
+	if (con) {
+		if (ast_context_remove_extension2(con, args->pu->parkingexten, 1, NULL, 0)) {
+			ast_log(LOG_WARNING, "Whoa, failed to remove the parking extension!\n");
+			res = -1;
+		} else {
+			notify_metermaids(args->pu->parkingexten,
+				pu_toremove->parkinglot->cfg.parking_con, AST_DEVICE_NOT_INUSE);
+		}
+	} else {
+		ast_log(LOG_WARNING, "Whoa, no parking context?\n");
+		res = -1;
+	}
+
+	parkinglot_unref(pu_toremove->parkinglot);
+	ast_free(pu_toremove);
+	args->pu = NULL;
+
+	if (!res && toremove) {
+		ast_hangup(toremove);
+	}
+	return res;
+}
+#endif	/* defined(TEST_FRAMEWORK) */
+
+#if defined(TEST_FRAMEWORK)
+AST_TEST_DEFINE(features_test)
+{
+	struct ast_channel *test_channel1 = NULL;
+	struct ast_channel *parked_chan = NULL;
+	struct ast_parkinglot *dynlot;
+	struct ast_park_call_args args = {
+		.timeout = DEFAULT_PARK_TIME,
+	};
+
+	int res = 0;
+
+	static const struct ast_channel_tech fake_tech = {
+		.fixup = fake_fixup, /* silence warning from masquerade */
+	};
+
+	static const char unique_parkinglot[] = "myuniquetestparkinglot3141592654";
+	static const char parkinglot_range[] = "750-760";
+
+	switch (cmd) {
+	case TEST_INIT:
+		info->name = "features_test";
+		info->category = "/main/features/";
+		info->summary = "Features unit test";
+		info->description =
+			"Tests whether parking respects PARKINGLOT settings";
+		return AST_TEST_NOT_RUN;
+	case TEST_EXECUTE:
+		break;
+	}
+
+	if (test_dialplan_usage_map(test)) {
+		res = -1;
+		goto exit_features_test;
+	}
+
+	/* changing a config option is a bad practice, but must be done in this case */
+	parkeddynamic = 1;
+
+	ast_test_status_update(test, "Test parking functionality with defaults\n");
+	if (!(test_channel1 = create_test_channel(&fake_tech))) {
+		res = -1;
+		goto exit_features_test;
+	}
+	if (park_call_full(test_channel1, NULL, &args)) {
+		res = -1;
+		goto exit_features_test;
+	}
+	if (unpark_test_channel(test_channel1, &args)) {
+		res = -1;
+		goto exit_features_test;
+	}
+
+
+	ast_test_status_update(test, "Check that certain parking options are respected\n");
+	if (!(test_channel1 = create_test_channel(&fake_tech))) {
+		res = -1;
+		goto exit_features_test;
+	}
+	pbx_builtin_setvar_helper(test_channel1, "PARKINGLOT", unique_parkinglot);
+	pbx_builtin_setvar_helper(test_channel1, "PARKINGDYNPOS", parkinglot_range);
+	if (park_call_full(test_channel1, NULL, &args)) {
+		res = -1;
+		goto exit_features_test;
+	}
+	/* grab newly created parking lot for destruction in the end */
+	dynlot = args.pu->parkinglot;
+	if (args.pu->parkingnum != 750
+		|| strcasecmp(dynlot->name, unique_parkinglot)
+		|| dynlot->cfg.parking_start != 750
+		|| dynlot->cfg.parking_stop != 760) {
+		ast_test_status_update(test, "Parking settings were not respected\n");
+		if (!unpark_test_channel(test_channel1, &args)) {
+			test_channel1 = NULL;
+		}
+		res = -1;
+		goto exit_features_test;
+	} else {
+		ast_test_status_update(test, "Parking settings for non-masquerading park verified\n");
+	}
+	if (unpark_test_channel(test_channel1, &args)) {
+		res = -1;
+		goto exit_features_test;
+	}
+
+
+	ast_test_status_update(test, "Check #2 that certain parking options are respected\n");
+	if (!(test_channel1 = create_test_channel(&fake_tech))) {
+		res = -1;
+		goto exit_features_test;
+	}
+	pbx_builtin_setvar_helper(test_channel1, "PARKINGLOT", unique_parkinglot);
+	pbx_builtin_setvar_helper(test_channel1, "PARKINGDYNPOS", parkinglot_range);
+	if (masq_park_call(test_channel1, NULL, 0, NULL, 0, &args)) {
+		res = -1;
+		goto exit_features_test;
+	}
+	/* hangup zombie channel */
+	ast_hangup(test_channel1);
+	test_channel1 = NULL;
+
+	dynlot = args.pu->parkinglot;
+	if (args.pu->parkingnum != 750
+		|| strcasecmp(dynlot->name, unique_parkinglot)
+		|| dynlot->cfg.parking_start != 750
+		|| dynlot->cfg.parking_stop != 760) {
+		ast_test_status_update(test, "Parking settings were not respected\n");
+		res = -1;
+	} else {
+		ast_test_status_update(test, "Parking settings for masquerading park verified\n");
+	}
+
+	/* find the real channel */
+	parked_chan = ast_channel_get_by_name("TestChannel1");
+	if (unpark_test_channel(parked_chan, &args)) {
+		if (parked_chan) {
+			ast_hangup(parked_chan);
+		}
+		res = -1;
+	}
+
+
+exit_features_test:
+
+	if (test_channel1) {
+		ast_hangup(test_channel1);
+	}
+
+	force_reload_load = 1;
+	ast_features_reload();
+	return res ? AST_TEST_FAIL : AST_TEST_PASS;
+}
+#endif	/* defined(TEST_FRAMEWORK) */
+
 int ast_features_init(void)
 {
 	int res;
@@ -7138,9 +7385,9 @@
 	}
 
 	res |= ast_devstate_prov_add("Park", metermaidstate);
-#ifdef TEST_FRAMEWORK
+#if defined(TEST_FRAMEWORK)
 	res |= AST_TEST_REGISTER(features_test);
-#endif
+#endif	/* defined(TEST_FRAMEWORK) */
 
 	return res;
 }




More information about the asterisk-commits mailing list