test_test.py 13.4 KB
Newer Older
1 2 3
import os
import shutil
import tempfile
4
import unittest
5 6 7 8
try:
    from unittest import mock
except ImportError:
    import mock
9

10
from avocado.core import test, exceptions
11
from avocado.utils import astring, script
12 13 14 15 16 17 18 19 20 21

PASS_SCRIPT_CONTENTS = """#!/bin/sh
true
"""

FAIL_SCRIPT_CONTENTS = """#!/bin/sh
false
"""


22 23
class TestClassTestUnit(unittest.TestCase):

24 25 26 27
    class DummyTest(test.Test):
        def test(self):
            pass

28 29 30
    def setUp(self):
        self.tmpdir = tempfile.mkdtemp(prefix="avocado_" + __name__)

31 32 33 34 35 36 37 38 39 40 41 42 43
    def _get_fake_filename_test(self, name):

        class FakeFilename(test.Test):
            @property
            def filename(self):
                return name

            def test(self):
                pass

        tst_id = test.TestID("test", name=name)
        return FakeFilename("test", tst_id, base_logdir=self.tmpdir)

44 45 46
    def tearDown(self):
        shutil.rmtree(self.tmpdir)

47
    def test_ugly_name(self):
48 49
        def run(name, path_name):
            """ Initialize test and check the dirs were created """
50
            tst = self.DummyTest("test", test.TestID(1, name),
51
                                 base_logdir=self.tmpdir)
52 53 54
            self.assertEqual(os.path.basename(tst.logdir), path_name)
            self.assertTrue(os.path.exists(tst.logdir))
            self.assertEqual(os.path.dirname(os.path.dirname(tst.logdir)),
55 56
                             self.tmpdir)

57 58
        run("/absolute/path", "1-_absolute_path")
        run("./relative/path", "1-._relative_path")
59
        run("../../multi_level/relative/path",
60
            "1-.._.._multi_level_relative_path")
61 62
        # Greek word 'kosme'
        run("\xce\xba\xe1\xbd\xb9\xcf\x83\xce\xbc\xce\xb5",
63
            "1-\xce\xba\xe1\xbd\xb9\xcf\x83\xce\xbc\xce\xb5")
64 65 66 67 68 69 70
        # Particularly problematic noncharacters in 16-bit applications
        name = ("\xb7\x95\xef\xb7\x96\xef\xb7\x97\xef\xb7\x98\xef\xb7\x99"
                "\xef\xb7\x9a\xef\xb7\x9b\xef\xb7\x9c\xef\xb7\x9d\xef\xb7"
                "\x9e\xef\xb7\x9f\xef\xb7\xa0\xef\xb7\xa1\xef\xb7\xa2\xef"
                "\xb7\xa3\xef\xb7\xa4\xef\xb7\xa5\xef\xb7\xa6\xef\xb7\xa7"
                "\xef\xb7\xa8\xef\xb7\xa9\xef\xb7\xaa\xef\xb7\xab\xef\xb7"
                "\xac\xef\xb7\xad\xef\xb7\xae\xef\xb7\xaf")
71
        run(name, "1-" + name)
72

73
    def test_long_name(self):
74
        def check(uid, name, variant, exp_logdir):
75
            tst = self.DummyTest("test", test.TestID(uid, name, variant),
76
                                 base_logdir=self.tmpdir)
77 78 79 80 81
            self.assertEqual(os.path.basename(tst.logdir), exp_logdir)
            return tst

        # Everything fits
        check(1, "a" * 253, None, "1-" + ("a" * 253))
82 83
        check(2, "a" * 251, {"variant_id": 1}, "2-" + ("a" * 251) + ";1")
        check(99, "a" * 249, {"variant_id": 88}, "99-" + ("a" * 249) + ";88")
84
        # Shrink name
85
        check(3, "a" * 252, {"variant_id": 1}, "3-" + ('a' * 251) + ";1")
86
        # Shrink variant
87 88
        check("a" * 253, "whatever", {"variant_id": 99}, "a" * 253 + ";9")
        check("a" * 254, "whatever", {"variant_id": 99}, "a" * 254 + ";")
89
        # No variant
90 91
        tst = check("a" * 255, "whatever", {"variant_id": "whatever-else"},
                    "a" * 255)
92
        # Impossible to store (uid does not fit
93 94
        self.assertRaises(AssertionError, check, "a" * 256, "whatever",
                          {"variant_id": "else"}, None)
95 96 97

        self.assertEqual(os.path.basename(tst.workdir),
                         os.path.basename(tst.logdir))
98 99 100 101 102 103 104 105

    def test_data_dir(self):
        """
        Tests that a valid datadir exists follwowing the test filename
        """
        max_length_name = os.path.join(self.tmpdir, "a" * 250)
        tst = self._get_fake_filename_test(max_length_name)
        self.assertEqual(os.path.join(self.tmpdir, max_length_name + ".data"),
106
                         tst.datadir)
