Statistics
| Branch: | Tag: | Revision:

root / test / docs_unittest.py @ 6be8e2bf

History | View | Annotate | Download (4.5 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
    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
    prefix_exception = frozenset(["/", "/version", "/2"])
96

    
97
    undocumented = []
98

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

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

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

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

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

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

    
128

    
129
class TestManpages(unittest.TestCase):
130
  """Manpage tests"""
131

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

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

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

    
147
  def _CheckManpage(self, script, mantext, commands):
148
    missing = []
149

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

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

    
159

    
160
if __name__ == "__main__":
161
  testutils.GanetiTestProgram()