Patchwork [RFC] run-tests: support per-line conditional output in tests

login
register
mail settings
Submitter Matt Harbison
Date April 4, 2017, 4:01 a.m.
Message ID <cfefdb4546a3a3891830.1491278515@Envy>
Download mbox | patch
Permalink /patch/19947/
State Superseded
Headers show

Comments

Matt Harbison - April 4, 2017, 4:01 a.m.
# HG changeset patch
# User Matt Harbison <matt_harbison@yahoo.com>
# Date 1491275149 14400
#      Mon Apr 03 23:05:49 2017 -0400
# Node ID cfefdb4546a3a38918303ed43447ebe93051de51
# Parent  81abd0d12c8641df666d356f6033d84cd55977a8
run-tests: support per-line conditional output in tests

Duplicating entire tests just because the output is different is both error
prone and can make the tests harder to read.  This harnesses the existing '(?)'
infrastructure, both to improve readability, and because it seemed like the path
of least resistance.

I think this syntax seems natural.  For example, this:

  2 r4/.hg/cache/checkisexec (execbit ?)

pretty naturally reads as "checkisexec, if execbit".  In some ways though, this
inverts the meaning of '?'.  For '(?)', the line is purely optional.  In the
example, it is mandatory iff execbit.  Otherwise, it is carried forward as
optional, to preserve the test output.  I tried it the other way, (listing
'no-exec' in the example), but that is too confusing to read.

The only thing that I haven't figured out yet is why the '(glob)' interferes
in the first hardlink.t hunk.  If it is kept, that line falls to the bottom of
the (xxx ?) sequence on Windows.  As it is, this test runs cleanly on Linux.
Kostia Balytskyi - April 4, 2017, 10:05 a.m.
On 04/04/2017 05:01, Matt Harbison wrote:

> # HG changeset patch

> # User Matt Harbison <matt_harbison@yahoo.com>

> # Date 1491275149 14400

> #      Mon Apr 03 23:05:49 2017 -0400

> # Node ID cfefdb4546a3a38918303ed43447ebe93051de51

> # Parent  81abd0d12c8641df666d356f6033d84cd55977a8

> run-tests: support per-line conditional output in tests

>

> Duplicating entire tests just because the output is different is both error

> prone and can make the tests harder to read.  This harnesses the existing '(?)'

> infrastructure, both to improve readability, and because it seemed like the path

> of least resistance.

>

> I think this syntax seems natural.  For example, this:

>

>    2 r4/.hg/cache/checkisexec (execbit ?)

>

> pretty naturally reads as "checkisexec, if execbit".  In some ways though, this

> inverts the meaning of '?'.  For '(?)', the line is purely optional.  In the

> example, it is mandatory iff execbit.  Otherwise, it is carried forward as

> optional, to preserve the test output.  I tried it the other way, (listing

> 'no-exec' in the example), but that is too confusing to read.


How about:

     2 r4/.hg/cache/checkisexec (execbit !)

Does that look like "mandatory iff execbit"?
In general, I am in favor of the idea.

>

> The only thing that I haven't figured out yet is why the '(glob)' interferes

> in the first hardlink.t hunk.  If it is kept, that line falls to the bottom of

> the (xxx ?) sequence on Windows.  As it is, this test runs cleanly on Linux.

>

> diff --git a/tests/run-tests.py b/tests/run-tests.py

> --- a/tests/run-tests.py

> +++ b/tests/run-tests.py

> @@ -497,6 +497,9 @@

>   # sans \t, \n and \r

>   CDATA_EVIL = re.compile(br"[\000-\010\013\014\016-\037]")

>   

> +#optline = re.compile(b'(.*) \(([a-z0-9 +.]*) \?\)\n$')

> +optline = re.compile(b'(.+) \((.+?) \?\)\n$')

> +

>   def cdatasafe(data):

>       """Make a string safe to include in a CDATA block.

>   

> @@ -1271,8 +1274,19 @@

>                       if r:

>                           els.pop(i)

>                           break

> -                    if el and el.endswith(b" (?)\n"):

> -                        optional.append(i)

> +                    if el:

> +                        if el.endswith(b" (?)\n"):

> +                            optional.append(i)

> +                        else:

> +                            m = optline.match(el)

> +                            if m:

> +                                conditions = [c for c in m.group(2).split(' ')]

> +

> +                                if self._hghave(conditions)[0]:

> +                                    lout = el

> +                                else:

> +                                    optional.append(i)

> +

>                       i += 1

>   

>                   if r:

> @@ -1298,8 +1312,10 @@

>                   # clean up any optional leftovers

>                   while expected.get(pos, None):

>                       el = expected[pos].pop(0)

> -                    if el and not el.endswith(b" (?)\n"):

> -                        break

> +                    if el:

> +                        if (not optline.match(el)

> +                            and not el.endswith(b" (?)\n")):

> +                            break

>                       postout.append(b'  ' + el)

>   

>               if lcmd:

> @@ -1371,6 +1387,12 @@

>               if el.endswith(b" (?)\n"):

>                   retry = "retry"

>                   el = el[:-5] + b"\n"

> +            else:

> +                m = optline.match(el)

> +                if m:

> +                    el = m.group(1) + b"\n"

> +                    retry = "retry"

> +

>               if el.endswith(b" (esc)\n"):

>                   if PYTHON3:

>                       el = el[:-7].decode('unicode_escape') + '\n'

> diff --git a/tests/test-clone.t b/tests/test-clone.t

> --- a/tests/test-clone.t

> +++ b/tests/test-clone.t

> @@ -31,10 +31,10 @@

>     default                       10:a7949464abda

>     $ ls .hg/cache

>     branch2-served

> -  checkisexec

> -  checklink

> -  checklink-target

> -  checknoexec

> +  checkisexec (execbit ?)

> +  checklink (symlink ?)

> +  checklink-target (symlink ?)

> +  checknoexec (execbit ?)

>     rbc-names-v1

>     rbc-revs-v1

>   

> @@ -49,9 +49,9 @@

>   

>     $ ls .hg/cache

>     branch2-served

> -  checkisexec

> -  checklink

> -  checklink-target

> +  checkisexec (execbit ?)

> +  checklink (symlink ?)

> +  checklink-target (symlink ?)

>   

>     $ cat a

>     a

> diff --git a/tests/test-fileset.t b/tests/test-fileset.t

> --- a/tests/test-fileset.t

> +++ b/tests/test-fileset.t

> @@ -441,10 +441,10 @@

>     M b2

>     A 1k

>     A 2k

> -  A b2link

> +  A b2link (no-windows ?)

>     A bin

>     A c1

> -  A con.xml

> +  A con.xml (no-windows ?)

>     R a2

>     $ hg status --change 2

>     M b2

> @@ -452,10 +452,10 @@

>     M b2

>     A 1k

>     A 2k

> -  A b2link

> +  A b2link (no-windows ?)

>     A bin

>     A c1

> -  A con.xml

> +  A con.xml (no-windows ?)

>     R a2

>     $ hg status --change 4

>     A .hgsub

> @@ -464,7 +464,7 @@

>     A dos

>     A mac

>     A mixed

> -  R con.xml

> +  R con.xml (no-windows ?)

>     ! a1

>     ? b2.orig

>     ? c3

> @@ -551,9 +551,9 @@

>   ------------

>   

>     $ hg status --removed  --rev 4

> -  R con.xml

> +  R con.xml (no-windows ?)

>     $ fileset "status(4, 'wdir()', removed())"

> -  con.xml

> +  con.xml (no-windows ?)

>   

>     $ hg status --removed --rev 2

>     R a2

> @@ -585,19 +585,19 @@

>     A .hgsubstate

>     A 1k

>     A 2k

> -  A b2link

> +  A b2link (no-windows ?)

>     A bin

>     A c1

> -  A con.xml

> +  A con.xml (no-windows ?)

>     $ fileset "status('0:1', '3:4', added())"

>     .hgsub

>     .hgsubstate

>     1k

>     2k

> -  b2link

> +  b2link (no-windows ?)

>     bin

>     c1

> -  con.xml

> +  con.xml (no-windows ?)

>   

>   tests with empty value

>   ----------------------

> diff --git a/tests/test-hardlinks.t b/tests/test-hardlinks.t

> --- a/tests/test-hardlinks.t

> +++ b/tests/test-hardlinks.t

> @@ -211,10 +211,10 @@

>     2 r4/.hg/00changelog.i

>     2 r4/.hg/branch

>     2 r4/.hg/cache/branch2-served

> -  2 r4/.hg/cache/checkisexec

> +  2 r4/.hg/cache/checkisexec (execbit ?)

>     3 r4/.hg/cache/checklink (?)

> -  ? r4/.hg/cache/checklink-target (glob)

> -  2 r4/.hg/cache/checknoexec

> +  ? r4/.hg/cache/checklink-target (glob) (symlink ?)

> +  2 r4/.hg/cache/checknoexec (execbit ?)

>     2 r4/.hg/cache/rbc-names-v1

>     2 r4/.hg/cache/rbc-revs-v1

>     2 r4/.hg/dirstate

> @@ -251,9 +251,9 @@

>     2 r4/.hg/00changelog.i

>     1 r4/.hg/branch

>     2 r4/.hg/cache/branch2-served

> -  2 r4/.hg/cache/checkisexec

> -  2 r4/.hg/cache/checklink-target

> -  2 r4/.hg/cache/checknoexec

> +  2 r4/.hg/cache/checkisexec (execbit ?)

> +  2 r4/.hg/cache/checklink-target (symlink ?)

> +  2 r4/.hg/cache/checknoexec (execbit ?)

>     2 r4/.hg/cache/rbc-names-v1

>     2 r4/.hg/cache/rbc-revs-v1

>     1 r4/.hg/dirstate

> diff --git a/tests/test-tags.t b/tests/test-tags.t

> --- a/tests/test-tags.t

> +++ b/tests/test-tags.t

> @@ -672,9 +672,9 @@

>   

>     $ ls tagsclient/.hg/cache

>     branch2-served

> -  checkisexec

> -  checklink

> -  checklink-target

> +  checkisexec (execbit ?)

> +  checklink (symlink ?)

> +  checklink-target (symlink ?)

>     hgtagsfnodes1

>     rbc-names-v1

>     rbc-revs-v1

> @@ -699,9 +699,9 @@

>   

>     $ ls tagsclient/.hg/cache

>     branch2-served

> -  checkisexec

> -  checklink

> -  checklink-target

> +  checkisexec (execbit ?)

> +  checklink (symlink ?)

> +  checklink-target (symlink ?)

>     hgtagsfnodes1

>     rbc-names-v1

>     rbc-revs-v1

> _______________________________________________

> Mercurial-devel mailing list

> Mercurial-devel@mercurial-scm.org

> https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Matt Harbison - April 5, 2017, 3:58 a.m.
On Tue, 04 Apr 2017 00:01:55 -0400, Matt Harbison <mharbison72@gmail.com>  
wrote:

> # HG changeset patch
> # User Matt Harbison <matt_harbison@yahoo.com>
> # Date 1491275149 14400
> #      Mon Apr 03 23:05:49 2017 -0400
> # Node ID cfefdb4546a3a38918303ed43447ebe93051de51
> # Parent  81abd0d12c8641df666d356f6033d84cd55977a8
> run-tests: support per-line conditional output in tests
>
> Duplicating entire tests just because the output is different is both  
> error
> prone and can make the tests harder to read.  This harnesses the  
> existing '(?)'
> infrastructure, both to improve readability, and because it seemed like  
> the path
> of least resistance.
>
> I think this syntax seems natural.  For example, this:
>
>   2 r4/.hg/cache/checkisexec (execbit ?)
>
> pretty naturally reads as "checkisexec, if execbit".  In some ways  
> though, this
> inverts the meaning of '?'.  For '(?)', the line is purely optional.  In  
> the
> example, it is mandatory iff execbit.  Otherwise, it is carried forward  
> as
> optional, to preserve the test output.  I tried it the other way,  
> (listing
> 'no-exec' in the example), but that is too confusing to read.
>
> The only thing that I haven't figured out yet is why the '(glob)'  
> interferes
> in the first hardlink.t hunk.  If it is kept, that line falls to the  
> bottom of
> the (xxx ?) sequence on Windows.  As it is, this test runs cleanly on  
> Linux.

Actually, this is an existing problem with '(?)' too.  Changing (xxx ?) to  
(?) without the *.py changes yields the same behavior.


> diff --git a/tests/run-tests.py b/tests/run-tests.py
> --- a/tests/run-tests.py
> +++ b/tests/run-tests.py
> @@ -497,6 +497,9 @@
>  # sans \t, \n and \r
>  CDATA_EVIL = re.compile(br"[\000-\010\013\014\016-\037]")
> +#optline = re.compile(b'(.*) \(([a-z0-9 +.]*) \?\)\n$')
> +optline = re.compile(b'(.+) \((.+?) \?\)\n$')
> +
>  def cdatasafe(data):
>      """Make a string safe to include in a CDATA block.
> @@ -1271,8 +1274,19 @@
>                      if r:
>                          els.pop(i)
>                          break
> -                    if el and el.endswith(b" (?)\n"):
> -                        optional.append(i)
> +                    if el:
> +                        if el.endswith(b" (?)\n"):
> +                            optional.append(i)
> +                        else:
> +                            m = optline.match(el)
> +                            if m:
> +                                conditions = [c for c in  
> m.group(2).split(' ')]
> +
> +                                if self._hghave(conditions)[0]:
> +                                    lout = el
> +                                else:
> +                                    optional.append(i)
> +
>                      i += 1
>                 if r:
> @@ -1298,8 +1312,10 @@
>                  # clean up any optional leftovers
>                  while expected.get(pos, None):
>                      el = expected[pos].pop(0)
> -                    if el and not el.endswith(b" (?)\n"):
> -                        break
> +                    if el:
> +                        if (not optline.match(el)
> +                            and not el.endswith(b" (?)\n")):
> +                            break
>                      postout.append(b'  ' + el)
>             if lcmd:
> @@ -1371,6 +1387,12 @@
>              if el.endswith(b" (?)\n"):
>                  retry = "retry"
>                  el = el[:-5] + b"\n"
> +            else:
> +                m = optline.match(el)
> +                if m:
> +                    el = m.group(1) + b"\n"
> +                    retry = "retry"
> +
>              if el.endswith(b" (esc)\n"):
>                  if PYTHON3:
>                      el = el[:-7].decode('unicode_escape') + '\n'
> diff --git a/tests/test-clone.t b/tests/test-clone.t
> --- a/tests/test-clone.t
> +++ b/tests/test-clone.t
> @@ -31,10 +31,10 @@
>    default                       10:a7949464abda
>    $ ls .hg/cache
>    branch2-served
> -  checkisexec
> -  checklink
> -  checklink-target
> -  checknoexec
> +  checkisexec (execbit ?)
> +  checklink (symlink ?)
> +  checklink-target (symlink ?)
> +  checknoexec (execbit ?)
>    rbc-names-v1
>    rbc-revs-v1
> @@ -49,9 +49,9 @@
>   $ ls .hg/cache
>    branch2-served
> -  checkisexec
> -  checklink
> -  checklink-target
> +  checkisexec (execbit ?)
> +  checklink (symlink ?)
> +  checklink-target (symlink ?)
>   $ cat a
>    a
> diff --git a/tests/test-fileset.t b/tests/test-fileset.t
> --- a/tests/test-fileset.t
> +++ b/tests/test-fileset.t
> @@ -441,10 +441,10 @@
>    M b2
>    A 1k
>    A 2k
> -  A b2link
> +  A b2link (no-windows ?)
>    A bin
>    A c1
> -  A con.xml
> +  A con.xml (no-windows ?)
>    R a2
>    $ hg status --change 2
>    M b2
> @@ -452,10 +452,10 @@
>    M b2
>    A 1k
>    A 2k
> -  A b2link
> +  A b2link (no-windows ?)
>    A bin
>    A c1
> -  A con.xml
> +  A con.xml (no-windows ?)
>    R a2
>    $ hg status --change 4
>    A .hgsub
> @@ -464,7 +464,7 @@
>    A dos
>    A mac
>    A mixed
> -  R con.xml
> +  R con.xml (no-windows ?)
>    ! a1
>    ? b2.orig
>    ? c3
> @@ -551,9 +551,9 @@
>  ------------
>   $ hg status --removed  --rev 4
> -  R con.xml
> +  R con.xml (no-windows ?)
>    $ fileset "status(4, 'wdir()', removed())"
> -  con.xml
> +  con.xml (no-windows ?)
>   $ hg status --removed --rev 2
>    R a2
> @@ -585,19 +585,19 @@
>    A .hgsubstate
>    A 1k
>    A 2k
> -  A b2link
> +  A b2link (no-windows ?)
>    A bin
>    A c1
> -  A con.xml
> +  A con.xml (no-windows ?)
>    $ fileset "status('0:1', '3:4', added())"
>    .hgsub
>    .hgsubstate
>    1k
>    2k
> -  b2link
> +  b2link (no-windows ?)
>    bin
>    c1
> -  con.xml
> +  con.xml (no-windows ?)
> tests with empty value
>  ----------------------
> diff --git a/tests/test-hardlinks.t b/tests/test-hardlinks.t
> --- a/tests/test-hardlinks.t
> +++ b/tests/test-hardlinks.t
> @@ -211,10 +211,10 @@
>    2 r4/.hg/00changelog.i
>    2 r4/.hg/branch
>    2 r4/.hg/cache/branch2-served
> -  2 r4/.hg/cache/checkisexec
> +  2 r4/.hg/cache/checkisexec (execbit ?)
>    3 r4/.hg/cache/checklink (?)
> -  ? r4/.hg/cache/checklink-target (glob)
> -  2 r4/.hg/cache/checknoexec
> +  ? r4/.hg/cache/checklink-target (glob) (symlink ?)
> +  2 r4/.hg/cache/checknoexec (execbit ?)
>    2 r4/.hg/cache/rbc-names-v1
>    2 r4/.hg/cache/rbc-revs-v1
>    2 r4/.hg/dirstate
> @@ -251,9 +251,9 @@
>    2 r4/.hg/00changelog.i
>    1 r4/.hg/branch
>    2 r4/.hg/cache/branch2-served
> -  2 r4/.hg/cache/checkisexec
> -  2 r4/.hg/cache/checklink-target
> -  2 r4/.hg/cache/checknoexec
> +  2 r4/.hg/cache/checkisexec (execbit ?)
> +  2 r4/.hg/cache/checklink-target (symlink ?)
> +  2 r4/.hg/cache/checknoexec (execbit ?)
>    2 r4/.hg/cache/rbc-names-v1
>    2 r4/.hg/cache/rbc-revs-v1
>    1 r4/.hg/dirstate
> diff --git a/tests/test-tags.t b/tests/test-tags.t
> --- a/tests/test-tags.t
> +++ b/tests/test-tags.t
> @@ -672,9 +672,9 @@
>   $ ls tagsclient/.hg/cache
>    branch2-served
> -  checkisexec
> -  checklink
> -  checklink-target
> +  checkisexec (execbit ?)
> +  checklink (symlink ?)
> +  checklink-target (symlink ?)
>    hgtagsfnodes1
>    rbc-names-v1
>    rbc-revs-v1
> @@ -699,9 +699,9 @@
>   $ ls tagsclient/.hg/cache
>    branch2-served
> -  checkisexec
> -  checklink
> -  checklink-target
> +  checkisexec (execbit ?)
> +  checklink (symlink ?)
> +  checklink-target (symlink ?)
>    hgtagsfnodes1
>    rbc-names-v1
>    rbc-revs-v1
Jun Wu - April 6, 2017, 10:27 p.m.
Excerpts from Matt Harbison's message of 2017-04-04 00:01:55 -0400:
> The only thing that I haven't figured out yet is why the '(glob)' interferes
> in the first hardlink.t hunk.  If it is kept, that line falls to the bottom of
> the (xxx ?) sequence on Windows.  As it is, this test runs cleanly on Linux.