107 108 109 110 111 112 113

    def test_no_data_dir(self):
        """
        Tests that with a filename too long, no datadir is possible
        """
        above_limit_name = os.path.join(self.tmpdir, "a" * 251)
        tst = self._get_fake_filename_test(above_limit_name)
114
        self.assertFalse(tst.datadir)
115 116
        tst._record_reference_stdout       # Should do nothing
        tst._record_reference_stderr       # Should do nothing
117 118
        tst._record_reference_stdout()
        tst._record_reference_stderr()
119

120
    def test_all_dirs_exists_no_hang(self):
121 122 123
        with mock.patch('os.path.exists', return_value=True):
            self.assertRaises(exceptions.TestSetupFail, self.DummyTest, "test",
                              test.TestID(1, "name"), base_logdir=self.tmpdir)
124

125
    def test_try_override_test_variable(self):
126 127 128 129
        test = self.DummyTest(base_logdir=self.tmpdir)
        self.assertRaises(AttributeError, setattr, test, "name", "whatever")
        self.assertRaises(AttributeError, setattr, test, "status", "whatever")

130

131 132 133
class TestClassTest(unittest.TestCase):

    def setUp(self):
134 135
        class AvocadoPass(test.Test):

136
            def test(self):
137 138 139 140
                variable = True
                self.assertTrue(variable)
                self.whiteboard = 'foo'

141
        self.base_logdir = tempfile.mkdtemp(prefix='avocado_' + __name__)
142 143 144
        self.tst_instance_pass = AvocadoPass(base_logdir=self.base_logdir)
        self.tst_instance_pass.run_avocado()

145
    def test_class_attributes_name(self):
146
        self.assertEqual(self.tst_instance_pass.name, '0-AvocadoPass')
147

148
    def test_class_attributes_status(self):
149 150
        self.assertEqual(self.tst_instance_pass.status, 'PASS')

151
    def test_class_attributes_time_elapsed(self):
152 153
        self.assertIsInstance(self.tst_instance_pass.time_elapsed, float)

154
    def test_whiteboard_save(self):
155 156
        whiteboard_file = os.path.join(
            self.tst_instance_pass.logdir, 'whiteboard')
157 158 159 160 161
        self.assertTrue(os.path.isfile(whiteboard_file))
        with open(whiteboard_file, 'r') as whiteboard_file_obj:
            whiteboard_contents = whiteboard_file_obj.read().strip()
            self.assertTrue(whiteboard_contents, 'foo')

162
    def test_running_test_twice_with_the_same_uid_failure(self):
163 164 165 166 167 168 169
        class AvocadoPass(test.Test):

            def test(self):
                pass

        self.assertRaises(exceptions.TestSetupFail, AvocadoPass,
                          base_logdir=self.base_logdir)
170 171

    def tearDown(self):
172
        shutil.rmtree(self.base_logdir)
173 174


175
class SimpleTestClassTest(unittest.TestCase):
176 177

    def setUp(self):
178
        self.tmpdir = tempfile.mkdtemp(prefix='avocado_' + __name__)
179 180 181 182
        self.script = None

    def test_simple_test_pass_status(self):
        self.script = script.TemporaryScript(
183 184
            'avocado_pass.sh',
            PASS_SCRIPT_CONTENTS,
185
            'avocado_simpletest_unittest')
186 187 188 189 190 191
        self.script.save()
        tst_instance = test.SimpleTest(
            name=test.TestID(1, self.script.path),
            base_logdir=self.tmpdir)
        tst_instance.run_avocado()
        self.assertEqual(tst_instance.status, 'PASS')
192

193 194
    def test_simple_test_fail_status(self):
        self.script = script.TemporaryScript(
195 196
            'avocado_fail.sh',
            FAIL_SCRIPT_CONTENTS,
197
            'avocado_simpletest_unittest')
198 199 200
        self.script.save()
        tst_instance = test.SimpleTest(
            name=test.TestID(1, self.script.path),
201
            base_logdir=self.tmpdir)
202 203
        tst_instance.run_avocado()
        self.assertEqual(tst_instance.status, 'FAIL')
204 205

    def tearDown(self):
206 207
        if self.script is not None:
            self.script.remove()
208
        shutil.rmtree(self.tmpdir)
209

210

211
class MockingTest(unittest.TestCase):
212 213 214 215 216 217

    def setUp(self):
        self.tests = []

    def test_init(self):
        # No params
218
        self.tests.append(test.MockingTest())
219
        # Positional
220
        self.tests.append(test.MockingTest("test", test.TestID(1, "my_name"),
221 222 223
                                           {}, None, "1",
                                           None, None, "extra_param1",
                                           "extra_param2"))
224
        self.assertEqual(self.tests[-1].name, "1-my_name")
225
        # Kwargs
226
        self.tests.append(test.MockingTest(methodName="test",
227
                                           name=test.TestID(1, "my_name2"),
228 229 230 231
                                           params={}, base_logdir=None,
                                           tag="a", job=None, runner_queue=None,
                                           extra1="extra_param1",
                                           extra2="extra_param2"))
