Remove symlinks created in argv0-symlink.exp and general cleanup

Message ID 1438287227-11303-1-git-send-email-simon.marchi@ericsson.com
State New, archived
Headers

Commit Message

Simon Marchi July 30, 2015, 8:13 p.m. UTC
  When running argv0-symlink.exp, symlinks are left in the test output
directory.  One of them is a recursive symlink.  This causes the same tests
to be found multiple times and disturbs subsequent test runs.

To witness it simply, just run

  $ make check RUNTESTFLAGS="argv0-symlink.exp"

twice in a row.  The second run will find and run argv0-symlink.exp
multiple times because of the recursive symlink left by the first run.  Note
that this only happens when building in tree.  The simple fix is to
remove the links when we are done.

At the same time, I did a general cleanup of the test:

  - Add and use a create_link proc.
  - Bail out early if target does not support argv[0].
  - Of course, remove created symlinks before returning.

gdb/testsuite/ChangeLog:

	* gdb.base/argv0-symlink.exp: Remove symlinks when done.
	General cleanup.
---
 gdb/testsuite/gdb.base/argv0-symlink.exp | 90 ++++++++++++++++++++------------
 1 file changed, 56 insertions(+), 34 deletions(-)
  

Comments

Pedro Alves Aug. 3, 2015, 2:23 p.m. UTC | #1
On 07/30/2015 09:13 PM, Simon Marchi wrote:
> When running argv0-symlink.exp, symlinks are left in the test output
> directory.  One of them is a recursive symlink.  This causes the same tests
> to be found multiple times and disturbs subsequent test runs.
> 
> To witness it simply, just run
> 
>   $ make check RUNTESTFLAGS="argv0-symlink.exp"
> 
> twice in a row.  The second run will find and run argv0-symlink.exp
> multiple times because of the recursive symlink left by the first run.  Note
> that this only happens when building in tree.  The simple fix is to
> remove the links when we are done.
> 
> At the same time, I did a general cleanup of the test:
> 
>   - Add and use a create_link proc.

>   - Bail out early if target does not support argv[0].

What's the rationale for that?  It seems that'd skip the
tests that ensure that "info inferiors" shows the $filelink; those
aren't currently guarded by $has_argv.  AFAICS, that was done
on purpose.  See:

 git show 673dc4a0
 git show 673dc4a0:gdb/testsuite/gdb.base/argv0-symlink.exp

>   - Of course, remove created symlinks before returning.

I think you should leave them, actually.  That's a general direction
we've been following -- leaving build/test artifacts in place in case
the test fails and we need to debug what happened.
So instead what we do is remove any leftover from a previous run
that could interfere, when we start a new run.  (I think the patch
is already doing that too.)

Thanks,
Pedro Alves
  
Simon Marchi Aug. 3, 2015, 3:16 p.m. UTC | #2
On 15-08-03 10:23 AM, Pedro Alves wrote:
> On 07/30/2015 09:13 PM, Simon Marchi wrote:
>> When running argv0-symlink.exp, symlinks are left in the test output
>> directory.  One of them is a recursive symlink.  This causes the same tests
>> to be found multiple times and disturbs subsequent test runs.
>>
>> To witness it simply, just run
>>
>>   $ make check RUNTESTFLAGS="argv0-symlink.exp"
>>
>> twice in a row.  The second run will find and run argv0-symlink.exp
>> multiple times because of the recursive symlink left by the first run.  Note
>> that this only happens when building in tree.  The simple fix is to
>> remove the links when we are done.
>>
>> At the same time, I did a general cleanup of the test:
>>
>>   - Add and use a create_link proc.
> 
>>   - Bail out early if target does not support argv[0].
> 
> What's the rationale for that?  It seems that'd skip the
> tests that ensure that "info inferiors" shows the $filelink; those
> aren't currently guarded by $has_argv.  AFAICS, that was done
> on purpose.  See:
> 
>  git show 673dc4a0
>  git show 673dc4a0:gdb/testsuite/gdb.base/argv0-symlink.exp

Right.

>>   - Of course, remove created symlinks before returning.
> 
> I think you should leave them, actually.  That's a general direction
> we've been following -- leaving build/test artifacts in place in case
> the test fails and we need to debug what happened.
> So instead what we do is remove any leftover from a previous run
> that could interfere, when we start a new run.  (I think the patch
> is already doing that too.)

