summaryrefslogtreecommitdiffstats
path: root/src/lib/cc/tests/json_feed_unittests.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/cc/tests/json_feed_unittests.cc')
-rw-r--r--src/lib/cc/tests/json_feed_unittests.cc174
1 files changed, 174 insertions, 0 deletions
diff --git a/src/lib/cc/tests/json_feed_unittests.cc b/src/lib/cc/tests/json_feed_unittests.cc
new file mode 100644
index 0000000000..e289757d00
--- /dev/null
+++ b/src/lib/cc/tests/json_feed_unittests.cc
@@ -0,0 +1,174 @@
+// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+#include <cc/data.h>
+#include <cc/json_feed.h>
+#include <gtest/gtest.h>
+#include <sstream>
+#include <string>
+
+using namespace isc::config;
+using namespace isc::data;
+
+namespace {
+
+/// @brief Test fixture class for @ref JSONFeed class.
+class JSONFeedTest : public ::testing::Test {
+public:
+
+ /// @brief Constructor.
+ ///
+ /// Initializes @ref json_map_ and @ref json_list_ which hold reference
+ /// JSON structures.
+ JSONFeedTest()
+ : json_map_(), json_list_() {
+ ElementPtr m = Element::fromJSON(createJSON());
+ ElementPtr l = Element::createList();
+ l->add(m);
+ json_map_ = m;
+ json_list_ = l;
+ }
+
+ /// @brief Creates a JSON map holding 20 elements.
+ ///
+ /// Each map value is a list of 20 elements.
+ std::string createJSON() const {
+ // Create a list of 20 elements.
+ ElementPtr list_element = Element::createList();
+ for (unsigned i = 0; i < 20; ++i) {
+ std::ostringstream s;
+ s << "list_element" << i;
+ list_element->add(Element::create(s.str()));
+ }
+
+ // Create a map of 20 elements. Each map element holds a list
+ // of 20 elements.
+ ElementPtr map_element = Element::createMap();
+ for (unsigned i = 0; i < 20; ++i) {
+ std::ostringstream s;
+ s << "map_element" << i;
+ map_element->set(s.str(), list_element);
+ }
+
+ return (prettyPrint(map_element));
+ }
+
+ /// @brief Test that the JSONFeed correctly recognizes the beginning
+ /// and the end of the JSON structure.
+ ///
+ /// @param input_json A string holding an input JSON structure.
+ /// @param expected_output A structure holding expected output from the
+ /// @ref JSONFeed::toElement.
+ void testRead(const std::string& input_json,
+ const ConstElementPtr& expected_output) {
+ JSONFeed feed;
+ ASSERT_NO_THROW(feed.initModel());
+
+ // Post the data into the feed in 10 bytes long chunks.
+ size_t chunk = 10;
+
+ for (size_t i = 0; i < input_json.size(); i += chunk) {
+ bool done = false;
+ // When we're near the end of the data stream, the chunk length may
+ // vary.
+ if (i + chunk >= input_json.size()) {
+ chunk = input_json.size() - i;
+ done = true;
+ }
+ // Feed the parser with a data chunk and parse it.
+ feed.postBuffer(&input_json[i], chunk);
+ feed.poll();
+ if (!done) {
+ ASSERT_TRUE(feed.needData());
+ }
+ }
+
+ // Convert parsed/collected data in the feed into the structure of
+ // elements.
+ ConstElementPtr element_from_feed = feed.toElement();
+ EXPECT_TRUE(element_from_feed->equals(*expected_output));
+ }
+
+ /// @brief Test that the @ref JSONFeed signals an error when the input
+ /// string holds invalid data.
+ ///
+ /// @param input_json A string holding an input JSON structure.
+ void testInvalidRead(const std::string& input_json) {
+ JSONFeed feed;
+ ASSERT_NO_THROW(feed.initModel());
+
+ ASSERT_NO_THROW(feed.postBuffer(&input_json[0], input_json.size()));
+ ASSERT_NO_THROW(feed.poll());
+
+ EXPECT_FALSE(feed.needData());
+ EXPECT_FALSE(feed.feedOk());
+ }
+
+ /// @brief JSON map holding a number of lists.
+ ConstElementPtr json_map_;
+
+ /// @brief JSON list holding a map of lists.
+ ConstElementPtr json_list_;
+
+};
+
+// This test verifies that a JSON structure starting with '{' is accepted
+// and parsed.
+TEST_F(JSONFeedTest, startWithBrace) {
+ std::string json = createJSON();
+ testRead(json, json_map_);
+}
+
+// This test verifies that a JSON structure starting with '[' is accepted
+// and parsed.
+TEST_F(JSONFeedTest, startWithSquareBracket) {
+ std::string json = createJSON();
+ json = std::string("[") + json + std::string("]");
+ testRead(json, json_list_);
+}
+
+// This test verifies that input JSON can be preceded with whitespaces.
+TEST_F(JSONFeedTest, startWithWhitespace) {
+ std::string json = createJSON();
+ json = std::string(" \r\r\t ") + json;
+ testRead(json, json_map_);
+}
+
+// This test verifies that an empty map is accepted and parsed.
+TEST_F(JSONFeedTest, emptyMap) {
+ std::string json = "{}";
+ testRead(json, Element::createMap());
+}
+
+// This test verifies that an empty list is accepted and parsed.
+TEST_F(JSONFeedTest, emptyList) {
+ std::string json = "[ ]";
+ testRead(json, Element::createList());
+}
+
+// This test verifies that an error is signalled when a JSON structure
+// is preceded by invalid character.
+TEST_F(JSONFeedTest, unexpectedCharacter) {
+ std::string json = "a {}";
+ testInvalidRead(json);
+}
+
+// This test verifies that an error is signalled when a JSON structure
+// lacks an opening brace character.
+TEST_F(JSONFeedTest, noOpeningBrace) {
+ std::string json = "\"x\": \"y\" }";
+ testInvalidRead(json);
+}
+
+// This test verifies that an error is signalled when a JSON structure
+// lacks an opening square bracket.
+TEST_F(JSONFeedTest, noOpeningSquareBracket) {
+ std::string json = "\"x\", \"y\" ]";
+ testInvalidRead(json);
+}
+
+} // end of anonymous namespace.