232
        self.assertEqual(self.tests[-1].name, "1-my_name2")
233 234
        # both (theoretically impossible in python, but valid for nasty tests)
        # keyword args are used as they explicitly represent what they mean
235 236 237 238
        self.tests.append(test.MockingTest("not used", "who cares", {}, None, "0",
                                           None, None, "extra_param1",
                                           "extra_param2",
                                           methodName="test",
239
                                           name=test.TestID(1, "my_name3"),
240 241 242 243
                                           params={}, base_logdir=None,
                                           tag="3", job=None, runner_queue=None,
                                           extra1="extra_param3",
                                           extra2="extra_param4"))
244
        self.assertEqual(self.tests[-1].name, "1-my_name3")
245
        # combination
246
        self.tests.append(test.MockingTest("test", test.TestID(1, "my_name4"),
247 248
                                           tag="321",
                                           other_param="Whatever"))
249
        self.assertEqual(self.tests[-1].name, "1-my_name4")
250 251 252 253 254 255
        # ugly combination (positional argument overrides kwargs, this only
        # happens when the substituted class reorders the positional arguments.
        # We try to first match keyword args and then fall-back to positional
        # ones.
        name = "positional_method_name_becomes_test_name"
        tag = "positional_base_logdir_becomes_tag"
256
        self.tests.append(test.MockingTest(test.TestID(1, name), None, None, tag,
257 258
                                           methodName="test",
                                           other_param="Whatever"))
259
        self.assertEqual(self.tests[-1].name, "1-" + name)
260 261 262 263

    def tearDown(self):
        for tst in self.tests:
            try:
264
                shutil.rmtree(os.path.dirname(os.path.dirname(tst.logdir)))
265 266 267
            except Exception:
                pass

L
Lukáš Doktor 已提交
268

269 270 271 272 273 274 275 276
class TestID(unittest.TestCase):

    def test_uid_name(self):
        uid = 1
        name = 'file.py:klass.test_method'
        test_id = test.TestID(uid, name)
        self.assertEqual(test_id.uid, 1)
        self.assertEqual(test_id.str_uid, '1')
277 278
        self.assertEqual(test_id.str_filesystem,
                         astring.string_to_safe_path('%s-%s' % (uid, name)))
279 280 281 282 283 284 285 286 287
        self.assertIs(test_id.variant, None)
        self.assertIs(test_id.str_variant, '')

    def test_uid_name_no_digits(self):
        uid = 1
        name = 'file.py:klass.test_method'
        test_id = test.TestID(uid, name, no_digits=2)
        self.assertEqual(test_id.uid, 1)
        self.assertEqual(test_id.str_uid, '01')
288 289
        self.assertEqual(test_id.str_filesystem,
                         astring.string_to_safe_path('%s-%s' % ('01', name)))
290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306
        self.assertIs(test_id.variant, None)
        self.assertIs(test_id.str_variant, '')

    def test_uid_name_large_digits(self):
        """
        Tests that when the filesystem can only cope with the size of
        the Test ID, that's the only thing that will be kept.
        """
        uid = 1
        name = 'test'
        test_id = test.TestID(uid, name, no_digits=255)
        self.assertEqual(test_id.uid, 1)
        self.assertEqual(test_id.str_uid, '%0255i' % uid)
        self.assertEqual(test_id.str_filesystem, '%0255i' % uid)
        self.assertIs(test_id.variant, None)
        self.assertIs(test_id.str_variant, '')

307
    def test_uid_name_uid_too_large_digits(self):
308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341
        """
        Tests that when the filesystem can not cope with the size of
        the Test ID, not even the test uid, an exception will be
        raised.
        """
        test_id = test.TestID(1, 'test', no_digits=256)
        self.assertRaises(AssertionError, lambda: test_id.str_filesystem)

    def test_uid_large_name(self):
        """
        Tests that when the filesystem can not cope with the size of
        the Test ID, the name will be shortened.
        """
        uid = 1
        name = 'test_' * 51     # 255 characters
        test_id = test.TestID(uid, name)
        self.assertEqual(test_id.uid, 1)
        # only 253 can fit for the test name
        self.assertEqual(test_id.str_filesystem, '%s-%s' % (uid, name[:253]))
        self.assertIs(test_id.variant, None)
        self.assertIs(test_id.str_variant, "")

    def test_uid_name_large_variant(self):
        """
        Tests that when the filesystem can not cope with the size of
        the Test ID, and a variant name is present, the name will be
        removed.
        """
        uid = 1
        name = 'test'
        variant_id = 'fast_' * 51    # 255 characters
        variant = {'variant_id': variant_id}
        test_id = test.TestID(uid, name, variant=variant)
        self.assertEqual(test_id.uid, 1)
342
        self.assertEqual(test_id.str_filesystem, '%s;%s' % (uid, variant_id[:253]))
343
        self.assertIs(test_id.variant, variant_id)
344
        self.assertEqual(test_id.str_variant, ";%s" % variant_id)
345 346


347 348
if __name__ == '__main__':
    unittest.main()