// 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 AOT compiler can generate stripped versions of
// ELF and assembly output. This test is currently very weak, in that it just
// checks that the stripped version is strictly smaller than the unstripped one.

// OtherResources=use_save_debugging_info_flag_program.dart

import "dart:io";

import 'package:expect/expect.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 not available on the test device.
  }

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

  await withTempDir('strip-flag-test', (String tempDir) async {
    final cwDir = path.dirname(Platform.script.toFilePath());
    // We can just reuse the program for the use_save_debugging_info_flag test.
    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,
    ]);

    // Run the AOT compiler to generate stripped and unstripped ELF snapshots.
    final unstrippedSnapshot = path.join(tempDir, 'whole.so');
    await run(genSnapshot, <String>[
      '--snapshot-kind=app-aot-elf',
      '--elf=$unstrippedSnapshot',
      scriptDill,
    ]);

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

    compareStrippedAndUnstripped(
        stripped: strippedSnapshot, unstripped: unstrippedSnapshot);

    if (Platform.isWindows) {
      return; // No assembly generation on Windows.
    }

    final unstrippedCode = path.join(tempDir, 'whole.S');
    await run(genSnapshot, <String>[
      '--snapshot-kind=app-aot-assembly',
      '--assembly=$unstrippedCode',
      scriptDill,
    ]);

    final strippedCode = path.join(tempDir, 'stripped.S');
    await run(genSnapshot, <String>[
      '--snapshot-kind=app-aot-assembly',
      '--assembly=$strippedCode',
      '--strip',
      scriptDill,
    ]);

    compareStrippedAndUnstripped(
        stripped: strippedCode, unstripped: unstrippedCode);
  });
}

void compareStrippedAndUnstripped(
    {required String stripped, required String unstripped}) {
  final strippedSize = File(stripped).lengthSync();
  final unstrippedSize = File(unstripped).lengthSync();
  print("File size for stripped file $stripped: $strippedSize");
  print("File size for stripped file $unstripped: $unstrippedSize");
  Expect.isTrue(strippedSize < unstrippedSize);
}
