Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
source_report_test.cc
Go to the documentation of this file.
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
9namespace dart {
10
11#ifndef PRODUCT
12
13static ObjectPtr ExecuteScript(const char* script, bool allow_errors = false) {
14 Dart_Handle lib;
15 {
17 if (allow_errors) {
18 lib = TestCase::LoadTestScriptWithErrors(script, nullptr);
19 } else {
20 lib = TestCase::LoadTestScript(script, nullptr);
21 }
22 EXPECT_VALID(lib);
23 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
25 }
26 return Api::UnwrapHandle(lib);
27}
28
29ISOLATE_UNIT_TEST_CASE(SourceReport_Coverage_NoCalls) {
30 // WARNING: This MUST be big enough for the serialized JSON string.
31 const int kBufferSize = 1024;
32 char buffer[kBufferSize];
33 const char* kScript =
34 "main() {\n"
35 "}";
36
37 Library& lib = Library::Handle();
38 lib ^= ExecuteScript(kScript);
39 ASSERT(!lib.IsNull());
40 const Script& script =
43 JSONStream js;
44 report.PrintJSON(&js, script);
45 const char* json_str = js.ToCString();
46 ASSERT(strlen(json_str) < kBufferSize);
47 ElideJSONSubstring("libraries", json_str, buffer);
48 EXPECT_STREQ(
49 "{\"type\":\"SourceReport\",\"ranges\":"
50
51 // One compiled range, one hit at function declaration.
52 "[{\"scriptIndex\":0,\"startPos\":0,\"endPos\":9,\"compiled\":true,"
53 "\"coverage\":{\"hits\":[0],\"misses\":[]}}],"
54
55 // One script in the script table.
56 "\"scripts\":[{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
57 "\"uri\":\"file:\\/\\/\\/test-lib\",\"_kind\":\"kernel\"}]}",
58 buffer);
59}
60
61ISOLATE_UNIT_TEST_CASE(SourceReport_Coverage_Filters_single) {
62 // WARNING: This MUST be big enough for the serialized JSON string.
63 const int kBufferSize = 1024;
64 char buffer[kBufferSize];
65 const char* kScript =
66 "main() {\n"
67 "}";
68
69 Library& lib = Library::Handle();
70 lib ^= ExecuteScript(kScript);
71 ASSERT(!lib.IsNull());
72
73 GrowableObjectArray& filters =
77 JSONStream js;
79 const char* json_str = js.ToCString();
80 ASSERT(strlen(json_str) < kBufferSize);
81 ElideJSONSubstring("libraries", json_str, buffer);
82 EXPECT_STREQ(
83 "{\"type\":\"SourceReport\",\"ranges\":"
84
85 // One compiled range, one hit at function declaration.
86 "[{\"scriptIndex\":0,\"startPos\":0,\"endPos\":9,\"compiled\":true,"
87 "\"coverage\":{\"hits\":[0],\"misses\":[]}}],"
88
89 // One script in the script table.
90 "\"scripts\":[{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
91 "\"uri\":\"file:\\/\\/\\/test-lib\",\"_kind\":\"kernel\"}]}",
92 buffer);
93}
94
95ISOLATE_UNIT_TEST_CASE(SourceReport_Coverage_Filters_empty) {
96 // WARNING: This MUST be big enough for the serialized JSON string.
97 const int kBufferSize = 1024;
98 char buffer[kBufferSize];
99 const char* kScript =
100 "main() {\n"
101 "}";
102
103 Library& lib = Library::Handle();
104 lib ^= ExecuteScript(kScript);
105 ASSERT(!lib.IsNull());
106
107 GrowableObjectArray& filters =
109 filters.Add(String::Handle(String::New("foo:bar/")));
110 SourceReport report(SourceReport::kCoverage, filters);
111 JSONStream js;
112 report.PrintJSON(&js, Script::Handle(Script::null()));
113 const char* json_str = js.ToCString();
114 ASSERT(strlen(json_str) < kBufferSize);
115 ElideJSONSubstring("libraries", json_str, buffer);
116 EXPECT_STREQ(
117 "{\"type\":\"SourceReport\",\"ranges\":"
118
119 // No compiled range.
120 "[],"
121
122 // No script.
123 "\"scripts\":[]}",
124 buffer);
125}
126
127ISOLATE_UNIT_TEST_CASE(SourceReport_Coverage_SimpleCall) {
128 // WARNING: This MUST be big enough for the serialized JSON string.
129 const int kBufferSize = 1024;
130 char buffer[kBufferSize];
131 const char* kScript =
132 "helper0() {}\n"
133 "helper1() {}\n"
134 "main() {\n"
135 " if (true) {\n"
136 " helper0();\n"
137 " } else {\n"
138 " helper1();\n"
139 " }\n"
140 "}";
141
142 Library& lib = Library::Handle();
143 lib ^= ExecuteScript(kScript);
144 ASSERT(!lib.IsNull());
145 const Script& script =
147
149 JSONStream js;
150 report.PrintJSON(&js, script);
151 const char* json_str = js.ToCString();
152 ASSERT(strlen(json_str) < kBufferSize);
153 ElideJSONSubstring("classes", json_str, buffer);
154 ElideJSONSubstring("libraries", buffer, buffer);
155 EXPECT_STREQ(
156 "{\"type\":\"SourceReport\",\"ranges\":["
157
158 // One range compiled with one hit at function declaration (helper0).
159 "{\"scriptIndex\":0,\"startPos\":0,\"endPos\":11,\"compiled\":true,"
160 "\"coverage\":{\"hits\":[0],\"misses\":[]}},"
161
162 // One range not compiled (helper1).
163 "{\"scriptIndex\":0,\"startPos\":13,\"endPos\":24,\"compiled\":false},"
164
165 // One range with two hits and a miss (main).
166 "{\"scriptIndex\":0,\"startPos\":26,\"endPos\":94,\"compiled\":true,"
167 "\"coverage\":{\"hits\":[26,53],\"misses\":[79]}}],"
168
169 // Only one script in the script table.
170 "\"scripts\":[{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
171 "\"uri\":\"file:\\/\\/\\/test-lib\",\"_kind\":\"kernel\"}]}",
172 buffer);
173}
174
175ISOLATE_UNIT_TEST_CASE(SourceReport_Coverage_ForceCompile) {
176 // WARNING: This MUST be big enough for the serialized JSON string.
177 const int kBufferSize = 1024;
178 char buffer[kBufferSize];
179 const char* kScript =
180 "helper0() {}\n"
181 "helper1() {}\n"
182 "main() {\n"
183 " if (true) {\n"
184 " helper0();\n"
185 " } else {\n"
186 " helper1();\n"
187 " }\n"
188 "}";
189
190 Library& lib = Library::Handle();
191 lib ^= ExecuteScript(kScript);
192 ASSERT(!lib.IsNull());
193 const Script& script =
195
197 JSONStream js;
198 report.PrintJSON(&js, script);
199 const char* json_str = js.ToCString();
200 ASSERT(strlen(json_str) < kBufferSize);
201 ElideJSONSubstring("classes", json_str, buffer);
202 ElideJSONSubstring("libraries", buffer, buffer);
203
204 EXPECT_STREQ(
205 "{\"type\":\"SourceReport\",\"ranges\":["
206
207 // One range compiled with one hit at function declaration (helper0).
208 "{\"scriptIndex\":0,\"startPos\":0,\"endPos\":11,\"compiled\":true,"
209 "\"coverage\":{\"hits\":[0],\"misses\":[]}},"
210
211 // This range is compiled even though it wasn't called (helper1).
212 "{\"scriptIndex\":0,\"startPos\":13,\"endPos\":24,\"compiled\":true,"
213 "\"coverage\":{\"hits\":[],\"misses\":[13]}},"
214
215 // One range with two hits and a miss (main).
216 "{\"scriptIndex\":0,\"startPos\":26,\"endPos\":94,\"compiled\":true,"
217 "\"coverage\":{\"hits\":[26,53],\"misses\":[79]}}],"
218
219 // Only one script in the script table.
220 "\"scripts\":[{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
221 "\"uri\":\"file:\\/\\/\\/test-lib\",\"_kind\":\"kernel\"}]}",
222 buffer);
223}
224
225ISOLATE_UNIT_TEST_CASE(SourceReport_Coverage_UnusedClass_NoForceCompile) {
226 // WARNING: This MUST be big enough for the serialized JSON string.
227 const int kBufferSize = 1024;
228 char buffer[kBufferSize];
229 const char* kScript =
230 "helper0() {}\n"
231 "class Unused {\n"
232 " helper1() { helper0(); }\n"
233 "}\n"
234 "main() {\n"
235 " helper0();\n"
236 "}";
237
238 Library& lib = Library::Handle();
239 lib ^= ExecuteScript(kScript);
240 ASSERT(!lib.IsNull());
241 const Script& script =
243
245 JSONStream js;
246 report.PrintJSON(&js, script);
247 const char* json_str = js.ToCString();
248 ASSERT(strlen(json_str) < kBufferSize);
249 ElideJSONSubstring("classes", json_str, buffer);
250 ElideJSONSubstring("libraries", buffer, buffer);
251 EXPECT_STREQ(
252 "{\"type\":\"SourceReport\",\"ranges\":["
253
254 // UnusedClass is not compiled.
255 "{\"scriptIndex\":0,\"startPos\":13,\"endPos\":55,\"compiled\":false},"
256
257 // helper0 is compiled.
258 "{\"scriptIndex\":0,\"startPos\":0,\"endPos\":11,\"compiled\":true,"
259 "\"coverage\":{\"hits\":[0],\"misses\":[]}},"
260
261 // One range with two hits (main).
262 "{\"scriptIndex\":0,\"startPos\":57,\"endPos\":79,\"compiled\":true,"
263 "\"coverage\":{\"hits\":[57,68],\"misses\":[]}}],"
264
265 // Only one script in the script table.
266 "\"scripts\":[{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
267 "\"uri\":\"file:\\/\\/\\/test-lib\",\"_kind\":\"kernel\"}]}",
268 buffer);
269}
270
271ISOLATE_UNIT_TEST_CASE(SourceReport_Coverage_UnusedClass_ForceCompile) {
272 // WARNING: This MUST be big enough for the serialized JSON string.
273 const int kBufferSize = 1024;
274 char buffer[kBufferSize];
275 const char* kScript =
276 "helper0() {}\n"
277 "class Unused {\n"
278 " helper1() { helper0(); }\n"
279 "}\n"
280 "main() {\n"
281 " helper0();\n"
282 "}";
283
284 Library& lib = Library::Handle();
285 lib ^= ExecuteScript(kScript);
286 ASSERT(!lib.IsNull());
287 const Script& script =
289
291 JSONStream js;
292 report.PrintJSON(&js, script);
293 const char* json_str = js.ToCString();
294 ASSERT(strlen(json_str) < kBufferSize);
295 ElideJSONSubstring("classes", json_str, buffer);
296 ElideJSONSubstring("libraries", buffer, buffer);
297 EXPECT_STREQ(
298 "{\"type\":\"SourceReport\",\"ranges\":["
299
300 // UnusedClass.helper1 is compiled.
301 "{\"scriptIndex\":0,\"startPos\":30,\"endPos\":53,\"compiled\":true,"
302 "\"coverage\":{\"hits\":[],\"misses\":[30,42]}},"
303
304 // helper0 is compiled.
305 "{\"scriptIndex\":0,\"startPos\":0,\"endPos\":11,\"compiled\":true,"
306 "\"coverage\":{\"hits\":[0],\"misses\":[]}},"
307
308 // One range with two hits (main).
309 "{\"scriptIndex\":0,\"startPos\":57,\"endPos\":79,\"compiled\":true,"
310 "\"coverage\":{\"hits\":[57,68],\"misses\":[]}}],"
311
312 // Only one script in the script table.
313 "\"scripts\":[{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
314 "\"uri\":\"file:\\/\\/\\/test-lib\",\"_kind\":\"kernel\"}]}",
315 buffer);
316}
317
318ISOLATE_UNIT_TEST_CASE(SourceReport_Coverage_UnusedClass_ForceCompileError) {
319 // WARNING: This MUST be big enough for the serialized JSON string.
320 const int kBufferSize = 1024;
321 char buffer[kBufferSize];
322 const char* kScript =
323 "helper0() {}\n"
324 "class Unused {\n"
325 " helper1() { helper0()+ }\n" // syntax error
326 "}\n"
327 "main() {\n"
328 " helper0();\n"
329 "}";
330
331 Library& lib = Library::Handle();
332 lib ^= ExecuteScript(kScript, true);
333 ASSERT(!lib.IsNull());
334 const Script& script =
336
338 JSONStream js;
339 report.PrintJSON(&js, script);
340 const char* json_str = js.ToCString();
341 ASSERT(strlen(json_str) < kBufferSize);
342 ElideJSONSubstring("classes", json_str, buffer);
343 ElideJSONSubstring("libraries", buffer, buffer);
344 EXPECT_STREQ(
345 "{\"type\":\"SourceReport\",\"ranges\":["
346
347 // UnusedClass has a syntax error.
348 "{\"scriptIndex\":0,\"startPos\":30,\"endPos\":53,\"compiled\":false,"
349 "\"error\":{\"type\":\"@Error\",\"_vmType\":\"LanguageError\","
350 "\"kind\":\"LanguageError\",\"id\":\"objects\\/0\","
351 "\"message\":\"'file:\\/\\/\\/test-lib': error: "
352 "\\/test-lib:3:26: "
353 "Error: This couldn't be parsed.\\n"
354 " helper1() { helper0()+ }\\n ^\"}},"
355
356 // helper0 is compiled.
357 "{\"scriptIndex\":0,\"startPos\":0,\"endPos\":11,\"compiled\":true,"
358 "\"coverage\":{\"hits\":[0],\"misses\":[]}},"
359
360 // One range with two hits (main).
361 "{\"scriptIndex\":0,\"startPos\":57,\"endPos\":79,\"compiled\":true,"
362 "\"coverage\":{\"hits\":[57,68],\"misses\":[]}}],"
363
364 // Only one script in the script table.
365 "\"scripts\":[{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
366 "\"uri\":\"file:\\/\\/\\/test-lib\",\"_kind\":\"kernel\"}]}",
367 buffer);
368}
369
370ISOLATE_UNIT_TEST_CASE(SourceReport_Coverage_LibrariesAlreadyCompiled) {
371 // WARNING: This MUST be big enough for the serialized JSON string.
372 const int kBufferSize = 1024;
373 char buffer[kBufferSize];
374 const char* kScript =
375 "helper0() {}\n"
376 "class Unused {\n"
377 " helper1() { helper0(); }\n"
378 "}\n"
379 "main() {\n"
380 " helper0();\n"
381 "}";
382
383 Library& lib = Library::Handle();
384 lib ^= ExecuteScript(kScript);
385 ASSERT(!lib.IsNull());
386 const Script& script =
388
389 Zone* zone = thread->zone();
390 ZoneCStringSet* libraries_already_compiled = new (zone) ZoneCStringSet(zone);
391 libraries_already_compiled->Insert(RESOLVED_USER_TEST_URI);
393 libraries_already_compiled, SourceReport::kForceCompile);
394 JSONStream js;
395 report.PrintJSON(&js, script);
396 const char* json_str = js.ToCString();
397 ASSERT(strlen(json_str) < kBufferSize);
398 ElideJSONSubstring("classes", json_str, buffer);
399 ElideJSONSubstring("libraries", buffer, buffer);
400 EXPECT_STREQ(
401 "{\"type\":\"SourceReport\",\"ranges\":["
402
403 // UnusedClass is not compiled.
404 "{\"scriptIndex\":0,\"startPos\":13,\"endPos\":55,\"compiled\":false},"
405
406 // helper0 is compiled.
407 "{\"scriptIndex\":0,\"startPos\":0,\"endPos\":11,\"compiled\":true,"
408 "\"coverage\":{\"hits\":[0],\"misses\":[]}},"
409
410 // One range with two hits (main).
411 "{\"scriptIndex\":0,\"startPos\":57,\"endPos\":79,\"compiled\":true,"
412 "\"coverage\":{\"hits\":[57,68],\"misses\":[]}}],"
413
414 // Only one script in the script table.
415 "\"scripts\":[{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
416 "\"uri\":\"file:\\/\\/\\/test-lib\",\"_kind\":\"kernel\"}]}",
417 buffer);
418}
419
420ISOLATE_UNIT_TEST_CASE(SourceReport_Coverage_NestedFunctions) {
421 // WARNING: This MUST be big enough for the serialized JSON string.
422 const int kBufferSize = 1024;
423 char buffer[kBufferSize];
424 const char* kScript =
425 "helper0() {\n"
426 " nestedHelper0() {}\n"
427 " nestedHelper1() {}\n"
428 " nestedHelper0();\n"
429 "}\n"
430 "helper1() {}\n"
431 "main() {\n"
432 " if (true) {\n"
433 " helper0();\n"
434 " } else {\n"
435 " helper1();\n"
436 " }\n"
437 "}";
438
439 Library& lib = Library::Handle();
440 lib ^= ExecuteScript(kScript);
441 ASSERT(!lib.IsNull());
442 const Script& script =
444
446 JSONStream js;
447 report.PrintJSON(&js, script);
448 const char* json_str = js.ToCString();
449 ASSERT(strlen(json_str) < kBufferSize);
450 ElideJSONSubstring("classes", json_str, buffer);
451 ElideJSONSubstring("libraries", buffer, buffer);
452
453 EXPECT_STREQ(
454 "{\"type\":\"SourceReport\",\"ranges\":["
455
456 // One range compiled with one hit (helper0).
457 "{\"scriptIndex\":0,\"startPos\":0,\"endPos\":73,\"compiled\":true,"
458 "\"coverage\":{\"hits\":[0,56],\"misses\":[]}},"
459
460 // One range not compiled (helper1).
461 "{\"scriptIndex\":0,\"startPos\":75,\"endPos\":86,\"compiled\":false},"
462
463 // One range with two hits and a miss (main).
464 "{\"scriptIndex\":0,\"startPos\":88,\"endPos\":156,\"compiled\":true,"
465 "\"coverage\":{\"hits\":[88,115],\"misses\":[141]}},"
466
467 // Nested range compiled (nestedHelper0).
468 "{\"scriptIndex\":0,\"startPos\":14,\"endPos\":31,\"compiled\":true,"
469 "\"coverage\":{\"hits\":[14],\"misses\":[]}},"
470
471 // Nested range not compiled (nestedHelper1).
472 "{\"scriptIndex\":0,\"startPos\":35,\"endPos\":52,\"compiled\":false}],"
473
474 // Only one script in the script table.
475 "\"scripts\":[{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
476 "\"uri\":\"file:\\/\\/\\/test-lib\",\"_kind\":\"kernel\"}]}",
477 buffer);
478}
479
480ISOLATE_UNIT_TEST_CASE(SourceReport_Coverage_RestrictedRange) {
481 // WARNING: This MUST be big enough for the serialized JSON string.
482 const int kBufferSize = 1024;
483 char buffer[kBufferSize];
484 const char* kScript =
485 "helper0() {\n"
486 " nestedHelper0() {}\n"
487 " nestedHelper1() {}\n"
488 " nestedHelper0();\n"
489 "}\n"
490 "helper1() {}\n"
491 "main() {\n"
492 " if (true) {\n"
493 " helper0();\n"
494 " } else {\n"
495 " helper1();\n"
496 " }\n"
497 "}";
498
499 Library& lib = Library::Handle();
500 lib ^= ExecuteScript(kScript);
501 ASSERT(!lib.IsNull());
502 const Script& script =
504 const Function& helper = Function::Handle(
506
508 JSONStream js;
509 // Restrict the report to only helper0 and it's nested functions.
510 report.PrintJSON(&js, script, helper.token_pos(), helper.end_token_pos());
511 const char* json_str = js.ToCString();
512 ASSERT(strlen(json_str) < kBufferSize);
513 ElideJSONSubstring("classes", json_str, buffer);
514 ElideJSONSubstring("libraries", buffer, buffer);
515
516 EXPECT_STREQ(
517 "{\"type\":\"SourceReport\",\"ranges\":["
518
519 // One range compiled with one hit (helper0).
520 "{\"scriptIndex\":0,\"startPos\":0,\"endPos\":73,\"compiled\":true,"
521 "\"coverage\":{\"hits\":[0,56],\"misses\":[]}},"
522
523 // Nested range compiled (nestedHelper0).
524 "{\"scriptIndex\":0,\"startPos\":14,\"endPos\":31,\"compiled\":true,"
525 "\"coverage\":{\"hits\":[14],\"misses\":[]}},"
526
527 // Nested range not compiled (nestedHelper1).
528 "{\"scriptIndex\":0,\"startPos\":35,\"endPos\":52,\"compiled\":false}],"
529
530 // Only one script in the script table.
531 "\"scripts\":[{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
532 "\"uri\":\"file:\\/\\/\\/test-lib\",\"_kind\":\"kernel\"}]}",
533 buffer);
534}
535
536ISOLATE_UNIT_TEST_CASE(SourceReport_Coverage_AllFunctions) {
537 const char* kScript =
538 "helper0() {}\n"
539 "helper1() {}\n"
540 "main() {\n"
541 " if (true) {\n"
542 " helper0();\n"
543 " } else {\n"
544 " helper1();\n"
545 " }\n"
546 "}";
547
548 Library& lib = Library::Handle();
549 lib ^= ExecuteScript(kScript);
550 ASSERT(!lib.IsNull());
551
553 JSONStream js;
554
555 // We generate a report with all functions in the VM.
556 Script& null_script = Script::Handle();
557 report.PrintJSON(&js, null_script);
558 const char* result = js.ToCString();
559
560 // Sanity check the header.
561 EXPECT_SUBSTRING("{\"type\":\"SourceReport\",\"ranges\":[", result);
562
563 // Make sure that the main function was found.
564 EXPECT_SUBSTRING(
565 "\"startPos\":26,\"endPos\":94,\"compiled\":true,"
566 "\"coverage\":{\"hits\":[26,53],\"misses\":[79]}",
567 result);
568
569 // More than one script is referenced in the report.
570 EXPECT_SUBSTRING("\"scriptIndex\":0", result);
571 EXPECT_SUBSTRING("\"scriptIndex\":1", result);
572 EXPECT_SUBSTRING("\"scriptIndex\":2", result);
573}
574
575ISOLATE_UNIT_TEST_CASE(SourceReport_Coverage_AllFunctions_ForceCompile) {
576 const char* kScript =
577 "helper0() {}\n"
578 "helper1() {}\n"
579 "main() {\n"
580 " if (true) {\n"
581 " helper0();\n"
582 " } else {\n"
583 " helper1();\n"
584 " }\n"
585 "}";
586
587 Library& lib = Library::Handle();
588 lib ^= ExecuteScript(kScript);
589 ASSERT(!lib.IsNull());
590
592 JSONStream js;
593
594 // We generate a report with all functions in the VM.
595 Script& null_script = Script::Handle();
596 report.PrintJSON(&js, null_script);
597 const char* result = js.ToCString();
598
599 // Sanity check the header.
600 EXPECT_SUBSTRING("{\"type\":\"SourceReport\",\"ranges\":[", result);
601
602 // Make sure that the main function was found.
603 EXPECT_SUBSTRING(
604 "\"startPos\":26,\"endPos\":94,\"compiled\":true,"
605 "\"coverage\":{\"hits\":[26,53],\"misses\":[79]}",
606 result);
607
608 // More than one script is referenced in the report.
609 EXPECT_SUBSTRING("\"scriptIndex\":0", result);
610 EXPECT_SUBSTRING("\"scriptIndex\":1", result);
611 EXPECT_SUBSTRING("\"scriptIndex\":2", result);
612}
613
614ISOLATE_UNIT_TEST_CASE(SourceReport_CallSites_SimpleCall) {
615 // WARNING: This MUST be big enough for the serialized JSON string.
616 const int kBufferSize = 2048;
617 char buffer[kBufferSize];
618 const char* kScript =
619 "helper0() {}\n"
620 "helper1() {}\n"
621 "main() {\n"
622 " helper0();\n"
623 "}";
624
625 Library& lib = Library::Handle();
626 lib ^= ExecuteScript(kScript);
627 ASSERT(!lib.IsNull());
628 const Script& script =
630
632 JSONStream js;
633 report.PrintJSON(&js, script);
634 const char* json_str = js.ToCString();
635 ASSERT(strlen(json_str) < kBufferSize);
636 ElideJSONSubstring("classes", json_str, buffer);
637 ElideJSONSubstring("libraries", buffer, buffer);
638 EXPECT_STREQ(
639 "{\"type\":\"SourceReport\",\"ranges\":["
640
641 // One range compiled with no callsites (helper0).
642 "{\"scriptIndex\":0,\"startPos\":0,\"endPos\":11,\"compiled\":true,"
643 "\"callSites\":[]},"
644
645 // One range not compiled (helper1).
646 "{\"scriptIndex\":0,\"startPos\":13,\"endPos\":24,\"compiled\":false},"
647
648 // One range compiled with one callsite (main).
649 "{\"scriptIndex\":0,\"startPos\":26,\"endPos\":48,\"compiled\":true,"
650 "\"callSites\":["
651 "{\"name\":\"helper0\",\"tokenPos\":37,\"cacheEntries\":["
652 "{\"target\":{\"type\":\"@Function\",\"fixedId\":true,\"id\":\"\","
653 "\"name\":\"helper0\",\"owner\":{\"type\":\"@Library\",\"fixedId\":true,"
654 "\"id\":\"\",\"name\":\"\",\"uri\":\"file:\\/\\/\\/test-lib\"},"
655 "\"_kind\":\"RegularFunction\",\"static\":true,\"const\":false,"
656 "\"implicit\":false,\"abstract\":false,"
657 "\"_intrinsic\":false,\"_native\":false,\"isGetter\":false,"
658 "\"isSetter\":false,\"location\":{\"type\":"
659 "\"SourceLocation\",\"script\":{\"type\":\"@Script\",\"fixedId\":true,"
660 "\"id\":\"\",\"uri\":\"file:\\/\\/\\/test-lib\",\"_kind\":\"kernel\"},"
661 "\"tokenPos\":0,\"endTokenPos\":11,\"line\":1,\"column\":1}},\"count\":1}"
662 "]}]}],"
663
664 // One script in the script table.
665 "\"scripts\":[{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
666 "\"uri\":\"file:\\/\\/\\/test-lib\",\"_kind\":\"kernel\"}]}",
667 buffer);
668}
669
670ISOLATE_UNIT_TEST_CASE(SourceReport_CallSites_PolymorphicCall) {
671 // WARNING: This MUST be big enough for the serialized JSON string.
672 const int kBufferSize = 4096;
673 char buffer[kBufferSize];
674 const char* kScript =
675 "class Common {\n"
676 " func() {}\n"
677 "}\n"
678 "class Uncommon {\n"
679 " func() {}\n"
680 "}\n"
681 "helper(arg) {\n"
682 " arg.func();\n"
683 "}\n"
684 "main() {\n"
685 " Common common = new Common();\n"
686 " Uncommon uncommon = new Uncommon();\n"
687 " helper(common);\n"
688 " helper(common);\n"
689 " helper(uncommon);\n"
690 "}";
691
692 Library& lib = Library::Handle();
693 lib ^= ExecuteScript(kScript);
694 ASSERT(!lib.IsNull());
695 const Script& script =
697 const Function& helper = Function::Handle(
699
701 JSONStream js;
702 report.PrintJSON(&js, script, helper.token_pos(), helper.end_token_pos());
703 const char* json_str = js.ToCString();
704 ASSERT(strlen(json_str) < kBufferSize);
705 ElideJSONSubstring("classes", json_str, buffer);
706 ElideJSONSubstring("libraries", buffer, buffer);
707 EXPECT_STREQ(
708 "{\"type\":\"SourceReport\",\"ranges\":["
709
710 // One range...
711 "{\"scriptIndex\":0,\"startPos\":60,\"endPos\":88,\"compiled\":true,"
712
713 // With one call site...
714 "\"callSites\":[{\"name\":\"dyn:func\",\"tokenPos\":80,\"cacheEntries\":["
715
716 // First receiver: "Common", called twice.
717 "{\"receiver\":{\"type\":\"@Class\",\"fixedId\":true,\"id\":\"\","
718 "\"name\":\"Common\","
719 "\"location\":{\"type\":\"SourceLocation\","
720 "\"script\":{\"type\":\"@Script\","
721 "\"fixedId\":true,\"id\":\"\","
722 "\"uri\":\"file:\\/\\/\\/test-lib\","
723 "\"_kind\":\"kernel\"},\"tokenPos\":0,\"endTokenPos\":27,\"line\":1,"
724 "\"column\":1},"
725 "\"library\":{\"type\":\"@Library\",\"fixedId\":true,"
726 "\"id\":\"\",\"name\":\"\",\"uri\":\"file:\\/\\/\\/test-lib\"}},"
727
728 "\"target\":{\"type\":\"@Function\",\"fixedId\":true,\"id\":\"\","
729 "\"name\":\"func\","
730 "\"owner\":{\"type\":\"@Class\",\"fixedId\":true,\"id\":\"\","
731 "\"name\":\"Common\","
732 "\"location\":{\"type\":\"SourceLocation\","
733 "\"script\":{\"type\":\"@Script\","
734 "\"fixedId\":true,\"id\":\"\","
735 "\"uri\":\"file:\\/\\/\\/test-lib\","
736 "\"_kind\":\"kernel\"},\"tokenPos\":0,\"endTokenPos\":27,\"line\":1,"
737 "\"column\":1},"
738 "\"library\":{\"type\":\"@Library\",\"fixedId\":true,"
739 "\"id\":\"\",\"name\":\"\",\"uri\":\"file:\\/\\/\\/test-lib\"}"
740 "},\"_kind\":\"RegularFunction\","
741 "\"static\":false,\"const\":false,\"implicit\":false,\"abstract\":"
742 "false,\"_intrinsic\":false,"
743 "\"_native\":false,\"isGetter\":false,\"isSetter\":false,"
744 "\"location\":{\"type\":\"SourceLocation\","
745 "\"script\":{\"type\":\"@Script\",\"fixedId\":true,"
746 "\"id\":\"\",\"uri\":\"file:\\/\\/\\/test-lib\","
747 "\"_kind\":\"kernel\"},\"tokenPos\":17,\"endTokenPos\":25,\"line\":2,"
748 "\"column\":3}},"
749
750 "\"count\":2},"
751
752 // Second receiver: "Uncommon", called once.
753 "{\"receiver\":{\"type\":\"@Class\",\"fixedId\":true,\"id\":\"\","
754 "\"name\":\"Uncommon\","
755 "\"location\":{\"type\":\"SourceLocation\","
756 "\"script\":{\"type\":\"@Script\","
757 "\"fixedId\":true,\"id\":\"\","
758 "\"uri\":\"file:\\/\\/\\/test-lib\","
759 "\"_kind\":\"kernel\"},\"tokenPos\":29,\"endTokenPos\":58,\"line\":4,"
760 "\"column\":1},"
761 "\"library\":{\"type\":\"@Library\",\"fixedId\":true,"
762 "\"id\":\"\",\"name\":\"\",\"uri\":\"file:\\/\\/\\/test-lib\"}},"
763
764 "\"target\":{\"type\":\"@Function\",\"fixedId\":true,\"id\":\"\","
765 "\"name\":\"func\","
766 "\"owner\":{\"type\":\"@Class\",\"fixedId\":true,\"id\":\"\","
767 "\"name\":\"Uncommon\","
768 "\"location\":{\"type\":\"SourceLocation\","
769 "\"script\":{\"type\":\"@Script\","
770 "\"fixedId\":true,\"id\":\"\","
771 "\"uri\":\"file:\\/\\/\\/test-lib\","
772 "\"_kind\":\"kernel\"},\"tokenPos\":29,\"endTokenPos\":58,\"line\":4,"
773 "\"column\":1},"
774 "\"library\":{\"type\":\"@Library\",\"fixedId\":true,"
775 "\"id\":\"\",\"name\":\"\",\"uri\":\"file:\\/\\/\\/test-lib\"}"
776 "},\"_kind\":\"RegularFunction\","
777 "\"static\":false,\"const\":false,\"implicit\":false,\"abstract\":"
778 "false,\"_intrinsic\":false,"
779 "\"_native\":false,\"isGetter\":false,\"isSetter\":false,"
780 "\"location\":{\"type\":\"SourceLocation\","
781 "\"script\":{\"type\":\"@Script\",\"fixedId\":true,"
782 "\"id\":\"\",\"uri\":\"file:\\/\\/\\/test-lib\","
783 "\"_kind\":\"kernel\"},\"tokenPos\":48,\"endTokenPos\":56,\"line\":5,"
784 "\"column\":3}},"
785
786 "\"count\":1}]}]}],"
787
788 // One script in the script table.
789 "\"scripts\":[{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
790 "\"uri\":\"file:\\/\\/\\/test-lib\",\"_kind\":\"kernel\"}]}",
791 buffer);
792}
793
794ISOLATE_UNIT_TEST_CASE(SourceReport_MultipleReports) {
795 // WARNING: This MUST be big enough for the serialized JSON string.
796 const int kBufferSize = 2048;
797 char buffer[kBufferSize];
798 const char* kScript =
799 "helper0() {}\n"
800 "helper1() {}\n"
801 "main() {\n"
802 " helper0();\n"
803 "}";
804
805 Library& lib = Library::Handle();
806 lib ^= ExecuteScript(kScript);
807 ASSERT(!lib.IsNull());
808 const Script& script =
810
812 JSONStream js;
813 report.PrintJSON(&js, script);
814 const char* json_str = js.ToCString();
815 ASSERT(strlen(json_str) < kBufferSize);
816 ElideJSONSubstring("classes", json_str, buffer);
817 ElideJSONSubstring("libraries", buffer, buffer);
818 EXPECT_STREQ(
819 "{\"type\":\"SourceReport\",\"ranges\":["
820
821 // One range compiled with no callsites (helper0).
822 "{\"scriptIndex\":0,\"startPos\":0,\"endPos\":11,\"compiled\":true,"
823 "\"callSites\":[],"
824 "\"coverage\":{\"hits\":[0],\"misses\":[]}},"
825
826 // One range not compiled (helper1).
827 "{\"scriptIndex\":0,\"startPos\":13,\"endPos\":24,\"compiled\":false},"
828
829 // One range compiled with one callsite (main)m
830 "{\"scriptIndex\":0,\"startPos\":26,\"endPos\":48,\"compiled\":true,"
831 "\"callSites\":[{\"name\":\"helper0\",\"tokenPos\":37,\"cacheEntries\":[{"
832 "\"target\":{\"type\":\"@Function\",\"fixedId\":true,\"id\":\"\","
833 "\"name\":\"helper0\",\"owner\":{\"type\":\"@Library\",\"fixedId\":true,"
834 "\"id\":\"\",\"name\":\"\",\"uri\":\"file:\\/\\/\\/test-lib\"},\"_"
835 "kind\":\"RegularFunction\",\"static\":true,\"const\":false,\"implicit\":"
836 "false,\"abstract\":false,\"_"
837 "intrinsic\":false,\"_native\":false,\"isGetter\":false,"
838 "\"isSetter\":false,\"location\":{\"type\":"
839 "\"SourceLocation\",\"script\":{\"type\":\"@Script\",\"fixedId\":true,"
840 "\"id\":\"\",\"uri\":\"file:\\/\\/\\/test-lib\",\"_kind\":\"kernel\"},"
841 "\"tokenPos\":0,\"endTokenPos\":11,\"line\":1,\"column\":1}},\"count\":1}"
842 "]}],\"coverage\":{"
843 "\"hits\":[26,37],\"misses\":[]}}],"
844
845 // One script in the script table.
846 "\"scripts\":[{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
847 "\"uri\":\"file:\\/\\/\\/test-lib\",\"_kind\":\"kernel\"}]}",
848 buffer);
849}
850
851ISOLATE_UNIT_TEST_CASE(SourceReport_PossibleBreakpoints_Simple) {
852 // WARNING: This MUST be big enough for the serialized JSON string.
853 const int kBufferSize = 1024;
854 char buffer[kBufferSize];
855 const char* kScript =
856 "helper0() {}\n"
857 "helper1() {}\n"
858 "main() {\n"
859 " if (true) {\n"
860 " helper0();\n"
861 " } else {\n"
862 " helper1();\n"
863 " }\n"
864 "}";
865
866 Library& lib = Library::Handle();
867 lib ^= ExecuteScript(kScript);
868 ASSERT(!lib.IsNull());
869 const Script& script =
871
873 JSONStream js;
874 report.PrintJSON(&js, script);
875 const char* json_str = js.ToCString();
876 ASSERT(strlen(json_str) < kBufferSize);
877 ElideJSONSubstring("classes", json_str, buffer);
878 ElideJSONSubstring("libraries", buffer, buffer);
879 EXPECT_STREQ(
880 "{\"type\":\"SourceReport\",\"ranges\":["
881
882 // helper0.
883 "{\"scriptIndex\":0,\"startPos\":0,\"endPos\":11,\"compiled\":true,"
884 "\"possibleBreakpoints\":[7,11]},"
885
886 // One range not compiled (helper1).
887 "{\"scriptIndex\":0,\"startPos\":13,\"endPos\":24,\"compiled\":false},"
888
889 // main.
890 "{\"scriptIndex\":0,\"startPos\":26,\"endPos\":94,\"compiled\":true,"
891 "\"possibleBreakpoints\":[30,53,79,94]}],"
892
893 // Only one script in the script table.
894 "\"scripts\":[{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
895 "\"uri\":\"file:\\/\\/\\/test-lib\",\"_kind\":\"kernel\"}]}",
896 buffer);
897}
898
899ISOLATE_UNIT_TEST_CASE(SourceReport_Coverage_Issue35453_NoSuchMethod) {
900 // WARNING: This MUST be big enough for the serialized JSON string.
901 const int kBufferSize = 1024;
902 char buffer[kBufferSize];
903 const char* kScript =
904 "class Foo {\n"
905 " void bar() {}\n"
906 "}\n"
907 "class Unused implements Foo {\n"
908 " dynamic noSuchMethod(_) {}\n"
909 "}\n"
910 "void main() {\n"
911 " Foo().bar();\n"
912 "}\n";
913
914 Library& lib = Library::Handle();
915 lib ^= ExecuteScript(kScript);
916 ASSERT(!lib.IsNull());
917 const Script& script =
919
921 JSONStream js;
922 report.PrintJSON(&js, script);
923 const char* json_str = js.ToCString();
924 ASSERT(strlen(json_str) < kBufferSize);
925 ElideJSONSubstring("classes", json_str, buffer);
926 ElideJSONSubstring("libraries", buffer, buffer);
927 EXPECT_STREQ(
928 "{\"type\":\"SourceReport\",\"ranges\":["
929
930 // Foo is hit.
931 "{\"scriptIndex\":0,\"startPos\":14,\"endPos\":26,\"compiled\":true,"
932 "\"coverage\":{\"hits\":[14],\"misses\":[]}},"
933
934 // Unused is missed.
935 "{\"scriptIndex\":0,\"startPos\":62,\"endPos\":87,\"compiled\":true,"
936 "\"coverage\":{\"hits\":[],\"misses\":[62]}},"
937
938 // Main is hit.
939 "{\"scriptIndex\":0,\"startPos\":91,\"endPos\":120,\"compiled\":true,"
940 "\"coverage\":{\"hits\":[91,107,113],\"misses\":[]}}],"
941
942 // Only one script in the script table.
943 "\"scripts\":[{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
944 "\"uri\":\"file:\\/\\/\\/test-lib\",\"_kind\":\"kernel\"}]}",
945 buffer);
946}
947
948ISOLATE_UNIT_TEST_CASE(SourceReport_Coverage_Issue47017_Assert) {
949 // WARNING: This MUST be big enough for the serialized JSON string.
950 const int kBufferSize = 1024;
951 char buffer[kBufferSize];
952 const char* kScript =
953 "void foo(Object? bar) {\n"
954 " assert(bar == null);\n"
955 "}\n"
956 "void main() {\n"
957 " foo(null);\n"
958 "}\n";
959
960 Library& lib = Library::Handle();
961 const bool old_asserts = IsolateGroup::Current()->asserts();
963 lib ^= ExecuteScript(kScript);
964 IsolateGroup::Current()->set_asserts(old_asserts);
965 ASSERT(!lib.IsNull());
966 const Script& script =
968
970 JSONStream js;
971 report.PrintJSON(&js, script);
972 const char* json_str = js.ToCString();
973 ASSERT(strlen(json_str) < kBufferSize);
974 ElideJSONSubstring("classes", json_str, buffer);
975 ElideJSONSubstring("libraries", buffer, buffer);
976 EXPECT_STREQ(
977 "{\"type\":\"SourceReport\",\"ranges\":["
978
979 // Foo is hit, and the assert is hit.
980 "{\"scriptIndex\":0,\"startPos\":0,\"endPos\":47,\"compiled\":true,"
981 "\"coverage\":{\"hits\":[0,33],\"misses\":[]}},"
982
983 // Main is hit.
984 "{\"scriptIndex\":0,\"startPos\":49,\"endPos\":76,\"compiled\":true,"
985 "\"coverage\":{\"hits\":[49,65],\"misses\":[]}}],"
986
987 // Only one script in the script table.
988 "\"scripts\":[{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
989 "\"uri\":\"file:\\/\\/\\/test-lib\",\"_kind\":\"kernel\"}]}",
990 buffer);
991}
992
993ISOLATE_UNIT_TEST_CASE(SourceReport_Coverage_Issue47021_StaticOnlyClasses) {
994 // WARNING: This MUST be big enough for the serialized JSON string.
995 const int kBufferSize = 2048;
996 char buffer[kBufferSize];
997 const char* kScript =
998 "abstract class AllStatic {\n"
999 " AllStatic._();\n"
1000 " static int test() => 123;\n"
1001 " static int foo = 456;\n"
1002 "}\n"
1003 "class NotAbstract {\n"
1004 " NotAbstract._();\n"
1005 " static int test() => 123;\n"
1006 " static int foo = 456;\n"
1007 "}\n"
1008 "abstract class NotConstructor {\n"
1009 " void _() {}\n"
1010 " static int test() => 123;\n"
1011 "}\n"
1012 "abstract class NotPrivate {\n"
1013 " NotPrivate();\n"
1014 " static int test() => 123;\n"
1015 "}\n"
1016 "abstract class HasParams {\n"
1017 " HasParams._(int i);\n"
1018 " static int test() => 123;\n"
1019 "}\n"
1020 "abstract class HasFields {\n"
1021 " HasFields._();\n"
1022 " static int test() => 123;\n"
1023 " int foo = 0;\n"
1024 "}\n"
1025 "abstract class HasNonStaticFunction {\n"
1026 " HasNonStaticFunction._();\n"
1027 " static int test() => 123;\n"
1028 " int foo() => 456;\n"
1029 "}\n"
1030 "abstract class HasSubclass {\n"
1031 " HasSubclass._();\n"
1032 " static int test() => 123;\n"
1033 " static int foo = 456;\n"
1034 "}\n"
1035 "abstract class Subclass extends HasSubclass {\n"
1036 " Subclass() : super._();\n"
1037 "}\n"
1038 "void main() {\n"
1039 " AllStatic.test();\n"
1040 " NotAbstract.test();\n"
1041 " NotConstructor.test();\n"
1042 " NotPrivate.test();\n"
1043 " HasParams.test();\n"
1044 " HasFields.test();\n"
1045 " HasNonStaticFunction.test();\n"
1046 " HasSubclass.test();\n"
1047 "}\n";
1048
1049 Library& lib = Library::Handle();
1050 lib ^= ExecuteScript(kScript);
1051 ASSERT(!lib.IsNull());
1052 const Script& script =
1054
1056 JSONStream js;
1057 report.PrintJSON(&js, script);
1058 const char* json_str = js.ToCString();
1059 ASSERT(strlen(json_str) < kBufferSize);
1060 ElideJSONSubstring("classes", json_str, buffer);
1061 ElideJSONSubstring("libraries", buffer, buffer);
1062 EXPECT_STREQ(
1063 "{\"type\":\"SourceReport\",\"ranges\":["
1064
1065 // Subclass() is missed.
1066 "{\"scriptIndex\":0,\"startPos\":775,\"endPos\":797,\"compiled\":true,"
1067 "\"coverage\":{\"hits\":[],\"misses\":[775,794]}},"
1068
1069 // AllStatic.test() is hit. AllStatic._() is ignored (would be pos: 29).
1070 "{\"scriptIndex\":0,\"startPos\":46,\"endPos\":70,\"compiled\":true,"
1071 "\"coverage\":{\"hits\":[46],\"misses\":[]}},"
1072
1073 // HasSubclass._() is missed, not ignored.
1074 "{\"scriptIndex\":0,\"startPos\":656,\"endPos\":671,\"compiled\":true,"
1075 "\"coverage\":{\"hits\":[],\"misses\":[656]}},"
1076
1077 // HasSubclass.test() is hit.
1078 "{\"scriptIndex\":0,\"startPos\":675,\"endPos\":699,\"compiled\":true,"
1079 "\"coverage\":{\"hits\":[675],\"misses\":[]}},"
1080
1081 // HasParams._(int i) is missed, not ignored.
1082 "{\"scriptIndex\":0,\"startPos\":370,\"endPos\":388,\"compiled\":true,"
1083 "\"coverage\":{\"hits\":[],\"misses\":[370]}},"
1084
1085 // HasParams.test() is hit.
1086 "{\"scriptIndex\":0,\"startPos\":392,\"endPos\":416,\"compiled\":true,"
1087 "\"coverage\":{\"hits\":[392],\"misses\":[]}},"
1088
1089 // NotAbstract._() is missed, not ignored.
1090 "{\"scriptIndex\":0,\"startPos\":120,\"endPos\":135,\"compiled\":true,"
1091 "\"coverage\":{\"hits\":[],\"misses\":[120]}},"
1092
1093 // NotAbstract.test() is hit.
1094 "{\"scriptIndex\":0,\"startPos\":139,\"endPos\":163,\"compiled\":true,"
1095 "\"coverage\":{\"hits\":[139],\"misses\":[]}},"
1096
1097 // HasFields._() is missed, not ignored.
1098 "{\"scriptIndex\":0,\"startPos\":449,\"endPos\":462,\"compiled\":true,"
1099 "\"coverage\":{\"hits\":[],\"misses\":[449]}},"
1100
1101 // HasFields.test() is hit.
1102 "{\"scriptIndex\":0,\"startPos\":466,\"endPos\":490,\"compiled\":true,"
1103 "\"coverage\":{\"hits\":[466],\"misses\":[]}},"
1104
1105 // NotPrivate() is missed, not ignored.
1106 "{\"scriptIndex\":0,\"startPos\":297,\"endPos\":309,\"compiled\":true,"
1107 "\"coverage\":{\"hits\":[],\"misses\":[297]}},"
1108
1109 // NotPrivate.test() is hit.
1110 "{\"scriptIndex\":0,\"startPos\":313,\"endPos\":337,\"compiled\":true,"
1111 "\"coverage\":{\"hits\":[313],\"misses\":[]}},"
1112
1113 // HasNonStaticFunction._() is missed, not ignored.
1114 "{\"scriptIndex\":0,\"startPos\":549,\"endPos\":573,\"compiled\":true,"
1115 "\"coverage\":{\"hits\":[],\"misses\":[549]}},"
1116
1117 // HasNonStaticFunction.test() is hit.
1118 "{\"scriptIndex\":0,\"startPos\":577,\"endPos\":601,\"compiled\":true,"
1119 "\"coverage\":{\"hits\":[577],\"misses\":[]}},"
1120
1121 // HasNonStaticFunction.foo() is missed.
1122 "{\"scriptIndex\":0,\"startPos\":605,\"endPos\":621,\"compiled\":true,"
1123 "\"coverage\":{\"hits\":[],\"misses\":[605]}},"
1124
1125 // NotConstructor._() is missed, not ignored.
1126 "{\"scriptIndex\":0,\"startPos\":225,\"endPos\":235,\"compiled\":true,"
1127 "\"coverage\":{\"hits\":[],\"misses\":[225]}},"
1128
1129 // NotConstructor.test() is hit.
1130 "{\"scriptIndex\":0,\"startPos\":239,\"endPos\":263,\"compiled\":true,"
1131 "\"coverage\":{\"hits\":[239],\"misses\":[]}},"
1132
1133 // Main is hit.
1134 "{\"scriptIndex\":0,\"startPos\":801,\"endPos\":996,\"compiled\":true,"
1135 "\"coverage\":{\"hits\":"
1136 "[801,827,849,874,895,915,935,966,988],\"misses\":[]}}],"
1137
1138 // Only one script in the script table.
1139 "\"scripts\":[{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
1140 "\"uri\":\"file:\\/\\/\\/test-lib\",\"_kind\":\"kernel\"}]}",
1141 buffer);
1142}
1143
1144ISOLATE_UNIT_TEST_CASE(SourceReport_Coverage_IssueCov341_LateFinalVars) {
1145 // https://github.com/dart-lang/coverage/issues/341
1146 // WARNING: This MUST be big enough for the serialized JSON string.
1147 const int kBufferSize = 1024;
1148 char buffer[kBufferSize];
1149 const char* kScript =
1150 "int foo(bool bar) {\n"
1151 " late final int baz;\n"
1152 " if (bar) {\n"
1153 " baz = 123;\n"
1154 " } else {\n"
1155 " baz = 456;\n"
1156 " }\n"
1157 " return baz;\n"
1158 "}\n"
1159 "main() {\n"
1160 " foo(true);\n"
1161 " foo(false);\n"
1162 "}\n";
1163
1164 Library& lib = Library::Handle();
1165 lib ^= ExecuteScript(kScript);
1166 ASSERT(!lib.IsNull());
1167 const Script& script =
1169
1171 JSONStream js;
1172 report.PrintJSON(&js, script);
1173 const char* json_str = js.ToCString();
1174 ASSERT(strlen(json_str) < kBufferSize);
1175 ElideJSONSubstring("classes", json_str, buffer);
1176 ElideJSONSubstring("libraries", buffer, buffer);
1177 EXPECT_STREQ(
1178 "{\"type\":\"SourceReport\",\"ranges\":["
1179
1180 // foo is hit, but the late variable sets and gets are ignored.
1181 "{\"scriptIndex\":0,\"startPos\":0,\"endPos\":114,\"compiled\":true,"
1182 "\"coverage\":{\"hits\":[0],\"misses\":[]}},"
1183
1184 // Main is hit.
1185 "{\"scriptIndex\":0,\"startPos\":116,\"endPos\":152,\"compiled\":true,\""
1186 "coverage\":{\"hits\":[116,127,140],\"misses\":[]}}],"
1187
1188 // Only one script in the script table.
1189 "\"scripts\":[{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
1190 "\"uri\":\"file:\\/\\/\\/test-lib\",\"_kind\":\"kernel\"}]}",
1191 buffer);
1192}
1193
1194ISOLATE_UNIT_TEST_CASE(SourceReport_Coverage_IssueCov386_EnhancedEnums) {
1195 // https://github.com/dart-lang/coverage/issues/386
1196 // https://github.com/dart-lang/coverage/issues/377
1197 // WARNING: This MUST be big enough for the serialized JSON string.
1198 const int kBufferSize = 1024;
1199 char buffer[kBufferSize];
1200 const char* kScript =
1201 "enum FoodType {\n"
1202 " candy();\n"
1203 " const FoodType();\n"
1204 " factory FoodType.candyFactory() => candy;\n"
1205 "}\n"
1206 "void main() {\n"
1207 " final food = FoodType.candyFactory();\n"
1208 "}\n";
1209
1210 Library& lib = Library::Handle();
1211 lib ^= ExecuteScript(kScript);
1212 ASSERT(!lib.IsNull());
1213 const Script& script =
1215
1217 JSONStream js;
1218 report.PrintJSON(&js, script);
1219 const char* json_str = js.ToCString();
1220 ASSERT(strlen(json_str) < kBufferSize);
1221 ElideJSONSubstring("classes", json_str, buffer);
1222 ElideJSONSubstring("libraries", buffer, buffer);
1223 EXPECT_STREQ(
1224 "{\"type\":\"SourceReport\",\"ranges\":["
1225
1226 // Main is hit.
1227 "{\"scriptIndex\":0,\"startPos\":49,\"endPos\":89,\"compiled\":true,"
1228 "\"coverage\":{\"hits\":[49],\"misses\":[]}},"
1229
1230 // The enum's constructor, and toString, are not included in the hitmap,
1231 // but the factory is included.
1232 "{\"scriptIndex\":0,\"startPos\":93,\"endPos\":147,\"compiled\":true,"
1233 "\"coverage\":{\"hits\":[93,131],\"misses\":[]}}],"
1234
1235 // Only one script in the script table.
1236 "\"scripts\":[{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
1237 "\"uri\":\"file:\\/\\/\\/test-lib\",\"_kind\":\"kernel\"}]}",
1238 buffer);
1239}
1240
1241ISOLATE_UNIT_TEST_CASE(SourceReport_Regress95008_RedirectingFactory) {
1242 // WARNING: This MUST be big enough for the serialized JSON string.
1243 const int kBufferSize = 1024;
1244 char buffer[kBufferSize];
1245 const char* kScript = R"(
1246class A {
1247 A();
1248 factory A.foo(int i) = B; // LINE_A
1249}
1250
1251class B extends A {
1252 int i;
1253 B(this.i); // LINE_B
1254}
1255
1256main() {
1257 A.foo(42);
1258}
1259)";
1260
1261 Library& lib = Library::Handle();
1262 lib ^= ExecuteScript(kScript);
1263 ASSERT(!lib.IsNull());
1264 const Script& script =
1266
1268 JSONStream js;
1269 report.PrintJSON(&js, script);
1270 const char* json_str = js.ToCString();
1271 ASSERT(strlen(json_str) < kBufferSize);
1272 ElideJSONSubstring("classes", json_str, buffer);
1273 ElideJSONSubstring("libraries", buffer, buffer);
1274 EXPECT_STREQ(
1275 "{\"type\":\"SourceReport\",\"ranges\":["
1276
1277 // A()
1278 "{\"scriptIndex\":0,\"startPos\":13,\"endPos\":16,\"compiled\":true,"
1279 "\"coverage\":{\"hits\":[13],\"misses\":[]}},"
1280
1281 // B()
1282 "{\"scriptIndex\":0,\"startPos\":90,\"endPos\":99,\"compiled\":true,"
1283 "\"coverage\":{\"hits\":[90],\"misses\":[]}},"
1284
1285 // main
1286 "{\"scriptIndex\":0,\"startPos\":114,\"endPos\":136,\"compiled\":true,"
1287 "\"coverage\":{\"hits\":[114,127],\"misses\":[]}}],"
1288
1289 // Only one script in the script table.
1290 "\"scripts\":[{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
1291 "\"uri\":\"file:\\/\\/\\/test-lib\",\"_kind\":\"kernel\"}]}",
1292 buffer);
1293}
1294
1295ISOLATE_UNIT_TEST_CASE(SourceReport_Regress53519_Destructuring) {
1296 // WARNING: This MUST be big enough for the serialized JSON string.
1297 const int kBufferSize = 1024;
1298 char buffer[kBufferSize];
1299 const char* kScript = R"(
1300main() {
1301 destructure({
1302 'hello': 'world',
1303 'count': [1, 2, 3],
1304 });
1305}
1306
1307String destructure(Map<String, dynamic> map) {
1308 final {'hello': world, 'count': count} = map;
1309 return 'Hello $world, count: $count';
1310}
1311)";
1312
1313 Library& lib = Library::Handle();
1314 lib ^= ExecuteScript(kScript);
1315 ASSERT(!lib.IsNull());
1316 const Script& script =
1318
1320 JSONStream js;
1321 report.PrintJSON(&js, script);
1322 const char* json_str = js.ToCString();
1323 ASSERT(strlen(json_str) < kBufferSize);
1324 ElideJSONSubstring("classes", json_str, buffer);
1325 ElideJSONSubstring("libraries", buffer, buffer);
1326 EXPECT_STREQ(
1327 "{\"type\":\"SourceReport\",\"ranges\":["
1328
1329 // main
1330 "{\"scriptIndex\":0,\"startPos\":1,\"endPos\":78,\"compiled\":true,"
1331 "\"coverage\":{\"hits\":[1,12,24,61],\"misses\":[]}},"
1332
1333 // destructure
1334 "{\"scriptIndex\":0,\"startPos\":81,\"endPos\":216,\"compiled\":true,"
1335 "\"coverage\":{\"hits\":[81,144,160,214],\"misses\":[]}}],"
1336
1337 // Only one script in the script table.
1338 "\"scripts\":[{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
1339 "\"uri\":\"file:\\/\\/\\/test-lib\",\"_kind\":\"kernel\"}]}",
1340 buffer);
1341}
1342
1343ISOLATE_UNIT_TEST_CASE(SourceReport_BranchCoverage_if) {
1344 // WARNING: This MUST be big enough for the serialized JSON string.
1345 const int kBufferSize = 1024;
1346 char buffer[kBufferSize];
1347 const char* kScript = R"(
1348int ifTest(int x) {
1349 if (x > 0) {
1350 if (x > 10) {
1351 return 10;
1352 } else {
1353 return 1;
1354 }
1355 } else {
1356 return 0;
1357 }
1358}
1359
1360main() {
1361 ifTest(1);
1362}
1363)";
1364
1365 Library& lib = Library::Handle();
1366 const bool old_branch_coverage = IsolateGroup::Current()->branch_coverage();
1368 lib ^= ExecuteScript(kScript);
1369 IsolateGroup::Current()->set_branch_coverage(old_branch_coverage);
1370 ASSERT(!lib.IsNull());
1371 const Script& script =
1373
1375 JSONStream js;
1376 report.PrintJSON(&js, script);
1377 const char* json_str = js.ToCString();
1378 ASSERT(strlen(json_str) < kBufferSize);
1379 ElideJSONSubstring("classes", json_str, buffer);
1380 ElideJSONSubstring("libraries", buffer, buffer);
1381 EXPECT_STREQ(
1382 "{\"type\":\"SourceReport\",\"ranges\":["
1383
1384 // In ifTest, the outer true case is hit, the inner true case is missed,
1385 // the inner false case is hit, and the outer false case is missed.
1386 "{\"scriptIndex\":0,\"startPos\":1,\"endPos\":135,\"compiled\":true,"
1387 "\"branchCoverage\":{\"hits\":[1,34,82],\"misses\":[52,115]}},"
1388
1389 // Main is hit.
1390 "{\"scriptIndex\":0,\"startPos\":138,\"endPos\":160,\"compiled\":true,"
1391 "\"branchCoverage\":{\"hits\":[138],\"misses\":[]}}],"
1392
1393 // Only one script in the script table.
1394 "\"scripts\":[{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
1395 "\"uri\":\"file:\\/\\/\\/test-lib\",\"_kind\":\"kernel\"}]}",
1396 buffer);
1397}
1398
1399ISOLATE_UNIT_TEST_CASE(SourceReport_BranchCoverage_loops) {
1400 // WARNING: This MUST be big enough for the serialized JSON string.
1401 const int kBufferSize = 1024;
1402 char buffer[kBufferSize];
1403 const char* kScript = R"(
1404int loopTest() {
1405 var x = 0;
1406
1407 while (x < 10) {
1408 ++x;
1409 }
1410
1411 do {
1412 ++x;
1413 } while (false);
1414
1415 for (int i = 0; i < 10; ++i) {
1416 ++x;
1417 }
1418
1419 for (final i in [1, 2, 3]) {
1420 ++x;
1421 }
1422
1423 return x;
1424}
1425
1426main() {
1427 loopTest();
1428}
1429)";
1430
1431 Library& lib = Library::Handle();
1432 const bool old_branch_coverage = IsolateGroup::Current()->branch_coverage();
1434 lib ^= ExecuteScript(kScript);
1435 IsolateGroup::Current()->set_branch_coverage(old_branch_coverage);
1436 ASSERT(!lib.IsNull());
1437 const Script& script =
1439
1441 JSONStream js;
1442 report.PrintJSON(&js, script);
1443 const char* json_str = js.ToCString();
1444 ASSERT(strlen(json_str) < kBufferSize);
1445 ElideJSONSubstring("classes", json_str, buffer);
1446 ElideJSONSubstring("libraries", buffer, buffer);
1447 EXPECT_STREQ(
1448 "{\"type\":\"SourceReport\",\"ranges\":["
1449
1450 // In loopTest, the while loop, do-while loop, for loop, and for-in loop
1451 // are all hit.
1452 "{\"scriptIndex\":0,\"startPos\":1,\"endPos\":205,\"compiled\":true,"
1453 "\"branchCoverage\":{\"hits\":[1,49,70,132,177],\"misses\":[]}},"
1454
1455 // Main is hit.
1456 "{\"scriptIndex\":0,\"startPos\":208,\"endPos\":231,\"compiled\":true,"
1457 "\"branchCoverage\":{\"hits\":[208],\"misses\":[]}}],"
1458
1459 // Only one script in the script table.
1460 "\"scripts\":[{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
1461 "\"uri\":\"file:\\/\\/\\/test-lib\",\"_kind\":\"kernel\"}]}",
1462 buffer);
1463}
1464
1465ISOLATE_UNIT_TEST_CASE(SourceReport_BranchCoverage_switch) {
1466 // WARNING: This MUST be big enough for the serialized JSON string.
1467 const int kBufferSize = 1024;
1468 char buffer[kBufferSize];
1469 const char* kScript = R"(
1470int switchTest(int x) {
1471 switch (x) {
1472 case 0:
1473 return 10;
1474 case 1:
1475 return 20;
1476 default:
1477 return 30;
1478 }
1479}
1480
1481main() {
1482 switchTest(1);
1483}
1484)";
1485
1486 Library& lib = Library::Handle();
1487 const bool old_branch_coverage = IsolateGroup::Current()->branch_coverage();
1489 lib ^= ExecuteScript(kScript);
1490 IsolateGroup::Current()->set_branch_coverage(old_branch_coverage);
1491 ASSERT(!lib.IsNull());
1492 const Script& script =
1494
1496 JSONStream js;
1497 report.PrintJSON(&js, script);
1498 const char* json_str = js.ToCString();
1499 ASSERT(strlen(json_str) < kBufferSize);
1500 ElideJSONSubstring("classes", json_str, buffer);
1501 ElideJSONSubstring("libraries", buffer, buffer);
1502 EXPECT_STREQ(
1503 "{\"type\":\"SourceReport\",\"ranges\":["
1504
1505 // In switchTest, the 1 case is hit and the others are missed.
1506 "{\"scriptIndex\":0,\"startPos\":1,\"endPos\":132,\"compiled\":true,"
1507 "\"branchCoverage\":{\"hits\":[1,73],\"misses\":[44,102]}},"
1508
1509 // Main is hit.
1510 "{\"scriptIndex\":0,\"startPos\":135,\"endPos\":161,\"compiled\":true,"
1511 "\"branchCoverage\":{\"hits\":[135],\"misses\":[]}}],"
1512
1513 // Only one script in the script table.
1514 "\"scripts\":[{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
1515 "\"uri\":\"file:\\/\\/\\/test-lib\",\"_kind\":\"kernel\"}]}",
1516 buffer);
1517}
1518
1519ISOLATE_UNIT_TEST_CASE(SourceReport_BranchCoverage_try) {
1520 // WARNING: This MUST be big enough for the serialized JSON string.
1521 const int kBufferSize = 1024;
1522 char buffer[kBufferSize];
1523 const char* kScript = R"(
1524void tryTestInner() {
1525 try {
1526 throw "abc";
1527 } catch (e) {
1528 } finally {
1529 }
1530
1531 try {
1532 throw "def";
1533 } finally {
1534 }
1535}
1536
1537void tryTestOuter() {
1538 try {
1539 tryTestInner();
1540 } catch (e) {
1541 }
1542}
1543
1544main() {
1545 tryTestOuter();
1546}
1547)";
1548
1549 Library& lib = Library::Handle();
1550 const bool old_branch_coverage = IsolateGroup::Current()->branch_coverage();
1552 lib ^= ExecuteScript(kScript);
1553 IsolateGroup::Current()->set_branch_coverage(old_branch_coverage);
1554 ASSERT(!lib.IsNull());
1555 const Script& script =
1557
1559 JSONStream js;
1560 report.PrintJSON(&js, script);
1561 const char* json_str = js.ToCString();
1562 ASSERT(strlen(json_str) < kBufferSize);
1563 ElideJSONSubstring("classes", json_str, buffer);
1564 ElideJSONSubstring("libraries", buffer, buffer);
1565 EXPECT_STREQ(
1566 "{\"type\":\"SourceReport\",\"ranges\":["
1567
1568 // In tryTestInner, the try/catch/finally and the try/finally are all hit,
1569 // and the try/finally rethrows its exception.
1570 "{\"scriptIndex\":0,\"startPos\":1,\"endPos\":126,\"compiled\":true,"
1571 "\"branchCoverage\":{\"hits\":[1,29,62,76,89,120],\"misses\":[]}},"
1572
1573 // In tryTestOuter, the exception thrown by tryTestInner causes both the
1574 // try and the catch to be hit.
1575 "{\"scriptIndex\":0,\"startPos\":129,\"endPos\":199,\"compiled\":true,"
1576 "\"branchCoverage\":{\"hits\":[129,157,193],\"misses\":[]}},"
1577
1578 // Main is hit.
1579 "{\"scriptIndex\":0,\"startPos\":202,\"endPos\":229,\"compiled\":true,"
1580 "\"branchCoverage\":{\"hits\":[202],\"misses\":[]}}],"
1581
1582 // Only one script in the script table.
1583 "\"scripts\":[{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
1584 "\"uri\":\"file:\\/\\/\\/test-lib\",\"_kind\":\"kernel\"}]}",
1585 buffer);
1586}
1587
1588#endif // !PRODUCT
1589
1590} // namespace dart
static const size_t kBufferSize
Definition SkString.cpp:27
static ObjectPtr UnwrapHandle(Dart_Handle object)
void Insert(typename KeyValueTrait::Pair kv)
Definition hash_map.h:230
TokenPosition token_pos() const
Definition object.h:3426
TokenPosition end_token_pos() const
Definition object.h:3435
void Add(const Object &value, Heap::Space space=Heap::kNew) const
Definition object.cc:25070
static GrowableObjectArrayPtr New(Heap::Space space=Heap::kNew)
Definition object.h:11118
static IsolateGroup * Current()
Definition isolate.h:534
void set_branch_coverage(bool value)
Definition isolate.h:457
void set_asserts(bool value)
Definition isolate.h:452
ScriptPtr LookupScript(const String &url, bool useResolvedUri=false) const
Definition object.cc:14056
FunctionPtr LookupFunctionAllowPrivate(const String &name) const
Definition object.cc:14131
static ObjectPtr null()
Definition object.h:433
bool IsNull() const
Definition object.h:363
static Object & Handle()
Definition object.h:407
void PrintJSON(JSONStream *js, const Script &script, TokenPosition start_pos=TokenPosition::kMinSource, TokenPosition end_pos=TokenPosition::kMaxSource)
static StringPtr New(const char *cstr, Heap::Space space=Heap::kNew)
Definition object.cc:23777
static Dart_Handle LoadTestScript(const char *script, Dart_NativeEntryResolver resolver, const char *lib_uri=RESOLVED_USER_TEST_URI, bool finalize=true, bool allow_compile_errors=false)
Definition unit_test.cc:422
static Dart_Handle LoadTestScriptWithErrors(const char *script, Dart_NativeEntryResolver resolver=nullptr, const char *lib_uri=RESOLVED_USER_TEST_URI, bool finalize=true)
Definition unit_test.cc:414
static Thread * Current()
Definition thread.h:361
struct _Dart_Handle * Dart_Handle
Definition dart_api.h:258
#define ASSERT(E)
static const uint8_t buffer[]
GAsyncResult * result
void ElideJSONSubstring(const char *prefix, const char *in, char *out, const char *postfix)
Definition unit_test.cc:776
DART_EXPORT Dart_Handle Dart_Invoke(Dart_Handle target, Dart_Handle name, int number_of_arguments, Dart_Handle *arguments)
Dart_Handle NewString(const char *str)
static ObjectPtr ExecuteScript(const char *script, bool allow_errors=false)
#define ISOLATE_UNIT_TEST_CASE(name)
Definition unit_test.h:64
#define RESOLVED_USER_TEST_URI
Definition unit_test.h:317
#define EXPECT_VALID(handle)
Definition unit_test.h:650