diff options
Diffstat (limited to 'tests/json/t-json.c')
-rw-r--r-- | tests/json/t-json.c | 344 |
1 files changed, 344 insertions, 0 deletions
diff --git a/tests/json/t-json.c b/tests/json/t-json.c new file mode 100644 index 00000000..ec294f72 --- /dev/null +++ b/tests/json/t-json.c @@ -0,0 +1,344 @@ +/* t-json.c - Regression test. + Copyright (C) 2018 Bundesamt für Sicherheit in der Informationstechnik + Software engineering by Intevation GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + GPGME 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <sys/stat.h> + +#include <gpgme.h> +#include <gpg-error.h> + +#include "../gpg/t-support.h" +#include "../../src/cJSON.h" + +/* Register tests here */ +static const char*tests[] = { "t-config", NULL }; + +static int verbose = 0; + +static char * +get_file (const char *fname) +{ + gpg_error_t err; + gpgrt_stream_t fp; + struct stat st; + char *buf; + size_t buflen; + + fp = gpgrt_fopen (fname, "r"); + if (!fp) + { + err = gpg_error_from_syserror (); + fprintf (stderr, "Error: can't open '%s': %s\n", fname, + gpg_strerror (err)); + return NULL; + } + + if (fstat (gpgrt_fileno(fp), &st)) + { + err = gpg_error_from_syserror (); + fprintf (stderr, "Error: can't stat '%s': %s\n", fname, + gpg_strerror (err)); + gpgrt_fclose (fp); + return NULL; + } + + buflen = st.st_size; + buf = malloc (buflen+1); + if (!buf) + { + fprintf (stderr, "Error: no mem\n"); + gpgrt_fclose (fp); + return NULL; + } + + if (gpgrt_fread (buf, buflen, 1, fp) != 1) + { + err = gpg_error_from_syserror (); + fprintf (stderr, "error reading '%s': %s\n", fname, gpg_strerror (err)); + gpgrt_fclose (fp); + free (buf); + return NULL; + } + buf[buflen] = 0; + gpgrt_fclose (fp); + + return buf; +} + +/* Check that the element needle exists in hay. Returns 0 if + the needle was found. */ +int +test_contains (cjson_t needle, cjson_t hay) +{ + /*fprintf (stderr, "checking \n%s\n -------against-------- \n%s\n", + cJSON_Print (needle), cJSON_Print (hay)); */ + + /* Type check. This automatically checks bool vals and NULL */ + if (needle->type != hay->type) + { + if (verbose) + fprintf (stderr, "type mismatch expected %i got %i\n", needle->type, + hay->type); + return 1; + } + + /* First the simple types */ + if (cjson_is_number (needle)) + { + if (needle->valueint != hay->valueint) + { + if (verbose) + fprintf (stderr, "Value mismatch. Expected %i got %i\n", + needle->valueint, hay->valueint); + return 1; + } + } + if (cjson_is_string (needle)) + { + if (strcmp (needle->valuestring, hay->valuestring)) + { + if (verbose) + fprintf (stderr, "String mismatch Expected '%s' got '%s'\n", + needle->valuestring, hay->valuestring); + return 1; + } + } + + /* Now the complex types */ + if (needle->child) + { + if (!hay->child) + { + fprintf (stderr, "Depth mismatch. Expected child for %s\n", + nonnull (needle->string)); + } + if (test_contains (needle->child, hay->child)) + { + return 1; + } + } + + if (needle->prev) + { + return 0; + } + + /* Walk elements of an array */ + for (cjson_t it = needle->next; it; it = it->next) + { + int found = 0; + if (!it->string && it->child) + { + /* Try out all other anonymous children on the same level */ + cjson_t hit = hay; + /* Return to the beginning */ + while (hit->prev) + { + hit = hit->prev; + } + for (; hit && hit->child; hit = hit->next) + { + found |= !test_contains (it->child, hit->child); + if (found) + { + break; + } + } + if (!found) + { + return 1; + } + continue; + } + + /* Try the children in the haystack */ + for (cjson_t hit = hay; hit; hit = hit->next) + { + if (hit->string && it->string && + !strcmp (hit->string, it->string)) + { + found = 1; + if (test_contains (it, hit)) + { + return 1; + } + } + } + if (!found) + { + if (verbose) + fprintf (stderr, "Failed to find '%s' in list\n", + nonnull (it->string)); + return 1; + } + } + return 0; +} + + +int +check_response (const char *response, const char *expected) +{ + cjson_t hay; + cjson_t needle; + int rc; + size_t erroff; + + hay = cJSON_Parse (response, &erroff); + + if (!hay) + { + fprintf (stderr, "Failed to parse json at %i:\n%s\n", (int) erroff, + response); + return 1; + } + needle = cJSON_Parse (expected, &erroff); + if (!needle) + { + fprintf (stderr, "Failed to parse json at %i:\n%s\n", (int) erroff, + expected); + cJSON_Delete (hay); + return 1; + } + + rc = test_contains (needle, hay); + + cJSON_Delete (needle); + cJSON_Delete (hay); + return rc; +} + + +int +run_test (const char *test, const char *gpgme_json) +{ + gpgme_ctx_t ctx; + gpgme_data_t json_stdin = NULL; + gpgme_data_t json_stdout = NULL; + gpgme_data_t json_stderr = NULL; + char *test_in; + char *test_out; + const char *argv[2]; + char *response; + char *expected; + size_t response_size; + int rc = 0; + const char *top_srcdir = getenv ("top_srcdir"); + + if (!top_srcdir) + { + fprintf (stderr, "Error top_srcdir environment variable not set\n"); + exit(1); + } + + gpgrt_asprintf (&test_in, "%s//tests//json//%s.in", + top_srcdir, test); + gpgrt_asprintf (&test_out, "%s//tests//json//%s.out", + top_srcdir, test); + + printf ("Running %s...\n", test); + + fail_if_err (gpgme_new (&ctx)); + + gpgme_set_protocol (ctx, GPGME_PROTOCOL_SPAWN); + + fail_if_err (gpgme_data_new_from_file (&json_stdin, test_in, 1)); + fail_if_err (gpgme_data_new (&json_stdout)); + fail_if_err (gpgme_data_new (&json_stderr)); + + argv[0] = gpgme_json; + argv[1] = "-s"; + + fail_if_err (gpgme_op_spawn (ctx, gpgme_json, argv, + json_stdin, + json_stdout, + json_stderr, + 0)); + response = gpgme_data_release_and_get_mem (json_stdout, + &response_size); + test (response_size); + + expected = get_file (test_out); + + test (expected); + + rc = check_response (response, expected); + + if (!rc) + { + printf (" success\n"); + gpgme_data_release (json_stderr); + } + else + { + char *buf; + size_t size; + + buf = gpgme_data_release_and_get_mem (json_stderr, &size); + printf (" failed\n"); + if (size) + { + printf ("gpgme-json stderr:\n%.*s\n", (int)size, buf); + } + free (buf); + } + + free (test_out); + free (test_in); + free (response); + free (expected); + gpgme_data_release (json_stdin); + gpgme_release (ctx); + + return rc; +} + +int +main (int argc, char *argv[]) +{ + const char *gpgme_json = getenv ("gpgme_json"); + + if (argc == 2 && !strcmp (argv[1], "--verbose")) + { + /* Note that verbose will print out lots of mismatchs + because we have to try trough anonymous objects */ + verbose = 1; + } + + + init_gpgme (GPGME_PROTOCOL_SPAWN); + + for (const char **test = tests; *test; test++) + { + if (run_test (*test, gpgme_json)) + { + exit(1); + } + } + return 0; +} |