From 6a672c3b7860, it seems we may be able to just say 2 there:

  -  ? r4/.hg/cache/checklink-target (glob)
  +  2 r4/.hg/cache/checklink-target

I like this feature.
Matt Harbison - April 7, 2017, 12:06 a.m.
On Thu, 06 Apr 2017 18:27:31 -0400, Jun Wu <quark@fb.com> wrote:

> Excerpts from Matt Harbison's message of 2017-04-04 00:01:55 -0400:
>> The only thing that I haven't figured out yet is why the '(glob)'  
>> interferes
>> in the first hardlink.t hunk.  If it is kept, that line falls to the  
>> bottom of
>> the (xxx ?) sequence on Windows.  As it is, this test runs cleanly on  
>> Linux.
>
> From 6a672c3b7860, it seems we may be able to just say 2 there:
>
>   -  ? r4/.hg/cache/checklink-target (glob)
>   +  2 r4/.hg/cache/checklink-target

Interesting.  That's the commit that changed it from a number to the glob,  
so I assumed that it was important.  I did manage to fix the issue, and  
don't have OS X in front of me, so I'll leave that alone for now.

> I like this feature.
Jun Wu - April 7, 2017, 12:15 a.m.
Excerpts from Matt Harbison's message of 2017-04-06 20:06:02 -0400:
> On Thu, 06 Apr 2017 18:27:31 -0400, Jun Wu <quark@fb.com> wrote:
> 
> > Excerpts from Matt Harbison's message of 2017-04-04 00:01:55 -0400:
> >> The only thing that I haven't figured out yet is why the '(glob)'  
> >> interferes
> >> in the first hardlink.t hunk.  If it is kept, that line falls to the  
> >> bottom of
> >> the (xxx ?) sequence on Windows.  As it is, this test runs cleanly on  
> >> Linux.
> >
> > From 6a672c3b7860, it seems we may be able to just say 2 there:
> >
> >   -  ? r4/.hg/cache/checklink-target (glob)
> >   +  2 r4/.hg/cache/checklink-target
> 
> Interesting.  That's the commit that changed it from a number to the glob,  
> so I assumed that it was important.  I did manage to fix the issue, and  
> don't have OS X in front of me, so I'll leave that alone for now.

