import/export daemon: Record amount of data transferred
[ganeti-local] / test / docs_unittest.py
1 #!/usr/bin/python
2 #
3
4 # Copyright (C) 2009 Google Inc.
5 #
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
10 #
11 # This program is distributed in the hope that it will be useful, but
12 # WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 # General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 # 02110-1301, USA.
20
21
22 """Script for unittesting documentation"""
23
24 import unittest
25 import re
26
27 from ganeti import _autoconf
28 from ganeti import utils
29 from ganeti import cmdlib
30 from ganeti import build
31 from ganeti.rapi import connector
32
33 import testutils
34
35
36 class TestDocs(unittest.TestCase):
37   """Documentation tests"""
38
39   @staticmethod
40   def _ReadDocFile(filename):
41     return utils.ReadFile("%s/doc/%s" %
42                           (testutils.GetSourceDir(), filename))
43
44   def testHookDocs(self):
45     """Check whether all hooks are documented.
46
47     """
48     hooksdoc = self._ReadDocFile("hooks.rst")
49
50     for name in dir(cmdlib):
51       obj = getattr(cmdlib, name)
52
53       if (isinstance(obj, type) and
54           issubclass(obj, cmdlib.LogicalUnit) and
55           hasattr(obj, "HPATH")):
56         self._CheckHook(name, obj, hooksdoc)
57
58   def _CheckHook(self, name, lucls, hooksdoc):
59     if lucls.HTYPE is None:
60       return
61
62     # TODO: Improve this test (e.g. find hooks documented but no longer
63     # existing)
64
65     pattern = r"^:directory:\s*%s\s*$" % re.escape(lucls.HPATH)
66
67     self.assert_(re.findall(pattern, hooksdoc, re.M),
68                  msg=("Missing documentation for hook %s/%s" %
69                       (lucls.HTYPE, lucls.HPATH)))
70
71
72   def testRapiDocs(self):
73     """Check whether all RAPI resources are documented.
74
75     """
76     rapidoc = self._ReadDocFile("rapi.rst")
77
78     node_name = "[node_name]"
79     instance_name = "[instance_name]"
80     job_id = "[job_id]"
81
82     resources = connector.GetHandlers(re.escape(node_name),
83                                       re.escape(instance_name),
84                                       re.escape(job_id))
85
86     titles = []
87
88     prevline = None
89     for line in rapidoc.splitlines():
90       if re.match(r"^\++$", line):
91         titles.append(prevline)
92
93       prevline = line
94
95     undocumented = []
96
97     for key, handler in resources.iteritems():
98       # Regex objects
99       if hasattr(key, "match"):
100         found = False
101         for title in titles:
102           if (title.startswith("``") and
103               title.endswith("``") and
104               key.match(title[2:-2])):
105             found = True
106             break
107
108         if not found:
109           # TODO: Find better way of identifying resource
110           undocumented.append(str(handler))
111
112       elif ("``%s``" % key) not in titles:
113         undocumented.append(key)
114
115     self.failIf(undocumented,
116                 msg=("Missing RAPI resource documentation for %s" %
117                      utils.CommaJoin(undocumented)))
118
119
120 class TestManpages(unittest.TestCase):
121   """Manpage tests"""
122
123   @staticmethod
124   def _ReadManFile(name):
125     return utils.ReadFile("%s/man/%s.sgml" %
126                           (testutils.GetSourceDir(), name))
127
128   @staticmethod
129   def _LoadScript(name):
130     return build.LoadModule("scripts/%s" % name)
131
132   def test(self):
133     for script in _autoconf.GNT_SCRIPTS:
134       self._CheckManpage(script,
135                          self._ReadManFile(script),
136                          self._LoadScript(script).commands.keys())
137
138   def _CheckManpage(self, script, mantext, commands):
139     missing = []
140
141     for cmd in commands:
142       pattern = "<cmdsynopsis>\s*<command>%s</command>" % re.escape(cmd)
143       if not re.findall(pattern, mantext, re.S):
144         missing.append(cmd)
145
146     self.failIf(missing,
147                 msg=("Manpage for '%s' missing documentation for %s" %
148                      (script, utils.CommaJoin(missing))))
149
150
151 if __name__ == "__main__":
152   testutils.GanetiTestProgram()