poke-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH] pk_mi_json convert functions and tests.


From: Jose E. Marchesi
Subject: Re: [PATCH] pk_mi_json convert functions and tests.
Date: Tue, 28 Jul 2020 22:55:53 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/28.0.50 (gnu/linux)

Hi Kostas!
Thanks for the patch.

> diff --git a/poke/pk-mi-json.c b/poke/pk-mi-json.c
> index 3ec81924..80601b5a 100644
> --- a/poke/pk-mi-json.c
> +++ b/poke/pk-mi-json.c
> @@ -26,6 +26,24 @@
>  #include "pk-mi.h"
>  #include "pk-mi-json.h"
>  #include "pk-mi-msg.h"
> +#include "libpoke.h"
> +
> +#define PK_MI_CHECK(errmsg, A, M, ...) \
> +   do                                  \
> +    {                                  \
> +      if (!(A))                        \
> +        {                              \
> +          if (errmsg == NULL)          \
> +            goto error;                \
> +          assert (asprintf (errmsg, "[ERROR] " M , ##__VA_ARGS__) != -1); \
> +          goto error;                  \
> +        }                              \
> +    }                                  \
> +    while (0)
> +
> +#define PK_MI_DEBUG(M, ...)                  \
> +      fprintf (stderr, "DEBUG %s:%d: " M "\n",\
> +        __FILE__, __LINE__, ##__VA_ARGS__)

PK_MI_DEBUG doesn't seem to be used anywhere... please remove it :)

>  /* Message::
>     {
> @@ -422,7 +440,7 @@ pk_mi_json_to_msg (const char *str)
>  {
>    pk_mi_msg msg = NULL;
>    struct json_tokener *tokener;
> -  json_object *json;
> +  struct json_object *json;

Hm?  Why?  Isn't `json_object' a typedef of `struct json_object'?

> diff --git a/testsuite/poke.mi-json/mi-json.c 
> b/testsuite/poke.mi-json/mi-json.c
> index 4b7aea69..863f377c 100644
> --- a/testsuite/poke.mi-json/mi-json.c
> +++ b/testsuite/poke.mi-json/mi-json.c
> @@ -20,9 +20,14 @@
>  
>  #include <stdlib.h>
>  #include <dejagnu.h>
> +#include <json.h>
>  
>  #include "pk-mi-msg.h"
>  #include "pk-mi-json.h"
> +#include "libpoke.h"
> +
> +#define PASS 1
> +#define FAIL 0
>  
>  void
>  test_json_to_msg ()
> @@ -37,6 +42,1023 @@ test_json_to_msg ()
>      fail ("json_to_msg_1");
>  }
>  
> +static int
> +test_json_to_int (const char *pk_int_str_obj)
> +{
> +  pk_val pk_int;
> +  int signed_p;
> +  char *errmsg;
> +
> +  if (pk_mi_json_to_val (&pk_int, pk_int_str_obj, &errmsg) == -1)
> +    return FAIL;
> +
> +  if (pk_type_code (pk_typeof (pk_int)) != PK_INT)
> +    return FAIL;
> +
> +  signed_p = pk_uint_value (pk_integral_type_signed_p (pk_typeof (pk_int)));
> +  if (!signed_p)
> +    return FAIL;
> +
> +  /* Testing with hard-coded values described on test_json_to_val.
> +     (NOTE to jemarch): if he agrees with this approach.  */
> +  if (pk_int_value (pk_int) != -3500)
> +    return FAIL;
> +
> +  if (pk_int_size (pk_int) != 32)
> +    return FAIL;

Good try, but over my cold dead body :P

Just pass the expected value in an int64_t to test_json_to_int, and use
it.  Coupling, coupling!

> +
> +  return PASS;
> +}
> +
> +static int
> +test_json_to_uint (const char *pk_uint_str_obj)
> +{
> +  pk_val pk_uint;
> +  int signed_p;
> +
> +  if (pk_mi_json_to_val (&pk_uint, pk_uint_str_obj, NULL) == -1)
> +    return FAIL;
> +
> +  if (pk_type_code (pk_typeof (pk_uint)) != PK_INT)
> +    return FAIL;
> +
> +  signed_p = pk_uint_value (pk_integral_type_signed_p (pk_typeof (pk_uint)));
> +  if (signed_p)
> +    return FAIL;
> +
> +  if (pk_uint_value (pk_uint) != 3500)
> +    return FAIL;
> +
> +  if (pk_uint_size (pk_uint) != 32)
> +    return FAIL;

Ditto!

> +
> +  return PASS;
> +}
> +
> +static int
> +test_json_to_string (const char *pk_string_str_obj)
> +{
> +  pk_val pk_string;
> +  const char *pk_string_value;
> +
> +  if (pk_mi_json_to_val (&pk_string, pk_string_str_obj, NULL) == -1)
> +    return FAIL;
> +
> +  if (pk_type_code (pk_typeof (pk_string)) != PK_STRING)
> +    return FAIL;
> +
> +  pk_string_value = pk_string_str (pk_string);
> +  if (strncmp (pk_string_value, "kostas", strlen ("kostas")))
> +    return FAIL;

Ditto!

> +
> +  return PASS;
> +}
> +
> +static int
> +test_json_to_offset (const char *pk_offset_str_obj)
> +{
> +  pk_val pk_offset, pk_magnitude, pk_unit;
> +  int signed_p;
> +
> +  if (pk_mi_json_to_val (&pk_offset, pk_offset_str_obj, NULL) == -1)
> +    return FAIL;
> +
> +  if (pk_type_code (pk_typeof (pk_offset)) != PK_OFFSET)
> +    return FAIL;
> +
> +  pk_magnitude = pk_offset_magnitude (pk_offset);
> +  pk_unit = pk_offset_unit (pk_offset);
> +
> +  signed_p = pk_uint_value (pk_integral_type_signed_p (pk_typeof 
> (pk_magnitude)));
> +  if (signed_p)
> +    return FAIL;
> +
> +  if (pk_uint_value (pk_magnitude) != 3500)
> +    return FAIL;
> +
> +  if (pk_uint_size (pk_magnitude) != 32)
> +    return FAIL;
> +
> +  if (pk_uint_value (pk_unit) != 3500)
> +    return FAIL;
> +
> +  if (pk_uint_size (pk_unit) != 64)
> +    return FAIL;
> +
> +  return PASS;
> +}

Ditto!

> +
> +static int
> +test_json_to_null (const char *pk_null_str_obj)
> +{
> +  pk_val pk_null;
> +
> +  if (pk_mi_json_to_val (&pk_null, pk_null_str_obj, NULL) == -1)
> +    return FAIL;
> +
> +  if (pk_null != PK_NULL)
> +    return FAIL;
> +
> +  return PASS;
> +}

Here is ok :D

> +
> +static int
> +test_json_to_sct (const char *pk_sct_str_obj)
> +{
> +  pk_val pk_sct, pk_sct_name, pk_sct_fname, pk_sct_foffset, pk_sct_fvalue;
> +  char *errmsg;
> +
> +  if (pk_mi_json_to_val (&pk_sct, pk_sct_str_obj, &errmsg) == -1)
> +    return FAIL;
> +
> +  if (pk_type_code (pk_typeof (pk_sct)) != PK_STRUCT)
> +    return FAIL;
> +
> +  pk_sct_name = pk_struct_type_name (pk_struct_type (pk_sct));
> +
> +  if (pk_type_code (pk_typeof (pk_sct_name)) != PK_STRING)
> +    return FAIL;
> +
> +  if (strncmp (pk_string_str (pk_sct_name), "foo", strlen ("foo")))
> +    return FAIL;
> +
> +  if (pk_uint_value (pk_struct_nfields (pk_sct)) != 2)
> +    return FAIL;
> +
> +  pk_sct_fname = pk_struct_field_name (pk_sct, 0);
> +  pk_sct_foffset = pk_struct_field_boffset (pk_sct, 0);
> +  pk_sct_fvalue = pk_struct_field_value (pk_sct, 0);
> +
> +  if (pk_type_code (pk_typeof (pk_sct_fname)) != PK_STRING)
> +    return FAIL;
> +
> +  if (strncmp (pk_string_str (pk_sct_fname), "x", strlen ("x")))
> +    return FAIL;
> +
> +  if (pk_type_code (pk_typeof (pk_sct_foffset)) != PK_OFFSET)
> +    return FAIL;
> +
> +  if (pk_uint_value (pk_offset_magnitude (pk_sct_foffset)) != 3500)
> +    return FAIL;
> +
> +  if (pk_uint_size (pk_offset_magnitude (pk_sct_foffset)) != 32)
> +    return FAIL;
> +
> +  if (pk_uint_value (pk_offset_unit (pk_sct_foffset)) != 3500)
> +    return FAIL;
> +
> +  if (pk_uint_size (pk_offset_unit (pk_sct_foffset)) != 64)
> +    return FAIL;
> +
> +  if (pk_type_code (pk_typeof (pk_sct_fvalue)) != PK_STRING)
> +    return FAIL;
> +
> +  if (strncmp (pk_string_str (pk_sct_fvalue), "foobar", strlen ("foobar")))
> +    return FAIL;
> +
> +  pk_sct_fname = pk_struct_field_name (pk_sct, 1);
> +  pk_sct_foffset = pk_struct_field_boffset (pk_sct, 1);
> +  pk_sct_fvalue = pk_struct_field_value (pk_sct, 1);
> +
> +  if (pk_type_code (pk_typeof (pk_sct_fname)) != PK_STRING)
> +    return FAIL;
> +
> +  if (strncmp (pk_string_str (pk_sct_fname), "y", strlen ("y")))
> +    return FAIL;
> +
> +  if (pk_type_code (pk_typeof (pk_sct_foffset)) != PK_OFFSET)
> +    return FAIL;
> +
> +  if (pk_int_value (pk_offset_magnitude (pk_sct_foffset)) != -12345)
> +    return FAIL;
> +
> +  if (pk_int_size (pk_offset_magnitude (pk_sct_foffset)) != 32)
> +    return FAIL;
> +
> +  if (pk_int_value (pk_offset_unit (pk_sct_foffset)) != 3500)
> +    return FAIL;
> +
> +  if (pk_int_size (pk_offset_unit (pk_sct_foffset)) != 64)
> +    return FAIL;
> +
> +  if (pk_type_code (pk_typeof (pk_sct_fvalue)) != PK_INT)
> +    return FAIL;
> +
> +  if (pk_int_value (pk_sct_fvalue) != -3500)
> +    return FAIL;
> +
> +  if (pk_int_size (pk_sct_fvalue) != 32)
> +    return FAIL;
> +
> +  /* TODO: add tests for mapping.  */
> +  return PASS;
> +}

Ditto!

And you see, if you remove the coupling and make test_json_to_int also
get the expected int, you can reuse it in test_json_to_sct instead of
replicating the logic.  Same for the other fields of the struct.

Coupling is the Satan of programming.  Embrace cohesion :)

> +static int
> +test_json_to_array (const char *pk_array_str_obj)
> +{
> +  pk_val pk_array, pk_elem_val, pk_elem_offset;
> +
> +  if (pk_mi_json_to_val (&pk_array, pk_array_str_obj, NULL) == -1)
> +    return FAIL;
> +
> +  if (pk_type_code (pk_typeof (pk_array)) != PK_ARRAY)
> +    return FAIL;
> +
> +  if (pk_uint_value (pk_array_nelem (pk_array)) != 3)
> +    return FAIL;
> +
> +  pk_elem_val = pk_array_elem_val (pk_array, 0);
> +  pk_elem_offset = pk_array_elem_boffset (pk_array, 0);
> +
> +  if (pk_type_code (pk_typeof (pk_elem_val)) != PK_STRING)
> +    return FAIL;
> +
> +  if (strncmp (pk_string_str (pk_elem_val), "foobar", strlen ("foobar")))
> +    return FAIL;
> +
> +  if (pk_type_code (pk_typeof (pk_elem_offset)) != PK_OFFSET)
> +    return FAIL;
> +
> +  if (pk_uint_value (pk_offset_magnitude (pk_elem_offset)) != 3500)
> +    return FAIL;
> +
> +  if (pk_uint_size (pk_offset_magnitude (pk_elem_offset)) != 32)
> +    return FAIL;
> +
> +  if (pk_uint_value (pk_offset_unit (pk_elem_offset)) != 3500)
> +    return FAIL;
> +
> +  if (pk_uint_size (pk_offset_unit (pk_elem_offset)) != 64)
> +    return FAIL;
> +
> +  pk_elem_val = pk_array_elem_val (pk_array, 1);
> +  pk_elem_offset = pk_array_elem_boffset (pk_array, 1);
> +
> +  if (pk_type_code (pk_typeof (pk_elem_val)) != PK_STRING)
> +    return FAIL;
> +
> +  if (strncmp (pk_string_str (pk_elem_val), "barfoo", strlen ("barfoo")))
> +    return FAIL;
> +
> +  if (pk_type_code (pk_typeof (pk_elem_offset)) != PK_OFFSET)
> +    return FAIL;
> +
> +  if (pk_int_value (pk_offset_magnitude (pk_elem_offset)) != -12345)
> +    return FAIL;
> +
> +  if (pk_int_size (pk_offset_magnitude (pk_elem_offset)) != 32)
> +    return FAIL;
> +
> +  if (pk_uint_value (pk_offset_unit (pk_elem_offset)) != 3500)
> +    return FAIL;
> +
> +  if (pk_uint_size (pk_offset_unit (pk_elem_offset)) != 64)
> +    return FAIL;
> +
> +  pk_elem_val = pk_array_elem_val (pk_array, 2);
> +  pk_elem_offset = pk_array_elem_boffset (pk_array, 2);
> +
> +  if (pk_type_code (pk_typeof (pk_elem_val)) != PK_STRING)
> +    return FAIL;
> +
> +  if (strncmp (pk_string_str (pk_elem_val), "farboo", strlen ("farboo")))
> +    return FAIL;
> +
> +  if (pk_type_code (pk_typeof (pk_elem_offset)) != PK_OFFSET)
> +    return FAIL;
> +
> +  if (pk_int_value (pk_offset_magnitude (pk_elem_offset)) != -25)
> +    return FAIL;
> +
> +  if (pk_int_size (pk_offset_magnitude (pk_elem_offset)) != 32)
> +    return FAIL;
> +
> +  if (pk_uint_value (pk_offset_unit (pk_elem_offset)) != 150)
> +    return FAIL;
> +
> +  if (pk_uint_size (pk_offset_unit (pk_elem_offset)) != 64)
> +    return FAIL;
> +
> +  return PASS;
> +}

Same comments for test_json_to_array.

> +void
> +test_json_to_val ()
> +{
> +  pk_val pk_int, pk_uint, pk_offset, pk_null, pk_array, pk_struct;
> +  const char *pk_int_str_obj, *pk_uint_str_obj, *pk_string_str_obj;
> +  const char *pk_offset_str_obj, *pk_null_str_obj, *pk_sct_str_obj;
> +  const char *pk_array_str_obj;
> +
> +  pk_int_str_obj = "{ \"PokeValue\" :\
> +    {\
> +      \"type\" : \"Integer\", \"value\" : -3500, \"size\" : 32\
> +    } }";
> +
> +  pk_uint_str_obj = "{ \"PokeValue\" :\
> +    {\
> +      \"type\" : \"UnsignedInteger\", \"value\" : 3500, \"size\" : 32\
> +    } }";

Hmm, wouldn't it be worth it to have the different JSON values stored in
files instead?

Actually...  we could hack a little infrastructure here for having test
files like:

---- begin of foo.json ----
/* Preamble */
##
-3500 as int<12>
##
{ "PokeValue" :
 {
   "type" : "Integer", "value" : -3500, "size" : 12
 }
}
---- end of foo.json -----

We could make the testsuite to load all the .json files in the
directory.

For each .json file, you can use libpoke in order to parse the preamble
(everything until the first ##) as Poke code:

int pk_compile_buffer (pk_compiler pkc, const char *buffer,
                       const char **end);

Then you can use libpoke to parse the desired value (between the first
and second ##):

int pk_compile_expression (pk_compiler pkc, const char *buffer,
                           const char **end, pk_val *val);

That will give you the pk_val you want to compare to.  Then you can read
the rest of the file and parse it as JSON with json-c.  Then you call
json_to_val and compare.

And there you go: generic test driver and it is SO easy to add more
tests :)

Example for a struct:

---- begin of bar.json ---
deftype Foo = struct { int i; long j; };
##
Foo { i = 10, j = 20 }
##
{ "PokeValue" :
 {
  "type" : "Struct",
  "fields" :
  [
    {
     "i" : { "type" : "Integer", "value" : 10, "size" : 32 },
     "j" : ...
    }
  ]
  ...
 }
}
---- end of bar.json ----

WDYT?

> +  pk_string_str_obj = "{ \"PokeValue\" :\
> +    {\
> +      \"type\" : \"String\",  \"value\" : \"kostas\"\
> +    } }";
> +
> +  pk_offset_str_obj = "{ \"PokeValue\" :\
> +    {\
> +      \"type\" : \"Offset\",\
> +      \"magnitude\" :\
> +        {\
> +          \"type\" : \"UnsignedInteger\", \"value\" : 3500, \"size\" : 32\
> +        },\
> +      \"unit\" :\
> +        {\
> +          \"type\" : \"UnsignedInteger\", \"value\" : 3500, \"size\" : 64\
> +        }\
> +    } }";
> +
> +  pk_null_str_obj = "{ \"PokeValue\" :\
> +    {\
> +      \"type\" : \"Null\", \"value\" : null\
> +    } }";
> +
> +  pk_sct_str_obj = "{ \"PokeValue\" :\
> +    { \"type\" : \"Struct\",\
> +      \"name\" :\
> +        {\
> +          \"type\" : \"String\", \"value\" : \"foo\"\
> +        },\
> +      \"fields\" :\
> +        [\
> +          {\
> +            \"name\" :\
> +              {\
> +                \"type\" : \"String\", \"value\" : \"x\"\
> +              },\
> +            \"offset\" :\
> +              {\
> +                \"type\" : \"Offset\",\
> +                \"magnitude\" : { \"type\" : \"UnsignedInteger\", \"value\" 
> : 3500, \"size\" : 32 },\
> +                \"unit\" : { \"type\" : \"UnsignedInteger\", \"value\" : 
> 3500, \"size\" : 64 }\
> +              },\
> +            \"value\" : { \"type\" : \"String\", \"value\" : \"foobar\" }\
> +          },\
> +          {\
> +            \"name\" :\
> +              {\
> +                \"type\" : \"String\", \"value\" : \"y\"\
> +              },\
> +            \"offset\" :\
> +              {\
> +                \"type\" : \"Offset\",\
> +                \"magnitude\" :\
> +                  {\
> +                    \"type\" : \"Integer\", \"value\" : -12345, \"size\" : 
> 32\
> +                  },\
> +                \"unit\" :\
> +                  {\
> +                    \"type\" : \"UnsignedInteger\", \"value\" : 3500, 
> \"size\" : 64\
> +                  }\
> +              },\
> +            \"value\" :\
> +              {\
> +                \"type\" : \"Integer\", \"value\" : -3500, \"size\" : 32\
> +              }\
> +          }\
> +        ],\
> +      \"mapping\" : { \"type\" : \"Null\", \"value\" : null }\
> +    } }";
> +
> +  pk_array_str_obj = "{ \"PokeValue\" :\
> +    {\
> +      \"type\" : \"Array\",\
> +      \"elements\" :\
> +        [\
> +          {\
> +            \"value\" :\
> +              {\
> +                \"type\" : \"String\", \"value\" : \"foobar\"\
> +              },\
> +            \"offset\" :\
> +              {\
> +                \"type\" : \"Offset\",\
> +                \"magnitude\" :\
> +                {\
> +                  \"type\" : \"UnsignedInteger\", \"value\" : 3500, \"size\" 
> : 32\
> +                },\
> +                \"unit\" :\
> +                {\
> +                  \"type\" : \"UnsignedInteger\", \"value\" : 3500, \"size\" 
> : 64\
> +                }\
> +              }\
> +          },\
> +          {\
> +            \"value\" :\
> +              {\
> +                \"type\" : \"String\", \"value\" : \"barfoo\"\
> +              },\
> +            \"offset\" :\
> +              {\
> +                \"type\" : \"Offset\",\
> +                \"magnitude\" :\
> +                {\
> +                  \"type\" : \"Integer\", \"value\" : -12345, \"size\" : 32\
> +                },\
> +                \"unit\" :\
> +                {\
> +                  \"type\" : \"UnsignedInteger\", \"value\" : 3500, \"size\" 
> : 64\
> +                }\
> +              }\
> +          },\
> +          {\
> +            \"value\" :\
> +              {\
> +                \"type\" : \"String\", \"value\" : \"farboo\"\
> +              },\
> +            \"offset\" :\
> +              {\
> +                \"type\" : \"Offset\",\
> +                \"magnitude\" :\
> +                  {\
> +                    \"type\" : \"Integer\", \"value\" : -25, \"size\" : 32\
> +                  },\
> +                \"unit\" :\
> +                  {\
> +                    \"type\" : \"UnsignedInteger\", \"value\" : 150, 
> \"size\" : 64\
> +                  }\
> +              }\
> +          }\
> +        ],\
> +      \"mapping\" :\
> +        {\
> +          \"type\" : \"Null\", \"value\" : null\
> +        }\
> +    } }";
> +
> +    if (test_json_to_int (pk_int_str_obj) == PASS)
> +      pass ("json_to_int");
> +    else
> +      fail ("json_to_int");
> +
> +    if (test_json_to_uint (pk_uint_str_obj) == PASS)
> +      pass ("json_to_uint");
> +    else
> +      fail ("json_to_uint");
> +
> +    if (test_json_to_string (pk_string_str_obj) == PASS)
> +      pass ("json_to_string");
> +    else
> +      fail ("json_to_string");
> +
> +    if (test_json_to_offset (pk_offset_str_obj) == PASS)
> +      pass ("json_to_offset");
> +    else
> +      fail ("json_to_offset");
> +
> +    if (test_json_to_null (pk_null_str_obj) == PASS)
> +      pass ("json_to_null");
> +    else
> +      fail ("json_to_null");
> +
> +    if (test_json_to_sct (pk_sct_str_obj) == PASS)
> +      pass ("json_to_sct");
> +    else
> +      fail ("json_to_sct");
> +
> +    if (test_json_to_array (pk_array_str_obj) == PASS)
> +      pass ("json_to_array");
> +    else
> +      fail ("json_to_array");
> +
> +}
> +
> +static int
> +parse_json_str_object (const char *json_str, struct json_object **pk_obj)
> +{
> +  struct json_tokener *tok = json_tokener_new ();
> +  enum json_tokener_error jerr;
> +
> +  do
> +    {
> +      *pk_obj = json_tokener_parse_ex (tok, json_str,
> +                                          strlen (json_str));
> +    }
> +  while ((jerr = json_tokener_get_error (tok)) == json_tokener_continue);
> +
> +  return jerr == json_tokener_success ? PASS : FAIL;
> +}
> +
> +static int
> +test_int_to_json (struct json_object *pk_int_obj, pk_val pk_int)
> +{
> +  struct json_object *current;
> +  const char *typename;
> +
> +  /* Poke integers properties are : "type", "value" and "size".  */
> +  if (json_object_object_length (pk_int_obj) != 3)
> +    return FAIL;
> +
> +  if (!json_object_object_get_ex (pk_int_obj, "type", &current))
> +    return FAIL;
> +
> +  typename = json_object_get_string (current);
> +  if (strncmp (typename, "Integer", strlen ("Integer")))
> +    return FAIL;
> +
> +  if (!json_object_object_get_ex (pk_int_obj, "value", &current))
> +    return FAIL;
> +
> +  if (json_object_get_int64 (current) != pk_int_value (pk_int))
> +    return FAIL;
> +
> +  if (!json_object_object_get_ex (pk_int_obj, "size", &current))
> +    return FAIL;
> +
> +  if (json_object_get_int (current) != pk_int_size (pk_int))
> +    return FAIL;
> +
> +  return PASS;
> +}
> +
> +static int
> +test_uint_to_json (struct json_object *pk_uint_obj, pk_val pk_uint)
> +{
> +  struct json_object *current;
> +  const char *typename;
> +
> +  /* Poke unsigned integers properties are : "type", "value" and "size".  */
> +  if (json_object_object_length (pk_uint_obj) != 3)
> +    return FAIL;
> +
> +  if (!json_object_object_get_ex (pk_uint_obj, "type", &current))
> +    return FAIL;
> +
> +  typename = json_object_get_string (current);
> +  if (strncmp (typename, "UnsignedInteger",
> +               strlen ("UnsignedInteger")))
> +    return FAIL;
> +
> +  if (!json_object_object_get_ex (pk_uint_obj, "value", &current))
> +    return FAIL;
> +
> +  /* NOTE: This version of libjson-c does not support *_get_uint64 so we use
> +     the int64 version and always cast to the unsigned type.  */
> +  if ((uint64_t) json_object_get_int64 (current) != pk_uint_value (pk_uint))
> +    return FAIL;
> +
> +  if (!json_object_object_get_ex (pk_uint_obj, "size", &current))
> +    return FAIL;
> +
> +  if (json_object_get_int (current) != pk_uint_size (pk_uint))
> +    return FAIL;
> +
> +  return PASS;
> +}
> +
> +static int
> +test_string_to_json (struct json_object *pk_string_obj, pk_val pk_string)
> +{
> +  struct json_object *current;
> +  const char *typename, *json_str_value, *pk_string_value;
> +
> +  /* Poke string properties are : "type" and "value".  */
> +  if (json_object_object_length (pk_string_obj) != 2)
> +    return FAIL;
> +
> +  if (!json_object_object_get_ex (pk_string_obj, "type", &current))
> +    return FAIL;
> +
> +  typename = json_object_get_string (current);
> +  if (strncmp (typename, "String", strlen ("String")))
> +    return FAIL;
> +
> +  if (!json_object_object_get_ex (pk_string_obj, "value", &current))
> +    return FAIL;
> +
> +  json_str_value = json_object_get_string (current);
> +  pk_string_value = pk_string_str (pk_string);
> +  if (strncmp (json_str_value, pk_string_value, strlen (pk_string_value)))
> +    return FAIL;
> +
> +  return PASS;
> +}
> +
> +static int
> +test_offset_to_json (struct json_object *pk_offset_obj, pk_val pk_offset)
> +{
> +  struct json_object *current;
> +  pk_val pk_magnitude, pk_unit;
> +  const char *typename;
> +  int signed_p;
> +
> +  /* Poke offset properties are : "type", "magnitude" and "unit".  */
> +  if (json_object_object_length (pk_offset_obj) != 3)
> +    return FAIL;
> +
> +  if (!json_object_object_get_ex (pk_offset_obj, "type", &current))
> +    return FAIL;
> +
> +  typename = json_object_get_string (current);
> +  if (strncmp (typename, "Offset", strlen ("Offset")))
> +    return FAIL;
> +
> +  if (!json_object_object_get_ex (pk_offset_obj, "magnitude", &current))
> +    return FAIL;
> +
> +  /* "magnitude" is either an UnsignedInteger or an Integer.
> +      Check if its UnsignedInteger or Integer.  */
> +  pk_magnitude = pk_offset_magnitude (pk_offset);
> +  signed_p = pk_uint_value (pk_integral_type_signed_p (pk_typeof 
> (pk_magnitude)));
> +  if (signed_p && test_int_to_json (current, pk_magnitude) == FAIL)
> +    return FAIL;
> +
> +  if (!signed_p && test_uint_to_json (current, pk_magnitude) == FAIL)
> +    return FAIL;
> +
> +  /* "unit" is an UnsignedInteger.  */
> +  if (!json_object_object_get_ex (pk_offset_obj, "unit", &current))
> +    return FAIL;
> +
> +  pk_unit = pk_offset_unit (pk_offset);
> +  if (test_uint_to_json (current, pk_unit) == FAIL)
> +    return FAIL;
> +
> +  return PASS;
> +}
> +
> +static int
> +test_null_to_json (struct json_object *pk_null_obj, pk_val pk_null)
> +{
> +  struct json_object *current;
> +  const char *typename;
> +
> +  /* Poke null properties are : "type" and "value".  */
> +  if (json_object_object_length (pk_null_obj) != 2)
> +    return FAIL;
> +
> +  if (!json_object_object_get_ex (pk_null_obj, "type", &current))
> +    return FAIL;
> +
> +  typename = json_object_get_string (current);
> +  if (strncmp (typename, "Null", strlen ("Null")))
> +    return FAIL;
> +
> +  if (!json_object_object_get_ex (pk_null_obj, "value", &current))
> +    return FAIL;
> +
> +  if (current != NULL)
> +    return FAIL;
> +
> +  return PASS;
> +}
> +
> +static int test_array_to_json ();
> +
> +static int
> +test_sct_to_json (struct json_object *pk_sct_obj, pk_val pk_sct)
> +{
> +  struct json_object *current, *pk_sct_fields_obj, *pk_sct_field_obj;
> +  pk_val pk_sct_name, pk_sct_fname, pk_sct_foffset, pk_sct_fvalue;
> +  int signed_p;
> +  const char *typename;
> +
> +  /* Poke struct properties are : "type", "name", "fields" and "mapping".  */
> +  if (json_object_object_length (pk_sct_obj) != 4)
> +    return FAIL;
> +
> +  if (!json_object_object_get_ex (pk_sct_obj, "type", &current))
> +    return FAIL;
> +
> +  typename = json_object_get_string (current);
> +  if (strncmp (typename, "Struct", strlen ("Struct")))
> +    return FAIL;
> +
> +  if (!json_object_object_get_ex (pk_sct_obj, "name", &current))
> +    return FAIL;
> +
> +  pk_sct_name = pk_struct_type_name (pk_struct_type (pk_sct));
> +
> +  if (test_string_to_json (current, pk_sct_name) == FAIL)
> +    return FAIL;
> +
> +  /* Get the fields of a struct and check them.  */
> +  if (!json_object_object_get_ex (pk_sct_obj, "fields", &pk_sct_fields_obj))
> +    return FAIL;
> +
> +  for (size_t i = 0 ; i < pk_uint_value (pk_struct_nfields (pk_sct)) ; i++)
> +    {
> +      pk_sct_fname = pk_struct_field_name (pk_sct, i);
> +      pk_sct_foffset = pk_struct_field_boffset (pk_sct, i);
> +      pk_sct_fvalue = pk_struct_field_value (pk_sct, i);
> +
> +      pk_sct_field_obj = json_object_array_get_idx (pk_sct_fields_obj, i);
> +
> +      if (!json_object_object_get_ex (pk_sct_field_obj, "name", &current))
> +        return FAIL;
> +
> +      if (test_string_to_json (current, pk_sct_fname) == FAIL)
> +        return FAIL;
> +
> +      if (!json_object_object_get_ex (pk_sct_field_obj, "offset", &current))
> +        return FAIL;
> +
> +      if (test_offset_to_json (current, pk_sct_foffset) == FAIL)
> +        return FAIL;
> +
> +      if (!json_object_object_get_ex (pk_sct_field_obj, "value", &current))
> +        return FAIL;
> +
> +      if (pk_sct_fvalue == PK_NULL)
> +        {
> +          if (test_null_to_json (current, pk_sct_fvalue) == FAIL)
> +            return FAIL;
> +        }
> +      else
> +        {
> +          switch (pk_type_code (pk_typeof (pk_sct_fvalue)))
> +            {
> +              case PK_INT:
> +                signed_p = pk_uint_value (pk_integral_type_signed_p (
> +                                          pk_typeof (pk_sct_fvalue)));
> +                if (signed_p && test_int_to_json (current, pk_sct_fvalue) == 
> FAIL)
> +                  return FAIL;
> +                if (!signed_p && test_uint_to_json (current, pk_sct_fvalue) 
> == FAIL)
> +                  return FAIL;
> +                break;
> +              case PK_STRING:
> +                if (test_string_to_json (current, pk_sct_fvalue) == FAIL)
> +                  return FAIL;
> +                break;
> +              case PK_OFFSET:
> +                if (test_offset_to_json (current, pk_sct_fvalue) == FAIL)
> +                  return FAIL;
> +                break;
> +              case PK_STRUCT:
> +                if (test_sct_to_json (current, pk_sct_fvalue) == FAIL)
> +                  return FAIL;
> +                break;
> +              case PK_ARRAY:
> +                if (test_array_to_json (current, pk_sct_fvalue) == FAIL)
> +                  return FAIL;
> +                break;
> +              case PK_CLOSURE:
> +              case PK_ANY:
> +                return FAIL;
> +            }
> +        }
> +    }
> +
> +  /* TODO: add test for mapping when its added on pk-mi-json.c.  */
> +  return PASS;
> +}
> +
> +static int
> +test_array_to_json (struct json_object *pk_array_obj, pk_val pk_array)
> +{
> +  struct json_object *current, *pk_array_elems_obj, *pk_array_elem_obj;
> +  pk_val pk_array_elem_value, pk_array_elem_offset;
> +  const char *typename;
> +  int signed_p;
> +
> +  /* Poke array properties are : "type", "elements" and "mapping".  */
> +  if (json_object_object_length (pk_array_obj) != 3)
> +    return FAIL;
> +
> +  if (!json_object_object_get_ex (pk_array_obj, "type", &current))
> +    return FAIL;
> +
> +  typename = json_object_get_string (current);
> +  if (strncmp (typename, "Array", strlen ("Array")))
> +    return FAIL;
> +
> +  if (!json_object_object_get_ex (pk_array_obj, "elements", 
> &pk_array_elems_obj))
> +    return FAIL;
> +
> +  /* Access every element of the array and check it.  */
> +  for (size_t i = 0 ; i < pk_uint_value (pk_array_nelem (pk_array)) ; i++)
> +    {
> +      pk_array_elem_value = pk_array_elem_val (pk_array, i);
> +      pk_array_elem_offset = pk_array_elem_boffset (pk_array, i);
> +
> +      pk_array_elem_obj = json_object_array_get_idx (pk_array_elems_obj, i);
> +
> +      if (!json_object_object_get_ex (pk_array_elem_obj, "offset", &current))
> +        return FAIL;
> +
> +      if (test_offset_to_json (current, pk_array_elem_offset) == FAIL)
> +        return FAIL;
> +
> +      if (!json_object_object_get_ex (pk_array_elem_obj, "value", &current))
> +        return FAIL;
> +
> +      if (pk_array_elem_value == PK_NULL)
> +        {
> +          if (test_null_to_json (current, pk_array_elem_value) == FAIL)
> +            return FAIL;
> +        }
> +      else
> +        {
> +          switch (pk_type_code (pk_typeof (pk_array_elem_value)))
> +            {
> +              case PK_INT:
> +                signed_p = pk_uint_value (pk_integral_type_signed_p (
> +                                          pk_typeof (pk_array_elem_value)));
> +                if (signed_p
> +                    && test_int_to_json (current, pk_array_elem_value) == 
> FAIL)
> +                  return FAIL;
> +                if (!signed_p
> +                    && test_uint_to_json (current, pk_array_elem_value) == 
> FAIL)
> +                  return FAIL;
> +                break;
> +              case PK_STRING:
> +                if (test_string_to_json (current, pk_array_elem_value) == 
> FAIL)
> +                  return FAIL;
> +                break;
> +              case PK_OFFSET:
> +                if (test_offset_to_json (current, pk_array_elem_value) == 
> FAIL)
> +                  return FAIL;
> +                break;
> +              case PK_STRUCT:
> +                if (test_sct_to_json (current, pk_array_elem_value) == FAIL)
> +                  return FAIL;
> +                break;
> +              case PK_ARRAY:
> +                if (test_array_to_json (current, pk_array_elem_value) == 
> FAIL)
> +                  return FAIL;
> +                break;
> +              case PK_CLOSURE:
> +              case PK_ANY:
> +                return FAIL;
> +            }
> +        }
> +    }
> +
> +  /* TODO: add test for mapping when its added on pk-mi-json.c.  */
> +  return PASS;
> +}
> +
> +void
> +test_val_to_json ()
> +{
> +  pk_val pk_int, pk_uint, pk_string, pk_offset, pk_null, pk_array, pk_sct;
> +  pk_val pk_sct_type, nfields, *fnames, *ftypes;
> +  struct json_object *pk_obj, *current;
> +  const char *pk_int_str_obj, *pk_uint_str_obj, *pk_string_str_obj;
> +  const char *pk_offset_str_obj, *pk_null_str_obj, *pk_array_str_obj;
> +  const char *pk_sct_str_obj;
> +
> +  /* Construct the Poke values.  */
> +  pk_null = PK_NULL;
> +  pk_int = pk_make_int (-25, 32);
> +  pk_uint = pk_make_uint (150, 32);
> +  pk_string = pk_make_string ("kostas");
> +  pk_offset = pk_make_offset (pk_uint, pk_make_uint (10, 64));
> +  pk_array = pk_make_array (pk_make_uint (5, 64),
> +                            pk_make_array_type (pk_typeof (pk_uint), 
> PK_NULL));
> +
> +  nfields = pk_make_uint (3, 64);
> +  fnames = (pk_val *) malloc (pk_uint_value (nfields) * sizeof (pk_val));
> +  ftypes = (pk_val *) malloc (pk_uint_value (nfields) * sizeof (pk_val));
> +
> +  pk_sct_type = pk_make_struct_type (nfields, pk_make_string ("foo"), fnames,
> +                                     ftypes);
> +  pk_sct = pk_make_struct (nfields, pk_sct_type);
> +
> +  pk_struct_type_set_ftype (pk_sct_type, 0, pk_make_string ("x"));
> +  pk_struct_type_set_ftype (pk_sct_type, 1, pk_make_string ("y"));
> +  pk_struct_type_set_ftype (pk_sct_type, 2, pk_make_string ("z"));
> +
> +  pk_struct_type_set_fname (pk_sct_type, 0, pk_make_string_type ());
> +  pk_struct_type_set_fname (pk_sct_type, 1, pk_typeof (pk_uint));
> +  pk_struct_type_set_fname (pk_sct_type, 2, pk_typeof (pk_int));
> +
> +  pk_struct_set_field_value (pk_sct, 0, pk_string);
> +  pk_struct_set_field_value (pk_sct, 1, pk_uint);
> +  pk_struct_set_field_value (pk_sct, 2, pk_int);
> +
> +  pk_struct_set_field_boffset (pk_sct, 0, pk_offset);
> +  pk_struct_set_field_boffset (pk_sct, 1, pk_offset);
> +  pk_struct_set_field_boffset (pk_sct, 2, pk_offset);
> +
> +  pk_struct_set_field_name (pk_sct, 0, pk_make_string ("x"));
> +  pk_struct_set_field_name (pk_sct, 1, pk_make_string ("y"));
> +  pk_struct_set_field_name (pk_sct, 2, pk_make_string ("z"));
> +
> +  for (size_t i = 0 ; i < pk_uint_value (pk_array_nelem (pk_array)) ; i++)
> +    {
> +      pk_array_set_elem_boffset (pk_array, i, pk_offset);
> +      pk_array_set_elem_val (pk_array, i, pk_make_uint (i + 1, 32));
> +    }
> +
> +  /* Convert them and test the result.  */
> +  pk_int_str_obj = pk_mi_val_to_json (pk_int, NULL);
> +  pk_uint_str_obj = pk_mi_val_to_json (pk_uint, NULL);
> +  pk_string_str_obj = pk_mi_val_to_json (pk_string, NULL);
> +  pk_offset_str_obj = pk_mi_val_to_json (pk_offset, NULL);
> +  pk_sct_str_obj = pk_mi_val_to_json (pk_sct, NULL);
> +  pk_array_str_obj = pk_mi_val_to_json (pk_array, NULL);
> +  pk_null_str_obj = pk_mi_val_to_json (pk_null, NULL);
> +
> +  /* Parse all objects and check them.  */
> +  if (parse_json_str_object (pk_int_str_obj, &pk_obj)
> +      && json_object_object_get_ex (pk_obj, "PokeValue", &current))
> +    {
> +      if (test_int_to_json (current, pk_int) == PASS)
> +        pass ("int_to_json");
> +      else
> +        fail ("int_to_json");
> +    }
> +  else
> +    fail ("int_to_json");
> +
> +  if (parse_json_str_object (pk_uint_str_obj, &pk_obj)
> +      && json_object_object_get_ex (pk_obj, "PokeValue", &current))
> +    {
> +      if (test_uint_to_json (current, pk_uint) == PASS)
> +        pass ("uint_to_json");
> +      else
> +        fail ("uint_to_json");
> +    }
> +  else
> +    fail ("uint_to_json");
> +
> +  if (parse_json_str_object (pk_string_str_obj, &pk_obj)
> +      && json_object_object_get_ex (pk_obj, "PokeValue", &current))
> +    {
> +      if (test_string_to_json (current, pk_string) == PASS)
> +        pass ("string_to_json");
> +      else
> +        fail ("string_to_json");
> +    }
> +  else
> +    fail ("string_to_json");
> +
> +  if (parse_json_str_object (pk_offset_str_obj, &pk_obj)
> +      && json_object_object_get_ex (pk_obj, "PokeValue", &current))
> +    {
> +      if (test_offset_to_json (current, pk_offset) == PASS)
> +        pass ("offset_to_json");
> +      else
> +        fail ("offset_to_json");
> +    }
> +  else
> +    fail ("offset_to_json");
> +
> +  if (parse_json_str_object (pk_null_str_obj, &pk_obj)
> +      && json_object_object_get_ex (pk_obj, "PokeValue", &current))
> +    {
> +      if (test_null_to_json (current, pk_null) == PASS)
> +        pass ("null_to_json");
> +      else
> +        fail ("null_to_json");
> +    }
> +  else
> +    fail ("null_to_json");
> +
> +  if (parse_json_str_object (pk_sct_str_obj, &pk_obj)
> +      && json_object_object_get_ex (pk_obj, "PokeValue", &current))
> +    {
> +      if (test_sct_to_json (current, pk_sct) == PASS)
> +        pass ("sct_to_json");
> +      else
> +        fail ("sct_to_json");
> +    }
> +  else
> +    fail ("sct_to_json");
> +
> +  if (parse_json_str_object (pk_array_str_obj, &pk_obj)
> +      && json_object_object_get_ex (pk_obj, "PokeValue", &current))
> +    {
> +      if (test_array_to_json (current, pk_array) == PASS)
> +        pass ("array_to_json");
> +      else
> +        fail ("array_to_json");
> +    }
> +  else
> +    fail ("array_to_json");
> +
> +  free (fnames);
> +  free (ftypes);
> +
> +  /* Test for very large unsigned integers which are stored as signed on JSON
> +     representation due to lack of support for uint64 values.  */
> +  pk_uint = pk_make_uint (UINT64_MAX, 64);
> +  pk_uint_str_obj = pk_mi_val_to_json (pk_uint, NULL);
> +
> +  if (parse_json_str_object (pk_uint_str_obj, &pk_obj)
> +      && json_object_object_get_ex (pk_obj, "PokeValue", &current))
> +    {
> +      if (test_uint_to_json (current, pk_uint) == PASS)
> +        pass ("large_uint_to_json");
> +      else
> +        fail ("large_uint_to_json");
> +    }
> +  else
> +    fail ("large_uint_to_json");
> +}
> +
>  void
>  pk_fatal (const char *msg)
>  {
> @@ -49,6 +1071,8 @@ int
>  main (int argc, char *argv[])
>  {
>    test_json_to_msg ();
> +  test_json_to_val ();
> +  test_val_to_json ();
>    totals ();
>    return 0;
>  }



reply via email to

[Prev in Thread] Current Thread [Next in Thread]