Statistics
| Branch: | Tag: | Revision:

root / test / docs_unittest.py @ 6760e4ed

History | View | Annotate | Download (4.5 kB)

1 3f991867 Michael Hanselmann
#!/usr/bin/python
2 3f991867 Michael Hanselmann
#
3 3f991867 Michael Hanselmann
4 3f991867 Michael Hanselmann
# Copyright (C) 2009 Google Inc.
5 3f991867 Michael Hanselmann
#
6 3f991867 Michael Hanselmann
# This program is free software; you can redistribute it and/or modify
7 3f991867 Michael Hanselmann
# it under the terms of the GNU General Public License as published by
8 3f991867 Michael Hanselmann
# the Free Software Foundation; either version 2 of the License, or
9 3f991867 Michael Hanselmann
# (at your option) any later version.
10 3f991867 Michael Hanselmann
#
11 3f991867 Michael Hanselmann
# This program is distributed in the hope that it will be useful, but
12 3f991867 Michael Hanselmann
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 3f991867 Michael Hanselmann
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 3f991867 Michael Hanselmann
# General Public License for more details.
15 3f991867 Michael Hanselmann
#
16 3f991867 Michael Hanselmann
# You should have received a copy of the GNU General Public License
17 3f991867 Michael Hanselmann
# along with this program; if not, write to the Free Software
18 3f991867 Michael Hanselmann
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 3f991867 Michael Hanselmann
# 02110-1301, USA.
20 3f991867 Michael Hanselmann
21 3f991867 Michael Hanselmann
22 3f991867 Michael Hanselmann
"""Script for unittesting documentation"""
23 3f991867 Michael Hanselmann
24 3f991867 Michael Hanselmann
import unittest
25 3f991867 Michael Hanselmann
import re
26 3f991867 Michael Hanselmann
27 36bf7973 Michael Hanselmann
from ganeti import _autoconf
28 3f991867 Michael Hanselmann
from ganeti import utils
29 3f991867 Michael Hanselmann
from ganeti import cmdlib
30 e948770c Michael Hanselmann
from ganeti import build
31 bf968b7f Michael Hanselmann
from ganeti.rapi import connector
32 3f991867 Michael Hanselmann
33 3f991867 Michael Hanselmann
import testutils
34 3f991867 Michael Hanselmann
35 3f991867 Michael Hanselmann
36 3f991867 Michael Hanselmann
class TestDocs(unittest.TestCase):
37 3f991867 Michael Hanselmann
  """Documentation tests"""
38 3f991867 Michael Hanselmann
39 3f991867 Michael Hanselmann
  @staticmethod
40 3f991867 Michael Hanselmann
  def _ReadDocFile(filename):
41 3f991867 Michael Hanselmann
    return utils.ReadFile("%s/doc/%s" %
42 3f991867 Michael Hanselmann
                          (testutils.GetSourceDir(), filename))
43 3f991867 Michael Hanselmann
44 3f991867 Michael Hanselmann
  def testHookDocs(self):
45 3f991867 Michael Hanselmann
    """Check whether all hooks are documented.
46 3f991867 Michael Hanselmann

47 3f991867 Michael Hanselmann
    """
48 3f991867 Michael Hanselmann
    hooksdoc = self._ReadDocFile("hooks.rst")
49 3f991867 Michael Hanselmann
50 3f991867 Michael Hanselmann
    for name in dir(cmdlib):
51 3f991867 Michael Hanselmann
      obj = getattr(cmdlib, name)
52 3f991867 Michael Hanselmann
53 3f991867 Michael Hanselmann
      if (isinstance(obj, type) and
54 3f991867 Michael Hanselmann
          issubclass(obj, cmdlib.LogicalUnit) and
55 3f991867 Michael Hanselmann
          hasattr(obj, "HPATH")):
56 3f991867 Michael Hanselmann
        self._CheckHook(name, obj, hooksdoc)
57 3f991867 Michael Hanselmann
58 3f991867 Michael Hanselmann
  def _CheckHook(self, name, lucls, hooksdoc):
59 3f991867 Michael Hanselmann
    if lucls.HTYPE is None:
60 3f991867 Michael Hanselmann
      return
61 3f991867 Michael Hanselmann
62 3f991867 Michael Hanselmann
    # TODO: Improve this test (e.g. find hooks documented but no longer
63 3f991867 Michael Hanselmann
    # existing)
64 3f991867 Michael Hanselmann
65 3f991867 Michael Hanselmann
    pattern = r"^:directory:\s*%s\s*$" % re.escape(lucls.HPATH)
66 3f991867 Michael Hanselmann
67 3f991867 Michael Hanselmann
    self.assert_(re.findall(pattern, hooksdoc, re.M),
68 3f991867 Michael Hanselmann
                 msg=("Missing documentation for hook %s/%s" %
69 3f991867 Michael Hanselmann
                      (lucls.HTYPE, lucls.HPATH)))
70 3f991867 Michael Hanselmann
71 3f991867 Michael Hanselmann
72 bf968b7f Michael Hanselmann
  def testRapiDocs(self):
73 bf968b7f Michael Hanselmann
    """Check whether all RAPI resources are documented.
74 bf968b7f Michael Hanselmann

75 bf968b7f Michael Hanselmann
    """
76 bf968b7f Michael Hanselmann
    rapidoc = self._ReadDocFile("rapi.rst")
77 bf968b7f Michael Hanselmann
78 bf968b7f Michael Hanselmann
    node_name = "[node_name]"
79 bf968b7f Michael Hanselmann
    instance_name = "[instance_name]"
80 bf968b7f Michael Hanselmann
    job_id = "[job_id]"