It makes sense.

The problem is that it also affects when running other tests.
For example, doing a

  $ make check RUNTESTFLAGS="argv0-symlink.exp"

and then

  $ make check RUNTESTFLAGS="whatis.exp"

gives

  http://paste.ubuntu.com/11993577/

At least, it's possible to avoid it by doing

  $ make check RUNTESTFLAGS="gdb.base/whatis.exp"

instead.  However, it also affect those as well:

  $ make check
  $ make check RUNTESTFLAGS="--directory=gdb.base"

runtest will find all tests recursively, resulting in this:

  http://paste.ubuntu.com/11993659/

Building out-of-tree would avoid this altogether, of course.  The
reason I build in-tree is that I use a script [1] to regression-test
my patches.  The script is a bit dumb and requires to build in the
git repo.  I think I'll improve it a bit to make it possible to
build OOT.

Simon

[1] https://github.com/simark/gdb-check
  
Pedro Alves Aug. 3, 2015, 4:34 p.m. UTC | #3
On 08/03/2015 04:16 PM, Simon Marchi wrote:

> The problem is that it also affects when running other tests.
> For example, doing a
> 
>   $ make check RUNTESTFLAGS="argv0-symlink.exp"
> 
> and then
> 
>   $ make check RUNTESTFLAGS="whatis.exp"
> 
> gives
> 
>   http://paste.ubuntu.com/11993577/

Urgh.  Maybe there's some other change to argv0-symlink.exp
that could be made to avoid this?  I haven't looked at this
in enough detail to give a good informed suggestion, but
maybe putting the symlink elsewhere?

> 
> At least, it's possible to avoid it by doing
> 
>   $ make check RUNTESTFLAGS="gdb.base/whatis.exp"
> 
> instead.  However, it also affect those as well:
> 
>   $ make check
>   $ make check RUNTESTFLAGS="--directory=gdb.base"
> 
> runtest will find all tests recursively, resulting in this:
> 
>   http://paste.ubuntu.com/11993659/
> 
> Building out-of-tree would avoid this altogether, of course.  The
> reason I build in-tree is that I use a script [1] to regression-test
> my patches.  The script is a bit dumb and requires to build in the
> git repo.  I think I'll improve it a bit to make it possible to
> build OOT.

Personally, I'd vote for making in-tree builds, or at least testing,
officially unsupported.  I think gcc already does so...

> 
> Simon
> 
> [1] https://github.com/simark/gdb-check
> 

Thanks,
Pedro Alves
  
Pedro Alves Aug. 3, 2015, 4:38 p.m. UTC | #4
On 08/03/2015 05:34 PM, Pedro Alves wrote:
> On 08/03/2015 04:16 PM, Simon Marchi wrote:
> 
>> > The problem is that it also affects when running other tests.
>> > For example, doing a
>> > 
>> >   $ make check RUNTESTFLAGS="argv0-symlink.exp"
>> > 
>> > and then
>> > 
>> >   $ make check RUNTESTFLAGS="whatis.exp"
>> > 
>> > gives
>> > 
>> >   http://paste.ubuntu.com/11993577/
> Urgh.  Maybe there's some other change to argv0-symlink.exp
> that could be made to avoid this?  I haven't looked at this
> in enough detail to give a good informed suggestion, but
> maybe putting the symlink elsewhere?

(I meant to add that even deleting the symlink after testing
isn't a 100% fix, as some testsuite bug can cause a perror or
even you can always ctrl-c / kill the testsuite run before
the symlink is removed.)

Thanks,
Pedro Alves
  
Simon Marchi Aug. 3, 2015, 6:10 p.m. UTC | #5
On 15-08-03 12:34 PM, Pedro Alves wrote:
> Urgh.  Maybe there's some other change to argv0-symlink.exp
> that could be made to avoid this?  I haven't looked at this
> in enough detail to give a good informed suggestion, but
> maybe putting the symlink elsewhere?

When running tests in parallel, everything gets put in
an output directory, with one directory per test, right?
Could we do this all the time?

