From: Carl E. L. <ce...@li...> - 2012-08-20 18:48:27
|
OProfile testsuite, Add symbol checking functionality This patch adds additional testing and workload capability. The patch adds the capability to easily add a new workload specification and a list of symbols that should be present in the OProfile report. The testsuite runs each of the specified workloads with each of the event lists currently specified and then checks that each of the symbols for workload are found in the OProfile report. Signed-off-by: Carl Love <ce...@us...> --- testsuite/Makefile | 25 +++++++++++ testsuite/README | 8 ++++ testsuite/lib/op_workloads.exp | 32 ++++++++++++++ testsuite/lib/verify.exp | 19 ++++++++ .../oprofile-opcontrol/oprofile-opcontrol-run.exp | 34 ++++++++++++--- testsuite/oprofile-operf/oprofile-operf-run.exp | 50 ++++++++++++++-------- testsuite/workloads/memcpyt_src/Makefile | 23 ++++++++++ testsuite/workloads/memcpyt_src/memcpyt.c | 45 +++++++++++++++++++ testsuite/workloads/thread_src/Makefile | 23 ++++++++++ testsuite/workloads/thread_src/thread.c | 47 ++++++++++++++++++++ 10 files changed, 281 insertions(+), 25 deletions(-) create mode 100644 testsuite/Makefile create mode 100644 testsuite/lib/op_workloads.exp create mode 100644 testsuite/lib/verify.exp create mode 100644 testsuite/workloads/memcpyt_src/Makefile create mode 100644 testsuite/workloads/memcpyt_src/memcpyt.c create mode 100644 testsuite/workloads/thread_src/Makefile create mode 100644 testsuite/workloads/thread_src/thread.c diff --git a/testsuite/Makefile b/testsuite/Makefile new file mode 100644 index 0000000..aabc40f --- /dev/null +++ b/testsuite/Makefile @@ -0,0 +1,25 @@ +# Makefile +# Copyright (C) 2012 Carl Love, IBM +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# + +memcpyt: + cd workloads/memcpyt_src && $(MAKE) + cd workloads/thread_src && $(MAKE) + +clean: + rm workloads/memcpyt_src/memcpyt_bin + rm workloads/thread_src/thread_bin diff --git a/testsuite/README b/testsuite/README index 5bcb4fe..bed8ad3 100644 --- a/testsuite/README +++ b/testsuite/README @@ -2,6 +2,14 @@ This testsuite directory contains a simple testsuite to check the functionality of OProfile on the machine. The testsuite supports testing the previous user interface using opcontrol and the new operf interface. +The testsuite consists of several workloads. Each workload is run using +an architecture specific list of event sets. The OProfile report for +each workload run is then checked to make sure the expected symbols that +are specific to that workload are found in the profile report. + +Setting up the testsuite requires the workloads be compiled by typing +"make" in this directory. The workload executables can be "cleaned up" +by typing "make clean". Running the opcontrol OProfile testsuite requires the following: diff --git a/testsuite/lib/op_workloads.exp b/testsuite/lib/op_workloads.exp new file mode 100644 index 0000000..7183e31 --- /dev/null +++ b/testsuite/lib/op_workloads.exp @@ -0,0 +1,32 @@ + + +if {! [array exists op_workload_table]} { + array set op_workload_table {} +} + +# Make sure the workload binary name is unique and not a substring of the +# directory or the test to see if the symbol exists may find the symbol in +# the directory name not the executable. + +set op_workload_table(tcl) \ + { \ + {tclsh oprofile-operf/workload.tcl 5000} \ + {libtcl} \ + {/no-vmlinux} \ + } + +set op_workload_table(memcpy) \ + { \ + {workloads/memcpyt_src/memcpyt_bin} \ + {memcpyt_bin} \ + {main} \ + {/no-vmlinux} \ + } + +set op_workload_table(thread) \ + { \ + {workloads/thread_src/thread_bin} \ + {thread_bin} \ + {mythread} \ + {/no-vmlinux} \ + } diff --git a/testsuite/lib/verify.exp b/testsuite/lib/verify.exp new file mode 100644 index 0000000..c2e6729 --- /dev/null +++ b/testsuite/lib/verify.exp @@ -0,0 +1,19 @@ +proc verify_output { workload_table_entry } { + + set workload_spec $workload_table_entry + set max [llength $workload_spec] + + # Note, first entry in the workload spec is the name of the workload + # executable file. The following entries are the symbols contained in + # the binary file. + for {set index 1} {$index < $max} {incr index} { + set symbol [lindex $workload_spec $index] + set result [local_exec "opreport --symbols --long-filenames" "" "" 100 ] + + if { [regexp $symbol "$result" ]} { + pass "opreport contains symbol: $symbol" + } else { + fail "opreport does not contain symbol: $symbol" + } + } +} diff --git a/testsuite/oprofile-opcontrol/oprofile-opcontrol-run.exp b/testsuite/oprofile-opcontrol/oprofile-opcontrol-run.exp index 5edbb59..618dc88 100644 --- a/testsuite/oprofile-opcontrol/oprofile-opcontrol-run.exp +++ b/testsuite/oprofile-opcontrol/oprofile-opcontrol-run.exp @@ -19,6 +19,8 @@ load_lib "op_events.exp" load_lib "op_util.exp" +load_lib "op_workloads.exp" +load_lib "verify.exp" set op_daemon_running 0 @@ -232,13 +234,31 @@ proc op_daemon_stop {} { } proc op_daemon_cycle {ctrs} { - op_daemon_delete_any_samples $ctrs - op_daemon_start $ctrs - op_spin 5000 - op_daemon_flush - op_daemon_check_samples_exist $ctrs - op_daemon_stop - op_daemon_delete_any_samples $ctrs + global op_workload_table + + foreach entry [array name op_workload_table] { + print "op_daemon_cycle entry: $entry" + + set workload [lindex $op_workload_table($entry) 0] + print "op_daemon_cycle workload: $workload" + + op_daemon_delete_any_samples $ctrs + op_daemon_start $ctrs + + # run the workload +# op_spin 5000 + local_exec ${workload} "" "" 100 + + op_daemon_flush + op_daemon_check_samples_exist $ctrs + + op_daemon_stop + op_daemon_delete_any_samples $ctrs + + # verify the instersting symbols for this test are found in + # the output + verify_output $op_workload_table($entry) + } } proc op_check_daemon {} { diff --git a/testsuite/oprofile-operf/oprofile-operf-run.exp b/testsuite/oprofile-operf/oprofile-operf-run.exp index 868d698..f2ada9b 100644 --- a/testsuite/oprofile-operf/oprofile-operf-run.exp +++ b/testsuite/oprofile-operf/oprofile-operf-run.exp @@ -19,6 +19,8 @@ load_lib "op_events.exp" load_lib "op_util.exp" +load_lib "op_workloads.exp" +load_lib "verify.exp" set operf_version "" set operf_supported 0 @@ -62,29 +64,41 @@ proc oprofile-operf_get_version {} { } proc do_test {ctrs} { + global op_workload_table set ctr_opts {} set kernel 1 set user 1 set count 5000 - set workload "tclsh oprofile-operf/workload.tcl $count" - - set test "operf do test" - foreach ctr $ctrs { -# n - counter number, no longer used but didn't want to change specification format - set n [lindex $ctr 0] - set event [lindex $ctr 1] - set um [lindex $ctr 2] - set count [lindex $ctr 3] - append ctr_opts "${event}:${count}:${um}:${kernel}:${user}," - } - set cmd "operf --events ${ctr_opts} ${workload}" - set test $cmd + set name tcl + set entry $op_workload_table($name) + set workload [lindex $entry 0] + + foreach entry [array name op_workload_table] { + set workload [lindex $op_workload_table($entry) 0] + set test "operf do test" + set ctr_opts "" + + foreach ctr $ctrs { +# n - counter number, no longer used but didn't want to change specification format + set n [lindex $ctr 0] + set event [lindex $ctr 1] + set um [lindex $ctr 2] + set count [lindex $ctr 3] + append ctr_opts "${event}:${count}:${um}:${kernel}:${user}," + } + set cmd "operf --events ${ctr_opts} ${workload}" + set test $cmd - if {[lindex [local_exec $cmd "" "" 100] 0] == 0} { + if {[lindex [local_exec $cmd "" "" 100] 0] == 0} { pass $test - } else { + } else { fail $test + } + + # verify the instersting symbols for this test are found in + # the output + verify_output $op_workload_table($entry) } } @@ -97,10 +111,10 @@ proc operf_check_samples_exist {ctrs} { set n [lindex $ctr 0] set event [lindex $ctr 1] - verbose "running opreport --long-filenames event:$event" - set result [local_exec "opreport --long-filenames event:$event" "" "" 100 ] + verbose "running opreport --symbols --long-filenames event:$event" + set result [local_exec "opreport --symbols --long-filenames event:$event" "" "" 100 ] + if { [regexp "error:" "$result" ]} { -# if { [regexp "opreport error:" "$result" ]} fix check to match output fail "$test: {$event} created nonzero sample files" } else { pass "$test: {$event} created nonzero sample files" diff --git a/testsuite/workloads/memcpyt_src/Makefile b/testsuite/workloads/memcpyt_src/Makefile new file mode 100644 index 0000000..f88db6c --- /dev/null +++ b/testsuite/workloads/memcpyt_src/Makefile @@ -0,0 +1,23 @@ +# Makefile +# Copyright (C) 2012 Carl Love, IBM +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# + +# Make sure the workload binary name is unique and not a substring of the +# directory or the test to see if the symbol exists may find the symbol in +# the directory name not the executable. +memcpyt: memcpyt.c + gcc -g -o memcpyt_bin memcpyt.c diff --git a/testsuite/workloads/memcpyt_src/memcpyt.c b/testsuite/workloads/memcpyt_src/memcpyt.c new file mode 100644 index 0000000..f128190 --- /dev/null +++ b/testsuite/workloads/memcpyt_src/memcpyt.c @@ -0,0 +1,45 @@ +/* Makefile + * Copyright (C) 2012 IBM + + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <string.h> + +main() +{ + int j; + long a4k, b4k; + char a[8192], b[8192]; + int source_offset, dest_offset; + char *source_address, *dest_address; + int iterations, copy_length; + + iterations = 1000000000; + copy_length = 65; + source_offset = 3; + dest_offset = 7; + + a4k = (long)(a+4095) & 0xfff; + b4k = (long)(b+4095) & 0xfff; + a4k = (4095 - a4k) & 0xfff; + b4k = (4095 - b4k) & 0xfff; + + source_address=a+a4k+source_offset; + dest_address=b+b4k+dest_offset; + + for(j=0;j<iterations;j++) + memcpy(dest_address, source_address, copy_length); +} diff --git a/testsuite/workloads/thread_src/Makefile b/testsuite/workloads/thread_src/Makefile new file mode 100644 index 0000000..a7c5e36 --- /dev/null +++ b/testsuite/workloads/thread_src/Makefile @@ -0,0 +1,23 @@ +# Makefile +# Copyright (C) 2012 Carl Love, IBM +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# + +# Make sure the workload binary name is unique and not a substring of the +# directory or the test to see if the symbol exists may find the symbol in +# the directory name not the executable. +thread: thread.c + gcc -g -o thread_bin -pthread thread.c diff --git a/testsuite/workloads/thread_src/thread.c b/testsuite/workloads/thread_src/thread.c new file mode 100644 index 0000000..ae4eb70 --- /dev/null +++ b/testsuite/workloads/thread_src/thread.c @@ -0,0 +1,47 @@ +/* Makefile + * Copyright (C) 2012 IBM + + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <stdio.h> +#include <pthread.h> +#include <stdlib.h> + +#define N 300 +void* mythread(void* arg) +{ + int i,j,k; + long c; + for(i=0; i< N; i++) + for(j=0; j< N; j++) + for(k=0; k< N; k++) + c=i+j+k; + printf("In thread!\n"); + return NULL; +} +int main() +{ + pthread_t th; + + if ( pthread_create(&th,NULL,mythread,NULL)!=0) + { + printf("can not create thread,exit!\n"); + exit(0); + } + printf("main process!\n"); + sleep(3); + return 0; +} -- 1.7.12.rc1.22.gbfbf4d4 |
From: Carl E. L. <ce...@li...> - 2012-10-05 23:49:27
|
OProfile testsuite, Add symbol checking functionality This patch adds additional testing and workload capability. The patch adds the capability to easily add a new workload specification and a list of symbols that should be present in the OProfile report. The testsuite runs each of the specified workloads with each of the event lists currently specified. The output from opreport is checked to verify the workload symbols are found. Signed-off-by: Carl Love <ce...@us...> --- testsuite/README | 16 ++- testsuite/lib/op_events.exp | 5 + testsuite/lib/op_util.exp | 29 ++++ testsuite/lib/op_workloads.exp | 57 ++++++++ testsuite/lib/verify.exp | 25 ++++ .../oprofile-opcontrol/oprofile-opcontrol-run.exp | 60 +++++++-- testsuite/oprofile-operf/oprofile-operf-run.exp | 149 ++++++++++++--------- testsuite/workloads/memcpyt_src/memcpyt.c | 45 +++++++ testsuite/workloads/tcl_src/workload.tcl | 36 +++++ testsuite/workloads/thread_src/thread.c | 52 +++++++ 10 files changed, 394 insertions(+), 80 deletions(-) create mode 100644 testsuite/lib/op_workloads.exp create mode 100644 testsuite/lib/verify.exp create mode 100644 testsuite/workloads/memcpyt_src/memcpyt.c create mode 100644 testsuite/workloads/tcl_src/workload.tcl create mode 100644 testsuite/workloads/thread_src/thread.c diff --git a/testsuite/README b/testsuite/README index c8067b0..2b94e7b 100644 --- a/testsuite/README +++ b/testsuite/README @@ -2,6 +2,11 @@ This testsuite directory contains a simple testsuite to check the functionality of OProfile on the machine. The testsuite supports testing the previous user interface using opcontrol and the new operf interface. +The testsuite consists of several workloads. Each workload is run using +an architecture specific list of event sets. The OProfile report for +each workload run is then checked to make sure the expected symbols that +are specific to that workload are found in the profile report. + Running the opcontrol OProfile testsuite requires the following: @@ -15,20 +20,21 @@ following command: runtest --tool oprofile-opcontrol -The operf OProfile testsuite requires the following: +The system-wide operf OProfile testsuite requires the following: -Superuser privileges -The dejagnu and expect packages are installed -The OProfile commands to be on the PATH -The operf tests are run by being in this directory and running the following -command: +The system-wide operf tests are run by being in this directory and running +the following command: runtest --tool oprofile-operf -Both testsuites can be run at the sametime, provided you meet the requirement -for running OProfile opcontrol and the OPerf testsuites, with the command +The two testsuites can be run at the sametime, provided you meet the +requirement for running OProfile opcontrol and the OPerf testsuites, with +the command: runtest --tool oprofile diff --git a/testsuite/lib/op_events.exp b/testsuite/lib/op_events.exp index 41a90b5..b09f54e 100644 --- a/testsuite/lib/op_events.exp +++ b/testsuite/lib/op_events.exp @@ -132,6 +132,11 @@ set op_comprehensive_event_table(p4) \ # represents a single testcase. so in these CPUs there's 2 testcases per # CPU. it's not much, but then, that makes it somewhat easier to run and # less likely to fail. +# +# The symbol check test only uses the first event group when collecting data +# to check for a symbol. It is best that the first event group contain an +# event such as CYCLES or count instructions which will reliably collect +# a significant number of samples. set op_event_table(ppro) \ { \ diff --git a/testsuite/lib/op_util.exp b/testsuite/lib/op_util.exp index 6a74b3a..5b3a235 100644 --- a/testsuite/lib/op_util.exp +++ b/testsuite/lib/op_util.exp @@ -272,3 +272,32 @@ proc check_user {} { set user_is_root 0 } } + +proc compile_workload {workload_src compile_options } { + + # Ideally the TCL command target_compile should be used. However, + # target_compile is ignoring the compiler options argument. + + set compiler "cc" + set extension [lindex [split $workload_src "."] 1] + set workload_exc [ lindex [split $workload_src "."] 0]_bin + + if { [string compare $extension "c"] == 0 } { + # workload is a C program, see if it needs to be compiled. + set test [local_exec "ls $workload_exc" "" "" 10] + + if { [lindex $test 0] == 1 } { + # workload has not been compiled + set result [local_exec "$compiler -o $workload_exc $workload_src $compile_options" "" "" 10 ] + if { [lindex $result 0] == 1 } { + print "\nERROR compiling workload: $workload_src" + print "Compiler error message: $result\n" + } + } + return [ lindex [split $workload_src "."] 0]_bin + } + + # Assume the workload is a script, set the executable + # name to the same as the source name. + return $workload_src +} diff --git a/testsuite/lib/op_workloads.exp b/testsuite/lib/op_workloads.exp new file mode 100644 index 0000000..9ffb00a --- /dev/null +++ b/testsuite/lib/op_workloads.exp @@ -0,0 +1,57 @@ + + +if {! [array exists op_workload_table]} { + array set op_workload_table {} +} + +# Make sure the workload binary name is unique and not a substring of the +# directory or the test to see if the symbol exists may find the symbol in +# the directory name not the executable. +# +# The op_workload_table consists of three or more entries. The entries +# are as follows: +# +# First entry is the C code source file name for a program or +# the complete command to run the script if the workload is a script +# +# Second entry is any compile line options for a C program +# +# Remaining entries are symbols which should be found in the OProfile +# output +# +# Specifically the op_workload_table for C program foo.c that has the symbols +# foo, foo_symbol1 and foo_symbol2 in the binary file and is to be compiled +# with the "-O2" compiler option would be: +# +# set op_workload_table(foo) \ +# { \ +# { workloads/foo.c } \ +# { -O2 } \ +# { foo_symbol1 } \ +# { foo_symbol2 } \ +# { + +set op_workload_table(tcl) \ + { \ + {tclsh workloads/tcl_src/workload.tcl 50000 }\ + {} \ + {/bin/dd} \ + } + +set op_workload_table(memcpy) \ + { \ + {workloads/memcpyt_src/memcpyt.c} \ + {} \ + {memcpyt_bin} \ + {main} \ + {/no-vmlinux} \ + } + +set op_workload_table(thread) \ + { \ + {workloads/thread_src/thread.c} \ + {-pthread} \ + {thread_bin} \ + {mythread} \ + {/no-vmlinux} \ + } diff --git a/testsuite/lib/verify.exp b/testsuite/lib/verify.exp new file mode 100644 index 0000000..2faed80 --- /dev/null +++ b/testsuite/lib/verify.exp @@ -0,0 +1,25 @@ +proc verify_output { workload_table_entry workload ctr_opts} { + + set workload_spec $workload_table_entry + set max [llength $workload_spec] + + # Note, starting with the second entry in the workload spec is the name + # of the workload executable file. The following entries are additional + # symbols contained in the binary file. + for {set index 2} {$index < $max} {incr index} { + set symbol [lindex $workload_spec $index] + set result [local_exec "opreport --symbols --long-filenames" "" "" 100 ] + + if { [regexp $symbol "$result" ]} { + verbose "Verify the symbols for workload: $workload" + verbose " Performance counter events: $ctr_opts" + pass " opreport contains symbol: $symbol" + verbose "\n" + } else { + print "Verify the symbols for workload: $workload" + print " Performance counter events: $ctr_opts" + fail " opreport does not contain symbol: $symbol" + print "\n" + } + } +} diff --git a/testsuite/oprofile-opcontrol/oprofile-opcontrol-run.exp b/testsuite/oprofile-opcontrol/oprofile-opcontrol-run.exp index 935ca46..141c326 100644 --- a/testsuite/oprofile-opcontrol/oprofile-opcontrol-run.exp +++ b/testsuite/oprofile-opcontrol/oprofile-opcontrol-run.exp @@ -19,6 +19,8 @@ load_lib "op_events.exp" load_lib "op_util.exp" +load_lib "op_workloads.exp" +load_lib "verify.exp" set op_daemon_running 0 @@ -208,21 +210,55 @@ proc op_daemon_stop {} { local_exec "rm -f /root/.oprofile/daemonrc" "" "" 100 } -proc op_daemon_cycle {ctrs} { - op_daemon_delete_any_samples - op_daemon_start $ctrs - op_spin 5000 - op_daemon_flush - op_daemon_check_samples_exist $ctrs - op_daemon_stop - op_daemon_delete_any_samples +proc op_daemon_cycle {ctrs symbol_check} { + global op_workload_table + + foreach entry [array name op_workload_table] { + + set workload_src [lindex $op_workload_table($entry) 0] + set compile_options [lindex $op_workload_table($entry) 1] + set workload_exc [compile_workload $workload_src $compile_options] + + op_daemon_delete_any_samples + op_daemon_start $ctrs + + # run the workload + local_exec ${workload_exc} "" "" 100 + + op_daemon_flush + op_daemon_check_samples_exist $ctrs + + op_daemon_stop + + set ctr_opts {} + foreach ctr $ctrs { + set n [lindex $ctr 0] + set event [lindex $ctr 1] + set um [lindex $ctr 2] + set count [lindex $ctr 3] + append ctr_opts "{$n $event $um $count} " + } + + # Verify the interesting symbols for this test are found in + # the output. Only checking the symbols for the first group of + # events. + if {$symbol_check == 1} { + local_exec "sleep 2" "" "" 10 + verify_output $op_workload_table($entry) $workload_exc $ctr_opts + } + + op_daemon_delete_any_samples + } } proc op_check_daemon {} { global op_event_table set cpu [op_cpu_type] + set symbol_check 1 + foreach spec $op_event_table($cpu) { - op_daemon_cycle $spec + op_daemon_cycle $spec $symbol_check + set symbol_check 0 } } @@ -257,9 +293,11 @@ if {$user_is_root == 0} { send "OProfile is properly installed and the opcontrol command is \n" send "in the root's path. Will not run opcontrol tests.\n" } else { - # just to be paranoid and make sure there is no operf data that - # opreport might pickup by mistake, delete any existing operf data + # Just to be paranoid and make sure there is no operf or opcontrol + # data that opreport might pickup by mistake, delete any existing + # data. operf_delete_samples + op_daemon_delete_any_samples oprofile_start op_check_daemon diff --git a/testsuite/oprofile-operf/oprofile-operf-run.exp b/testsuite/oprofile-operf/oprofile-operf-run.exp index 9a8070f..b362d32 100644 --- a/testsuite/oprofile-operf/oprofile-operf-run.exp +++ b/testsuite/oprofile-operf/oprofile-operf-run.exp @@ -19,7 +19,8 @@ load_lib "op_events.exp" load_lib "op_util.exp" - +load_lib "op_workloads.exp" +load_lib "verify.exp" set operf_version "" @@ -46,7 +47,7 @@ proc operf_get_version {} { } } -proc do_test {ctrs} { +proc do_test {ctrs symbol_check} { # The tests are run in system-wide mode which requires the user to be # root. System-wide mode is being used to make the operf interface # testing as functionally equivalent to the opcontrol interface testing @@ -58,72 +59,87 @@ proc do_test {ctrs} { # operf. After the workload has run, a script is called to kill the # operf data collection processes. - set ctr_opts {} + global op_workload_table set kernel 1 set user 1 - set count 5000 - set test "operf do test" - foreach ctr $ctrs { -# n - counter number, no longer used but didn't want to change -# specification format - set n [lindex $ctr 0] - set event [lindex $ctr 1] - set um [lindex $ctr 2] - set count [lindex $ctr 3] - append ctr_opts "${event}:${count}:${um}:${kernel}:${user}," - } + foreach entry [array name op_workload_table] { + set workload_src [lindex $op_workload_table($entry) 0] + set compile_options [lindex $op_workload_table($entry) 1] + set test "operf do test" + set ctr_opts {} + + set workload_exc [compile_workload $workload_src $compile_options] + + foreach ctr $ctrs { +# n - counter number, no longer used but didn't want to change +# specification format + set n [lindex $ctr 0] + set event [lindex $ctr 1] + set um [lindex $ctr 2] + set count [lindex $ctr 3] + append ctr_opts "${event}:${count}:${um}:${kernel}:${user}," + } - # create the script to run operf command - set filename "/tmp/operf_run.zzzz" - set fileId [open $filename "w"] - puts $fileId "#!/bin/bash" - puts -nonewline $fileId "operf --system-wide --events " - puts -nonewline $fileId $ctr_opts - puts -nonewline $fileId " 2>&1 | tee > /tmp/operf_out.zzzz" - close $fileId - - local_exec "chmod 755 /tmp/operf_run.zzzz" "" "" 10 - - # Start operf data collection in the background - exec /tmp/operf_run.zzzz & - - # Create the script to stop the operf data collection. Note this - # must be done after operf starts and writes the kill command out to - # operf_out.zzzz. - set filename "/tmp/operf_create_stop.zzzz" - set fileId [open $filename "w"] - puts $fileId "#!/bin/bash" - puts $fileId "echo -n \"kill -s INT \" > /tmp/operf_stop.zzzz " - - # Get the process id to kill - puts $fileId "cat /tmp/operf_out.zzzz | grep \"kill\" | cut -d\"\'\" -f2 | cut -d\" \" -f3 >> /tmp/operf_stop.zzzz " - close $fileId - - # check that operf started correctly - if {[lindex [local_exec "grep \"usage\" /tmp/operf_out.zzzz " "" "" 100] 0] == 1} { - pass $test - } else { - fail $test - } + # create the script to run operf command + set filename "/tmp/operf_run.zzzz" + set fileId [open $filename "w"] + puts $fileId "#!/bin/bash" + puts -nonewline $fileId "operf --system-wide --events " + puts -nonewline $fileId $ctr_opts + puts -nonewline $fileId " 2>&1 | tee > /tmp/operf_out.zzzz" + close $fileId + + local_exec "chmod 755 /tmp/operf_run.zzzz" "" "" 10 + + # Start operf data collection in the background + exec /tmp/operf_run.zzzz & + + # Create the script to stop the operf data collection. Note this + # must be done after operf starts and writes the kill command out to + # operf_out.zzzz. + set filename "/tmp/operf_create_stop.zzzz" + set fileId [open $filename "w"] + puts $fileId "#!/bin/bash" + puts $fileId "echo -n \"kill -s INT \" > /tmp/operf_stop.zzzz " + + # Get the process id to kill + puts $fileId "cat /tmp/operf_out.zzzz | grep \"kill\" | cut -d\"\'\" -f2 | cut -d\" \" -f3 >> /tmp/operf_stop.zzzz " + close $fileId + + # check that operf started correctly + if {[lindex [local_exec "grep \"usage\" /tmp/operf_out.zzzz " "" "" 100] 0] == 1} { + pass $test + } else { + fail $test + } -# Run the script to create the operf stop script based on the -# output of the operf command. - local_exec "sleep 1" "" "" 10 - local_exec "chmod 755 /tmp/operf_create_stop.zzzz" "" "" 10 - exec /tmp/operf_create_stop.zzzz + # Run the script to create the operf stop script based on the + # output of the operf command. + local_exec "sleep 1" "" "" 10 + local_exec "chmod 755 /tmp/operf_create_stop.zzzz" "" "" 10 + exec /tmp/operf_create_stop.zzzz -# Run the workload - op_spin $count + # Run the workload + set result [local_exec "$workload_exc" "" "" 60] - local_exec "chmod 755 /tmp/operf_stop.zzzz" "" "" 10 - exec /tmp/operf_stop.zzzz + local_exec "chmod 755 /tmp/operf_stop.zzzz" "" "" 10 + exec /tmp/operf_stop.zzzz -# cleanup the files created - local_exec "rm -f /tmp/operf_out.zzzz" "" "" 10 - local_exec "rm -f /tmp/operf_stop.zzzz" "" "" 10 - local_exec "rm -f /tmp/operf_run.zzzz" "" "" 10 - local_exec "rm -f /tmp/operf_create_stop.zzzz" "" "" 10 + # Verify the interesting symbols for this test are found in + # the output. Only checking the symbols for the first group of + # events. + if {$symbol_check == 1} { + local_exec "sleep 2" "" "" 10 + verify_output $op_workload_table($entry) $workload_exc $ctr_opts + } + + # cleanup the files created + local_exec "rm -f /tmp/operf_out.zzzz" "" "" 10 + local_exec "rm -f /tmp/operf_stop.zzzz" "" "" 10 + local_exec "rm -f /tmp/operf_run.zzzz" "" "" 10 + local_exec "rm -f /tmp/operf_create_stop.zzzz" "" "" 10 + } } proc operf_check_samples_exist {ctrs} { @@ -135,8 +151,8 @@ proc operf_check_samples_exist {ctrs} { set n [lindex $ctr 0] set event [lindex $ctr 1] - verbose "running opreport --long-filenames event:$event" - set result [ local_exec "opreport --long-filenames event:$event" "" "" 100 ] + verbose "running opreport --symbols --long-filenames event:$event" + set result [ local_exec "opreport --symbols --long-filenames event:$event" "" "" 100 ] if { [regexp "error:" "$result" ]} { fail "$test: {$event} created nonzero sample files" } else { @@ -154,11 +170,16 @@ proc oprofile-operf_run_tests {} { } else { + set symbol_check 1 foreach spec $op_event_table($cpu) { - do_test $spec + # Just do the symbol check on the first event group. The + # assumption is the first event group contains cycles or count + # instructions which will reliably collect a lot of samples. + do_test $spec $symbol_check operf_check_samples_exist $spec + set symbol_check 0 + operf_delete_samples } - operf_delete_samples } } diff --git a/testsuite/workloads/memcpyt_src/memcpyt.c b/testsuite/workloads/memcpyt_src/memcpyt.c new file mode 100644 index 0000000..c3fc10d --- /dev/null +++ b/testsuite/workloads/memcpyt_src/memcpyt.c @@ -0,0 +1,45 @@ +/* memcpyt.c + * Copyright (C) 2012 IBM + + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <string.h> + +main() +{ + int j; + long a4k, b4k; + char a[8192], b[8192]; + int source_offset, dest_offset; + char *source_address, *dest_address; + int iterations, copy_length; + + iterations = 50000000; + copy_length = 65; + source_offset = 3; + dest_offset = 7; + + a4k = (long)(a+4095) & 0xfff; + b4k = (long)(b+4095) & 0xfff; + a4k = (4095 - a4k) & 0xfff; + b4k = (4095 - b4k) & 0xfff; + + source_address=a+a4k+source_offset; + dest_address=b+b4k+dest_offset; + + for(j=0;j<iterations;j++) + memcpy(dest_address, source_address, copy_length); +} diff --git a/testsuite/workloads/tcl_src/workload.tcl b/testsuite/workloads/tcl_src/workload.tcl new file mode 100644 index 0000000..78359db --- /dev/null +++ b/testsuite/workloads/tcl_src/workload.tcl @@ -0,0 +1,36 @@ +# workload.tcl +# Copyright (C) 2012 IBM + +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +if { $argc != 1 } { + set count 1000 +} else { + set count [lindex $argv 0] +} + +puts $count + +set j 23523 +set k 15431 +set m 73141 +set n 93802 +for {set i 0} {$i < $count} {incr i} { + set j [expr {($k * $m - ($n >> 2)) % 4294967296}] + set k [expr {($m + $n * ($j ^ $k)) % 4294967296}] + set m [expr {($n * $j - ($k << 2)) % 4294967296}] + set n [expr {($j + $k * ($m ^ $k)) % 4294967296}] +} +exec dd bs=16 if=/dev/urandom of=/dev/null count=$count diff --git a/testsuite/workloads/thread_src/thread.c b/testsuite/workloads/thread_src/thread.c new file mode 100644 index 0000000..b726658 --- /dev/null +++ b/testsuite/workloads/thread_src/thread.c @@ -0,0 +1,52 @@ +/* thread.c + * Copyright (C) 2012 IBM + + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <stdio.h> +#include <pthread.h> +#include <stdlib.h> + +#define N 300 + +void* mythread(void* arg) +{ + int i,j,k; + long c; + + printf("Thread start!\n"); + for(i=0; i< N; i++) + for(j=0; j< N; j++) + for(k=0; k< N; k++) + c=i+j+k; + printf("Thread done!\n"); + return NULL; +} +int main() +{ + pthread_t th; + + printf("main process start!\n"); + if ( pthread_create(&th,NULL,mythread,NULL)!=0) + { + printf("can not create thread,exit!\n"); + exit(0); + } + pthread_join(th, NULL); /* wait for thread */ + + printf("main process done!\n"); + return 0; +} -- 1.7.12.rc1.22.gbfbf4d4 |
From: Maynard J. <may...@us...> - 2012-10-08 13:50:21
|
On 10/05/2012 06:48 PM, Carl E. Love wrote: > OProfile testsuite, Add symbol checking functionality > > This patch adds additional testing and workload capability. The > patch adds the capability to easily add a new workload specification > and a list of symbols that should be present in the OProfile report. > The testsuite runs each of the specified workloads with each of the > event lists currently specified. The output from opreport is > checked to verify the workload symbols are found. Carl, Good stuff! Just a few comments. Please see below. Thanks. -Maynard > > Signed-off-by: Carl Love <ce...@us...> > --- > testsuite/README | 16 ++- > testsuite/lib/op_events.exp | 5 + > testsuite/lib/op_util.exp | 29 ++++ > testsuite/lib/op_workloads.exp | 57 ++++++++ > testsuite/lib/verify.exp | 25 ++++ > .../oprofile-opcontrol/oprofile-opcontrol-run.exp | 60 +++++++-- > testsuite/oprofile-operf/oprofile-operf-run.exp | 149 ++++++++++++--------- > testsuite/workloads/memcpyt_src/memcpyt.c | 45 +++++++ > testsuite/workloads/tcl_src/workload.tcl | 36 +++++ > testsuite/workloads/thread_src/thread.c | 52 +++++++ > 10 files changed, 394 insertions(+), 80 deletions(-) > create mode 100644 testsuite/lib/op_workloads.exp > create mode 100644 testsuite/lib/verify.exp > create mode 100644 testsuite/workloads/memcpyt_src/memcpyt.c > create mode 100644 testsuite/workloads/tcl_src/workload.tcl > create mode 100644 testsuite/workloads/thread_src/thread.c > > diff --git a/testsuite/README b/testsuite/README > index c8067b0..2b94e7b 100644 > --- a/testsuite/README > +++ b/testsuite/README > @@ -2,6 +2,11 @@ This testsuite directory contains a simple testsuite to check the > functionality of OProfile on the machine. The testsuite supports testing > the previous user interface using opcontrol and the new operf interface. > > +The testsuite consists of several workloads. Each workload is run using > +an architecture specific list of event sets. The OProfile report for > +each workload run is then checked to make sure the expected symbols that > +are specific to that workload are found in the profile report. > + > > Running the opcontrol OProfile testsuite requires the following: > > @@ -15,20 +20,21 @@ following command: > runtest --tool oprofile-opcontrol > > > -The operf OProfile testsuite requires the following: > +The system-wide operf OProfile testsuite requires the following: > > -Superuser privileges > -The dejagnu and expect packages are installed > -The OProfile commands to be on the PATH > > -The operf tests are run by being in this directory and running the following > -command: > +The system-wide operf tests are run by being in this directory and running > +the following command: > > runtest --tool oprofile-operf > > > -Both testsuites can be run at the sametime, provided you meet the requirement > -for running OProfile opcontrol and the OPerf testsuites, with the command > +The two testsuites can be run at the sametime, provided you meet the > +requirement for running OProfile opcontrol and the OPerf testsuites, with > +the command: The phrase "at the sametime" is a bit ambiguous. How about rephrasing this sentence thusly: "To run both oprontrol and operf testsuites (provided the requirements for both are met), use the command:" > > runtest --tool oprofile > > diff --git a/testsuite/lib/op_events.exp b/testsuite/lib/op_events.exp > index 41a90b5..b09f54e 100644 > --- a/testsuite/lib/op_events.exp > +++ b/testsuite/lib/op_events.exp > @@ -132,6 +132,11 @@ set op_comprehensive_event_table(p4) \ > # represents a single testcase. so in these CPUs there's 2 testcases per > # CPU. it's not much, but then, that makes it somewhat easier to run and > # less likely to fail. > +# > +# The symbol check test only uses the first event group when collecting data > +# to check for a symbol. It is best that the first event group contain an > +# event such as CYCLES or count instructions which will reliably collect > +# a significant number of samples. > > set op_event_table(ppro) \ > { \ > diff --git a/testsuite/lib/op_util.exp b/testsuite/lib/op_util.exp > index 6a74b3a..5b3a235 100644 > --- a/testsuite/lib/op_util.exp > +++ b/testsuite/lib/op_util.exp > @@ -272,3 +272,32 @@ proc check_user {} { > set user_is_root 0 > } > } > + > +proc compile_workload {workload_src compile_options } { > + > + # Ideally the TCL command target_compile should be used. However, > + # target_compile is ignoring the compiler options argument. > + > + set compiler "cc" > + set extension [lindex [split $workload_src "."] 1] > + set workload_exc [ lindex [split $workload_src "."] 0]_bin > + > + if { [string compare $extension "c"] == 0 } { > + # workload is a C program, see if it needs to be compiled. > + set test [local_exec "ls $workload_exc" "" "" 10] > + > + if { [lindex $test 0] == 1 } { > + # workload has not been compiled > + set result [local_exec "$compiler -o $workload_exc $workload_src $compile_options" "" "" 10 ] > + if { [lindex $result 0] == 1 } { > + print "\nERROR compiling workload: $workload_src" > + print "Compiler error message: $result\n" > + } > + } > + return [ lindex [split $workload_src "."] 0]_bin > + } > + > + # Assume the workload is a script, set the executable > + # name to the same as the source name. > + return $workload_src > +} > diff --git a/testsuite/lib/op_workloads.exp b/testsuite/lib/op_workloads.exp > new file mode 100644 > index 0000000..9ffb00a > --- /dev/null > +++ b/testsuite/lib/op_workloads.exp > @@ -0,0 +1,57 @@ > + > + > +if {! [array exists op_workload_table]} { > + array set op_workload_table {} > +} > + > +# Make sure the workload binary name is unique and not a substring of the > +# directory or the test to see if the symbol exists may find the symbol in > +# the directory name not the executable. > +# > +# The op_workload_table consists of three or more entries. The entries > +# are as follows: > +# > +# First entry is the C code source file name for a program or > +# the complete command to run the script if the workload is a script > +# > +# Second entry is any compile line options for a C program > +# > +# Remaining entries are symbols which should be found in the OProfile > +# output > +# > +# Specifically the op_workload_table for C program foo.c that has the symbols > +# foo, foo_symbol1 and foo_symbol2 in the binary file and is to be compiled > +# with the "-O2" compiler option would be: > +# > +# set op_workload_table(foo) \ > +# { \ > +# { workloads/foo.c } \ > +# { -O2 } \ > +# { foo_symbol1 } \ > +# { foo_symbol2 } \ > +# { > + > +set op_workload_table(tcl) \ > + { \ > + {tclsh workloads/tcl_src/workload.tcl 50000 }\ > + {} \ > + {/bin/dd} \ > + } > + > +set op_workload_table(memcpy) \ > + { \ > + {workloads/memcpyt_src/memcpyt.c} \ > + {} \ > + {memcpyt_bin} \ > + {main} \ > + {/no-vmlinux} \ If config/unix.exp:oprofile_start finds a vmlinux file (e.g., the SLES /boot/vmlinux-<version> file or the RHEL debuginfo vmlinux file), then the "/no-vmlinux" symbol won't be found, and the test will fail. > + } > + > +set op_workload_table(thread) \ > + { \ > + {workloads/thread_src/thread.c} \ > + {-pthread} \ > + {thread_bin} \ > + {mythread} \ > + {/no-vmlinux} \ Ditto above remark. > + } > diff --git a/testsuite/lib/verify.exp b/testsuite/lib/verify.exp > new file mode 100644 > index 0000000..2faed80 > --- /dev/null > +++ b/testsuite/lib/verify.exp > @@ -0,0 +1,25 @@ > +proc verify_output { workload_table_entry workload ctr_opts} { > + > + set workload_spec $workload_table_entry > + set max [llength $workload_spec] > + > + # Note, starting with the second entry in the workload spec is the name > + # of the workload executable file. The following entries are additional > + # symbols contained in the binary file. > + for {set index 2} {$index < $max} {incr index} { > + set symbol [lindex $workload_spec $index] > + set result [local_exec "opreport --symbols --long-filenames" "" "" 100 ] > + > + if { [regexp $symbol "$result" ]} { > + verbose "Verify the symbols for workload: $workload" > + verbose " Performance counter events: $ctr_opts" > + pass " opreport contains symbol: $symbol" > + verbose "\n" > + } else { > + print "Verify the symbols for workload: $workload" > + print " Performance counter events: $ctr_opts" > + fail " opreport does not contain symbol: $symbol" > + print "\n" > + } > + } > +} > diff --git a/testsuite/oprofile-opcontrol/oprofile-opcontrol-run.exp b/testsuite/oprofile-opcontrol/oprofile-opcontrol-run.exp > index 935ca46..141c326 100644 > --- a/testsuite/oprofile-opcontrol/oprofile-opcontrol-run.exp > +++ b/testsuite/oprofile-opcontrol/oprofile-opcontrol-run.exp > @@ -19,6 +19,8 @@ > > load_lib "op_events.exp" > load_lib "op_util.exp" > +load_lib "op_workloads.exp" > +load_lib "verify.exp" > > set op_daemon_running 0 > > @@ -208,21 +210,55 @@ proc op_daemon_stop {} { > local_exec "rm -f /root/.oprofile/daemonrc" "" "" 100 > } > > -proc op_daemon_cycle {ctrs} { > - op_daemon_delete_any_samples > - op_daemon_start $ctrs > - op_spin 5000 > - op_daemon_flush > - op_daemon_check_samples_exist $ctrs > - op_daemon_stop > - op_daemon_delete_any_samples > +proc op_daemon_cycle {ctrs symbol_check} { > + global op_workload_table > + > + foreach entry [array name op_workload_table] { > + > + set workload_src [lindex $op_workload_table($entry) 0] > + set compile_options [lindex $op_workload_table($entry) 1] > + set workload_exc [compile_workload $workload_src $compile_options] > + > + op_daemon_delete_any_samples The samples are deleted once, before entering this proc, again in the line above, and thirdly, at the end of the "foreach entry [array name op_workload_table]" loop. I suggest removing the above line. The sample deletion at the end of the loop is good to have, since it not only removes the sample data in preparation for the next loop, it also removes the sample data for the case when we're finished (and don't want to leave any test data sitting around). > + op_daemon_start $ctrs > + > + # run the workload > + local_exec ${workload_exc} "" "" 100 > + > + op_daemon_flush > + op_daemon_check_samples_exist $ctrs > + > + op_daemon_stop > + > + set ctr_opts {} > + foreach ctr $ctrs { > + set n [lindex $ctr 0] > + set event [lindex $ctr 1] > + set um [lindex $ctr 2] > + set count [lindex $ctr 3] > + append ctr_opts "{$n $event $um $count} " > + } The above foreach loop need only be done once -- before the beginning of the "foreach entry [array name op_workload_table]" loop. > + > + # Verify the interesting symbols for this test are found in > + # the output. Only checking the symbols for the first group of > + # events. > + if {$symbol_check == 1} { > + local_exec "sleep 2" "" "" 10 > + verify_output $op_workload_table($entry) $workload_exc $ctr_opts > + } > + > + op_daemon_delete_any_samples > + } > } > > proc op_check_daemon {} { > global op_event_table > set cpu [op_cpu_type] > + set symbol_check 1 > + > foreach spec $op_event_table($cpu) { > - op_daemon_cycle $spec > + op_daemon_cycle $spec $symbol_check > + set symbol_check 0 > } > } > > @@ -257,9 +293,11 @@ if {$user_is_root == 0} { > send "OProfile is properly installed and the opcontrol command is \n" > send "in the root's path. Will not run opcontrol tests.\n" > } else { > - # just to be paranoid and make sure there is no operf data that > - # opreport might pickup by mistake, delete any existing operf data > + # Just to be paranoid and make sure there is no operf or opcontrol > + # data that opreport might pickup by mistake, delete any existing > + # data. > operf_delete_samples > + op_daemon_delete_any_samples > > oprofile_start > op_check_daemon > diff --git a/testsuite/oprofile-operf/oprofile-operf-run.exp b/testsuite/oprofile-operf/oprofile-operf-run.exp > index 9a8070f..b362d32 100644 > --- a/testsuite/oprofile-operf/oprofile-operf-run.exp > +++ b/testsuite/oprofile-operf/oprofile-operf-run.exp > @@ -19,7 +19,8 @@ > > load_lib "op_events.exp" > load_lib "op_util.exp" > - > +load_lib "op_workloads.exp" > +load_lib "verify.exp" > > set operf_version "" > > @@ -46,7 +47,7 @@ proc operf_get_version {} { > } > } > > -proc do_test {ctrs} { > +proc do_test {ctrs symbol_check} { > # The tests are run in system-wide mode which requires the user to be > # root. System-wide mode is being used to make the operf interface > # testing as functionally equivalent to the opcontrol interface testing > @@ -58,72 +59,87 @@ proc do_test {ctrs} { > # operf. After the workload has run, a script is called to kill the > # operf data collection processes. > > - set ctr_opts {} > + global op_workload_table > set kernel 1 > set user 1 > - set count 5000 > > - set test "operf do test" > - foreach ctr $ctrs { > -# n - counter number, no longer used but didn't want to change > -# specification format > - set n [lindex $ctr 0] > - set event [lindex $ctr 1] > - set um [lindex $ctr 2] > - set count [lindex $ctr 3] > - append ctr_opts "${event}:${count}:${um}:${kernel}:${user}," > - } > + foreach entry [array name op_workload_table] { > + set workload_src [lindex $op_workload_table($entry) 0] > + set compile_options [lindex $op_workload_table($entry) 1] > + set test "operf do test" > + set ctr_opts {} > + > + set workload_exc [compile_workload $workload_src $compile_options] > + > + foreach ctr $ctrs { > +# n - counter number, no longer used but didn't want to change > +# specification format > + set n [lindex $ctr 0] > + set event [lindex $ctr 1] > + set um [lindex $ctr 2] > + set count [lindex $ctr 3] > + append ctr_opts "${event}:${count}:${um}:${kernel}:${user}," > + } As with the opcontrol test, the above foreach loop need only be done once -- before the beginning of the "foreach entry [array name op_workload_table]" loop. > > - # create the script to run operf command > - set filename "/tmp/operf_run.zzzz" > - set fileId [open $filename "w"] > - puts $fileId "#!/bin/bash" > - puts -nonewline $fileId "operf --system-wide --events " > - puts -nonewline $fileId $ctr_opts > - puts -nonewline $fileId " 2>&1 | tee > /tmp/operf_out.zzzz" > - close $fileId > - > - local_exec "chmod 755 /tmp/operf_run.zzzz" "" "" 10 > - > - # Start operf data collection in the background > - exec /tmp/operf_run.zzzz & > - > - # Create the script to stop the operf data collection. Note this > - # must be done after operf starts and writes the kill command out to > - # operf_out.zzzz. > - set filename "/tmp/operf_create_stop.zzzz" > - set fileId [open $filename "w"] > - puts $fileId "#!/bin/bash" > - puts $fileId "echo -n \"kill -s INT \" > /tmp/operf_stop.zzzz " > - > - # Get the process id to kill > - puts $fileId "cat /tmp/operf_out.zzzz | grep \"kill\" | cut -d\"\'\" -f2 | cut -d\" \" -f3 >> /tmp/operf_stop.zzzz " > - close $fileId > - > - # check that operf started correctly > - if {[lindex [local_exec "grep \"usage\" /tmp/operf_out.zzzz " "" "" 100] 0] == 1} { > - pass $test > - } else { > - fail $test > - } > + # create the script to run operf command > + set filename "/tmp/operf_run.zzzz" > + set fileId [open $filename "w"] > + puts $fileId "#!/bin/bash" > + puts -nonewline $fileId "operf --system-wide --events " > + puts -nonewline $fileId $ctr_opts > + puts -nonewline $fileId " 2>&1 | tee > /tmp/operf_out.zzzz" > + close $fileId > + > + local_exec "chmod 755 /tmp/operf_run.zzzz" "" "" 10 > + > + # Start operf data collection in the background > + exec /tmp/operf_run.zzzz & > + > + # Create the script to stop the operf data collection. Note this > + # must be done after operf starts and writes the kill command out to > + # operf_out.zzzz. > + set filename "/tmp/operf_create_stop.zzzz" > + set fileId [open $filename "w"] > + puts $fileId "#!/bin/bash" > + puts $fileId "echo -n \"kill -s INT \" > /tmp/operf_stop.zzzz " > + > + # Get the process id to kill > + puts $fileId "cat /tmp/operf_out.zzzz | grep \"kill\" | cut -d\"\'\" -f2 | cut -d\" \" -f3 >> /tmp/operf_stop.zzzz " > + close $fileId > + > + # check that operf started correctly > + if {[lindex [local_exec "grep \"usage\" /tmp/operf_out.zzzz " "" "" 100] 0] == 1} { > + pass $test > + } else { > + fail $test > + } > > -# Run the script to create the operf stop script based on the > -# output of the operf command. > - local_exec "sleep 1" "" "" 10 > - local_exec "chmod 755 /tmp/operf_create_stop.zzzz" "" "" 10 > - exec /tmp/operf_create_stop.zzzz > + # Run the script to create the operf stop script based on the > + # output of the operf command. > + local_exec "sleep 1" "" "" 10 > + local_exec "chmod 755 /tmp/operf_create_stop.zzzz" "" "" 10 > + exec /tmp/operf_create_stop.zzzz > > -# Run the workload > - op_spin $count > + # Run the workload > + set result [local_exec "$workload_exc" "" "" 60] > > - local_exec "chmod 755 /tmp/operf_stop.zzzz" "" "" 10 > - exec /tmp/operf_stop.zzzz > + local_exec "chmod 755 /tmp/operf_stop.zzzz" "" "" 10 > + exec /tmp/operf_stop.zzzz > > -# cleanup the files created > - local_exec "rm -f /tmp/operf_out.zzzz" "" "" 10 > - local_exec "rm -f /tmp/operf_stop.zzzz" "" "" 10 > - local_exec "rm -f /tmp/operf_run.zzzz" "" "" 10 > - local_exec "rm -f /tmp/operf_create_stop.zzzz" "" "" 10 > + # Verify the interesting symbols for this test are found in > + # the output. Only checking the symbols for the first group of > + # events. > + if {$symbol_check == 1} { > + local_exec "sleep 2" "" "" 10 > + verify_output $op_workload_table($entry) $workload_exc $ctr_opts > + } > + > + # cleanup the files created > + local_exec "rm -f /tmp/operf_out.zzzz" "" "" 10 > + local_exec "rm -f /tmp/operf_stop.zzzz" "" "" 10 > + local_exec "rm -f /tmp/operf_run.zzzz" "" "" 10 > + local_exec "rm -f /tmp/operf_create_stop.zzzz" "" "" 10 > + } You call operf_delete_samples two times: once before starting any tests and again at the end of the foreach loop of the oprofile-operf_run_tests proc. You don't remove sample data in between workload tests, which I think you should do. If you add a call to operf_delete_samples at the end of your "foreach entry [array name op_workload_table]" loop, then the deletion in oprofile-operf_run_tests becomes superfluous (and can be removed). > } > > proc operf_check_samples_exist {ctrs} { > @@ -135,8 +151,8 @@ proc operf_check_samples_exist {ctrs} { > set n [lindex $ctr 0] > set event [lindex $ctr 1] > > - verbose "running opreport --long-filenames event:$event" > - set result [ local_exec "opreport --long-filenames event:$event" "" "" 100 ] > + verbose "running opreport --symbols --long-filenames event:$event" > + set result [ local_exec "opreport --symbols --long-filenames event:$event" "" "" 100 ] > if { [regexp "error:" "$result" ]} { > fail "$test: {$event} created nonzero sample files" > } else { > @@ -154,11 +170,16 @@ proc oprofile-operf_run_tests {} { > > } else { > > + set symbol_check 1 > foreach spec $op_event_table($cpu) { > - do_test $spec > + # Just do the symbol check on the first event group. The > + # assumption is the first event group contains cycles or count > + # instructions which will reliably collect a lot of samples. > + do_test $spec $symbol_check > operf_check_samples_exist $spec > + set symbol_check 0 > + operf_delete_samples > } > - operf_delete_samples > } > } > > diff --git a/testsuite/workloads/memcpyt_src/memcpyt.c b/testsuite/workloads/memcpyt_src/memcpyt.c > new file mode 100644 > index 0000000..c3fc10d > --- /dev/null > +++ b/testsuite/workloads/memcpyt_src/memcpyt.c > @@ -0,0 +1,45 @@ > +/* memcpyt.c > + * Copyright (C) 2012 IBM > + > + * This file is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation; either version 2 of the License, or > + * (at your option) any later version. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program; if not, write to the Free Software > + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. > + */ > + > +#include <string.h> > + > +main() > +{ > + int j; > + long a4k, b4k; > + char a[8192], b[8192]; > + int source_offset, dest_offset; > + char *source_address, *dest_address; > + int iterations, copy_length; > + > + iterations = 50000000; > + copy_length = 65; > + source_offset = 3; > + dest_offset = 7; > + > + a4k = (long)(a+4095) & 0xfff; > + b4k = (long)(b+4095) & 0xfff; > + a4k = (4095 - a4k) & 0xfff; > + b4k = (4095 - b4k) & 0xfff; > + > + source_address=a+a4k+source_offset; > + dest_address=b+b4k+dest_offset; > + > + for(j=0;j<iterations;j++) > + memcpy(dest_address, source_address, copy_length); > +} > diff --git a/testsuite/workloads/tcl_src/workload.tcl b/testsuite/workloads/tcl_src/workload.tcl > new file mode 100644 > index 0000000..78359db > --- /dev/null > +++ b/testsuite/workloads/tcl_src/workload.tcl > @@ -0,0 +1,36 @@ > +# workload.tcl > +# Copyright (C) 2012 IBM > + > +# This file is free software; you can redistribute it and/or modify > +# it under the terms of the GNU General Public License as published by > +# the Free Software Foundation; either version 2 of the License, or > +# (at your option) any later version. > +# > +# This program is distributed in the hope that it will be useful, > +# but WITHOUT ANY WARRANTY; without even the implied warranty of > +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > +# GNU General Public License for more details. > +# > +# You should have received a copy of the GNU General Public License > +# along with this program; if not, write to the Free Software > +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. > + > +if { $argc != 1 } { > + set count 1000 > +} else { > + set count [lindex $argv 0] > +} > + > +puts $count > + > +set j 23523 > +set k 15431 > +set m 73141 > +set n 93802 > +for {set i 0} {$i < $count} {incr i} { > + set j [expr {($k * $m - ($n >> 2)) % 4294967296}] > + set k [expr {($m + $n * ($j ^ $k)) % 4294967296}] > + set m [expr {($n * $j - ($k << 2)) % 4294967296}] > + set n [expr {($j + $k * ($m ^ $k)) % 4294967296}] > +} > +exec dd bs=16 if=/dev/urandom of=/dev/null count=$count > diff --git a/testsuite/workloads/thread_src/thread.c b/testsuite/workloads/thread_src/thread.c > new file mode 100644 > index 0000000..b726658 > --- /dev/null > +++ b/testsuite/workloads/thread_src/thread.c > @@ -0,0 +1,52 @@ > +/* thread.c > + * Copyright (C) 2012 IBM > + > + * This file is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation; either version 2 of the License, or > + * (at your option) any later version. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program; if not, write to the Free Software > + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. > + */ > + > +#include <stdio.h> > +#include <pthread.h> > +#include <stdlib.h> > + > +#define N 300 > + > +void* mythread(void* arg) > +{ > + int i,j,k; > + long c; > + > + printf("Thread start!\n"); > + for(i=0; i< N; i++) > + for(j=0; j< N; j++) > + for(k=0; k< N; k++) > + c=i+j+k; > + printf("Thread done!\n"); > + return NULL; > +} > +int main() > +{ > + pthread_t th; > + > + printf("main process start!\n"); > + if ( pthread_create(&th,NULL,mythread,NULL)!=0) > + { > + printf("can not create thread,exit!\n"); > + exit(0); > + } > + pthread_join(th, NULL); /* wait for thread */ > + > + printf("main process done!\n"); > + return 0; > +} |
From: Carl E. L. <ce...@li...> - 2012-10-08 21:10:56
|
On Mon, 2012-10-08 at 08:49 -0500, Maynard Johnson wrote: > On 10/05/2012 06:48 PM, Carl E. Love wrote: > > OProfile testsuite, Add symbol checking functionality <snip>runtest --tool oprofile > > > > -Both testsuites can be run at the sametime, provided you meet the requirement > > -for running OProfile opcontrol and the OPerf testsuites, with the command > > +The two testsuites can be run at the sametime, provided you meet the > > +requirement for running OProfile opcontrol and the OPerf testsuites, with > > +the command: > The phrase "at the sametime" is a bit ambiguous. How about rephrasing this sentence thusly: > "To run both oprontrol and operf testsuites (provided the requirements for both are met), use the command:" OK, works for me. <snip> > > +# > > +# Specifically the op_workload_table for C program foo.c that has the symbols > > +# foo, foo_symbol1 and foo_symbol2 in the binary file and is to be compiled > > +# with the "-O2" compiler option would be: > > +# > > +# set op_workload_table(foo) \ > > +# { \ > > +# { workloads/foo.c } \ > > +# { -O2 } \ > > +# { foo_symbol1 } \ > > +# { foo_symbol2 } \ > > +# { > > + > > +set op_workload_table(tcl) \ > > + { \ > > + {tclsh workloads/tcl_src/workload.tcl 50000 }\ > > + {} \ > > + {/bin/dd} \ > > + } > > + > > +set op_workload_table(memcpy) \ > > + { \ > > + {workloads/memcpyt_src/memcpyt.c} \ > > + {} \ > > + {memcpyt_bin} \ > > + {main} \ > > + {/no-vmlinux} \ > If config/unix.exp:oprofile_start finds a vmlinux file (e.g., the SLES /boot/vmlinux-<version> > file or the RHEL debuginfo vmlinux file), then the "/no-vmlinux" symbol won't be found, and the > test will fail. Fixed > > + } > > + > > +set op_workload_table(thread) \ > > + { \ > > + {workloads/thread_src/thread.c} \ > > + {-pthread} \ > > + {thread_bin} \ > > + {mythread} \ > > + {/no-vmlinux} \ > Ditto above remark. OK, removed no-vmlinux from the two lists of events. <snip> > > + > > + foreach entry [array name op_workload_table] { > > + > > + set workload_src [lindex $op_workload_table($entry) 0] > > + set compile_options [lindex $op_workload_table($entry) 1] > > + set workload_exc [compile_workload $workload_src $compile_options] > > + > > + op_daemon_delete_any_samples > The samples are deleted once, before entering this proc, again in the line above, and thirdly, > at the end of the "foreach entry [array name op_workload_table]" loop. I suggest removing the > above line. The sample deletion at the end of the loop is good to have, since it not only removes > the sample data in preparation for the next loop, it also removes the sample data for the case when > we're finished (and don't want to leave any test data sitting around). Agreed the above delete can be removed. Done. > > + op_daemon_start $ctrs > > + > > + # run the workload > > + local_exec ${workload_exc} "" "" 100 > > + > > + op_daemon_flush > > + op_daemon_check_samples_exist $ctrs > > + > > + op_daemon_stop > > + > > + set ctr_opts {} > > + foreach ctr $ctrs { > > + set n [lindex $ctr 0] > > + set event [lindex $ctr 1] > > + set um [lindex $ctr 2] > > + set count [lindex $ctr 3] > > + append ctr_opts "{$n $event $um $count} " > > + } > The above foreach loop need only be done once -- before the beginning of the "foreach entry > [array name op_workload_table]" loop. Agreed, moved up as suggested. <snip> > > > > -proc do_test {ctrs} { > > +proc do_test {ctrs symbol_check} { > > # The tests are run in system-wide mode which requires the user to be > > # root. System-wide mode is being used to make the operf interface > > # testing as functionally equivalent to the opcontrol interface testing > > @@ -58,72 +59,87 @@ proc do_test {ctrs} { > > # operf. After the workload has run, a script is called to kill the > > # operf data collection processes. > > > > - set ctr_opts {} > > + global op_workload_table > > set kernel 1 > > set user 1 > > - set count 5000 > > > > - set test "operf do test" > > - foreach ctr $ctrs { > > -# n - counter number, no longer used but didn't want to change > > -# specification format > > - set n [lindex $ctr 0] > > - set event [lindex $ctr 1] > > - set um [lindex $ctr 2] > > - set count [lindex $ctr 3] > > - append ctr_opts "${event}:${count}:${um}:${kernel}:${user}," > > - } > > + foreach entry [array name op_workload_table] { > > + set workload_src [lindex $op_workload_table($entry) 0] > > + set compile_options [lindex $op_workload_table($entry) 1] > > + set test "operf do test" > > + set ctr_opts {} > > + > > + set workload_exc [compile_workload $workload_src $compile_options] > > + > > + foreach ctr $ctrs { > > +# n - counter number, no longer used but didn't want to change > > +# specification format > > + set n [lindex $ctr 0] > > + set event [lindex $ctr 1] > > + set um [lindex $ctr 2] > > + set count [lindex $ctr 3] > > + append ctr_opts "${event}:${count}:${um}:${kernel}:${user}," > > + } > As with the opcontrol test, the above foreach loop need only be done once -- before the beginning of > the "foreach entry [array name op_workload_table]" loop. Agreed, can be moved up. <snip> > > > > -# cleanup the files created > > - local_exec "rm -f /tmp/operf_out.zzzz" "" "" 10 > > - local_exec "rm -f /tmp/operf_stop.zzzz" "" "" 10 > > - local_exec "rm -f /tmp/operf_run.zzzz" "" "" 10 > > - local_exec "rm -f /tmp/operf_create_stop.zzzz" "" "" 10 > > + # Verify the interesting symbols for this test are found in > > + # the output. Only checking the symbols for the first group of > > + # events. > > + if {$symbol_check == 1} { > > + local_exec "sleep 2" "" "" 10 > > + verify_output $op_workload_table($entry) $workload_exc $ctr_opts > > + } > > + > > + # cleanup the files created > > + local_exec "rm -f /tmp/operf_out.zzzz" "" "" 10 > > + local_exec "rm -f /tmp/operf_stop.zzzz" "" "" 10 > > + local_exec "rm -f /tmp/operf_run.zzzz" "" "" 10 > > + local_exec "rm -f /tmp/operf_create_stop.zzzz" "" "" 10 > > + } > You call operf_delete_samples two times: once before starting any tests and again at the end of the > foreach loop of the oprofile-operf_run_tests proc. You don't remove sample data in between workload > tests, which I think you should do. If you add a call to operf_delete_samples at the end of your > "foreach entry [array name op_workload_table]" loop, then the deletion in oprofile-operf_run_tests > becomes superfluous (and can be removed). I agree, just one complication. The check that samples exist (operf_check_samples_exist) is done in the caller (oprofile-operf_run_tests) to this procedure. So, the symbol exists check was moved to this routine right before the symbol check. Then the call to delete samples (operf_delete_samples) was added right after the file cleanup. With those changes, the delete samples call (operf_delete_samples) from the caller (oprofile-operf_run_tests) was removed as suggested. The updated patch ---------------------------------------------------------------------------------------------- >From aa9276574dd02cefe6d8102e1d2620eae0b8355d Mon Sep 17 00:00:00 2001 From: Carl Love <ce...@us...> Date: Fri, 5 Oct 2012 12:46:20 -0500 Subject: [PATCH] OProfile testsuite, Add symbol checking functionality This patch adds additional testing and workload capability. The patch adds the capability to easily add a new workload specification and a list of symbols that should be present in the OProfile report. The testsuite runs each of the specified workloads with each of the event lists currently specified. The output from opreport is checked to verify the workload symbols are found. Signed-off-by: Carl Love <ce...@us...> --- testsuite/README | 15 ++- testsuite/lib/op_events.exp | 5 + testsuite/lib/op_util.exp | 29 +++++ testsuite/lib/op_workloads.exp | 55 +++++++++ testsuite/lib/verify.exp | 25 ++++ .../oprofile-opcontrol/oprofile-opcontrol-run.exp | 59 +++++++-- testsuite/oprofile-operf/oprofile-operf-run.exp | 134 ++++++++++++--------- testsuite/workloads/memcpyt_src/memcpyt.c | 45 +++++++ testsuite/workloads/tcl_src/workload.tcl | 36 ++++++ testsuite/workloads/thread_src/thread.c | 52 ++++++++ 10 files changed, 383 insertions(+), 72 deletions(-) create mode 100644 testsuite/lib/op_workloads.exp create mode 100644 testsuite/lib/verify.exp create mode 100644 testsuite/workloads/memcpyt_src/memcpyt.c create mode 100644 testsuite/workloads/tcl_src/workload.tcl create mode 100644 testsuite/workloads/thread_src/thread.c diff --git a/testsuite/README b/testsuite/README index c8067b0..ce35e08 100644 --- a/testsuite/README +++ b/testsuite/README @@ -2,6 +2,11 @@ This testsuite directory contains a simple testsuite to check the functionality of OProfile on the machine. The testsuite supports testing the previous user interface using opcontrol and the new operf interface. +The testsuite consists of several workloads. Each workload is run using +an architecture specific list of event sets. The OProfile report for +each workload run is then checked to make sure the expected symbols that +are specific to that workload are found in the profile report. + Running the opcontrol OProfile testsuite requires the following: @@ -15,20 +20,20 @@ following command: runtest --tool oprofile-opcontrol -The operf OProfile testsuite requires the following: +The system-wide operf OProfile testsuite requires the following: -Superuser privileges -The dejagnu and expect packages are installed -The OProfile commands to be on the PATH -The operf tests are run by being in this directory and running the following -command: +The system-wide operf tests are run by being in this directory and running +the following command: runtest --tool oprofile-operf -Both testsuites can be run at the sametime, provided you meet the requirement -for running OProfile opcontrol and the OPerf testsuites, with the command +To run both oprontrol and operf testsuites (provided the requirements for +both are met), use the command runtest --tool oprofile diff --git a/testsuite/lib/op_events.exp b/testsuite/lib/op_events.exp index 41a90b5..b09f54e 100644 --- a/testsuite/lib/op_events.exp +++ b/testsuite/lib/op_events.exp @@ -132,6 +132,11 @@ set op_comprehensive_event_table(p4) \ # represents a single testcase. so in these CPUs there's 2 testcases per # CPU. it's not much, but then, that makes it somewhat easier to run and # less likely to fail. +# +# The symbol check test only uses the first event group when collecting data +# to check for a symbol. It is best that the first event group contain an +# event such as CYCLES or count instructions which will reliably collect +# a significant number of samples. set op_event_table(ppro) \ { \ diff --git a/testsuite/lib/op_util.exp b/testsuite/lib/op_util.exp index 6a74b3a..5b3a235 100644 --- a/testsuite/lib/op_util.exp +++ b/testsuite/lib/op_util.exp @@ -272,3 +272,32 @@ proc check_user {} { set user_is_root 0 } } + +proc compile_workload {workload_src compile_options } { + + # Ideally the TCL command target_compile should be used. However, + # target_compile is ignoring the compiler options argument. + + set compiler "cc" + set extension [lindex [split $workload_src "."] 1] + set workload_exc [ lindex [split $workload_src "."] 0]_bin + + if { [string compare $extension "c"] == 0 } { + # workload is a C program, see if it needs to be compiled. + set test [local_exec "ls $workload_exc" "" "" 10] + + if { [lindex $test 0] == 1 } { + # workload has not been compiled + set result [local_exec "$compiler -o $workload_exc $workload_src $compile_options" "" "" 10 ] + if { [lindex $result 0] == 1 } { + print "\nERROR compiling workload: $workload_src" + print "Compiler error message: $result\n" + } + } + return [ lindex [split $workload_src "."] 0]_bin + } + + # Assume the workload is a script, set the executable + # name to the same as the source name. + return $workload_src +} diff --git a/testsuite/lib/op_workloads.exp b/testsuite/lib/op_workloads.exp new file mode 100644 index 0000000..45f6b16 --- /dev/null +++ b/testsuite/lib/op_workloads.exp @@ -0,0 +1,55 @@ + + +if {! [array exists op_workload_table]} { + array set op_workload_table {} +} + +# Make sure the workload binary name is unique and not a substring of the +# directory or the test to see if the symbol exists may find the symbol in +# the directory name not the executable. +# +# The op_workload_table consists of three or more entries. The entries +# are as follows: +# +# First entry is the C code source file name for a program or +# the complete command to run the script if the workload is a script +# +# Second entry is any compile line options for a C program +# +# Remaining entries are symbols which should be found in the OProfile +# output +# +# Specifically the op_workload_table for C program foo.c that has the symbols +# foo, foo_symbol1 and foo_symbol2 in the binary file and is to be compiled +# with the "-O2" compiler option would be: +# +# set op_workload_table(foo) \ +# { \ +# { workloads/foo.c } \ +# { -O2 } \ +# { foo_symbol1 } \ +# { foo_symbol2 } \ +# { + +set op_workload_table(tcl) \ + { \ + {tclsh workloads/tcl_src/workload.tcl 150000}\ + {} \ + {/bin/dd} \ + } + +set op_workload_table(memcpy) \ + { \ + {workloads/memcpyt_src/memcpyt.c} \ + {} \ + {memcpyt_bin} \ + {main} \ + } + +set op_workload_table(thread) \ + { \ + {workloads/thread_src/thread.c} \ + {-pthread} \ + {thread_bin} \ + {mythread} \ + } diff --git a/testsuite/lib/verify.exp b/testsuite/lib/verify.exp new file mode 100644 index 0000000..2faed80 --- /dev/null +++ b/testsuite/lib/verify.exp @@ -0,0 +1,25 @@ +proc verify_output { workload_table_entry workload ctr_opts} { + + set workload_spec $workload_table_entry + set max [llength $workload_spec] + + # Note, starting with the second entry in the workload spec is the name + # of the workload executable file. The following entries are additional + # symbols contained in the binary file. + for {set index 2} {$index < $max} {incr index} { + set symbol [lindex $workload_spec $index] + set result [local_exec "opreport --symbols --long-filenames" "" "" 100 ] + + if { [regexp $symbol "$result" ]} { + verbose "Verify the symbols for workload: $workload" + verbose " Performance counter events: $ctr_opts" + pass " opreport contains symbol: $symbol" + verbose "\n" + } else { + print "Verify the symbols for workload: $workload" + print " Performance counter events: $ctr_opts" + fail " opreport does not contain symbol: $symbol" + print "\n" + } + } +} diff --git a/testsuite/oprofile-opcontrol/oprofile-opcontrol-run.exp b/testsuite/oprofile-opcontrol/oprofile-opcontrol-run.exp index 935ca46..ae87b18 100644 --- a/testsuite/oprofile-opcontrol/oprofile-opcontrol-run.exp +++ b/testsuite/oprofile-opcontrol/oprofile-opcontrol-run.exp @@ -19,6 +19,8 @@ load_lib "op_events.exp" load_lib "op_util.exp" +load_lib "op_workloads.exp" +load_lib "verify.exp" set op_daemon_running 0 @@ -50,6 +52,7 @@ proc op_daemon_check_samples_exist {ctrs} { set test "nonzero-sized sample file creation" if {$op_daemon_running == 0} { +print "op_daemon_check_samples_exist, op_daemon not running as expected" unsupported $test return } @@ -208,21 +211,53 @@ proc op_daemon_stop {} { local_exec "rm -f /root/.oprofile/daemonrc" "" "" 100 } -proc op_daemon_cycle {ctrs} { - op_daemon_delete_any_samples - op_daemon_start $ctrs - op_spin 5000 - op_daemon_flush - op_daemon_check_samples_exist $ctrs - op_daemon_stop - op_daemon_delete_any_samples +proc op_daemon_cycle {ctrs symbol_check} { + global op_workload_table + + set ctr_opts {} + foreach ctr $ctrs { + set n [lindex $ctr 0] + set event [lindex $ctr 1] + set um [lindex $ctr 2] + set count [lindex $ctr 3] + append ctr_opts "{$n $event $um $count} " + } + + foreach entry [array name op_workload_table] { + + set workload_src [lindex $op_workload_table($entry) 0] + set compile_options [lindex $op_workload_table($entry) 1] + set workload_exc [compile_workload $workload_src $compile_options] + + op_daemon_start $ctrs + + # run the workload + local_exec ${workload_exc} "" "" 100 + + op_daemon_flush + op_daemon_check_samples_exist $ctrs + op_daemon_stop + + # Verify the interesting symbols for this test are found in + # the output. Only checking the symbols for the first group of + # events. + if {$symbol_check == 1} { + local_exec "sleep 2" "" "" 10 + verify_output $op_workload_table($entry) $workload_exc $ctr_opts + } + + op_daemon_delete_any_samples + } } proc op_check_daemon {} { global op_event_table set cpu [op_cpu_type] + set symbol_check 1 + foreach spec $op_event_table($cpu) { - op_daemon_cycle $spec + op_daemon_cycle $spec $symbol_check + set symbol_check 0 } } @@ -257,9 +292,11 @@ if {$user_is_root == 0} { send "OProfile is properly installed and the opcontrol command is \n" send "in the root's path. Will not run opcontrol tests.\n" } else { - # just to be paranoid and make sure there is no operf data that - # opreport might pickup by mistake, delete any existing operf data + # Just to be paranoid and make sure there is no operf or opcontrol + # data that opreport might pickup by mistake, delete any existing + # data. operf_delete_samples + op_daemon_delete_any_samples oprofile_start op_check_daemon diff --git a/testsuite/oprofile-operf/oprofile-operf-run.exp b/testsuite/oprofile-operf/oprofile-operf-run.exp index 9a8070f..5993daa 100644 --- a/testsuite/oprofile-operf/oprofile-operf-run.exp +++ b/testsuite/oprofile-operf/oprofile-operf-run.exp @@ -19,7 +19,8 @@ load_lib "op_events.exp" load_lib "op_util.exp" - +load_lib "op_workloads.exp" +load_lib "verify.exp" set operf_version "" @@ -46,7 +47,7 @@ proc operf_get_version {} { } } -proc do_test {ctrs} { +proc do_test {ctrs symbol_check} { # The tests are run in system-wide mode which requires the user to be # root. System-wide mode is being used to make the operf interface # testing as functionally equivalent to the opcontrol interface testing @@ -58,12 +59,11 @@ proc do_test {ctrs} { # operf. After the workload has run, a script is called to kill the # operf data collection processes. - set ctr_opts {} + global op_workload_table set kernel 1 set user 1 - set count 5000 + set ctr_opts {} - set test "operf do test" foreach ctr $ctrs { # n - counter number, no longer used but didn't want to change # specification format @@ -74,56 +74,75 @@ proc do_test {ctrs} { append ctr_opts "${event}:${count}:${um}:${kernel}:${user}," } - # create the script to run operf command - set filename "/tmp/operf_run.zzzz" - set fileId [open $filename "w"] - puts $fileId "#!/bin/bash" - puts -nonewline $fileId "operf --system-wide --events " - puts -nonewline $fileId $ctr_opts - puts -nonewline $fileId " 2>&1 | tee > /tmp/operf_out.zzzz" - close $fileId - - local_exec "chmod 755 /tmp/operf_run.zzzz" "" "" 10 - - # Start operf data collection in the background - exec /tmp/operf_run.zzzz & - - # Create the script to stop the operf data collection. Note this - # must be done after operf starts and writes the kill command out to - # operf_out.zzzz. - set filename "/tmp/operf_create_stop.zzzz" - set fileId [open $filename "w"] - puts $fileId "#!/bin/bash" - puts $fileId "echo -n \"kill -s INT \" > /tmp/operf_stop.zzzz " - - # Get the process id to kill - puts $fileId "cat /tmp/operf_out.zzzz | grep \"kill\" | cut -d\"\'\" -f2 | cut -d\" \" -f3 >> /tmp/operf_stop.zzzz " - close $fileId - - # check that operf started correctly - if {[lindex [local_exec "grep \"usage\" /tmp/operf_out.zzzz " "" "" 100] 0] == 1} { - pass $test - } else { - fail $test - } + foreach entry [array name op_workload_table] { + set workload_src [lindex $op_workload_table($entry) 0] + set compile_options [lindex $op_workload_table($entry) 1] + set test "operf do test" + + set workload_exc [compile_workload $workload_src $compile_options] + + # create the script to run operf command + set filename "/tmp/operf_run.zzzz" + set fileId [open $filename "w"] + puts $fileId "#!/bin/bash" + puts -nonewline $fileId "operf --system-wide --events " + puts -nonewline $fileId $ctr_opts + puts -nonewline $fileId " 2>&1 | tee > /tmp/operf_out.zzzz" + close $fileId + + local_exec "chmod 755 /tmp/operf_run.zzzz" "" "" 10 + + # Start operf data collection in the background + exec /tmp/operf_run.zzzz & + + # Create the script to stop the operf data collection. Note this + # must be done after operf starts and writes the kill command out to + # operf_out.zzzz. + set filename "/tmp/operf_create_stop.zzzz" + set fileId [open $filename "w"] + puts $fileId "#!/bin/bash" + puts $fileId "echo -n \"kill -s INT \" > /tmp/operf_stop.zzzz " + + # Get the process id to kill + puts $fileId "cat /tmp/operf_out.zzzz | grep \"kill\" | cut -d\"\'\" -f2 | cut -d\" \" -f3 >> /tmp/operf_stop.zzzz " + close $fileId + + # check that operf started correctly + if {[lindex [local_exec "grep \"usage\" /tmp/operf_out.zzzz " "" "" 100] 0] == 1} { + pass $test + } else { + fail $test + } + + # Run the script to create the operf stop script based on the + # output of the operf command. + local_exec "sleep 2" "" "" 10 + local_exec "chmod 755 /tmp/operf_create_stop.zzzz" "" "" 10 + exec /tmp/operf_create_stop.zzzz -# Run the script to create the operf stop script based on the -# output of the operf command. - local_exec "sleep 1" "" "" 10 - local_exec "chmod 755 /tmp/operf_create_stop.zzzz" "" "" 10 - exec /tmp/operf_create_stop.zzzz + # Run the workload + set result [local_exec "$workload_exc" "" "" 60] -# Run the workload - op_spin $count + local_exec "chmod 755 /tmp/operf_stop.zzzz" "" "" 10 + exec /tmp/operf_stop.zzzz - local_exec "chmod 755 /tmp/operf_stop.zzzz" "" "" 10 - exec /tmp/operf_stop.zzzz + operf_check_samples_exist $ctrs + + # Verify the interesting symbols for this test are found in + # the output. Only checking the symbols for the first group of + # events. + if {$symbol_check == 1} { + local_exec "sleep 2" "" "" 10 + verify_output $op_workload_table($entry) $workload_exc $ctr_opts + } -# cleanup the files created - local_exec "rm -f /tmp/operf_out.zzzz" "" "" 10 - local_exec "rm -f /tmp/operf_stop.zzzz" "" "" 10 - local_exec "rm -f /tmp/operf_run.zzzz" "" "" 10 - local_exec "rm -f /tmp/operf_create_stop.zzzz" "" "" 10 + # cleanup the files created + local_exec "rm -f /tmp/operf_out.zzzz" "" "" 10 + local_exec "rm -f /tmp/operf_stop.zzzz" "" "" 10 + local_exec "rm -f /tmp/operf_run.zzzz" "" "" 10 + local_exec "rm -f /tmp/operf_create_stop.zzzz" "" "" 10 + operf_delete_samples + } } proc operf_check_samples_exist {ctrs} { @@ -135,8 +154,8 @@ proc operf_check_samples_exist {ctrs} { set n [lindex $ctr 0] set event [lindex $ctr 1] - verbose "running opreport --long-filenames event:$event" - set result [ local_exec "opreport --long-filenames event:$event" "" "" 100 ] + verbose "running opreport --symbols --long-filenames event:$event" + set result [ local_exec "opreport --symbols --long-filenames event:$event" "" "" 100 ] if { [regexp "error:" "$result" ]} { fail "$test: {$event} created nonzero sample files" } else { @@ -154,11 +173,14 @@ proc oprofile-operf_run_tests {} { } else { + set symbol_check 1 foreach spec $op_event_table($cpu) { - do_test $spec - operf_check_samples_exist $spec + # Just do the symbol check on the first event group. The + # assumption is the first event group contains cycles or count + # instructions which will reliably collect a lot of samples. + do_test $spec $symbol_check + set symbol_check 0 } - operf_delete_samples } } diff --git a/testsuite/workloads/memcpyt_src/memcpyt.c b/testsuite/workloads/memcpyt_src/memcpyt.c new file mode 100644 index 0000000..c3fc10d --- /dev/null +++ b/testsuite/workloads/memcpyt_src/memcpyt.c @@ -0,0 +1,45 @@ +/* memcpyt.c + * Copyright (C) 2012 IBM + + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <string.h> + +main() +{ + int j; + long a4k, b4k; + char a[8192], b[8192]; + int source_offset, dest_offset; + char *source_address, *dest_address; + int iterations, copy_length; + + iterations = 50000000; + copy_length = 65; + source_offset = 3; + dest_offset = 7; + + a4k = (long)(a+4095) & 0xfff; + b4k = (long)(b+4095) & 0xfff; + a4k = (4095 - a4k) & 0xfff; + b4k = (4095 - b4k) & 0xfff; + + source_address=a+a4k+source_offset; + dest_address=b+b4k+dest_offset; + + for(j=0;j<iterations;j++) + memcpy(dest_address, source_address, copy_length); +} diff --git a/testsuite/workloads/tcl_src/workload.tcl b/testsuite/workloads/tcl_src/workload.tcl new file mode 100644 index 0000000..78359db --- /dev/null +++ b/testsuite/workloads/tcl_src/workload.tcl @@ -0,0 +1,36 @@ +# workload.tcl +# Copyright (C) 2012 IBM + +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +if { $argc != 1 } { + set count 1000 +} else { + set count [lindex $argv 0] +} + +puts $count + +set j 23523 +set k 15431 +set m 73141 +set n 93802 +for {set i 0} {$i < $count} {incr i} { + set j [expr {($k * $m - ($n >> 2)) % 4294967296}] + set k [expr {($m + $n * ($j ^ $k)) % 4294967296}] + set m [expr {($n * $j - ($k << 2)) % 4294967296}] + set n [expr {($j + $k * ($m ^ $k)) % 4294967296}] +} +exec dd bs=16 if=/dev/urandom of=/dev/null count=$count diff --git a/testsuite/workloads/thread_src/thread.c b/testsuite/workloads/thread_src/thread.c new file mode 100644 index 0000000..b726658 --- /dev/null +++ b/testsuite/workloads/thread_src/thread.c @@ -0,0 +1,52 @@ +/* thread.c + * Copyright (C) 2012 IBM + + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <stdio.h> +#include <pthread.h> +#include <stdlib.h> + +#define N 300 + +void* mythread(void* arg) +{ + int i,j,k; + long c; + + printf("Thread start!\n"); + for(i=0; i< N; i++) + for(j=0; j< N; j++) + for(k=0; k< N; k++) + c=i+j+k; + printf("Thread done!\n"); + return NULL; +} +int main() +{ + pthread_t th; + + printf("main process start!\n"); + if ( pthread_create(&th,NULL,mythread,NULL)!=0) + { + printf("can not create thread,exit!\n"); + exit(0); + } + pthread_join(th, NULL); /* wait for thread */ + + printf("main process done!\n"); + return 0; +} -- 1.7.12.rc1.22.gbfbf4d4 |
From: Maynard J. <may...@us...> - 2012-10-09 15:22:17
|
On 10/08/2012 04:10 PM, Carl E. Love wrote: > On Mon, 2012-10-08 at 08:49 -0500, Maynard Johnson wrote: >> On 10/05/2012 06:48 PM, Carl E. Love wrote: >>> OProfile testsuite, Add symbol checking functionality > Carl, Thanks for the nice enhancement to the oprofile testsuite! Patch applied. -Maynard [snip] |
From: Carl E. L. <ce...@li...> - 2012-08-21 16:55:03
|
Maynard, Will: I found that the removal of two debug print statements didn't make it into the final patch. My mistake. I have updated the patch to remove these debug print statements. Carl Love ----------------------------------------------------------------------- OProfile testsuite, Add symbol checking functionality This patch adds additional testing and workload capability. The patch adds the capability to easily add a new workload specification and a list of symbols that should be present in the OProfile report. The testsuite runs each of the specified workloads with each of the event lists currently specified and then checks that each of the symbols for workload are found in the OProfile report. Signed-off-by: Carl Love <ce...@us...> --- testsuite/Makefile | 25 +++++++++++ testsuite/README | 8 ++++ testsuite/lib/op_workloads.exp | 32 +++++++++++++ testsuite/lib/verify.exp | 19 ++++++++ .../oprofile-opcontrol/oprofile-opcontrol-run.exp | 32 ++++++++++--- testsuite/oprofile-operf/oprofile-operf-run.exp | 52 +++++++++++++--------- testsuite/workloads/memcpyt_src/Makefile | 23 ++++++++++ testsuite/workloads/memcpyt_src/memcpyt.c | 45 +++++++++++++++++++ testsuite/workloads/thread_src/Makefile | 23 ++++++++++ testsuite/workloads/thread_src/thread.c | 47 +++++++++++++++++++ 10 files changed, 279 insertions(+), 27 deletions(-) create mode 100644 testsuite/Makefile create mode 100644 testsuite/lib/op_workloads.exp create mode 100644 testsuite/lib/verify.exp create mode 100644 testsuite/workloads/memcpyt_src/Makefile create mode 100644 testsuite/workloads/memcpyt_src/memcpyt.c create mode 100644 testsuite/workloads/thread_src/Makefile create mode 100644 testsuite/workloads/thread_src/thread.c diff --git a/testsuite/Makefile b/testsuite/Makefile new file mode 100644 index 0000000..aabc40f --- /dev/null +++ b/testsuite/Makefile @@ -0,0 +1,25 @@ +# Makefile +# Copyright (C) 2012 Carl Love, IBM +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# + +memcpyt: + cd workloads/memcpyt_src && $(MAKE) + cd workloads/thread_src && $(MAKE) + +clean: + rm workloads/memcpyt_src/memcpyt_bin + rm workloads/thread_src/thread_bin diff --git a/testsuite/README b/testsuite/README index 55c0d47..678cb96 100644 --- a/testsuite/README +++ b/testsuite/README @@ -2,6 +2,14 @@ This testsuite directory contains a simple testsuite to check the functionality of OProfile on the machine. The testsuite supports testing the previous user interface using opcontrol and the new operf interface. +The testsuite consists of several workloads. Each workload is run using +an architecture specific list of event sets. The OProfile report for +each workload run is then checked to make sure the expected symbols that +are specific to that workload are found in the profile report. + +Setting up the testsuite requires the workloads be compiled by typing +"make" in this directory. The workload executables can be "cleaned up" +by typing "make clean". Running the opcontrol OProfile testsuite requires the following: diff --git a/testsuite/lib/op_workloads.exp b/testsuite/lib/op_workloads.exp new file mode 100644 index 0000000..7183e31 --- /dev/null +++ b/testsuite/lib/op_workloads.exp @@ -0,0 +1,32 @@ + + +if {! [array exists op_workload_table]} { + array set op_workload_table {} +} + +# Make sure the workload binary name is unique and not a substring of the +# directory or the test to see if the symbol exists may find the symbol in +# the directory name not the executable. + +set op_workload_table(tcl) \ + { \ + {tclsh oprofile-operf/workload.tcl 5000} \ + {libtcl} \ + {/no-vmlinux} \ + } + +set op_workload_table(memcpy) \ + { \ + {workloads/memcpyt_src/memcpyt_bin} \ + {memcpyt_bin} \ + {main} \ + {/no-vmlinux} \ + } + +set op_workload_table(thread) \ + { \ + {workloads/thread_src/thread_bin} \ + {thread_bin} \ + {mythread} \ + {/no-vmlinux} \ + } diff --git a/testsuite/lib/verify.exp b/testsuite/lib/verify.exp new file mode 100644 index 0000000..c2e6729 --- /dev/null +++ b/testsuite/lib/verify.exp @@ -0,0 +1,19 @@ +proc verify_output { workload_table_entry } { + + set workload_spec $workload_table_entry + set max [llength $workload_spec] + + # Note, first entry in the workload spec is the name of the workload + # executable file. The following entries are the symbols contained in + # the binary file. + for {set index 1} {$index < $max} {incr index} { + set symbol [lindex $workload_spec $index] + set result [local_exec "opreport --symbols --long-filenames" "" "" 100 ] + + if { [regexp $symbol "$result" ]} { + pass "opreport contains symbol: $symbol" + } else { + fail "opreport does not contain symbol: $symbol" + } + } +} diff --git a/testsuite/oprofile-opcontrol/oprofile-opcontrol-run.exp b/testsuite/oprofile-opcontrol/oprofile-opcontrol-run.exp index 086d5d4..53a11cd 100644 --- a/testsuite/oprofile-opcontrol/oprofile-opcontrol-run.exp +++ b/testsuite/oprofile-opcontrol/oprofile-opcontrol-run.exp @@ -19,6 +19,8 @@ load_lib "op_events.exp" load_lib "op_util.exp" +load_lib "op_workloads.exp" +load_lib "verify.exp" set op_daemon_running 0 @@ -232,13 +234,29 @@ proc op_daemon_stop {} { } proc op_daemon_cycle {ctrs} { - op_daemon_delete_any_samples $ctrs - op_daemon_start $ctrs - op_spin 5000 - op_daemon_flush - op_daemon_check_samples_exist $ctrs - op_daemon_stop - op_daemon_delete_any_samples $ctrs + global op_workload_table + + foreach entry [array name op_workload_table] { + + set workload [lindex $op_workload_table($entry) 0] + + op_daemon_delete_any_samples $ctrs + op_daemon_start $ctrs + + # run the workload +# op_spin 5000 + local_exec ${workload} "" "" 100 + + op_daemon_flush + op_daemon_check_samples_exist $ctrs + + op_daemon_stop + op_daemon_delete_any_samples $ctrs + + # verify the instersting symbols for this test are found in + # the output + verify_output $op_workload_table($entry) + } } proc op_check_daemon {} { diff --git a/testsuite/oprofile-operf/oprofile-operf-run.exp b/testsuite/oprofile-operf/oprofile-operf-run.exp index 868d698..db451a4 100644 --- a/testsuite/oprofile-operf/oprofile-operf-run.exp +++ b/testsuite/oprofile-operf/oprofile-operf-run.exp @@ -19,9 +19,10 @@ load_lib "op_events.exp" load_lib "op_util.exp" +load_lib "op_workloads.exp" +load_lib "verify.exp" set operf_version "" -set operf_supported 0 proc oprofile-operf_get_version {} { global operf_version @@ -32,7 +33,6 @@ proc oprofile-operf_get_version {} { if {[regexp "\[0-9\]+\(.\[0-9\]+\)+\[a-zA-Z_\]*" $result operf_version] == 1} { verbose "version is $operf_version" - set operf_supported 1 pass $test } else { verbose "unable to determine version" @@ -62,29 +62,41 @@ proc oprofile-operf_get_version {} { } proc do_test {ctrs} { + global op_workload_table set ctr_opts {} set kernel 1 set user 1 set count 5000 - set workload "tclsh oprofile-operf/workload.tcl $count" - - set test "operf do test" - foreach ctr $ctrs { -# n - counter number, no longer used but didn't want to change specification format - set n [lindex $ctr 0] - set event [lindex $ctr 1] - set um [lindex $ctr 2] - set count [lindex $ctr 3] - append ctr_opts "${event}:${count}:${um}:${kernel}:${user}," - } - set cmd "operf --events ${ctr_opts} ${workload}" - set test $cmd + set name tcl + set entry $op_workload_table($name) + set workload [lindex $entry 0] + + foreach entry [array name op_workload_table] { + set workload [lindex $op_workload_table($entry) 0] + set test "operf do test" + set ctr_opts "" + + foreach ctr $ctrs { +# n - counter number, no longer used but didn't want to change specification format + set n [lindex $ctr 0] + set event [lindex $ctr 1] + set um [lindex $ctr 2] + set count [lindex $ctr 3] + append ctr_opts "${event}:${count}:${um}:${kernel}:${user}," + } + set cmd "operf --events ${ctr_opts} ${workload}" + set test $cmd - if {[lindex [local_exec $cmd "" "" 100] 0] == 0} { + if {[lindex [local_exec $cmd "" "" 100] 0] == 0} { pass $test - } else { + } else { fail $test + } + + # verify the instersting symbols for this test are found in + # the output + verify_output $op_workload_table($entry) } } @@ -97,10 +109,10 @@ proc operf_check_samples_exist {ctrs} { set n [lindex $ctr 0] set event [lindex $ctr 1] - verbose "running opreport --long-filenames event:$event" - set result [local_exec "opreport --long-filenames event:$event" "" "" 100 ] + verbose "running opreport --symbols --long-filenames event:$event" + set result [local_exec "opreport --symbols --long-filenames event:$event" "" "" 100 ] + if { [regexp "error:" "$result" ]} { -# if { [regexp "opreport error:" "$result" ]} fix check to match output fail "$test: {$event} created nonzero sample files" } else { pass "$test: {$event} created nonzero sample files" diff --git a/testsuite/workloads/memcpyt_src/Makefile b/testsuite/workloads/memcpyt_src/Makefile new file mode 100644 index 0000000..f88db6c --- /dev/null +++ b/testsuite/workloads/memcpyt_src/Makefile @@ -0,0 +1,23 @@ +# Makefile +# Copyright (C) 2012 Carl Love, IBM +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# + +# Make sure the workload binary name is unique and not a substring of the +# directory or the test to see if the symbol exists may find the symbol in +# the directory name not the executable. +memcpyt: memcpyt.c + gcc -g -o memcpyt_bin memcpyt.c diff --git a/testsuite/workloads/memcpyt_src/memcpyt.c b/testsuite/workloads/memcpyt_src/memcpyt.c new file mode 100644 index 0000000..f128190 --- /dev/null +++ b/testsuite/workloads/memcpyt_src/memcpyt.c @@ -0,0 +1,45 @@ +/* Makefile + * Copyright (C) 2012 IBM + + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <string.h> + +main() +{ + int j; + long a4k, b4k; + char a[8192], b[8192]; + int source_offset, dest_offset; + char *source_address, *dest_address; + int iterations, copy_length; + + iterations = 1000000000; + copy_length = 65; + source_offset = 3; + dest_offset = 7; + + a4k = (long)(a+4095) & 0xfff; + b4k = (long)(b+4095) & 0xfff; + a4k = (4095 - a4k) & 0xfff; + b4k = (4095 - b4k) & 0xfff; + + source_address=a+a4k+source_offset; + dest_address=b+b4k+dest_offset; + + for(j=0;j<iterations;j++) + memcpy(dest_address, source_address, copy_length); +} diff --git a/testsuite/workloads/thread_src/Makefile b/testsuite/workloads/thread_src/Makefile new file mode 100644 index 0000000..a7c5e36 --- /dev/null +++ b/testsuite/workloads/thread_src/Makefile @@ -0,0 +1,23 @@ +# Makefile +# Copyright (C) 2012 Carl Love, IBM +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# + +# Make sure the workload binary name is unique and not a substring of the +# directory or the test to see if the symbol exists may find the symbol in +# the directory name not the executable. +thread: thread.c + gcc -g -o thread_bin -pthread thread.c diff --git a/testsuite/workloads/thread_src/thread.c b/testsuite/workloads/thread_src/thread.c new file mode 100644 index 0000000..ae4eb70 --- /dev/null +++ b/testsuite/workloads/thread_src/thread.c @@ -0,0 +1,47 @@ +/* Makefile + * Copyright (C) 2012 IBM + + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <stdio.h> +#include <pthread.h> +#include <stdlib.h> + +#define N 300 +void* mythread(void* arg) +{ + int i,j,k; + long c; + for(i=0; i< N; i++) + for(j=0; j< N; j++) + for(k=0; k< N; k++) + c=i+j+k; + printf("In thread!\n"); + return NULL; +} +int main() +{ + pthread_t th; + + if ( pthread_create(&th,NULL,mythread,NULL)!=0) + { + printf("can not create thread,exit!\n"); + exit(0); + } + printf("main process!\n"); + sleep(3); + return 0; +} -- 1.7.12.rc1.22.gbfbf4d4 |