Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable more fs tests on Windows #31360

Merged
merged 4 commits into from
Feb 4, 2016
Merged

Enable more fs tests on Windows #31360

merged 4 commits into from
Feb 4, 2016

Conversation

pitdicker
Copy link
Contributor

  • use symlink_file and symlink_dir instead of the old soft_link

  • create a junction instead of a directory symlink for testing recursive_rmdir (as it causes the
    same troubles, but can be created by users without SeCreateSymbolicLinkPrivilege)

  • remove_dir_all was unable to remove directory symlinks and junctions

  • only run tests that create symlinks if we have the right permissions.

  • rename Path2 to Path

  • remove the global #[allow(deprecated)] and outdated comments

  • After factoring out create_junction() from the test directory_junctions_are_directories and
    removing needlessly complex code, what I was left with was:

    #[test]
    #[cfg(windows)]
    fn directory_junctions_are_directories() {
        use sys::fs::create_junction;
    
        let tmpdir = tmpdir();
    
        let foo = tmpdir.join("foo");
        let bar = tmpdir.join("bar");
    
        fs::create_dir(&foo).unwrap();
        check!(create_junction(&foo, &bar));
        assert!(bar.metadata().unwrap().is_dir());
    }
    

    It test whether a junction is a directory instead of a reparse point. But it actually test the
    target of the junction (which is a directory if it exists) instead of the junction itself, which
    should always be a symlink. So this test is invalid, and I expect it only exists because the
    author was suprised by it. So I removed it.

Some things that do not yet work right:

  • relative symlinks do not accept forward slashes
  • the conversion of paths for create_junction is hacky
  • remove_dir_all now messes with the internal data of FileAttr to be able to remove symlinks.
    We should add some method like is_symlink_dir() to it, so code outside the standard library
    can see the difference between file and directory symlinks too.

@rust-highfive
Copy link
Collaborator

r? @alexcrichton

(rust_highfive has picked a reviewer for you, use r? to override)

// `SeCreateSymbolicLinkPrivilege`). Instead of disabling these test on Windows, use this
// function to test whether we have permission, and return otherwise. This way, we still don't
// run these tests most of the time, but at least we do if the user has the right permissions.
pub fn got_symlink_permission(tmpdir: &TempDir) -> bool {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this function always return true on unix? I'm somewhat wary about us auto-ignoring tests as it may be easy for the tests to accidentally be ignored in the future.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No problem, that was my first try.

@pitdicker
Copy link
Contributor Author

Updated. Thanks for the good review!

@pitdicker
Copy link
Contributor Author

I have added the test create_dir_all_with_junctions() for #26716.

Also this uncovered a bug with create_dir_all: it fails if the path contains a dangling symlink.
But I would like to leave that for an other PR.

}
}
#[cfg(not(windows))]
#[allow(unused_variables)]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of conditional compilation here (e.g. defining the same signature twice and having an #[allow] this could also do something like

if cfg!(unix) {
    return true
}

That should be more resilient to cross-compilation concerns in the future at least

@alexcrichton
Copy link
Member

Thanks @pitdicker! Looks good to me modulo a few last nits but otherwise r=me

@pitdicker
Copy link
Contributor Author

Updated.

I should really learn to use the right line length...

@alexcrichton
Copy link
Member

@bors: r+ 0bd55e5

@bors
Copy link
Contributor

bors commented Feb 4, 2016

⌛ Testing commit 0bd55e5 with merge f2b7960...

@bors
Copy link
Contributor

bors commented Feb 4, 2016

💔 Test failed - auto-win-msvc-64-opt

@pitdicker
Copy link
Contributor Author

Oops. It fails because symlink_junction() is only used in test, but not exposed in the standard library.
I would like to make it available some time like the Symlink_*() functions, but not in this state. I will put it in a test module for now.

@pitdicker
Copy link
Contributor Author

It should be ok now

