- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / tools / profile_reset / jtl_parser_unittest.cc
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.
4
5 #include "chrome/tools/profile_reset/jtl_parser.h"
6
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"
12
13 namespace {
14
15 // Helpers -------------------------------------------------------------------
16
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;
25
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);
33 }
34
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;
41
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());
48 }
49
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);
56 }
57
58 // Tests ---------------------------------------------------------------------
59
60 TEST(JtlParser, CompactingEmpty) {
61   const char kSourceCode[] = "";
62   const char kCompactedSourceCode[] = "";
63
64   scoped_ptr<JtlParser> parser(CreateParserFromVerboseText(kSourceCode));
65   EXPECT_EQ(kCompactedSourceCode, parser->compacted_source());
66 }
67
68 TEST(JtlParser, CompactingTrivial) {
69   const char kSourceCode[] = "foo";
70   const char kCompactedSourceCode[] = "foo";
71
72   scoped_ptr<JtlParser> parser(CreateParserFromVerboseText(kSourceCode));
73   EXPECT_EQ(kCompactedSourceCode, parser->compacted_source());
74 }
75
76 TEST(JtlParser, CompactingOneLine) {
77   const char kSourceCode[] = "  \r f\to o  ( true )   ";
78   const char kCompactedSourceCode[] = "foo(true)";
79
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));
85   }
86 }
87
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);
94
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));
100   }
101 }
102
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);
113
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));
119   }
120 }
121
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"}
154   };
155
156   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(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());
161   }
162 }
163
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}
187   };
188
189   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(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);
200   }
201 }
202
203 TEST(JtlParser, ParsingEmpty) {
204   const char kSourceCode[] = "";
205
206   scoped_ptr<JtlParser> parser(CreateParserFromVerboseText(kSourceCode));
207   EXPECT_TRUE(parser->HasFinished());
208 }
209
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}
226   };
227
228   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(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());
237   }
238 }
239
240 TEST(JtlParser, ParsingMultipleWellFormedOperations) {
241   const char kSourceCode[] =
242       "foo1(true).foo2.foo3(\"bar\");"
243       "foo4(\"bar\", false);";
244
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());
251 }
252
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},
268   };
269
270   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(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());
281   }
282 }
283
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"}
306   };
307
308   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(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);
313   }
314 }
315
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"}
335   };
336
337   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(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);
343   }
344 }
345
346 }  // namespace