81 bf968b7f Michael Hanselmann
82 bf968b7f Michael Hanselmann
    resources = connector.GetHandlers(re.escape(node_name),
83 bf968b7f Michael Hanselmann
                                      re.escape(instance_name),
84 bf968b7f Michael Hanselmann
                                      re.escape(job_id))
85 bf968b7f Michael Hanselmann
86 bf968b7f Michael Hanselmann
    titles = []
87 bf968b7f Michael Hanselmann
88 bf968b7f Michael Hanselmann
    prevline = None
89 bf968b7f Michael Hanselmann
    for line in rapidoc.splitlines():
90 bf968b7f Michael Hanselmann
      if re.match(r"^\++$", line):
91 bf968b7f Michael Hanselmann
        titles.append(prevline)
92 bf968b7f Michael Hanselmann
93 bf968b7f Michael Hanselmann
      prevline = line
94 bf968b7f Michael Hanselmann
95 2c0be3d0 Michael Hanselmann
    prefix_exception = frozenset(["/", "/version", "/2"])
96 2c0be3d0 Michael Hanselmann
97 bf968b7f Michael Hanselmann
    undocumented = []
98 bf968b7f Michael Hanselmann
99 bf968b7f Michael Hanselmann
    for key, handler in resources.iteritems():
100 bf968b7f Michael Hanselmann
      # Regex objects
101 bf968b7f Michael Hanselmann
      if hasattr(key, "match"):
102 2c0be3d0 Michael Hanselmann
        self.assert_(key.pattern.startswith("^/2/"),
103 2c0be3d0 Michael Hanselmann
                     msg="Pattern %r does not start with '^/2/'" % key.pattern)
104 2c0be3d0 Michael Hanselmann
105 bf968b7f Michael Hanselmann
        found = False
106 bf968b7f Michael Hanselmann
        for title in titles:
107 bf968b7f Michael Hanselmann
          if (title.startswith("``") and
108 bf968b7f Michael Hanselmann
              title.endswith("``") and
109 bf968b7f Michael Hanselmann
              key.match(title[2:-2])):
110 bf968b7f Michael Hanselmann
            found = True
111 bf968b7f Michael Hanselmann
            break
112 bf968b7f Michael Hanselmann
113 bf968b7f Michael Hanselmann
        if not found:
114 bf968b7f Michael Hanselmann
          # TODO: Find better way of identifying resource
115 2c0be3d0 Michael Hanselmann
          undocumented.append(key.pattern)
116 2c0be3d0 Michael Hanselmann
117 2c0be3d0 Michael Hanselmann
      else:
118 2c0be3d0 Michael Hanselmann
        self.assert_(key.startswith("/2/") or key in prefix_exception,
119 2c0be3d0 Michael Hanselmann
                     msg="Path %r does not start with '/2/'" % key)
120 bf968b7f Michael Hanselmann
121 2c0be3d0 Michael Hanselmann
        if ("``%s``" % key) not in titles:
122 2c0be3d0 Michael Hanselmann
          undocumented.append(key)
123 bf968b7f Michael Hanselmann
124 bf968b7f Michael Hanselmann
    self.failIf(undocumented,
125 bf968b7f Michael Hanselmann
                msg=("Missing RAPI resource documentation for %s" %
126 ab3e6da8 Iustin Pop
                     utils.CommaJoin(undocumented)))
127 bf968b7f Michael Hanselmann
128 bf968b7f Michael Hanselmann
129 36bf7973 Michael Hanselmann
class TestManpages(unittest.TestCase):
130 36bf7973 Michael Hanselmann
  """Manpage tests"""
131 36bf7973 Michael Hanselmann
132 36bf7973 Michael Hanselmann
  @staticmethod
133 36bf7973 Michael Hanselmann
  def _ReadManFile(name):
134 36bf7973 Michael Hanselmann
    return utils.ReadFile("%s/man/%s.sgml" %
135 36bf7973 Michael Hanselmann
                          (testutils.GetSourceDir(), name))
136 36bf7973 Michael Hanselmann
137 36bf7973 Michael Hanselmann
  @staticmethod
138 36bf7973 Michael Hanselmann
  def _LoadScript(name):
139 e948770c Michael Hanselmann
    return build.LoadModule("scripts/%s" % name)
140 36bf7973 Michael Hanselmann
141 36bf7973 Michael Hanselmann
  def test(self):
142 36bf7973 Michael Hanselmann
    for script in _autoconf.GNT_SCRIPTS:
143 36bf7973 Michael Hanselmann
      self._CheckManpage(script,
144 36bf7973 Michael Hanselmann
                         self._ReadManFile(script),
145 36bf7973 Michael Hanselmann
                         self._LoadScript(script).commands.keys())
146 36bf7973 Michael Hanselmann
147 36bf7973 Michael Hanselmann
  def _CheckManpage(self, script, mantext, commands):
148 36bf7973 Michael Hanselmann
    missing = []
149 36bf7973 Michael Hanselmann
150 36bf7973 Michael Hanselmann
    for cmd in commands:
151 36bf7973 Michael Hanselmann
      pattern = "<cmdsynopsis>\s*<command>%s</command>" % re.escape(cmd)
152 36bf7973 Michael Hanselmann
      if not re.findall(pattern, mantext, re.S):
153 36bf7973 Michael Hanselmann
        missing.append(cmd)
154 36bf7973 Michael Hanselmann
155 36bf7973 Michael Hanselmann
    self.failIf(missing,
156 36bf7973 Michael Hanselmann
                msg=("Manpage for '%s' missing documentation for %s" %
157 ab3e6da8 Iustin Pop
                     (script, utils.CommaJoin(missing))))
158 36bf7973 Michael Hanselmann
159 36bf7973 Michael Hanselmann
160 3f991867 Michael Hanselmann
if __name__ == "__main__":
161 25231ec5 Michael Hanselmann
  testutils.GanetiTestProgram()