test-revert: prepare methodical testing of revert cases
authorPierre-Yves David <pierre-yves.david@fb.com>
Wed, 25 Jun 2014 16:37:06 +0100
changeset 22124 e51784473fc0
parent 22123 7740db54bf73
child 22125 7fce964be27d
test-revert: prepare methodical testing of revert cases We introduce a script to generate revert cases and use it to prepare a test repo. See the inline documentation for details.
tests/test-revert.t
--- a/tests/test-revert.t	Wed Jun 25 15:59:21 2014 +0100
+++ b/tests/test-revert.t	Wed Jun 25 16:37:06 2014 +0100
@@ -394,4 +394,121 @@
   R ignored
   R newadd
 
+Systematic behavior validation of most possible cases
+=====================================================
 
+This section tests most of the possible combinations of working directory
+changes and inter-revision changes. The number of possible cases is significant
+but they all have a slighly different handling. So this section commits to
+generating and testing all of them to allow safe refactoring of the revert code.
+
+A python script is used to generate a file history for each combination of
+changes between, on one side the working directory and its parent and on
+the other side, changes between a revert target (--rev) and working directory
+parent. The three states generated are:
+
+- a "base" revision
+- a "parent" revision
+- the working directory (based on "parent")
+
+The file generated have names of the form:
+
+ <changeset-state>_<working-copy-state>
+
+Here, "changeset-state" conveys the state in "base" and "parent" (or the change
+that happen between them), "working-copy-state" is self explanatory.
+
+All known states are not tested yet. See inline documentation for details.
+Special cases from merge and rename are not tested by this section.
+
+There are also multiple cases where the current revert implementation is known to
+slightly misbehave.
+
+Write the python script to disk
+-------------------------------
+
+  $ cat << EOF > gen-revert-cases.py
+  > # generate proper file state to test revert behavior
+  > import sys
+  > 
+  > # content of the file in "base" and "parent"
+  > ctxcontent = {
+  >     # modified: file content change from base to parent
+  >     'modified': ['base', 'parent'],
+  > }
+  > 
+  > # content of file in working copy
+  > wccontent = {
+  >     # clean: wc content is the same as parent
+  >     'clean': lambda cc: cc[1],
+  > }
+  > 
+  > # build the combination of possible states
+  > combination = []
+  > for ctxkey in ctxcontent:
+  >     for wckey in wccontent:
+  >         filename = "%s_%s" % (ctxkey, wckey)
+  >         combination.append((filename, ctxkey, wckey))
+  > 
+  > # make sure we have stable output
+  > combination.sort()
+  > 
+  > # retrieve the state we must generate
+  > target = sys.argv[1]
+  > 
+  > # compute file content
+  > content = []
+  > for filename, ctxkey, wckey in combination:
+  >     cc = ctxcontent[ctxkey]
+  >     if target == 'base':
+  >         content.append((filename, cc[0]))
+  >     elif target == 'parent':
+  >         content.append((filename, cc[1]))
+  >     elif target == 'wc':
+  >         content.append((filename, wccontent[wckey](cc)))
+  >     else:
+  >         print >> sys.stderr, "unknown target:", target
+  >         sys.exit(1)
+  > 
+  > # write actual content
+  > for filename, data in content:
+  >     f = open(filename, 'w')
+  >     f.write(data + '\n')
+  >     f.close()
+  > EOF
+
+
+Generate appropriate repo state
+-------------------------------
+
+  $ hg init revert-ref
+  $ cd revert-ref
+
+Generate base changeset
+
+  $ python ../gen-revert-cases.py base
+  $ hg addremove --similarity 0
+  adding modified_clean
+  $ hg status
+  A modified_clean
+  $ hg commit -m 'base'
+
+Create parent changeset
+
+  $ python ../gen-revert-cases.py parent
+  $ hg addremove --similarity 0
+  $ hg status
+  M modified_clean
+  $ hg commit -m 'parent'
+
+Setup working directory
+
+  $ python ../gen-revert-cases.py wc | cat
+  $ hg addremove --similarity 0
+  $ hg status
+
+  $ hg status --rev 'desc("base")'
+  M modified_clean
+
+  $ cd ..
+