// Copyright (c) 2019, 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.

// This test ensures that the flag for --dwarf-stack-traces given at AOT
// compile-time will be used at runtime (irrespective if other values were
// passed to the runtime).

import "dart:async";
import "dart:convert";
import "dart:io";

import 'package:expect/expect.dart';
import 'package:native_stack_traces/native_stack_traces.dart';
import 'package:path/path.dart' as path;

import 'use_flag_test_helper.dart';

main(List<String> args) async {
  if (!isAOTRuntime) {
    return; // Running in JIT: AOT binaries not available.
  }

  if (Platform.isAndroid) {
    return; // SDK tree and dart_bootstrap not available on the test device.
  }

  // These are the tools we need to be available to run on a given platform:
  if (!await testExecutable(genSnapshot)) {
    throw "Cannot run test as $genSnapshot not available";
  }
  if (!await testExecutable(aotRuntime)) {
    throw "Cannot run test as $aotRuntime not available";
  }
  if (!File(platformDill).existsSync()) {
    throw "Cannot run test as $platformDill does not exist";
  }

  await withTempDir('dwarf-flag-test', (String tempDir) async {
    // We have to use the program in its original location so it can use
    // the dart:_internal library (as opposed to adding it as an OtherResources
    // option to the test).
    final script = path.join(sdkDir, 'runtime', 'tests', 'vm', 'dart',
        'use_dwarf_stack_traces_flag_program.dart');
    final scriptDill = path.join(tempDir, 'flag_program.dill');

    // Compile script to Kernel IR.
    await run(genKernel, <String>[
      '--aot',
      '--platform=$platformDill',
      '-o',
      scriptDill,
      script,
    ]);

    // Run the AOT compiler with/without Dwarf stack traces.
    final scriptDwarfSnapshot = path.join(tempDir, 'dwarf.so');
    final scriptNonDwarfSnapshot = path.join(tempDir, 'non_dwarf.so');
    final scriptDwarfDebugInfo = path.join(tempDir, 'debug_info.so');
    await Future.wait(<Future>[
      run(genSnapshot, <String>[
        // We test --dwarf-stack-traces-mode, not --dwarf-stack-traces, because
        // the latter is a handler that sets the former and also may change
        // other flags. This way, we limit the difference between the two
        // snapshots and also directly test the flag saved as a VM global flag.
        '--dwarf-stack-traces-mode',
        '--save-debugging-info=$scriptDwarfDebugInfo',
        '--snapshot-kind=app-aot-elf',
        '--elf=$scriptDwarfSnapshot',
        scriptDill,
      ]),
      run(genSnapshot, <String>[
        '--no-dwarf-stack-traces-mode',
        '--snapshot-kind=app-aot-elf',
        '--elf=$scriptNonDwarfSnapshot',
        scriptDill,
      ]),
    ]);

    // Run the resulting Dwarf-AOT compiled script.

    final output1 = await runTestProgram(aotRuntime,
        <String>['--dwarf-stack-traces-mode', scriptDwarfSnapshot, scriptDill]);
    final output2 = await runTestProgram(aotRuntime, <String>[
      '--no-dwarf-stack-traces-mode',
      scriptDwarfSnapshot,
      scriptDill
    ]);

    // Run the resulting non-Dwarf-AOT compiled script.
    final nonDwarfTrace1 = (await runTestProgram(aotRuntime, <String>[
      '--dwarf-stack-traces-mode',
      scriptNonDwarfSnapshot,
      scriptDill,
    ]))
        .trace;
    final nonDwarfTrace2 = (await runTestProgram(aotRuntime, <String>[
      '--no-dwarf-stack-traces-mode',
      scriptNonDwarfSnapshot,
      scriptDill,
    ]))
        .trace;

    // Ensure the result is based off the flag passed to gen_snapshot, not
    // the one passed to the runtime.
    Expect.deepEquals(nonDwarfTrace1, nonDwarfTrace2);

    // Check with DWARF from separate debugging information.
    await compareTraces(nonDwarfTrace1, output1, output2, scriptDwarfDebugInfo);
    // Check with DWARF in generated snapshot.
    await compareTraces(nonDwarfTrace1, output1, output2, scriptDwarfSnapshot);

    if (Platform.isLinux || Platform.isMacOS) {
      final scriptAssembly = path.join(tempDir, 'dwarf_assembly.S');
      final scriptDwarfAssemblyDebugInfo =
          path.join(tempDir, 'dwarf_assembly_info.so');
      final scriptDwarfAssemblySnapshot =
          path.join(tempDir, 'dwarf_assembly.so');
      // We get a separate .dSYM bundle on MacOS.
      final scriptDwarfAssemblyDebugSnapshot =
          scriptDwarfAssemblySnapshot + (Platform.isMacOS ? '.dSYM' : '');

      await run(genSnapshot, <String>[
        // We test --dwarf-stack-traces-mode, not --dwarf-stack-traces, because
        // the latter is a handler that sets the former and also may change
        // other flags. This way, we limit the difference between the two
        // snapshots and also directly test the flag saved as a VM global flag.
        '--dwarf-stack-traces-mode',
        '--save-debugging-info=$scriptDwarfAssemblyDebugInfo',
        '--snapshot-kind=app-aot-assembly',
        '--assembly=$scriptAssembly',
        scriptDill,
      ]);

      await assembleSnapshot(scriptAssembly, scriptDwarfAssemblySnapshot,
          debug: true);

      // Run the resulting Dwarf-AOT compiled script.
      final assemblyOutput1 = await runTestProgram(aotRuntime, <String>[
        '--dwarf-stack-traces-mode',
        scriptDwarfAssemblySnapshot,
        scriptDill,
      ]);
      final assemblyOutput2 = await runTestProgram(aotRuntime, <String>[
        '--no-dwarf-stack-traces-mode',
        scriptDwarfAssemblySnapshot,
        scriptDill,
      ]);

      // Check with DWARF in assembled snapshot.
      await compareTraces(nonDwarfTrace1, assemblyOutput1, assemblyOutput2,
          scriptDwarfAssemblyDebugSnapshot,
          fromAssembly: true);
      // Check with DWARF from separate debugging information.
      await compareTraces(nonDwarfTrace1, assemblyOutput1, assemblyOutput2,
          scriptDwarfAssemblyDebugInfo,
          fromAssembly: true);
    }
  });
}