> Personally, I'd vote for making in-tree builds, or at least testing,
> officially unsupported.  I think gcc already does so...

I agree.
  
Pedro Alves Aug. 3, 2015, 6:42 p.m. UTC | #6
On 08/03/2015 07:10 PM, Simon Marchi wrote:
> On 15-08-03 12:34 PM, Pedro Alves wrote:
>> Urgh.  Maybe there's some other change to argv0-symlink.exp
>> that could be made to avoid this?  I haven't looked at this
>> in enough detail to give a good informed suggestion, but
>> maybe putting the symlink elsewhere?
> 
> When running tests in parallel, everything gets put in
> an output directory, with one directory per test, right?
> Could we do this all the time?

Probably.

> 
>> Personally, I'd vote for making in-tree builds, or at least testing,
>> officially unsupported.  I think gcc already does so...
> 
> I agree.
> 


Thanks,
Pedro Alves
  
Sergio Durigan Junior Aug. 4, 2015, 4:11 p.m. UTC | #7
On Monday, August 03 2015, Pedro Alves wrote:

> On 08/03/2015 07:10 PM, Simon Marchi wrote:
>> On 15-08-03 12:34 PM, Pedro Alves wrote:
>>> Urgh.  Maybe there's some other change to argv0-symlink.exp
>>> that could be made to avoid this?  I haven't looked at this
>>> in enough detail to give a good informed suggestion, but
>>> maybe putting the symlink elsewhere?
>> 
>> When running tests in parallel, everything gets put in
>> an output directory, with one directory per test, right?
>> Could we do this all the time?
>
> Probably.

FWIW, I've been playing with the testsuite lately, and I also think this
can be a good idea.  I can help with this if needed.
  
Joel Brobecker Aug. 4, 2015, 5:21 p.m. UTC | #8
> Personally, I'd vote for making in-tree builds, or at least testing,
> officially unsupported.  I think gcc already does so...

We should seriously discuss this, one day, as we keep having to
spend time fixing issues specific to that mode.
  
Doug Evans Aug. 11, 2015, 5:35 p.m. UTC | #9
On Tue, Aug 4, 2015 at 10:21 AM, Joel Brobecker <brobecker@adacore.com> wrote:
>> Personally, I'd vote for making in-tree builds, or at least testing,
>> officially unsupported.  I think gcc already does so...
>
> We should seriously discuss this, one day, as we keep having to
> spend time fixing issues specific to that mode.

I don't have a strong opinion on making in-tree testing unsupported,
but I do have a strong opinion on another thing that can make the
in-tree testing issue moot.

Let's remove all of testsuite/*/Makefile.in, they're always
out of date anyway (i.e., no one updates gdb.foo/Makefile.in to
remove binaries added by new tests),
and except for "make clean" aren't really used for anything.
The "make clean" in testsuite/Makefile.in can just "rm -rf foo bar ..."
[where "foo bar ..." are *not* the gdb.* testsuite dirs, but rather
the outputs,etc. directories of check-parallel]
IOW, testing would create the needed directories on the fly,
even in serial mode,
and to simplify "make clean" they'd always be put in a fixed
subdir of testsuite (just like check-parallel does now).

As for whether to always have one directory per test
(in serial and parallel modes), that *could* be treated as a separate
issue, but if it reduces complexity by doing the same thing
for serial and parallel then great.
[And while in-tree testing could still be unsupported,
I think(!) the current issue with it would be fixed.]
  
Joel Brobecker Aug. 11, 2015, 7:58 p.m. UTC | #10
> I don't have a strong opinion on making in-tree testing unsupported,
> but I do have a strong opinion on another thing that can make the
> in-tree testing issue moot.
> 
> Let's remove all of testsuite/*/Makefile.in, they're always
> out of date anyway (i.e., no one updates gdb.foo/Makefile.in to
> remove binaries added by new tests),
> and except for "make clean" aren't really used for anything.
> The "make clean" in testsuite/Makefile.in can just "rm -rf foo bar ..."
> [where "foo bar ..." are *not* the gdb.* testsuite dirs, but rather
> the outputs,etc. directories of check-parallel]
> IOW, testing would create the needed directories on the fly,
> even in serial mode,
> and to simplify "make clean" they'd always be put in a fixed
> subdir of testsuite (just like check-parallel does now).

I think some of these issues are worth improving independently
of whether the build was in-tree or not.

> As for whether to always have one directory per test
> (in serial and parallel modes), that *could* be treated as a separate
> issue, but if it reduces complexity by doing the same thing
> for serial and parallel then great.
> [And while in-tree testing could still be unsupported,
> I think(!) the current issue with it would be fixed.]

If in-tree build happens to work without effort from us, then
OK to continue having it. But I don't think treating as bugs
issues that are specific to in-tree building & testing would
be the best investment of our resources.

I tried to remember why people thought in-tree building is more
convenient for them, and couldn't remember of any reason other
than convenience. But is it really more convenient? Are there
other reasons I forgot about?
  
Doug Evans Aug. 11, 2015, 8:43 p.m. UTC | #11
On Tue, Aug 11, 2015 at 12:58 PM, Joel Brobecker <brobecker@adacore.com> wrote:
>> I don't have a strong opinion on making in-tree testing unsupported,
>> but I do have a strong opinion on another thing that can make the
>> in-tree testing issue moot.
>>
>> Let's remove all of testsuite/*/Makefile.in, they're always
>> out of date anyway (i.e., no one updates gdb.foo/Makefile.in to
>> remove binaries added by new tests),
>> and except for "make clean" aren't really used for anything.
>> The "make clean" in testsuite/Makefile.in can just "rm -rf foo bar ..."
>> [where "foo bar ..." are *not* the gdb.* testsuite dirs, but rather
>> the outputs,etc. directories of check-parallel]
>> IOW, testing would create the needed directories on the fly,
>> even in serial mode,
>> and to simplify "make clean" they'd always be put in a fixed
>> subdir of testsuite (just like check-parallel does now).
>
> I think some of these issues are worth improving independently
> of whether the build was in-tree or not.
>
>> As for whether to always have one directory per test
>> (in serial and parallel modes), that *could* be treated as a separate
>> issue, but if it reduces complexity by doing the same thing
>> for serial and parallel then great.
>> [And while in-tree testing could still be unsupported,
>> I think(!) the current issue with it would be fixed.]
>
> If in-tree build happens to work without effort from us, then
> OK to continue having it. But I don't think treating as bugs
> issues that are specific to in-tree building & testing would
> be the best investment of our resources.
>
> I tried to remember why people thought in-tree building is more
> convenient for them, and couldn't remember of any reason other
> than convenience. But is it really more convenient? Are there
> other reasons I forgot about?

FAOD, I'm *not* advocating for keeping in-tree builds working.
I never do them myself so I really have no direct interest in whether
it works or not. But, if something I want to do anyway happens
to improve life for someone else, then I'm ok with that.
  
Joel Brobecker Aug. 11, 2015, 11:02 p.m. UTC | #12
> FAOD, I'm *not* advocating for keeping in-tree builds working.
> I never do them myself so I really have no direct interest in whether
> it works or not. But, if something I want to do anyway happens
> to improve life for someone else, then I'm ok with that.

Same here.
  
Pedro Alves Aug. 12, 2015, 9:30 a.m. UTC | #13
On 08/11/2015 06:35 PM, Doug Evans wrote:
> On Tue, Aug 4, 2015 at 10:21 AM, Joel Brobecker <brobecker@adacore.com> wrote:
>>> Personally, I'd vote for making in-tree builds, or at least testing,
>>> officially unsupported.  I think gcc already does so...
>>
>> We should seriously discuss this, one day, as we keep having to
>> spend time fixing issues specific to that mode.
> 
> I don't have a strong opinion on making in-tree testing unsupported,
> but I do have a strong opinion on another thing that can make the
> in-tree testing issue moot.
> 
> Let's remove all of testsuite/*/Makefile.in, they're always
> out of date anyway (i.e., no one updates gdb.foo/Makefile.in to
> remove binaries added by new tests),
> and except for "make clean" aren't really used for anything.
> The "make clean" in testsuite/Makefile.in can just "rm -rf foo bar ..."
> [where "foo bar ..." are *not* the gdb.* testsuite dirs, but rather
> the outputs,etc. directories of check-parallel]
> IOW, testing would create the needed directories on the fly,
> even in serial mode,
> and to simplify "make clean" they'd always be put in a fixed
> subdir of testsuite (just like check-parallel does now).

*nod*

I believe Yao had patches a while ago that went in this direction.
Don't know what happened to them.  [+Yao].

> 
> As for whether to always have one directory per test
> (in serial and parallel modes), that *could* be treated as a separate
> issue, but if it reduces complexity by doing the same thing
> for serial and parallel then great.

I believe this would be worthwhile.

Taking this a step further, if we always ran in parallel mode (the
equivalent of make check -j1 FORCE_PARALLEL=1), then variable bleeding
between tests would no longer be an issue, as then we'd invoke a
dejagnu/runtest per test.  That would mean making GNU Make a
requirement for testing (which IMO, should be OK).

> [And while in-tree testing could still be unsupported,
> I think(!) the current issue with it would be fixed.]

Thanks,
Pedro Alves
  
Sergio Durigan Junior Aug. 12, 2015, 4:40 p.m. UTC | #14
On Wednesday, August 12 2015, Pedro Alves wrote:

>> As for whether to always have one directory per test
>> (in serial and parallel modes), that *could* be treated as a separate
>> issue, but if it reduces complexity by doing the same thing
>> for serial and parallel then great.
>
> I believe this would be worthwhile.
>
> Taking this a step further, if we always ran in parallel mode (the
> equivalent of make check -j1 FORCE_PARALLEL=1), then variable bleeding
> between tests would no longer be an issue, as then we'd invoke a
> dejagnu/runtest per test.  That would mean making GNU Make a
> requirement for testing (which IMO, should be OK).

FWIW, this would be awesome.  I am not sure about forcing the dependency
on GNU Make for the testing (this would be OK by me, but maybe someone
has a case against), but defaulting to FORCE_PARALLEL=1 would be a step
forward, indeed.  While hacking our testsuite to implement a way to
verify the racy tests we have, I could see how the fact that each test
has its own directory makes a difference.

Thanks,
  
Joel Brobecker Aug. 12, 2015, 5:22 p.m. UTC | #15
> FWIW, this would be awesome.  I am not sure about forcing the dependency
> on GNU Make for the testing (this would be OK by me, but maybe someone
> has a case against), but defaulting to FORCE_PARALLEL=1 would be a step
> forward, indeed.  While hacking our testsuite to implement a way to
> verify the racy tests we have, I could see how the fact that each test
> has its own directory makes a difference.

The only argument against GNU/Make that I remember is that on the *BSDs,
GNU/Make is not the default. But the benefits we are getting from using
GNU/Make continues to increase, so I think we're reaching a point where
it seems to make better sense to me to require it. Doesn't GCC already
do anyways?
  
Doug Evans Aug. 12, 2015, 5:37 p.m. UTC | #16
On Wed, Aug 12, 2015 at 10:22 AM, Joel Brobecker <brobecker@adacore.com> wrote:
>> FWIW, this would be awesome.  I am not sure about forcing the dependency
>> on GNU Make for the testing (this would be OK by me, but maybe someone
>> has a case against), but defaulting to FORCE_PARALLEL=1 would be a step
>> forward, indeed.  While hacking our testsuite to implement a way to
>> verify the racy tests we have, I could see how the fact that each test
>> has its own directory makes a difference.
>
> The only argument against GNU/Make that I remember is that on the *BSDs,
> GNU/Make is not the default. But the benefits we are getting from using
> GNU/Make continues to increase, so I think we're reaching a point where
> it seems to make better sense to me to require it. Doesn't GCC already
> do anyways?

I suspect, though I haven't tried, if we remove the check-parallel/check-single
test, it would be straightforward to remove the GNU make requirement
and just move the details to a wrapper script.

Always invoking runtest by a wrapper script has other benefits.

I'm not advocating for this, I only ever use GNU make.
But if the topic comes up, it's not clear to me GNU make
is an absolute requirement.
  
Joel Brobecker Aug. 12, 2015, 6:43 p.m. UTC | #17
> I suspect, though I haven't tried, if we remove the
> check-parallel/check-single test, it would be straightforward to
> remove the GNU make requirement and just move the details to a wrapper
> script.

