mirror of
https://github.com/apache/impala.git
synced 2026-01-10 18:00:14 -05:00
Many of the test modules included calls to 'logging.basicConfig' at global scope in their implementation. This meant that by just importing one of these files, other tests would inherit their logging format. This is typically a bad idea in Python -- modules should not have side effects like this on import. The format was additionally inconsistent. In some cases we had a "--" prepended to the format, and in others we didn't. The "--" is very useful since it lets developers copy-paste query-test output back into the shell to reproduce an issue. This patch fixes the above by centralizing the logging configuration in a pytest hook that runs prior to all pytests. A few other non-pytest related tools now configure logging in their "main" code which is only triggered when the module is executed directly. I tested that, with this change, logs still show up properly in the .xml output files from 'run-tests.py' as well as when running tests manually from impala-py.test Change-Id: I55ef0214b43f87da2d71804913ba4caa964f789f Reviewed-on: http://gerrit.cloudera.org:8080/11225 Reviewed-by: Philip Zeyliger <philip@cloudera.com> Tested-by: Impala Public Jenkins <impala-public-jenkins@cloudera.com>
104 lines
4.0 KiB
Python
104 lines
4.0 KiB
Python
# Licensed to the Apache Software Foundation (ASF) under one
|
|
# or more contributor license agreements. See the NOTICE file
|
|
# distributed with this work for additional information
|
|
# regarding copyright ownership. The ASF licenses this file
|
|
# to you under the Apache License, Version 2.0 (the
|
|
# "License"); you may not use this file except in compliance
|
|
# with the License. You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing,
|
|
# software distributed under the License is distributed on an
|
|
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
# KIND, either express or implied. See the License for the
|
|
# specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
import logging
|
|
import os
|
|
import pkgutil
|
|
|
|
PLUGIN_DIR = os.path.join(os.environ['IMPALA_HOME'], 'tests', 'benchmark', 'plugins')
|
|
|
|
# Setup logging for this module.
|
|
LOG = logging.getLogger('plugin_runner')
|
|
LOG.setLevel(level=logging.INFO)
|
|
|
|
class PluginRunner(object):
|
|
''' Loads user specified plugins, if found, and initializes them.
|
|
|
|
Looks in /tests/plugins and searches each module for plugin_name. plugin_name
|
|
is the name of the class that the user has used to implement a plugin. If the class
|
|
is found, it is initialized and added to self.__plugins. If it's not found, an error
|
|
message is logged and the plugin in not loaded.
|
|
'''
|
|
|
|
def __init__(self, plugin_infos):
|
|
self.__available_modules = self.__get_plugin_modules()
|
|
self.__get_plugins_from_modules(plugin_infos)
|
|
|
|
@property
|
|
def plugins(self):
|
|
return self.__plugins
|
|
|
|
def __getstate__(self):
|
|
state = self.__dict__.copy()
|
|
del state['__available_modules']
|
|
return state
|
|
|
|
def __get_plugin_modules(self):
|
|
''' Gets all the modules in the directory and imports them'''
|
|
modules = pkgutil.iter_modules(path=[PLUGIN_DIR])
|
|
available_modules = []
|
|
for loader, mod_name, ispkg in modules:
|
|
yield __import__("tests.benchmark.plugins.%s" % mod_name, fromlist=[mod_name])
|
|
|
|
def __get_plugins_from_modules(self, plugin_infos):
|
|
'''Look for user specified plugins in the available modules.'''
|
|
self.__plugins = []
|
|
plugin_names = []
|
|
for module in self.__available_modules:
|
|
for plugin_info in plugin_infos:
|
|
plugin_name, scope = self.__get_plugin_info(plugin_info)
|
|
plugin_names.append(plugin_name)
|
|
if hasattr(module, plugin_name):
|
|
self.__plugins.append(getattr(module, plugin_name)(scope=scope.lower()))
|
|
# The plugin(s) that could not be loaded are captured in the set difference
|
|
# between plugin_names and self.__plugins
|
|
plugins_found = [p.__name__ for p in self.__plugins]
|
|
LOG.debug("Plugins found: %s" % ', '.join(plugins_found))
|
|
plugins_not_found = set(plugin_names).difference(plugins_found)
|
|
# If the user's entered a plugin that does not exist, raise an error.
|
|
if len(plugins_not_found):
|
|
msg = "Plugin(s) not found: %s" % (','.join(list(plugins_not_found)))
|
|
raise RuntimeError, msg
|
|
|
|
def __get_plugin_info(self, plugin_info):
|
|
info = plugin_info.split(':')
|
|
if len(info) == 1:
|
|
return info[0], 'query'
|
|
elif len(info) == 2:
|
|
return info[0], info[1]
|
|
else:
|
|
raise ValueError("Plugin names specified in the form <plugin_name>[:<scope>]")
|
|
|
|
def print_plugin_names(self):
|
|
for p in self.__plugins:
|
|
LOG.debug("Plugin: %s, Scope: %s" % (p.__name__, p.scope))
|
|
|
|
def run_plugins_pre(self, context=None, scope=None):
|
|
if len(self.__plugins) == 0: return
|
|
if context: context['scope'] = scope
|
|
for p in self.__plugins:
|
|
if not scope or p.scope == scope.lower():
|
|
LOG.debug('Running pre-hook for %s at scope %s' % (p.__name__, scope))
|
|
p.run_pre_hook(context=context)
|
|
|
|
def run_plugins_post(self, context=None, scope=None):
|
|
if len(self.__plugins) == 0: return
|
|
for p in self.__plugins:
|
|
if not scope or p.scope == scope.lower():
|
|
LOG.debug('Running post-hook for %s at scope %s' % (p.__name__, scope))
|
|
p.run_post_hook(context=context)
|