Statistics
| Branch: | Tag: | Revision:

root / test / docs_unittest.py @ 0897dc97

History | View | Annotate | Download (4.6 kB)

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
    group_name = "[group_name]"
81
    job_id = "[job_id]"
82

    
83
    resources = connector.GetHandlers(re.escape(node_name),
84
                                      re.escape(instance_name),
85
                                      re.escape(group_name),
86
                                      re.escape(job_id))
87

    
88
    titles = []
89

    
90
    prevline = None
91
    for line in rapidoc.splitlines():
92
      if re.match(r"^\++$", line):
93
        titles.append(prevline)
94

    
95
      prevline = line
96

    
97
    prefix_exception = frozenset(["/", "/version", "/2"])
98

    
99
    undocumented = []
100

    
101
    for key, handler in resources.iteritems():
102
      # Regex objects
103
      if hasattr(key, "match"):
104
        self.assert_(key.pattern.startswith("^/2/"),
105
                     msg="Pattern %r does not start with '^/2/'" % key.pattern)
106

    
107
        found = False
108
        for title in titles:
109
          if (title.startswith("``") and
110
              title.endswith("``") and
111
              key.match(title[2:-2])):
112
            found = True
113
            break
114

    
115
        if not found:
116
          # TODO: Find better way of identifying resource
117
          undocumented.append(key.pattern)
118

    
119
      else:
120
        self.assert_(key.startswith("/2/") or key in prefix_exception,
121
                     msg="Path %r does not start with '/2/'" % key)
122

    
123
        if ("``%s``" % key) not in titles:
124
          undocumented.append(key)
125

    
126
    self.failIf(undocumented,
127
                msg=("Missing RAPI resource documentation for %s" %
128
                     utils.CommaJoin(undocumented)))
129

    
130

    
131
class TestManpages(unittest.TestCase):
132
  """Manpage tests"""
133

    
134
  @staticmethod
135
  def _ReadManFile(name):
136
    return utils.ReadFile("%s/man/%s.rst" %
137
                          (testutils.GetSourceDir(), name))
138

    
139
  @staticmethod
140
  def _LoadScript(name):
141
    return build.LoadModule("scripts/%s" % name)
142

    
143
  def test(self):
144
    for script in _autoconf.GNT_SCRIPTS:
145
      self._CheckManpage(script,
146
                         self._ReadManFile(script),
147
                         self._LoadScript(script).commands.keys())
148

    
149
  def _CheckManpage(self, script, mantext, commands):
150
    missing = []
151

    
152
    for cmd in commands:
153
      pattern = r"^(\| )?\*\*%s\*\*" % re.escape(cmd)
154
      if not re.findall(pattern, mantext, re.DOTALL | re.MULTILINE):
155
        missing.append(cmd)
156

    
157
    self.failIf(missing,
158
                msg=("Manpage for '%s' missing documentation for %s" %
159
                     (script, utils.CommaJoin(missing))))
160

    
161

    
162
if __name__ == "__main__":
163
  testutils.GanetiTestProgram()