1from __future__ import unicode_literals
2
3import contextlib
4import os
5import shutil
6import sys
7import tempfile
8import uuid
9
10import six
11from six.moves import cStringIO as StringIO
12
13from rbtools.utils.filesystem import cleanup_tempfiles, make_tempdir
14from rbtools.testing import TestCase
15
16
17class RBTestBase(TestCase):
18    """Base class for RBTools tests.
19
20    Its side effect in that it change home directory before test suit will
21    run. This is because RBTools actively works with files and almost all
22    tests employ file I/O operations.
23    """
24
25    @classmethod
26    def setUpClass(cls):
27        super(RBTestBase, cls).setUpClass()
28
29        cls._cls_old_cwd = os.getcwd()
30
31    @classmethod
32    def tearDownClass(cls):
33        os.chdir(cls._cls_old_cwd)
34
35        super(RBTestBase, cls).tearDownClass()
36
37    def setUp(self):
38        super(RBTestBase, self).setUp()
39
40        self._old_cwd = os.getcwd()
41        self.old_home = os.environ['HOME']
42        self.set_user_home_tmp()
43
44    def tearDown(self):
45        super(RBTestBase, self).tearDown()
46
47        os.chdir(self._old_cwd)
48        cleanup_tempfiles()
49
50        if self.old_home:
51            os.environ['HOME'] = self.old_home
52
53    def chdir_tmp(self, dir=None):
54        """Changes current directory to a temporary directory."""
55        dirname = make_tempdir(parent=dir)
56        os.chdir(dirname)
57        return dirname
58
59    def gen_uuid(self):
60        """Generates UUID value which can be useful where some unique value
61        is required."""
62        return str(uuid.uuid4())
63
64    def get_user_home(self):
65        """Returns current user's home directory."""
66        return os.environ['HOME']
67
68    def reset_cl_args(self, values=[]):
69        """Replaces command-line arguments with new ones.
70
71        Useful for testing program's command-line options.
72        """
73        sys.argv = values
74
75    def set_user_home(self, path):
76        """Set home directory of current user."""
77        os.environ['HOME'] = path
78
79    def set_user_home_tmp(self):
80        """Set temporary directory as current user's home."""
81        self.set_user_home(make_tempdir())
82
83    def catch_output(self, func):
84        stdout = sys.stdout
85        outbuf = StringIO()
86        sys.stdout = outbuf
87        func()
88        sys.stdout = stdout
89        return outbuf.getvalue()
90
91    @contextlib.contextmanager
92    def reviewboardrc(self, data, use_temp_dir=False):
93        """Manage a temporary .reviewboardrc file.
94
95        Args:
96            data (dict)
97                A dictionary of key-value pairs to write into the
98                .reviewboardrc file.
99
100                A best effort attempt will be made to convert the value into
101                an appropriate string.
102
103            use_temp_dir (boolean)
104                A boolean that indicates if a temporary directory should be
105                created and used as the working directory for the context.
106        """
107        if use_temp_dir:
108            temp_dir = tempfile.mkdtemp()
109            cwd = os.getcwd()
110            os.chdir(temp_dir)
111
112        with open('.reviewboardrc', 'w') as fp:
113            for key, value in six.iteritems(data):
114                fp.write('%s = %r\n' % (key, value))
115
116        try:
117            yield
118        finally:
119            if use_temp_dir:
120                os.chdir(cwd)
121                shutil.rmtree(temp_dir)
122