1/*
2 * Copyright 2015-present Facebook, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <folly/json.h>
18
19#include <folly/Benchmark.h>
20#include <folly/Conv.h>
21#include <folly/FileUtil.h>
22#include <folly/Range.h>
23#include <folly/portability/GFlags.h>
24#include <folly/portability/GTest.h>
25
26using folly::dynamic;
27using folly::parseJson;
28using folly::toJson;
29
30constexpr folly::StringPiece kLargeAsciiString =
31 "akjhfk jhkjlakjhfk jhkjlakjhfk jhkjl akjhfk"
32 "akjhfk jhkjlakjhfk jhkjlakjhfk jhkjl akjhfk"
33 "akjhfk jhkjlakjhfk jhkjlakjhfk jhkjl akjhfk"
34 "akjhfk jhkjlakjhfk jhkjlakjhfk jhkjl akjhfk"
35 "akjhfk jhkjlakjhfk jhkjlakjhfk jhkjl akjhfk"
36 "akjhfk jhkjlakjhfk jhkjlakjhfk jhkjl akjhfk"
37 "akjhfk jhkjlakjhfk jhkjlakjhfk jhkjl akjhfk"
38 "akjhfk jhkjlakjhfk jhkjlakjhfk jhkjl akjhfk"
39 "akjhfk jhkjlakjhfk jhkjlakjhfk jhkjl akjhfk"
40 "akjhfk jhkjlakjhfk jhkjlakjhfk jhkjl akjhfk"
41 "akjhfk jhkjlakjhfk jhkjlakjhfk jhkjl akjhfk";
42
43constexpr folly::StringPiece kLargeNonAsciiString =
44 "qwerty \xc2\x80 \xef\xbf\xbf poiuy"
45 "qwerty \xc2\x80 \xef\xbf\xbf poiuy"
46 "qwerty \xc2\x80 \xef\xbf\xbf poiuy"
47 "qwerty \xc2\x80 \xef\xbf\xbf poiuy"
48 "qwerty \xc2\x80 \xef\xbf\xbf poiuy"
49 "qwerty \xc2\x80 \xef\xbf\xbf poiuy"
50 "qwerty \xc2\x80 \xef\xbf\xbf poiuy"
51 "qwerty \xc2\x80 \xef\xbf\xbf poiuy"
52 "qwerty \xc2\x80 \xef\xbf\xbf poiuy"
53 "qwerty \xc2\x80 \xef\xbf\xbf poiuy";
54
55constexpr folly::StringPiece kLargeAsciiStringWithSpecialChars =
56 "<script>foo%@bar.com</script>"
57 "<script>foo%@bar.com</script>"
58 "<script>foo%@bar.com</script>"
59 "<script>foo%@bar.com</script>"
60 "<script>foo%@bar.com</script>"
61 "<script>foo%@bar.com</script>"
62 "<script>foo%@bar.com</script>";
63
64TEST(Json, StripComments) {
65 const std::string kTestDir = "folly/test/";
66 const std::string kTestFile = "json_test_data/commented.json";
67 const std::string kTestExpected = "json_test_data/commented.json.exp";
68
69 std::string testStr;
70 std::string expectedStr;
71 if (!folly::readFile(kTestFile.data(), testStr) &&
72 !folly::readFile((kTestDir + kTestFile).data(), testStr)) {
73 FAIL() << "can not read test file " << kTestFile;
74 }
75 if (!folly::readFile(kTestExpected.data(), expectedStr) &&
76 !folly::readFile((kTestDir + kTestExpected).data(), expectedStr)) {
77 FAIL() << "can not read test file " << kTestExpected;
78 }
79 EXPECT_EQ(expectedStr, folly::json::stripComments(testStr));
80}
81
82BENCHMARK(jsonSerialize, iters) {
83 const dynamic obj = kLargeNonAsciiString;
84
85 folly::json::serialization_opts opts;
86 for (size_t i = 0; i < iters; ++i) {
87 folly::json::serialize(obj, opts);
88 }
89}
90
91BENCHMARK(jsonSerializeWithNonAsciiEncoding, iters) {
92 const dynamic obj = kLargeNonAsciiString;
93
94 folly::json::serialization_opts opts;
95 opts.encode_non_ascii = true;
96
97 for (size_t i = 0; i < iters; ++i) {
98 folly::json::serialize(obj, opts);
99 }
100}
101
102BENCHMARK(jsonSerializeWithUtf8Validation, iters) {
103 const dynamic obj = kLargeNonAsciiString;
104
105 folly::json::serialization_opts opts;
106 opts.validate_utf8 = true;
107
108 for (size_t i = 0; i < iters; ++i) {
109 folly::json::serialize(obj, opts);
110 }
111}
112
113BENCHMARK(jsonSerializeAsciiWithUtf8Validation, iters) {
114 const dynamic obj = kLargeAsciiString;
115
116 folly::json::serialization_opts opts;
117 opts.validate_utf8 = true;
118
119 for (size_t i = 0; i < iters; ++i) {
120 folly::json::serialize(obj, opts);
121 }
122}
123
124BENCHMARK(jsonSerializeWithExtraUnicodeEscapes, iters) {
125 const dynamic obj = kLargeAsciiStringWithSpecialChars;
126
127 folly::json::serialization_opts opts;
128 opts.extra_ascii_to_escape_bitmap =
129 folly::json::buildExtraAsciiToEscapeBitmap("<%@");
130
131 for (size_t i = 0; i < iters; ++i) {
132 folly::json::serialize(obj, opts);
133 }
134}
135
136BENCHMARK(parseSmallStringWithUtf, iters) {
137 for (size_t i = 0; i < iters << 4; ++i) {
138 parseJson("\"I \\u2665 UTF-8 thjasdhkjh blah blah blah\"");
139 }
140}
141
142BENCHMARK(parseNormalString, iters) {
143 for (size_t i = 0; i < iters << 4; ++i) {
144 parseJson("\"akjhfk jhkjlakjhfk jhkjlakjhfk jhkjl akjhfk\"");
145 }
146}
147
148BENCHMARK(parseBigString, iters) {
149 const auto json = folly::to<std::string>('"', kLargeAsciiString, '"');
150
151 for (size_t i = 0; i < iters; ++i) {
152 parseJson(json);
153 }
154}
155
156BENCHMARK(toJson, iters) {
157 dynamic something = parseJson(
158 "{\"old_value\":40,\"changed\":true,\"opened\":false,\"foo\":[1,2,3,4,5,6]}");
159
160 for (size_t i = 0; i < iters; i++) {
161 toJson(something);
162 }
163}
164
165int main(int argc, char** argv) {
166 testing::InitGoogleTest(&argc, argv);
167 gflags::ParseCommandLineFlags(&argc, &argv, true);
168 if (FLAGS_benchmark) {
169 folly::runBenchmarks();
170 }
171 return RUN_ALL_TESTS();
172}
173