class DwarfTestOutput {
  final List<String> trace;
  final int allocateObjectAddress;

  DwarfTestOutput(this.trace, this.allocateObjectAddress);
}

Future<void> compareTraces(List<String> nonDwarfTrace, DwarfTestOutput output1,
    DwarfTestOutput output2, String dwarfPath,
    {bool fromAssembly = false}) async {
  // For DWARF stack traces, we can't guarantee that the stack traces are
  // textually equal on all platforms, but if we retrieve the PC offsets
  // out of the stack trace, those should be equal.
  final tracePCOffsets1 = collectPCOffsets(output1.trace);
  final tracePCOffsets2 = collectPCOffsets(output2.trace);
  Expect.deepEquals(tracePCOffsets1, tracePCOffsets2);

  // Check that translating the DWARF stack trace (without internal frames)
  // matches the symbolic stack trace.
  print("Reading DWARF info from ${dwarfPath}");
  final dwarf = Dwarf.fromFile(dwarfPath);
  Expect.isNotNull(dwarf);

  // Check that build IDs match for traces from running ELF snapshots.
  if (!fromAssembly) {
    Expect.isNotNull(dwarf!.buildId);
    print('Dwarf build ID: "${dwarf.buildId!}"');
    // We should never generate an all-zero build ID.
    Expect.notEquals(dwarf.buildId, "00000000000000000000000000000000");
    // This is a common failure case as well, when HashBitsContainer ends up
    // hashing over seemingly empty sections.
    Expect.notEquals(dwarf.buildId, "01000000010000000100000001000000");
    final buildId1 = buildId(output1.trace);
    Expect.isFalse(buildId1.isEmpty);
    print('Trace 1 build ID: "${buildId1}"');
    Expect.equals(dwarf.buildId, buildId1);
    final buildId2 = buildId(output2.trace);
    Expect.isFalse(buildId2.isEmpty);
    print('Trace 2 build ID: "${buildId2}"');
    Expect.equals(dwarf.buildId, buildId2);
  }

  final decoder = DwarfStackTraceDecoder(dwarf!);
  // Run on the second trace just for the side effect of getting the header
  // information so we can get the PC offset of the output address.
  await Stream.fromIterable(output2.trace).transform(decoder).toList();
  final allocateObjectPCOffset2 =
      decoder.offsetOf(output2.allocateObjectAddress);
  final translatedDwarfTrace1 =
      await Stream.fromIterable(output1.trace).transform(decoder).toList();
  final allocateObjectPCOffset1 =
      decoder.offsetOf(output1.allocateObjectAddress);

  print('Offset of first stub address '
      '0x${output1.allocateObjectAddress.toRadixString(16)}'
      ' is $allocateObjectPCOffset1');
  print('Offset of second stub address '
      '0x${output2.allocateObjectAddress.toRadixString(16)}'
      ' is $allocateObjectPCOffset2');

  Expect.isNotNull(allocateObjectPCOffset1);
  Expect.isNotNull(allocateObjectPCOffset2);
  final allocateObjectRelocatedAddress1 =
      dwarf.virtualAddressOf(allocateObjectPCOffset1!);
  final allocateObjectRelocatedAddress2 =
      dwarf.virtualAddressOf(allocateObjectPCOffset2!);

  final allocateObjectCallInfo1 = dwarf.callInfoFor(
      allocateObjectRelocatedAddress1,
      includeInternalFrames: true);
  final allocateObjectCallInfo2 = dwarf.callInfoFor(
      allocateObjectRelocatedAddress2,
      includeInternalFrames: true);

  Expect.isNotNull(allocateObjectCallInfo1);
  Expect.isNotNull(allocateObjectCallInfo2);
  Expect.equals(allocateObjectCallInfo1!.length, 1);
  Expect.equals(allocateObjectCallInfo2!.length, 1);
  Expect.isTrue(
      allocateObjectCallInfo1.first is StubCallInfo, 'is not a StubCall');
  Expect.isTrue(
      allocateObjectCallInfo2.first is StubCallInfo, 'is not a StubCall');
  final stubCall1 = allocateObjectCallInfo1.first as StubCallInfo;
  final stubCall2 = allocateObjectCallInfo2.first as StubCallInfo;
  Expect.equals(stubCall1.name, stubCall2.name);
  Expect.contains('AllocateObject', stubCall1.name);
  Expect.contains('AllocateObject', stubCall2.name);

  print("Successfully matched AllocateObject stub addresses");
  print("");

  final translatedStackFrames = onlySymbolicFrameLines(translatedDwarfTrace1);
  final originalStackFrames = onlySymbolicFrameLines(nonDwarfTrace);

  print('Stack frames from translated non-symbolic stack trace:');
  translatedStackFrames.forEach(print);
  print('');

  print('Stack frames from original symbolic stack trace:');
  originalStackFrames.forEach(print);
  print('');

  Expect.isTrue(translatedStackFrames.length > 0);
  Expect.isTrue(originalStackFrames.length > 0);

  // In symbolic mode, we don't store column information to avoid an increase
  // in size of CodeStackMaps. Thus, we need to strip any columns from the
  // translated non-symbolic stack to compare them via equality.
  final columnStrippedTranslated = removeColumns(translatedStackFrames);

  print('Stack frames from translated non-symbolic stack trace, no columns:');
  columnStrippedTranslated.forEach(print);
  print('');

  Expect.deepEquals(columnStrippedTranslated, originalStackFrames);

  // Since we compiled directly to ELF, there should be a DSO base address
  // in the stack trace header and 'virt' markers in the stack frames.

  // The offsets of absolute addresses from their respective DSO base
  // should be the same for both traces.
  final dsoBase1 = dsoBaseAddresses(output1.trace).single;
  final dsoBase2 = dsoBaseAddresses(output2.trace).single;

  final absTrace1 = absoluteAddresses(output1.trace);
  final absTrace2 = absoluteAddresses(output2.trace);

  final relocatedFromDso1 = absTrace1.map((a) => a - dsoBase1);
  final relocatedFromDso2 = absTrace2.map((a) => a - dsoBase2);

  Expect.deepEquals(relocatedFromDso1, relocatedFromDso2);

  // We don't print 'virt' relocated addresses when running assembled snapshots.
  if (fromAssembly) return;

  // The relocated addresses marked with 'virt' should match between the
  // different runs, and they should also match the relocated address
  // calculated from the PCOffset for each frame as well as the relocated
  // address for each frame calculated using the respective DSO base.
  final virtTrace1 = explicitVirtualAddresses(output1.trace);
  final virtTrace2 = explicitVirtualAddresses(output2.trace);

  Expect.deepEquals(virtTrace1, virtTrace2);

  Expect.deepEquals(
      virtTrace1, tracePCOffsets1.map((o) => o.virtualAddressIn(dwarf)));
  Expect.deepEquals(
      virtTrace2, tracePCOffsets2.map((o) => o.virtualAddressIn(dwarf)));

  Expect.deepEquals(virtTrace1, relocatedFromDso1);
  Expect.deepEquals(virtTrace2, relocatedFromDso2);
}

