tests: add tests for server-side linknode adjustment with wireprotov2
authorGregory Szorc <gregory.szorc@gmail.com>
Mon, 10 Dec 2018 17:26:12 +0000
changeset 53694 ca6372b7e566
parent 53693 afdbc9c6a333
child 53695 3ed77780f4a6
push id1081
push usergszorc@mozilla.com
push dateMon, 10 Dec 2018 21:46:46 +0000
tests: add tests for server-side linknode adjustment with wireprotov2 The current implementation of linknode serving in wireprotov2 simply serves up the linkrev/linknode as stored: it doesn't attempt to adjust the linknode to what the receiver is aware of. This can result in the client seeing a linknode referencing a changeset that is unknown to it. This commit adds test coverage of that scenario. The tests in test-wireproto-command-filesdata.t demonstrate two failures. First, the linknode refers to a changeset not in the available set. Second, the server doesn't send a file revision that it should have (because of linkrev filtering). The test in test-wireproto-exchange.t demonstrates that the lack of a file revision results in a corrupted repository on the client. Differential Revision: https://phab.mercurial-scm.org/D5404
tests/test-wireproto-command-filedata.t
tests/test-wireproto-command-filesdata.t
tests/test-wireproto-exchangev2.t
--- a/tests/test-wireproto-command-filedata.t
+++ b/tests/test-wireproto-command-filedata.t
@@ -22,19 +22,36 @@
   $ echo f1 > dir0/child1/f
   $ hg commit -m 'commit 2'
 
   $ hg -q up -r 0
   $ echo a2 >> a
   $ hg commit -m 'commit 3'
   created new head
 
+Create multiple heads introducing the same changeset
+
+  $ hg -q up -r 0
+  $ echo foo > dupe-file
+  $ hg commit -Am 'dupe 1'
+  adding dupe-file
+  created new head
+  $ hg -q up -r 0
+  $ echo foo > dupe-file
+  $ hg commit -Am 'dupe 2'
+  adding dupe-file
+  created new head
+
   $ hg log -G -T '{rev}:{node} {desc}\n'
-  @  3:5ce944d7fece1252dae06c34422b573c191b9489 commit 3
+  @  5:732c3dd7bee94242de656000e5f458e7ccfe2828 dupe 2
   |
+  | o  4:4334f10897d13c3e8beb4b636f7272b4ec2d0322 dupe 1
+  |/
+  | o  3:5ce944d7fece1252dae06c34422b573c191b9489 commit 3
+  |/
   | o  2:b3c27db01410dae01e5485d425b1440078df540c commit 2
   | |
   | o  1:3ef5e551f219ba505481d34d6b0316b017fa3f00 commit 1
   |/
   o  0:91b232a2253ce0638496f67bdfd7a4933fb51b25 commit 0
   
 
   $ hg --debug debugindex a
@@ -42,16 +59,20 @@
        0       0 649d149df43d83882523b7fb1e6a3af6f1907b39 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000
        1       1 0a86321f1379d1a9ecd0579a22977af7a5acaf11 649d149df43d83882523b7fb1e6a3af6f1907b39 0000000000000000000000000000000000000000
        2       3 7e5801b6d5f03a5a54f3c47b583f7567aad43e5b 649d149df43d83882523b7fb1e6a3af6f1907b39 0000000000000000000000000000000000000000
 
   $ hg --debug debugindex dir0/child0/e
      rev linkrev nodeid                                   p1                                       p2
        0       0 bbba6c06b30f443d34ff841bc985c4d0827c6be4 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000
 
+  $ hg --debug debugindex dupe-file
+     rev linkrev nodeid                                   p1                                       p2
+       0       4 2ed2a3912a0b24502043eae84ee4b279c18b90dd 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000
+
   $ hg serve -p $HGPORT -d --pid-file hg.pid -E error.log
   $ cat hg.pid > $DAEMON_PIDS
 
 Missing arguments is an error
 
   $ sendhttpv2peer << EOF
   > command filedata
   > EOF
