123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268 |
- #include <library/cpp/testing/unittest/registar.h>
- #include <util/system/sanitizers.h>
- #include "json.h"
- #include <library/cpp/json/json_value.h>
- #include <limits>
- Y_UNIT_TEST_SUITE(JsonWriter) {
- Y_UNIT_TEST(Struct) {
- NJsonWriter::TBuf w;
- w.BeginList();
- w.BeginObject()
- .WriteKey("key")
- .WriteString("value")
- .UnsafeWritePair("\"xk\":13")
- .WriteKey("key2")
- .BeginList()
- .BeginObject()
- .EndObject()
- .BeginObject()
- .EndObject()
- .EndList()
- .EndObject();
- w.WriteInt(43);
- w.UnsafeWriteValue("\"x\"");
- w.WriteString("...");
- w.EndList();
- const char* exp = "[{\"key\":\"value\",\"xk\":13,\"key2\":[{},{}]},43,\"x\",\"...\"]";
- UNIT_ASSERT_EQUAL(w.Str(), exp);
- }
- Y_UNIT_TEST(EscapedString) {
- NJsonWriter::TBuf w(NJsonWriter::HEM_ESCAPE_HTML);
- w.WriteString(" \n \r \t \007 \b \f ' <tag> &ent; \"txt\" ");
- TString ws = w.Str();
- const char* exp = "\" \\n \\r \\t \\u0007 \\b \\f ' <tag> &ent; "txt" \"";
- UNIT_ASSERT_STRINGS_EQUAL(ws.c_str(), exp);
- }
- Y_UNIT_TEST(UnescapedString) {
- NJsonWriter::TBuf w;
- w.WriteString(" \n \r \t \b \f '; -- <tag> &ent; \"txt\"", NJsonWriter::HEM_DONT_ESCAPE_HTML);
- TString ws = w.Str();
- const char* exp = "\" \\n \\r \\t \\b \\f \\u0027; -- \\u003Ctag\\u003E &ent; \\\"txt\\\"\"";
- UNIT_ASSERT_STRINGS_EQUAL(ws.c_str(), exp);
- }
- Y_UNIT_TEST(UnescapedChaining) {
- NJsonWriter::TBuf w(NJsonWriter::HEM_DONT_ESCAPE_HTML);
- w.UnsafeWriteRawBytes("(", 1);
- w.BeginList().WriteString("<>&'\\").BeginList();
- w.EndList().EndList();
- TString ws = w.Str();
- const char* exp = "([\"\\u003C\\u003E&\\u0027\\\\\",[]]";
- UNIT_ASSERT_STRINGS_EQUAL(ws.c_str(), exp);
- }
- Y_UNIT_TEST(Utf8) {
- TString ws = NJsonWriter::TBuf().WriteString("яЯ σΣ ש א").Str();
- const char* exp = "\"яЯ σΣ ש א\"";
- UNIT_ASSERT_STRINGS_EQUAL(ws.c_str(), exp);
- }
- Y_UNIT_TEST(WrongObject) {
- NJsonWriter::TBuf w;
- w.BeginObject();
- UNIT_ASSERT_EXCEPTION(w.WriteString("hehe"), NJsonWriter::TError);
- }
- Y_UNIT_TEST(WrongList) {
- NJsonWriter::TBuf w;
- w.BeginList();
- UNIT_ASSERT_EXCEPTION(w.WriteKey("hehe"), NJsonWriter::TError);
- }
- Y_UNIT_TEST(Incomplete) {
- NJsonWriter::TBuf w;
- w.BeginList();
- UNIT_ASSERT_EXCEPTION(w.Str(), NJsonWriter::TError);
- }
- Y_UNIT_TEST(BareKey) {
- NJsonWriter::TBuf w;
- w.BeginObject()
- .CompatWriteKeyWithoutQuotes("p")
- .WriteInt(1)
- .CompatWriteKeyWithoutQuotes("n")
- .WriteInt(0)
- .EndObject();
- TString ws = w.Str();
- const char* exp = "{p:1,n:0}";
- UNIT_ASSERT_STRINGS_EQUAL(ws.c_str(), exp);
- }
- Y_UNIT_TEST(UnescapedStringInObject) {
- NJsonWriter::TBuf w(NJsonWriter::HEM_DONT_ESCAPE_HTML);
- w.BeginObject().WriteKey("key").WriteString("</&>'").EndObject();
- TString ws = w.Str();
- const char* exp = "{\"key\":\"\\u003C\\/&\\u003E\\u0027\"}";
- UNIT_ASSERT_STRINGS_EQUAL(ws.c_str(), exp);
- }
- Y_UNIT_TEST(ForeignStreamStr) {
- NJsonWriter::TBuf w(NJsonWriter::HEM_DONT_ESCAPE_HTML, &Cerr);
- UNIT_ASSERT_EXCEPTION(w.Str(), NJsonWriter::TError);
- }
- Y_UNIT_TEST(ForeignStreamValue) {
- TStringStream ss;
- NJsonWriter::TBuf w(NJsonWriter::HEM_DONT_ESCAPE_HTML, &ss);
- w.WriteInt(1543);
- UNIT_ASSERT_STRINGS_EQUAL(ss.Str(), "1543");
- }
- Y_UNIT_TEST(Indentation) {
- NJsonWriter::TBuf w(NJsonWriter::HEM_DONT_ESCAPE_HTML);
- w.SetIndentSpaces(2);
- w.BeginList()
- .WriteInt(1)
- .WriteString("hello")
- .BeginObject()
- .WriteKey("abc")
- .WriteInt(3)
- .WriteKey("def")
- .WriteInt(4)
- .EndObject()
- .EndList();
- const char* exp = "[\n"
- " 1,\n"
- " \"hello\",\n"
- " {\n"
- " \"abc\":3,\n"
- " \"def\":4\n"
- " }\n"
- "]";
- UNIT_ASSERT_STRINGS_EQUAL(exp, w.Str());
- }
- Y_UNIT_TEST(WriteJsonValue) {
- using namespace NJson;
- TJsonValue val;
- val.AppendValue(1);
- val.AppendValue("2");
- val.AppendValue(3.5);
- TJsonValue obj;
- obj.InsertValue("key", TJsonValue("value"));
- val.AppendValue(obj);
- val.AppendValue(TJsonValue(JSON_NULL));
- NJsonWriter::TBuf w(NJsonWriter::HEM_DONT_ESCAPE_HTML);
- w.WriteJsonValue(&val);
- const char exp[] = "[1,\"2\",3.5,{\"key\":\"value\"},null]";
- UNIT_ASSERT_STRINGS_EQUAL(exp, w.Str());
- }
- Y_UNIT_TEST(WriteJsonValueSorted) {
- using namespace NJson;
- TJsonValue val;
- val.InsertValue("1", TJsonValue(1));
- val.InsertValue("2", TJsonValue(2));
- TJsonValue obj;
- obj.InsertValue("zero", TJsonValue(0));
- obj.InsertValue("succ", TJsonValue(1));
- val.InsertValue("0", obj);
- NJsonWriter::TBuf w(NJsonWriter::HEM_DONT_ESCAPE_HTML);
- w.WriteJsonValue(&val, true);
- const char exp[] = "{\"0\":{\"succ\":1,\"zero\":0},\"1\":1,\"2\":2}";
- UNIT_ASSERT_STRINGS_EQUAL(exp, w.Str());
- }
- Y_UNIT_TEST(Unescaped) {
- NJsonWriter::TBuf buf(NJsonWriter::HEM_UNSAFE);
- buf.WriteString("</security>'");
- UNIT_ASSERT_STRINGS_EQUAL("\"</security>'\"", buf.Str());
- }
- Y_UNIT_TEST(LittleBobbyJsonp) {
- NJsonWriter::TBuf buf;
- buf.WriteString("hello\xe2\x80\xa8\xe2\x80\xa9stranger");
- UNIT_ASSERT_STRINGS_EQUAL("\"hello\\u2028\\u2029stranger\"", buf.Str());
- }
- Y_UNIT_TEST(LittleBobbyInvalid) {
- NJsonWriter::TBuf buf;
- TStringBuf incomplete("\xe2\x80\xa8", 2);
- buf.WriteString(incomplete);
- // garbage in - garbage out
- UNIT_ASSERT_STRINGS_EQUAL("\"\xe2\x80\"", buf.Str());
- }
- Y_UNIT_TEST(OverlyZealous) {
- NJsonWriter::TBuf buf;
- buf.WriteString("—");
- UNIT_ASSERT_STRINGS_EQUAL("\"—\"", buf.Str());
- }
- Y_UNIT_TEST(RelaxedEscaping) {
- NJsonWriter::TBuf buf(NJsonWriter::HEM_RELAXED);
- buf.WriteString("</>");
- UNIT_ASSERT_STRINGS_EQUAL("\"\\u003C/\\u003E\"", buf.Str());
- }
- Y_UNIT_TEST(FloatFormatting) {
- NJsonWriter::TBuf buf(NJsonWriter::HEM_DONT_ESCAPE_HTML);
- buf.BeginList()
- .WriteFloat(0.12345678987654321f)
- .WriteDouble(0.12345678987654321)
- .WriteFloat(0.315501, PREC_NDIGITS, 3)
- .WriteFloat(244.13854, PREC_NDIGITS, 4)
- .WriteFloat(10385.8324, PREC_POINT_DIGITS, 2)
- .BeginObject()
- .WriteKey("1")
- .WriteDouble(1111.71, PREC_POINT_DIGITS, 0)
- .WriteKey("2")
- .WriteDouble(1111.71, PREC_NDIGITS, 1)
- .EndObject()
- .EndList();
- const char exp[] = "[0.123457,0.1234567899,0.316,244.1,10385.83,{\"1\":1112,\"2\":1e+03}]";
- UNIT_ASSERT_STRINGS_EQUAL(exp, buf.Str());
- }
- Y_UNIT_TEST(NanFormatting) {
- {
- NJsonWriter::TBuf buf;
- buf.BeginObject();
- buf.WriteKey("nanvalue");
- UNIT_ASSERT_EXCEPTION(buf.WriteFloat(std::numeric_limits<double>::quiet_NaN()), yexception);
- }
- {
- NJsonWriter::TBuf buf;
- buf.BeginObject();
- buf.WriteKey("infvalue");
- UNIT_ASSERT_EXCEPTION(buf.WriteFloat(std::numeric_limits<double>::infinity()), yexception);
- }
- {
- NJsonWriter::TBuf buf;
- buf.BeginList();
- UNIT_ASSERT_EXCEPTION(buf.WriteFloat(std::numeric_limits<double>::quiet_NaN()), yexception);
- }
- {
- NJsonWriter::TBuf buf;
- buf.BeginList();
- UNIT_ASSERT_EXCEPTION(buf.WriteFloat(std::numeric_limits<double>::infinity()), yexception);
- }
- {
- NJsonWriter::TBuf buf;
- buf.SetWriteNanAsString();
- buf.BeginObject()
- .WriteKey("nanvalue")
- .WriteFloat(std::numeric_limits<double>::quiet_NaN())
- .WriteKey("infvalue")
- .WriteFloat(std::numeric_limits<double>::infinity())
- .WriteKey("minus_infvalue")
- .WriteFloat(-std::numeric_limits<float>::infinity())
- .WriteKey("l")
- .BeginList()
- .WriteFloat(std::numeric_limits<float>::quiet_NaN())
- .EndList()
- .EndObject();
- UNIT_ASSERT_STRINGS_EQUAL(buf.Str(), R"raw_json({"nanvalue":"nan","infvalue":"inf","minus_infvalue":"-inf","l":["nan"]})raw_json");
- }
- {
- NJsonWriter::TBuf buf;
- buf.BeginObject()
- .WriteKey("<>&")
- .WriteString("Ololo")
- .UnsafeWriteKey("<>&")
- .WriteString("Ololo2")
- .EndObject();
- UNIT_ASSERT_STRINGS_EQUAL(buf.Str(), R"({"\u003C\u003E&":"Ololo","<>&":"Ololo2"})");
- }
- }
- }
|