aboutsummaryrefslogtreecommitdiffstats
path: root/tests/json/t-json.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/json/t-json.c')
-rw-r--r--tests/json/t-json.c344
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;
+}