提交 2b1e807b 编写于 作者: R Rudá Moura

avocado.utils.script: Introduce script module.

Introduce avocado.utils.script module to handle the creation
of scripts stored in the file system.

The module includes a flexible class for creating generic scripts and
 includes utilities functions too. Some examples:

    CONTENT = """
    #!/bin/sh
    echo "Hi There!"
    """

    x = avocado.utils.script.Script('/var/tmp/test.sh', CONTENT)
    x.save()
    ... do something with x, like run it ...
    x.remove()

    t = avocado.utils.script.make_temp_script('test.sh', CONTENT)
    ... do something with y, like run it ...

Avocado functional tests makes use of script creation,
so we will handle these creation using this proper module.
Signed-off-by: NRudá Moura <rmoura@redhat.com>
上级 d7ad156d
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
# See LICENSE for more details.
#
# Copyright: Red Hat Inc. 2014
# Author: Ruda Moura <rmoura@redhat.com>
"""
Module to handle scripts creation.
"""
import os
import tempfile
import shutil
class Script(object):
"""
Class that represents a script.
"""
def __init__(self, path, content, mode=0775):
"""
Creates an instance of :class:`Script`.
Note that when the instance inside a with statement, it will
automatically call save() and then remove() for you.
:param path: the script file name.
:param content: the script content.
:param mode: set file mode, default to 0775.
"""
self.path = path
self.content = content
self.mode = mode
self.stored = False
def __repr__(self):
return '%s(path="%s", stored=%s)' % (self.__class__.__name__,
self.path,
self.stored)
def __str__(self):
return self.path
def __enter__(self):
self.save()
return self
def __exit__(self, exc_type, exc_value, exc_traceback):
self.remove()
def save(self):
"""
Store script to file system.
:return: `True` if script has been stored, otherwise `False`.
"""
if not os.path.isdir(os.path.dirname(self.path)):
os.makedirs(os.path.dirname(self.path))
with open(self.path, 'w') as fd:
fd.write(self.content)
os.chmod(self.path, self.mode)
self.stored = True
return self.stored
def remove(self):
"""
Remove script from the file system.
:return: `True` if script has been removed, otherwise `False`.
"""
if os.path.exists(self.path):
os.remove(self.path)
self.stored = False
return True
else:
return False
class TemporaryScript(Script):
"""
Class that represents a temporary script.
"""
def __init__(self, name, content, prefix='avocado_script', mode=0775):
"""
Creates an instance of :class:`TemporaryScript`.
Note that when the instance inside a with statement, it will
automatically call save() and then remove() for you.
When the instance object is garbage collected, it will automatically
call remove() for you.
:param name: the script file name.
:param content: the script content.
:param prefix: prefix for the temporary directory name.
:param mode: set file mode, default to 0775.
"""
tmpdir = tempfile.mkdtemp(prefix=prefix)
self.path = os.path.join(tmpdir, name)
self.content = content
self.mode = mode
self.stored = False
def __del__(self):
self.remove()
def remove(self):
if os.path.exists(os.path.dirname(self.path)):
shutil.rmtree(os.path.dirname(self.path))
self.stored = False
def make_script(path, content, mode=0775):
"""
Creates a new script stored in the file system.
:param path: the script file name.
:param contet: the script content.
:param mode: set file mode, default to 0775.
:return: the script path.
"""
scpt = Script(path, content, mode=mode)
scpt.save()
return scpt.path
def make_temp_script(name, content, prefix='avocado_script', mode=0775):
"""
Creates a new temporary script stored in the file system.
:param path: the script file name.
:param contet: the script content.
:param prefix: the directory prefix Default to 'avocado_script'.
:param mode: set file mode, default to 0775.
:return: the script path.
"""
scpt = TemporaryScript(name, content, prefix=prefix, mode=mode)
scpt.save()
return scpt.path
......@@ -30,6 +30,7 @@ if os.path.isdir(os.path.join(basedir, 'avocado')):
sys.path.append(basedir)
from avocado.utils import process
from avocado.utils import script
PASS_SCRIPT_CONTENTS = """#!/bin/sh
true
......@@ -212,20 +213,20 @@ class RunnerOperationTest(unittest.TestCase):
class RunnerDropinTest(unittest.TestCase):
def setUp(self):
self.base_logdir = tempfile.mkdtemp(prefix='avocado_dropin_functional')
self.pass_script = os.path.join(self.base_logdir, 'avocado_pass.sh')
with open(self.pass_script, 'w') as pass_script_obj:
pass_script_obj.write(PASS_SCRIPT_CONTENTS)
os.chmod(self.pass_script, 0775)
self.fail_script = os.path.join(self.base_logdir, 'avocado_fail.sh')
with open(self.fail_script, 'w') as fail_script_obj:
fail_script_obj.write(FAIL_SCRIPT_CONTENTS)
os.chmod(self.fail_script, 0775)
self.pass_script = script.TemporaryScript(
'avocado_pass.sh',
PASS_SCRIPT_CONTENTS,
'avocado_dropin_functional')
self.pass_script.save()
self.fail_script = script.TemporaryScript(
'avocado_fail.sh',
FAIL_SCRIPT_CONTENTS,
'avocado_dropin_functional')
self.fail_script.save()
def test_dropin_pass(self):
os.chdir(basedir)
cmd_line = './scripts/avocado run %s' % self.pass_script
cmd_line = './scripts/avocado run %s' % self.pass_script.path
result = process.run(cmd_line, ignore_status=True)
expected_rc = 0
self.assertEqual(result.exit_status, expected_rc,
......@@ -234,7 +235,7 @@ class RunnerDropinTest(unittest.TestCase):
def test_dropin_fail(self):
os.chdir(basedir)
cmd_line = './scripts/avocado run %s' % self.fail_script
cmd_line = './scripts/avocado run %s' % self.fail_script.path
result = process.run(cmd_line, ignore_status=True)
expected_rc = 1
self.assertEqual(result.exit_status, expected_rc,
......@@ -277,8 +278,8 @@ class RunnerDropinTest(unittest.TestCase):
"Avocado did not return rc %d:\n%s" % (expected_rc, result))
def tearDown(self):
if os.path.isdir(self.base_logdir):
shutil.rmtree(self.base_logdir, ignore_errors=True)
self.pass_script.remove()
self.fail_script.remove()
class ExternalPluginsTest(unittest.TestCase):
......@@ -287,10 +288,9 @@ class ExternalPluginsTest(unittest.TestCase):
self.base_sourcedir = tempfile.mkdtemp(prefix='avocado_source_plugins')
def test_void_plugin(self):
self.void_plugin = os.path.join(self.base_sourcedir, 'avocado_void.py')
with open(self.void_plugin, 'w') as void:
void.write(VOID_PLUGIN_CONTENTS)
os.chmod(self.void_plugin, 0775)
self.void_plugin = script.make_script(
os.path.join(self.base_sourcedir, 'avocado_void.py'),
VOID_PLUGIN_CONTENTS)
os.chdir(basedir)
cmd_line = './scripts/avocado --plugins %s plugins' % self.base_sourcedir
result = process.run(cmd_line, ignore_status=True)
......@@ -298,11 +298,9 @@ class ExternalPluginsTest(unittest.TestCase):
self.assertIn(expected_output, result.stdout)
def test_syntax_error_plugin(self):
self.syntax_err_plugin = os.path.join(self.base_sourcedir, 'avocado_syntax_err.py')
with open(self.syntax_err_plugin, 'w') as synerr:
synerr.write(SYNTAX_ERROR_PLUGIN_CONTENTS)
os.chmod(self.syntax_err_plugin, 0775)
self.syntax_err_plugin = script.make_script(
os.path.join(self.base_sourcedir, 'avocado_syntax_err.py'),
SYNTAX_ERROR_PLUGIN_CONTENTS)
os.chdir(basedir)
cmd_line = './scripts/avocado --plugins %s' % self.base_sourcedir
result = process.run(cmd_line, ignore_status=True)
......@@ -310,10 +308,9 @@ class ExternalPluginsTest(unittest.TestCase):
self.assertIn(expected_output, result.stderr)
def test_hello_plugin(self):
self.hello_plugin = os.path.join(self.base_sourcedir, 'avocado_hello.py')
with open(self.hello_plugin, 'w') as hello:
hello.write(HELLO_PLUGIN_CONTENTS)
os.chmod(self.hello_plugin, 0775)
self.hello_plugin = script.make_script(
os.path.join(self.base_sourcedir, 'avocado_hello.py'),
HELLO_PLUGIN_CONTENTS)
os.chdir(basedir)
cmd_line = './scripts/avocado --plugins %s hello' % self.base_sourcedir
result = process.run(cmd_line, ignore_status=True)
......
......@@ -28,6 +28,7 @@ if os.path.isdir(os.path.join(basedir, 'avocado')):
from avocado.version import VERSION
from avocado.utils import process
from avocado.utils import script
SCRIPT_CONTENT = """#!/bin/sh
echo "Avocado Version: $AVOCADO_VERSION"
......@@ -54,15 +55,15 @@ test "$AVOCADO_VERSION" = "{version}" -a \
class EnvironmentVariablesTest(unittest.TestCase):
def setUp(self):
self.base_logdir = tempfile.mkdtemp(prefix='avocado_env_vars_functional')
self.script = os.path.join(self.base_logdir, 'version.sh')
with open(self.script, 'w') as script_obj:
script_obj.write(SCRIPT_CONTENT)
os.chmod(self.script, 0775)
self.script = script.TemporaryScript(
'version.sh',
SCRIPT_CONTENT,
'avocado_env_vars_functional')
self.script.save()
def test_environment_vars(self):
os.chdir(basedir)
cmd_line = './scripts/avocado run %s' % self.script
cmd_line = './scripts/avocado run %s' % self.script.path
result = process.run(cmd_line, ignore_status=True)
expected_rc = 0
self.assertEqual(result.exit_status, expected_rc,
......@@ -70,8 +71,7 @@ class EnvironmentVariablesTest(unittest.TestCase):
(expected_rc, result))
def tearDown(self):
if os.path.isdir(self.base_logdir):
shutil.rmtree(self.base_logdir, ignore_errors=True)
self.script.remove()
if __name__ == '__main__':
......
......@@ -27,6 +27,7 @@ if os.path.isdir(os.path.join(basedir, 'avocado')):
sys.path.append(basedir)
from avocado.utils import process
from avocado.utils import script
OUTPUT_SCRIPT_CONTENTS = """#!/bin/sh
echo "Hello, avocado!"
......@@ -36,15 +37,15 @@ echo "Hello, avocado!"
class RunnerDropinTest(unittest.TestCase):
def setUp(self):
self.base_logdir = tempfile.mkdtemp(prefix='avocado_output_check_functional')
self.output_script = os.path.join(self.base_logdir, 'output_check.sh')
with open(self.output_script, 'w') as output_script_obj:
output_script_obj.write(OUTPUT_SCRIPT_CONTENTS)
os.chmod(self.output_script, 0775)
self.output_script = script.TemporaryScript(
'output_check.sh',
OUTPUT_SCRIPT_CONTENTS,
'avocado_output_check_functional')
self.output_script.save()
def test_output_record_none(self):
os.chdir(basedir)
cmd_line = './scripts/avocado run %s --output-check-record none' % self.output_script
cmd_line = './scripts/avocado run %s --output-check-record none' % self.output_script.path
result = process.run(cmd_line, ignore_status=True)
expected_rc = 0
self.assertEqual(result.exit_status, expected_rc,
......@@ -57,7 +58,7 @@ class RunnerDropinTest(unittest.TestCase):
def test_output_record_stdout(self):
os.chdir(basedir)
cmd_line = './scripts/avocado run %s --output-check-record stdout' % self.output_script
cmd_line = './scripts/avocado run %s --output-check-record stdout' % self.output_script.path
result = process.run(cmd_line, ignore_status=True)
expected_rc = 0
self.assertEqual(result.exit_status, expected_rc,
......@@ -70,7 +71,7 @@ class RunnerDropinTest(unittest.TestCase):
def test_output_record_all(self):
os.chdir(basedir)
cmd_line = './scripts/avocado run %s --output-check-record all' % self.output_script
cmd_line = './scripts/avocado run %s --output-check-record all' % self.output_script.path
result = process.run(cmd_line, ignore_status=True)
expected_rc = 0
self.assertEqual(result.exit_status, expected_rc,
......@@ -83,7 +84,7 @@ class RunnerDropinTest(unittest.TestCase):
def test_output_record_and_check(self):
self.test_output_record_all()
cmd_line = './scripts/avocado run %s' % self.output_script
cmd_line = './scripts/avocado run %s' % self.output_script.path
result = process.run(cmd_line, ignore_status=True)
expected_rc = 0
self.assertEqual(result.exit_status, expected_rc,
......@@ -93,10 +94,10 @@ class RunnerDropinTest(unittest.TestCase):
def test_output_tamper_stdout(self):
self.test_output_record_all()
tampered_msg = "I PITY THE FOOL THAT STANDS ON MY WAY!"
stdout_file = os.path.join("%s.data/stdout.expected" % self.output_script)
stdout_file = os.path.join("%s.data/stdout.expected" % self.output_script.path)
with open(stdout_file, 'w') as stdout_file_obj:
stdout_file_obj.write(tampered_msg)
cmd_line = './scripts/avocado run %s --xunit -' % self.output_script
cmd_line = './scripts/avocado run %s --xunit -' % self.output_script.path
result = process.run(cmd_line, ignore_status=True)
expected_rc = 1
self.assertEqual(result.exit_status, expected_rc,
......@@ -107,10 +108,10 @@ class RunnerDropinTest(unittest.TestCase):
def test_disable_output_check(self):
self.test_output_record_all()
tampered_msg = "I PITY THE FOOL THAT STANDS ON MY WAY!"
stdout_file = os.path.join("%s.data/stdout.expected" % self.output_script)
stdout_file = os.path.join("%s.data/stdout.expected" % self.output_script.path)
with open(stdout_file, 'w') as stdout_file_obj:
stdout_file_obj.write(tampered_msg)
cmd_line = './scripts/avocado run %s --disable-output-check --xunit -' % self.output_script
cmd_line = './scripts/avocado run %s --disable-output-check --xunit -' % self.output_script.path
result = process.run(cmd_line, ignore_status=True)
expected_rc = 0
self.assertEqual(result.exit_status, expected_rc,
......@@ -119,8 +120,7 @@ class RunnerDropinTest(unittest.TestCase):
self.assertNotIn(tampered_msg, result.stdout)
def tearDown(self):
if os.path.isdir(self.base_logdir):
shutil.rmtree(self.base_logdir, ignore_errors=True)
self.output_script.remove()
if __name__ == '__main__':
unittest.main()
......@@ -28,6 +28,7 @@ if os.path.isdir(os.path.join(basedir, 'avocado')):
sys.path.append(basedir)
from avocado import test
from avocado.utils import script
@unittest.skip("This class should not be tested per se")
......@@ -116,23 +117,26 @@ class TestClassTest(unittest.TestCase):
class DropinClassTest(unittest.TestCase):
def setUp(self):
self.base_logdir = tempfile.mkdtemp(prefix='avocado_dropin_unittest')
self.pass_script = os.path.join(self.base_logdir, 'avocado_pass.sh')
with open(self.pass_script, 'w') as pass_script_obj:
pass_script_obj.write(PASS_SCRIPT_CONTENTS)
os.chmod(self.pass_script, 0775)
self.fail_script = os.path.join(self.base_logdir, 'avocado_fail.sh')
with open(self.fail_script, 'w') as fail_script_obj:
fail_script_obj.write(FAIL_SCRIPT_CONTENTS)
os.chmod(self.fail_script, 0775)
self.tst_instance_pass = test.DropinTest(path=self.pass_script,
base_logdir=self.base_logdir)
self.pass_script = script.TemporaryScript(
'avocado_pass.sh',
PASS_SCRIPT_CONTENTS,
'avocado_dropin_unittest')
self.pass_script.save()
self.fail_script = script.TemporaryScript(
'avocado_fail.sh',
FAIL_SCRIPT_CONTENTS,
'avocado_dropin_unittest')
self.fail_script.save()
self.tst_instance_pass = test.DropinTest(
path=self.pass_script.path,
base_logdir=os.path.dirname(self.pass_script.path))
self.tst_instance_pass.run_avocado()
self.tst_instance_fail = test.DropinTest(path=self.fail_script,
base_logdir=self.base_logdir)
self.tst_instance_fail = test.DropinTest(
path=self.fail_script.path,
base_logdir=os.path.dirname(self.fail_script.path))
self.tst_instance_fail.run_avocado()
def testDropinPassStatus(self):
......@@ -142,8 +146,8 @@ class DropinClassTest(unittest.TestCase):
self.assertEqual(self.tst_instance_fail.status, 'FAIL')
def tearDown(self):
if os.path.isdir(self.base_logdir):
shutil.rmtree(self.base_logdir, ignore_errors=True)
self.pass_script.remove()
self.fail_script.remove()
if __name__ == '__main__':
unittest.main()
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册