diff --git a/kloudbuster/kloudbuster.py b/kloudbuster/kloudbuster.py index db68e69..e9bf0f5 100755 --- a/kloudbuster/kloudbuster.py +++ b/kloudbuster/kloudbuster.py @@ -902,8 +902,7 @@ def generate_charts(json_results, html_file_name, is_config): is_config) return 0 - -def main(): +def process_cli_args(args): cli_opts = [ cfg.StrOpt("config", short="c", @@ -987,7 +986,10 @@ def main(): metavar=""), ] CONF.register_cli_opts(cli_opts) - CONF(sys.argv[1:], project="kloudbuster", version=__version__) + CONF(args, project="kloudbuster", version=__version__) + +def main(): + process_cli_args(sys.argv[1:]) logging.setup("kloudbuster") if CONF.rc and not CONF.tested_rc: diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..6e37de9 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,93 @@ +""" +This module is used to define shared pytest fixtures. +Because this module is placed under tests, all fixtures defined here can be used +by all test cases below tests +""" +import os +import shutil + +import pytest + +def stage_file(dirname, filename, content=None): + # we cannot use a os.path.join because we want to support + # multi-parts in the filename + if dirname.endswith('/') and filename.startswith('/'): + pathname = dirname + filename[1:] + elif filename.startswith('/') or dirname.endswith('/'): + pathname = dirname + filename + else: + pathname = dirname + '/' + filename + print('Staging file: ', pathname) + os.makedirs(os.path.dirname(pathname), exist_ok=True) + if content is None: + content = pathname + with open(pathname, 'w') as ff: + ff.write(content) + + +@pytest.fixture +def stage_fs(): + """ + This fixture can be used to stage a complete file system below a given root. + + This is a fixture factory and each test function can call stage_fs with the root of the + file system to stage and with a configuration. + The entire root_fs will be deleted when the fixture terminates unless skip_clean=True + + Example of files_config: + { + 'file1.yaml': 'any content', + 'folder1': { + 'file_with_arbitrary_content.yaml': None, + 'empty_file.txt': '', + 'nested_empty_folder: {} + } + 'folder1/file2.txt': None + } + if '/tmp/pico' is passed as fs_root, this fixture will stage the following files: + + /tmp/pico/file1.yaml (containing 'any content') + /tmp/pico/folder1/file_with_arbitrary_content.yaml (containing arbitary text) + /tmp/pico/folder1/empty_file.txt (empty) + /tmp/pico/folder1/nested_empty_folder/ (empty directory) + /tmp/pico/folder1/file2.txt (any content) + + + To use this fixture, simply add "stage_fs" as argument to your test function, then + call stage_fs() with arguments described in below _stage_fs function. + Also see the unit test code (test_fixtures.py) + """ + saved_fs_root = [] + def _stage_fs(fs_root, files_config, skip_clean=False): + """ + fs_root: pathname of the root under which all all the files defined in files_config must be staged + files_config: a dict of file content reflecting the desired staged file system + skip_clean: set to True if you do not want the staged directory to be cleaned on exit (for troubleshooting only) + """ + if not saved_fs_root: + if skip_clean: + # for troubleshooting, it is possible to preserve + # the stage_fs directory after the test finishes + saved_fs_root.append(None) + else: + saved_fs_root.append(fs_root) + # remove the stage_fs root directory at start + # so we're sure we start with a clean directory + shutil.rmtree(fs_root, ignore_errors=True) + os.makedirs(fs_root, exist_ok=True) + + for file, content in files_config.items(): + if isinstance(content, dict): + # remove any "/" at start + if file[0] == '/': + file = file[1:] + new_fs_root = os.path.join(fs_root, file) + os.makedirs(new_fs_root, exist_ok=True) + _stage_fs(new_fs_root, content) + else: + stage_file(fs_root, file, content) + yield _stage_fs + if saved_fs_root: + if saved_fs_root[0]: + # remove the stage_fs directory when the fixture terminates + shutil.rmtree(saved_fs_root[0], ignore_errors=True) diff --git a/tests/test_kloudbuster.py b/tests/test_kloudbuster.py index a002cc6..714b1b6 100644 --- a/tests/test_kloudbuster.py +++ b/tests/test_kloudbuster.py @@ -19,7 +19,43 @@ test_kloudbuster Tests for `kloudbuster` module. """ from kloudbuster.kb_config import KBConfig +from kloudbuster.kloudbuster import process_cli_args -def test_config(): - cfg = KBConfig() - cfg.update_configs() +def test_kbconfig_default(): + # verify that we load the defaulgt config properly + kbcfg = KBConfig() + kbcfg.update_configs() + cfg = kbcfg.config_scale + assert cfg.openrc_file is None + assert cfg.vm_creation_concurrency == 5 + assert cfg.client.flavor.vcpus == 1 + +config_yaml = """ +client: + flavor: + vcpus: 100 + ram: 2048 + disk: 0 + extra_specs: + "hw:cpu_policy": dedicated + storage_stage_configs: + vm_count: 1 + target: 'volume' + disk_size: 10 + io_file_size: 55 +""" +def test_kbconfig_overide(stage_fs): + config_fs = { + 'config.yaml': config_yaml + } + stage_fs('/tmp/kbtest', config_fs) + # verify that config override is working + args = ['-c', '/tmp/kbtest/config.yaml'] + process_cli_args(args) + kbcfg = KBConfig() + kbcfg.init_with_cli() + kbcfg.update_configs() + cfg = kbcfg.config_scale + print(cfg.client.storage_stage_configs) + assert cfg.client.flavor.vcpus == 100 + assert cfg.client.storage_stage_configs.io_file_size == 55