Fix compiler warning due to missing function prototype.
[svn.git] / subversion / tests / cmdline / svnlook_tests.py
blob1b847f550be0d2965f1f1f5be1eb64c732bf4dff
1 #!/usr/bin/env python
3 # svnlook_tests.py: testing the 'svnlook' tool.
5 # Subversion is a tool for revision control.
6 # See http://subversion.tigris.org for more information.
8 # ====================================================================
9 # Copyright (c) 2000-2004, 2007 CollabNet. All rights reserved.
11 # This software is licensed as described in the file COPYING, which
12 # you should have received as part of this distribution. The terms
13 # are also available at http://subversion.tigris.org/license-1.html.
14 # If newer versions of this license are posted there, you may use a
15 # newer version instead, at your option.
17 ######################################################################
19 # General modules
20 import re, os
22 # Our testing module
23 import svntest
26 # (abbreviation)
27 Skip = svntest.testcase.Skip
28 XFail = svntest.testcase.XFail
29 Item = svntest.wc.StateItem
32 #----------------------------------------------------------------------
34 # Convenience functions to make writing more tests easier
36 def run_svnlook(*varargs):
37 """Run svnlook with VARARGS, returns stdout as list of lines.
38 Raises Failure if any stderr messages."""
39 exit_code, output, dummy_errput = svntest.main.run_command(
40 svntest.main.svnlook_binary, 0, 0, *varargs)
42 return output
45 def expect(tag, expected, got):
46 if expected != got:
47 print "When testing: %s" % tag
48 print "Expected: %s" % expected
49 print " Got: %s" % got
50 raise svntest.Failure
53 # Tests
55 def test_misc(sbox):
56 "test miscellaneous svnlook features"
58 sbox.build()
59 wc_dir = sbox.wc_dir
60 repo_dir = sbox.repo_dir
62 # Make a couple of local mods to files
63 mu_path = os.path.join(wc_dir, 'A', 'mu')
64 rho_path = os.path.join(wc_dir, 'A', 'D', 'G', 'rho')
65 svntest.main.file_append(mu_path, 'appended mu text')
66 svntest.main.file_append(rho_path, 'new appended text for rho')
68 # Created expected output tree for 'svn ci'
69 expected_output = svntest.wc.State(wc_dir, {
70 'A/mu' : Item(verb='Sending'),
71 'A/D/G/rho' : Item(verb='Sending'),
74 # Create expected status tree; all local revisions should be at 1,
75 # but mu and rho should be at revision 2.
76 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
77 expected_status.tweak('A/mu', 'A/D/G/rho', wc_rev=2)
79 svntest.actions.run_and_verify_commit(wc_dir,
80 expected_output,
81 expected_status,
82 None,
83 wc_dir)
85 # give the repo a new UUID
86 uuid = "01234567-89ab-cdef-89ab-cdef01234567"
87 svntest.main.run_command_stdin(svntest.main.svnadmin_binary, None, 1,
88 ["SVN-fs-dump-format-version: 2\n",
89 "\n",
90 "UUID: ", uuid, "\n",
92 'load', '--force-uuid', repo_dir)
94 expect('youngest', [ '2\n' ], run_svnlook('youngest', repo_dir))
96 expect('uuid', [ uuid + '\n' ], run_svnlook('uuid', repo_dir))
98 # it would be nice to test the author too, but the current test framework
99 # does not pull a username when testing over ra_neon or ra_svn,
100 # so the commits have an empty author.
102 expect('log', [ 'log msg\n' ], run_svnlook('log', repo_dir))
104 # check if the 'svnlook tree' output can be expanded to
105 # the 'svnlook tree --full-paths' output if demanding the whole repository
106 treelist = run_svnlook('tree', repo_dir)
107 treelistfull = run_svnlook('tree', '--full-paths', repo_dir)
108 path = ''
109 n = 0
110 for entry in treelist:
111 len1 = len(entry)
112 len2 = len(entry.lstrip())
113 path = path[0:2*(len1-len2)-1] + entry.strip()
114 test = treelistfull[n].rstrip()
115 if n != 0:
116 test = "/" + test
117 if not path == test:
118 print "Unexpected result from tree with --full-paths:"
119 print " entry : %s" % entry.rstrip()
120 print " with --full-paths: %s" % treelistfull[n].rstrip()
121 raise svntest.Failure
122 n = n + 1
124 # check if the 'svnlook tree' output is the ending of
125 # the 'svnlook tree --full-paths' output if demanding
126 # any part of the repository
127 n = 0
128 treelist = run_svnlook('tree', repo_dir, '/A/B')
129 treelistfull = run_svnlook('tree', '--full-paths', repo_dir, '/A/B')
130 for entry in treelist:
131 if not treelistfull[n].endswith(entry.lstrip()):
132 print "Unexpected result from tree with --full-paths:"
133 print " entry : %s" % entry.rstrip()
134 print " with --full-paths: %s" % treelistfull[n].rstrip()
135 raise svntest.Failure
136 n = n + 1
138 treelist = run_svnlook('tree', repo_dir, '/')
139 if treelist[0] != '/\n':
140 raise svntest.Failure
142 expect('propget svn:log', [ 'log msg' ],
143 run_svnlook('propget', '--revprop', repo_dir, 'svn:log'))
146 proplist = run_svnlook('proplist', '--revprop', repo_dir)
147 proplist = [prop.strip() for prop in proplist]
148 proplist.sort()
150 # We cannot rely on svn:author's presence. ra_svn doesn't set it.
151 if not (proplist == [ 'svn:author', 'svn:date', 'svn:log' ]
152 or proplist == [ 'svn:date', 'svn:log' ]):
153 print "Unexpected result from proplist: %s" % proplist
154 raise svntest.Failure
156 prop_name = 'foo:bar-baz-quux'
157 exit_code, output, errput = svntest.main.run_svnlook('propget',
158 '--revprop', repo_dir,
159 prop_name)
161 expected_err = "Property '%s' not found on revision " % prop_name
162 for line in errput:
163 if line.find(expected_err) != -1:
164 break
165 else:
166 raise svntest.main.SVNUnmatchedError
168 exit_code, output, errput = svntest.main.run_svnlook('propget',
169 '-r1', repo_dir,
170 prop_name, '/')
172 expected_err = "Property '%s' not found on path '/' in revision " % prop_name
173 for line in errput:
174 if line.find(expected_err) != -1:
175 break
176 else:
177 raise svntest.main.SVNUnmatchedError
179 #----------------------------------------------------------------------
180 # Issue 1089
181 def delete_file_in_moved_dir(sbox):
182 "delete file in moved dir"
184 sbox.build()
185 wc_dir = sbox.wc_dir
186 repo_dir = sbox.repo_dir
188 # move E to E2 and delete E2/alpha
189 E_path = os.path.join(wc_dir, 'A', 'B', 'E')
190 E2_path = os.path.join(wc_dir, 'A', 'B', 'E2')
191 svntest.actions.run_and_verify_svn(None, None, [], 'mv', E_path, E2_path)
192 alpha_path = os.path.join(E2_path, 'alpha')
193 svntest.actions.run_and_verify_svn(None, None, [], 'rm', alpha_path)
195 # commit
196 expected_output = svntest.wc.State(wc_dir, {
197 'A/B/E' : Item(verb='Deleting'),
198 'A/B/E2' : Item(verb='Adding'),
199 'A/B/E2/alpha' : Item(verb='Deleting'),
201 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
202 expected_status.remove('A/B/E', 'A/B/E/alpha', 'A/B/E/beta')
203 expected_status.add({
204 'A/B/E2' : Item(status=' ', wc_rev=2),
205 'A/B/E2/beta' : Item(status=' ', wc_rev=2),
207 svntest.actions.run_and_verify_commit(wc_dir,
208 expected_output,
209 expected_status,
210 None,
211 wc_dir)
213 exit_code, output, errput = svntest.main.run_svnlook("dirs-changed",
214 repo_dir)
215 if errput:
216 raise svntest.Failure
218 # Okay. No failure, but did we get the right output?
219 if len(output) != 2:
220 raise svntest.Failure
221 if not ((output[0].strip() == 'A/B/')
222 and (output[1].strip() == 'A/B/E2/')):
223 raise svntest.Failure
226 #----------------------------------------------------------------------
227 # Issue 1241
228 def test_print_property_diffs(sbox):
229 "test the printing of property diffs"
231 sbox.build()
232 wc_dir = sbox.wc_dir
233 repo_dir = sbox.repo_dir
235 # Add a bogus property to iota
236 iota_path = os.path.join(wc_dir, 'iota')
237 svntest.actions.run_and_verify_svn(None, None, [], 'propset',
238 'bogus_prop', 'bogus_val', iota_path)
240 # commit the change
241 svntest.actions.run_and_verify_svn(None, None, [],
242 'ci', '-m', 'log msg', iota_path)
244 # Grab the diff
245 exit_code, expected_output, err = svntest.actions.run_and_verify_svn(
246 None, None, [], 'diff', '-r', 'PREV', iota_path)
248 exit_code, output, errput = svntest.main.run_svnlook("diff", repo_dir)
249 if errput:
250 raise svntest.Failure
252 # Okay. No failure, but did we get the right output?
253 if len(output) != len(expected_output):
254 raise svntest.Failure
256 # replace wcdir/iota with iota in expected_output
257 for i in xrange(len(expected_output)):
258 expected_output[i] = expected_output[i].replace(iota_path, 'iota')
260 svntest.verify.compare_and_display_lines('', '', expected_output, output)
262 #----------------------------------------------------------------------
263 # Check that svnlook info repairs allows inconsistent line endings in logs.
265 def info_bad_newlines(sbox):
266 "svnlook info must allow inconsistent newlines"
268 dump_str = """SVN-fs-dump-format-version: 2
270 UUID: dc40867b-38f6-0310-9f5f-f81aa277e06e
272 Revision-number: 0
273 Prop-content-length: 56
274 Content-length: 56
277 svn:date
278 V 27
279 2005-05-03T19:09:41.129900Z
280 PROPS-END
282 Revision-number: 1
283 Prop-content-length: 99
284 Content-length: 99
287 svn:log
289 \n\r\n
290 K 10
291 svn:author
295 svn:date
296 V 27
297 2005-05-03T19:10:19.975578Z
298 PROPS-END
300 Node-path: file
301 Node-kind: file
302 Node-action: add
303 Prop-content-length: 10
304 Text-content-length: 5
305 Text-content-md5: e1cbb0c3879af8347246f12c559a86b5
306 Content-length: 15
308 PROPS-END
309 text
314 # load dumpfile with inconsistent newlines into repos.
315 svntest.actions.load_repo(sbox, dump_str=dump_str)
317 exit_code, output, errput = svntest.main.run_svnlook("info",
318 sbox.repo_dir, "-r1")
319 if errput:
320 raise svntest.Failure
322 def changed_copy_info(sbox):
323 "test --copy-info flag on the changed command"
324 sbox.build()
325 wc_dir = sbox.wc_dir
326 repo_dir = sbox.repo_dir
328 # Copy alpha to /A/alpha2.
329 E_path = os.path.join(wc_dir, 'A', 'B', 'E')
330 alpha_path = os.path.join(wc_dir, 'A', 'B', 'E', 'alpha')
331 alpha2_path = os.path.join(wc_dir, 'A', 'alpha2')
332 svntest.actions.run_and_verify_svn(None, None, [], 'cp', alpha_path,
333 alpha2_path)
335 # commit
336 expected_output = svntest.wc.State(wc_dir, {
337 'A/alpha2' : Item(verb='Adding'),
339 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
340 expected_status.add({
341 'A/alpha2' : Item(status=' ', wc_rev=2),
343 svntest.actions.run_and_verify_commit(wc_dir,
344 expected_output,
345 expected_status,
346 None,
347 wc_dir)
349 exit_code, output, errput = svntest.main.run_svnlook("changed", repo_dir)
350 if errput:
351 raise svntest.Failure
353 expect("changed without --copy-info", ["A A/alpha2\n"], output)
355 exit_code, output, errput = svntest.main.run_svnlook("changed",
356 repo_dir, "--copy-info")
357 if errput:
358 raise svntest.Failure
360 expect("changed with --copy-info",
361 ["A + A/alpha2\n",
362 " (from A/B/E/alpha:r1)\n"],
363 output)
365 #----------------------------------------------------------------------
366 # Issue 2663
367 def tree_non_recursive(sbox):
368 "test 'svnlook tree --non-recursive'"
370 sbox.build()
371 repo_dir = sbox.repo_dir
373 expected_results_root = ('/', ' iota', ' A/')
374 expected_results_deep = ('B/', ' lambda', ' E/', ' F/')
376 # check the output of svnlook --non-recursive on the
377 # root of the repository
378 treelist = run_svnlook('tree', '--non-recursive', repo_dir)
379 for entry in treelist:
380 if not entry.rstrip() in expected_results_root:
381 print "Unexpected result from tree with --non-recursive:"
382 print " entry : %s" % entry.rstrip()
383 raise svntest.Failure
384 if len(treelist) != len(expected_results_root):
385 print "Expected %i output entries, found %i" \
386 % (len(expected_results_root), len(treelist))
387 raise svntest.Failure
389 # check the output of svnlook --non-recursive on a
390 # subdirectory of the repository
391 treelist = run_svnlook('tree', '--non-recursive', repo_dir, '/A/B')
392 for entry in treelist:
393 if not entry.rstrip() in expected_results_deep:
394 print "Unexpected result from tree with --non-recursive:"
395 print " entry : %s" % entry.rstrip()
396 raise svntest.Failure
397 if len(treelist) != len(expected_results_deep):
398 print "Expected %i output entries, found %i" \
399 % (len(expected_results_deep), len(treelist))
400 raise svntest.Failure
402 #----------------------------------------------------------------------
403 def limit_history(sbox):
404 "history --limit"
405 sbox.build(create_wc=False)
406 repo_url = sbox.repo_url
407 svntest.actions.run_and_verify_svn(None, None, [],
408 'mv', '-m', 'log msg',
409 repo_url + "/iota", repo_url + "/iota2")
410 svntest.actions.run_and_verify_svn(None, None, [],
411 'mv', '-m', 'log msg',
412 repo_url + "/A/mu", repo_url + "/iota")
413 history = run_svnlook("history", "--limit=1", sbox.repo_dir)
414 # Ignore the two lines of header, and verify expected number of items.
415 if len(history[2:]) != 1:
416 raise svntest.Failure("Output not limited to expected number of items")
418 #----------------------------------------------------------------------
419 def diff_ignore_whitespace(sbox):
420 "test 'svnlook diff -x -b' and 'svnlook diff -x -w'"
422 sbox.build()
423 repo_dir = sbox.repo_dir
424 wc_dir = sbox.wc_dir
426 # Make whitespace-only changes to mu
427 mu_path = os.path.join(wc_dir, 'A', 'mu')
428 svntest.main.file_write(mu_path, "This is the file 'mu'.\n", "wb")
430 # Created expected output tree for 'svn ci'
431 expected_output = svntest.wc.State(wc_dir, {
432 'A/mu' : Item(verb='Sending'),
435 # Create expected status tree; all local revisions should be at 1,
436 # but mu should be at revision 2.
437 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
438 expected_status.tweak('A/mu', wc_rev=2)
440 svntest.actions.run_and_verify_commit(wc_dir,
441 expected_output,
442 expected_status,
443 None,
444 wc_dir)
446 # Check the output of 'svnlook diff -x --ignore-space-change' on mu.
447 # It should not print anything.
448 output = run_svnlook('diff', '-r2', '-x', '--ignore-space-change',
449 repo_dir, '/A/mu')
450 if output != []:
451 raise svntest.Failure
453 # Check the output of 'svnlook diff -x --ignore-all-space' on mu.
454 # It should not print anything.
455 output = run_svnlook('diff', '-r2', '-x', '--ignore-all-space',
456 repo_dir, '/A/mu')
457 if output != []:
458 raise svntest.Failure
460 #----------------------------------------------------------------------
461 def diff_ignore_eolstyle(sbox):
462 "test 'svnlook diff -x --ignore-eol-style'"
464 sbox.build()
465 repo_dir = sbox.repo_dir
466 wc_dir = sbox.wc_dir
468 if os.name == 'nt':
469 crlf = '\n'
470 else:
471 crlf = '\r\n'
473 mu_path = os.path.join(wc_dir, 'A', 'mu')
475 rev = 1
476 # do the --ignore-eol-style test for each eol-style
477 for eol, eolchar in zip(['CRLF', 'CR', 'native', 'LF'],
478 [crlf, '\015', '\n', '\012']):
479 # rewrite file mu and set the eol-style property.
480 svntest.main.file_write(mu_path, "This is the file 'mu'." + eolchar, 'wb')
481 svntest.main.run_svn(None, 'propset', 'svn:eol-style', eol, mu_path)
483 # Created expected output tree for 'svn ci'
484 expected_output = svntest.wc.State(wc_dir, {
485 'A/mu' : Item(verb='Sending'),
488 # Create expected status tree; all local revisions should be at
489 # revision 1, but mu should be at revision rev + 1.
490 expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
491 expected_status.tweak('A/mu', wc_rev=rev + 1)
493 svntest.actions.run_and_verify_commit(wc_dir,
494 expected_output,
495 expected_status,
496 None,
497 wc_dir)
499 # Grab the diff
500 exit_code, expected_output, err = svntest.actions.run_and_verify_svn(
501 None, None, [],
502 'diff', '-r', 'PREV', '-x', '--ignore-eol-style', mu_path)
505 output = run_svnlook('diff', '-r', str(rev + 1), '-x',
506 '--ignore-eol-style', repo_dir, '/A/mu')
507 rev += 1
509 # replace wcdir/A/mu with A/mu in expected_output
510 for i in xrange(len(expected_output)):
511 expected_output[i] = expected_output[i].replace(mu_path, 'A/mu')
513 svntest.verify.compare_and_display_lines('', '', expected_output, output)
516 ########################################################################
517 # Run the tests
520 # list all tests here, starting with None:
521 test_list = [ None,
522 test_misc,
523 delete_file_in_moved_dir,
524 test_print_property_diffs,
525 info_bad_newlines,
526 changed_copy_info,
527 tree_non_recursive,
528 limit_history,
529 diff_ignore_whitespace,
530 diff_ignore_eolstyle,
533 if __name__ == '__main__':
534 svntest.main.run_tests(test_list)
535 # NOTREACHED
538 ### End of file.