summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2021-05-01 17:28:44 +0100
committerDan Goodliffe <dan@randomdan.homeip.net>2021-11-07 16:41:37 +0000
commitfc8c9a6c7bec176299915c6adab120e1bf2ea4e9 (patch)
tree837426e53f3ec0cd06a6b7c9244c57a7c4229953
parentFix the fact I've been spelling persistence wrong this whole time (diff)
downloadilt-fc8c9a6c7bec176299915c6adab120e1bf2ea4e9.tar.bz2
ilt-fc8c9a6c7bec176299915c6adab120e1bf2ea4e9.tar.xz
ilt-fc8c9a6c7bec176299915c6adab120e1bf2ea4e9.zip
Lots of test cases, few minor fixes
-rw-r--r--lib/jsonParse.impl.cpp5
-rw-r--r--lib/jsonParse.ll8
-rw-r--r--lib/persistence.cpp2
-rw-r--r--test/Jamfile.jam2
-rw-r--r--test/fixtures/json/bad/bad.json1
-rw-r--r--test/fixtures/json/bad/empty_abs.json (renamed from test/fixtures/json/empty_abs.json)0
-rw-r--r--test/fixtures/json/bad/implicit_abs.json (renamed from test/fixtures/json/implicit_abs.json)0
-rw-r--r--test/fixtures/json/bad/late_type.json4
-rw-r--r--test/fixtures/json/bad/missing_member.json3
-rw-r--r--test/fixtures/json/bad/not.json1
-rw-r--r--test/fixtures/json/bad/unexp_array.json3
-rw-r--r--test/fixtures/json/bad/unexp_bool.json3
-rw-r--r--test/fixtures/json/bad/unexp_float.json3
-rw-r--r--test/fixtures/json/bad/unexp_null.json3
-rw-r--r--test/fixtures/json/bad/unexp_obj.json3
-rw-r--r--test/fixtures/json/bad/unexp_str.json3
-rw-r--r--test/fixtures/json/implicit.json3
-rw-r--r--test/fixtures/json/shared_ptr_null.json8
-rw-r--r--test/test-persistence.cpp62
19 files changed, 105 insertions, 12 deletions
diff --git a/lib/jsonParse.impl.cpp b/lib/jsonParse.impl.cpp
index 3ed8e62..4d13eae 100644
--- a/lib/jsonParse.impl.cpp
+++ b/lib/jsonParse.impl.cpp
@@ -12,7 +12,7 @@ json::jsonParser::LexerError(const char * msg)
void
json::jsonParser::appendEscape(const char * cphs, std::string & str)
{
- appendEscape(std::strtoul(cphs, nullptr, 16), str);
+ appendEscape(std::strtoul(cphs + 1, nullptr, 16), str);
}
void
@@ -39,4 +39,7 @@ json::jsonParser::appendEscape(unsigned long cp, std::string & str)
str += char(((cp >> 6) & 63) + 128);
str += char((cp & 63) + 128);
}
+ else {
+ throw std::range_error("Invalid UTF-8 sequence");
+ }
}
diff --git a/lib/jsonParse.ll b/lib/jsonParse.ll
index 52ad89f..c9c708c 100644
--- a/lib/jsonParse.ll
+++ b/lib/jsonParse.ll
@@ -17,6 +17,7 @@ class jsonBaseFlexLexer;
#ifdef __clang__
#pragma clang diagnostic ignored "-Wnull-conversion"
#endif
+[[maybe_unused]]static constexpr auto x=getpid;
%}
beginobj "{"
@@ -152,7 +153,6 @@ text [^\\\"]*
<*>[ \t\r\n\f] {
}
-%%
-
-// Make iwyu think unistd.h is required
-[[maybe_unused]]static auto x=getpid;
+<*>. {
+ LexerError("Unexpected input");
+}
diff --git a/lib/persistence.cpp b/lib/persistence.cpp
index 5744cd7..15391ad 100644
--- a/lib/persistence.cpp
+++ b/lib/persistence.cpp
@@ -62,6 +62,7 @@ namespace Persistence {
throw std::runtime_error("Unexpected object");
}
+ /// LCOV_EXCL_START Don't think we can trigger these from something lexer will parse
void
Selection::beforeValue(Stack &)
{
@@ -78,4 +79,5 @@ namespace Persistence {
Selection::endObject(Stack &)
{
}
+ /// LCOV_EXCL_STOP
}
diff --git a/test/Jamfile.jam b/test/Jamfile.jam
index 2c09b8a..8a9843c 100644
--- a/test/Jamfile.jam
+++ b/test/Jamfile.jam
@@ -19,4 +19,4 @@ run test-collection.cpp ;
run test-obj.cpp ;
run test-maths.cpp ;
run test-network.cpp ;
-run test-persistence.cpp : -- : [ sequence.insertion-sort [ glob fixtures/json/*.json ] ] ;
+run test-persistence.cpp : -- : [ sequence.insertion-sort [ glob fixtures/json/*.json fixtures/json/bad/*.json ] ] ;
diff --git a/test/fixtures/json/bad/bad.json b/test/fixtures/json/bad/bad.json
new file mode 100644
index 0000000..8c611b1
--- /dev/null
+++ b/test/fixtures/json/bad/bad.json
@@ -0,0 +1 @@
+{ bad }
diff --git a/test/fixtures/json/empty_abs.json b/test/fixtures/json/bad/empty_abs.json
index 7d22001..7d22001 100644
--- a/test/fixtures/json/empty_abs.json
+++ b/test/fixtures/json/bad/empty_abs.json
diff --git a/test/fixtures/json/implicit_abs.json b/test/fixtures/json/bad/implicit_abs.json
index 573b323..573b323 100644
--- a/test/fixtures/json/implicit_abs.json
+++ b/test/fixtures/json/bad/implicit_abs.json
diff --git a/test/fixtures/json/bad/late_type.json b/test/fixtures/json/bad/late_type.json
new file mode 100644
index 0000000..171575a
--- /dev/null
+++ b/test/fixtures/json/bad/late_type.json
@@ -0,0 +1,4 @@
+{
+ "str": "trigger",
+ "@typeid": "doesn't matter"
+}
diff --git a/test/fixtures/json/bad/missing_member.json b/test/fixtures/json/bad/missing_member.json
new file mode 100644
index 0000000..0c8a1fd
--- /dev/null
+++ b/test/fixtures/json/bad/missing_member.json
@@ -0,0 +1,3 @@
+{
+ "missing": true
+}
diff --git a/test/fixtures/json/bad/not.json b/test/fixtures/json/bad/not.json
new file mode 100644
index 0000000..6b7a9f4
--- /dev/null
+++ b/test/fixtures/json/bad/not.json
@@ -0,0 +1 @@
+not json
diff --git a/test/fixtures/json/bad/unexp_array.json b/test/fixtures/json/bad/unexp_array.json
new file mode 100644
index 0000000..399a2bd
--- /dev/null
+++ b/test/fixtures/json/bad/unexp_array.json
@@ -0,0 +1,3 @@
+{
+ "bl": []
+}
diff --git a/test/fixtures/json/bad/unexp_bool.json b/test/fixtures/json/bad/unexp_bool.json
new file mode 100644
index 0000000..85a4bd1
--- /dev/null
+++ b/test/fixtures/json/bad/unexp_bool.json
@@ -0,0 +1,3 @@
+{
+ "str": true
+}
diff --git a/test/fixtures/json/bad/unexp_float.json b/test/fixtures/json/bad/unexp_float.json
new file mode 100644
index 0000000..bd824b6
--- /dev/null
+++ b/test/fixtures/json/bad/unexp_float.json
@@ -0,0 +1,3 @@
+{
+ "bl": 3.14
+}
diff --git a/test/fixtures/json/bad/unexp_null.json b/test/fixtures/json/bad/unexp_null.json
new file mode 100644
index 0000000..2edc363
--- /dev/null
+++ b/test/fixtures/json/bad/unexp_null.json
@@ -0,0 +1,3 @@
+{
+ "str": null
+}
diff --git a/test/fixtures/json/bad/unexp_obj.json b/test/fixtures/json/bad/unexp_obj.json
new file mode 100644
index 0000000..6331897
--- /dev/null
+++ b/test/fixtures/json/bad/unexp_obj.json
@@ -0,0 +1,3 @@
+{
+ "str": {}
+}
diff --git a/test/fixtures/json/bad/unexp_str.json b/test/fixtures/json/bad/unexp_str.json
new file mode 100644
index 0000000..45ac749
--- /dev/null
+++ b/test/fixtures/json/bad/unexp_str.json
@@ -0,0 +1,3 @@
+{
+ "bl": "3.14"
+}
diff --git a/test/fixtures/json/implicit.json b/test/fixtures/json/implicit.json
index 03dec4b..478cec6 100644
--- a/test/fixtures/json/implicit.json
+++ b/test/fixtures/json/implicit.json
@@ -2,7 +2,8 @@
"@typeid": "TestObject",
"flt": 1,
"ptr": {
- "str": "trigger"
+ "str": "trigger",
+ "bl": false
},
"str": "after"
}
diff --git a/test/fixtures/json/shared_ptr_null.json b/test/fixtures/json/shared_ptr_null.json
new file mode 100644
index 0000000..c2461e8
--- /dev/null
+++ b/test/fixtures/json/shared_ptr_null.json
@@ -0,0 +1,8 @@
+{
+ "@typeid": "SharedTestObject",
+ "sptr": {
+ "@typeid": "SubObject",
+ "@id": "someid"
+ },
+ "ssptr": null
+}
diff --git a/test/test-persistence.cpp b/test/test-persistence.cpp
index d5910e9..6dcb94d 100644
--- a/test/test-persistence.cpp
+++ b/test/test-persistence.cpp
@@ -1,5 +1,6 @@
#define BOOST_TEST_MODULE test_persistence
+#include <boost/test/data/test_case.hpp>
#include <boost/test/unit_test.hpp>
#include <glm/glm.hpp>
@@ -63,7 +64,7 @@ struct TestObject : public Persistence::Persistable {
struct JPP : public Persistence::JsonParsePersistence {
template<typename T>
T
- load_json(const char * path)
+ load_json(const std::filesystem::path & path)
{
BOOST_TEST_CONTEXT(path) {
std::ifstream ss {path};
@@ -147,14 +148,16 @@ BOOST_FIXTURE_TEST_CASE(load_empty_object, JPP)
BOOST_CHECK_EQUAL(to->str, "after");
}
-BOOST_FIXTURE_TEST_CASE(fail_implicit_abs_object, JPP)
+static std::vector<std::filesystem::path>
+fixtures_in(const std::filesystem::path & root)
{
- BOOST_CHECK_THROW(load_json<std::unique_ptr<TestObject>>(FIXTURESDIR "json/implicit_abs.json"), std::runtime_error);
+ return {std::filesystem::directory_iterator {root}, {}};
}
-BOOST_FIXTURE_TEST_CASE(fail_empty_abs_object, JPP)
+BOOST_DATA_TEST_CASE_F(JPP, various_parse_failures, fixtures_in(FIXTURESDIR "json/bad"), path)
{
- BOOST_CHECK_THROW(load_json<std::unique_ptr<TestObject>>(FIXTURESDIR "json/empty_abs.json"), std::runtime_error);
+ std::ifstream ss {path};
+ BOOST_CHECK_THROW(loadState<std::unique_ptr<TestObject>>(ss), std::runtime_error);
}
BOOST_FIXTURE_TEST_CASE(load_abs_object, JPP)
@@ -211,3 +214,52 @@ BOOST_FIXTURE_TEST_CASE(load_shared_object2, JPP)
BOOST_CHECK_EQUAL(to->sptr.use_count(), 2);
BOOST_CHECK_EQUAL(to->ssptr.use_count(), 2);
}
+
+BOOST_FIXTURE_TEST_CASE(load_shared_object_null, JPP)
+{
+ auto to = load_json<std::unique_ptr<SharedTestObject>>(FIXTURESDIR "json/shared_ptr_null.json");
+ BOOST_CHECK(to->sptr);
+ BOOST_CHECK(!to->ssptr);
+}
+
+using svs = std::tuple<const char * const, std::string_view>;
+BOOST_DATA_TEST_CASE_F(JPP, load_strings,
+ boost::unit_test::data::make<svs>({
+ {R"J("")J", ""},
+ {R"J("non empty")J", "non empty"},
+ {R"J("new\nline")J", "new\nline"},
+ {R"J("quote\"mark")J", "quote\"mark"},
+ {R"J("tab\t")J", "tab\t"},
+ {R"J("back\bspace?")J", "back\bspace?"},
+ {R"J("form\ffeed?")J", "form\ffeed?"},
+ {R"J("forward\/slash")J", "forward/slash"},
+ {R"J("\u00a5 yen")J", "¥ yen"},
+ {R"J("gbp \u00a3")J", "gbp £"},
+ {R"J("\u007E tilde")J", "~ tilde"},
+ {R"J("\u056b ARMENIAN SMALL LETTER INI")J", "ի ARMENIAN SMALL LETTER INI"},
+ {R"J("\u0833 SAMARITAN PUNCTUATION BAU")J", "࠳ SAMARITAN PUNCTUATION BAU"},
+ }),
+ in, exp)
+{
+ std::stringstream str {in};
+ BOOST_CHECK_EQUAL(loadState<std::string>(str), exp);
+}
+
+using cpstr = std::tuple<unsigned long, std::string_view>;
+BOOST_DATA_TEST_CASE(utf8_decode,
+ boost::unit_test::data::make<cpstr>({
+ {9, "\t"},
+ {0x00010000, "𐀀"},
+ }),
+ cp, str)
+{
+ std::string out;
+ BOOST_CHECK_NO_THROW(json::jsonParser::appendEscape(cp, out));
+ BOOST_CHECK_EQUAL(out, str);
+}
+
+BOOST_DATA_TEST_CASE(utf8_decode_bad, boost::unit_test::data::make<unsigned long>({0xd800, 0xdfff, 0x110000}), cp)
+{
+ std::string out;
+ BOOST_CHECK_THROW(json::jsonParser::appendEscape(cp, out), std::runtime_error);
+}