PageRenderTime 27ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/tests/plugin_tests.py

https://gitlab.com/pbandark/sos
Python | 341 lines | 261 code | 68 blank | 12 comment | 3 complexity | 50a39496dcee42730867da0c94b192ed MD5 | raw file
  1. import unittest
  2. import os
  3. import tempfile
  4. # PYCOMPAT
  5. import six
  6. try:
  7. from StringIO import StringIO
  8. except:
  9. from io import StringIO
  10. from sos.plugins import Plugin, regex_findall, _mangle_command
  11. from sos.archive import TarFileArchive
  12. import sos.policies
  13. PATH = os.path.dirname(__file__)
  14. def j(filename):
  15. return os.path.join(PATH, filename)
  16. def create_file(size):
  17. f = tempfile.NamedTemporaryFile(delete=False)
  18. f.write(six.b("*" * size * 1024 * 1024))
  19. f.flush()
  20. f.close()
  21. return f.name
  22. class MockArchive(TarFileArchive):
  23. def __init__(self):
  24. self.m = {}
  25. self.strings = {}
  26. def name(self):
  27. return "mock.archive"
  28. def add_file(self, src, dest=None):
  29. if not dest:
  30. dest = src
  31. self.m[src] = dest
  32. def add_string(self, content, dest):
  33. self.m[dest] = content
  34. def add_link(self, dest, link_name):
  35. pass
  36. def open_file(self, name):
  37. return open(self.m.get(name), 'r')
  38. def close(self):
  39. pass
  40. def compress(self, method):
  41. pass
  42. class MockPlugin(Plugin):
  43. option_list = [("opt", 'an option', 'fast', None),
  44. ("opt2", 'another option', 'fast', False)]
  45. def setup(self):
  46. pass
  47. class NamedMockPlugin(Plugin):
  48. """This plugin has a description."""
  49. plugin_name = "testing"
  50. def setup(self):
  51. pass
  52. class ForbiddenMockPlugin(Plugin):
  53. """This plugin has a description."""
  54. plugin_name = "forbidden"
  55. def setup(self):
  56. self.add_forbidden_path("tests")
  57. class EnablerPlugin(Plugin):
  58. def is_installed(self, pkg):
  59. return self.is_installed
  60. class MockOptions(object):
  61. pass
  62. class PluginToolTests(unittest.TestCase):
  63. def test_regex_findall(self):
  64. test_s = "\n".join(['this is only a test', 'there are only two lines'])
  65. test_fo = StringIO(test_s)
  66. matches = regex_findall(r".*lines$", test_fo)
  67. self.assertEquals(matches, ['there are only two lines'])
  68. def test_regex_findall_miss(self):
  69. test_s = "\n".join(['this is only a test', 'there are only two lines'])
  70. test_fo = StringIO(test_s)
  71. matches = regex_findall(r".*not_there$", test_fo)
  72. self.assertEquals(matches, [])
  73. def test_regex_findall_bad_input(self):
  74. matches = regex_findall(r".*", None)
  75. self.assertEquals(matches, [])
  76. matches = regex_findall(r".*", [])
  77. self.assertEquals(matches, [])
  78. matches = regex_findall(r".*", 1)
  79. self.assertEquals(matches, [])
  80. def test_mangle_command(self):
  81. name_max = 255
  82. self.assertEquals("foo", _mangle_command("/usr/bin/foo", name_max))
  83. self.assertEquals("foo_-x", _mangle_command("/usr/bin/foo -x", name_max))
  84. self.assertEquals("foo_--verbose", _mangle_command("/usr/bin/foo --verbose", name_max))
  85. self.assertEquals("foo_.path.to.stuff", _mangle_command("/usr/bin/foo /path/to/stuff", name_max))
  86. longcmd ="foo is " + "a" * 256 + " long_command"
  87. expected = longcmd[0:name_max].replace(' ', '_')
  88. self.assertEquals(expected, _mangle_command(longcmd, name_max))
  89. class PluginTests(unittest.TestCase):
  90. sysroot = os.getcwd()
  91. def setUp(self):
  92. self.mp = MockPlugin({
  93. 'cmdlineopts': MockOptions(),
  94. 'sysroot': self.sysroot
  95. })
  96. self.mp.archive = MockArchive()
  97. def test_plugin_default_name(self):
  98. p = MockPlugin({'sysroot': self.sysroot})
  99. self.assertEquals(p.name(), "mockplugin")
  100. def test_plugin_set_name(self):
  101. p = NamedMockPlugin({'sysroot': self.sysroot})
  102. self.assertEquals(p.name(), "testing")
  103. def test_plugin_no_descrip(self):
  104. p = MockPlugin({'sysroot': self.sysroot})
  105. self.assertEquals(p.get_description(), "<no description available>")
  106. def test_plugin_no_descrip(self):
  107. p = NamedMockPlugin({'sysroot': self.sysroot})
  108. self.assertEquals(p.get_description(), "This plugin has a description.")
  109. def test_set_plugin_option(self):
  110. p = MockPlugin({'sysroot': self.sysroot})
  111. p.set_option("opt", "testing")
  112. self.assertEquals(p.get_option("opt"), "testing")
  113. def test_set_nonexistant_plugin_option(self):
  114. p = MockPlugin({'sysroot': self.sysroot})
  115. self.assertFalse(p.set_option("badopt", "testing"))
  116. def test_get_nonexistant_plugin_option(self):
  117. p = MockPlugin({'sysroot': self.sysroot})
  118. self.assertEquals(p.get_option("badopt"), 0)
  119. def test_get_unset_plugin_option(self):
  120. p = MockPlugin({'sysroot': self.sysroot})
  121. self.assertEquals(p.get_option("opt"), 0)
  122. def test_get_unset_plugin_option_with_default(self):
  123. # this shows that even when we pass in a default to get,
  124. # we'll get the option's default as set in the plugin
  125. # this might not be what we really want
  126. p = MockPlugin({'sysroot': self.sysroot})
  127. self.assertEquals(p.get_option("opt", True), True)
  128. def test_get_unset_plugin_option_with_default_not_none(self):
  129. # this shows that even when we pass in a default to get,
  130. # if the plugin default is not None
  131. # we'll get the option's default as set in the plugin
  132. # this might not be what we really want
  133. p = MockPlugin({'sysroot': self.sysroot})
  134. self.assertEquals(p.get_option("opt2", True), False)
  135. def test_get_option_as_list_plugin_option(self):
  136. p = MockPlugin({'sysroot': self.sysroot})
  137. p.set_option("opt", "one,two,three")
  138. self.assertEquals(p.get_option_as_list("opt"), ['one', 'two', 'three'])
  139. def test_get_option_as_list_plugin_option_default(self):
  140. p = MockPlugin({'sysroot': self.sysroot})
  141. self.assertEquals(p.get_option_as_list("opt", default=[]), [])
  142. def test_get_option_as_list_plugin_option_not_list(self):
  143. p = MockPlugin({'sysroot': self.sysroot})
  144. p.set_option("opt", "testing")
  145. self.assertEquals(p.get_option_as_list("opt"), ['testing'])
  146. def test_copy_dir(self):
  147. self.mp._do_copy_path("tests")
  148. self.assertEquals(self.mp.archive.m["tests/plugin_tests.py"], 'tests/plugin_tests.py')
  149. def test_copy_dir_bad_path(self):
  150. self.mp._do_copy_path("not_here_tests")
  151. self.assertEquals(self.mp.archive.m, {})
  152. def test_copy_dir_forbidden_path(self):
  153. p = ForbiddenMockPlugin({
  154. 'cmdlineopts': MockOptions(),
  155. 'sysroot': self.sysroot
  156. })
  157. p.archive = MockArchive()
  158. p.setup()
  159. p._do_copy_path("tests")
  160. self.assertEquals(p.archive.m, {})
  161. class AddCopySpecTests(unittest.TestCase):
  162. expect_paths = set(['tests/tail_test.txt'])
  163. def setUp(self):
  164. self.mp = MockPlugin({
  165. 'cmdlineopts': MockOptions(),
  166. 'sysroot': os.getcwd()
  167. })
  168. self.mp.archive = MockArchive()
  169. def assert_expect_paths(self):
  170. def pathmunge(path):
  171. if path[0] == '/':
  172. path = path[1:]
  173. return os.path.join(self.mp.sysroot, path)
  174. expected_paths = set(map(pathmunge, self.expect_paths))
  175. self.assertEquals(self.mp.copy_paths, expected_paths)
  176. # add_copy_spec()
  177. def test_single_file(self):
  178. self.mp.add_copy_spec('tests/tail_test.txt')
  179. self.assert_expect_paths()
  180. def test_glob_file(self):
  181. self.mp.add_copy_spec('tests/tail_test.*')
  182. self.assert_expect_paths()
  183. def test_single_file_under_limit(self):
  184. self.mp.add_copy_spec_limit("tests/tail_test.txt", 1)
  185. self.assert_expect_paths()
  186. # add_copy_spec_limit()
  187. def test_single_file_over_limit(self):
  188. self.mp.sysroot = '/'
  189. fn = create_file(2) # create 2MB file, consider a context manager
  190. self.mp.add_copy_spec_limit(fn, 1)
  191. content, fname = self.mp.copy_strings[0]
  192. self.assertTrue("tailed" in fname)
  193. self.assertTrue("tmp" in fname)
  194. self.assertTrue("/" not in fname)
  195. self.assertEquals(1024 * 1024, len(content))
  196. os.unlink(fn)
  197. def test_bad_filename(self):
  198. self.mp.sysroot = '/'
  199. self.assertFalse(self.mp.add_copy_spec_limit('', 1))
  200. self.assertFalse(self.mp.add_copy_spec_limit(None, 1))
  201. def test_glob_file_over_limit(self):
  202. self.mp.sysroot = '/'
  203. # assume these are in /tmp
  204. fn = create_file(2)
  205. fn2 = create_file(2)
  206. self.mp.add_copy_spec_limit("/tmp/tmp*", 1)
  207. self.assertEquals(len(self.mp.copy_strings), 1)
  208. content, fname = self.mp.copy_strings[0]
  209. self.assertTrue("tailed" in fname)
  210. self.assertEquals(1024 * 1024, len(content))
  211. os.unlink(fn)
  212. os.unlink(fn2)
  213. class CheckEnabledTests(unittest.TestCase):
  214. def setUp(self):
  215. self.mp = EnablerPlugin({
  216. 'policy': sos.policies.load(),
  217. 'sysroot': os.getcwd()
  218. })
  219. def test_checks_for_file(self):
  220. f = j("tail_test.txt")
  221. self.mp.files = (f,)
  222. self.assertTrue(self.mp.check_enabled())
  223. def test_checks_for_package(self):
  224. self.mp.packages = ('foo',)
  225. self.assertTrue(self.mp.check_enabled())
  226. def test_allows_bad_tuple(self):
  227. f = j("tail_test.txt")
  228. self.mp.files = (f)
  229. self.mp.packages = ('foo')
  230. self.assertTrue(self.mp.check_enabled())
  231. def test_enabled_by_default(self):
  232. self.assertTrue(self.mp.check_enabled())
  233. class RegexSubTests(unittest.TestCase):
  234. def setUp(self):
  235. self.mp = MockPlugin({
  236. 'cmdlineopts': MockOptions(),
  237. 'sysroot': os.getcwd()
  238. })
  239. self.mp.archive = MockArchive()
  240. def test_file_never_copied(self):
  241. self.assertEquals(0, self.mp.do_file_sub("never_copied", r"^(.*)$", "foobar"))
  242. def test_no_replacements(self):
  243. self.mp.add_copy_spec(j("tail_test.txt"))
  244. self.mp.collect()
  245. replacements = self.mp.do_file_sub(j("tail_test.txt"), r"wont_match", "foobar")
  246. self.assertEquals(0, replacements)
  247. def test_replacements(self):
  248. # test uses absolute paths
  249. self.mp.sysroot = '/'
  250. self.mp.add_copy_spec(j("tail_test.txt"))
  251. self.mp.collect()
  252. replacements = self.mp.do_file_sub(j("tail_test.txt"), r"(tail)", "foobar")
  253. self.assertEquals(1, replacements)
  254. self.assertTrue("foobar" in self.mp.archive.m.get(j('tail_test.txt')))
  255. if __name__ == "__main__":
  256. unittest.main()
  257. # vim: set et ts=4 sw=4 :