The minus and plus signs are the change I think we can make, not the patch
introduced.

6a672c3b7860 is inconsistent about "checklink-target" it added to the test.
One of them uses "?", the other uses "2". So I think we can change it to "2"
without issues.

> 
> > I like this feature.
Matt Harbison - April 7, 2017, 3:25 a.m.
On Thu, 06 Apr 2017 20:15:41 -0400, Jun Wu <quark@fb.com> wrote:

> Excerpts from Matt Harbison's message of 2017-04-06 20:06:02 -0400:
>> On Thu, 06 Apr 2017 18:27:31 -0400, Jun Wu <quark@fb.com> wrote:
>>
>> > Excerpts from Matt Harbison's message of 2017-04-04 00:01:55 -0400:
>> >> The only thing that I haven't figured out yet is why the '(glob)'
>> >> interferes
>> >> in the first hardlink.t hunk.  If it is kept, that line falls to the
>> >> bottom of
>> >> the (xxx ?) sequence on Windows.  As it is, this test runs cleanly on
>> >> Linux.
>> >
>> > From 6a672c3b7860, it seems we may be able to just say 2 there:
>> >
>> >   -  ? r4/.hg/cache/checklink-target (glob)
>> >   +  2 r4/.hg/cache/checklink-target
>>
>> Interesting.  That's the commit that changed it from a number to the  
>> glob,
>> so I assumed that it was important.  I did manage to fix the issue, and
>> don't have OS X in front of me, so I'll leave that alone for now.
>
> The minus and plus signs are the change I think we can make, not the  
> patch
> introduced.