Future<DwarfTestOutput> runTestProgram(
    String executable, List<String> args) async {
  final result = await runHelper(executable, args);

  if (result.exitCode == 0) {
    throw 'Command did not fail with non-zero exit code';
  }
  Expect.isTrue(result.stdout.isNotEmpty);
  Expect.isTrue(result.stderr.isNotEmpty);

  return DwarfTestOutput(
      LineSplitter.split(result.stderr).toList(), int.parse(result.stdout));
}

final _buildIdRE = RegExp(r"build_id: '([a-f\d]+)'");
String buildId(Iterable<String> lines) {
  for (final line in lines) {
    final match = _buildIdRE.firstMatch(line);
    if (match != null) {
      return match.group(1)!;
    }
  }
  return '';
}

final _symbolicFrameRE = RegExp(r'^#\d+\s+');

Iterable<String> onlySymbolicFrameLines(Iterable<String> lines) {
  return lines.where((line) => _symbolicFrameRE.hasMatch(line));
}

final _columnsRE = RegExp(r'[(](.*:\d+):\d+[)]');

Iterable<String> removeColumns(Iterable<String> lines) sync* {
  for (final line in lines) {
    final match = _columnsRE.firstMatch(line);
    if (match != null) {
      yield line.replaceRange(match.start, match.end, '(${match.group(1)!})');
    } else {
      yield line;
    }
  }
}

Iterable<int> parseUsingAddressRegExp(RegExp re, Iterable<String> lines) sync* {
  for (final line in lines) {
    final match = re.firstMatch(line);
    if (match != null) {
      yield int.parse(match.group(1)!, radix: 16);
    }
  }
}

final _absRE = RegExp(r'abs ([a-f\d]+)');

Iterable<int> absoluteAddresses(Iterable<String> lines) =>
    parseUsingAddressRegExp(_absRE, lines);

final _virtRE = RegExp(r'virt ([a-f\d]+)');

Iterable<int> explicitVirtualAddresses(Iterable<String> lines) =>
    parseUsingAddressRegExp(_virtRE, lines);

final _dsoBaseRE = RegExp(r'isolate_dso_base: ([a-f\d]+)');

Iterable<int> dsoBaseAddresses(Iterable<String> lines) =>
    parseUsingAddressRegExp(_dsoBaseRE, lines);
