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; +} | 