Dependency tracking also requires GNU/Make; would you be able to
take care of that through the wrapper?

> Always invoking runtest by a wrapper script has other benefits.
> 
> I'm not advocating for this, I only ever use GNU make.
> But if the topic comes up, it's not clear to me GNU make
> is an absolute requirement.

It would be nice to list the additional benefits and decide whether
we want to go that route or not, ideally more-or-less independently
of whether we want to require GNU/Make or not.

The reason why I am advocating in favor of requiring GNU/Make is that
we are regularly hindered or doing extra work trying to support non-
GNU/Make, while on the other hand, the community affected by this
proposal only need to update their build procedures to put GNU/Make
on their PATH. And since GCC already requires GNU/Make, I cannot
understand why it would be difficult to do so.
  
Doug Evans Aug. 12, 2015, 6:49 p.m. UTC | #18
On Wed, Aug 12, 2015 at 11:43 AM, Joel Brobecker <brobecker@adacore.com> wrote:
>> I suspect, though I haven't tried, if we remove the
>> check-parallel/check-single test, it would be straightforward to
>> remove the GNU make requirement and just move the details to a wrapper
>> script.
>
> Dependency tracking also requires GNU/Make; would you be able to
> take care of that through the wrapper?

Maybe I missed something but I didn't see any real dependency
tracking as far as the invocation of runtest goes.
Clearly the current implementation uses dependencies
to implement check-parallel, but I wouldn't call those
dependencies per-se.

>> Always invoking runtest by a wrapper script has other benefits.
>>
>> I'm not advocating for this, I only ever use GNU make.
>> But if the topic comes up, it's not clear to me GNU make
>> is an absolute requirement.
>
> It would be nice to list the additional benefits and decide whether
> we want to go that route or not, ideally more-or-less independently
> of whether we want to require GNU/Make or not.
>
> The reason why I am advocating in favor of requiring GNU/Make is that
> we are regularly hindered or doing extra work trying to support non-
> GNU/Make, while on the other hand, the community affected by this
> proposal only need to update their build procedures to put GNU/Make
> on their PATH. And since GCC already requires GNU/Make, I cannot
> understand why it would be difficult to do so.

How often does it come up in the context of "make check"
(beyond the check-parallel implementation).
Other reasons for wanting to require GNU/Make are outside the scope
of my email. :-)
  
Joel Brobecker Aug. 12, 2015, 7:41 p.m. UTC | #19
> How often does it come up in the context of "make check"
> (beyond the check-parallel implementation).
> Other reasons for wanting to require GNU/Make are outside the scope
> of my email. :-)

That's true. But I think it's important to look at the complete picture
while we're trying to decide the benefits vs downsides of switching over
to GNU/Make. "make check" is one aspect that might benefit, but there
are others, and it gives more weight, IMO, to the suggestion of making
GNU/Make a requirement.
  
Doug Evans Aug. 12, 2015, 8:22 p.m. UTC | #20
On Wed, Aug 12, 2015 at 12:41 PM, Joel Brobecker <brobecker@adacore.com> wrote:
>> How often does it come up in the context of "make check"
>> (beyond the check-parallel implementation).
>> Other reasons for wanting to require GNU/Make are outside the scope
>> of my email. :-)
>
> That's true. But I think it's important to look at the complete picture
> while we're trying to decide the benefits vs downsides of switching over
> to GNU/Make. "make check" is one aspect that might benefit, but there
> are others, and it gives more weight, IMO, to the suggestion of making
> GNU/Make a requirement.

I think you'll find we're in agreement.
[who wouldn't be?]
  

Patch

diff --git a/gdb/testsuite/gdb.base/argv0-symlink.exp b/gdb/testsuite/gdb.base/argv0-symlink.exp
index f030656..053f8c5 100644
--- a/gdb/testsuite/gdb.base/argv0-symlink.exp
+++ b/gdb/testsuite/gdb.base/argv0-symlink.exp
@@ -13,80 +13,102 @@ 
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
+
+# Delete files specified in ARGS.  The paths are relative to the standard
+# test output directory.
+
+proc cleanup {args} {
+    foreach file $args {
+        remote_exec host "rm -f [standard_output_file $file]"
+    }
+}
+
+
+# Create a symbolic link from LINK_NAME to TARGET.  Return 1 on success,
+# 0 otherwise.
+
+proc create_link {target link_name} {
+    set status [remote_exec host "ln -sf ${target} ${link_name}"]
+    if { [lindex $status 0] != 0 } {
+        return 0
+    }
+
+    return 1
+}
+
 standard_testfile
 
-set has_argv0 [gdb_has_argv0]
+if { ![gdb_has_argv0] } {
+    unsupported "target does not provide argv\[0\]"
+    return 0
+}
+
+set filelink "${testfile}-filelink"
+set dirlink "${testfile}-dirlink"
+
+# For a link named /PATH/TO/DIR/LINK, we want to check the output
+# against "/DIR/LINK", but computed in a way that doesn't make
+# assumptions about the test directory layout.
+set full_filelink [standard_output_file $filelink]
+set lastdir [file tail [file dirname $full_filelink]]
 
 if { [build_executable ${testfile}.exp ${testfile} ${srcfile}] == -1 } {
     return -1
 }
 
+# Remove any existing link.
+cleanup "$filelink" "$dirlink"
+
+# Test with symlink to files.
 set test "kept file symbolic link name"
-set filelink "${testfile}-filelink"
 
-remote_file host delete [standard_output_file $filelink]
-set status [remote_exec host "ln -sf ${testfile} [standard_output_file $filelink]"]
-if {[lindex $status 0] != 0} {
+if { ![create_link "${testfile}" "[standard_output_file $filelink]"] } {
     unsupported "$test (host does not support symbolic links)"
+    cleanup "$filelink" "$dirlink"
     return 0
 }
 
 clean_restart "$filelink"
 
-if ![runto_main] {
+if { ![runto_main] } {
     untested "could not run to main"
+    cleanup "$filelink" "$dirlink"
     return -1
 }
 
 gdb_test_no_output "set print repeats 10000"
 gdb_test_no_output "set print elements 10000"
 
-if { $has_argv0 } {
-    gdb_test {print argv[0]} "/$filelink\"" $test
-} else {
-    unsupported $test
-}
-
-# For a link named /PATH/TO/DIR/LINK, we want to check the output
-# against "/DIR/LINK", but computed in a way that doesn't make
-# assumptions about the test directory layout.
-set full_filelink [standard_output_file $filelink]
-set lastdir [file tail [file dirname $full_filelink]]
+gdb_test {print argv[0]} "/$filelink\"" $test
 
 gdb_test "info inferiors" "/$lastdir/$filelink *" "$test for info inferiors"
 
-
+# Test with symlink to dir.
 set test "kept directory symbolic link name"
-set dirlink "${testfile}-dirlink"
 
-# 'ln -sf' does not overwrite symbol link to a directory.
-# 'remote_file host delete' uses stat (not lstat), therefore it refuses to
-# delete a directory.
-remote_exec host "rm -f [standard_output_file $dirlink]"
-set status [remote_exec host "ln -sf . [standard_output_file $dirlink]"]
-if {[lindex $status 0] != 0} {
+if { ![create_link "." "[standard_output_file $dirlink]"] } {
     unsupported "$test (host does not support symbolic links)"
+    cleanup "$filelink" "$dirlink"
     return 0
 }
 
 clean_restart "$dirlink/$filelink"
 
-if ![runto_main] {
+if { ![runto_main] } {
     untested "could not run to main"
+    cleanup "$filelink" "$dirlink"
     return -1
 }
 
 gdb_test_no_output "set print repeats 10000"
 gdb_test_no_output "set print elements 10000"
 
-if { $has_argv0 } {
-    # gdbserver does not have this issue.
-    if ![is_remote target] {
-	setup_kfail "*-*-*" gdb/15934
-    }
-    gdb_test {print argv[0]} "/$dirlink/$filelink\"" $test
-} else {
-    unsupported $test
+# gdbserver does not have this issue.
+if { ![is_remote target] } {
+    setup_kfail "*-*-*" gdb/15934
 }
+gdb_test {print argv[0]} "/$dirlink/$filelink\"" $test
 
 gdb_test "info inferiors" "/$lastdir/$filelink *" "$test for info inferiors"
+
+cleanup "$filelink" "$dirlink"