diff --git a/tests/configs/complete.ini b/tests/configs/complete.ini new file mode 100644 index 0000000..b90033f --- /dev/null +++ b/tests/configs/complete.ini @@ -0,0 +1,32 @@ +[box] +bootstrap=tests/scripts/bootstrap.sh + +[box.tumbleweed] +name=tumbleweed +image=https://download.opensuse.org/repositories/home:/crameleon:/appliances/openSUSE_Tumbleweed/Tumbleweed.x86_64-libvirt.box + +[suite.one_minion] +minions=1 +box=tumbleweed + +[suite.two_minions] +minions=2 +box=tumbleweed + +[suite.one_minion_one_master] +minions=1 +masters=1 +box=tumbleweed + +[suite.one_master] +masters=1 +box=tumbleweed + +[suite.two_minions_one_master] +minions=2 +masters=1 +box=tumbleweed + +[test.hello] +apply=hello_world +test=salt/hello_world/tests/test_hello.py diff --git a/tests/configs/missing_box.ini b/tests/configs/missing_box.ini new file mode 100644 index 0000000..1feaff1 --- /dev/null +++ b/tests/configs/missing_box.ini @@ -0,0 +1,5 @@ +[suite] +foo=bar + +[test.foo] +foo=bar diff --git a/tests/configs/missing_box_image.ini b/tests/configs/missing_box_image.ini new file mode 100644 index 0000000..984d3d3 --- /dev/null +++ b/tests/configs/missing_box_image.ini @@ -0,0 +1,9 @@ +[box] +bootstrap=scripts/bootstrap.sh + +[box.tumbleweed] +name=mybox + +[suite.one_minion] +minions=1 +box=tumbleweed diff --git a/tests/configs/missing_box_name.ini b/tests/configs/missing_box_name.ini new file mode 100644 index 0000000..039bc79 --- /dev/null +++ b/tests/configs/missing_box_name.ini @@ -0,0 +1,9 @@ +[box] +bootstrap=scripts/bootstrap.sh + +[box.tumbleweed] +image=https://download.opensuse.org/repositories/home:/crameleon:/appliances/openSUSE_Tumbleweed/Tumbleweed.x86_64-libvirt.box + +[suite.one_minion] +minions=1 +box=tumbleweed diff --git a/tests/configs/missing_boxes.ini b/tests/configs/missing_boxes.ini new file mode 100644 index 0000000..531353b --- /dev/null +++ b/tests/configs/missing_boxes.ini @@ -0,0 +1,8 @@ +[box] +image=https://example.com/example.box + +[suite.example_suite] +minions=1 + +[test.example] +test=example.py diff --git a/tests/configs/missing_suite_box.ini b/tests/configs/missing_suite_box.ini new file mode 100644 index 0000000..ba224b4 --- /dev/null +++ b/tests/configs/missing_suite_box.ini @@ -0,0 +1,10 @@ +[box] +bootstrap=scripts/bootstrap.sh + +[box.tumbleweed] +name=tumblweed +image=https://download.opensuse.org/repositories/home:/crameleon:/appliances/openSUSE_Tumbleweed/Tumbleweed.x86_64-libvirt.box + +[suite.one_minion] +minions=1 + diff --git a/tests/configs/missing_suites.ini b/tests/configs/missing_suites.ini new file mode 100644 index 0000000..1afabaa --- /dev/null +++ b/tests/configs/missing_suites.ini @@ -0,0 +1,9 @@ +[box] +image=https://example.com/example.box + +[box.example] +name=ExampleBox +file=ExampleVagrantfile + +[test.example] +test=example.py diff --git a/tests/configs/undefined_suite_box.ini b/tests/configs/undefined_suite_box.ini new file mode 100644 index 0000000..a490f09 --- /dev/null +++ b/tests/configs/undefined_suite_box.ini @@ -0,0 +1,10 @@ +[box] +bootstrap=scripts/bootstrap.sh + +[box.tumbleweed] +name=tumblweed +image=https://download.opensuse.org/repositories/home:/crameleon:/appliances/openSUSE_Tumbleweed/Tumbleweed.x86_64-libvirt.box + +[suite.one_minion] +minions=1 +box=leap diff --git a/tests/scripts/bootstrap.sh b/tests/scripts/bootstrap.sh new file mode 100644 index 0000000..dc33ccc --- /dev/null +++ b/tests/scripts/bootstrap.sh @@ -0,0 +1 @@ +ln -s /vagrant /tmp/mysources diff --git a/tests/test_cli.py b/tests/test_cli.py new file mode 100644 index 0000000..308dc46 --- /dev/null +++ b/tests/test_cli.py @@ -0,0 +1,152 @@ +import pytest +import os +import vagrant +import dotenv +import libvirt + + +@pytest.fixture +def script(): + is_packaged = False + script = 'scullery' + if not is_packaged: + script = f'{script}.py' + return script + + +@pytest.fixture +def testbase(): + return os.path.abspath(os.path.dirname(os.getenv('PYTEST_CURRENT_TEST'))) + + +@pytest.fixture +def config(testbase, request): + return '{}/configs/{}.ini'.format(testbase, request.param) + + +@pytest.fixture +def virt(): + return libvirt.openReadOnly('qemu:///system') + +def test_no_arguments(script_runner, script): + result = script_runner.run(script) + assert result.success is False + assert 'the following arguments are required: --suite' in result.stderr + + +def test_no_config(script_runner, script): + result = script_runner.run(script, '--suite', 'foo', print_result=True) + assert result.success is False + assert 'Unable to locate configuration file' in result.stderr + + +@pytest.mark.parametrize('section,message', [ + ('box', 'No "box" section found in the configuration file'), + ('suites', 'No suites configured'), + ('boxes', 'No boxes configured'), + ('suite_box', 'Specified suite does not reference a box'), + ('box_name', 'Box configuration is incomplete'), + ('box_image', 'Box configuration is incomplete'), + ]) +def test_config_incomplete(script_runner, script, testbase, section, message): + configfile = '{}/configs/missing_{}.ini'.format(testbase, section) + result = script_runner.run(script, '--config', configfile, '--suite', 'one_minion') + assert result.success is False + assert message in result.stderr + + +@pytest.mark.parametrize('section,message', [ + ('suite_box', 'Suite references an undefined box') + ]) +def test_config_undefined(script_runner, script, testbase, section, message): + configfile = '{}/configs/undefined_{}.ini'.format(testbase, section) + result = script_runner.run(script, '--config', configfile, '--suite', 'one_minion') + assert result.success is False + assert message in result.stderr + + +@pytest.mark.parametrize('config', ['complete'], indirect=True) +@pytest.mark.parametrize('suite,report', [ + ('one_minion', "[Status(name='scullery-minion0', state='not_created', provider='libvirt')]"), + ('two_minions', "[Status(name='scullery-minion0', state='not_created', provider='libvirt'), Status(name='scullery-minion1', state='not_created', provider='libvirt')]"), + ('one_master', "[Status(name='scullery-master0', state='not_created', provider='libvirt')]"), + ('one_minion_one_master', "[Status(name='scullery-master0', state='not_created', provider='libvirt'), Status(name='scullery-minion0', state='not_created', provider='libvirt')]"), + ('two_minions_one_master', "[Status(name='scullery-master0', state='not_created', provider='libvirt'), Status(name='scullery-minion0', state='not_created', provider='libvirt'), Status(name='scullery-minion1', state='not_created', provider='libvirt')]") + ]) +def test_status_report_not_running(script_runner, script, config, suite, report): + result = script_runner.run(script, '--config', config, '--suite', suite, '--status') + assert result.success + assert result.stderr.endswith("INFO - main_interactive: Status report: {}\n".format(report)) + + +@pytest.mark.parametrize('config', ['complete'], indirect=True) +@pytest.mark.parametrize('suite', [ + 'one_minion', + 'two_minions', + 'one_master', + 'one_minion_one_master', + 'two_minions_one_master' + ]) +def test_launch_stop(script_runner, script, virt, config, suite): + cmd = (script, '--config', config, '--suite', suite) + result = script_runner.run(*cmd) + assert result.success + assert 'Launching {} ...\n'.format(suite) in result.stderr + domains = [] + print(virt.getURI()) + print(virt.listDomainsID()) + for domain in virt.listDomainsID(): + print(domain) + domains.append(virt.lookupByID(domain).name()) + print(str(domains)) + # consider refining this + assert any('scullery' in domain for domain in domains) + result = script_runner.run(*cmd, '--stop') + assert result.success + assert 'Destroying machines ...\n' in result.stderr + domains = [] + for domain in virt.listDomainsID(): + domains.append(virt.lookupByID(domain).name()) + assert not any('scullery' in domain for domain in domains) + + +@pytest.mark.parametrize('config', ['complete'], indirect=True) +@pytest.mark.parametrize('suite', [ + 'one_minion', + 'two_minions', + 'one_master', + 'one_minion_one_master', + 'two_minions_one_master' + ]) +def test_stop(script_runner, script, virt, config, suite): + cmd = (script, '--config', config, '--suite', suite, '--stop') + result = script_runner.run(*cmd) + assert result.success + domains = [] + for domain in virt.listDomainsID(): + domains.append(virt.lookupByID(domain).name()) + assert not any('scullery' in domain for domain in domains) + + +@pytest.mark.parametrize('config', ['complete'], indirect=True) +@pytest.mark.parametrize('suite,masters,minions', [ + ('one_minion', None, 'scullery-minion0'), + ('two_minions', None, 'scullery-minion0,scullery-minion1'), + ('one_master', 'scullery-master0', None), + ('one_minion_one_master', 'scullery-master0', 'scullery-minion0'), + ('two_minions_one_master', 'scullery-master0', 'scullery-minion0,scullery-minion1') + ]) +def test_envfile(script_runner, script, config, suite, masters, minions): + cmd = (script, '--config', config, '--suite', suite) + envfile = '.scullery_env' + result = script_runner.run(*cmd, '--env') + assert result.success + assert os.path.isfile(envfile) + envmap = dotenv.dotenv_values(envfile) + if masters is not None: + assert envmap['SCULLERY_MASTERS'] == masters + if minions is not None: + assert envmap['SCULLERY_MINIONS'] == minions + script_runner.run(*cmd, '--stop') + assert os.path.isfile(envfile) is False +