Yep.  I misread original commit.

> 6a672c3b7860 is inconsistent about "checklink-target" it added to the  
> test.
> One of them uses "?", the other uses "2". So I think we can change it to  
> "2"
> without issues.

If that's true, then I guess the 'checklink (?)' line is unnecessary too,  
because it isn't in the later test either.  I don't have access to  
Solaris, but I'll try to check on OS X tomorrow if I remember.

>>
>> > I like this feature.

Patch

diff --git a/tests/run-tests.py b/tests/run-tests.py
--- a/tests/run-tests.py
+++ b/tests/run-tests.py
@@ -497,6 +497,9 @@ 
 # sans \t, \n and \r
 CDATA_EVIL = re.compile(br"[\000-\010\013\014\016-\037]")
 
+#optline = re.compile(b'(.*) \(([a-z0-9 +.]*) \?\)\n$')
+optline = re.compile(b'(.+) \((.+?) \?\)\n$')
+
 def cdatasafe(data):
     """Make a string safe to include in a CDATA block.
 
@@ -1271,8 +1274,19 @@ 
                     if r:
                         els.pop(i)
                         break
-                    if el and el.endswith(b" (?)\n"):
-                        optional.append(i)
+                    if el:
+                        if el.endswith(b" (?)\n"):
+                            optional.append(i)
+                        else:
+                            m = optline.match(el)
+                            if m:
+                                conditions = [c for c in m.group(2).split(' ')]
+
+                                if self._hghave(conditions)[0]:
+                                    lout = el
+                                else:
+                                    optional.append(i)
+
                     i += 1
 
                 if r:
@@ -1298,8 +1312,10 @@ 
                 # clean up any optional leftovers
                 while expected.get(pos, None):
                     el = expected[pos].pop(0)
-                    if el and not el.endswith(b" (?)\n"):
-                        break
+                    if el:
+                        if (not optline.match(el)
+                            and not el.endswith(b" (?)\n")):
+                            break
                     postout.append(b'  ' + el)
 
             if lcmd:
@@ -1371,6 +1387,12 @@ 
             if el.endswith(b" (?)\n"):
                 retry = "retry"
                 el = el[:-5] + b"\n"
+            else:
+                m = optline.match(el)
+                if m:
+                    el = m.group(1) + b"\n"
+                    retry = "retry"
+
             if el.endswith(b" (esc)\n"):
                 if PYTHON3:
                     el = el[:-7].decode('unicode_escape') + '\n'
diff --git a/tests/test-clone.t b/tests/test-clone.t
--- a/tests/test-clone.t
+++ b/tests/test-clone.t
@@ -31,10 +31,10 @@ 
   default                       10:a7949464abda
   $ ls .hg/cache
   branch2-served
-  checkisexec
-  checklink
-  checklink-target
-  checknoexec
+  checkisexec (execbit ?)
+  checklink (symlink ?)
+  checklink-target (symlink ?)
+  checknoexec (execbit ?)
   rbc-names-v1
   rbc-revs-v1
 
@@ -49,9 +49,9 @@ 
 
   $ ls .hg/cache
   branch2-served
-  checkisexec
-  checklink
-  checklink-target
+  checkisexec (execbit ?)
+  checklink (symlink ?)
+  checklink-target (symlink ?)
 
   $ cat a
   a
diff --git a/tests/test-fileset.t b/tests/test-fileset.t
--- a/tests/test-fileset.t
+++ b/tests/test-fileset.t
@@ -441,10 +441,10 @@ 
   M b2
   A 1k
   A 2k
-  A b2link
+  A b2link (no-windows ?)
   A bin
   A c1
-  A con.xml
+  A con.xml (no-windows ?)
   R a2
   $ hg status --change 2
   M b2
@@ -452,10 +452,10 @@ 
   M b2
   A 1k
   A 2k
-  A b2link
+  A b2link (no-windows ?)
   A bin
   A c1
-  A con.xml
+  A con.xml (no-windows ?)
   R a2
   $ hg status --change 4
   A .hgsub
@@ -464,7 +464,7 @@ 
   A dos
   A mac
   A mixed
-  R con.xml
+  R con.xml (no-windows ?)
   ! a1
   ? b2.orig
   ? c3
@@ -551,9 +551,9 @@ 
 ------------
 
   $ hg status --removed  --rev 4
-  R con.xml
+  R con.xml (no-windows ?)
   $ fileset "status(4, 'wdir()', removed())"
-  con.xml
+  con.xml (no-windows ?)
 
   $ hg status --removed --rev 2
   R a2
@@ -585,19 +585,19 @@ 
   A .hgsubstate
   A 1k
   A 2k
-  A b2link
+  A b2link (no-windows ?)
   A bin
   A c1
-  A con.xml
+  A con.xml (no-windows ?)
   $ fileset "status('0:1', '3:4', added())"
   .hgsub
   .hgsubstate
   1k
   2k
-  b2link
+  b2link (no-windows ?)
   bin
   c1
-  con.xml
+  con.xml (no-windows ?)
 
 tests with empty value
 ----------------------
diff --git a/tests/test-hardlinks.t b/tests/test-hardlinks.t
--- a/tests/test-hardlinks.t
+++ b/tests/test-hardlinks.t
@@ -211,10 +211,10 @@ 
   2 r4/.hg/00changelog.i
   2 r4/.hg/branch
   2 r4/.hg/cache/branch2-served
-  2 r4/.hg/cache/checkisexec
+  2 r4/.hg/cache/checkisexec (execbit ?)
   3 r4/.hg/cache/checklink (?)
-  ? r4/.hg/cache/checklink-target (glob)
-  2 r4/.hg/cache/checknoexec
+  ? r4/.hg/cache/checklink-target (glob) (symlink ?)
+  2 r4/.hg/cache/checknoexec (execbit ?)
   2 r4/.hg/cache/rbc-names-v1
   2 r4/.hg/cache/rbc-revs-v1
   2 r4/.hg/dirstate
@@ -251,9 +251,9 @@ 
   2 r4/.hg/00changelog.i
   1 r4/.hg/branch
   2 r4/.hg/cache/branch2-served
-  2 r4/.hg/cache/checkisexec
-  2 r4/.hg/cache/checklink-target
-  2 r4/.hg/cache/checknoexec
+  2 r4/.hg/cache/checkisexec (execbit ?)
+  2 r4/.hg/cache/checklink-target (symlink ?)
+  2 r4/.hg/cache/checknoexec (execbit ?)
   2 r4/.hg/cache/rbc-names-v1
   2 r4/.hg/cache/rbc-revs-v1
   1 r4/.hg/dirstate
diff --git a/tests/test-tags.t b/tests/test-tags.t
--- a/tests/test-tags.t
+++ b/tests/test-tags.t
@@ -672,9 +672,9 @@ 
 
   $ ls tagsclient/.hg/cache
   branch2-served
-  checkisexec
-  checklink
-  checklink-target
+  checkisexec (execbit ?)
+  checklink (symlink ?)
+  checklink-target (symlink ?)
   hgtagsfnodes1
   rbc-names-v1
   rbc-revs-v1
@@ -699,9 +699,9 @@ 
 
   $ ls tagsclient/.hg/cache
   branch2-served
-  checkisexec
-  checklink
-  checklink-target
+  checkisexec (execbit ?)
+  checklink (symlink ?)
+  checklink-target (symlink ?)
   hgtagsfnodes1
   rbc-names-v1
   rbc-revs-v1