@alexcrichton
Copy link
Member

@bors: r+ fb172b6

bors added a commit that referenced this pull request Feb 4, 2016
- use `symlink_file` and `symlink_dir` instead of the old `soft_link`
- create a junction instead of a directory symlink for testing recursive_rmdir (as it causes the
  same troubles, but can be created by users without `SeCreateSymbolicLinkPrivilege`)
- `remove_dir_all` was unable to remove directory symlinks and junctions
- only run tests that create symlinks if we have the right permissions.
- rename `Path2` to `Path`
- remove the global `#[allow(deprecated)]` and outdated comments
- After factoring out `create_junction()` from the test `directory_junctions_are_directories` and
  removing needlessly complex code, what I was left with was:
  ```
  #[test]
  #[cfg(windows)]
  fn directory_junctions_are_directories() {
      use sys::fs::create_junction;

      let tmpdir = tmpdir();

      let foo = tmpdir.join("foo");
      let bar = tmpdir.join("bar");

      fs::create_dir(&foo).unwrap();
      check!(create_junction(&foo, &bar));
      assert!(bar.metadata().unwrap().is_dir());
  }
  ```
  It test whether a junction is a directory instead of a reparse point. But it actually test the
  target of the junction (which is a directory if it exists) instead of the junction itself, which
  should always be a symlink. So this test is invalid, and I expect it only exists because the
  author was suprised by it. So I removed it.

Some things that do not yet work right:
- relative symlinks do not accept forward slashes
- the conversion of paths for `create_junction` is hacky
- `remove_dir_all` now messes with the internal data of `FileAttr` to be able to remove symlinks.
  We should add some method like `is_symlink_dir()` to it, so code outside the standard library
  can see the difference between file and directory symlinks too.
@bors
Copy link
Contributor

bors commented Feb 4, 2016

⌛ Testing commit fb172b6 with merge d0ef740...

@bors bors merged commit fb172b6 into rust-lang:master Feb 4, 2016
@alexcrichton
Copy link
Member

@pitdicker oh one thing I just remembered, if you're gonna be working some more in this area could you add a regression test for remove_dir_all with junctions on Windows?

@pitdicker
Copy link
Contributor Author

I found the probleem because all tests that create directory symlinks or junctions failed when cleaning up... But having an explicit test can make it clearer I suppose. I will add one when a next pr is ready.

@alexcrichton
Copy link
Member

ah right good point, thanks!

Centril added a commit to Centril/rust that referenced this pull request Jul 29, 2019
…t, r=sfackler

std: Fix a failing `fs` test on Windows

In testing 4-core machines on Azure the `realpath_works_tricky` test in
the standard library is failing with "The directory name is invalid". In
attempting to debug this test I was able to reproduce the failure
locally on my machine, and after inspecing the test it I believe is
exploiting Unix-specific behavior that seems to only sometimes work on
Windows. Specifically the test basically executes:

    mkdir -p a/b
    mkdir -p a/d
    touch a/f
    ln -s a/b/c ../d/e
    ln -s a/d/e ../f

and then asserts that `canonicalize("a/b/c")` and
`canonicalize("a/d/e")` are equivalent to `a/f`. On Windows however the
first symlink is a "directory symlink" and the second is a file symlink.
In both cases, though, they're pointing to files. This means that for
whatever reason locally and on the 4-core environment the call to
`canonicalize` is failing. On Azure today it seems to be passing, and
I'm not entirely sure why. I'm sort of presuming that there's some sort
of internals going on here where there's some global Windows setting
which makes symlinks behavior more unix-like and ignore the directory
hint.

In any case this should keep the test working and also fixes the test
locally for me. It's also worth pointing out that this test was made Windows compatible in rust-lang#31360, a pretty ancient PR at this point.
Centril added a commit to Centril/rust that referenced this pull request Jul 29, 2019
…t, r=sfackler

std: Fix a failing `fs` test on Windows

