sorcery.c: Sorcery enhancements for wizard management

Added ability to specifiy a wizard is read-only when applying
it to a specific object type.  This allows you to specify
create, update and delete callbacks for the wizard but limit
which object types can use them.

Added the ability to allow an object type to have multiple
wizards of the same type.  This is indicated when a wizard
is added to a specific object type.

Added 3 new sorcery wizard functions:

* ast_sorcery_object_type_insert_wizard which does the same thing
  as the existing ast_sorcery_insert_wizard_mapping function but
  accepts the new read-only and allot-duplicates flags and also
  returns the ast_sorcery_wizard structure used and it's internal
  data structure. This allows immediate use of the wizard's
  callbacks without having to register a "wizard mapped" observer.

* ast_sorcery_object_type_apply_wizard which does the same
  thing as the existing ast_sorcery_apply_wizard_mapping function
  but has the added capabilities of
  ast_sorcery_object_type_insert_wizard.

* ast_sorcery_object_type_remove_wizard which removes a wizard
  matching both its name and its original argument string.

* The original logic in __ast_sorcery_insert_wizard_mapping was moved
  to __ast_sorcery_object_type_insert_wizard and enhanced for the
  new capabilities, then __ast_sorcery_insert_wizard_mapping was
  refactored to just call __ast_sorcery_insert_wizard_mapping.

* Added a unit test to test_sorcery.c to test the read-only
  capability.

Change-Id: I40f35840252e4313d99e11dbd80e270a3aa10605
This commit is contained in:
George Joseph
2019-03-14 10:46:53 -06:00
parent 9b5136ddc3
commit 69b194c837
3 changed files with 336 additions and 28 deletions

View File

@@ -3418,6 +3418,13 @@ AST_TEST_DEFINE(wizard_apply_and_insert)
ast_test_validate(test,
ast_sorcery_insert_wizard_mapping(sorcery, "test_object_type", "test2", "test2data", 0, 0) != 0);
ast_test_validate(test,
ast_sorcery_object_type_insert_wizard(sorcery, "test_object_type", "test2", "test2data2",
AST_SORCERY_WIZARD_APPLY_ALLOW_DUPLICATE, 0, NULL, NULL) == 0);
ast_test_validate(test,
ast_sorcery_object_type_remove_wizard(sorcery, "test_object_type", "test2", "test2data2") == 0);
ast_test_validate(test,
ast_sorcery_get_wizard_mapping(sorcery, "test_object_type", 0, &wizard, &data) == 0);
ast_test_validate(test, strcmp("test2", wizard->name) == 0);
@@ -3468,6 +3475,73 @@ AST_TEST_DEFINE(wizard_apply_and_insert)
return AST_TEST_PASS;
}
static struct ast_sorcery_wizard test_read_only_wizard = {
.name = "test-read-only",
.retrieve_id = sorcery_test_retrieve_id,
};
AST_TEST_DEFINE(wizard_read_only)
{
RAII_VAR(struct ast_sorcery *, sorcery, NULL, ast_sorcery_unref);
RAII_VAR(struct ast_sorcery_wizard *, wizard_read_only, &test_read_only_wizard, ast_sorcery_wizard_unregister);
RAII_VAR(struct ast_sorcery_wizard *, wizard1, &test_wizard, ast_sorcery_wizard_unregister);
RAII_VAR(struct test_sorcery_object *, obj, NULL, ao2_cleanup);
struct ast_sorcery_wizard *wizard;
switch (cmd) {
case TEST_INIT:
info->name = "wizard_read_only";
info->category = "/main/sorcery/";
info->summary = "sorcery wizard read-only test";
info->description =
"sorcery wizard read-only test";
return AST_TEST_NOT_RUN;
case TEST_EXECUTE:
break;
}
wizard1->load = sorcery_test_load;
wizard1->reload = sorcery_test_load;
if (!(sorcery = ast_sorcery_open())) {
ast_test_status_update(test, "Failed to open a sorcery instance\n");
return AST_TEST_FAIL;
}
ast_sorcery_wizard_register(wizard_read_only);
ast_sorcery_wizard_register(wizard1);
if ((ast_sorcery_apply_default(sorcery, "test_object_type", "test-read-only", NULL) != AST_SORCERY_APPLY_SUCCESS) ||
ast_sorcery_internal_object_register(sorcery, "test_object_type", test_sorcery_object_alloc, NULL, NULL)) {
ast_test_status_update(test, "Failed to apply object defaults\n");
return AST_TEST_FAIL;
}
ast_test_validate(test,
ast_sorcery_get_wizard_mapping_count(sorcery, "test_object_type") == 1);
ast_test_validate(test,
ast_sorcery_object_type_apply_wizard(sorcery, "test_object_type",
"test", "test2data", AST_SORCERY_WIZARD_APPLY_READONLY, &wizard, NULL) == 0);
ast_test_validate(test, strcmp(wizard->name, wizard1->name) == 0);
ast_test_validate(test,
ast_sorcery_get_wizard_mapping_count(sorcery, "test_object_type") == 2);
if (!(obj = ast_sorcery_alloc(sorcery, "test_object_type", "blah"))) {
ast_test_status_update(test, "Failed to allocate a known object type\n");
return AST_TEST_FAIL;
}
if (ast_sorcery_create(sorcery, obj) == 0) {
ast_test_status_update(test, "Should not have created object using read-only wizard\n");
return AST_TEST_FAIL;
}
return AST_TEST_PASS;
}
static int unload_module(void)
{
AST_TEST_UNREGISTER(wizard_registration);
@@ -3519,6 +3593,7 @@ static int unload_module(void)
AST_TEST_UNREGISTER(instance_observation);
AST_TEST_UNREGISTER(wizard_observation);
AST_TEST_UNREGISTER(wizard_apply_and_insert);
AST_TEST_UNREGISTER(wizard_read_only);
return 0;
}
@@ -3574,6 +3649,7 @@ static int load_module(void)
AST_TEST_REGISTER(global_observation);
AST_TEST_REGISTER(instance_observation);
AST_TEST_REGISTER(wizard_observation);
AST_TEST_REGISTER(wizard_read_only);
return AST_MODULE_LOAD_SUCCESS;
}