summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergei Krivonos <sergei.krivonos@mariadb.com>2021-10-25 00:19:37 +0300
committerSergei Krivonos <sergeikrivonos@gmail.com>2021-11-09 12:06:49 +0200
commitb17576322b600f53c7a0b74cf14830ad5bbad98e (patch)
tree53a79159fb27e2aa8a02446bdc7d5d0b21e80d36
parentcf047efd42ab64d730e2b84c7482e56b695678ef (diff)
downloadmariadb-git-b17576322b600f53c7a0b74cf14830ad5bbad98e.tar.gz
MDEV-23766: add Json_writer consistency asserts to check array/object sequence
-rw-r--r--sql/my_json_writer.cc138
-rw-r--r--sql/my_json_writer.h20
2 files changed, 116 insertions, 42 deletions
diff --git a/sql/my_json_writer.cc b/sql/my_json_writer.cc
index f4cf8204d61..ea20854eb1e 100644
--- a/sql/my_json_writer.cc
+++ b/sql/my_json_writer.cc
@@ -18,6 +18,14 @@
#include "sql_string.h"
#include "my_json_writer.h"
+#ifndef NDEBUG
+bool Json_writer::named_item_expected() const
+{
+ return named_items_expectation.size()
+ && named_items_expectation.back();
+}
+#endif
+
void Json_writer::append_indent()
{
if (!document_start)
@@ -26,9 +34,27 @@ void Json_writer::append_indent()
output.append(' ');
}
-void Json_writer::start_object()
+inline void Json_writer::on_start_object()
{
+#ifndef NDEBUG
+ if(!is_on_fmt_helper_call)
+ {
+ DBUG_ASSERT(got_name == named_item_expected());
+ named_items_expectation.push_back(true);
+ }
+
+ bool was_on_fmt_helper_call= is_on_fmt_helper_call;
+ is_on_fmt_helper_call= true;
+#endif
fmt_helper.on_start_object();
+#ifndef NDEBUG
+ is_on_fmt_helper_call= was_on_fmt_helper_call;
+#endif
+}
+
+void Json_writer::start_object()
+{
+ on_start_object();
if (!element_started)
start_element();
@@ -38,11 +64,36 @@ void Json_writer::start_object()
first_child=true;
element_started= false;
document_start= false;
+#ifndef NDEBUG
+ got_name= false;
+#endif
+}
+
+bool Json_writer::on_start_array()
+{
+#ifndef NDEBUG
+ bool was_on_fmt_helper_call= is_on_fmt_helper_call;
+ is_on_fmt_helper_call= true;
+#endif
+ bool helped= fmt_helper.on_start_array();
+#ifndef NDEBUG
+ is_on_fmt_helper_call= was_on_fmt_helper_call;
+#endif
+ return helped;
}
void Json_writer::start_array()
{
- if (fmt_helper.on_start_array())
+#ifndef NDEBUG
+ if(!is_on_fmt_helper_call)
+ {
+ DBUG_ASSERT(got_name == named_item_expected());
+ named_items_expectation.push_back(false);
+ got_name= false;
+ }
+#endif
+
+ if (on_start_array())
return;
if (!element_started)
@@ -58,6 +109,11 @@ void Json_writer::start_array()
void Json_writer::end_object()
{
+#ifndef NDEBUG
+ named_items_expectation.pop_back();
+ DBUG_ASSERT(!got_name);
+ got_name= false;
+#endif
indent_level-=INDENT_SIZE;
if (!first_child)
append_indent();
@@ -68,6 +124,10 @@ void Json_writer::end_object()
void Json_writer::end_array()
{
+#ifndef NDEBUG
+ named_items_expectation.pop_back();
+ got_name= false;
+#endif
if (fmt_helper.on_end_array())
return;
indent_level-=INDENT_SIZE;
@@ -80,31 +140,25 @@ void Json_writer::end_array()
Json_writer& Json_writer::add_member(const char *name)
{
size_t len= strlen(name);
- if (fmt_helper.on_add_member(name, len))
- return *this; // handled
-
- // assert that we are in an object
- DBUG_ASSERT(!element_started);
- start_element();
-
- output.append('"');
- output.append(name, len);
- output.append("\": ", 3);
- return *this;
+ return add_member(name, len);
}
Json_writer& Json_writer::add_member(const char *name, size_t len)
{
- if (fmt_helper.on_add_member(name, len))
- return *this; // handled
-
- // assert that we are in an object
- DBUG_ASSERT(!element_started);
- start_element();
+ if (!fmt_helper.on_add_member(name, len))
+ {
+ // assert that we are in an object
+ DBUG_ASSERT(!element_started);
+ start_element();
- output.append('"');
- output.append(name, len);
- output.append("\": ");
+ output.append('"');
+ output.append(name, len);
+ output.append("\": ", 3);
+ }
+#ifndef NDEBUG
+ if (!is_on_fmt_helper_call)
+ got_name= true;
+#endif
return *this;
}
@@ -200,19 +254,13 @@ void Json_writer::add_null()
void Json_writer::add_unquoted_str(const char* str)
{
size_t len= strlen(str);
- if (fmt_helper.on_add_str(str, len))
- return;
-
- if (!element_started)
- start_element();
-
- output.append(str, len);
- element_started= false;
+ add_unquoted_str(str, len);
}
void Json_writer::add_unquoted_str(const char* str, size_t len)
{
- if (fmt_helper.on_add_str(str, len))
+ DBUG_ASSERT(is_on_fmt_helper_call || got_name == named_item_expected());
+ if (on_add_str(str, len))
return;
if (!element_started)
@@ -222,19 +270,24 @@ void Json_writer::add_unquoted_str(const char* str, size_t len)
element_started= false;
}
+inline bool Json_writer::on_add_str(const char *str, size_t num_bytes)
+{
+#ifndef NDEBUG
+ got_name= false;
+ bool was_on_fmt_helper_call= is_on_fmt_helper_call;
+ is_on_fmt_helper_call= true;
+#endif
+ bool helped= fmt_helper.on_add_str(str, num_bytes);
+#ifndef NDEBUG
+ is_on_fmt_helper_call= was_on_fmt_helper_call;
+#endif
+ return helped;
+}
+
void Json_writer::add_str(const char *str)
{
size_t len= strlen(str);
- if (fmt_helper.on_add_str(str, len))
- return;
-
- if (!element_started)
- start_element();
-
- output.append('"');
- output.append(str, len);
- output.append('"');
- element_started= false;
+ add_str(str, len);
}
/*
@@ -243,7 +296,8 @@ void Json_writer::add_str(const char *str)
void Json_writer::add_str(const char* str, size_t num_bytes)
{
- if (fmt_helper.on_add_str(str, num_bytes))
+ DBUG_ASSERT(is_on_fmt_helper_call || got_name == named_item_expected());
+ if (on_add_str(str, num_bytes))
return;
if (!element_started)
diff --git a/sql/my_json_writer.h b/sql/my_json_writer.h
index bc8002de529..94cd438bbb0 100644
--- a/sql/my_json_writer.h
+++ b/sql/my_json_writer.h
@@ -181,6 +181,17 @@ private:
class Json_writer
{
+#ifndef NDEBUG
+
+ std::vector<bool> named_items_expectation;
+
+ bool named_item_expected() const;
+
+ bool got_name;
+ bool is_on_fmt_helper_call;
+
+#endif
+
public:
/* Add a member. We must be in an object. */
Json_writer& add_member(const char *name);
@@ -204,6 +215,11 @@ public:
private:
void add_unquoted_str(const char* val);
void add_unquoted_str(const char* val, size_t len);
+
+ bool on_add_str(const char *str, size_t num_bytes);
+ bool on_start_array();
+ void on_start_object();
+
public:
/* Start a child object */
void start_object();
@@ -221,6 +237,10 @@ public:
size_t get_truncated_bytes() { return output.get_truncated_bytes(); }
Json_writer() :
+#ifndef NDEBUG
+ got_name(false),
+ is_on_fmt_helper_call(false),
+#endif
indent_level(0), document_start(true), element_started(false),
first_child(true)
{