1#!/usr/bin/env python 2# 3# input_validation_tests.py: testing input validation 4# 5# Subversion is a tool for revision control. 6# See http://subversion.apache.org for more information. 7# 8# ==================================================================== 9# Licensed to the Apache Software Foundation (ASF) under one 10# or more contributor license agreements. See the NOTICE file 11# distributed with this work for additional information 12# regarding copyright ownership. The ASF licenses this file 13# to you under the Apache License, Version 2.0 (the 14# "License"); you may not use this file except in compliance 15# with the License. You may obtain a copy of the License at 16# 17# http://www.apache.org/licenses/LICENSE-2.0 18# 19# Unless required by applicable law or agreed to in writing, 20# software distributed under the License is distributed on an 21# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 22# KIND, either express or implied. See the License for the 23# specific language governing permissions and limitations 24# under the License. 25###################################################################### 26 27import os 28import svntest 29 30# (abbreviation) 31Skip = svntest.testcase.Skip_deco 32SkipUnless = svntest.testcase.SkipUnless_deco 33XFail = svntest.testcase.XFail_deco 34Issues = svntest.testcase.Issues_deco 35Issue = svntest.testcase.Issue_deco 36Wimp = svntest.testcase.Wimp_deco 37Item = svntest.wc.StateItem 38 39 40###################################################################### 41# Utilities 42 43# Common URL targets to pass where only path arguments are expected. 44_invalid_wc_path_targets = ['file:///', '^/'] 45 46def run_and_verify_svn_in_wc(sbox, expected_stderr, *varargs): 47 """Like svntest.actions.run_and_verify_svn, but temporarily 48 changes the current working directory to the sandboxes' 49 working copy and only checks the expected error output.""" 50 51 wc_dir = sbox.wc_dir 52 old_dir = os.getcwd() 53 try: 54 os.chdir(wc_dir) 55 svntest.actions.run_and_verify_svn([], expected_stderr, 56 *varargs) 57 finally: 58 os.chdir(old_dir) 59 60 61###################################################################### 62# Tests 63# 64# Each test must return on success or raise on failure. 65#---------------------------------------------------------------------- 66 67def invalid_wcpath_add(sbox): 68 "non-working copy paths for 'add'" 69 sbox.build(read_only=True) 70 for target in _invalid_wc_path_targets: 71 run_and_verify_svn_in_wc(sbox, "svn:.*is not a local path", 'add', target) 72 73def invalid_wcpath_changelist(sbox): 74 "non-working copy paths for 'changelist'" 75 sbox.build(read_only=True) 76 for target in _invalid_wc_path_targets: 77 run_and_verify_svn_in_wc(sbox, "svn:.*is not a local path", 'changelist', 78 'foo', target) 79 run_and_verify_svn_in_wc(sbox, "svn:.*is not a local path", 'changelist', 80 '--remove', target) 81 82def invalid_wcpath_cleanup(sbox): 83 "non-working copy paths for 'cleanup'" 84 sbox.build(read_only=True) 85 for target in _invalid_wc_path_targets: 86 run_and_verify_svn_in_wc(sbox, "svn:.*is not a local path", 'cleanup', 87 target) 88 89def invalid_wcpath_commit(sbox): 90 "non-working copy paths for 'commit'" 91 sbox.build(read_only=True) 92 for target in _invalid_wc_path_targets: 93 run_and_verify_svn_in_wc(sbox, "svn: E205000: '.*' is not a local path", 'commit', target) 94 95def invalid_copy_sources(sbox): 96 "invalid sources for 'copy'" 97 sbox.build(read_only=True) 98 for (src1, src2) in [("iota", "^/"), ("^/", "iota"), ("file://", "iota")]: 99 run_and_verify_svn_in_wc(sbox, "svn: E200007: Cannot mix repository and working " + 100 "copy sources", 'copy', src1, src2, "A") 101 102def invalid_copy_target(sbox): 103 "invalid target for 'copy'" 104 sbox.build(read_only=True) 105 mu_path = os.path.join('A', 'mu') 106 C_path = os.path.join('A', 'C') 107 run_and_verify_svn_in_wc(sbox, "svn: E155(007|010): Path '.*' is not a directory", 108 'copy', mu_path, C_path, "iota") 109 110def invalid_delete_targets(sbox): 111 "invalid targets for 'delete'" 112 sbox.build(read_only=True) 113 for (target1, target2) in [("iota", "^/"), ("file://", "iota")]: 114 run_and_verify_svn_in_wc(sbox, "svn: E200009: Cannot mix repository and working " 115 "copy targets", 'delete', target1, target2) 116 117def invalid_diff_targets(sbox): 118 "invalid targets for 'diff'" 119 sbox.build(read_only=True) 120 for (target1, target2, target3) in [("iota", "^/", "A/mu"), ("file://", "iota", "A/mu")]: 121 run_and_verify_svn_in_wc(sbox, "svn: E200009: Cannot mix repository and working " 122 "copy targets", 'diff', target1, target2, target3) 123 124def invalid_export_targets(sbox): 125 "invalid targets for 'export'" 126 sbox.build(read_only=True) 127 run_and_verify_svn_in_wc(sbox, "svn: (E000017|E720183): Can't create directory '.*iota':.*", 128 'export', '.', 'iota') 129 for target in ["^/", "file://"]: 130 run_and_verify_svn_in_wc(sbox, "svn:.*is not a local path", 131 'export', '.', target) 132 133def invalid_import_args(sbox): 134 "invalid arguments for 'import'" 135 sbox.build(read_only=True) 136 run_and_verify_svn_in_wc(sbox, "svn:.*is not a local path", 137 'import', '^/', '^/') 138 run_and_verify_svn_in_wc(sbox, "svn:.*is not a local path", 139 'import', '^/', 'iota') 140 run_and_verify_svn_in_wc(sbox, "svn: E205000: Invalid URL 'iota'", 141 'import', 'iota', 'iota') 142 143def invalid_log_targets(sbox): 144 "invalid targets for 'log'" 145 sbox.build(read_only=True) 146 for (target1, target2) in [('^/', '/a/b/c'), ('^/', '^/'), ('^/', 'file://')]: 147 run_and_verify_svn_in_wc(sbox, "svn: E205000: Only relative paths can be " + 148 "specified after a URL for 'svn log', but.*is " + 149 "not a relative path", 'log', target1, target2) 150 151def invalid_merge_args(sbox): 152 "invalid arguments for 'merge'" 153 sbox.build(read_only=True) 154 for args in [('iota', 'A/mu@HEAD'), 155 ('iota@BASE', 'A/mu@HEAD')]: 156 run_and_verify_svn_in_wc(sbox, "svn: E195002: .* working copy .* revision", 157 'merge', *args) 158 for args in [(sbox.repo_url, 'A@1', 'A'), 159 ('^/A', 'A@HEAD', 'A'), 160 ('A@HEAD', '^/A', 'A'), 161 ('A@HEAD', '^/A')]: 162 run_and_verify_svn_in_wc(sbox, "svn: E205000: Merge sources must both " 163 "be either paths or URLs", 'merge', *args) 164 run_and_verify_svn_in_wc(sbox, "svn: E155010: .* was not found", 165 'merge', '^/@0', '^/@1', 'nonexistent') 166 run_and_verify_svn_in_wc(sbox, "svn: E205000: Too many arguments given", 167 'merge', '-c42', '^/A/B', '^/A/C', 'iota') 168 run_and_verify_svn_in_wc(sbox, "svn: E205000: Cannot specify a revision range with" + 169 " two URLs", 'merge', '-c42', '^/mu', '^/') 170 run_and_verify_svn_in_wc(sbox, "svn: E155010: .* was not found", 171 'merge', '-c42', '^/mu', 'nonexistent') 172 173def invalid_wcpath_upgrade(sbox): 174 "non-working copy paths for 'upgrade'" 175 sbox.build(read_only=True) 176 for target in _invalid_wc_path_targets: 177 run_and_verify_svn_in_wc(sbox, "svn:.*is not a local path", 'upgrade', 178 target, target) 179 180def invalid_resolve_targets(sbox): 181 "non-working copy paths for 'resolve'" 182 sbox.build(read_only=True) 183 for target in _invalid_wc_path_targets: 184 run_and_verify_svn_in_wc(sbox, "svn:.*is not a local path", 'resolve', 185 '--accept', 'base', target) 186 187def invalid_resolved_targets(sbox): 188 "non-working copy paths for 'resolved'" 189 sbox.build(read_only=True) 190 for target in _invalid_wc_path_targets: 191 run_and_verify_svn_in_wc(sbox, "svn:.*is not a local path", 'resolved', 192 target) 193 194def invalid_revert_targets(sbox): 195 "non-working copy paths for 'revert'" 196 sbox.build(read_only=True) 197 for target in _invalid_wc_path_targets: 198 run_and_verify_svn_in_wc(sbox, "svn:.*is not a local path", 'revert', 199 target) 200 201def invalid_lock_targets(sbox): 202 "wc paths and repo URL target mixture for 'lock'" 203 sbox.build(read_only=True) 204 for (target1, target2) in [("iota", "^/"), ("file://", "iota")]: 205 run_and_verify_svn_in_wc(sbox, "svn: E200009: Cannot mix repository and working " 206 "copy targets", 'lock', target1, target2) 207 208def invalid_unlock_targets(sbox): 209 "wc paths and repo URL target mixture for 'unlock'" 210 sbox.build(read_only=True) 211 for (target1, target2) in [("iota", "^/"), ("file://", "iota")]: 212 run_and_verify_svn_in_wc(sbox, "svn: E200009: Cannot mix repository and working " 213 "copy targets", 'unlock', target1, target2) 214 215def invalid_status_targets(sbox): 216 "non-working copy paths for 'status'" 217 sbox.build(read_only=True) 218 for target in _invalid_wc_path_targets: 219 run_and_verify_svn_in_wc(sbox, "svn:.*is not a local path", 'status', 220 target) 221 222def invalid_patch_targets(sbox): 223 "non-working copy paths for 'patch'" 224 sbox.build(read_only=True) 225 for (target1, target2) in [("foo", "^/"), ("^/", "^/"), ("^/", "foo")]: 226 run_and_verify_svn_in_wc(sbox, "svn:.*is not a local path", 'patch', 227 target1, target2) 228 229def invalid_switch_targets(sbox): 230 "non-working copy paths for 'switch'" 231 sbox.build(read_only=True) 232 run_and_verify_svn_in_wc(sbox, "svn:.*is not a local path", 'switch', 233 "^/", "^/") 234 235def invalid_relocate_targets(sbox): 236 "non-working copy paths for 'relocate'" 237 sbox.build(read_only=True) 238 run_and_verify_svn_in_wc(sbox, "svn:.*is not a local path", 'relocate', 239 "^/", "^/", "^/") 240 241# See also basic_tests.py:basic_mkdir_mix_targets(), which tests 242# the same thing the other way around. 243def invalid_mkdir_targets(sbox): 244 "invalid targets for 'mkdir'" 245 sbox.build(read_only=True) 246 run_and_verify_svn_in_wc(sbox, "svn: E200009: Cannot mix repository and working " 247 "copy targets", 'mkdir', "folder", "^/folder") 248 249def invalid_update_targets(sbox): 250 "non-working copy paths for 'update'" 251 sbox.build(read_only=True) 252 run_and_verify_svn_in_wc(sbox, "svn:.*is not a local path", 'update', 253 "^/") 254 255def delete_repos_root(sbox): 256 "do stupid things with the repository root" 257 258 sbox.build(read_only=True) 259 wc_dir = sbox.wc_dir 260 repo_url = sbox.repo_url 261 262 expected_status = svntest.actions.get_virginal_state(wc_dir, 1) 263 264 expected_status.tweak('A/D/G', switched='S') 265 expected_status.remove('A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau') 266 svntest.actions.run_and_verify_switch(sbox.wc_dir, sbox.ospath('A/D/G'), 267 repo_url, 268 None, None, expected_status, 269 [], False, 270 '--set-depth', 'empty', '--ignore-ancestry') 271 272 expected_status.tweak('A/B/F', switched='S') 273 svntest.actions.run_and_verify_switch(sbox.wc_dir, sbox.ospath('A/B/F'), 274 repo_url, 275 None, None, expected_status, 276 [], False, 277 '--depth', 'empty', '--ignore-ancestry') 278 279 # Delete the wcroot (which happens to be the repository root) 280 expected_error = 'svn: E155035: \'.*\' is the root of a working copy ' + \ 281 'and cannot be deleted' 282 svntest.actions.run_and_verify_svn([], expected_error, 283 'rm', wc_dir) 284 285 # This should produce some error, because we can never commit this 286 expected_error = '.*repository root.*' 287 svntest.actions.run_and_verify_svn(None, expected_error, 288 'mv', sbox.ospath('A/D/G'), 289 sbox.ospath('Z')) 290 291 # And this currently fails with another nasty error about a wc-lock 292 expected_error = '.*repository root.*' 293 svntest.actions.run_and_verify_svn([], expected_error, 294 'rm', sbox.ospath('A/B/F')) 295 296######################################################################## 297# Run the tests 298 299# list all tests here, starting with None: 300test_list = [ None, 301 invalid_wcpath_add, 302 invalid_wcpath_changelist, 303 invalid_wcpath_cleanup, 304 invalid_wcpath_commit, 305 invalid_copy_sources, 306 invalid_copy_target, 307 invalid_delete_targets, 308 invalid_diff_targets, 309 invalid_export_targets, 310 invalid_import_args, 311 invalid_log_targets, 312 invalid_merge_args, 313 invalid_wcpath_upgrade, 314 invalid_resolve_targets, 315 invalid_resolved_targets, 316 invalid_revert_targets, 317 invalid_lock_targets, 318 invalid_unlock_targets, 319 invalid_status_targets, 320 invalid_patch_targets, 321 invalid_switch_targets, 322 invalid_relocate_targets, 323 invalid_mkdir_targets, 324 invalid_update_targets, 325 delete_repos_root, 326 ] 327 328if __name__ == '__main__': 329 svntest.main.run_tests(test_list) 330 # NOTREACHED 331 332 333### End of file. 334