// Copyright (c) 2022, 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 checks that gen_snapshot outputs static symbols for read-only data
// objects.

// OtherResources=use_save_debugging_info_flag_program.dart

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

import 'package:expect/expect.dart';
import 'package:native_stack_traces/elf.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('readonly-symbols-flag-test', (String tempDir) async {
    final cwDir = path.dirname(Platform.script.toFilePath());
    final script =
        path.join(cwDir, 'use_save_debugging_info_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 scriptSnapshot = path.join(tempDir, 'dwarf.so');
    final scriptDebuggingInfo = path.join(tempDir, 'debug_info.so');
    await run(genSnapshot, <String>[
      '--dwarf-stack-traces-mode',
      '--save-debugging-info=$scriptDebuggingInfo',
      '--snapshot-kind=app-aot-elf',
      '--elf=$scriptSnapshot',
      scriptDill,
    ]);

    checkElf(scriptSnapshot);
    checkElf(scriptDebuggingInfo);
  });
}

void checkElf(String filename) {
  // Check that the static symbol table contains entries that are not in the
  // dynamic symbol table, have STB_LOCAL binding, and are of type STT_OBJECT.
  final elf = Elf.fromFile(filename);
  Expect.isNotNull(elf);
  final dynamicSymbols = elf.dynamicSymbols.toList();
  for (final symbol in dynamicSymbols) {
    // All symbol tables have an initial entry with zero-valued fields.
    if (symbol.name == '') {
      Expect.equals(SymbolBinding.STB_LOCAL, symbol.bind);
      Expect.equals(SymbolType.STT_NOTYPE, symbol.type);
      Expect.equals(0, symbol.value);
    } else {
      Expect.equals(SymbolBinding.STB_GLOBAL, symbol.bind);
      Expect.equals(SymbolType.STT_OBJECT, symbol.type);
      Expect.isTrue(symbol.name.startsWith('_kDart'),
          'unexpected symbol name ${symbol.name}');
    }
  }
  final onlyStaticSymbols = elf.staticSymbols
      .where((s1) => !dynamicSymbols.any((s2) => s1.name == s2.name));
  Expect.isNotEmpty(onlyStaticSymbols, 'no static-only symbols');
  final objectSymbols =
      onlyStaticSymbols.where((s) => s.type == SymbolType.STT_OBJECT);
  Expect.isNotEmpty(objectSymbols, 'no static-only object symbols');
  for (final symbol in objectSymbols) {
    // Currently we only write local object symbols.
    Expect.equals(SymbolBinding.STB_LOCAL, symbol.bind);
    // All object symbols are prefixed with the type of the C++ object.
    final objectType = symbol.name.substring(0, symbol.name.indexOf('_'));
    switch (objectType) {
      // Used for entries in the non-clustered portion of the read-only data
      // section that don't correspond to a specific Dart object.
      case 'RawBytes':
      // Currently the only types of objects written to the non-clustered
      // portion of the read-only data section.
      case 'OneByteString':
      case 'TwoByteString':
      case 'CodeSourceMap':
      case 'PcDescriptors':
      case 'CompressedStackMaps':
        break;
      default:
        Expect.fail('unexpected object type $objectType');
    }
  }
}