@@ -304,9 +325,40 @@ Requesting parents and revision data wor
       b'parents': [
         b'd\x9d\x14\x9d\xf4=\x83\x88%#\xb7\xfb\x1ej:\xf6\xf1\x90{9',
         b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
       ]
     },
     b'a0\n00000000000000000000000000000000000000\n11111111111111111111111111111111111111\na2\n'
   ]
 
+Linknode for duplicate revision is the initial revision
+
+  $ sendhttpv2peer << EOF
+  > command filedata
+  >     nodes eval:[b'\x2e\xd2\xa3\x91\x2a\x0b\x24\x50\x20\x43\xea\xe8\x4e\xe4\xb2\x79\xc1\x8b\x90\xdd']
+  >     path eval:b'dupe-file'
+  >     fields eval:[b'linknode', b'parents', b'revision']
+  > EOF
+  creating http peer for wire protocol version 2
+  sending filedata command
+  response: gen[
+    {
+      b'totalitems': 1
+    },
+    {
+      b'fieldsfollowing': [
+        [
+          b'revision',
+          4
+        ]
+      ],
+      b'linknode': b'C4\xf1\x08\x97\xd1<>\x8b\xebKcorr\xb4\xec-\x03"',
+      b'node': b'.\xd2\xa3\x91*\x0b$P C\xea\xe8N\xe4\xb2y\xc1\x8b\x90\xdd',
+      b'parents': [
+        b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
+        b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+      ]
+    },
+    b'foo\n'
+  ]
+
   $ cat error.log
--- a/tests/test-wireproto-command-filesdata.t
+++ b/tests/test-wireproto-command-filesdata.t
@@ -29,19 +29,36 @@
   $ echo i0 > dir0/i
   $ hg -q commit -A -m 'commit 2'
 
   $ hg -q up -r 0
   $ echo a2 >> a
   $ hg commit -m 'commit 3'
   created new head
 
+Create multiple heads introducing the same file nodefile node
+
+  $ hg -q up -r 0
+  $ echo foo > dupe-file
+  $ hg commit -Am 'dupe 1'
+  adding dupe-file
+  created new head
+  $ hg -q up -r 0
+  $ echo foo > dupe-file
+  $ hg commit -Am 'dupe 2'
+  adding dupe-file
+  created new head
+
   $ hg log -G -T '{rev}:{node} {desc}\n'
-  @  3:476fbf122cd82f6726f0191ff146f67140946abc commit 3
+  @  5:47fc30580911232cb264675b402819deddf6c6f0 dupe 2
   |
+  | o  4:b16cce2967c1749ef4f4e3086a806cfbad8a3af7 dupe 1
+  |/
+  | o  3:476fbf122cd82f6726f0191ff146f67140946abc commit 3
+  |/
   | o  2:b91c03cbba3519ab149b6cd0a0afbdb5cf1b5c8a commit 2
   | |
   | o  1:5b0b1a23577e205ea240e39c9704e28d7697cbd8 commit 1
   |/
   o  0:6e875ff18c227659ad6143bb3580c65700734884 commit 0
   
 
   $ hg serve -p $HGPORT -d --pid-file hg.pid -E error.log
@@ -1156,9 +1173,121 @@ Requesting linknode field works
       b'totalitems': 1
     },
     {
       b'linknode': b'[\x0b\x1a#W~ ^\xa2@\xe3\x9c\x97\x04\xe2\x8dv\x97\xcb\xd8',
       b'node': b'\x03A\xfc\x84\x1b\xb5\xb4\xba\x93\xb2mM\xdaa\xf7y6]\xb3K'
     }
   ]
 
