OLD | NEW |
---|---|
(Empty) | |
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 <string> | |
8 | |
9 #include "base/json/json_writer.h" | |
10 #include "base/memory/scoped_ptr.h" | |
11 #include "base/values.h" | |
12 #include "testing/gmock/include/gmock/gmock-matchers.h" | |
13 #include "testing/gtest/include/gtest/gtest.h" | |
14 | |
15 namespace { | |
16 | |
17 // Helpers ------------------------------------------------------------------- | |
18 | |
19 void ExpectNextOperation(JtlParser* parser, | |
20 const char* expected_name, | |
21 const char* expected_args, | |
22 bool expected_ends_sentence) { | |
23 std::string actual_name; | |
24 base::ListValue actual_args; | |
25 std::string actual_args_json; | |
26 bool actual_ends_sentence; | |
27 | |
28 EXPECT_TRUE(parser->HasNextOperation()); | |
29 EXPECT_TRUE(parser->ParseNextOperation( | |
30 &actual_name, &actual_args, &actual_ends_sentence)); | |
31 EXPECT_EQ(expected_name, actual_name); | |
32 base::JSONWriter::Write(&actual_args, &actual_args_json); | |
33 EXPECT_EQ(expected_args, actual_args_json); | |
34 EXPECT_EQ(expected_ends_sentence, actual_ends_sentence); | |
35 } | |
36 | |
37 void ExpectNextOperationToFail(JtlParser* parser, | |
38 size_t expected_line_number, | |
39 const char* expected_context_prefix) { | |
40 std::string actual_name; | |
41 base::ListValue actual_args; | |
42 bool actual_ends_sentence; | |
43 | |
44 EXPECT_TRUE(parser->HasNextOperation()); | |
45 EXPECT_FALSE(parser->ParseNextOperation( | |
46 &actual_name, &actual_args, &actual_ends_sentence)); | |
47 EXPECT_THAT(parser->last_context(), | |
48 testing::StartsWith(expected_context_prefix)); | |
49 EXPECT_EQ(expected_line_number, parser->last_line_number()); | |
50 } | |
51 | |
52 // Tests --------------------------------------------------------------------- | |
53 | |
54 TEST(JtlParser, CompactingEmpty) { | |
55 const char kSourceCode[] = ""; | |
56 const char kCompactedSourceCode[] = ""; | |
57 | |
58 scoped_ptr<JtlParser> parser(JtlParser::Create(kSourceCode)); | |
59 EXPECT_EQ(kCompactedSourceCode, parser->compacted_source()); | |
60 } | |
61 | |
62 TEST(JtlParser, CompactingTrivial) { | |
63 const char kSourceCode[] = "foo"; | |
64 const char kCompactedSourceCode[] = "foo"; | |
65 | |
66 scoped_ptr<JtlParser> parser(JtlParser::Create(kSourceCode)); | |
67 EXPECT_EQ(kCompactedSourceCode, parser->compacted_source()); | |
68 } | |
69 | |
70 TEST(JtlParser, CompactingOneLine) { | |
71 const char kSourceCode[] = " \r f\to o ( true ) "; | |
72 const char kCompactedSourceCode[] = "foo(true)"; | |
73 | |
74 scoped_ptr<JtlParser> parser(JtlParser::Create(kSourceCode)); | |
75 EXPECT_EQ(kCompactedSourceCode, parser->compacted_source()); | |
76 for (size_t i = 0; i < arraysize(kCompactedSourceCode) - 1; ++i) { | |
77 SCOPED_TRACE(testing::Message("Position ") << i); | |
78 EXPECT_EQ(0u, parser->GetOriginalLineNumber(i)); | |
79 } | |
80 } | |
81 | |
82 TEST(JtlParser, CompactingMultipleLines) { | |
83 const char kSourceCode[] = "a\nbb\n \nccc \n\n d( \n e \n )"; | |
84 const char kCompactedSourceCode[] = "abbcccd(e)"; | |
85 const size_t kLineNumbers[] = {0u, 1u, 1u, 3u, 3u, 3u, 5u, 5u, 6u, 7u}; | |
86 COMPILE_ASSERT(arraysize(kCompactedSourceCode) == arraysize(kLineNumbers) + 1, | |
87 mismatched_test_data); | |
88 | |
89 scoped_ptr<JtlParser> parser(JtlParser::Create(kSourceCode)); | |
90 EXPECT_EQ(kCompactedSourceCode, parser->compacted_source()); | |
91 for (size_t i = 0; i < arraysize(kLineNumbers); ++i) { | |
92 SCOPED_TRACE(testing::Message("Position ") << i); | |
93 EXPECT_EQ(kLineNumbers[i], parser->GetOriginalLineNumber(i)); | |
94 } | |
95 } | |
96 | |
97 TEST(JtlParser, HandlingCommentsAndStringLiterals) { | |
98 struct TestCase { | |
99 const char* source_code; | |
100 const char* compacted_source_code; | |
101 } cases[] = { | |
102 {"//", ""}, | |
103 {"//comment", ""}, | |
104 {"foo //comment", "foo"}, | |
105 {"\"\"", "\"\""}, | |
106 {"\"\" // comment", "\"\""}, | |
107 {"\"literal\" // comment", "\"literal\""}, | |
108 {"\"literal\" \"literal\" // comment", "\"literal\"\"literal\""}, | |
109 {"foo // \"not a literal\"", "foo"}, | |
110 {"foo // \"not even matched", "foo"}, | |
111 {"foo // \"not a literal\" \"not even matched", "foo"}, | |
112 {"\"literal\" // \"not a literal\"", "\"literal\""}, | |
113 {"\"literal\" // \"not even matched", "\"literal\""}, | |
114 {"\"//not a comment//\"", "\"//notacomment//\""}, | |
battre
2013/09/27 15:00:01
This looks incorrect. You strip whitespaces in lit
engedy
2013/10/01 10:48:41
This is done as well.
| |
115 {"\"//not a comment//\" // comment", "\"//notacomment//\""}, | |
116 {"// \"//not a literal//\" // comment", ""}, | |
117 {"\"mistmachedliteral // comment", "\"mistmachedliteral"}, | |
118 {"\"literal // \"not a literal\"", "\"literal//\"notaliteral\""}, }; | |
battre
2013/09/27 15:00:01
Please add
"\"//literal\" \"//literal\""
engedy
2013/10/01 10:48:10
This is already done 3 lines above.
| |
119 | |
120 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) { | |
121 SCOPED_TRACE(cases[i].source_code); | |
122 scoped_ptr<JtlParser> parser(JtlParser::Create(cases[i].source_code)); | |
123 EXPECT_EQ(cases[i].compacted_source_code, parser->compacted_source()); | |
124 } | |
125 } | |
126 | |
127 TEST(JtlParser, CompactingOneLinesWithComments) { | |
128 const char kSourceCode[] = | |
129 "a/ /b//Comment \n//\n// Full line comment\n cd //"; | |
130 const char kCompactedSourceCode[] = "a//bcd"; | |
131 const size_t kLineNumbers[] = {0u, 0u, 0u, 0u, 3u, 3u}; | |
132 COMPILE_ASSERT(arraysize(kCompactedSourceCode) == arraysize(kLineNumbers) + 1, | |
133 mismatched_test_data); | |
134 | |
135 scoped_ptr<JtlParser> parser(JtlParser::Create(kSourceCode)); | |
136 EXPECT_EQ(kCompactedSourceCode, parser->compacted_source()); | |
137 for (size_t i = 0; i < arraysize(kLineNumbers); ++i) { | |
138 SCOPED_TRACE(testing::Message("Position ") << i); | |
139 EXPECT_EQ(kLineNumbers[i], parser->GetOriginalLineNumber(i)); | |
140 } | |
141 } | |
142 | |
143 TEST(JtlParser, ParsingEmpty) { | |
144 const char kSourceCode[] = ""; | |
145 | |
146 scoped_ptr<JtlParser> parser(JtlParser::Create(kSourceCode)); | |
147 EXPECT_FALSE(parser->HasNextOperation()); | |
148 } | |
149 | |
150 TEST(JtlParser, ParsingOneWellFormedOperation) { | |
151 struct TestCase { | |
152 const char* source_code; | |
153 const char* expected_name; | |
154 const char* expected_args; | |
155 const bool expected_ends_sentence; | |
156 } cases[] = { | |
157 {"foo1;", "foo1", "[]", true}, | |
158 {"foo2()/", "foo2", "[]", false}, | |
159 {"foo3(true);", "foo3", "[true]", true}, | |
160 {"foo4(false)/", "foo4", "[false]", false}, | |
161 {"foo5(\"bar\")/", "foo5", "[\"bar\"]", false}, | |
162 {"foo6(true, \"bar\")/", "foo6", "[true,\"bar\"]", false}, | |
163 {"foo7(\"bar\", false, true);", "foo7", "[\"bar\",false,true]", true} | |
164 }; | |
165 | |
166 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) { | |
167 SCOPED_TRACE(cases[i].expected_name); | |
168 scoped_ptr<JtlParser> parser(JtlParser::Create(cases[i].source_code)); | |
169 ExpectNextOperation(parser.get(), | |
170 cases[i].expected_name, | |
171 cases[i].expected_args, | |
172 cases[i].expected_ends_sentence); | |
173 EXPECT_FALSE(parser->HasNextOperation()); | |
174 } | |
175 } | |
176 | |
177 TEST(JtlParser, ParsingMultipleWellFormedOperations) { | |
178 const char kSourceCode[] = | |
179 "foo1(true)/foo2/foo3(\"bar\");" | |
180 "foo4(\"bar\", false);"; | |
181 | |
182 scoped_ptr<JtlParser> parser(JtlParser::Create(kSourceCode)); | |
183 ExpectNextOperation(parser.get(), "foo1", "[true]", false); | |
184 ExpectNextOperation(parser.get(), "foo2", "[]", false); | |
185 ExpectNextOperation(parser.get(), "foo3", "[\"bar\"]", true); | |
186 ExpectNextOperation(parser.get(), "foo4", "[\"bar\",false]", true); | |
187 EXPECT_FALSE(parser->HasNextOperation()); | |
188 } | |
189 | |
190 TEST(JtlParser, ParsingTrickyStringLiterals) { | |
191 struct TestCase { | |
192 const char* source_code; | |
193 const char* expected_name; | |
194 const char* expected_args; | |
195 const bool expected_ends_sentence; | |
196 } cases[] = { | |
197 {"prev()/foo1(\"\");next(true);", "foo1", "[\"\"]", true}, | |
198 {"prev()/foo2(\",\",true);next(true);", "foo2", "[\",\",true]", true}, | |
199 {"prev()/foo3(\")\",true);next(true);", "foo3", "[\")\",true]", true}, | |
200 {"prev()/foo4(\";\",true);next(true);", "foo4", "[\";\",true]", true}, | |
201 {"prev()/foo5(\"/\",true)/next(true);", "foo5", "[\"/\",true]", false}, | |
202 {"prev()/foo6(\"//\",true)/next(true);", "foo6", "[\"//\",true]", false}, | |
203 }; | |
204 | |
205 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) { | |
206 SCOPED_TRACE(cases[i].expected_name); | |
207 scoped_ptr<JtlParser> parser(JtlParser::Create(cases[i].source_code)); | |
208 ExpectNextOperation(parser.get(), "prev", "[]", false); | |
209 ExpectNextOperation(parser.get(), | |
210 cases[i].expected_name, | |
211 cases[i].expected_args, | |
212 cases[i].expected_ends_sentence); | |
213 ExpectNextOperation(parser.get(), "next", "[true]", true); | |
214 EXPECT_FALSE(parser->HasNextOperation()); | |
215 } | |
216 } | |
217 | |
218 TEST(JtlParser, FirstOperationIsIllFormed) { | |
battre
2013/09/27 15:00:01
Add a test for parsing program ";;"?
engedy
2013/10/01 10:48:10
Done.
| |
219 struct TestCase { | |
220 const char* source_code; | |
221 const char* operation_name; | |
222 } cases[] = { | |
223 {"bad_args1(not a boolean value);", "bad_args1"}, | |
224 {"bad_args2(,);", "bad_args2"}, | |
225 {"bad_args3(...);", "bad_args3"}, | |
226 {"bad_args4(1);", "bad_args4"}, | |
227 {"bad_args5(1.2);", "bad_args5"}, | |
228 {"bad_args6([\"bar\"]);", "bad_args6"}, | |
229 {"bad_args7(False);", "bad_args7"}, | |
230 {"bad_args8(True);", "bad_args8"}, | |
231 {"bad_quotes1(\"missing, true)/good();", "bad_quotes1"}, | |
232 {"bad_quotes2(\", true)/good();", "bad_quotes2"}, | |
233 {"bad_missing_separator1", "bad_missing_separator1"}, | |
234 {"bad_missing_separator2()good();", "bad_missing_separator2"}, | |
235 {"bad_parenthesis1(true/good();", "bad_parenthesis1"}, | |
236 {"bad_parenthesis2(true/good());", "bad_parenthesis2"}, | |
237 {"bad_parenthesis3)/good();", "bad_parenthesis3"} | |
238 }; | |
239 | |
240 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) { | |
241 SCOPED_TRACE(cases[i].operation_name); | |
242 scoped_ptr<JtlParser> parser(JtlParser::Create(cases[i].source_code)); | |
243 ExpectNextOperationToFail(parser.get(), 0, cases[i].operation_name); | |
244 } | |
245 } | |
246 | |
247 TEST(JtlParser, SecondOperationIsIllFormed) { | |
248 struct TestCase { | |
249 const char* source_code; | |
250 const char* bad_operation_name; | |
251 } cases[] = { | |
252 {"\ngood(true,false)\n/bad_args(,);", "bad_args"}, | |
253 {"\ngood(true,false)\n/bad_quotes1(bar\", true)/good();", "bad_quotes1"}, | |
254 {"\ngood(true,false)\n/bad_quotes2(\", true)/good();", "bad_quotes2"}, | |
255 {"\ngood(true,false)\n/missing_separator1", "missing_separator1"}, | |
256 {"\ngood(true,false)\n/missing_separator2()good()", "missing_separator2"}, | |
257 {"\ngood(true,false)\n/bad_parens1(true/good();", "bad_parens1"}, | |
258 {"\ngood(true,false)\n/bad_parens2(true/good());", "bad_parens2"}, | |
259 {"\ngood(true,false)\n/bad_parens3)/good();", "bad_parens3"} | |
260 }; | |
261 | |
262 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) { | |
263 SCOPED_TRACE(cases[i].bad_operation_name); | |
264 scoped_ptr<JtlParser> parser(JtlParser::Create(cases[i].source_code)); | |
265 ExpectNextOperation(parser.get(), "good", "[true,false]", false); | |
266 ExpectNextOperationToFail(parser.get(), 2, cases[i].bad_operation_name); | |
267 } | |
268 } | |
269 | |
270 } // namespace | |
OLD | NEW |