File: 901_memory.t

package info (click to toggle)
libconvert-binary-c-perl 0.85-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, trixie
  • size: 13,260 kB
  • sloc: ansic: 47,820; perl: 4,980; yacc: 2,143; makefile: 61
file content (127 lines) | stat: -rw-r--r-- 3,505 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
################################################################################
#
# Copyright (c) 2002-2024 Marcus Holland-Moritz. All rights reserved.
# This program is free software; you can redistribute it and/or modify
# it under the same terms as Perl itself.
#
################################################################################

use Test;
use Convert::Binary::C;

$^W = 1;

BEGIN {
  @files = grep /[1-4]\d{2}_[a-z]+\.t$/i, <tests/*.t>;
  plan tests => 1 + 9*@files
}

$debug = Convert::Binary::C::feature( 'debug' );
ok( defined $debug );

$dbfile = 'tests/debug.out';
$cmd  = "$^X -w " . join( ' ', map qq["-I$_"], @INC );
@args = ( debug => "m", debugfile => $dbfile );

for my $test ( @files ) {
  print "# testing '$test'\n";

  -e $dbfile and unlink $dbfile;

  if( $debug ) {
    open TEST, "$cmd $test @args |" or die $!;
    while(<TEST>){}
    close TEST;
  }

  my $exf = -e $dbfile ? 1 : 0;

  my $reason = $debug ? '' : 'no debugging';

  skip( $reason, $exf, 1, "dubious: no debug output file created" );

  my %i = $exf ? get_alloc_info( $dbfile ) : ();

  if( $exf ) {
    print "# results for '$test':\n";
    print "#   allocs      => $i{allocs} blocks\n";
    print "#   frees       => $i{frees} blocks\n";
    print "#   max. blocks => $i{max_blocks} blocks\n";
    print "#   max. memory => $i{max_total} bytes\n";
    print "#   leakage     => $i{leakage} bytes\n";
  }

  if( $debug and !$exf ) {
    $reason = 'no output file created';
  }

  skip( $reason, ($i{allocs} || 0) > 0, 1, "dubious: no memory allocations" );
  skip( $reason, $i{allocs}, $i{frees}, "malloc/free mismatch" );
  skip( $reason, $i{leakage}, 0, "memory leaks detected" );

  for( qw( multi_alloc null_free unalloc_free not_free assert_fail ) ) {
    print "# $_:\n";
    skip( $reason, exists $i{$_} ? @{$i{$_}} == 0 : 0 );
    $i{$_} && @{$i{$_}} or next;
    for( @{$i{$_}} ) { print "# $_\n" }
  }
}


sub get_alloc_info {
  my $file = shift;
  my %alloc;
  my %info = (
    allocs       => 0,
    frees        => 0,
    max_blocks   => 0,
    max_total    => 0,
    multi_alloc  => [],
    null_free    => [],
    unalloc_free => [],
    not_free     => [],
    assert_fail  => [],
  );
  my $count = 0;
  my $total = 0;

  open MEM, $file or die $!;
  while( <MEM> ) {
    /^(.*?):(A|F|V)=(?:(\d+)\@)?([0-9a-zA-Z]{8,})$/ or next;
    if( $2 eq 'A' ) {
      exists $alloc{$4} and
        push @{$info{multi_alloc}}, "0x$4 in $1 (previously allocated in $alloc{$4}[0])";
      next if exists $alloc{$4};
      $alloc{$4} = [$1,$3];
      $count++;
      $total += $3;
      $info{allocs}++;
      $info{min_size} = $info{max_size} = $3 unless exists $info{min_size};
      $info{min_size} = $3 if $3 < $info{min_size};
      $info{max_size} = $3 if $3 > $info{max_size};
    }
    elsif( $2 eq 'F' ) {
      $4 eq '00000000' and push @{$info{null_free}}, "0x$4 in $1";
      exists $alloc{$4} or push @{$info{unalloc_free}}, "0x$4 in $1";
      next unless exists $alloc{$4};
      $count--;
      $total -= $alloc{$4}[1];
      $info{frees}++;
      delete $alloc{$4};
    }
    else { # $2 eq 'V'
      exists $alloc{$4} or push @{$info{assert_fail}}, "0x$4 in $1";
      next; # nothing needs to be updated
    }
    $info{max_blocks} = $count if $count > $info{max_blocks};
    $info{max_total}  = $total if $total > $info{max_total};
  }
  close MEM;

  for( sort keys %alloc ) {
    push @{$info{not_free}}, "0x$_ in $alloc{$_}[0]";
  }

  $info{leakage} = $total;
  %info;
}