+Test behavior where a file node is introduced in 2 DAG heads
+
+Request for changeset introducing filenode returns linknode as self
+
+  $ sendhttpv2peer << EOF
+  > command filesdata
+  >     revisions eval:[{
+  >         b'type': b'changesetexplicit',
+  >         b'nodes': [
+  >             b'\xb1\x6c\xce\x29\x67\xc1\x74\x9e\xf4\xf4\xe3\x08\x6a\x80\x6c\xfb\xad\x8a\x3a\xf7',
+  >         ]}]
+  >     fields eval:[b'linknode']
+  >     pathfilter eval:{b'include': [b'path:dupe-file']}
+  > EOF
+  creating http peer for wire protocol version 2
+  sending filesdata command
+  response: gen[
+    {
+      b'totalitems': 1,
+      b'totalpaths': 1
+    },
+    {
+      b'path': b'dupe-file',
+      b'totalitems': 1
+    },
+    {
+      b'linknode': b'\xb1l\xce)g\xc1t\x9e\xf4\xf4\xe3\x08j\x80l\xfb\xad\x8a:\xf7',
+      b'node': b'.\xd2\xa3\x91*\x0b$P C\xea\xe8N\xe4\xb2y\xc1\x8b\x90\xdd'
+    }
+  ]
+
+  $ sendhttpv2peer << EOF
+  > command filesdata
+  >     revisions eval:[{
+  >         b'type': b'changesetexplicit',
+  >         b'nodes': [
+  >             b'\xb1\x6c\xce\x29\x67\xc1\x74\x9e\xf4\xf4\xe3\x08\x6a\x80\x6c\xfb\xad\x8a\x3a\xf7',
+  >         ]}]
+  >     fields eval:[b'linknode']
+  >     haveparents eval:True
+  >     pathfilter eval:{b'include': [b'path:dupe-file']}
+  > EOF
+  creating http peer for wire protocol version 2
+  sending filesdata command
+  response: gen[
+    {
+      b'totalitems': 1,
+      b'totalpaths': 1
+    },
+    {
+      b'path': b'dupe-file',
+      b'totalitems': 1
+    },
+    {
+      b'linknode': b'\xb1l\xce)g\xc1t\x9e\xf4\xf4\xe3\x08j\x80l\xfb\xad\x8a:\xf7',
+      b'node': b'.\xd2\xa3\x91*\x0b$P C\xea\xe8N\xe4\xb2y\xc1\x8b\x90\xdd'
+    }
+  ]
+
+Request for changeset where recorded linknode isn't in DAG ancestry will get
+rewritten accordingly
+TODO this is buggy
+
+  $ sendhttpv2peer << EOF
+  > command filesdata
+  >     revisions eval:[{
+  >         b'type': b'changesetexplicit',
+  >         b'nodes': [
+  >             b'\x47\xfc\x30\x58\x09\x11\x23\x2c\xb2\x64\x67\x5b\x40\x28\x19\xde\xdd\xf6\xc6\xf0',
+  >         ]}]
+  >     fields eval:[b'linknode']
+  >     pathfilter eval:{b'include': [b'path:dupe-file']}
+  > EOF
+  creating http peer for wire protocol version 2
+  sending filesdata command
+  response: gen[
+    {
+      b'totalitems': 1,
+      b'totalpaths': 1
+    },
+    {
+      b'path': b'dupe-file',
+      b'totalitems': 1
+    },
+    {
+      b'linknode': b'\xb1l\xce)g\xc1t\x9e\xf4\xf4\xe3\x08j\x80l\xfb\xad\x8a:\xf7',
+      b'node': b'.\xd2\xa3\x91*\x0b$P C\xea\xe8N\xe4\xb2y\xc1\x8b\x90\xdd'
+    }
+  ]
+
+TODO this is buggy
+
+  $ sendhttpv2peer << EOF
+  > command filesdata
+  >     revisions eval:[{
+  >         b'type': b'changesetexplicit',
+  >         b'nodes': [
+  >             b'\x47\xfc\x30\x58\x09\x11\x23\x2c\xb2\x64\x67\x5b\x40\x28\x19\xde\xdd\xf6\xc6\xf0',
+  >         ]}]
+  >     fields eval:[b'linknode']
+  >     haveparents eval:True
+  >     pathfilter eval:{b'include': [b'path:dupe-file']}
+  > EOF
+  creating http peer for wire protocol version 2
+  sending filesdata command
+  response: gen[
+    {
+      b'totalitems': 0,
+      b'totalpaths': 0
+    }
+  ]
+
   $ cat error.log
