Roll src/third_party/WebKit bf18a82:a9cee16 (svn 185297:185304)
[chromium-blink-merge.git] / chrome / tools / profile_reset / jtl_parser_unittest.cc
blobfd43d8edef9f6828e45c6908629c6a9c266b3012
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/tools/profile_reset/jtl_parser.h"
7 #include "base/json/json_writer.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/values.h"
10 #include "testing/gmock/include/gmock/gmock.h"
11 #include "testing/gtest/include/gtest/gtest.h"
13 namespace {
15 // Helpers -------------------------------------------------------------------
17 void ExpectNextOperation(JtlParser* parser,
18 const char* expected_name,
19 const char* expected_args_json,
20 bool expected_ends_sentence) {
21 std::string actual_name;
22 base::ListValue actual_args;
23 std::string actual_args_json;
24 bool actual_ends_sentence;
26 EXPECT_FALSE(parser->HasFinished());
27 EXPECT_TRUE(parser->ParseNextOperation(
28 &actual_name, &actual_args, &actual_ends_sentence));
29 EXPECT_EQ(expected_name, actual_name);
30 base::JSONWriter::Write(&actual_args, &actual_args_json);
31 EXPECT_EQ(expected_args_json, actual_args_json);
32 EXPECT_EQ(expected_ends_sentence, actual_ends_sentence);
35 void ExpectNextOperationToFail(JtlParser* parser,
36 size_t expected_line_number,
37 const char* expected_context_prefix) {
38 std::string actual_name;
39 base::ListValue actual_args;
40 bool actual_ends_sentence;
42 EXPECT_FALSE(parser->HasFinished());
43 EXPECT_FALSE(parser->ParseNextOperation(
44 &actual_name, &actual_args, &actual_ends_sentence));
45 EXPECT_THAT(parser->GetLastContext(),
46 testing::StartsWith(expected_context_prefix));
47 EXPECT_EQ(expected_line_number, parser->GetLastLineNumber());
50 JtlParser* CreateParserFromVerboseText(const std::string& verbose_text) {
51 std::string compacted_source_code;
52 std::vector<size_t> newline_indices;
53 EXPECT_TRUE(JtlParser::RemoveCommentsAndAllWhitespace(
54 verbose_text, &compacted_source_code, &newline_indices, NULL));
55 return new JtlParser(compacted_source_code, newline_indices);
58 // Tests ---------------------------------------------------------------------
60 TEST(JtlParser, CompactingEmpty) {
61 const char kSourceCode[] = "";
62 const char kCompactedSourceCode[] = "";
64 scoped_ptr<JtlParser> parser(CreateParserFromVerboseText(kSourceCode));
65 EXPECT_EQ(kCompactedSourceCode, parser->compacted_source());
68 TEST(JtlParser, CompactingTrivial) {
69 const char kSourceCode[] = "foo";
70 const char kCompactedSourceCode[] = "foo";
72 scoped_ptr<JtlParser> parser(CreateParserFromVerboseText(kSourceCode));
73 EXPECT_EQ(kCompactedSourceCode, parser->compacted_source());
76 TEST(JtlParser, CompactingOneLine) {
77 const char kSourceCode[] = " \r f\to o ( true ) ";
78 const char kCompactedSourceCode[] = "foo(true)";
80 scoped_ptr<JtlParser> parser(CreateParserFromVerboseText(kSourceCode));
81 EXPECT_EQ(kCompactedSourceCode, parser->compacted_source());
82 for (size_t i = 0; i < arraysize(kCompactedSourceCode) - 1; ++i) {
83 SCOPED_TRACE(testing::Message("Position ") << i);
84 EXPECT_EQ(0u, parser->GetOriginalLineNumber(i));
88 TEST(JtlParser, CompactingMultipleLines) {
89 const char kSourceCode[] = "a\nbb\n \nccc \n\n d( \n e \n )";
90 const char kCompactedSourceCode[] = "abbcccd(e)";
91 const size_t kLineNumbers[] = {0u, 1u, 1u, 3u, 3u, 3u, 5u, 5u, 6u, 7u};
92 COMPILE_ASSERT(arraysize(kCompactedSourceCode) == arraysize(kLineNumbers) + 1,
93 mismatched_test_data);
95 scoped_ptr<JtlParser> parser(CreateParserFromVerboseText(kSourceCode));
96 EXPECT_EQ(kCompactedSourceCode, parser->compacted_source());
97 for (size_t i = 0; i < arraysize(kLineNumbers); ++i) {
98 SCOPED_TRACE(testing::Message("Position ") << i);
99 EXPECT_EQ(kLineNumbers[i], parser->GetOriginalLineNumber(i));
103 TEST(JtlParser, CompactingMultipleLinesWithComments) {
104 const char kSourceCode[] =
105 "a/ /b//Comment \n"
106 "//\n"
107 "// Full line comment\n"
108 " cd //";
109 const char kCompactedSourceCode[] = "a//bcd";
110 const size_t kLineNumbers[] = {0u, 0u, 0u, 0u, 3u, 3u};
111 COMPILE_ASSERT(arraysize(kCompactedSourceCode) == arraysize(kLineNumbers) + 1,
112 mismatched_test_data);
114 scoped_ptr<JtlParser> parser(CreateParserFromVerboseText(kSourceCode));
115 EXPECT_EQ(kCompactedSourceCode, parser->compacted_source());
116 for (size_t i = 0; i < arraysize(kLineNumbers); ++i) {
117 SCOPED_TRACE(testing::Message("Position ") << i);
118 EXPECT_EQ(kLineNumbers[i], parser->GetOriginalLineNumber(i));
122 TEST(JtlParser, HandlingCommentsAndStringLiterals) {
123 struct TestCase {
124 const char* source_code;
125 const char* compacted_source_code;
126 } cases[] = {
127 {"//", ""},
128 {"//comment", ""},
129 {"foo // comment", "foo"},
130 {"foo // // comment", "foo"},
131 {"foo //", "foo"},
132 {"\"literal\"", "\"literal\""},
133 {"\"literal with space\"", "\"literal with space\""},
134 {"\"\"", "\"\""},
135 {"\"\"\"\"", "\"\"\"\""},
136 {"\"\" // comment", "\"\""},
137 {"\"literal\" // comment", "\"literal\""},
138 {"\"literal\" \"literal\" // comment", "\"literal\"\"literal\""},
139 {"foo // \"not a literal\"", "foo"},
140 {"foo // \"not even matched", "foo"},
141 {"foo // \"not a literal\" \"not even matched", "foo"},
142 {"\"literal\" // \"not a literal\"", "\"literal\""},
143 {"\"literal\" // \"not even matched", "\"literal\""},
144 {"\"//not a comment//\"", "\"//not a comment//\""},
145 {"\"//not a comment//\" // comment", "\"//not a comment//\""},
146 {"// \"//not a literal//\" // comment", ""},
147 {"\"literal\" // \"//not a literal//\" // comment", "\"literal\""},
148 {"\"//not a comment//\" // \"//not a literal//\" // comment",
149 "\"//not a comment//\""},
150 {"\"literal // \"not a literal nor a comment",
151 "\"literal // \"notaliteralnoracomment"},
152 {"\"literal // \"not a literal nor a comment//\"",
153 "\"literal // \"notaliteralnoracomment"}
156 for (size_t i = 0; i < arraysize(cases); ++i) {
157 SCOPED_TRACE(cases[i].source_code);
158 scoped_ptr<JtlParser> parser(
159 CreateParserFromVerboseText(cases[i].source_code));
160 EXPECT_EQ(cases[i].compacted_source_code, parser->compacted_source());
164 TEST(JtlParser, MismatchedDoubleQuotesBeforeEndOfLine) {
165 struct TestCase {
166 const char* source_code;
167 size_t error_line_number;
168 } cases[] = {
169 {"\"", 0},
170 {"\"mismatched literal", 0},
171 {"\n\"", 1},
172 {"\"\n\"", 0},
173 {"\"\"\"", 0},
174 {"\"\"\n\"", 1},
175 {"\"\"\n\"\n\"", 1},
176 {"\" // not a comment", 0},
177 {"\" // not a comment\n\"", 0},
178 {"\"\" // comment\n\"", 1},
179 {"\"\"\" // not a comment\n\"", 0},
180 {"\"\"\" // \" neither a literal nor a comment\"\n\"", 0},
181 {"\"\" // comment\n\"// not a comment", 1},
182 {"\" // not a comment\"\n\"// not a comment", 1},
183 {"foo(\"bar\");\nfoo(\"mismatched);", 1},
184 {"foo(\n\"bar\", \"mismatched);", 1},
185 {"foo(\n\"bar\", \"mismatched); //comment", 1},
186 {"foo(\n\"bar\", \"mismatched);\ngood(\"bar\")", 1}
189 for (size_t i = 0; i < arraysize(cases); ++i) {
190 SCOPED_TRACE(cases[i].source_code);
191 std::string compacted_source_code;
192 std::vector<size_t> newline_indices;
193 size_t error_line_number;
194 EXPECT_FALSE(JtlParser::RemoveCommentsAndAllWhitespace(
195 cases[i].source_code,
196 &compacted_source_code,
197 &newline_indices,
198 &error_line_number));
199 EXPECT_EQ(cases[i].error_line_number, error_line_number);
203 TEST(JtlParser, ParsingEmpty) {
204 const char kSourceCode[] = "";
206 scoped_ptr<JtlParser> parser(CreateParserFromVerboseText(kSourceCode));
207 EXPECT_TRUE(parser->HasFinished());
210 TEST(JtlParser, ParsingOneWellFormedOperation) {
211 struct TestCase {
212 const char* source_code;
213 const char* expected_name;
214 const char* expected_args;
215 const bool expected_ends_sentence;
216 } cases[] = {
217 {"foo1;", "foo1", "[]", true},
218 {"foo2().", "foo2", "[]", false},
219 {"foo3(true);", "foo3", "[true]", true},
220 {"foo4(false).", "foo4", "[false]", false},
221 {"foo5(\"bar\").", "foo5", "[\"bar\"]", false},
222 {"foo6(\" b a r \").", "foo6", "[\" b a r \"]", false},
223 {"foo7(true, \"bar\").", "foo7", "[true,\"bar\"]", false},
224 {"foo8(\"bar\", false, true);", "foo8", "[\"bar\",false,true]", true},
225 {"foo9(\"bar\", \" b a r \");", "foo9", "[\"bar\",\" b a r \"]", true}
228 for (size_t i = 0; i < arraysize(cases); ++i) {
229 SCOPED_TRACE(cases[i].expected_name);
230 scoped_ptr<JtlParser> parser(
231 CreateParserFromVerboseText(cases[i].source_code));
232 ExpectNextOperation(parser.get(),
233 cases[i].expected_name,
234 cases[i].expected_args,
235 cases[i].expected_ends_sentence);
236 EXPECT_TRUE(parser->HasFinished());
240 TEST(JtlParser, ParsingMultipleWellFormedOperations) {
241 const char kSourceCode[] =
242 "foo1(true).foo2.foo3(\"bar\");"
243 "foo4(\"bar\", false);";
245 scoped_ptr<JtlParser> parser(CreateParserFromVerboseText(kSourceCode));
246 ExpectNextOperation(parser.get(), "foo1", "[true]", false);
247 ExpectNextOperation(parser.get(), "foo2", "[]", false);
248 ExpectNextOperation(parser.get(), "foo3", "[\"bar\"]", true);
249 ExpectNextOperation(parser.get(), "foo4", "[\"bar\",false]", true);
250 EXPECT_TRUE(parser->HasFinished());
253 TEST(JtlParser, ParsingTrickyStringLiterals) {
254 struct TestCase {
255 const char* source_code;
256 const char* expected_name;
257 const char* expected_args;
258 const bool expected_ends_sentence;
259 } cases[] = {
260 {"prev().foo1(\"\");next(true);", "foo1", "[\"\"]", true},
261 {"prev().foo2(\" \");next(true);", "foo2", "[\" \"]", true},
262 {"prev().foo3(\",\",true);next(true);", "foo3", "[\",\",true]", true},
263 {"prev().foo4(\")\",true);next(true);", "foo4", "[\")\",true]", true},
264 {"prev().foo5(\";\",true);next(true);", "foo5", "[\";\",true]", true},
265 {"prev().foo6(\"/\",true).next(true);", "foo6", "[\"/\",true]", false},
266 {"prev().foo7(\"//\",true).next(true);", "foo7", "[\"//\",true]", false},
267 {"prev().foo8(\".\",true).next(true);", "foo8", "[\".\",true]", false},
270 for (size_t i = 0; i < arraysize(cases); ++i) {
271 SCOPED_TRACE(cases[i].expected_name);
272 scoped_ptr<JtlParser> parser(
273 CreateParserFromVerboseText(cases[i].source_code));
274 ExpectNextOperation(parser.get(), "prev", "[]", false);
275 ExpectNextOperation(parser.get(),
276 cases[i].expected_name,
277 cases[i].expected_args,
278 cases[i].expected_ends_sentence);
279 ExpectNextOperation(parser.get(), "next", "[true]", true);
280 EXPECT_TRUE(parser->HasFinished());
284 TEST(JtlParser, FirstOperationIsIllFormed) {
285 struct TestCase {
286 const char* source_code;
287 const char* operation_name;
288 } cases[] = {
289 {";;", ";"},
290 {"bad_args1(not a boolean value);", "bad_args1"},
291 {"bad_args2(,);", "bad_args2"},
292 {"bad_args3(...);", "bad_args3"},
293 {"bad_args4(1);", "bad_args4"},
294 {"bad_args5(1.2);", "bad_args5"},
295 {"bad_args6([\"bar\"]);", "bad_args6"},
296 {"bad_args7(False);", "bad_args7"},
297 {"bad_args8(True);", "bad_args8"},
298 {"bad_quotes1(missing both, true).good();", "bad_quotes1"},
299 {"bad_quotes2(true, \"missing one).good(); //\"", "bad_quotes2"},
300 {"bad_quotes3(\"too\" \"much\", true).good();", "bad_quotes3"},
301 {"bad_missing_separator1", "bad_missing_separator1"},
302 {"bad_missing_separator2()good();", "bad_missing_separator2"},
303 {"bad_parenthesis1(true.good();", "bad_parenthesis1"},
304 {"bad_parenthesis2(true.good());", "bad_parenthesis2"},
305 {"bad_parenthesis3).good();", "bad_parenthesis3"}
308 for (size_t i = 0; i < arraysize(cases); ++i) {
309 SCOPED_TRACE(cases[i].operation_name);
310 scoped_ptr<JtlParser> parser(
311 CreateParserFromVerboseText(cases[i].source_code));
312 ExpectNextOperationToFail(parser.get(), 0, cases[i].operation_name);
316 TEST(JtlParser, SecondOperationIsIllFormed) {
317 struct TestCase {
318 const char* source_code;
319 const char* bad_operation_name;
320 } cases[] = {
321 {"\ngood(true,false)\n.bad_args(,);", "bad_args"},
322 {"\ngood(true,false)\n.bad_quotes1(missing both, true).good();",
323 "bad_quotes1"},
324 {"\ngood(true,false)\n.bad_quotes2(\"missing one, true).good(); //\"",
325 "bad_quotes2"},
326 {"\ngood(true,false)\n.bad_quotes3(\"too\" \"many\", true).good();",
327 "bad_quotes3"},
328 {"\ngood(true,false)\n.bad_separator1()/good();", "bad_separator1"},
329 {"\ngood(true,false)\n.missing_separator1", "missing_separator1"},
330 {"\ngood(true,false)\n.missing_separator2()good();",
331 "missing_separator2"},
332 {"\ngood(true,false)\n.bad_parens1(true.good();", "bad_parens1"},
333 {"\ngood(true,false)\n.bad_parens2(true.good());", "bad_parens2"},
334 {"\ngood(true,false)\n.bad_parens3).good();", "bad_parens3"}
337 for (size_t i = 0; i < arraysize(cases); ++i) {
338 SCOPED_TRACE(cases[i].bad_operation_name);
339 scoped_ptr<JtlParser> parser(
340 CreateParserFromVerboseText(cases[i].source_code));
341 ExpectNextOperation(parser.get(), "good", "[true,false]", false);
342 ExpectNextOperationToFail(parser.get(), 2, cases[i].bad_operation_name);
346 } // namespace