// 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.

// @dart = 2.9

// 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);

    // Currently there are no appropriate buildtools on the simulator trybots as
    // normally they compile to ELF and don't need them for compiling assembly
    // snapshots.
    if ((Platform.isLinux || Platform.isMacOS) && !isSimulator) {
      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 allocateObjectInstructionsOffset;

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

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);

  if (tracePCOffsets1.isNotEmpty) {
    final exampleOffset = tracePCOffsets1.first;

    // We run the test program on the same host OS as the test, so any of the
    // PCOffsets above should have this information.
    Expect.isNotNull(exampleOffset.os);
    Expect.isNotNull(exampleOffset.architecture);
    Expect.isNotNull(exampleOffset.usingSimulator);
    Expect.isNotNull(exampleOffset.compressedPointers);

    Expect.equals(exampleOffset.os, Platform.operatingSystem);
    final archString = '${exampleOffset.usingSimulator ? 'SIM' : ''}'
        '${exampleOffset.architecture.toUpperCase()}'
        '${exampleOffset.compressedPointers ? 'C' : ''}';
    final baseBuildDir = path.basename(buildDir);
    Expect.isTrue(baseBuildDir.endsWith(archString),
        'Expected $baseBuildDir to end with $archString');
  }

  // 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);
  final translatedDwarfTrace1 =
      await Stream.fromIterable(output1.trace).transform(decoder).toList();

  final allocateObjectPCOffset1 = PCOffset(
      output1.allocateObjectInstructionsOffset, InstructionsSection.isolate);
  final allocateObjectPCOffset2 = PCOffset(
      output2.allocateObjectInstructionsOffset, InstructionsSection.isolate);

  print('Offset of first stub address is $allocateObjectPCOffset1');
  print('Offset of second stub address is $allocateObjectPCOffset2');

  final allocateObjectCallInfo1 = dwarf.callInfoForPCOffset(
      allocateObjectPCOffset1,
      includeInternalFrames: true);
  final allocateObjectCallInfo2 = dwarf.callInfoForPCOffset(
      allocateObjectPCOffset2,
      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);
