1 new commit in galaxy-central: https://bitbucket.org/galaxy/galaxy-central/commits/dc3944242df9/ Changeset: dc3944242df9 User: greg Date: 2013-12-04 21:07:39 Summary: Correctly use the initialized test_environment dict when running the tool shed's install and test framework and additional code cleanup for the framework. Affected #: 8 files diff -r ca25579a90e97157e32b527e7471cde90e9beed0 -r dc3944242df936a5026988aaf11f0a90fbe7b115 lib/tool_shed/scripts/check_repositories_for_functional_tests.py --- a/lib/tool_shed/scripts/check_repositories_for_functional_tests.py +++ b/lib/tool_shed/scripts/check_repositories_for_functional_tests.py @@ -4,7 +4,7 @@ import sys new_path = [ os.path.join( os.getcwd(), "lib" ), - os.path.join( os.getcwd(), "test" ) ] + os.path.join( os.getcwd(), "test" ) ] new_path.extend( sys.path[ 1: ] ) sys.path = new_path @@ -21,8 +21,8 @@ import tempfile import time -from base.util import get_database_version -from base.util import get_repository_current_revision +from install_and_test_tool_shed_repositories.base.util import get_database_version +from install_and_test_tool_shed_repositories.base.util import get_repository_current_revision from galaxy.model.orm import and_ from galaxy.model.orm import not_ from galaxy.model.orm import select diff -r ca25579a90e97157e32b527e7471cde90e9beed0 -r dc3944242df936a5026988aaf11f0a90fbe7b115 lib/tool_shed/scripts/check_tool_dependency_definition_repositories.py --- a/lib/tool_shed/scripts/check_tool_dependency_definition_repositories.py +++ b/lib/tool_shed/scripts/check_tool_dependency_definition_repositories.py @@ -25,9 +25,8 @@ import galaxy.webapps.tool_shed.config as tool_shed_config import galaxy.webapps.tool_shed.model.mapping -from base.util import get_database_version -from base.util import get_repository_current_revision -from base.util import get_test_environment +from install_and_test_tool_shed_repositories.base.util import get_database_version +from install_and_test_tool_shed_repositories.base.util import get_repository_current_revision from galaxy.model.orm import and_ from galaxy.model.orm import not_ from galaxy.model.orm import select diff -r ca25579a90e97157e32b527e7471cde90e9beed0 -r dc3944242df936a5026988aaf11f0a90fbe7b115 scripts/functional_tests.py --- a/scripts/functional_tests.py +++ b/scripts/functional_tests.py @@ -13,7 +13,7 @@ new_path.extend( sys.path[1:] ) sys.path = new_path -from base.util import parse_tool_panel_config +from base.tool_shed_util import parse_tool_panel_config from galaxy import eggs diff -r ca25579a90e97157e32b527e7471cde90e9beed0 -r dc3944242df936a5026988aaf11f0a90fbe7b115 test/base/tool_shed_util.py --- /dev/null +++ b/test/base/tool_shed_util.py @@ -0,0 +1,90 @@ +import logging +import os +import sys + +cwd = os.getcwd() +if cwd not in sys.path: + sys.path.append( cwd ) + +new_path = [ os.path.join( cwd, "lib" ) ] +if new_path not in sys.path: + new_path.extend( sys.path ) + sys.path = new_path + +from galaxy.util import parse_xml + +log = logging.getLogger(__name__) + +def get_installed_repository_info( elem, last_galaxy_test_file_dir, last_tested_repository_name, last_tested_changeset_revision, tool_path ): + """ + Return the GALAXY_TEST_FILE_DIR, the containing repository name and the change set revision for the tool elem. + This only happens when testing tools installed from the tool shed. + """ + tool_config_path = elem.get( 'file' ) + installed_tool_path_items = tool_config_path.split( '/repos/' ) + sans_shed = installed_tool_path_items[ 1 ] + path_items = sans_shed.split( '/' ) + repository_owner = path_items[ 0 ] + repository_name = path_items[ 1 ] + changeset_revision = path_items[ 2 ] + if repository_name != last_tested_repository_name or changeset_revision != last_tested_changeset_revision: + # Locate the test-data directory. + installed_tool_path = os.path.join( installed_tool_path_items[ 0 ], 'repos', repository_owner, repository_name, changeset_revision ) + for root, dirs, files in os.walk( os.path.join(tool_path, installed_tool_path )): + if '.' in dirs: + dirs.remove( '.hg' ) + if 'test-data' in dirs: + return os.path.join( root, 'test-data' ), repository_name, changeset_revision + return None, repository_name, changeset_revision + return last_galaxy_test_file_dir, last_tested_repository_name, last_tested_changeset_revision + +def parse_tool_panel_config( config, shed_tools_dict ): + """ + Parse a shed-related tool panel config to generate the shed_tools_dict. This only happens when testing tools installed from the tool shed. + """ + last_galaxy_test_file_dir = None + last_tested_repository_name = None + last_tested_changeset_revision = None + tool_path = None + has_test_data = False + tree = parse_xml( config ) + root = tree.getroot() + tool_path = root.get('tool_path') + for elem in root: + if elem.tag == 'tool': + galaxy_test_file_dir, \ + last_tested_repository_name, \ + last_tested_changeset_revision = get_installed_repository_info( elem, + last_galaxy_test_file_dir, + last_tested_repository_name, + last_tested_changeset_revision, + tool_path ) + if galaxy_test_file_dir: + if not has_test_data: + has_test_data = True + if galaxy_test_file_dir != last_galaxy_test_file_dir: + if not os.path.isabs( galaxy_test_file_dir ): + galaxy_test_file_dir = os.path.join( os.getcwd(), galaxy_test_file_dir ) + guid = elem.get( 'guid' ) + shed_tools_dict[ guid ] = galaxy_test_file_dir + last_galaxy_test_file_dir = galaxy_test_file_dir + elif elem.tag == 'section': + for section_elem in elem: + if section_elem.tag == 'tool': + galaxy_test_file_dir, \ + last_tested_repository_name, \ + last_tested_changeset_revision = get_installed_repository_info( section_elem, + last_galaxy_test_file_dir, + last_tested_repository_name, + last_tested_changeset_revision, + tool_path ) + if galaxy_test_file_dir: + if not has_test_data: + has_test_data = True + if galaxy_test_file_dir != last_galaxy_test_file_dir: + if not os.path.isabs( galaxy_test_file_dir ): + galaxy_test_file_dir = os.path.join( os.getcwd(), galaxy_test_file_dir ) + guid = section_elem.get( 'guid' ) + shed_tools_dict[ guid ] = galaxy_test_file_dir + last_galaxy_test_file_dir = galaxy_test_file_dir + return has_test_data, shed_tools_dict diff -r ca25579a90e97157e32b527e7471cde90e9beed0 -r dc3944242df936a5026988aaf11f0a90fbe7b115 test/base/util.py --- a/test/base/util.py +++ /dev/null @@ -1,140 +0,0 @@ -import logging -import os -import platform -import sys - -cwd = os.getcwd() -if cwd not in sys.path: - sys.path.append( cwd ) - -new_path = [ os.path.join( cwd, "lib" ) ] -if new_path not in sys.path: - new_path.extend( sys.path ) - sys.path = new_path - -from galaxy.util import parse_xml -from galaxy import eggs - -eggs.require( 'mercurial' ) - -from mercurial import hg -from mercurial import ui - -log = logging.getLogger(__name__) - -def get_database_version( app ): - ''' - This method returns the value of the version column from the migrate_version table, using the provided app's SQLAlchemy session to determine - which table to get that from. This way, it's provided with an instance of a Galaxy UniverseApplication, it will return the Galaxy instance's - database migration version. If a tool shed UniverseApplication is provided, it returns the tool shed's database migration version. - ''' - sa_session = app.model.context.current - result = sa_session.execute( 'SELECT version FROM migrate_version LIMIT 1' ) - # This query will return the following structure: - # row = [ column 0, column 1, ..., column n ] - # rows = [ row 0, row 1, ..., row n ] - # The first column in the first row is the version number we want. - for row in result: - version = row[ 0 ] - break - return version - -def get_installed_repository_info( elem, last_galaxy_test_file_dir, last_tested_repository_name, last_tested_changeset_revision, tool_path ): - """ - Return the GALAXY_TEST_FILE_DIR, the containing repository name and the change set revision for the tool elem. - This only happens when testing tools installed from the tool shed. - """ - tool_config_path = elem.get( 'file' ) - installed_tool_path_items = tool_config_path.split( '/repos/' ) - sans_shed = installed_tool_path_items[ 1 ] - path_items = sans_shed.split( '/' ) - repository_owner = path_items[ 0 ] - repository_name = path_items[ 1 ] - changeset_revision = path_items[ 2 ] - if repository_name != last_tested_repository_name or changeset_revision != last_tested_changeset_revision: - # Locate the test-data directory. - installed_tool_path = os.path.join( installed_tool_path_items[ 0 ], 'repos', repository_owner, repository_name, changeset_revision ) - for root, dirs, files in os.walk( os.path.join(tool_path, installed_tool_path )): - if '.hg' in dirs: - dirs.remove( '.hg' ) - if 'test-data' in dirs: - return os.path.join( root, 'test-data' ), repository_name, changeset_revision - return None, repository_name, changeset_revision - return last_galaxy_test_file_dir, last_tested_repository_name, last_tested_changeset_revision - -def get_repository_current_revision( repo_path ): - ''' - This method uses the python mercurial API to get the current working directory's mercurial changeset hash. Note that if the author of mercurial - changes the API, this method will have to be updated or replaced. - ''' - # Initialize a mercurial repo object from the provided path. - repo = hg.repository( ui.ui(), repo_path ) - # Get the working directory's change context. - ctx = repo[ None ] - # Extract the changeset hash of the first parent of that change context (the most recent changeset to which the working directory was updated). - changectx = ctx.parents()[ 0 ] - # Also get the numeric revision, so we can return the customary id:hash changeset identifiers. - ctx_rev = changectx.rev() - hg_id = '%d:%s' % ( ctx_rev, str( changectx ) ) - return hg_id - -def get_test_environment( current_environment=None ): - if current_environment is None: - current_environment = {} - rval = current_environment - rval[ 'python_version' ] = platform.python_version() - rval[ 'architecture' ] = platform.machine() - os, hostname, os_version, uname, arch, processor = platform.uname() - rval[ 'system' ] = '%s %s' % ( os, os_version ) - return rval - -def parse_tool_panel_config( config, shed_tools_dict ): - """ - Parse a shed-related tool panel config to generate the shed_tools_dict. This only happens when testing tools installed from the tool shed. - """ - last_galaxy_test_file_dir = None - last_tested_repository_name = None - last_tested_changeset_revision = None - tool_path = None - has_test_data = False - tree = parse_xml( config ) - root = tree.getroot() - tool_path = root.get('tool_path') - for elem in root: - if elem.tag == 'tool': - galaxy_test_file_dir, \ - last_tested_repository_name, \ - last_tested_changeset_revision = get_installed_repository_info( elem, - last_galaxy_test_file_dir, - last_tested_repository_name, - last_tested_changeset_revision, - tool_path ) - if galaxy_test_file_dir: - if not has_test_data: - has_test_data = True - if galaxy_test_file_dir != last_galaxy_test_file_dir: - if not os.path.isabs( galaxy_test_file_dir ): - galaxy_test_file_dir = os.path.join( os.getcwd(), galaxy_test_file_dir ) - guid = elem.get( 'guid' ) - shed_tools_dict[ guid ] = galaxy_test_file_dir - last_galaxy_test_file_dir = galaxy_test_file_dir - elif elem.tag == 'section': - for section_elem in elem: - if section_elem.tag == 'tool': - galaxy_test_file_dir, \ - last_tested_repository_name, \ - last_tested_changeset_revision = get_installed_repository_info( section_elem, - last_galaxy_test_file_dir, - last_tested_repository_name, - last_tested_changeset_revision, - tool_path ) - if galaxy_test_file_dir: - if not has_test_data: - has_test_data = True - if galaxy_test_file_dir != last_galaxy_test_file_dir: - if not os.path.isabs( galaxy_test_file_dir ): - galaxy_test_file_dir = os.path.join( os.getcwd(), galaxy_test_file_dir ) - guid = section_elem.get( 'guid' ) - shed_tools_dict[ guid ] = galaxy_test_file_dir - last_galaxy_test_file_dir = galaxy_test_file_dir - return has_test_data, shed_tools_dict diff -r ca25579a90e97157e32b527e7471cde90e9beed0 -r dc3944242df936a5026988aaf11f0a90fbe7b115 test/install_and_test_tool_shed_repositories/base/util.py --- /dev/null +++ b/test/install_and_test_tool_shed_repositories/base/util.py @@ -0,0 +1,54 @@ +import logging +import os +import sys + +cwd = os.getcwd() +if cwd not in sys.path: + sys.path.append( cwd ) + +new_path = [ os.path.join( cwd, "lib" ) ] +if new_path not in sys.path: + new_path.extend( sys.path ) + sys.path = new_path + +from galaxy import eggs + +eggs.require( 'mercurial' ) + +from mercurial import hg +from mercurial import ui + +log = logging.getLogger(__name__) + +def get_database_version( app ): + ''' + This method returns the value of the version column from the migrate_version table, using the provided app's SQLAlchemy session to determine + which table to get that from. This way, it's provided with an instance of a Galaxy UniverseApplication, it will return the Galaxy instance's + database migration version. If a tool shed UniverseApplication is provided, it returns the tool shed's database migration version. + ''' + sa_session = app.model.context.current + result = sa_session.execute( 'SELECT version FROM migrate_version LIMIT 1' ) + # This query will return the following structure: + # row = [ column 0, column 1, ..., column n ] + # rows = [ row 0, row 1, ..., row n ] + # The first column in the first row is the version number we want. + for row in result: + version = row[ 0 ] + break + return version + +def get_repository_current_revision( repo_path ): + ''' + This method uses the python mercurial API to get the current working directory's mercurial changeset hash. Note that if the author of mercurial + changes the API, this method will have to be updated or replaced. + ''' + # Initialize a mercurial repo object from the provided path. + repo = hg.repository( ui.ui(), repo_path ) + # Get the working directory's change context. + ctx = repo[ None ] + # Extract the changeset hash of the first parent of that change context (the most recent changeset to which the working directory was updated). + changectx = ctx.parents()[ 0 ] + # Also get the numeric revision, so we can return the customary id:hash changeset identifiers. + ctx_rev = changectx.rev() + hg_id = '%d:%s' % ( ctx_rev, str( changectx ) ) + return hg_id diff -r ca25579a90e97157e32b527e7471cde90e9beed0 -r dc3944242df936a5026988aaf11f0a90fbe7b115 test/install_and_test_tool_shed_repositories/functional/test_install_repositories.py --- a/test/install_and_test_tool_shed_repositories/functional/test_install_repositories.py +++ b/test/install_and_test_tool_shed_repositories/functional/test_install_repositories.py @@ -1,6 +1,8 @@ -import new, logging +import logging +import new import install_and_test_tool_shed_repositories.base.test_db_util as test_db_util from install_and_test_tool_shed_repositories.base.twilltestcase import InstallTestRepository + log = logging.getLogger(__name__) @@ -80,4 +82,3 @@ # from baseclasses (which should be a tuple of classes) and with namespace dict. new_class_obj = new.classobj( str( name ), baseclasses, namespace ) G[ name ] = new_class_obj - diff -r ca25579a90e97157e32b527e7471cde90e9beed0 -r dc3944242df936a5026988aaf11f0a90fbe7b115 test/install_and_test_tool_shed_repositories/functional_tests.py --- a/test/install_and_test_tool_shed_repositories/functional_tests.py +++ b/test/install_and_test_tool_shed_repositories/functional_tests.py @@ -10,9 +10,9 @@ cwd = os.getcwd() sys.path.append( cwd ) new_path = [ os.path.join( cwd, "scripts" ), - os.path.join( cwd, "lib" ), - os.path.join( cwd, 'test' ), - os.path.join( cwd, 'scripts', 'api' ) ] + os.path.join( cwd, "lib" ), + os.path.join( cwd, 'test' ), + os.path.join( cwd, 'scripts', 'api' ) ] new_path.extend( sys.path ) sys.path = new_path @@ -30,6 +30,7 @@ import install_and_test_tool_shed_repositories.functional.test_install_repositories as test_install_repositories import logging import nose +import platform import random import re import shutil @@ -41,10 +42,9 @@ import tool_shed.util.shed_util_common as suc import urllib -from base.util import get_database_version -from base.util import get_repository_current_revision -from base.util import get_test_environment -from base.util import parse_tool_panel_config +from base.tool_shed_util import parse_tool_panel_config +from install_and_test_tool_shed_repositories.base.util import get_database_version +from install_and_test_tool_shed_repositories.base.util import get_repository_current_revision from common import update from datetime import datetime from galaxy.app import UniverseApplication @@ -614,31 +614,38 @@ owner = str( repository_dict[ 'owner' ] ) changeset_revision = str( repository_dict[ 'changeset_revision' ] ) log.debug( "Processing revision %s of repository %s owned by %s..." % ( changeset_revision, name, owner ) ) - # Populate the tool_test_results_dict. + # Retrieve the stored list of tool_test_results_dicts. tool_test_results_dicts, error_message = get_tool_test_results_dicts( galaxy_tool_shed_url, encoded_repository_metadata_id ) if error_message: log.debug( error_message ) else: - # The preparation script ~/tool_shed/scripts/check_repositories_for_functional_tests.py will have entered - # information in the 'test_environment' and possibly the 'missing_test_components' entries of the first - # tool_test_results_dict in the list of tool_test_results_dicts. We need to be careful to not lose this - # information. - try: - tool_test_results_dict = tool_test_results_dicts.pop( 0 ) - except Exception, e: - log.exception( "Invalid list of tool_test_results_dicts %s: %s" % ( str( tool_test_results_dicts ), str( e ) ) ) - continue + if tool_test_results_dicts: + # Inspect the tool_test_results_dict for the last test run to make sure it contains only a test_environment + # entry. If it contains more entries, then the script ~/tool_shed/api/check_repositories_for_functional_tests.py + # was not executed in preparation for this script's execution, so we'll just create an empty dictionary. + tool_test_results_dict = tool_test_results_dicts[ 0 ] + if len( tool_test_results_dict ) <= 1: + # We can re-use the mostly empty tool_test_results_dict for this run because it is either empty or it contains only + # a test_environment entry. If we use it we need to temporarily eliminate it from the list of tool_test_results_dicts + # since it will be re-inserted later. + tool_test_results_dict = tool_test_results_dicts.pop( 0 ) + else: + # The latest tool_test_results_dict has been populated with the results of a test run, so it cannot be used. + tool_test_results_dict = {} + else: + # Create a new dictionary for this test test run, + tool_test_results_dict = {} # See if this repository should be skipped for any reason. - this_repository_is_in_the_exclude_lost = False + this_repository_is_in_the_exclude_list = False skip_reason = None for exclude_dict in exclude_list: reason = exclude_dict[ 'reason' ] exclude_repositories = exclude_dict[ 'repositories' ] if ( name, owner, changeset_revision ) in exclude_repositories or ( name, owner, None ) in exclude_repositories: - this_repository_is_in_the_exclude_lost = True + this_repository_is_in_the_exclude_list = True skip_reason = reason break - if this_repository_is_in_the_exclude_lost: + if this_repository_is_in_the_exclude_list: tool_test_results_dict[ 'not_tested' ] = dict( reason=skip_reason ) params = dict( tools_functionally_correct=False, do_not_test=False ) @@ -647,19 +654,32 @@ log.debug( "Not testing revision %s of repository %s owned by %s because it is in the exclude list for this test run." % \ ( changeset_revision, name, owner ) ) else: - test_environment_dict = tool_test_results_dict.get( 'test_environment', None ) - test_environment_dict = get_test_environment( test_environment_dict ) + test_environment_dict = tool_test_results_dict.get( 'test_environment', {} ) + if len( test_environment_dict ) == 0: + # Set information about the tool shed to nothing since we cannot currently determine it from here. + # We could eventually add an API method... + test_environment_dict = dict( tool_shed_database_version='', + tool_shed_mercurial_version='', + tool_shed_revision='' ) # Add the current time as the approximate time that this test run occurs. A similar value will also be # set to the repository_metadata.time_last_tested column, but we also store it here because the Tool Shed # may be configured to store multiple test run results, so each must be associated with a time stamp. now = time.strftime( "%Y-%m-%d %H:%M:%S" ) + # Add information about the current platform. test_environment_dict[ 'time_tested' ] = now + test_environment_dict[ 'python_version' ] = platform.python_version() + test_environment_dict[ 'architecture' ] = platform.machine() + operating_system, hostname, operating_system_version, uname, arch, processor = platform.uname() + test_environment_dict[ 'system' ] = '%s %s' % ( operating_system, operating_system_version ) + # Add information about the current Galaxy environment. test_environment_dict[ 'galaxy_database_version' ] = get_database_version( app ) test_environment_dict[ 'galaxy_revision' ] = get_repository_current_revision( os.getcwd() ) + # Initialize and populate the tool_test_results_dict. tool_test_results_dict[ 'test_environment' ] = test_environment_dict tool_test_results_dict[ 'passed_tests' ] = [] tool_test_results_dict[ 'failed_tests' ] = [] tool_test_results_dict[ 'installation_errors' ] = dict( current_repository=[], repository_dependencies=[], tool_dependencies=[] ) + # Proceed with installing repositories and testing contained tools. repository, error_message = install_repository( app, repository_dict ) if error_message: tool_test_results_dict[ 'installation_errors' ][ 'current_repository' ] = error_message Repository URL: https://bitbucket.org/galaxy/galaxy-central/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email.