merchant

Merchant backend to process payments, run by merchants
Log | Files | Refs | Submodules | README | LICENSE

commit 18f9c6be2a7583af533e0253a8f40f76e5d916b3
parent 6efc5477e7bebfc1d251d06b57baf08080d8ff93
Author: priscilla <priscilla.huang@efrei.net>
Date:   Thu, 17 Nov 2022 09:54:27 -0500

test

Diffstat:
Msrc/backenddb/plugin_merchantdb_postgres.c | 2+-
Msrc/backenddb/test_merchantdb.c | 429++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 427 insertions(+), 4 deletions(-)

diff --git a/src/backenddb/plugin_merchantdb_postgres.c b/src/backenddb/plugin_merchantdb_postgres.c @@ -6820,7 +6820,7 @@ postgres_insert_pickup_blind_signature ( * Delete information about a template. * * @param cls closure - * @param instance_id instance to delete product of + * @param instance_id instance to delete template of * @param template_id template to delete * @return DB status code, #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS * if template unknow. diff --git a/src/backenddb/test_merchantdb.c b/src/backenddb/test_merchantdb.c @@ -6889,9 +6889,9 @@ run (void *cls) plugin->preflight (plugin->cls); result = run_tests (); - if (0 == result) - /* result = run_template_tests (); - if (0 == result)*/ + if (0 == result) + result = run_template_tests (); + if (0 == result) { /* Test dropping tables */ if (GNUNET_OK != plugin->drop_tables (plugin->cls)) @@ -6954,7 +6954,430 @@ main (int argc, } +/* *********** Templates ********** */ +/** + * A container for data relevant to a template. + */ +struct TemplateData +{ + /** + * The identifier of the template. + */ + const char *id; + + /** + * The details of the template. + */ + struct TALER_MERCHANTDB_TemplateDetails template; +}; + + +/** + * Creates a template for testing with. + * + * @param id the id of the template. + * @param template the template data to fill. + */ +static void +make_template (const char *id, + struct TemplateData *template) +{ + template->id = id; + template->template.template_description = "This is a test template"; + template->template.image = GNUNET_strdup (""); + GNUNET_assert (NULL != template->template.image); + template->template.template_contract = json_array (); + GNUNET_assert (NULL != template->template.template_contract); +} + + +/** + * Frees memory associated with @e TemplateData. + * + * @param product the container to free. + */ +static void +free_template_data (struct TemplateData *template) +{ + GNUNET_free (template->template.image); + json_decref (template->template.template_contract); +} + + +/** + * Compare two template for equality. + * + * @param a the first template. + * @param b the second template. + * @return 0 on equality, 1 otherwise. + */ +static int +check_template_equal (const struct TALER_MERCHANTDB_TemplateDetails *a, + const struct TALER_MERCHANTDB_TemplateDetails *b) +{ + if ((0 != strcmp (a->template_description, + b->template_description)) || + (0 != strcmp (a->image, + b->image)) || + (1 != json_equal (a->template_contract, + b->template_contract)) + return 1; + return 0; +} + + +/** + * Tests inserting template data into the database. + * + * @param instance the instance to insert the template for. + * @param template the template data to insert. + * @param expected_result the result we expect the db to return. + * @return 0 when successful, 1 otherwise. + */ +static int +test_insert_template (const struct InstanceData *instance, + const struct TemplateData *template, + enum GNUNET_DB_QueryStatus expected_result) +{ + TEST_COND_RET_ON_FAIL (expected_result == + plugin->insert_template (plugin->cls, + instance->instance.id, + template->id, + &template->template), + "Insert template failed\n"); + return 0; +} + + +/** + * Tests updating template data in the database. + * + * @param instance the instance to update the template for. + * @param template the template data to update. + * @param expected_result the result we expect the db to return. + * @return 0 when successful, 1 otherwise. + */ +static int +test_update_template (const struct InstanceData *instance, + const struct TemplateData *template, + enum GNUNET_DB_QueryStatus expected_result) +{ + TEST_COND_RET_ON_FAIL (expected_result == + plugin->update_template (plugin->cls, + instance->instance.id, + template->id, + &template->template), + "Update template failed\n"); + return 0; +} + + +/** + * Tests looking up a template from the db. + * + * @param instance the instance to query from. + * @param template the template to query and compare to. + * @return 0 when successful, 1 otherwise. + */ +static int +test_lookup_template (const struct InstanceData *instance, + const struct TemplateData *template) +{ + struct TALER_MERCHANTDB_TemplateDetails lookup_result; + if (0 > plugin->lookup_template (plugin->cls, + instance->instance.id, + template->id, + &lookup_result)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Lookup template failed\n"); + TALER_MERCHANTDB_template_details_free (&lookup_result); + return 1; + } + const struct TALER_MERCHANTDB_TemplateDetails *to_cmp = &template->template; + if (0 != check_templates_equal (&lookup_result, + to_cmp)) + { + GNUNET_break (0); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Lookup template failed: incorrect template returned\n"); + TALER_MERCHANTDB_template_details_free (&lookup_result); + return 1; + } + TALER_MERCHANTDB_template_details_free (&lookup_result); + return 0; +} + + +/** + * Closure for testing template lookup + */ +struct TestLookupTemplates_Closure +{ + /** + * Number of template ids to compare to + */ + unsigned int template_to_cmp_length; + + /** + * Pointer to array of template ids + */ + const struct TemplateData *templates_to_cmp; + + /** + * Pointer to array of number of matches for each product + */ + unsigned int *results_matching; + + /** + * Total number of results returned + */ + unsigned int results_length; +}; + + +/** + * Function called after calling @e test_lookup_templates + * + * @param cls a pointer to the lookup closure. + * @param template_id the identifier of the template found. + */ +static void +lookup_templates_cb (void *cls, + const char *template_id) +{ + struct TestLookupTemplates_Closure *cmp = cls; + if (NULL == cmp) + return; + cmp->results_length += 1; + for (unsigned int i = 0; cmp->templates_to_cmp_length > i; ++i) + { + if (0 == strcmp (cmp->templates_to_cmp[i].id, + template_id)) + cmp->results_matching[i] += 1; + } +} + + +/** + * Tests looking up all templates for an instance. + * + * @param instance the instance to query from. + * @param templates_length the number of templates we are expecting. + * @param templates the list of templates that we expect to be found. + * @return 0 when successful, 1 otherwise. + */ +static int +test_lookup_templates (const struct InstanceData *instance, + unsigned int templates_length, + const struct TemplateData *templates) +{ + unsigned int results_matching[templates_length]; + struct TestLookupTemplates_Closure cls = { + .templates_to_cmp_length = templates_length, + .templates_to_cmp = templates, + .results_matching = results_matching, + .results_length = 0 + }; + memset (results_matching, 0, sizeof (unsigned int) * templates_length); + if (0 > plugin->lookup_templates (plugin->cls, + instance->instance.id, + &lookup_templates_cb, + &cls)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Lookup templates failed\n"); + return 1; + } + if (templates_length != cls.results_length) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Lookup templates failed: incorrect number of results\n"); + return 1; + } + for (unsigned int i = 0; templates_length > i; ++i) + { + if (1 != cls.results_matching[i]) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Lookup templates failed: mismatched data\n"); + return 1; + } + } + return 0; +} + + +/** + * Tests deleting a template. + * + * @param instance the instance to delete the template from. + * @param template the template that should be deleted. + * @param expected_result the result that we expect the plugin to return. + * @return 0 when successful, 1 otherwise. + */ +static int +test_delete_template (const struct InstanceData *instance, + const struct TemplateData *template, + enum GNUNET_DB_QueryStatus expected_result) +{ + TEST_COND_RET_ON_FAIL (expected_result == + plugin->delete_template (plugin->cls, + instance->instance.id, + template->id), + "Delete template failed\n"); + return 0; +} + + +/** + * Closure for template tests. + */ +struct TestTemplates_Closure +{ + /** + * The instance to use for this test. + */ + struct InstanceData instance; + + /** + * The array of templates. + */ + struct TemplateData templates[2]; +}; + + +/** + * Sets up the data structures used in the template tests. + * + * @param cls the closure to fill with test data. + */ +static void +pre_test_templates (struct TestTemplates_Closure *cls) +{ + /* Instance */ + make_instance ("test_inst_templates", + &cls->instance); + + /* Templates */ + make_template ("test_templates_pd_0", + &cls->templates[0]); + + make_template ("test_templates_pd_1", + &cls->templates[1]); + cls->templates[1].template.template_description = "This is a another test template"; +} + + +/** + * Handles all teardown after testing. + * + * @param cls the closure containing memory to be freed. + */ +static void +post_test_templates (struct TestTemplates_Closure *cls) +{ + free_instance_data (&cls->instance); + free_template_data (&cls->templates[0]); + free_template_data (&cls->templates[1]); +} + + +/** + * Runs the tests for templates. + * + * @param cls the container of the test data. + * @return 0 on success, 1 otherwise. + */ +static int +run_test_templates (struct TestProducts_Closure *cls) +{ + struct GNUNET_Uuid uuid; + struct GNUNET_TIME_Timestamp refund_deadline = + GNUNET_TIME_relative_to_timestamp (GNUNET_TIME_UNIT_WEEKS); + + /* Test that insert without an instance fails */ + TEST_RET_ON_FAIL (test_insert_template (&cls->instance, + &cls->templates[0], + GNUNET_DB_STATUS_SUCCESS_NO_RESULTS)); + /* Insert the instance */ + TEST_RET_ON_FAIL (test_insert_instance (&cls->instance, + GNUNET_DB_STATUS_SUCCESS_ONE_RESULT)); + /* Test inserting a template */ + TEST_RET_ON_FAIL (test_insert_template (&cls->instance, + &cls->templates[0], + GNUNET_DB_STATUS_SUCCESS_ONE_RESULT)); + /* Test that double insert fails */ + TEST_RET_ON_FAIL (test_insert_template (&cls->instance, + &cls->templates[0], + GNUNET_DB_STATUS_SUCCESS_NO_RESULTS)); + /* Test lookup of individual templates */ + TEST_RET_ON_FAIL (test_lookup_template (&cls->instance, + &cls->templates[0])); + /* Make sure it fails correctly for templates that don't exist */ + if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != + plugin->lookup_template (plugin->cls, + cls->instance.instance.id, + "nonexistent_template", + NULL)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Lookup template failed\n"); + return 1; + } + /* Test template update */ + cls->templates[0].template.template_description = + "This is a test template that has been updated!"; + GNUNET_free (cls->templates[0].template.image); + cls->templates[0].template.image = GNUNET_strdup ("image"); + GNUNET_assert (0 == + json_array_append_new (cls->templates[0].template.template_contract, + json_string ("This is a test. 3CH."))); + TEST_RET_ON_FAIL (test_update_template (&cls->instance, + &cls->templates[0], + GNUNET_DB_STATUS_SUCCESS_ONE_RESULT)); + + TEST_RET_ON_FAIL (test_lookup_template (&cls->instance, + &cls->templates[0])); + TEST_RET_ON_FAIL (test_update_template (&cls->instance, + &cls->templates[1], + GNUNET_DB_STATUS_SUCCESS_NO_RESULTS)); + /* Test collective template lookup */ + TEST_RET_ON_FAIL (test_insert_template (&cls->instance, + &cls->templates[1], + GNUNET_DB_STATUS_SUCCESS_ONE_RESULT)); + TEST_RET_ON_FAIL (test_lookup_templates (&cls->instance, + 2, + cls->templates)); + + /* Test template deletion */ + TEST_RET_ON_FAIL (test_delete_template (&cls->instance, + &cls->templates[1], + GNUNET_DB_STATUS_SUCCESS_ONE_RESULT)); + /* Test double deletion fails */ + TEST_RET_ON_FAIL (test_delete_template (&cls->instance, + &cls->templates[1], + GNUNET_DB_STATUS_SUCCESS_NO_RESULTS)); + TEST_RET_ON_FAIL (test_lookup_templates (&cls->instance, + 1, + cls->templates)); + + +/** + * Takes care of template testing. + * + * @return 0 on success, 1 otherwise. + */ +static int +test_templates (void) +{ + struct TestTemplates_Closure test_cls; + pre_test_templates (&test_cls); + int test_result = run_test_templates (&test_cls); + post_test_templates (&test_cls); + return test_result; +} /* end of test_merchantdb.c */