Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: runtime/vm/source_report_test.cc

Issue 1533653003: Add SourceReport, a class for generating Dart source-level reports. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: tweaks Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 #include "vm/source_report.h"
6 #include "vm/dart_api_impl.h"
7 #include "vm/unit_test.h"
8
9 namespace dart {
10
11 static RawObject* ExecuteScript(const char* script) {
12 Dart_Handle h_lib = TestCase::LoadTestScript(script, NULL);
13 EXPECT_VALID(h_lib);
14 Library& lib = Library::Handle();
15 lib ^= Api::UnwrapHandle(h_lib);
16 EXPECT(!lib.IsNull());
17 Dart_Handle result = Dart_Invoke(h_lib, NewString("main"), 0, NULL);
18 EXPECT_VALID(result);
19 return Api::UnwrapHandle(h_lib);
20 }
21
22
23 TEST_CASE(SourceReport_Coverage_NoCalls) {
24 char buffer[1024];
25 const char* kScript =
26 "main() {\n"
27 "}";
28
29 Library& lib = Library::Handle();
30 lib ^= ExecuteScript(kScript);
31 ASSERT(!lib.IsNull());
32 const Script& script = Script::Handle(lib.LookupScript(
33 String::Handle(String::New("test-lib"))));
34
35 SourceReport report(SourceReport::kCoverage);
36 JSONStream js;
37 report.PrintJSONForScript(&js, script);
38 ElideJSONSubstring("libraries", js.ToCString(), buffer);
39 EXPECT_STREQ(
40 "{\"type\":\"SourceReport\",\"ranges\":"
41
42 // One compiled range, no hits or misses.
43 "[{\"scriptIndex\":0,\"startPos\":0,\"endPos\":5,\"compiled\":true,"
44 "\"coverage\":{\"hits\":[],\"misses\":[]}}],"
45
46 // One script in the script table.
47 "\"scripts\":[{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
48 "\"uri\":\"test-lib\",\"_kind\":\"script\"}]}",
49 buffer);
50 }
51
52
53 TEST_CASE(SourceReport_Coverage_SimpleCall) {
54 char buffer[1024];
55 const char* kScript =
56 "helper0() {}\n"
57 "helper1() {}\n"
58 "main() {\n"
59 " if (true) {\n"
60 " helper0();\n"
61 " } else {\n"
62 " helper1();\n"
63 " }\n"
64 "}";
65
66 Library& lib = Library::Handle();
67 lib ^= ExecuteScript(kScript);
68 ASSERT(!lib.IsNull());
69 const Script& script = Script::Handle(lib.LookupScript(
70 String::Handle(String::New("test-lib"))));
71
72 SourceReport report(SourceReport::kCoverage);
73 JSONStream js;
74 report.PrintJSONForScript(&js, script);
75 ElideJSONSubstring("classes", js.ToCString(), buffer);
76 ElideJSONSubstring("libraries", buffer, buffer);
77 EXPECT_STREQ(
78 "{\"type\":\"SourceReport\",\"ranges\":["
79
80 // One range compiled with no hits or misses (helper0).
81 "{\"scriptIndex\":0,\"startPos\":0,\"endPos\":4,\"compiled\":true,"
82 "\"coverage\":{\"hits\":[],\"misses\":[]}},"
83
84 // One range not compiled (helper1).
85 "{\"scriptIndex\":0,\"startPos\":6,\"endPos\":10,\"compiled\":false},"
86
87 // One range with a hit and a miss (main).
88 "{\"scriptIndex\":0,\"startPos\":12,\"endPos\":39,\"compiled\":true,"
89 "\"coverage\":{\"hits\":[23],\"misses\":[32]}}],"
90
91 // Only one script in the script table.
92 "\"scripts\":[{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
93 "\"uri\":\"test-lib\",\"_kind\":\"script\"}]}",
94 buffer);
95 }
96
97
98 TEST_CASE(SourceReport_Coverage_ForceCompile) {
99 char buffer[1024];
100 const char* kScript =
101 "helper0() {}\n"
102 "helper1() {}\n"
103 "main() {\n"
104 " if (true) {\n"
105 " helper0();\n"
106 " } else {\n"
107 " helper1();\n"
108 " }\n"
109 "}";
110
111 Library& lib = Library::Handle();
112 lib ^= ExecuteScript(kScript);
113 ASSERT(!lib.IsNull());
114 const Script& script = Script::Handle(lib.LookupScript(
115 String::Handle(String::New("test-lib"))));
116
117 SourceReport report(SourceReport::kCoverage, SourceReport::kForceCompile);
118 JSONStream js;
119 report.PrintJSONForScript(&js, script);
120 ElideJSONSubstring("classes", js.ToCString(), buffer);
121 ElideJSONSubstring("libraries", buffer, buffer);
122 EXPECT_STREQ(
123 "{\"type\":\"SourceReport\",\"ranges\":["
124
125 // One range compiled with no hits or misses (helper0).
126 "{\"scriptIndex\":0,\"startPos\":0,\"endPos\":4,\"compiled\":true,"
127 "\"coverage\":{\"hits\":[],\"misses\":[]}},"
128
129 // This range is compiled even though it wasn't called (helper1).
130 "{\"scriptIndex\":0,\"startPos\":6,\"endPos\":10,\"compiled\":true,"
131 "\"coverage\":{\"hits\":[],\"misses\":[]}},"
132
133 // One range with a hit and a miss (main).
134 "{\"scriptIndex\":0,\"startPos\":12,\"endPos\":39,\"compiled\":true,"
135 "\"coverage\":{\"hits\":[23],\"misses\":[32]}}],"
136
137 // Only one script in the script table.
138 "\"scripts\":[{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
139 "\"uri\":\"test-lib\",\"_kind\":\"script\"}]}",
140 buffer);
141 }
142
143
144 TEST_CASE(SourceReport_Coverage_NestedFunctions) {
145 char buffer[1024];
146 const char* kScript =
147 "helper0() {\n"
148 " nestedHelper0() {}\n"
149 " nestedHelper1() {}\n"
150 " nestedHelper0();\n"
151 "}\n"
152 "helper1() {}\n"
153 "main() {\n"
154 " if (true) {\n"
155 " helper0();\n"
156 " } else {\n"
157 " helper1();\n"
158 " }\n"
159 "}";
160
161 Library& lib = Library::Handle();
162 lib ^= ExecuteScript(kScript);
163 ASSERT(!lib.IsNull());
164 const Script& script = Script::Handle(lib.LookupScript(
165 String::Handle(String::New("test-lib"))));
166
167 SourceReport report(SourceReport::kCoverage);
168 JSONStream js;
169 report.PrintJSONForScript(&js, script);
170 ElideJSONSubstring("classes", js.ToCString(), buffer);
171 ElideJSONSubstring("libraries", buffer, buffer);
172 EXPECT_STREQ(
173 "{\"type\":\"SourceReport\",\"ranges\":["
174
175 // One range compiled with one hit (helper0).
176 "{\"scriptIndex\":0,\"startPos\":0,\"endPos\":22,\"compiled\":true,"
177 "\"coverage\":{\"hits\":[18],\"misses\":[]}},"
178
179 // One range not compiled (helper1).
180 "{\"scriptIndex\":0,\"startPos\":24,\"endPos\":28,\"compiled\":false},"
181
182 // One range with a hit and a miss (main).
183 "{\"scriptIndex\":0,\"startPos\":30,\"endPos\":57,\"compiled\":true,"
184 "\"coverage\":{\"hits\":[41],\"misses\":[50]}},"
185
186 // Nested range compiled (nestedHelper0).
187 "{\"scriptIndex\":0,\"startPos\":5,\"endPos\":9,\"compiled\":true,"
188 "\"coverage\":{\"hits\":[],\"misses\":[]}},"
189
190 // Nested range not compiled (nestedHelper1).
191 "{\"scriptIndex\":0,\"startPos\":11,\"endPos\":15,\"compiled\":false}],"
192
193 // Only one script in the script table.
194 "\"scripts\":[{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
195 "\"uri\":\"test-lib\",\"_kind\":\"script\"}]}",
196 buffer);
197 }
198
199
200 TEST_CASE(SourceReport_Coverage_RestrictedRange) {
201 char buffer[1024];
202 const char* kScript =
203 "helper0() {\n"
204 " nestedHelper0() {}\n"
205 " nestedHelper1() {}\n"
206 " nestedHelper0();\n"
207 "}\n"
208 "helper1() {}\n"
209 "main() {\n"
210 " if (true) {\n"
211 " helper0();\n"
212 " } else {\n"
213 " helper1();\n"
214 " }\n"
215 "}";
216
217 Library& lib = Library::Handle();
218 lib ^= ExecuteScript(kScript);
219 ASSERT(!lib.IsNull());
220 const Script& script = Script::Handle(lib.LookupScript(
221 String::Handle(String::New("test-lib"))));
222 const Function& helper = Function::Handle(
223 lib.LookupLocalFunction(String::Handle(String::New("helper0"))));
224
225 SourceReport report(SourceReport::kCoverage);
226 JSONStream js;
227 // Restrict the report to only helper0 and it's nested functions.
228 report.PrintJSONForScript(&js, script,
229 helper.token_pos(), helper.end_token_pos());
230 ElideJSONSubstring("classes", js.ToCString(), buffer);
231 ElideJSONSubstring("libraries", buffer, buffer);
232 EXPECT_STREQ(
233 "{\"type\":\"SourceReport\",\"ranges\":["
234
235 // One range compiled with one hit (helper0).
236 "{\"scriptIndex\":0,\"startPos\":0,\"endPos\":22,\"compiled\":true,"
237 "\"coverage\":{\"hits\":[18],\"misses\":[]}},"
238
239 // Nested range compiled (nestedHelper0).
240 "{\"scriptIndex\":0,\"startPos\":5,\"endPos\":9,\"compiled\":true,"
241 "\"coverage\":{\"hits\":[],\"misses\":[]}},"
242
243 // Nested range not compiled (nestedHelper1).
244 "{\"scriptIndex\":0,\"startPos\":11,\"endPos\":15,\"compiled\":false}],"
245
246 // Only one script in the script table.
247 "\"scripts\":[{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
248 "\"uri\":\"test-lib\",\"_kind\":\"script\"}]}",
249 buffer);
250 }
251
252
253 TEST_CASE(SourceReport_Coverage_AllFunctions) {
254 const char* kScript =
255 "helper0() {}\n"
256 "helper1() {}\n"
257 "main() {\n"
258 " if (true) {\n"
259 " helper0();\n"
260 " } else {\n"
261 " helper1();\n"
262 " }\n"
263 "}";
264
265 Library& lib = Library::Handle();
266 lib ^= ExecuteScript(kScript);
267 ASSERT(!lib.IsNull());
268
269 SourceReport report(SourceReport::kCoverage);
270 JSONStream js;
271
272 // We generate a report with all functions in the VM.
273 report.PrintJSON(&js);
274 const char* result = js.ToCString();
275
276 // Sanity check the header.
277 EXPECT_SUBSTRING("{\"type\":\"SourceReport\",\"ranges\":[", result);
278
279 // Make sure that the main function was found.
280 EXPECT_SUBSTRING(
281 "\"startPos\":12,\"endPos\":39,\"compiled\":true,"
282 "\"coverage\":{\"hits\":[23],\"misses\":[32]}",
283 result);
284
285 // More than one script is referenced in the report.
286 EXPECT_SUBSTRING("\"scriptIndex\":0", result);
287 EXPECT_SUBSTRING("\"scriptIndex\":1", result);
288 EXPECT_SUBSTRING("\"scriptIndex\":2", result);
289 }
290
291
292 TEST_CASE(SourceReport_CallSites_SimpleCall) {
293 char buffer[1024];
294 const char* kScript =
295 "helper0() {}\n"
296 "helper1() {}\n"
297 "main() {\n"
298 " helper0();\n"
299 "}";
300
301 Library& lib = Library::Handle();
302 lib ^= ExecuteScript(kScript);
303 ASSERT(!lib.IsNull());
304 const Script& script = Script::Handle(lib.LookupScript(
305 String::Handle(String::New("test-lib"))));
306
307 SourceReport report(SourceReport::kCallSites);
308 JSONStream js;
309 report.PrintJSONForScript(&js, script);
310 ElideJSONSubstring("classes", js.ToCString(), buffer);
311 ElideJSONSubstring("libraries", buffer, buffer);
312 EXPECT_STREQ(
313 "{\"type\":\"SourceReport\",\"ranges\":["
314
315 // One range compiled with no callsites (helper0).
316 "{\"scriptIndex\":0,\"startPos\":0,\"endPos\":4,\"compiled\":true,"
317 "\"callSites\":[]},"
318
319 // One range not compiled (helper1).
320 "{\"scriptIndex\":0,\"startPos\":6,\"endPos\":10,\"compiled\":false},"
321
322 // One range compiled with one callsite (main).
323 "{\"scriptIndex\":0,\"startPos\":12,\"endPos\":22,\"compiled\":true,"
324 "\"callSites\":["
325 "{\"name\":\"helper0\",\"tokenPos\":17,\"cacheEntries\":["
326 "{\"target\":{\"type\":\"@Function\",\"fixedId\":true,\"id\":\"\","
327 "\"name\":\"helper0\",\"owner\":{\"type\":\"@Library\",\"fixedId\":true,"
328 "\"id\":\"\",\"name\":\"\",\"uri\":\"test-lib\"},"
329 "\"_kind\":\"RegularFunction\",\"static\":true,\"const\":false,"
330 "\"_intrinsic\":false,\"_native\":false},\"count\":1}]}]}],"
331
332 // One script in the script table.
333 "\"scripts\":[{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
334 "\"uri\":\"test-lib\",\"_kind\":\"script\"}]}",
335 buffer);
336 }
337
338 TEST_CASE(SourceReport_CallSites_PolymorphicCall) {
339 char buffer[1024];
340 const char* kScript =
341 "class Common {\n"
342 " func() {}\n"
343 "}\n"
344 "class Uncommon {\n"
345 " func() {}\n"
346 "}\n"
347 "helper(arg) {\n"
348 " arg.func();\n"
349 "}\n"
350 "main() {\n"
351 " Common common = new Common();\n"
352 " Uncommon uncommon = new Uncommon();\n"
353 " helper(common);\n"
354 " helper(common);\n"
355 " helper(uncommon);\n"
356 "}";
357
358 Library& lib = Library::Handle();
359 lib ^= ExecuteScript(kScript);
360 ASSERT(!lib.IsNull());
361 const Script& script = Script::Handle(lib.LookupScript(
362 String::Handle(String::New("test-lib"))));
363 const Function& helper = Function::Handle(
364 lib.LookupLocalFunction(String::Handle(String::New("helper"))));
365
366 SourceReport report(SourceReport::kCallSites);
367 JSONStream js;
368 report.PrintJSONForScript(&js, script,
369 helper.token_pos(), helper.end_token_pos());
370 ElideJSONSubstring("classes", js.ToCString(), buffer);
371 ElideJSONSubstring("libraries", buffer, buffer);
372 EXPECT_STREQ(
373 "{\"type\":\"SourceReport\",\"ranges\":["
374
375 // One range...
376 "{\"scriptIndex\":0,\"startPos\":24,\"endPos\":37,\"compiled\":true,"
377
378 // With one call site...
379 "\"callSites\":[{\"name\":\"func\",\"tokenPos\":32,\"cacheEntries\":["
380
381 // First receiver: "Common", called twice.
382 "{\"receiver\":{\"type\":\"@Class\",\"fixedId\":true,\"id\":\"\","
383 "\"name\":\"Common\"},"
384
385 "\"target\":{\"type\":\"@Function\",\"fixedId\":true,\"id\":\"\","
386 "\"name\":\"func\","
387 "\"owner\":{\"type\":\"@Class\",\"fixedId\":true,\"id\":\"\","
388 "\"name\":\"Common\"},\"_kind\":\"RegularFunction\","
389 "\"static\":false,\"const\":false,\"_intrinsic\":false,"
390 "\"_native\":false},"
391
392 "\"count\":2},"
393
394 // Second receiver: "Uncommon", called once.
395 "{\"receiver\":{\"type\":\"@Class\",\"fixedId\":true,\"id\":\"\","
396 "\"name\":\"Uncommon\"},"
397
398 "\"target\":{\"type\":\"@Function\",\"fixedId\":true,\"id\":\"\","
399 "\"name\":\"func\","
400 "\"owner\":{\"type\":\"@Class\",\"fixedId\":true,\"id\":\"\","
401 "\"name\":\"Uncommon\"},\"_kind\":\"RegularFunction\","
402 "\"static\":false,\"const\":false,\"_intrinsic\":false,"
403 "\"_native\":false},"
404
405 "\"count\":1}]}]}],"
406
407 // One script in the script table.
408 "\"scripts\":[{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
409 "\"uri\":\"test-lib\",\"_kind\":\"script\"}]}",
410 buffer);
411 }
412
413 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698