1 # Unix SMB/CIFS implementation.
2 # Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007-2012
4 # Tests for documentation.
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 3 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
20 """Tests for presence of documentation."""
28 import xml
.etree
.ElementTree
as ET
30 class TestCase(samba
.tests
.TestCaseInTempDir
):
32 def _format_message(self
, parameters
, message
):
33 parameters
= list(parameters
)
34 parameters
= map(str, parameters
)
36 return message
+ '\n\n %s' % ('\n '.join(parameters
))
39 def get_documented_parameters(sourcedir
):
40 path
= os
.path
.join(sourcedir
, "bin", "default", "docs-xml", "smbdotconf")
41 if not os
.path
.exists(os
.path
.join(path
, "parameters.all.xml")):
42 raise Exception("Unable to find parameters.all.xml")
44 p
= open(os
.path
.join(path
, "parameters.all.xml"), 'r')
46 raise Exception("Error opening parameters file")
49 root
= ET
.fromstring(out
)
50 for parameter
in root
:
51 name
= parameter
.attrib
.get('name')
52 if parameter
.attrib
.get('removed') == "1":
55 syn
= parameter
.findall('synonym')
62 def get_documented_tuples(sourcedir
, omit_no_default
=True):
63 path
= os
.path
.join(sourcedir
, "bin", "default", "docs-xml", "smbdotconf")
64 if not os
.path
.exists(os
.path
.join(path
, "parameters.all.xml")):
65 raise Exception("Unable to find parameters.all.xml")
67 p
= open(os
.path
.join(path
, "parameters.all.xml"), 'r')
69 raise Exception("Error opening parameters file")
72 root
= ET
.fromstring(out
)
73 for parameter
in root
:
74 name
= parameter
.attrib
.get("name")
75 param_type
= parameter
.attrib
.get("type")
76 if parameter
.attrib
.get('removed') == "1":
78 values
= parameter
.findall("value")
81 if value
.attrib
.get("type") == "default":
82 defaults
.append(value
)
85 if len(defaults
) == 0:
88 elif len(defaults
) > 1:
89 raise Exception("More than one default found for parameter %s" % name
)
91 default_text
= defaults
[0].text
93 if default_text
is None:
95 context
= parameter
.attrib
.get("context")
96 yield name
, default_text
, context
, param_type
99 class SmbDotConfTests(TestCase
):
101 # defines the cases where the defaults may differ from the documentation
102 special_cases
= set(['log level', 'path', 'ldapsam:trusted', 'spoolss: architecture',
103 'share:fake_fscaps', 'ldapsam:editposix', 'rpc_daemon:DAEMON',
104 'rpc_server:SERVER', 'panic action', 'homedir map', 'NIS homedir',
105 'server string', 'netbios name', 'socket options', 'use mmap',
106 'ctdbd socket', 'printing', 'printcap name', 'queueresume command',
107 'queuepause command','lpresume command', 'lppause command',
108 'lprm command', 'lpq command', 'print command', 'template homedir',
109 'spoolss: os_major', 'spoolss: os_minor', 'spoolss: os_build',
110 'max open files', 'fss: prune stale', 'fss: sequence timeout'])
113 super(SmbDotConfTests
, self
).setUp()
114 # create a minimal smb.conf file for testparm
115 self
.smbconf
= os
.path
.join(self
.tempdir
, "paramtestsmb.conf")
116 f
= open(self
.smbconf
, 'w')
125 self
.blankconf
= os
.path
.join(self
.tempdir
, "emptytestsmb.conf")
126 f
= open(self
.blankconf
, 'w')
132 self
.topdir
= os
.path
.abspath(samba
.source_tree_topdir())
135 self
.documented
= set(get_documented_parameters(self
.topdir
))
137 self
.fail("Unable to load documented parameters")
140 self
.defaults
= set(get_documented_tuples(self
.topdir
))
142 self
.fail("Unable to load parameters")
145 self
.defaults_all
= set(get_documented_tuples(self
.topdir
, False))
147 self
.fail("Unable to load parameters")
151 super(SmbDotConfTests
, self
).tearDown()
152 os
.unlink(self
.smbconf
)
153 os
.unlink(self
.blankconf
)
155 def test_default_s3(self
):
156 self
._test
_default
(['bin/testparm'])
157 self
._set
_defaults
(['bin/testparm'])
159 # registry shares appears to need sudo
160 self
._set
_arbitrary
(['bin/testparm'],
161 exceptions
= ['client lanman auth',
162 'client plaintext auth',
165 self
._test
_empty
(['bin/testparm'])
167 def test_default_s4(self
):
168 self
._test
_default
(['bin/samba-tool', 'testparm'])
169 self
._set
_defaults
(['bin/samba-tool', 'testparm'])
170 self
._set
_arbitrary
(['bin/samba-tool', 'testparm'],
171 exceptions
= ['smb ports'])
172 self
._test
_empty
(['bin/samba-tool', 'testparm'])
174 def _test_default(self
, program
):
178 for tuples
in self
.defaults
:
179 param
, default
, context
, param_type
= tuples
180 if param
in self
.special_cases
:
188 self
.fail("%s has no valid context" % param
)
189 p
= subprocess
.Popen(program
+ ["-s", self
.smbconf
,
190 "--section-name", section
, "--parameter-name", param
],
191 stdout
=subprocess
.PIPE
, stderr
=subprocess
.PIPE
, cwd
=self
.topdir
).communicate()
192 if p
[0].upper().strip() != default
.upper():
193 if not (p
[0].upper().strip() == "" and default
== '""'):
194 doc_triple
= "%s\n Expected: %s" % (param
, default
)
195 failset
.add("%s\n Got: %s" % (doc_triple
, p
[0].upper().strip()))
198 self
.fail(self
._format
_message
(failset
,
199 "Parameters that do not have matching defaults:"))
201 def _set_defaults(self
, program
):
205 for tuples
in self
.defaults
:
206 param
, default
, context
, param_type
= tuples
208 if param
in ['printing']:
217 self
.fail("%s has no valid context" % param
)
218 p
= subprocess
.Popen(program
+ ["-s", self
.smbconf
,
219 "--section-name", section
, "--parameter-name", param
,
220 "--option", "%s = %s" % (param
, default
)],
221 stdout
=subprocess
.PIPE
, stderr
=subprocess
.PIPE
, cwd
=self
.topdir
).communicate()
222 if p
[0].upper().strip() != default
.upper():
223 if not (p
[0].upper().strip() == "" and default
== '""'):
224 doc_triple
= "%s\n Expected: %s" % (param
, default
)
225 failset
.add("%s\n Got: %s" % (doc_triple
, p
[0].upper().strip()))
228 self
.fail(self
._format
_message
(failset
,
229 "Parameters that do not have matching defaults:"))
231 def _set_arbitrary(self
, program
, exceptions
=None):
232 arbitrary
= {'string': 'string', 'boolean': 'yes', 'integer': '5',
233 'boolean-rev': 'yes',
237 'ustring': 'ustring',
238 'enum':'', 'boolean-auto': '', 'char': 'a', 'list': 'a, b, c'}
239 opposite_arbitrary
= {'string': 'string2', 'boolean': 'no', 'integer': '6',
244 'ustring': 'ustring2',
245 'enum':'', 'boolean-auto': '', 'char': 'b', 'list': 'd, e, f'}
250 for tuples
in self
.defaults_all
:
251 param
, default
, context
, param_type
= tuples
253 if param
in ['printing', 'copy', 'include', 'log level']:
256 # currently no easy way to set an arbitrary value for these
257 if param_type
in ['enum', 'boolean-auto']:
260 if exceptions
is not None:
261 if param
in exceptions
:
270 self
.fail("%s has no valid context" % param
)
272 value_to_use
= arbitrary
.get(param_type
)
273 if value_to_use
is None:
274 self
.fail("%s has an invalid type" % param
)
276 p
= subprocess
.Popen(program
+ ["-s", self
.smbconf
,
277 "--section-name", section
, "--parameter-name", param
,
278 "--option", "%s = %s" % (param
, value_to_use
)],
279 stdout
=subprocess
.PIPE
, stderr
=subprocess
.PIPE
, cwd
=self
.topdir
).communicate()
280 if p
[0].upper().strip() != value_to_use
.upper():
281 # currently no way to distinguish command lists
282 if param_type
== 'list':
283 if ", ".join(p
[0].upper().strip().split()) == value_to_use
.upper():
286 # currently no way to identify octal
287 if param_type
== 'integer':
289 if int(value_to_use
, 8) == int(p
[0].strip(), 8):
294 doc_triple
= "%s\n Expected: %s" % (param
, value_to_use
)
295 failset
.add("%s\n Got: %s" % (doc_triple
, p
[0].upper().strip()))
297 opposite_value
= opposite_arbitrary
.get(param_type
)
298 tempconf
= os
.path
.join(self
.tempdir
, "tempsmb.conf")
299 g
= open(tempconf
, 'w')
301 towrite
= section
+ "\n"
302 towrite
+= param
+ " = " + opposite_value
307 p
= subprocess
.Popen(program
+ ["-s", tempconf
, "--suppress-prompt",
308 "--option", "%s = %s" % (param
, value_to_use
)],
309 stdout
=subprocess
.PIPE
, stderr
=subprocess
.PIPE
, cwd
=self
.topdir
).communicate()
313 # testparm doesn't display a value if they are equivalent
314 if (value_to_use
.lower() != opposite_value
.lower()):
315 for line
in p
[0].splitlines():
316 if not line
.strip().startswith(param
):
319 value_found
= line
.split("=")[1].upper().strip()
320 if value_found
!= value_to_use
.upper():
321 # currently no way to distinguish command lists
322 if param_type
== 'list':
323 if ", ".join(value_found
.split()) == value_to_use
.upper():
326 # currently no way to identify octal
327 if param_type
== 'integer':
329 if int(value_to_use
, 8) == int(value_found
, 8):
334 doc_triple
= "%s\n Expected: %s" % (param
, value_to_use
)
335 failset
.add("%s\n Got: %s" % (doc_triple
, value_found
))
339 self
.fail(self
._format
_message
(failset
,
340 "Parameters that were unexpectedly not set:"))
342 def _test_empty(self
, program
):
343 p
= subprocess
.Popen(program
+ ["-s", self
.blankconf
, "--suppress-prompt"],
344 stdout
=subprocess
.PIPE
, stderr
=subprocess
.PIPE
, cwd
=self
.topdir
).communicate()
347 for line
in p
[0].splitlines():
348 if line
.strip().startswith('#'):
350 if line
.strip().startswith("idmap config *"):
352 output
+= line
.strip().lower() + '\n'
354 if output
.strip() != '[global]' and output
.strip() != '[globals]':
355 self
.fail("Testparm returned unexpected output on an empty smb.conf.")