source: valtobtest/subversion-1.6.2/subversion/tests/cmdline/tree_conflict_tests.py @ 3

Last change on this file since 3 was 3, checked in by valtob, 15 years ago

subversion source 1.6.2 as test

  • Property svn:executable set to *
File size: 27.0 KB
Line 
1#!/usr/bin/env python
2#
3#  tree_conflict_tests.py:  testing tree-conflict cases.
4#
5#  Subversion is a tool for revision control.
6#  See http://subversion.tigris.org for more information.
7#
8# ====================================================================
9# Copyright (c) 2000-2009 CollabNet.  All rights reserved.
10#
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.
16#
17######################################################################
18
19# General modules
20import sys, re, os, traceback
21
22# Our testing module
23import svntest
24from svntest import main,wc
25from svntest.actions import run_and_verify_svn
26from svntest.actions import run_and_verify_commit
27from svntest.actions import run_and_verify_resolved
28
29# (abbreviation)
30Skip = svntest.testcase.Skip
31SkipUnless = svntest.testcase.SkipUnless
32XFail = svntest.testcase.XFail
33Item = svntest.wc.StateItem
34AnyOutput = svntest.verify.AnyOutput
35
36# If verbose mode is enabled, print the LINE and a newline.
37def verbose_print(line):
38  if main.verbose_mode:
39    print(line)
40
41# If verbose mode is enabled, print the (assumed newline-terminated) LINES.
42def verbose_printlines(lines):
43  if main.verbose_mode:
44    for line in lines:
45      sys.stdout.write(line)
46
47######################################################################
48# Tests
49#
50#   Each test must return on success or raise on failure.
51
52
53#----------------------------------------------------------------------
54
55# The tests in this file are for cases where a tree conflict is to be raised.
56# (They do not check that conflicts are not raised in other cases.)
57
58# Note: Delete, Replace and Move are presently tested together but probably
59# will eventually need to be tested separately.
60
61# A tree conflict being raised means:
62#   - the conflict is reported initially
63#   - the conflict is persistently visible
64#   - the conflict blocks commits until resolved
65#   - the conflict blocks (some?) further merges
66# Desired:
67#   - interactive conflict resolution
68
69# A "tree conflict on file P/F" means:
70#   - the operation reports action code "C" on path P/F
71#   - "svn status" reports status code "C" on path P/F
72#   - "svn info" reports details of the conflict on path P/F
73#   - "svn commit" fails if the user-requested targets include path P/F
74#   - "svn merge/update/switch" fails if it tries to modify P/F in any way
75
76# A "tree conflict on dir P/D" means:
77#   - the operation reports action code "C" on path P/D
78#   - "svn status" reports status code "C" on path P/D
79#   - "svn info" reports details of the conflict on P/D
80#   - "svn commit" fails if it includes any part of the P/D sub-tree
81#   - "svn merge/up/sw" fails if it modifies any part of the P/D sub-tree
82
83#----------------------------------------------------------------------
84
85# Two sets of paths. The paths to be used for the destination of a copy
86# or move must differ between the incoming change and the local mods,
87# otherwise scenarios involving a move onto a move would conflict on the
88# destination node as well as on the source, and we only want to be testing
89# one thing at a time in most tests.
90def incoming_paths(root_dir, parent_dir):
91  """Create a set of paths in which the victims of tree conflicts are
92     children of PARENT_DIR. ROOT_DIR should be a shallower directory
93     in which items "F1" and "D1" can pre-exist and be shared across
94     multiple parent dirs."""
95  return {
96    'F1' : os.path.join(root_dir,   "F1"),
97    'F'  : os.path.join(parent_dir, "F"),
98    'F2' : os.path.join(parent_dir, "F2-in"),
99    'D1' : os.path.join(root_dir,   "D1"),
100    'D'  : os.path.join(parent_dir, "D"),
101    'D2' : os.path.join(parent_dir, "D2-in"),
102  }
103def localmod_paths(root_dir, parent_dir):
104  """Create a set of paths in which the victims of tree conflicts are
105     children of PARENT_DIR. ROOT_DIR should be a shallower directory
106     in which items "F1" and "D1" can pre-exist and be shared across
107     multiple parent dirs."""
108  return {
109    'F1' : os.path.join(root_dir,   "F1"),
110    'F'  : os.path.join(parent_dir, "F"),
111    'F2' : os.path.join(parent_dir, "F2-local"),
112    'D1' : os.path.join(root_dir,   "D1"),
113    'D'  : os.path.join(parent_dir, "D"),
114    'D2' : os.path.join(parent_dir, "D2-local"),
115  }
116
117# Perform the action MODACTION on the WC items given by PATHS. The
118# available actions can be seen within this function.
119def modify(modaction, paths):
120  F1 = paths['F1']  # existing file to copy from
121  F  = paths['F']   # target file
122  F2 = paths['F2']  # non-existing file to copy/move to
123  D1 = paths['D1']  # existing dir to copy from
124  D  = paths['D']   # target dir
125  D2 = paths['D2']  # non-existing dir to copy/move to
126
127  # print "  Mod: '" + modaction + "' '" + P + "'"
128
129  if modaction == 'ft':    # file text-mod
130    assert os.path.exists(F)
131    main.file_append(F, "This is a text-mod of file F.\n")
132  elif modaction == 'fP':  # file Prop-mod
133    assert os.path.exists(F)
134    main.run_svn(None, 'pset', 'fprop1', 'A prop set on file F.', F)
135  elif modaction == 'dP':  # dir Prop-mod
136    assert os.path.exists(D)
137    main.run_svn(None, 'pset', 'dprop1', 'A prop set on dir D.', D)
138  elif modaction == 'fD':  # file Delete
139    assert os.path.exists(F)
140    main.run_svn(None, 'del', F)
141  elif modaction == 'dD':  # dir Delete
142    assert os.path.exists(D)
143    main.run_svn(None, 'del', D)
144  elif modaction == 'fA':  # file Add (new)
145    assert os.path.exists(F)
146    main.run_svn(None, 'add', F)
147    main.run_svn(None, 'pset', 'fprop2', 'A prop of added file F.', F)
148  elif modaction == 'dA':  # dir Add (new)
149    assert os.path.exists(D)
150    main.run_svn(None, 'add', D)
151    main.run_svn(None, 'pset', 'dprop2', 'A prop of added dir D.', D)
152  elif modaction == 'fC':  # file Copy (from F1)
153    main.run_svn(None, 'copy', F1, F)
154  elif modaction == 'dC':  # dir Copy (from D1)
155    main.run_svn(None, 'copy', D1, D)
156  elif modaction == 'fM':  # file Move (to F2)
157    main.run_svn(None, 'rename', F, F2)
158  elif modaction == 'dM':  # dir Move (to D2)
159    main.run_svn(None, 'rename', D, D2)
160  elif modaction == 'fa':  # file add (new) on disk
161    assert not os.path.exists(F)
162    main.file_write(F, "This is file F.\n")
163  elif modaction == 'da':  # dir add (new) on disk
164    assert not os.path.exists(D)
165    os.mkdir(D)
166  elif modaction == 'fd':  # file delete from disk
167    assert os.path.exists(F)
168    os.remove(F)
169  elif modaction == 'dd':  # dir delete from disk
170    assert os.path.exists(D)
171    os.remove(D)
172  else:
173    raise Exception("unknown modaction: '" + modaction + "'")
174
175#----------------------------------------------------------------------
176
177# Lists of change scenarios
178#
179# Each scenario expresses a change in terms of the client commands
180# (including "move") that create that change. The change may exist in a
181# repository, or may be applied to a WC by an "update" or "switch" or
182# "merge", or may exist in a WC as a local modification.
183#
184# In addition, each scenario may include some local-modification actions
185# that, if performed on the WC after this change, will make the disk state
186# incompatible with the version-controlled state - e.g. by deleting a file
187# that metadata says is present or vice-versa.
188
189# File names:
190#   F1 = any existing file
191#   F  = the file-path being acted on
192#   F2 = any non-existent file-path
193#   D1 = any existing dir
194#   D  = the dir-path being acted on
195#   D2 = any non-existent dir-path
196#   P  = the parent dir of F and of D
197
198# Format of a change scenario:
199# (
200#   list of actions to create the file/directory to be changed later,
201#   list of actions to make the change
202# )
203
204# Action lists to initialise the repository with a file or directory absent
205# or present, to provide the starting point from which we perform the changes
206# that are to be tested.
207absent_f = []
208absent_d = []
209create_f = ['fa','fA']
210create_d = ['da','dA']
211
212# Scenarios that start with no existing versioned item
213#
214# CREATE:
215# file-add(F) = add-new(F)        or copy(F1,F)(and modify?)
216# dir-add(D)  = add-new(D)(deep?) or copy(D1,D)(and modify?)
217
218f_adds = [
219  #( absent_f, ['fa','fA'] ), ### local add-without-history: not a tree conflict
220  ( absent_f, ['fC'] ),
221  ( absent_f, ['fC','ft'] ), ### Fails because update seems to assume that the
222                             ### local file is unmodified (same as issue 1736?).
223  #( absent_f, ['fC','fP'] ),  # don't test all combinations, just because it's slow
224]
225d_adds = [
226  #( absent_d, ['da','dA'] ), ### local add-without-history: not a tree conflict
227  ( absent_d, ['dC'] ),
228  #( absent_d, ['dC','dP'] ),  # not yet
229]
230
231# Scenarios that start with an existing versioned item
232#
233# GO-AWAY: node is no longer at the path where it was.
234# file-del(F) = del(F) or move(F,F2)
235# dir-del(D)  = del(D) or move(D,D2)
236#
237# REPLACE: node is no longer at the path where it was, but another node is.
238# file-rpl(F) = file-del(F) + file-add(F)
239# dir-rpl(D)  = dir-del(D) + dir-add(D)
240# Note: Schedule replace-by-different-node-type is unsupported in WC.
241#
242# MODIFY:
243# file-mod(F) = text-mod(F) and/or prop-mod(F)
244# dir-mod(D)  = prop-mod(D) and/or file-mod(child-F) and/or dir-mod(child-D)
245
246f_dels = [
247  ( create_f, ['fD'] ),
248  ( create_f, ['fM'] ),
249]
250d_dels = [
251  ( create_d, ['dD'] ),
252  ( create_d, ['dM'] ),
253]
254
255f_rpls = [
256  #( create_f, ['fD','fa','fA'] ),  # replacement - not yet
257  #( create_f, ['fM','fa','fC'] ),  # don't test all combinations, just because it's slow
258]
259d_rpls = [
260  #( create_d, ['dD','dA'] ),  # replacement - not yet
261  #( create_d, ['dM','dC'] ),  # don't test all combinations, just because it's slow
262  # Note that directory replacement differs from file replacement: the
263  # schedule-delete dir is still on disk and is re-used for the re-addition.
264]
265f_rpl_d = [
266  # File replaced by directory: not yet testable
267]
268d_rpl_f = [
269  # Directory replaced by file: not yet testable
270]
271
272f_mods = [
273  ( create_f, ['ft'] ),
274  ( create_f, ['fP'] ),
275  #( create_f, ['ft','fP'] ),  # don't test all combinations, just because it's slow
276]
277d_mods = [
278  ( create_d, ['dP'] ),
279  # These test actions for operating on a child of the directory are not yet implemented:
280  #( create_d, ['f_fA'] ),
281  #( create_d, ['f_ft'] ),
282  #( create_d, ['f_fP'] ),
283  #( create_d, ['f_fD'] ),
284  #( create_d, ['d_dP'] ),
285  #( create_d, ['d_f_fA'] ),
286]
287
288#----------------------------------------------------------------------
289
290# Set up all of the given SCENARIOS in their respective unique paths.
291# This means committing their initialisation actions in r2, and then
292# committing their change actions in r3 (assuming the repos was at r1).
293# (See also the somewhat related svntest.actions.build_greek_tree_conflicts()
294# and tree-conflicts tests using deep_trees in various other .py files.)
295# SCENARIOS is a list of scenario tuples: (init_actions, change_actions).
296# WC_DIR is a local path of an existing WC.
297# BR_DIR is a nonexistent path within WC_DIR.
298# BR_DIR and any necessary parent directories will be created, and then the
299# scenario will be set up within it, and committed to the repository.
300def set_up_repos(wc_dir, br_dir, scenarios):
301
302  if not os.path.exists(br_dir):
303    main.run_svn(None, "mkdir", "--parents", br_dir)
304
305  # create the file F1 and dir D1 which the tests regard as pre-existing
306  paths = incoming_paths(wc_dir, wc_dir)  # second arg is bogus but unimportant
307  F1 = paths['F1']  # existing file to copy from
308  main.file_write(F1, "This is initially file F1.\n")
309  main.run_svn(None, 'add', F1)
310  D1 = paths['D1']  # existing dir to copy from
311  main.run_svn(None, 'mkdir', D1)
312
313  # create the initial parent dirs, and each file or dir unless to-be-added
314  for init_mods, action_mods in scenarios:
315    path = "_".join(action_mods)
316    P = os.path.join(br_dir, path)  # parent of items to be tested
317    main.run_svn(None, 'mkdir', '--parents', P)
318    for modaction in init_mods:
319      modify(modaction, incoming_paths(wc_dir, P))
320  run_and_verify_svn(None, AnyOutput, [],
321                     'commit', '-m', 'Initial set-up.', wc_dir)
322  # Capture the revision number
323  init_rev = 2  ### hard-coded
324
325  # modify all files and dirs in their various ways
326  for _path, action_mods in scenarios:
327    path = "_".join(action_mods)
328    P = os.path.join(br_dir, path)  # parent
329    for modaction in action_mods:
330      modify(modaction, incoming_paths(wc_dir, P))
331
332  # commit all the modifications
333  run_and_verify_svn(None, AnyOutput, [],
334                     'commit', '-m', 'Action.', wc_dir)
335  # Capture the revision number
336  changed_rev = 3  ### hard-coded
337
338  return (init_rev, changed_rev)
339
340#----------------------------------------------------------------------
341
342# Apply each of the changes in INCOMING_SCENARIOS to each of the local
343# modifications in LOCALMOD_SCENARIOS.
344# Ensure that the result in each case includes a tree conflict on the parent.
345# OPERATION = 'update' or 'switch' or 'merge'
346# If COMMIT_LOCAL_MODS is true, the LOCALMOD_SCENARIOS will be committed to
347# the target branch before applying the INCOMING_SCENARIOS.
348def ensure_tree_conflict(sbox, operation,
349                         incoming_scenarios, localmod_scenarios,
350                         commit_local_mods):
351  sbox.build()
352  wc_dir = sbox.wc_dir
353
354  def url_of(repo_relative_path):
355    return sbox.repo_url + '/' + repo_relative_path
356
357  verbose_print("")
358  verbose_print("=== Starting a set of '" + operation + "' tests.")
359
360  # Path to source branch, relative to wc_dir.
361  # Source is where the "incoming" mods are made.
362  source_br = "branch1"
363
364  verbose_print("--- Creating changes in repos")
365  source_wc_dir = os.path.join(wc_dir, source_br)
366  source_left_rev, source_right_rev = set_up_repos(wc_dir, source_wc_dir,
367                                                   incoming_scenarios)
368  head_rev = source_right_rev  ### assumption
369
370  # Local mods are the outer loop because cleaning up the WC is slow
371  # ('svn revert' isn't sufficient because it leaves unversioned files)
372  for _loc_init_mods, loc_action in localmod_scenarios:
373    # Determine the branch (directory) in which local mods will be made.
374    if operation == 'update':
375      # Path to target branch (where conflicts are raised), relative to wc_dir.
376      target_br = source_br
377      target_start_rev = source_left_rev
378    else:  # switch/merge
379      # Make, and work in, a "branch2" that is a copy of "branch1".
380      target_br = "branch2"
381      run_and_verify_svn(None, AnyOutput, [],
382                         'copy', '-r', str(source_left_rev), url_of(source_br),
383                         url_of(target_br),
384                         '-m', 'Create target branch.')
385      head_rev += 1
386      target_start_rev = head_rev
387
388    main.run_svn(None, 'checkout', '-r', str(target_start_rev), sbox.repo_url,
389                 wc_dir)
390
391    saved_cwd = os.getcwd()
392    os.chdir(wc_dir)
393
394    for _inc_init_mods, inc_action in incoming_scenarios:
395      scen_name = "_".join(inc_action)
396      source_url = url_of(source_br + '/' + scen_name)
397      target_path = os.path.join(target_br, scen_name)
398
399      verbose_print("=== " + str(inc_action) + " onto " + str(loc_action))
400
401      verbose_print("--- Making local mods")
402      for modaction in loc_action:
403        modify(modaction, localmod_paths(".", target_path))
404      if commit_local_mods:
405        run_and_verify_svn(None, AnyOutput, [],
406                           'commit', target_path,
407                           '-m', 'Mods in target branch.')
408        head_rev += 1
409
410      # What do we want to test for? (This selection could in future be
411      # passed in to this function as a parameter.)
412      test_what = [
413        'commit-ood',
414        'action',  # required for any of the following ones to work
415        'notify',
416        'commit-c',
417        'status-c',
418        'resolve',  # required for any of the following ones to work
419        'status-nc',
420        #'commit-ok',
421        ]
422
423      if 'commit-ood' in test_what:
424        # For update, verify the pre-condition that WC is out of date.
425        # For switch/merge, there is no such precondition.
426        if operation == 'update':
427          verbose_print("--- Trying to commit (expecting 'out-of-date' error)")
428          run_and_verify_commit(".", None, None, "Commit failed",
429                                target_path)
430
431      if modaction.startswith('f'):
432        victim = os.path.join(target_path, 'F')
433      else:
434        victim = os.path.join(target_path, 'D')
435
436      # Perform the operation that tries to apply incoming changes to the WC.
437      # The command is expected to do something (and give some output),
438      # and it should raise a conflict but not an error.
439      if 'action' in test_what:
440        # Determine what notification to expect
441        if 'notify' in test_what:
442          expected_stdout = svntest.verify.ExpectedOutput("   C " + victim
443                                                          + "\n",
444                                                          match_all=False)
445        else:
446          expected_stdout = svntest.verify.AnyOutput
447        # Do the main action
448        if operation == 'update':
449          verbose_print("--- Updating")
450          run_and_verify_svn(None, expected_stdout, [],
451                             'update', target_path)
452        elif operation == 'switch':
453          verbose_print("--- Switching")
454          run_and_verify_svn(None, expected_stdout, [],
455                             'switch', source_url, target_path)
456        elif operation == 'merge':
457          verbose_print("--- Merging")
458          run_and_verify_svn(None, expected_stdout, [],
459                             'merge', '--ignore-ancestry',
460                             '-r', str(source_left_rev) + ':' + str(source_right_rev),
461                             source_url, target_path)
462        else:
463          raise Exception("unknown operation: '" + operation + "'")
464
465      if 'commit-c' in test_what:
466        verbose_print("--- Trying to commit (expecting 'conflict' error)")
467        ### run_and_verify_commit() requires an "output_tree" argument, but
468        # here we get away with passing None because we know an implementation
469        # detail: namely that it's not going to look at that argument if it
470        # gets the stderr that we're expecting.
471        run_and_verify_commit(".", None, None, ".*conflict.*", victim)
472
473      if 'status-c' in test_what:
474        verbose_print("--- Checking that 'status' reports the conflict")
475        expected_stdout = svntest.verify.RegexOutput("^......C.* " +
476                                                     re.escape(victim) + "$",
477                                                     match_all=False)
478        run_and_verify_svn(None, expected_stdout, [],
479                           'status', victim)
480
481      if 'resolve' in test_what:
482        verbose_print("--- Resolving the conflict")
483        # Make sure resolving the parent does nothing.
484        run_and_verify_resolved([], os.path.dirname(victim))
485        # The real resolved call.
486        run_and_verify_resolved([victim])
487
488      if 'status-nc' in test_what:
489        verbose_print("--- Checking that 'status' does not report a conflict")
490        exitcode, stdout, stderr = run_and_verify_svn(None, None, [],
491                                                  'status', victim)
492        for line in stdout:
493          if line[6] == 'C': # and line.endswith(victim + '\n'):
494            raise svntest.Failure("unexpected status C") # on path '" + victim + "'")
495
496      if 'commit-ok' in test_what:
497        verbose_print("--- Committing (should now succeed)")
498        run_and_verify_svn(None, None, [],
499                           'commit', '-m', '', target_path)
500        target_start_rev += 1
501
502      verbose_print("")
503
504    os.chdir(saved_cwd)
505
506    # Clean up the target branch and WC
507    main.run_svn(None, 'revert', '-R', wc_dir)
508    main.safe_rmtree(wc_dir)
509    if operation != 'update':
510      run_and_verify_svn(None, AnyOutput, [],
511                         'delete', url_of(target_br),
512                         '-m', 'Delete target branch.')
513      head_rev += 1
514
515#----------------------------------------------------------------------
516
517# The main entry points for testing a set of scenarios.
518
519# Test 'update' and/or 'switch'
520# See test_wc_merge() for arguments.
521def test_tc_up_sw(sbox, incoming_scen, wc_scen):
522  sbox2 = sbox.clone_dependent()
523  ensure_tree_conflict(sbox, 'update', incoming_scen, wc_scen, False)
524  ensure_tree_conflict(sbox2, 'switch', incoming_scen, wc_scen, False)
525
526# Test 'merge'
527# INCOMING_SCEN is a list of scenarios describing the incoming changes to apply.
528# BR_SCEN  is a list of scenarios describing how the local branch has
529#   been modified relative to the merge-left source.
530# WC_SCEN is a list of scenarios describing the local WC mods.
531# One of BR_SCEN or WC_SCEN must be given but not both.
532def test_tc_merge(sbox, incoming_scen, br_scen=None, wc_scen=None):
533  if br_scen:
534    ensure_tree_conflict(sbox, 'merge', incoming_scen, br_scen, True)
535  else:
536    ensure_tree_conflict(sbox, 'merge', incoming_scen, wc_scen, False)
537
538#----------------------------------------------------------------------
539
540# Tests for update/switch affecting a file, where the incoming change
541# conflicts with a scheduled change in the WC.
542#
543# WC state: as scheduled (no obstruction)
544
545def up_sw_file_mod_onto_del(sbox):
546  "up/sw file: modify onto del/rpl/mv"
547  test_tc_up_sw(sbox, f_mods, f_dels + f_rpls)
548  # Note: See UC1 in notes/tree-conflicts/use-cases.txt.
549
550def up_sw_file_del_onto_mod(sbox):
551  "up/sw file: del/rpl/mv onto modify"
552  # Results: tree-conflict on F
553  #          no other change to WC (except possibly other half of move)
554  #          ### OR (see Nico's email <>):
555  #          schedule-delete but leave F on disk (can only apply with
556  #            text-mod; prop-mod can't be preserved in this way)
557  test_tc_up_sw(sbox, f_dels + f_rpls, f_mods)
558  # Note: See UC2 in notes/tree-conflicts/use-cases.txt.
559
560def up_sw_file_del_onto_del(sbox):
561  "up/sw file: del/rpl/mv onto del/rpl/mv"
562  test_tc_up_sw(sbox, f_dels + f_rpls, f_dels + f_rpls)
563  # Note: See UC3 in notes/tree-conflicts/use-cases.txt.
564
565def up_sw_file_add_onto_add(sbox):
566  "up/sw file: add onto add"
567  test_tc_up_sw(sbox, f_adds, f_adds)
568
569#----------------------------------------------------------------------
570
571# Tests for update/switch affecting a dir, where the incoming change
572# conflicts with a scheduled change in the WC.
573
574def up_sw_dir_mod_onto_del(sbox):
575  "up/sw dir: modify onto del/rpl/mv"
576  # WC state: any (D necessarily exists; children may have any state)
577  test_tc_up_sw(sbox, d_mods, d_dels + d_rpls)
578
579def up_sw_dir_del_onto_mod(sbox):
580  "up/sw dir: del/rpl/mv onto modify"
581  # WC state: any (D necessarily exists; children may have any state)
582  test_tc_up_sw(sbox, d_dels + d_rpls, d_mods)
583
584def up_sw_dir_del_onto_del(sbox):
585  "up/sw dir: del/rpl/mv onto del/rpl/mv"
586  # WC state: any (D necessarily exists; children may have any state)
587  test_tc_up_sw(sbox, d_dels + d_rpls, d_dels + d_rpls)
588
589# This is currently set as XFail over ra_dav because it hits
590# issue #3314 'DAV can overwrite directories during copy'
591#
592#   TRUNK@35827.DBG>svn st -v branch1
593#                   2        2 jrandom      branch1
594#                   2        2 jrandom      branch1\dC
595#   A  +            -        2 jrandom      branch1\dC\D
596#
597#   TRUNK@35827.DBG>svn log -r2:HEAD branch1 -v
598#   ------------------------------------------------------------------------
599#   r2 | jrandom | 2009-02-12 09:26:52 -0500 (Thu, 12 Feb 2009) | 1 line
600#   Changed paths:
601#      A /D1
602#      A /F1
603#      A /branch1
604#      A /branch1/dC
605#
606#   Initial set-up.
607#   ------------------------------------------------------------------------
608#   r3 | jrandom | 2009-02-12 09:26:52 -0500 (Thu, 12 Feb 2009) | 1 line
609#   Changed paths:
610#      A /branch1/dC/D (from /D1:2)
611#
612#   Action.
613#   ------------------------------------------------------------------------
614#
615#   TRUNK@35827.DBG>svn ci -m "Should be ood" branch1
616#   Adding         branch1\dC\D
617#
618#   Committed revision 4.
619def up_sw_dir_add_onto_add(sbox):
620  "up/sw dir: add onto add"
621  # WC state: as scheduled (no obstruction)
622  test_tc_up_sw(sbox, d_adds, d_adds)
623
624#----------------------------------------------------------------------
625
626# Tests for merge affecting a file, where the incoming change
627# conflicts with the target.
628
629def merge_file_mod_onto_not_file(sbox):
630  "merge file: modify onto not-file"
631  sbox2 = sbox.clone_dependent()
632  test_tc_merge(sbox, f_mods, br_scen = f_dels + f_rpl_d)
633  test_tc_merge(sbox2, f_mods, wc_scen = f_dels)
634  # Note: See UC4 in notes/tree-conflicts/use-cases.txt.
635
636def merge_file_del_onto_not_same(sbox):
637  "merge file: del/rpl/mv onto not-same"
638  sbox2 = sbox.clone_dependent()
639  test_tc_merge(sbox, f_dels + f_rpls, br_scen = f_mods)
640  test_tc_merge(sbox2, f_dels + f_rpls, wc_scen = f_mods)
641  # Note: See UC5 in notes/tree-conflicts/use-cases.txt.
642
643def merge_file_del_onto_not_file(sbox):
644  "merge file: del/rpl/mv onto not-file"
645  sbox2 = sbox.clone_dependent()
646  test_tc_merge(sbox, f_dels + f_rpls, br_scen = f_dels + f_rpl_d)
647  test_tc_merge(sbox2, f_dels + f_rpls, wc_scen = f_dels)
648  # Note: See UC6 in notes/tree-conflicts/use-cases.txt.
649
650def merge_file_add_onto_not_none(sbox):
651  "merge file: add onto not-none"
652  sbox2 = sbox.clone_dependent()
653  test_tc_merge(sbox, f_adds, br_scen = f_adds)  ### + d_adds (at path "F")
654  test_tc_merge(sbox2, f_adds, wc_scen = f_adds)  ### + d_adds (at path "F")
655
656#----------------------------------------------------------------------
657
658# Tests for merge affecting a dir, where the incoming change
659# conflicts with the target branch.
660
661def merge_dir_mod_onto_not_dir(sbox):
662  "merge dir: modify onto not-dir"
663  sbox2 = sbox.clone_dependent()
664  test_tc_merge(sbox, d_mods, br_scen = d_dels + d_rpl_f)
665  test_tc_merge(sbox2, d_mods, wc_scen = d_dels)
666
667def merge_dir_del_onto_not_same(sbox):
668  "merge dir: del/rpl/mv onto not-same"
669  sbox2 = sbox.clone_dependent()
670  test_tc_merge(sbox, d_dels + d_rpls, br_scen = d_mods)
671  test_tc_merge(sbox2, d_dels + d_rpls, wc_scen = d_mods)
672
673def merge_dir_del_onto_not_dir(sbox):
674  "merge dir: del/rpl/mv onto not-dir"
675  sbox2 = sbox.clone_dependent()
676  test_tc_merge(sbox, d_dels + d_rpls, br_scen = d_dels + d_rpl_f)
677  test_tc_merge(sbox2, d_dels + d_rpls, wc_scen = d_dels)
678
679def merge_dir_add_onto_not_none(sbox):
680  "merge dir: add onto not-none"
681  sbox2 = sbox.clone_dependent()
682  test_tc_merge(sbox, d_adds, br_scen = d_adds)  ### + f_adds (at path "D")
683  test_tc_merge(sbox2, d_adds, wc_scen = d_adds)  ### + f_adds (at path "D")
684
685
686#######################################################################
687# Run the tests
688
689
690# list all tests here, starting with None:
691test_list = [ None,
692              up_sw_file_mod_onto_del,
693              up_sw_file_del_onto_mod,
694              up_sw_file_del_onto_del,
695              up_sw_file_add_onto_add,
696              up_sw_dir_mod_onto_del,
697              up_sw_dir_del_onto_mod,
698              up_sw_dir_del_onto_del,
699              XFail(up_sw_dir_add_onto_add,
700                    svntest.main.is_ra_type_dav),
701              merge_file_mod_onto_not_file,
702              merge_file_del_onto_not_same,
703              merge_file_del_onto_not_file,
704              merge_file_add_onto_not_none,
705              merge_dir_mod_onto_not_dir,
706              XFail(merge_dir_del_onto_not_same),
707              merge_dir_del_onto_not_dir,
708              merge_dir_add_onto_not_none,
709             ]
710
711if __name__ == '__main__':
712  svntest.main.run_tests(test_list)
713  # NOTREACHED
714
715
716### End of file.
Note: See TracBrowser for help on using the repository browser.