// 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 AOT compiler can generate debugging information
// for stripped ELF output, and that using the debugging information to look
// up stripped stack trace information matches the non-stripped version.

// OtherResources=use_dwarf_stack_traces_flag_program.dart

import "dart:io";
import "dart:math";
import "dart:typed_data";

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('save-debug-info-flag-test', (String tempDir) async {
    final cwDir = path.dirname(Platform.script.toFilePath());
    // We can just reuse the program for the use_dwarf_stack_traces test.
    final script = path.join(cwDir, '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 Dwarf stack traces, once without stripping,
    // once with stripping, and once with stripping and saving debugging
    // information.
    final scriptWholeSnapshot = path.join(tempDir, 'whole.so');
    await run(genSnapshot, <String>[
      '--dwarf-stack-traces',
      '--snapshot-kind=app-aot-elf',
      '--elf=$scriptWholeSnapshot',
      scriptDill,
    ]);

    final scriptStrippedOnlySnapshot = path.join(tempDir, 'stripped_only.so');
    await run(genSnapshot, <String>[
      '--dwarf-stack-traces',
      '--snapshot-kind=app-aot-elf',
      '--elf=$scriptStrippedOnlySnapshot',
      '--strip',
      scriptDill,
    ]);

    final scriptStrippedSnapshot = path.join(tempDir, 'stripped.so');
    final scriptDebuggingInfo = path.join(tempDir, 'debug.so');
    await run(genSnapshot, <String>[
      '--dwarf-stack-traces',
      '--snapshot-kind=app-aot-elf',
      '--elf=$scriptStrippedSnapshot',
      '--strip',
      '--save-debugging-info=$scriptDebuggingInfo',
      scriptDill,
    ]);

    // Run the resulting scripts, saving the stack traces.
    final wholeTrace = await runError(aotRuntime, <String>[
      scriptWholeSnapshot,
      scriptDill,
    ]);
    final wholeOffsets = collectPCOffsets(wholeTrace);

    final strippedOnlyTrace = await runError(aotRuntime, <String>[
      scriptStrippedOnlySnapshot,
      scriptDill,
    ]);
    final strippedOnlyOffsets = collectPCOffsets(strippedOnlyTrace);

    final strippedTrace = await runError(aotRuntime, <String>[
      scriptStrippedSnapshot,
      scriptDill,
    ]);
    final strippedOffsets = collectPCOffsets(strippedTrace);

    // The retrieved offsets should be the same for all runs.
    Expect.deepEquals(wholeOffsets, strippedOffsets);
    Expect.deepEquals(strippedOnlyOffsets, strippedOffsets);

    // Stripped output should not change when --save-debugging-info is used.
    compareSnapshots(scriptStrippedOnlySnapshot, scriptStrippedSnapshot);

    print('');
    print("Original stack trace:");
    strippedTrace.forEach(print);

    final debugDwarf = Dwarf.fromFile(scriptDebuggingInfo);
    final wholeDwarf = Dwarf.fromFile(scriptWholeSnapshot);

    final fromDebug = await Stream.fromIterable(strippedTrace)
        .transform(DwarfStackTraceDecoder(debugDwarf))
        .toList();
    print("\nStack trace converted using separate debugging info:");
    print(fromDebug.join('\n'));

    final fromWhole = await Stream.fromIterable(strippedTrace)
        .transform(DwarfStackTraceDecoder(wholeDwarf))
        .toList();
    print("\nStack trace converted using unstripped ELF file:");
    print(fromWhole.join('\n'));

    Expect.deepEquals(fromDebug, fromWhole);
  });
}

void compareSnapshots(String file1, String file2) {
  final bytes1 = File(file1).readAsBytesSync();
  final bytes2 = File(file2).readAsBytesSync();
  final diff = diffBinary(bytes1, bytes2);
  if (diff.isNotEmpty) {
    print("\nFound differences between $file1 and $file2:");
    printDiff(diff);
  }
  Expect.equals(bytes1.length, bytes2.length);
  Expect.equals(0, diff.length);
}

Map<int, List<int>> diffBinary(Uint8List bytes1, Uint8List bytes2) {
  final ret = Map<int, List<int>>();
  final len = min(bytes1.length, bytes2.length);
  for (var i = 0; i < len; i++) {
    if (bytes1[i] != bytes2[i]) {
      ret[i] = <int>[bytes1[i], bytes2[i]];
    }
  }
  if (bytes1.length > len) {
    for (var i = len; i < bytes1.length; i++) {
      ret[i] = <int>[bytes1[i], -1];
    }
  } else if (bytes2.length > len) {
    for (var i = len; i < bytes2.length; i++) {
      ret[i] = <int>[-1, bytes2[i]];
    }
  }
  return ret;
}

void printDiff(Map<int, List<int>> map, [int maxOutput = 100]) {
  int lines = 0;
  for (var index in map.keys) {
    final pair = map[index];
    if (pair[0] == -1) {
      print('$index: <>, ${pair[1]}');
      lines++;
    } else if (pair[1] == -1) {
      print('$index: ${pair[0]}, <>');
      lines++;
    } else {
      print('$index: ${pair[0]}, ${pair[1]}');
      lines++;
    }
    if (lines >= maxOutput) {
      return;
    }
  }
}
