/*
- * Copyright 2016 Facebook, Inc.
+ * Copyright 2017 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
}
TEST(Json, JavascriptSafe) {
- auto badDouble = (1ll << 63ll) + 1;
+ auto badDouble = int64_t((1ULL << 63ULL) + 1);
dynamic badDyn = badDouble;
EXPECT_EQ(folly::toJson(badDouble), folly::to<std::string>(badDouble));
folly::json::serialization_opts opts;
opts.javascript_safe = true;
EXPECT_ANY_THROW(folly::json::serialize(badDouble, opts));
- auto okDouble = 1ll << 63ll;
+ auto okDouble = int64_t(1ULL << 63ULL);
dynamic okDyn = okDouble;
EXPECT_EQ(folly::toJson(okDouble), folly::to<std::string>(okDouble));
}
R"("\b\f\n\r\u0001\t\\\"/\u000b\u0007")");
}
+TEST(Json, EscapeCornerCases) {
+ // The escaping logic uses some bitwise operations to determine
+ // which bytes need escaping 8 bytes at a time. Test that this logic
+ // is correct regardless of positions by planting 2 characters that
+ // may need escaping at each possible position and checking the
+ // result, for varying string lengths.
+
+ folly::json::serialization_opts opts;
+ opts.validate_utf8 = true;
+
+ std::string s;
+ std::string expected;
+ for (bool ascii : {true, false}) {
+ opts.encode_non_ascii = ascii;
+
+ for (size_t len = 2; len < 32; ++len) {
+ for (size_t i = 0; i < len; ++i) {
+ for (size_t j = 0; j < len; ++j) {
+ if (i == j) {
+ continue;
+ }
+
+ s.clear();
+ expected.clear();
+
+ expected.push_back('"');
+ for (size_t pos = 0; pos < len; ++pos) {
+ if (pos == i) {
+ s.push_back('\\');
+ expected.append("\\\\");
+ } else if (pos == j) {
+ s.append("\xe2\x82\xac");
+ expected.append(ascii ? "\\u20ac" : "\xe2\x82\xac");
+ } else {
+ s.push_back('x');
+ expected.push_back('x');
+ }
+ }
+ expected.push_back('"');
+
+ EXPECT_EQ(folly::json::serialize(s, opts), expected) << ascii;
+ }
+ }
+ }
+ }
+}
+
TEST(Json, JsonNonAsciiEncoding) {
folly::json::serialization_opts opts;
opts.encode_non_ascii = true;
}
TEST(Json, SortKeys) {
- folly::json::serialization_opts opts_on, opts_off;
+ folly::json::serialization_opts opts_on, opts_off, opts_custom_sort;
opts_on.sort_keys = true;
opts_off.sort_keys = false;
+ opts_custom_sort.sort_keys = false; // should not be required
+ opts_custom_sort.sort_keys_by = [](
+ folly::dynamic const& a, folly::dynamic const& b) {
+ // just an inverse sort
+ return b < a;
+ };
+
dynamic value = dynamic::object
("foo", "bar")
("junk", 12)
R"({"a":[{"a":"b","c":"d"},12.5,"Yo Dawg",["heh"],null],)"
R"("another":32.2,"foo":"bar","junk":12})";
+ std::string inverse_sorted_keys =
+ R"({"junk":12,"foo":"bar","another":32.2,)"
+ R"("a":[{"c":"d","a":"b"},12.5,"Yo Dawg",["heh"],null]})";
+
EXPECT_EQ(value, parseJson(folly::json::serialize(value, opts_on)));
EXPECT_EQ(value, parseJson(folly::json::serialize(value, opts_off)));
+ EXPECT_EQ(value, parseJson(folly::json::serialize(value, opts_custom_sort)));
EXPECT_EQ(sorted_keys, folly::json::serialize(value, opts_on));
+ EXPECT_NE(sorted_keys, folly::json::serialize(value, opts_off));
+ EXPECT_EQ(
+ inverse_sorted_keys, folly::json::serialize(value, opts_custom_sort));
}
TEST(Json, PrintTo) {