debugcommands: introduce actions to perform deterministic reads
authorGregory Szorc <gregory.szorc@gmail.com>
Mon, 12 Mar 2018 15:49:02 -0700
changeset 37010 143219fc2620
parent 37009 8e89c2bec1f7
child 37011 16203c6079e7
debugcommands: introduce actions to perform deterministic reads "readavailable" is useful as a debugging device to see what data is available on a pipe. But the mechanism isn't deterministic because what's available on a pipe is highly conditional on timing, system load, OS behavior, etc. This makes it not suitable for tests. We introduce "ereadline," "read," and "eread" for performing deterministic I/O operations (at least on blocking file descriptors). We stop short of converting existing consumers of "readavailable" in tests because we're working out race conditions and deadlocks on Windows. But the goal is to eventually move tests away from "readavailable" to these new APIs. Differential Revision: https://phab.mercurial-scm.org/D2720
mercurial/debugcommands.py
--- a/mercurial/debugcommands.py	Wed Mar 07 20:41:59 2018 -0800
+++ b/mercurial/debugcommands.py	Mon Mar 12 15:49:02 2018 -0700
@@ -2715,6 +2715,21 @@
 
     Read a line of output from the server. If there are multiple output
     pipes, reads only the main pipe.
+
+    ereadline
+    ---------
+
+    Like ``readline``, but read from the stderr pipe, if available.
+
+    read <X>
+    --------
+
+    ``read()`` N bytes from the server's main output pipe.
+
+    eread <X>
+    ---------
+
+    ``read()`` N bytes from the server's stderr pipe, if available.
     """
     opts = pycompat.byteskwargs(opts)
 
@@ -2855,6 +2870,14 @@
             stderr.read()
         elif action == 'readline':
             stdout.readline()
+        elif action == 'ereadline':
+            stderr.readline()
+        elif action.startswith('read '):
+            count = int(action.split(' ', 1)[1])
+            stdout.read(count)
+        elif action.startswith('eread '):
+            count = int(action.split(' ', 1)[1])
+            stderr.read(count)
         else:
             raise error.Abort(_('unknown action: %s') % action)