Home | History | Annotate | Download | only in ltrace.main
      1 # This file is part of ltrace.
      2 # Copyright (C) 2014 Petr Machata, Red Hat Inc.
      3 # Copyright (C) 2006 Yao Qi <qiyao (at) cn.ibm.com>, IBM Corporation
      4 #
      5 # This program is free software; you can redistribute it and/or
      6 # modify it under the terms of the GNU General Public License as
      7 # published by the Free Software Foundation; either version 2 of the
      8 # License, or (at your option) any later version.
      9 #
     10 # This program is distributed in the hope that it will be useful, but
     11 # WITHOUT ANY WARRANTY; without even the implied warranty of
     12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13 # General Public License for more details.
     14 #
     15 # You should have received a copy of the GNU General Public License
     16 # along with this program; if not, write to the Free Software
     17 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
     18 # 02110-1301 USA
     19 
     20 # Objectives: Verify that Ltrace can trace all the system calls in
     21 # execution.  Note that this test is necessarily noisy.  Dynamic
     22 # linker adds a bunch of system calls of its own.
     23 
     24 set empty [ltraceCompile {} [ltraceSource c {
     25     int main (void) { return 0; }
     26 }]]
     27 
     28 set bin [ltraceCompile {} [ltraceSource c {
     29     #include <stdio.h>
     30     #include <unistd.h>
     31     #include <sys/syscall.h>
     32     #include <sys/stat.h>
     33     #include <errno.h>
     34     #include <stdlib.h>
     35 
     36     int
     37     main ()
     38     {
     39       FILE* fp;
     40       char s[]="system_calls";
     41       char buffer[1024];
     42       struct stat state;
     43 
     44       fp = fopen ("system_calls.tmp", "w");
     45       if (fp == NULL)
     46 	{
     47 	  printf("Can not create system_calls.tmp\n");
     48 	  exit (0);
     49 	}
     50       fwrite(s, sizeof(s), 1, fp);
     51       fseek (fp, 0, SEEK_CUR);
     52       fread(buffer, sizeof(s), 1, fp);
     53       fclose(fp);
     54 
     55       getcwd (buffer, sizeof buffer);
     56       chdir (".");
     57       symlink ("system_calls.tmp", "system_calls.link");
     58       remove("system_calls.link");
     59       rename ("system_calls.tmp", "system_calls.tmp1");
     60       stat ("system_calls.tmp", &state);
     61       access ("system_calls.tmp", R_OK);
     62       remove("system_calls.tmp1");
     63 
     64       mkdir ("system_call_mkdir", 0777);
     65       rmdir ("system_call_mkdir");
     66 
     67       return 0;
     68     }
     69 }]]
     70 
     71 proc Calls {logfile} {
     72     set fp [open $logfile]
     73     set ret {}
     74 
     75     while {[gets $fp line] >= 0} {
     76 	if [regexp -- {^[a-zA-Z0-9]*@SYS} $line] {
     77 	    set call [lindex [split $line @] 0]
     78 	    dict incr ret $call
     79 	}
     80     }
     81 
     82     close $fp
     83     return $ret
     84 }
     85 
     86 proc GetDefault {d key def} {
     87     if {[dict exists $d $key]} {
     88 	return [dict get $d $key]
     89     } else {
     90 	return $def
     91     }
     92 }
     93 
     94 proc Diff {d1 d2} {
     95     set keys [lsort -unique [concat [dict keys $d1] [dict keys $d2]]]
     96     set ret {}
     97     foreach key $keys {
     98 	set n1 [GetDefault $d1 $key 0]
     99 	set n2 [GetDefault $d2 $key 0]
    100 	set sum [expr $n1 - $n2]
    101 	if {[expr $sum != 0]} {
    102 		dict set ret $key $sum
    103 	}
    104     }
    105     return $ret
    106 }
    107 
    108 proc Match {d patterns} {
    109     foreach line $patterns {
    110 	set pattern [lindex $line 0]
    111 	set op [lindex $line 1]
    112 	set expect [lindex $line 2]
    113 
    114 	set count 0
    115 	foreach key [dict keys $d] {
    116 	    if [regexp -- $pattern $key] {
    117 		incr count [dict get $d $key]
    118 	    }
    119 	}
    120 
    121 	set msgMain "$pattern was recorded $count times"
    122 
    123 	if {[eval expr $count $op $expect]} {
    124 	    pass $msgMain
    125 	} else {
    126 	    fail "$msgMain, expected $op $expect"
    127 	}
    128     }
    129 }
    130 
    131 Match [Diff [Calls [ltraceRun -L -S -- $bin]] \
    132 	   [Calls [ltraceRun -L -S -- $empty]]] {
    133     { {^write$} == 1 }
    134     { {^unlink(at)?$} >= 2 }
    135     { {^open(at)?$} == 1 }
    136     { {^(new|f)?stat(64)?$} == 1 }
    137     { {^close$} == 1 }
    138     { {^getcwd$} == 1 }
    139     { {^chdir$} == 1 }
    140     { {^symlink(at)?$} == 1 }
    141     { {^f?access(at)?$} == 1 }
    142     { {^rename(at)?$} == 1 }
    143     { {^mkdir(at)?$} == 1 }
    144 }
    145 
    146 ltraceDone
    147