In testing 4-core machines on Azure the `realpath_works_tricky` test in
the standard library is failing with "The directory name is invalid". In
attempting to debug this test I was able to reproduce the failure
locally on my machine, and after inspecing the test it I believe is
exploiting Unix-specific behavior that seems to only sometimes work on
Windows. Specifically the test basically executes:

    mkdir -p a/b
    mkdir -p a/d
    touch a/f
    ln -s a/b/c ../d/e
    ln -s a/d/e ../f

and then asserts that `canonicalize("a/b/c")` and
`canonicalize("a/d/e")` are equivalent to `a/f`. On Windows however the
first symlink is a "directory symlink" and the second is a file symlink.
In both cases, though, they're pointing to files. This means that for
whatever reason locally and on the 4-core environment the call to
`canonicalize` is failing. On Azure today it seems to be passing, and
I'm not entirely sure why. I'm sort of presuming that there's some sort
of internals going on here where there's some global Windows setting
which makes symlinks behavior more unix-like and ignore the directory
hint.

In any case this should keep the test working and also fixes the test
locally for me. It's also worth pointing out that this test was made Windows compatible in rust-lang#31360, a pretty ancient PR at this point.
Centril added a commit to Centril/rust that referenced this pull request Jul 30, 2019
…t, r=sfackler

std: Fix a failing `fs` test on Windows

In testing 4-core machines on Azure the `realpath_works_tricky` test in
the standard library is failing with "The directory name is invalid". In
attempting to debug this test I was able to reproduce the failure
locally on my machine, and after inspecing the test it I believe is
exploiting Unix-specific behavior that seems to only sometimes work on
Windows. Specifically the test basically executes:

    mkdir -p a/b
    mkdir -p a/d
    touch a/f
    ln -s a/b/c ../d/e
    ln -s a/d/e ../f

and then asserts that `canonicalize("a/b/c")` and
`canonicalize("a/d/e")` are equivalent to `a/f`. On Windows however the
first symlink is a "directory symlink" and the second is a file symlink.
In both cases, though, they're pointing to files. This means that for
whatever reason locally and on the 4-core environment the call to
`canonicalize` is failing. On Azure today it seems to be passing, and
I'm not entirely sure why. I'm sort of presuming that there's some sort
of internals going on here where there's some global Windows setting
which makes symlinks behavior more unix-like and ignore the directory
hint.

In any case this should keep the test working and also fixes the test
locally for me. It's also worth pointing out that this test was made Windows compatible in rust-lang#31360, a pretty ancient PR at this point.
Centril added a commit to Centril/rust that referenced this pull request Jul 30, 2019
…t, r=sfackler

std: Fix a failing `fs` test on Windows

In testing 4-core machines on Azure the `realpath_works_tricky` test in
the standard library is failing with "The directory name is invalid". In
attempting to debug this test I was able to reproduce the failure
locally on my machine, and after inspecing the test it I believe is
exploiting Unix-specific behavior that seems to only sometimes work on
Windows. Specifically the test basically executes:

    mkdir -p a/b
    mkdir -p a/d
    touch a/f
    ln -s a/b/c ../d/e
    ln -s a/d/e ../f

and then asserts that `canonicalize("a/b/c")` and
`canonicalize("a/d/e")` are equivalent to `a/f`. On Windows however the
first symlink is a "directory symlink" and the second is a file symlink.
In both cases, though, they're pointing to files. This means that for
whatever reason locally and on the 4-core environment the call to
`canonicalize` is failing. On Azure today it seems to be passing, and
I'm not entirely sure why. I'm sort of presuming that there's some sort
of internals going on here where there's some global Windows setting
which makes symlinks behavior more unix-like and ignore the directory
hint.

In any case this should keep the test working and also fixes the test
locally for me. It's also worth pointing out that this test was made Windows compatible in rust-lang#31360, a pretty ancient PR at this point.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants