LCOV - code coverage report
Current view: top level - tests/json - t-json.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 108 161 67.1 %
Date: 2018-11-15 08:49:49 Functions: 5 5 100.0 %

          Line data    Source code
       1             : /* t-json.c - Regression test.
       2             :    Copyright (C) 2018 Bundesamt für Sicherheit in der Informationstechnik
       3             :                       Software engineering by Intevation GmbH
       4             : 
       5             :    This file is part of GPGME.
       6             : 
       7             :    GPGME is free software; you can redistribute it and/or modify it
       8             :    under the terms of the GNU Lesser General Public License as
       9             :    published by the Free Software Foundation; either version 2.1 of
      10             :    the License, or (at your option) any later version.
      11             : 
      12             :    GPGME is distributed in the hope that it will be useful, but
      13             :    WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15             :    Lesser General Public License for more details.
      16             : 
      17             :    You should have received a copy of the GNU Lesser General Public
      18             :    License along with this program; if not, write to the Free Software
      19             :    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
      20             :    02111-1307, USA.  */
      21             : 
      22             : #ifdef HAVE_CONFIG_H
      23             : # include <config.h>
      24             : #endif
      25             : 
      26             : #include <stdlib.h>
      27             : #include <stdio.h>
      28             : #include <string.h>
      29             : #include <errno.h>
      30             : #include <sys/stat.h>
      31             : 
      32             : #include <gpgme.h>
      33             : #include <gpg-error.h>
      34             : 
      35             : #include "../gpg/t-support.h"
      36             : #include "../../src/cJSON.h"
      37             : 
      38             : /* Register tests here */
      39             : static const char*tests[] = { "t-config", "t-version",
      40             :     "t-keylist", "t-keylist-secret", "t-decrypt", "t-config-opt",
      41             :     "t-encrypt", "t-encrypt-sign", "t-sign", "t-verify",
      42             :     "t-decrypt-verify", "t-export", "t-createkey",
      43             :     "t-export-secret-info", "t-chunking", "t-sig-notations",
      44             :     /* For these two the order is important
      45             :      * as t-import imports the deleted key from t-delete */
      46             :     "t-delete", "t-import",
      47             :     NULL };
      48             : 
      49             : static int verbose = 0;
      50             : 
      51             : static char *
      52          18 : get_file (const char *fname)
      53             : {
      54             :   gpg_error_t err;
      55             :   gpgrt_stream_t fp;
      56             :   struct stat st;
      57             :   char *buf;
      58             :   size_t buflen;
      59             : 
      60          18 :   fp = gpgrt_fopen (fname, "r");
      61          18 :   if (!fp)
      62             :     {
      63           0 :       err = gpg_error_from_syserror ();
      64           0 :       fprintf (stderr, "Error: can't open '%s': %s\n", fname,
      65             :                gpg_strerror (err));
      66           0 :       return NULL;
      67             :     }
      68             : 
      69          18 :   if (fstat (gpgrt_fileno(fp), &st))
      70             :     {
      71           0 :       err = gpg_error_from_syserror ();
      72           0 :       fprintf (stderr, "Error: can't stat '%s': %s\n", fname,
      73             :                gpg_strerror (err));
      74           0 :       gpgrt_fclose (fp);
      75           0 :       return NULL;
      76             :     }
      77             : 
      78          18 :   buflen = st.st_size;
      79          18 :   buf = malloc (buflen+1);
      80          18 :   if (!buf)
      81             :     {
      82           0 :       fprintf (stderr, "Error: no mem\n");
      83           0 :       gpgrt_fclose (fp);
      84           0 :       return NULL;
      85             :     }
      86             : 
      87          18 :   if (gpgrt_fread (buf, buflen, 1, fp) != 1)
      88             :     {
      89           0 :       err = gpg_error_from_syserror ();
      90           0 :       fprintf (stderr, "error reading '%s': %s\n", fname, gpg_strerror (err));
      91           0 :       gpgrt_fclose (fp);
      92           0 :       free (buf);
      93           0 :       return NULL;
      94             :     }
      95          18 :   buf[buflen] = 0;
      96          18 :   gpgrt_fclose (fp);
      97             : 
      98          18 :   return buf;
      99             : }
     100             : 
     101             : /* Check that the element needle exists in hay. Returns 0 if
     102             :    the needle was found. */
     103             : int
     104         504 : test_contains (cjson_t needle, cjson_t hay)
     105             : {
     106         504 :   if (verbose == 2)
     107           0 :     fprintf (stderr, "%s: -------checking-------- "
     108             :                      "\n%s\n -------against-------- \n%s\n",
     109           0 :              nonnull (needle->string), cJSON_Print (needle),
     110             :              cJSON_Print (hay));
     111             : 
     112             :   /* Type check. This automatically checks bool vals and NULL */
     113         504 :   if (needle->type != hay->type)
     114             :     {
     115          10 :       if (verbose)
     116           0 :         fprintf (stderr, "%s: type mismatch expected %i got %i\n",
     117           0 :                  nonnull (needle->string), needle->type,
     118             :                  hay->type);
     119          10 :       return 1;
     120             :     }
     121             : 
     122             :   /* First the simple types */
     123         494 :   if (cjson_is_number (needle))
     124             :     {
     125          73 :       if (needle->valueint != hay->valueint)
     126             :         {
     127           0 :           if (verbose)
     128           0 :             fprintf (stderr, "%s: value mismatch. Expected %i got %i\n",
     129           0 :                      nonnull (needle->string), needle->valueint,
     130             :                      hay->valueint);
     131           0 :           return 1;
     132             :         }
     133             :     }
     134         494 :   if (cjson_is_string (needle))
     135             :     {
     136         157 :       if (strcmp (needle->valuestring, hay->valuestring) &&
     137             :           /* Use * as a general don't care placeholder */
     138          17 :           strcmp (needle->valuestring, "*"))
     139             :         {
     140          14 :           if (verbose)
     141           0 :             fprintf (stderr, "%s: string mismatch Expected '%s' got '%s'\n",
     142             :                      needle->string, needle->valuestring, hay->valuestring);
     143          14 :           return 1;
     144             :         }
     145             :     }
     146             : 
     147             :   /* Now the complex types */
     148         480 :   if (needle->child)
     149             :     {
     150          65 :       if (!hay->child)
     151             :         {
     152           0 :           fprintf (stderr, "Depth mismatch. Expected child for %s\n",
     153           0 :                    nonnull (needle->string));
     154             :         }
     155          65 :       if (test_contains (needle->child, hay->child))
     156             :         {
     157           3 :           int found = 0;
     158           6 :           for (cjson_t hit = hay->child; hit; hit = hit->next)
     159             :             {
     160           6 :               found |= !test_contains (needle->child, hit);
     161           6 :               if (found)
     162             :                 {
     163           3 :                   break;
     164             :                 }
     165             :             }
     166           3 :           if (!found)
     167             :             {
     168           0 :               return 1;
     169             :             }
     170             :         }
     171             :     }
     172             : 
     173         480 :   if (needle->prev)
     174             :     {
     175         376 :       return 0;
     176             :     }
     177             : 
     178             :   /* Walk elements of an array */
     179         492 :   for (cjson_t it = needle->next; it; it = it->next)
     180             :     {
     181         397 :       int found = 0;
     182         397 :       if (!it->string && it->child)
     183             :         {
     184             :           /* Try out all other anonymous children on the same level */
     185          12 :           cjson_t hit = hay;
     186             :           /* Return to the beginning */
     187          24 :           while (hit->prev)
     188             :             {
     189           0 :               hit = hit->prev;
     190             :             }
     191          30 :           for (; hit && hit->child; hit = hit->next)
     192             :             {
     193          30 :               found |= !test_contains (it->child, hit->child);
     194          30 :               if (found)
     195             :                 {
     196          12 :                   break;
     197             :                 }
     198             :             }
     199          12 :           if (!found)
     200             :             {
     201           0 :               return 1;
     202             :             }
     203          12 :           continue;
     204             :         }
     205             : 
     206             :       /* Try the children in the haystack */
     207        5658 :       for (cjson_t hit = hay; hit; hit = hit->next)
     208             :         {
     209       10564 :           if (hit->string && it->string &&
     210        5282 :               !strcmp (hit->string, it->string))
     211             :             {
     212         385 :               found = 1;
     213         385 :               if (test_contains (it, hit))
     214             :                 {
     215           9 :                   return 1;
     216             :                 }
     217             :             }
     218             :         }
     219         376 :       if (!found)
     220             :         {
     221           0 :           if (verbose)
     222           0 :             fprintf (stderr, "Failed to find '%s' in list\n",
     223           0 :                      nonnull (it->string));
     224           0 :           return 1;
     225             :         }
     226             :     }
     227          95 :   return 0;
     228             : }
     229             : 
     230             : 
     231             : int
     232          18 : check_response (const char *response, const char *expected)
     233             : {
     234             :   cjson_t hay;
     235             :   cjson_t needle;
     236             :   int rc;
     237             :   size_t erroff;
     238             : 
     239          18 :   hay = cJSON_Parse (response, &erroff);
     240             : 
     241          18 :   if (!hay)
     242             :     {
     243           0 :       fprintf (stderr, "Failed to parse json at %i:\n%s\n", (int) erroff,
     244             :                response);
     245           0 :       return 1;
     246             :     }
     247          18 :   needle = cJSON_Parse (expected, &erroff);
     248          18 :   if (!needle)
     249             :     {
     250           0 :       fprintf (stderr, "Failed to parse json at %i:\n%s\n", (int) erroff,
     251             :                expected);
     252           0 :       cJSON_Delete (hay);
     253           0 :       return 1;
     254             :     }
     255             : 
     256          18 :   rc = test_contains (needle, hay);
     257             : 
     258          18 :   cJSON_Delete (needle);
     259          18 :   cJSON_Delete (hay);
     260          18 :   return rc;
     261             : }
     262             : 
     263             : 
     264             : int
     265          18 : run_test (const char *test, const char *gpgme_json)
     266             : {
     267             :   gpgme_ctx_t ctx;
     268          18 :   gpgme_data_t json_stdin = NULL;
     269          18 :   gpgme_data_t json_stdout = NULL;
     270          18 :   gpgme_data_t json_stderr = NULL;
     271             :   char *test_in;
     272             :   char *test_out;
     273             :   const char *argv[3];
     274             :   char *response;
     275          18 :   char *expected = NULL;
     276             :   size_t response_size;
     277          18 :   int rc = 0;
     278          18 :   const char *top_srcdir = getenv ("top_srcdir");
     279             : 
     280          18 :   if (!top_srcdir)
     281             :     {
     282           0 :       fprintf (stderr, "Error top_srcdir environment variable not set\n");
     283           0 :       exit(1);
     284             :     }
     285             : 
     286          18 :   gpgrt_asprintf (&test_in, "%s/tests/json/%s.in.json",
     287             :                   top_srcdir, test);
     288          18 :   gpgrt_asprintf (&test_out, "%s/tests/json/%s.out.json",
     289             :                   top_srcdir, test);
     290             : 
     291          18 :   printf ("Running %s...\n", test);
     292             : 
     293          18 :   fail_if_err (gpgme_new (&ctx));
     294             : 
     295          18 :   gpgme_set_protocol (ctx, GPGME_PROTOCOL_SPAWN);
     296             : 
     297          18 :   fail_if_err (gpgme_data_new_from_file (&json_stdin, test_in, 1));
     298          18 :   fail_if_err (gpgme_data_new (&json_stdout));
     299          18 :   fail_if_err (gpgme_data_new (&json_stderr));
     300             : 
     301          18 :   argv[0] = gpgme_json;
     302          18 :   argv[1] = "-s";
     303          18 :   argv[2] = NULL;
     304             : 
     305          18 :   fail_if_err (gpgme_op_spawn (ctx, gpgme_json, argv,
     306             :                                json_stdin,
     307             :                                json_stdout,
     308             :                                json_stderr,
     309             :                                0));
     310          18 :   response = gpgme_data_release_and_get_mem (json_stdout,
     311             :                                              &response_size);
     312          18 :   if (response_size)
     313             :     {
     314          18 :       expected = get_file (test_out);
     315             : 
     316          18 :       test (expected);
     317             : 
     318          18 :       rc = check_response (response, expected);
     319             :     }
     320             :   else
     321             :     {
     322           0 :       rc = 1;
     323             :     }
     324             : 
     325          18 :   if (!rc)
     326             :     {
     327          18 :       printf (" success\n");
     328          18 :       gpgme_data_release (json_stderr);
     329             :     }
     330             :   else
     331             :     {
     332             :       char *buf;
     333             :       size_t size;
     334             : 
     335           0 :       buf = gpgme_data_release_and_get_mem (json_stderr, &size);
     336           0 :       printf (" failed%s\n", response_size ? "" :
     337             :                              ", no response from gpgme-json");
     338           0 :       if (size)
     339             :         {
     340           0 :           printf ("gpgme-json stderr:\n%.*s\n", (int)size, buf);
     341             :         }
     342           0 :       free (buf);
     343             :     }
     344             : 
     345          18 :   free (test_out);
     346          18 :   free (test_in);
     347          18 :   free (response);
     348          18 :   free (expected);
     349          18 :   gpgme_data_release (json_stdin);
     350          18 :   gpgme_release (ctx);
     351             : 
     352          18 :   return rc;
     353             : }
     354             : 
     355             : int
     356           1 : main (int argc, char *argv[])
     357             : {
     358           1 :   const char *gpgme_json = getenv ("gpgme_json");
     359           1 :   int last_argc = -1;
     360             : 
     361           1 :   if (argc)
     362           1 :     { argc--; argv++; }
     363             : 
     364             : 
     365           2 :   while (argc && last_argc != argc )
     366             :     {
     367           0 :       last_argc = argc;
     368           0 :       if (!strcmp (*argv, "--verbose"))
     369             :         {
     370           0 :           verbose++;
     371           0 :           argc--; argv++;
     372             :         }
     373             :     }
     374             : 
     375           1 :   if (!check_gpg_version ("2.2.0"))
     376             :     {
     377             :       /* Lets not break too much or have to test all combinations */
     378           0 :       printf ("Testsuite skipped. Minimum GnuPG version (2.2.0) "
     379             :               "not found.\n");
     380           0 :       exit(0);
     381             :     }
     382             : 
     383           1 :   init_gpgme (GPGME_PROTOCOL_SPAWN);
     384             : 
     385          19 :   for (const char **test = tests; *test; test++)
     386             :     {
     387          18 :       if (run_test (*test, gpgme_json))
     388             :         {
     389           0 :           exit(1);
     390             :         }
     391             :     }
     392           1 :   return 0;
     393             : }

Generated by: LCOV version 1.13