Skip to content

Commit 8397571

Browse files
committed
Add real permission tests for Windows
1 parent 8622810 commit 8397571

File tree

1 file changed

+65
-27
lines changed

1 file changed

+65
-27
lines changed

src/test/groovy/PathExtensionsTest.groovy

Lines changed: 65 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -6,29 +6,54 @@ import spock.lang.Unroll
66

77
import java.nio.file.Files
88
import java.nio.file.Path
9+
import java.nio.file.attribute.*
910

1011
@Unroll
1112
class PathExtensionsTest extends Specification {
1213
@Shared
13-
private Path tmpdir = Path.of(System.getProperty("java.io.tmpdir"))
14-
@Shared
15-
private Path unwritableFile = tmpdir.resolve("coder-gateway-test/path-extensions/unwritable/file")
16-
@Shared
17-
private Path writableFile = tmpdir.resolve("coder-gateway-test/path-extensions/writable-file")
14+
private Path tmpdir = Path.of(System.getProperty("java.io.tmpdir")).resolve("coder-gateway-test/path-extensions/")
15+
16+
private void setPermissions(Path file) {
17+
AclFileAttributeView view = Files.getFileAttributeView(file, AclFileAttributeView.class)
18+
UserPrincipal user = view.getOwner()
19+
AclEntry entry = AclEntry.newBuilder()
20+
.setType(AclEntryType.DENY)
21+
.setPrincipal(user)
22+
.setPermissions(AclEntryPermission.WRITE_DATA)
23+
.build();
24+
List<AclEntry> acl = view.getAcl()
25+
acl.set(0, entry)
26+
view.setAcl(acl)
27+
}
1828

1929
void setupSpec() {
20-
// TODO: On Windows setWritable() only sets read-only; how do we set
21-
// actual permissions? Initially I tried an existing dir like WINDIR
22-
// which worked locally but in CI that is writable for some reason.
23-
if (unwritableFile.parent.toFile().exists()) {
24-
unwritableFile.parent.toFile().setWritable(true)
25-
unwritableFile.parent.toFile().deleteDir()
30+
// Clean up from the last run, if any.
31+
tmpdir.toFile().deleteDir()
32+
33+
// Push out the test files.
34+
for (String dir in ["read-only-dir", "no-permissions-dir"]) {
35+
Files.createDirectories(tmpdir.resolve(dir))
36+
tmpdir.resolve(dir).resolve("file").toFile().write("")
37+
}
38+
for (String file in ["read-only-file", "writable-file", "no-permissions-file"]) {
39+
tmpdir.resolve(file).toFile().write("")
40+
}
41+
42+
// On Windows `File.setWritable()` only sets read-only, not permissions
43+
// so on other platforms "read-only" is the same as "no permissions".
44+
tmpdir.resolve("read-only-file").toFile().setWritable(false)
45+
tmpdir.resolve("read-only-dir").toFile().setWritable(false)
46+
47+
// Create files without actual write permissions on Windows (not just
48+
// read-only). On other platforms this is the same as above.
49+
tmpdir.resolve("no-permissions-dir/file").toFile().write("")
50+
if (System.getProperty("os.name").toLowerCase().contains("windows")) {
51+
setPermissions(tmpdir.resolve("no-permissions-file"))
52+
setPermissions(tmpdir.resolve("no-permissions-dir"))
53+
} else {
54+
tmpdir.resolve("no-permissions-file").toFile().setWritable(false)
55+
tmpdir.resolve("no-permissions-dir").toFile().setWritable(false)
2656
}
27-
Files.createDirectories(unwritableFile.parent)
28-
unwritableFile.toFile().write("text")
29-
writableFile.toFile().write("text")
30-
unwritableFile.toFile().setWritable(false)
31-
unwritableFile.parent.toFile().setWritable(false)
3257
}
3358

3459
def "canCreateDirectory"() {
@@ -39,20 +64,33 @@ class PathExtensionsTest extends Specification {
3964

4065
where:
4166
path | expected
42-
unwritableFile | false
43-
unwritableFile.resolve("probably/nonexistent") | false
44-
// TODO: Java reports read-only directories on Windows as writable.
45-
unwritableFile.parent.resolve("probably/nonexistent") | System.getProperty("os.name").toLowerCase().contains("windows")
46-
writableFile | false
47-
writableFile.parent | true
48-
writableFile.resolve("nested/under/file") | false
49-
writableFile.parent.resolve("nested/under/dir") | true
50-
Path.of("relative to project") | true
51-
tmpdir.resolve("./foo/bar/../../coder-gateway-test/path-extensions") | true
67+
// A file is not valid for directory creation regardless of writability.
68+
tmpdir.resolve("read-only-file") | false
69+
tmpdir.resolve("read-only-file/nested/under/file") | false
70+
tmpdir.resolve("writable-file") | false
71+
tmpdir.resolve("writable-file/nested/under/file") | false
72+
tmpdir.resolve("read-only-dir/file") | false
73+
tmpdir.resolve("no-permissions-dir/file") | false
74+
75+
// Window: can create under read-only directories.
76+
tmpdir.resolve("read-only-dir") | System.getProperty("os.name").toLowerCase().contains("windows")
77+
tmpdir.resolve("read-only-dir/nested/under/dir") | System.getProperty("os.name").toLowerCase().contains("windows")
78+
79+
// Cannot create under a directory without permissions.
80+
tmpdir.resolve("no-permissions-dir") | false
81+
tmpdir.resolve("no-permissions-dir/nested/under/dir") | false
82+
83+
// Can create under a writable directory.
5284
tmpdir | true
53-
tmpdir.resolve("some/nested/non-existent/path") | true
85+
tmpdir.resolve("./foo/bar/../../coder-gateway-test/path-extensions") | true
86+
tmpdir.resolve("nested/under/dir") | true
5487
tmpdir.resolve("with space") | true
88+
89+
// Config/data directories should be fine.
5590
CoderCLIManager.getConfigDir() | true
5691
CoderCLIManager.getDataDir() | true
92+
93+
// Relative paths can work as well.
94+
Path.of("relative/to/project") | true
5795
}
5896
}

0 commit comments

Comments
 (0)