From 651179b5da0777f861e427f96fd8560bf1516ae5 Mon Sep 17 00:00:00 2001 From: Jay Berkenbilt Date: Mon, 17 Dec 2018 11:55:11 -0500 Subject: Add simple JSON serializer --- libtests/build.mk | 1 + libtests/json.cc | 155 +++++++++++++++++++++++++++++++++++++++++++ libtests/libtests.testcov | 5 ++ libtests/qtest/json.test | 17 +++++ libtests/qtest/json/json.out | 23 +++++++ 5 files changed, 201 insertions(+) create mode 100644 libtests/json.cc create mode 100644 libtests/qtest/json.test create mode 100644 libtests/qtest/json/json.out (limited to 'libtests') diff --git a/libtests/build.mk b/libtests/build.mk index e8f20270..7143eb56 100644 --- a/libtests/build.mk +++ b/libtests/build.mk @@ -10,6 +10,7 @@ BINS_libtests = \ flate \ hex \ input_source \ + json \ lzw \ md5 \ pointer_holder \ diff --git a/libtests/json.cc b/libtests/json.cc new file mode 100644 index 00000000..fb902c62 --- /dev/null +++ b/libtests/json.cc @@ -0,0 +1,155 @@ +#include +#include +#include +#include + +static void check(JSON& j, std::string const& exp) +{ + if (exp != j.serialize()) + { + std::cout << "Got " << j.serialize() << "; wanted " << exp << "\n"; + } +} + +static void test_main() +{ + JSON jstr = JSON::makeString( + "<1>\xcf\x80<2>\xf0\x9f\xa5\x94\\\"<3>\x03\t\b\r\n<4>"); + check(jstr, + "\"<1>\xcf\x80<2>\xf0\x9f\xa5\x94\\\\\\\"<3>" + "\\u0003\\t\\b\\r\\n<4>\""); + JSON jnull = JSON::makeNull(); + check(jnull, "null"); + JSON jarr = JSON::makeArray(); + check(jarr, "[]"); + JSON jstr2 = JSON::makeString("a\tb"); + JSON jint = JSON::makeInt(16059); + JSON jdouble = JSON::makeReal(3.14159); + JSON jexp = JSON::makeNumber("2.1e5"); + jarr.addArrayElement(jstr2); + jarr.addArrayElement(jnull); + jarr.addArrayElement(jint); + jarr.addArrayElement(jdouble); + jarr.addArrayElement(jexp); + check(jarr, + "[\n" + " \"a\\tb\",\n" + " null,\n" + " 16059,\n" + " 3.141590,\n" + " 2.1e5\n" + "]"); + JSON jmap = JSON::makeDictionary(); + check(jmap, "{}"); + jmap.addDictionaryMember("b", jstr2); + jmap.addDictionaryMember("a", jarr); + jmap.addDictionaryMember("c\r\nd", jnull); + jmap.addDictionaryMember("yes", JSON::makeBool(false)); + jmap.addDictionaryMember("no", JSON::makeBool(true)); + jmap.addDictionaryMember("empty_dict", JSON::makeDictionary()); + jmap.addDictionaryMember("empty_list", JSON::makeArray()); + jmap.addDictionaryMember("single", JSON::makeArray()). + addArrayElement(JSON::makeInt(12)); + check(jmap, + "{\n" + " \"a\": [\n" + " \"a\\tb\",\n" + " null,\n" + " 16059,\n" + " 3.141590,\n" + " 2.1e5\n" + " ],\n" + " \"b\": \"a\\tb\",\n" + " \"c\\r\\nd\": null,\n" + " \"empty_dict\": {},\n" + " \"empty_list\": [],\n" + " \"no\": true,\n" + " \"single\": [\n" + " 12\n" + " ],\n" + " \"yes\": false\n" + "}"); +} + +static void check_schema(JSON& obj, JSON& schema, bool exp, + std::string const& description) +{ + std::list errors; + std::cout << "--- " << description << std::endl; + assert(exp == obj.checkSchema(schema, errors)); + for (std::list::iterator iter = errors.begin(); + iter != errors.end(); ++iter) + { + std::cout << *iter << std::endl; + } + std::cout << "---" << std::endl; +} + +static void test_schema() +{ + // Since we don't have a JSON parser, use the PDF parser as a + // shortcut for creating a complex JSON structure. + JSON schema = QPDFObjectHandle::parse( + "<<" + " /one <<" + " /a <<" + " /q (queue)" + " /r <<" + " /x (ecks)" + " /y (why)" + " >>" + " /s [ (esses) ]" + " >>" + " >>" + " /two [" + " <<" + " /goose (gander)" + " /glarp (enspliel)" + " >>" + " ]" + ">>").getJSON(); + JSON a = QPDFObjectHandle::parse("[(not a) (dictionary)]").getJSON(); + check_schema(a, schema, false, "top-level type mismatch"); + JSON b = QPDFObjectHandle::parse( + "<<" + " /one <<" + " /a <<" + " /t (oops)" + " /r [" + " /x (ecks)" + " /y (why)" + " ]" + " /s << /z (esses) >>" + " >>" + " >>" + " /two [" + " <<" + " /goose (0 gander)" + " /glarp (0 enspliel)" + " >>" + " <<" + " /goose (1 gander)" + " /flarp (1 enspliel)" + " >>" + " 2" + " [ (three) ]" + " <<" + " /goose (4 gander)" + " /glarp (4 enspliel)" + " >>" + " ]" + ">>").getJSON(); + check_schema(b, schema, false, "top-level type mismatch"); + check_schema(a, a, false, "top-level schema array error"); + check_schema(b, b, false, "lower-level schema array error"); + check_schema(schema, schema, true, "pass"); +} + +int main() +{ + test_main(); + test_schema(); + + std::cout << "end of json tests\n"; + return 0; +} diff --git a/libtests/libtests.testcov b/libtests/libtests.testcov index 8b209281..775141d7 100644 --- a/libtests/libtests.testcov +++ b/libtests/libtests.testcov @@ -34,3 +34,8 @@ Pl_PNGFilter decodeUp 0 Pl_PNGFilter decodeAverage 0 Pl_PNGFilter decodePaeth 0 Pl_TIFFPredictor processRow 1 +JSON wanted dictionary 0 +JSON key missing in object 0 +JSON wanted array 0 +JSON schema array error 0 +JSON key extra in object 0 diff --git a/libtests/qtest/json.test b/libtests/qtest/json.test new file mode 100644 index 00000000..b62994d3 --- /dev/null +++ b/libtests/qtest/json.test @@ -0,0 +1,17 @@ +#!/usr/bin/env perl +require 5.008; +use warnings; +use strict; + +chdir("json") or die "chdir testdir failed: $!\n"; + +require TestDriver; + +my $td = new TestDriver('json'); + +$td->runtest("json", + {$td->COMMAND => "json"}, + {$td->FILE => "json.out", $td->EXIT_STATUS => 0}, + $td->NORMALIZE_NEWLINES); + +$td->report(1); diff --git a/libtests/qtest/json/json.out b/libtests/qtest/json/json.out new file mode 100644 index 00000000..f06cc1fb --- /dev/null +++ b/libtests/qtest/json/json.out @@ -0,0 +1,23 @@ +--- top-level type mismatch +top-level object is supposed to be a dictionary +--- +--- top-level type mismatch +json key "./one./a": key "/q" is present in schema but missing in object +json key "./one./a./r" is supposed to be a dictionary +json key "./one./a./s" is supposed to be an array +json key "./one./a": key "/t" is not present in schema but appears in object +json key "./two.1": key "/glarp" is present in schema but missing in object +json key "./two.1": key "/flarp" is not present in schema but appears in object +json key "./two.2" is supposed to be a dictionary +json key "./two.3" is supposed to be a dictionary +--- +--- top-level schema array error +top-level object schema array contains other than one item +--- +--- lower-level schema array error +json key "./one./a./r" schema array contains other than one item +json key "./two" schema array contains other than one item +--- +--- pass +--- +end of json tests -- cgit v1.2.3-54-g00ecf