/* Ousía Copyright (C) 2014, 2015 Benjamin Paaßen, Andreas Stöckel This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include namespace ousia { namespace variant { //static TerminalLogger logger{std::cerr, true}; static Logger logger; TEST(Reader, readString) { // Simple, double quoted string { CharReader reader("\"hello world\""); auto res = VariantReader::parseString(reader, logger); ASSERT_TRUE(res.first); ASSERT_EQ("hello world", res.second); } // Simple, double quoted string with whitespace { CharReader reader(" \"hello world\" "); auto res = VariantReader::parseString(reader, logger); ASSERT_TRUE(res.first); ASSERT_EQ("hello world", res.second); } // Simple, single quoted string { CharReader reader("'hello world'"); auto res = VariantReader::parseString(reader, logger); ASSERT_TRUE(res.first); ASSERT_EQ("hello world", res.second); } // Escape characters { CharReader reader("'\\'\\\"\\b\\f\\n\\r\\t\\v'"); auto res = VariantReader::parseString(reader, logger); ASSERT_TRUE(res.first); ASSERT_EQ("'\"\b\f\n\r\t\v", res.second); } } TEST(Reader, parseUnescapedString) { // Simple case { CharReader reader("hello world;"); auto res = VariantReader::parseUnescapedString(reader, logger, {';'}); ASSERT_TRUE(res.first); ASSERT_EQ("hello world", res.second); } // Simple case with whitespace { CharReader reader(" hello world ; "); auto res = VariantReader::parseUnescapedString(reader, logger, {';'}); ASSERT_TRUE(res.first); ASSERT_EQ("hello world", res.second); } // Linebreaks { CharReader reader(" hello\nworld ; "); auto res = VariantReader::parseUnescapedString(reader, logger, {';'}); ASSERT_TRUE(res.first); ASSERT_EQ("hello\nworld", res.second); } // End of stream { CharReader reader(" hello world "); auto res = VariantReader::parseUnescapedString(reader, logger, {';'}); ASSERT_TRUE(res.first); ASSERT_EQ("hello world", res.second); } } static const std::unordered_set noDelim; TEST(Reader, parseInteger) { // Valid integers { CharReader reader("0 "); auto res = VariantReader::parseInteger(reader, logger, noDelim); ASSERT_TRUE(res.first); ASSERT_EQ(0, res.second); } { CharReader reader("42 "); auto res = VariantReader::parseInteger(reader, logger, noDelim); ASSERT_TRUE(res.first); ASSERT_EQ(42, res.second); } { CharReader reader("-42"); auto res = VariantReader::parseInteger(reader, logger, noDelim); ASSERT_TRUE(res.first); ASSERT_EQ(-42, res.second); } { CharReader reader(" -0x4A2 "); auto res = VariantReader::parseInteger(reader, logger, noDelim); ASSERT_TRUE(res.first); ASSERT_EQ(-0x4A2, res.second); } { CharReader reader(" 0Xaffe"); auto res = VariantReader::parseInteger(reader, logger, noDelim); ASSERT_TRUE(res.first); ASSERT_EQ(0xAFFE, res.second); } { CharReader reader("0x7FFFFFFFFFFFFFFF"); auto res = VariantReader::parseInteger(reader, logger, noDelim); ASSERT_TRUE(res.first); ASSERT_EQ(0x7FFFFFFFFFFFFFFFL, res.second); } { CharReader reader("-0x7FFFFFFFFFFFFFFF"); auto res = VariantReader::parseInteger(reader, logger, noDelim); ASSERT_TRUE(res.first); ASSERT_EQ(-0x7FFFFFFFFFFFFFFFL, res.second); } // Invalid integers { CharReader reader("-"); auto res = VariantReader::parseInteger(reader, logger, noDelim); ASSERT_FALSE(res.first); } { CharReader reader("0a"); auto res = VariantReader::parseInteger(reader, logger, noDelim); ASSERT_FALSE(res.first); } { CharReader reader("-0xag"); auto res = VariantReader::parseInteger(reader, logger, noDelim); ASSERT_FALSE(res.first); } { CharReader reader("0x8000000000000000"); auto res = VariantReader::parseInteger(reader, logger, noDelim); ASSERT_FALSE(res.first); } } TEST(Reader, parseDouble) { // Valid doubles { CharReader reader("1.25"); auto res = VariantReader::parseDouble(reader, logger, noDelim); ASSERT_TRUE(res.first); ASSERT_EQ(1.25, res.second); } { CharReader reader(".25"); auto res = VariantReader::parseDouble(reader, logger, noDelim); ASSERT_TRUE(res.first); ASSERT_EQ(.25, res.second); } { CharReader reader(".25e1"); auto res = VariantReader::parseDouble(reader, logger, noDelim); ASSERT_TRUE(res.first); ASSERT_EQ(2.5, res.second); } { CharReader reader("-2.5e-1"); auto res = VariantReader::parseDouble(reader, logger, noDelim); ASSERT_TRUE(res.first); ASSERT_EQ(-0.25, res.second); } { CharReader reader("-50e-2"); auto res = VariantReader::parseDouble(reader, logger, noDelim); ASSERT_TRUE(res.first); ASSERT_EQ(-0.5, res.second); } { CharReader reader("-1."); auto res = VariantReader::parseDouble(reader, logger, noDelim); ASSERT_TRUE(res.first); ASSERT_EQ(-1., res.second); } { CharReader reader("-50.e-2"); auto res = VariantReader::parseDouble(reader, logger, {'.'}); ASSERT_TRUE(res.first); ASSERT_EQ(-50, res.second); } // Invalid doubles { CharReader reader(".e1"); auto res = VariantReader::parseDouble(reader, logger, noDelim); ASSERT_FALSE(res.first); } { CharReader reader("0e100000"); auto res = VariantReader::parseDouble(reader, logger, noDelim); ASSERT_FALSE(res.first); } } TEST(Reader, parseArray) { // Simple case (only primitive data types) { CharReader reader("[\"Hello, World\", unescaped\n string ,\n" "1234, 0.56, true, false, null]"); auto res = VariantReader::parseArray(reader, logger); ASSERT_TRUE(res.first); // Make sure array has the correct size ASSERT_EQ(7U, res.second.size()); // Check the types ASSERT_TRUE(res.second[0].isString()); ASSERT_TRUE(res.second[1].isString()); ASSERT_TRUE(res.second[2].isInt()); ASSERT_TRUE(res.second[3].isDouble()); ASSERT_TRUE(res.second[4].isBool()); ASSERT_TRUE(res.second[5].isBool()); ASSERT_TRUE(res.second[6].isNull()); // Check the values ASSERT_EQ("Hello, World", res.second[0].asString()); ASSERT_EQ("unescaped\n string", res.second[1].asString()); ASSERT_EQ(1234, res.second[2].asInt()); ASSERT_EQ(0.56, res.second[3].asDouble()); ASSERT_TRUE(res.second[4].asBool()); ASSERT_FALSE(res.second[5].asBool()); } // Ending with comma { CharReader reader("[ 'test' ,]"); auto res = VariantReader::parseArray(reader, logger); ASSERT_TRUE(res.first); // Make sure the array has the correct size ASSERT_EQ(1U, res.second.size()); // Check the types ASSERT_TRUE(res.second[0].isString()); // Check the values ASSERT_EQ("test", res.second[0].asString()); } // Recovery from invalid values { CharReader reader("[ 0invalidNumber, str, 1invalid]"); auto res = VariantReader::parseArray(reader, logger); ASSERT_TRUE(res.first); // Make sure the array has the correct size ASSERT_EQ(3U, res.second.size()); // Check the types (all must be strings since the numbers are invalid) ASSERT_TRUE(res.second[0].isString()); ASSERT_TRUE(res.second[1].isString()); ASSERT_TRUE(res.second[2].isString()); // Check the values ASSERT_EQ("0invalidNumber", res.second[0].asString()); ASSERT_EQ("str", res.second[1].asString()); ASSERT_EQ("1invalid", res.second[2].asString()); } } TEST(Reader, parseGeneric) { // Simple case, unescaped string { CharReader reader("hello world"); auto res = VariantReader::parseGeneric(reader, logger, {';'}); ASSERT_TRUE(res.first); ASSERT_TRUE(res.second.isString()); ASSERT_EQ("hello world", res.second.asString()); } // Simple case, double quoted string { CharReader reader(" \"hello world\" "); auto res = VariantReader::parseGeneric(reader, logger, {';'}); ASSERT_TRUE(res.first); ASSERT_TRUE(res.second.isString()); ASSERT_EQ("hello world", res.second.asString()); } // Simple case, single quoted string { CharReader reader(" 'hello world' "); auto res = VariantReader::parseGeneric(reader, logger, {';'}); ASSERT_TRUE(res.first); ASSERT_TRUE(res.second.isString()); ASSERT_EQ("hello world", res.second.asString()); } } } }