--- a/tests/test-wireproto-exchangev2.t
+++ b/tests/test-wireproto-exchangev2.t
@@ -1231,8 +1231,90 @@ Shallow clone doesn't work with revlogs
   received frame(size=11; request=1; stream=2; streamflags=encoded; type=command-response; flags=continuation)
   received frame(size=1005; request=1; stream=2; streamflags=encoded; type=command-response; flags=continuation)
   received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
   transaction abort!
   rollback completed
   (sent 5 HTTP requests and * bytes; received * bytes in responses) (glob)
   abort: revlog storage does not support missing parents write mode
   [255]
+
+  $ killdaemons.py
+
+Repo with 2 DAG branches introducing same filenode, to test linknode adjustment
+
+  $ hg init server-linknode
+  $ enablehttpv2 server-linknode
+  $ cd server-linknode
+  $ touch foo
+  $ hg -q commit -Am initial
+  $ echo foo > dupe-file
+  $ hg commit -Am 'dupe 1'
+  adding dupe-file
+  $ hg -q up -r 0
+  $ echo foo > dupe-file
+  $ hg commit -Am 'dupe 2'
+  adding dupe-file
+  created new head
+  $ hg serve -p $HGPORT -d --pid-file hg.pid -E error.log
+  $ cat hg.pid > $DAEMON_PIDS
+  $ cd ..
+
+Perform an incremental pull of both heads and ensure linkrev is written out properly
+
+  $ hg clone -r 96ee1d7354c4 http://localhost:$HGPORT client-linknode-1
+  new changesets 96ee1d7354c4
+  updating to branch default
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ cd client-linknode-1
+  $ touch extra
+  $ hg commit -Am extra
+  adding extra
+  $ cd ..
+
+  $ hg clone -r 96ee1d7354c4 http://localhost:$HGPORT client-linknode-2
+  new changesets 96ee1d7354c4
+  updating to branch default
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ cd client-linknode-2
+  $ touch extra
+  $ hg commit -Am extra
+  adding extra
+  $ cd ..
+
+  $ hg -R client-linknode-1 pull -r 1681c33f9f80
+  pulling from http://localhost:$HGPORT/
+  searching for changes
+  new changesets 1681c33f9f80
+  (run 'hg update' to get a working copy)
+
+#if reporevlogstore
+  $ hg -R client-linknode-1 debugrevlogindex dupe-file
+     rev linkrev nodeid       p1           p2
+       0       2 2ed2a3912a0b 000000000000 000000000000
+#endif
+
+  $ hg -R client-linknode-2 pull -r 639c8990d6a5
+  pulling from http://localhost:$HGPORT/
+  searching for changes
+  new changesets 639c8990d6a5
+  (run 'hg update' to get a working copy)
+
+#if reporevlogstore
+  $ hg -R client-linknode-2 debugrevlogindex dupe-file
+  abort: revlog 'dupe-file' not found
+  [255]
+#endif
+
+  $ hg -R client-linknode-2 verify
+  checking changesets
+  checking manifests
+  crosschecking files in changesets and manifests
+  checking files
+   warning: revlog 'data/dupe-file.i' not in fncache!
+   2: empty or missing dupe-file
+   dupe-file@2: manifest refers to unknown revision 2ed2a3912a0b
+  checked 3 changesets with 2 changes to 3 files
+  1 warnings encountered!
+  hint: run "hg debugrebuildfncache" to recover from corrupt fncache
+  2 integrity errors encountered!
+  (first damaged changeset appears to be 2)
+  [1]