ia64/xen-unstable

changeset 9045:136aea67b369

The attached patch does the following:

- introduces two basic tests for the virtual TPM (skipped on hardware
where a TPM is not available or vtpm manager has not been started
manually before)
- adapts the Makefiles to make the test cases available
- splits up the hotplug files into two files where the vtpm-common.sh
can be sourced by 'other' scripts as well
- uses echo "$var" to return variables from functions
- gets rid of the 'set +e" work-around
- introduces a script (vtpm-delete) to delete entries from the virtual
TPM directory in /etc/xen/vtpm.db

The xm-tests will skip over the 2nd test on most systems and the patch
has otherwise no effect on existing tests.

Signed-off-by: Stefan Berger <stefanb@us.ibm.com>
author emellor@leeni.uk.xensource.com
date Mon Feb 27 16:13:05 2006 +0100 (2006-02-27)
parents 911f3ecd975e
children d741fa272309
files tools/examples/Makefile tools/examples/vtpm tools/examples/vtpm-common.sh tools/xm-test/configure.ac tools/xm-test/lib/XmTestLib/XenDomain.py tools/xm-test/tests/Makefile.am xen-unstable.hg/tools/examples/vtpm-delete xen-unstable.hg/tools/examples/vtpm-hotplug-common.sh xen-unstable.hg/tools/xm-test/tests/vtpm/01_vtpm-list_pos.py xen-unstable.hg/tools/xm-test/tests/vtpm/02_vtpm-cat_pcrs.py xen-unstable.hg/tools/xm-test/tests/vtpm/Makefile.am
line diff
     1.1 --- a/tools/examples/Makefile	Mon Feb 27 16:11:01 2006 +0100
     1.2 +++ b/tools/examples/Makefile	Mon Feb 27 16:13:05 2006 +0100
     1.3 @@ -26,10 +26,10 @@ XEN_SCRIPTS += network-route vif-route
     1.4  XEN_SCRIPTS += network-nat vif-nat
     1.5  XEN_SCRIPTS += block
     1.6  XEN_SCRIPTS += block-enbd block-nbd
     1.7 -XEN_SCRIPTS += vtpm
     1.8 +XEN_SCRIPTS += vtpm vtpm-delete
     1.9  XEN_SCRIPT_DATA = xen-script-common.sh locking.sh logging.sh
    1.10  XEN_SCRIPT_DATA += xen-hotplug-common.sh xen-network-common.sh vif-common.sh
    1.11 -XEN_SCRIPT_DATA += block-common.sh vtpm-common.sh
    1.12 +XEN_SCRIPT_DATA += block-common.sh vtpm-common.sh vtpm-hotplug-common.sh
    1.13  
    1.14  XEN_HOTPLUG_DIR = /etc/hotplug
    1.15  XEN_HOTPLUG_SCRIPTS = xen-backend.agent
     2.1 --- a/tools/examples/vtpm	Mon Feb 27 16:11:01 2006 +0100
     2.2 +++ b/tools/examples/vtpm	Mon Feb 27 16:13:05 2006 +0100
     2.3 @@ -1,7 +1,7 @@
     2.4  #!/bin/sh
     2.5  
     2.6  dir=$(dirname "$0")
     2.7 -. "$dir/vtpm-common.sh"
     2.8 +. "$dir/vtpm-hotplug-common.sh"
     2.9  
    2.10  vtpm_fatal_error=0
    2.11  
     3.1 --- a/tools/examples/vtpm-common.sh	Mon Feb 27 16:11:01 2006 +0100
     3.2 +++ b/tools/examples/vtpm-common.sh	Mon Feb 27 16:13:05 2006 +0100
     3.3 @@ -17,21 +17,8 @@
     3.4  #
     3.5  
     3.6  dir=$(dirname "$0")
     3.7 -. "$dir/xen-hotplug-common.sh"
     3.8 -
     3.9 -findCommand "$@"
    3.10 -if [ "$command" != "online" ]  &&
    3.11 -   [ "$command" != "offline" ] &&
    3.12 -   [ "$command" != "add" ]     &&
    3.13 -   [ "$command" != "remove" ]
    3.14 -then
    3.15 -	log err "Invalid command: $command"
    3.16 -	exit 1
    3.17 -fi
    3.18 -
    3.19 -
    3.20 -XENBUS_PATH="${XENBUS_PATH:?}"
    3.21 -
    3.22 +. "$dir/logging.sh"
    3.23 +. "$dir/locking.sh"
    3.24  
    3.25  VTPMDB="/etc/xen/vtpm.db"
    3.26  
    3.27 @@ -58,15 +45,19 @@ if [ -z "$VTPM_IMPL_DEFINED" ]; then
    3.28  	function vtpm_resume() {
    3.29  		true
    3.30  	}
    3.31 +	function vtpm_delete() {
    3.32 +		true
    3.33 +	}
    3.34  fi
    3.35  
    3.36 +
    3.37  #Find the instance number for the vtpm given the name of the domain
    3.38  # Parameters
    3.39  # - vmname : the name of the vm
    3.40  # Return value
    3.41  #  Returns '0' if instance number could not be found, otherwise
    3.42  #  it returns the instance number in the variable 'instance'
    3.43 -function find_instance () {
    3.44 +function vtpmdb_find_instance () {
    3.45  	local vmname=$1
    3.46  	local ret=0
    3.47  	instance=`cat $VTPMDB |                    \
    3.48 @@ -80,18 +71,17 @@ function find_instance () {
    3.49  	             }                             \
    3.50  	           }'`
    3.51  	if [ "$instance" != "" ]; then
    3.52 -		ret=1
    3.53 +		ret=$instance
    3.54  	fi
    3.55 -	return $ret
    3.56 +	echo "$ret"
    3.57  }
    3.58  
    3.59  
    3.60  # Check whether a particular instance number is still available
    3.61 -# returns '1' if it is available
    3.62 -function is_free_instancenum () {
    3.63 +# returns "0" if it is not available, "1" otherwise.
    3.64 +function vtpmdb_is_free_instancenum () {
    3.65  	local instance=$1
    3.66  	local avail=1
    3.67 -
    3.68  	#Allowed instance number range: 1-255
    3.69  	if [ $instance -eq 0 -o $instance -gt 255 ]; then
    3.70  		avail=0
    3.71 @@ -110,13 +100,13 @@ function is_free_instancenum () {
    3.72  			fi
    3.73  		done
    3.74  	fi
    3.75 -	return $avail
    3.76 +	echo "$avail"
    3.77  }
    3.78  
    3.79  
    3.80  # Get an available instance number given the database
    3.81  # Returns an unused instance number
    3.82 -function get_free_instancenum () {
    3.83 +function vtpmdb_get_free_instancenum () {
    3.84  	local ctr
    3.85  	local instances
    3.86  	local don
    3.87 @@ -145,12 +135,12 @@ function get_free_instancenum () {
    3.88  		fi
    3.89  		let ctr=ctr+1
    3.90  	done
    3.91 -	let instance=$ctr
    3.92 +	echo "$ctr"
    3.93  }
    3.94  
    3.95  
    3.96  # Add a domain name and instance number to the DB file
    3.97 -function add_instance () {
    3.98 +function vtpmdb_add_instance () {
    3.99  	local vmname=$1
   3.100  	local inst=$2
   3.101  
   3.102 @@ -159,8 +149,8 @@ function add_instance () {
   3.103  		echo "#1st column: domain name" >> $VTPMDB
   3.104  		echo "#2nd column: TPM instance number" >> $VTPMDB
   3.105  	fi
   3.106 -	validate_entry $vmname $inst
   3.107 -	if [ $? -eq 0 ]; then
   3.108 +	res=$(vtpmdb_validate_entry $vmname $inst)
   3.109 +	if [ $res -eq 0 ]; then
   3.110  		echo "$vmname $inst" >> $VTPMDB
   3.111  	fi
   3.112  }
   3.113 @@ -168,11 +158,10 @@ function add_instance () {
   3.114  
   3.115  #Validate whether an entry is the same as passed to this
   3.116  #function
   3.117 -function validate_entry () {
   3.118 +function vtpmdb_validate_entry () {
   3.119  	local rc=0
   3.120  	local vmname=$1
   3.121  	local inst=$2
   3.122 -	local res
   3.123  
   3.124  	res=`cat $VTPMDB |             \
   3.125  	     gawk -vvmname=$vmname     \
   3.126 @@ -197,13 +186,15 @@ function validate_entry () {
   3.127  	elif [ "$res" == "2" ]; then
   3.128  		let rc=2
   3.129  	fi
   3.130 -	return $rc
   3.131 +	echo "$rc"
   3.132  }
   3.133  
   3.134  
   3.135  #Remove an entry from the vTPM database given its domain name
   3.136 -function remove_entry () {
   3.137 +#and instance number
   3.138 +function vtpmdb_remove_entry () {
   3.139  	local vmname=$1
   3.140 +	local instance=$2
   3.141  	local VTPMDB_TMP="$VTPMDB".tmp
   3.142  	`cat $VTPMDB |             \
   3.143  	 gawk -vvmname=$vmname     \
   3.144 @@ -214,6 +205,7 @@ function remove_entry () {
   3.145  	 '} > $VTPMDB_TMP`
   3.146  	if [ -e $VTPMDB_TMP ]; then
   3.147  		mv -f $VTPMDB_TMP $VTPMDB
   3.148 +		vtpm_delete $instance
   3.149  	else
   3.150  		log err "Error creating temporary file '$VTPMDB_TMP'."
   3.151  	fi
   3.152 @@ -222,7 +214,7 @@ function remove_entry () {
   3.153  
   3.154  # Find the reason for the creation of this device:
   3.155  # Set global REASON variable to 'resume' or 'create'
   3.156 -function get_create_reason () {
   3.157 +function vtpm_get_create_reason () {
   3.158  	local resume=$(xenstore-read $XENBUS_PATH/resume)
   3.159  	if [ "$resume" == "True" ]; then
   3.160  		REASON="resume"
   3.161 @@ -231,32 +223,30 @@ function get_create_reason () {
   3.162  	fi
   3.163  }
   3.164  
   3.165 +
   3.166  #Create a vTPM instance
   3.167  # If no entry in the TPM database is found, the instance is
   3.168  # created and an entry added to the database.
   3.169  function vtpm_create_instance () {
   3.170  	local domname=$(xenstore_read "$XENBUS_PATH"/domain)
   3.171  	local res
   3.172 -	set +e
   3.173 -	get_create_reason
   3.174 +	local instance
   3.175 +	vtpm_get_create_reason
   3.176  
   3.177  	claim_lock vtpmdb
   3.178 -
   3.179 -	find_instance $domname
   3.180 -	res=$?
   3.181 -	if [ $res -eq 0 ]; then
   3.182 +	instance=$(vtpmdb_find_instance $domname)
   3.183 +	if [ "$instance" == "0" ]; then
   3.184  		#Try to give the preferred instance to the domain
   3.185  		instance=$(xenstore_read "$XENBUS_PATH"/pref_instance)
   3.186  		if [ "$instance" != "" ]; then
   3.187 -			is_free_instancenum $instance
   3.188 -			res=$?
   3.189 +			res=$(vtpmdb_is_free_instancenum $instance)
   3.190  			if [ $res -eq 0 ]; then
   3.191 -				get_free_instancenum
   3.192 +				instance=$(vtpmdb_get_free_instancenum)
   3.193  			fi
   3.194  		else
   3.195 -			get_free_instancenum
   3.196 +			instance=$(vtpmdb_get_free_instancenum)
   3.197  		fi
   3.198 -		add_instance $domname $instance
   3.199 +		vtpmdb_add_instance $domname $instance
   3.200  		if [ "$REASON" == "create" ]; then
   3.201  			vtpm_create $instance
   3.202  		elif [ "$REASON" == "resume" ]; then
   3.203 @@ -279,25 +269,40 @@ function vtpm_create_instance () {
   3.204  		true
   3.205  	fi
   3.206  	xenstore_write $XENBUS_PATH/instance $instance
   3.207 -	set -e
   3.208  }
   3.209  
   3.210  
   3.211 -#Remove an instance
   3.212 +#Remove an instance when a VM is terminating or suspending.
   3.213 +#Since it is assumed that the VM will appear again, the
   3.214 +#entry is kept in the VTPMDB file.
   3.215  function vtpm_remove_instance () {
   3.216  	local domname=$(xenstore_read "$XENBUS_PATH"/domain)
   3.217 -	set +e
   3.218 -	find_instance $domname
   3.219 -	res=$?
   3.220 -	if [ $res -eq 0 ]; then
   3.221 -		#Something is really wrong with the DB
   3.222 -		log err "vTPM DB file $VTPMDB has no entry for '$domname'"
   3.223 -	else
   3.224 +
   3.225 +	claim_lock vtpmdb
   3.226 +
   3.227 +	instance=$(vtpmdb_find_instance $domname)
   3.228 +
   3.229 +	if [ "$instance" != "0" ]; then
   3.230  		if [ "$REASON" == "suspend" ]; then
   3.231  			vtpm_suspend $instance
   3.232  		fi
   3.233  	fi
   3.234 -	set -e
   3.235 +
   3.236 +	release_lock vtpmdb
   3.237  }
   3.238  
   3.239  
   3.240 +#Remove an entry in the VTPMDB file given the domain's name
   3.241 +#1st parameter: The name of the domain
   3.242 +function vtpm_delete_instance () {
   3.243 +	local rc
   3.244 +
   3.245 +	claim_lock vtpmdb
   3.246 +
   3.247 +	instance=$(vtpmdb_find_instance $1)
   3.248 +	if [ "$instance" != "0" ]; then
   3.249 +		vtpmdb_remove_entry $1 $instance
   3.250 +	fi
   3.251 +
   3.252 +	release_lock vtpmdb
   3.253 +}
     4.1 --- a/tools/xm-test/configure.ac	Mon Feb 27 16:11:01 2006 +0100
     4.2 +++ b/tools/xm-test/configure.ac	Mon Feb 27 16:13:05 2006 +0100
     4.3 @@ -93,6 +93,7 @@ AC_CONFIG_FILES([
     4.4      tests/unpause/Makefile
     4.5      tests/vcpu-pin/Makefile
     4.6      tests/vcpu-disable/Makefile
     4.7 +    tests/vtpm/Makefile
     4.8      tests/enforce_dom0_cpus/Makefile
     4.9      lib/XmTestReport/xmtest.py
    4.10      lib/XmTestLib/config.py
     5.1 --- a/tools/xm-test/lib/XmTestLib/XenDomain.py	Mon Feb 27 16:11:01 2006 +0100
     5.2 +++ b/tools/xm-test/lib/XmTestLib/XenDomain.py	Mon Feb 27 16:13:05 2006 +0100
     5.3 @@ -99,6 +99,7 @@ class XenConfig:
     5.4          # These options need to be lists
     5.5          self.defaultOpts["disk"] = []
     5.6          self.defaultOpts["vif"]  = []
     5.7 +        self.defaultOpts["vtpm"] = []
     5.8  
     5.9          self.opts = self.defaultOpts
    5.10  
     6.1 --- a/tools/xm-test/tests/Makefile.am	Mon Feb 27 16:11:01 2006 +0100
     6.2 +++ b/tools/xm-test/tests/Makefile.am	Mon Feb 27 16:13:05 2006 +0100
     6.3 @@ -23,6 +23,7 @@ SUBDIRS = 	               	\
     6.4  		unpause         \
     6.5  		vcpu-disable    \
     6.6  		vcpu-pin	\
     6.7 +		vtpm            \
     6.8  		enforce_dom0_cpus	\
     6.9  		save restore migrate
    6.10  
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/xen-unstable.hg/tools/examples/vtpm-delete	Mon Feb 27 16:13:05 2006 +0100
     7.3 @@ -0,0 +1,9 @@
     7.4 +#!/bin/sh
     7.5 +
     7.6 +# This scripts must be called the following way:
     7.7 +# vtpm-delete <domain name>
     7.8 +
     7.9 +dir=$(dirname "$0")
    7.10 +. "$dir/vtpm-common.sh"
    7.11 +
    7.12 +vtpm_delete_instance $1
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/xen-unstable.hg/tools/examples/vtpm-hotplug-common.sh	Mon Feb 27 16:13:05 2006 +0100
     8.3 @@ -0,0 +1,35 @@
     8.4 +#
     8.5 +# Copyright (c) 2005 IBM Corporation
     8.6 +# Copyright (c) 2005 XenSource Ltd.
     8.7 +#
     8.8 +# This library is free software; you can redistribute it and/or
     8.9 +# modify it under the terms of version 2.1 of the GNU Lesser General Public
    8.10 +# License as published by the Free Software Foundation.
    8.11 +#
    8.12 +# This library is distributed in the hope that it will be useful,
    8.13 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
    8.14 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    8.15 +# Lesser General Public License for more details.
    8.16 +#
    8.17 +# You should have received a copy of the GNU Lesser General Public
    8.18 +# License along with this library; if not, write to the Free Software
    8.19 +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    8.20 +#
    8.21 +
    8.22 +dir=$(dirname "$0")
    8.23 +. "$dir/xen-hotplug-common.sh"
    8.24 +
    8.25 +findCommand "$@"
    8.26 +if [ "$command" != "online" ]  &&
    8.27 +   [ "$command" != "offline" ] &&
    8.28 +   [ "$command" != "add" ]     &&
    8.29 +   [ "$command" != "remove" ]
    8.30 +then
    8.31 +	log err "Invalid command: $command"
    8.32 +	exit 1
    8.33 +fi
    8.34 +
    8.35 +
    8.36 +XENBUS_PATH="${XENBUS_PATH:?}"
    8.37 +
    8.38 +. "$dir/vtpm-common.sh"
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/xen-unstable.hg/tools/xm-test/tests/vtpm/01_vtpm-list_pos.py	Mon Feb 27 16:13:05 2006 +0100
     9.3 @@ -0,0 +1,45 @@
     9.4 +#!/usr/bin/python
     9.5 +
     9.6 +# Copyright (C) International Business Machines Corp., 2006
     9.7 +# Author: Stefan Berger <stefanb@us.ibm.com)
     9.8 +
     9.9 +# Positive Test: create domain with virtual TPM attached at build time,
    9.10 +#                verify list
    9.11 +
    9.12 +
    9.13 +from XmTestLib import *
    9.14 +
    9.15 +def vtpm_cleanup(domName):
    9.16 +	# Since this is only a temporary domain I clean up the domain from the
    9.17 +	# virtual TPM directory
    9.18 +	traceCommand("/etc/xen/scripts/vtpm-delete %s" % domName)
    9.19 +
    9.20 +if ENABLE_HVM_SUPPORT:
    9.21 +    SKIP("vtpm-list not supported for HVM domains")
    9.22 +
    9.23 +config = {"vtpm":"instance=1,backend=0"}
    9.24 +domain = XmTestDomain(extraConfig=config)
    9.25 +
    9.26 +try:
    9.27 +    domain.start()
    9.28 +except DomainError, e:
    9.29 +    if verbose:
    9.30 +        print e.extra
    9.31 +    vtpm_cleanup(domain.getName())
    9.32 +    FAIL("Unable to create domain")
    9.33 +
    9.34 +domName = domain.getName()
    9.35 +
    9.36 +status, output = traceCommand("xm vtpm-list %s" % domain.getId())
    9.37 +eyecatcher = "/local/domain/0/backend/vtpm"
    9.38 +where = output.find(eyecatcher)
    9.39 +if status != 0:
    9.40 +    vtpm_cleanup(domName)
    9.41 +    FAIL("xm vtpm-list returned bad status, expected 0, status is %i" % status)
    9.42 +elif where < 0:
    9.43 +    vtpm_cleanup(domName)
    9.44 +    FAIL("Fail to list virtual TPM device")
    9.45 +
    9.46 +domain.stop()
    9.47 +
    9.48 +vtpm_cleanup(domName)
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/xen-unstable.hg/tools/xm-test/tests/vtpm/02_vtpm-cat_pcrs.py	Mon Feb 27 16:13:05 2006 +0100
    10.3 @@ -0,0 +1,81 @@
    10.4 +#!/usr/bin/python
    10.5 +
    10.6 +# Copyright (C) International Business Machines Corp., 2006
    10.7 +# Author: Stefan Berger <stefanb@us.ibm.com)
    10.8 +
    10.9 +# Positive Test: create domain with virtual TPM attached at build time,
   10.10 +#                check list of pcrs
   10.11 +
   10.12 +from XmTestLib import *
   10.13 +
   10.14 +def vtpm_cleanup(domName):
   10.15 +	# Since this is only a temporary domain I clean up the domain from the
   10.16 +	# virtual TPM directory
   10.17 +	traceCommand("/etc/xen/scripts/vtpm-delete %s" % domName)
   10.18 +
   10.19 +if ENABLE_HVM_SUPPORT:
   10.20 +    SKIP("vtpm-list not supported for HVM domains")
   10.21 +
   10.22 +status, output = traceCommand("ls /dev/tpm0")
   10.23 +if re.search("No such file or directory",output):
   10.24 +    SKIP("This machine has no hardware TPM; cannot run this test")
   10.25 +
   10.26 +status, output = traceCommand("ps aux | grep vtpm_manager | grep -v grep")
   10.27 +if output == "":
   10.28 +    FAIL("virtual TPM manager must be started to run this test")
   10.29 +
   10.30 +# vtpm manager has been detected
   10.31 +config = {"vtpm":"instance=1,backend=0"}
   10.32 +domain = XmTestDomain(extraConfig=config)
   10.33 +
   10.34 +try:
   10.35 +    domain.start()
   10.36 +except DomainError, e:
   10.37 +    if verbose:
   10.38 +        print e.extra
   10.39 +    vtpm_cleanup(domain.getName())
   10.40 +    FAIL("Unable to create domain")
   10.41 +
   10.42 +domName = domain.getName()
   10.43 +
   10.44 +try:
   10.45 +    console = XmConsole(domain.getName())
   10.46 +except ConsoleError, e:
   10.47 +    vtpm_cleanup(domName)
   10.48 +    FAIL(str(e))
   10.49 +
   10.50 +try:
   10.51 +    console.sendInput("input")
   10.52 +    run = console.runCmd("ls /sys")
   10.53 +except ConsoleError, e:
   10.54 +    saveLog(console.getHistory())
   10.55 +    vtpm_cleanup(domName)
   10.56 +    FAIL(str(e))
   10.57 +
   10.58 +if re.search("No such file",run["output"]):
   10.59 +    try:
   10.60 +        run = console.runCmd("mkdir /sys")
   10.61 +        run = console.runCmd("mount -t sysfs /sys /sys")
   10.62 +    except ConsoleError, e:
   10.63 +        saveLog(console.getHistory())
   10.64 +        vtpm_cleanup(domName)
   10.65 +        FAIL(str(e))
   10.66 +
   10.67 +try:
   10.68 +    run = console.runCmd("cat /sys/devices/platform/tpm_vtpm/pcrs")
   10.69 +except ConsoleError, e:
   10.70 +    saveLog(console.getHistory())
   10.71 +    vtpm_cleanup(domName)
   10.72 +    FAIL(str(e))
   10.73 +
   10.74 +if re.search("No such file",run["output"]):
   10.75 +    FAIL("TPM frontend support not compiled into (domU?) kernel")
   10.76 +
   10.77 +console.closeConsole()
   10.78 +
   10.79 +domain.stop()
   10.80 +
   10.81 +vtpm_cleanup(domName)
   10.82 +
   10.83 +if not re.search("PCR-00:",run["output"]):
   10.84 +	FAIL("Virtual TPM is not working correctly on /dev/vtpm on backend side")
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/xen-unstable.hg/tools/xm-test/tests/vtpm/Makefile.am	Mon Feb 27 16:13:05 2006 +0100
    11.3 @@ -0,0 +1,22 @@
    11.4 +
    11.5 +SUBDIRS =
    11.6 +
    11.7 +TESTS = 01_vtpm-list_pos.test \
    11.8 +        02_vtpm-cat_pcrs.test
    11.9 +
   11.10 +XFAIL_TESTS =
   11.11 +
   11.12 +EXTRA_DIST = $(TESTS) $(XFAIL_TESTS)
   11.13 +
   11.14 +TESTS_ENVIRONMENT=@TENV@
   11.15 +
   11.16 +%.test: %.py
   11.17 +	cp $< $@
   11.18 +	chmod +x $@
   11.19 +
   11.20 +clean-local: am_config_clean-local
   11.21 +
   11.22 +am_config_clean-local:
   11.23 +	rm -f *test
   11.24 +	rm -f *log
   11.25 +	rm -f *~