dart-sdk/tests/standalone/dwarf_stack_trace_invisible_functions_test.dart
Vyacheslav Egorov 19e56613cf [infra] Prevent VM AOT tests from poluting SDK source.
Extend test_runner VMOptions support with an ability to specify
paths relative to temporary compilation directory.

    // VMOptions=--foo=$TEST_COMPILATION_DIR/foo.file

The same directory will also be passed as an environment variable
to execution command.

Migrate most of the tests which used to write stuff into the SDK
root to use this feature. I am leaving vm/dart/causal/* tests
unmigrated because migrating requires time consuming manual
update of expectations (which encode raw line numbers). I have
a follow up CL which changes how these tests are written which
will make migration trivial.

Change-Id: Id53008be66de8ff18623efac27ff15750f407749
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/300600
Reviewed-by: William Hesse <whesse@google.com>
Commit-Queue: Slava Egorov <vegorov@google.com>
2023-05-03 13:24:39 +00:00

125 lines
3.2 KiB
Dart

// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
/// VMOptions=--dwarf-stack-traces --save-debugging-info=$TEST_COMPILATION_DIR/dwarf_invisible_functions.so
import 'dart:io';
import 'package:native_stack_traces/native_stack_traces.dart';
import 'package:path/path.dart' as path;
import 'dwarf_stack_trace_test.dart' as dwarf_stack_trace_test;
const int LINE_A = 23;
const int LINE_B = 29;
const int LINE_C = 36;
const int LINE_D = 44;
const int LINE_E = 56;
@pragma("vm:prefer-inline")
bar() {
// Keep the 'throw' and its argument on separate lines.
throw // force linebreak with dart format // LINE_A
"Hello, Dwarf!";
}
@pragma("vm:never-inline")
foo() {
bar(); // LINE_B
}
@pragma("vm:never-inline")
bazz(void Function() func) {
// Call through tear-off (implicit closure function) which should be
// omitted from the stack trace.
func(); // LINE_C
}
class A<T> {
A();
@pragma("vm:never-inline")
void add(T x) {
bazz(foo); // LINE_D
}
}
dynamic aa = int.parse('1') == 1 ? A() : [];
Future<void> main() async {
String rawStack = "";
try {
// Dynamic call to a generic-covariant method goes through the
// dynamic invocation forwarder function, which should be
// omitted from the stack trace.
aa.add(42); // LINE_E
} catch (e, st) {
rawStack = st.toString();
}
if (path.basenameWithoutExtension(Platform.executable) !=
"dart_precompiled_runtime") {
return; // Not running from an AOT compiled snapshot.
}
if (Platform.isAndroid) {
return; // Generated dwarf.so not available on the test device.
}
final dwarf = Dwarf.fromFile(path.join(
Platform.environment["TEST_COMPILATION_DIR"]!,
"dwarf_invisible_functions.so"))!;
await dwarf_stack_trace_test.checkStackTrace(
rawStack, dwarf, expectedCallsInfo);
}
final expectedCallsInfo = <List<DartCallInfo>>[
// Frame 1: the throw in bar, which was inlined
// into foo (so we'll get information for two calls for that PC address).
[
DartCallInfo(
function: "bar",
filename: "dwarf_stack_trace_invisible_functions_test.dart",
line: LINE_A,
column: 3,
inlined: true),
DartCallInfo(
function: "foo",
filename: "dwarf_stack_trace_invisible_functions_test.dart",
line: LINE_B,
column: 3,
inlined: false)
],
// Frame 2: call to foo in bazz.
[
DartCallInfo(
function: "bazz",
filename: "dwarf_stack_trace_invisible_functions_test.dart",
line: LINE_C,
column: 3,
inlined: false)
],
// Frame 3: call to bazz in A.method.
[
DartCallInfo(
function: "A.add",
filename: "dwarf_stack_trace_invisible_functions_test.dart",
line: LINE_D,
column: 5,
inlined: false)
],
// Frame 4: the call to foo in main.
[
DartCallInfo(
function: "main",
filename: "dwarf_stack_trace_invisible_functions_test.dart",
line: LINE_E,
column: 8,
inlined: false)
],
// Don't assume anything about any of the frames below the main,
// as this makes the test too brittle.
];