root/galaxy-central/scripts/functional_tests.py @ 2

リビジョン 2, 13.3 KB (コミッタ: hatakeyama, 14 年 前)

import galaxy-central

行番号 
1#!/usr/bin/env python
2
3import os, sys, shutil
4
5# Assume we are run from the galaxy root directory, add lib to the python path
6cwd = os.getcwd()
7new_path = [ os.path.join( cwd, "lib" ) ]
8new_path.extend( sys.path[1:] )
9sys.path = new_path
10
11from galaxy import eggs
12
13eggs.require( "nose" )
14eggs.require( "NoseHTML" )
15eggs.require( "twill==0.9" )
16eggs.require( "Paste" )
17eggs.require( "PasteDeploy" )
18eggs.require( "Cheetah" )
19
20# this should not be required, but it is under certain conditions, thanks to this bug:
21# http://code.google.com/p/python-nose/issues/detail?id=284
22eggs.require( "pysqlite" )
23
24import atexit, logging, os, os.path, sys, tempfile
25import twill, unittest, time
26import subprocess, sys, threading, random
27import httplib, socket
28from paste import httpserver
29import galaxy.app
30from galaxy.app import UniverseApplication
31from galaxy.web import buildapp
32from galaxy import tools
33from galaxy.util import bunch
34
35log = logging.getLogger( "functional_tests.py" )
36
37default_galaxy_test_host = "localhost"
38default_galaxy_test_port_min = 8000
39default_galaxy_test_port_max = 9999
40default_galaxy_locales = 'en'
41default_galaxy_test_file_dir = "test-data"
42
43def main():
44   
45    # ---- Configuration ------------------------------------------------------
46   
47    galaxy_test_host = os.environ.get( 'GALAXY_TEST_HOST', default_galaxy_test_host )
48    galaxy_test_port = os.environ.get( 'GALAXY_TEST_PORT', None )
49    if 'HTTP_ACCEPT_LANGUAGE' not in os.environ:
50        os.environ['HTTP_ACCEPT_LANGUAGE'] = default_galaxy_locales
51    galaxy_test_file_dir = os.environ.get( 'GALAXY_TEST_FILE_DIR', default_galaxy_test_file_dir )
52    if not os.path.isabs( galaxy_test_file_dir ):
53        galaxy_test_file_dir = os.path.join( os.getcwd(), galaxy_test_file_dir )
54    start_server = 'GALAXY_TEST_EXTERNAL' not in os.environ   
55    tool_path = os.environ.get( 'GALAXY_TEST_TOOL_PATH', 'tools' )
56    if start_server:
57        psu_production = False
58        galaxy_test_proxy_port = None
59        if 'GALAXY_TEST_PSU_PRODUCTION' in os.environ:
60            if not galaxy_test_port:
61                raise Exception( 'Please set GALAXY_TEST_PORT to the port to which the proxy server will proxy' )
62            galaxy_test_proxy_port = os.environ.get( 'GALAXY_TEST_PROXY_PORT', None )
63            if not galaxy_test_proxy_port:
64                raise Exception( 'Please set GALAXY_TEST_PROXY_PORT to the port on which the proxy server is listening' )
65            base_file_path = os.environ.get( 'GALAXY_TEST_BASE_FILE_PATH', None )
66            if not base_file_path:
67                raise Exception( 'Please set GALAXY_TEST_BASE_FILE_PATH to the directory which will contain the dataset files directory' )
68            base_new_file_path = os.environ.get( 'GALAXY_TEST_BASE_NEW_FILE_PATH', None )
69            if not base_new_file_path:
70                raise Exception( 'Please set GALAXY_TEST_BASE_NEW_FILE_PATH to the directory which will contain the temporary directory' )
71            database_connection = os.environ.get( 'GALAXY_TEST_DBURI', None )
72            if not database_connection:
73                raise Exception( 'Please set GALAXY_TEST_DBURI to the URI of the database to be used for tests' )
74            nginx_upload_store = os.environ.get( 'GALAXY_TEST_NGINX_UPLOAD_STORE', None )
75            if not nginx_upload_store:
76                raise Exception( 'Please set GALAXY_TEST_NGINX_UPLOAD_STORE to the path where the nginx upload module places uploaded files' )
77            default_cluster_job_runner = os.environ.get( 'GALAXY_TEST_DEFAULT_CLUSTER_JOB_RUNNER', 'pbs:///' )
78            file_path = tempfile.mkdtemp( dir=base_file_path )
79            new_file_path = tempfile.mkdtemp( dir=base_new_file_path )
80            cluster_files_directory = os.path.join( new_file_path, 'pbs' )
81            job_working_directory = os.path.join( new_file_path, 'job_working_directory' )
82            os.mkdir( cluster_files_directory )
83            os.mkdir( job_working_directory )
84            kwargs = dict( database_engine_option_pool_size = '10',
85                           database_engine_option_max_overflow = '20',
86                           database_engine_option_strategy = 'threadlocal',
87                           nginx_x_accel_redirect_base = '/_x_accel_redirect',
88                           nginx_upload_store = nginx_upload_store,
89                           nginx_upload_path = '/_upload',
90                           cluster_files_directory = cluster_files_directory,
91                           job_working_directory = job_working_directory,
92                           outputs_to_working_directory = 'True',
93                           set_metadata_externally = 'True',
94                           static_enabled = 'False',
95                           debug = 'False',
96                           track_jobs_in_database = 'True',
97                           job_scheduler_policy = 'FIFO',
98                           start_job_runners = 'pbs',
99                           default_cluster_job_runner = default_cluster_job_runner, )
100            psu_production = True
101        else:
102            if 'GALAXY_TEST_DBPATH' in os.environ:
103                db_path = os.environ['GALAXY_TEST_DBPATH']
104            else:
105                tempdir = tempfile.mkdtemp()
106                db_path = os.path.join( tempdir, 'database' )
107            file_path = os.path.join( db_path, 'files' )
108            new_file_path = os.path.join( db_path, 'tmp' )
109            if 'GALAXY_TEST_DBURI' in os.environ:
110                database_connection = os.environ['GALAXY_TEST_DBURI']
111            else:
112                database_connection = 'sqlite:///' + os.path.join( db_path, 'universe.sqlite' )
113            kwargs = {}
114        for dir in file_path, new_file_path:
115            try:
116                os.makedirs( dir )
117            except OSError:
118                pass
119           
120    print "Database connection:", database_connection
121   
122    # What requires these?       
123    os.environ['GALAXY_TEST_HOST'] = galaxy_test_host
124    os.environ['GALAXY_TEST_FILE_DIR'] = galaxy_test_file_dir
125           
126    # ---- Build Application --------------------------------------------------
127       
128    app = None
129           
130    if start_server:
131       
132        global_conf = { '__file__' : 'universe_wsgi.ini.sample' }
133        if psu_production:
134            global_conf = None
135
136        # Build the Universe Application
137        app = UniverseApplication( job_queue_workers = 5,
138                                   id_secret = 'changethisinproductiontoo',
139                                   template_path = "templates",
140                                   database_connection = database_connection,
141                                   file_path = file_path,
142                                   new_file_path = new_file_path,
143                                   tool_path = tool_path,
144                                   tool_config_file = "tool_conf.xml.sample",
145                                   datatype_converters_config_file = "datatype_converters_conf.xml.sample",
146                                   tool_parse_help = False,
147                                   test_conf = "test.conf",
148                                   log_destination = "stdout",
149                                   use_heartbeat = False,
150                                   allow_user_creation = True,
151                                   allow_user_deletion = True,
152                                   admin_users = 'test@bx.psu.edu',
153                                   library_import_dir = galaxy_test_file_dir,
154                                   user_library_import_dir = os.path.join( galaxy_test_file_dir, 'users' ),
155                                   global_conf = global_conf,
156                                   **kwargs )
157       
158        log.info( "Embedded Universe application started" );
159       
160    # ---- Run webserver ------------------------------------------------------
161   
162    server = None
163   
164    if start_server:
165       
166        webapp = buildapp.app_factory( dict(), use_translogger = False, static_enabled = False, app=app )
167
168        if galaxy_test_port is not None:
169            server = httpserver.serve( webapp, host=galaxy_test_host, port=galaxy_test_port, start_loop=False )
170        else:
171            random.seed()
172            for i in range( 0, 9 ):
173                try:
174                    galaxy_test_port = str( random.randint( default_galaxy_test_port_min, default_galaxy_test_port_max ) )
175                    log.debug( "Attempting to serve app on randomly chosen port: %s" % galaxy_test_port )
176                    server = httpserver.serve( webapp, host=galaxy_test_host, port=galaxy_test_port, start_loop=False )
177                    break
178                except socket.error, e:
179                    if e[0] == 98:
180                        continue
181                    raise
182            else:
183                raise Exception( "Unable to open a port between %s and %s to start Galaxy server" % ( default_galaxy_test_port_min, default_galaxy_test_port_max ) )
184        if galaxy_test_proxy_port:
185            os.environ['GALAXY_TEST_PORT'] = galaxy_test_proxy_port
186        else:
187            os.environ['GALAXY_TEST_PORT'] = galaxy_test_port
188
189        t = threading.Thread( target=server.serve_forever )
190        t.start()
191
192        # Test if the server is up
193        for i in range( 10 ):
194            conn = httplib.HTTPConnection( galaxy_test_host, galaxy_test_port ) # directly test the app, not the proxy
195            conn.request( "GET", "/" )
196            if conn.getresponse().status == 200:
197                break
198            time.sleep( 0.1 )
199        else:
200            raise Exception( "Test HTTP server did not return '200 OK' after 10 tries" )
201           
202        # Test if the proxy server is up
203        if psu_production:
204            conn = httplib.HTTPConnection( galaxy_test_host, galaxy_test_proxy_port ) # directly test the app, not the proxy
205            conn.request( "GET", "/" )
206            if not conn.getresponse().status == 200:
207                raise Exception( "Test HTTP proxy server did not return '200 OK'" )
208           
209        log.info( "Embedded web server started" )
210
211   
212    # ---- Load toolbox for generated tests -----------------------------------
213   
214    # We don't add the tests to the path until everything is up and running
215    new_path = [ os.path.join( cwd, "test" ) ]
216    new_path.extend( sys.path[1:] )
217    sys.path = new_path
218   
219    import functional.test_toolbox
220   
221    if app:
222        # TODO: provisions for loading toolbox from file when using external server
223        functional.test_toolbox.toolbox = app.toolbox
224        functional.test_toolbox.build_tests()
225    else:
226        # FIXME: This doesn't work at all now that toolbox requires an 'app' instance
227        #        (to get at datatypes, might just pass a datatype registry directly)
228        my_app = bunch.Bunch( datatypes_registry = galaxy.datatypes.registry.Registry() )
229        test_toolbox.toolbox = tools.ToolBox( 'tool_conf.xml.test', 'tools', my_app )
230
231    # ---- Find tests ---------------------------------------------------------
232   
233    if galaxy_test_proxy_port:
234        log.info( "Functional tests will be run against %s:%s" % ( galaxy_test_host, galaxy_test_proxy_port ) )
235    else:
236        log.info( "Functional tests will be run against %s:%s" % ( galaxy_test_host, galaxy_test_port ) )
237   
238    success = False
239   
240    try:
241       
242        import nose.core
243        import nose.config
244        import nose.loader
245        import nose.plugins.manager
246       
247        test_config = nose.config.Config( env = os.environ, plugins=nose.plugins.manager.DefaultPluginManager() )
248        test_config.configure( sys.argv )
249       
250        loader = nose.loader.TestLoader( config = test_config )
251       
252        plug_loader = test_config.plugins.prepareTestLoader( loader )
253        if plug_loader is not None:
254            loader = plug_loader
255       
256        tests = loader.loadTestsFromNames( test_config.testNames )
257       
258        test_runner = nose.core.TextTestRunner(
259            stream = test_config.stream,
260            verbosity = test_config.verbosity,
261            config = test_config)
262       
263        plug_runner = test_config.plugins.prepareTestRunner( test_runner )
264        if plug_runner is not None:
265            test_runner = plug_runner
266       
267        result = test_runner.run( tests )
268       
269        success = result.wasSuccessful()
270       
271    except:
272        log.exception( "Failure running tests" )
273       
274    log.info( "Shutting down" )
275   
276    # ---- Teardown -----------------------------------------------------------
277   
278    if server:
279        log.info( "Shutting down embedded web server" )
280        server.server_close()
281        server = None
282        log.info( "Embedded web server stopped" )
283    if app:
284        log.info( "Shutting down app" )
285        app.shutdown()
286        app = None
287        log.info( "Embedded Universe application stopped" )
288    try:
289        if os.path.exists( tempdir ) and 'GALAXY_TEST_NO_CLEANUP' not in os.environ:
290            log.info( "Cleaning up temporary files in %s" % tempdir )
291            shutil.rmtree( tempdir )
292    except:
293        pass
294    if psu_production and 'GALAXY_TEST_NO_CLEANUP' not in os.environ:
295        for dir in ( file_path, new_file_path ):
296            try:
297                if os.path.exists( dir ):
298                    log.info( 'Cleaning up temporary files in %s' % dir )
299                    shutil.rmtree( dir )
300            except:
301                pass
302       
303    if success:
304        return 0
305    else:
306        return 1
307
308if __name__ == "__main__":
309    sys.exit( main() )
Note: リポジトリブラウザについてのヘルプは TracBrowser を参照してください。