GraphQL-Houtou

 view release on metacpan or  search on metacpan

util/leak-check.pl  view on Meta::CPAN

use warnings;

use Cwd qw(abs_path getcwd);
use File::Basename qw(dirname);
use File::Path qw(make_path remove_tree);
use File::Spec;
use File::Temp qw(tempdir);
use Getopt::Long qw(GetOptions);
my @requested_cases;
my $build_dir;
my $keep_build_dir = 0;
my $help = 0;
my $backend = (($^O // '') eq 'darwin') ? 'leaks' : 'asan';

GetOptions(
  'case=s@' => \@requested_cases,
  'build-dir=s' => \$build_dir,
  'keep-build-dir!' => \$keep_build_dir,
  'backend=s' => \$backend,
  'help' => \$help,
) or usage(1);

usage(0) if $help;

my $repo_root = abs_path(File::Spec->catdir(dirname(abs_path($0)), File::Spec->updir));
my %cases = (
  parser_public => {
    description => 'public parser surface (canonical AST, block strings, errors)',
    command => [ qw(perl -Iblib/lib -Iblib/arch t/21_public_parser_api.t) ],
  },
  execution => {
    description => 'sync runtime execution coverage',
    command => [ qw(perl -Iblib/lib -Iblib/arch t/15_runtime_execute.t) ],
  },
  vm_execute => {
    description => 'native VM execution coverage',
    command => [ qw(perl -Iblib/lib -Iblib/arch t/19_vm_execute.t) ],
  },
  promise => {
    description => 'Promise::XS async execution coverage',
    command => [ qw(perl -Iblib/lib -Iblib/arch t/16_runtime_promise.t) ],
  },
  aliases => {
    description => 'field alias handling across execution lanes',
    command => [ qw(perl -Iblib/lib -Iblib/arch t/29_field_aliases.t) ],
  },
  persisted => {
    description => 'persisted program / bundle round trips',
    command => [ qw(perl -Iblib/lib -Iblib/arch t/22_persisted_queries.t) ],
  },
  oneof => {
    description => 'oneOf coercion including croaking error paths',
    command => [ qw(perl -Iblib/lib -Iblib/arch t/33_oneof_input_objects.t) ],
  },
  croak_safety => {
    description => 'escaped die recovery on the exec-state lane',
    command => [ qw(perl -Iblib/lib -Iblib/arch t/34_exec_state_croak_safety.t) ],
  },
  soak => {
    description => 'long-running worker RSS soak (short profile)',
    command => [ qw(perl -Iblib/lib -Iblib/arch util/soak-test.pl --iterations 3000 --warmup 1000) ],
  },
);

my @case_names = @requested_cases
  ? @requested_cases
  : qw(parser_public execution vm_execute promise aliases persisted oneof croak_safety soak);
for my $name (@case_names) {
  die "Unknown leak-check case: $name\n" unless exists $cases{$name};
}
die "Unknown backend: $backend\n" unless $backend eq 'asan' || $backend eq 'leaks';

$build_dir ||= tempdir('houtou-leak-check-XXXXXX', TMPDIR => 1, CLEANUP => !$keep_build_dir);
$build_dir = abs_path($build_dir);

stage_repo($repo_root, $build_dir);
build_copy($build_dir, $backend);

my @failures;
for my $name (@case_names) {
  my $result = run_case($build_dir, $name, $cases{$name});
  push @failures, $result if !$result->{ok};
}

say "";
say "Leak check summary:";
for my $name (@case_names) {
  my ($failure) = grep { $_->{name} eq $name } @failures;
  if ($failure) {
    say "  FAIL $name";
  } else {
    say "  PASS $name";
  }
}

say "Build directory kept at: $build_dir" if $keep_build_dir;

if (@failures) {
  say "";
  for my $failure (@failures) {
    say "Case $failure->{name} failed:";
    say $failure->{reason};
    say "Log: $failure->{log}";
    say "";
  }
  exit 1;
}

exit 0;

sub build_copy {
  my ($dir, $selected_backend) = @_;
  my @configure = qw(perl Build.PL);
  if ($selected_backend eq 'asan') {
    push @configure,
      q(--extra_compiler_flags=-O1 -g -fno-omit-frame-pointer -fsanitize=address),
      q(--extra_linker_flags=-fsanitize=address);
  }

  run_command(
    dir => $dir,



( run in 0.984 second using v1.01-cache-2.11-cpan-4ab04211f4c )