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

// This test checks that --resolve-dwarf-paths outputs absolute and relative
// paths in DWARF information.

// OtherResources=use_dwarf_stack_traces_flag_program.dart

import "dart:async";
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 {
    final cwDir = path.dirname(Platform.script.toFilePath());
    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,
    ]);

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

    // Run the resulting Dwarf-AOT compiled script.
    final dwarfTrace = await runError(aotRuntime, <String>[
      scriptDwarfSnapshot,
      scriptDill,
    ]);

    final tracePCOffsets = collectPCOffsets(dwarfTrace);

    // Check that translating the DWARF stack trace (without internal frames)
    // matches the symbolic stack trace.
    final dwarf = Dwarf.fromFile(scriptDwarfSnapshot);
    Expect.isNotNull(dwarf);
    checkDwarfInfo(dwarf!, tracePCOffsets);
  });
}

void checkDwarfInfo(Dwarf dwarf, Iterable<PCOffset> offsets) {
  final filenames = <String>{};
  for (final offset in offsets) {
    final callInfo = offset.callInfoFrom(dwarf);
    Expect.isNotNull(callInfo);
    Expect.isNotEmpty(callInfo!);
    for (final e in callInfo) {
      Expect.isTrue(e is DartCallInfo, 'Call is not from the Dart source: $e.');
      final entry = e as DartCallInfo;
      var filename = entry.filename;
      if (!filename.startsWith('/')) {
        filename = path.join(sdkDir, filename);
      }
      if (filenames.add(filename)) {
        Expect.isTrue(
            File(filename).existsSync(), 'File $filename does not exist.');
      }
    }
  }
  print('Checked filenames:');
  for (final filename in filenames) {
    print('- ${filename}');
  }
  Expect.isNotEmpty(filenames);
}
