Consider different possibilities for tmpdir.
[leap_pycommon.git] / src / leap / common / testing / basetest.py
1 # -*- coding: utf-8 -*-
2 # basetest.py
3 # Copyright (C) 2013 LEAP
4 #
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation, either version 3 of the License, or
8 # (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 """
18 Common testing facilities
19 """
20 import os
21 import platform
22 import shutil
23 import tempfile
24
25 try:
26     import unittest2 as unittest
27 except ImportError:
28     import unittest
29
30 from leap.common.check import leap_assert
31 from leap.common.files import mkdir_p, check_and_fix_urw_only
32
33
34 class BaseLeapTest(unittest.TestCase):
35     """
36     Base Leap TestCase
37     """
38     __name__ = "leap_test"
39     _system = platform.system()
40
41     @classmethod
42     def setUpClass(cls):
43         cls.setUpEnv()
44
45     @classmethod
46     def tearDownClass(cls):
47         cls.tearDownEnv()
48
49     @classmethod
50     def setUpEnv(cls):
51         """
52         Sets up common facilities for testing this TestCase:
53         - custom PATH and HOME environmental variables
54         - creates a temporal folder to which those point.
55         It saves the old path and home vars so they can be restored later.
56         """
57         cls.old_path = os.environ['PATH']
58         cls.old_home = os.environ['HOME']
59         cls.tempdir = tempfile.mkdtemp(prefix="leap_tests-")
60         cls.home = cls.tempdir
61         bin_tdir = os.path.join(
62             cls.tempdir,
63             'bin')
64         os.environ["PATH"] = bin_tdir
65         os.environ["HOME"] = cls.tempdir
66
67     @classmethod
68     def tearDownEnv(cls):
69         """
70         Cleanup common facilities used for testing this TestCase:
71         - restores the default PATH and HOME variables
72         - removes the temporal folder
73         """
74         os.environ["PATH"] = cls.old_path
75         os.environ["HOME"] = cls.old_home
76         # safety check! please do not wipe my home...
77         # XXX needs to adapt to non-linuces
78         leap_assert(
79             cls.tempdir.startswith('/tmp/leap_tests-') or
80             (cls.tempdir.startswith('/tmp/') and
81              cls.tempdir.startswith(tempfile.gettempdir()) and
82              'leap_tests-' in cls.tempdir) or
83             cls.tempdir.startswith('/var/folder'),
84             "beware! tried to remove a dir which does not "
85             "live in temporal folder!")
86         shutil.rmtree(cls.tempdir)
87
88     # you have to override these methods
89     # this way we ensure we did not put anything
90     # here that you can forget to call.
91
92     def setUp(self):
93         """not implemented"""
94         raise NotImplementedError("abstract base class")
95
96     def tearDown(self):
97         """not implemented"""
98         raise NotImplementedError("abstract base class")
99
100     #
101     # helper methods
102     #
103
104     def _missing_test_for_plat(self, do_raise=False):
105         """
106         Raises NotImplementedError for this platform
107         if do_raise is True
108
109         :param do_raise: flag to actually raise exception
110         :type do_raise: bool
111         """
112         if do_raise:
113             raise NotImplementedError(
114                 "This test is not implemented "
115                 "for the running platform: %s" %
116                 self._system)
117
118     def get_tempfile(self, filename):
119         """
120         Returns the path of a given filename
121         prepending the temporal dir associated with this
122         TestCase
123
124         :param filename: the filename
125         :type filename: str
126         """
127         return os.path.join(self.tempdir, filename)
128
129     def touch(self, filepath):
130         """
131         Touches a filepath, creating folders along
132         the way if needed.
133
134         :param filepath: path to be touched
135         :type filepath: str
136         """
137         folder, filename = os.path.split(filepath)
138         if not os.path.isdir(folder):
139             mkdir_p(folder)
140         self.assertTrue(os.path.isdir(folder))
141         with open(filepath, 'w') as fp:
142             fp.write(' ')
143         self.assertTrue(os.path.isfile(filepath))
144
145     def chmod600(self, filepath):
146         """
147         Chmods 600 a file
148
149         :param filepath: filepath to be chmodded
150         :type filepath: str
151         """
152         check_and_fix_urw_only(filepath)