Damien Martin-Guillerez | f88f4d8 | 2015-09-25 13:56:55 +0000 | [diff] [blame] | 1 | // Copyright 2014 The Bazel Authors. All rights reserved. |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 2 | // |
| 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // you may not use this file except in compliance with the License. |
| 5 | // You may obtain a copy of the License at |
| 6 | // |
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | // |
| 9 | // Unless required by applicable law or agreed to in writing, software |
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | // See the License for the specific language governing permissions and |
| 13 | // limitations under the License. |
| 14 | package com.google.devtools.build.lib.unix; |
| 15 | |
Ulf Adams | 795895a | 2015-03-06 15:58:35 +0000 | [diff] [blame] | 16 | import static com.google.common.truth.Truth.assertThat; |
ajmichael | ad32f62 | 2018-02-09 10:19:29 -0800 | [diff] [blame] | 17 | import static java.nio.charset.StandardCharsets.UTF_8; |
michajlo | 660d17f | 2020-03-27 09:01:57 -0700 | [diff] [blame] | 18 | import static org.junit.Assert.assertThrows; |
Philipp Wollermann | 1d50375 | 2015-06-30 16:36:01 +0000 | [diff] [blame] | 19 | import static org.junit.Assert.fail; |
ajmichael | ad32f62 | 2018-02-09 10:19:29 -0800 | [diff] [blame] | 20 | import static org.junit.Assume.assumeTrue; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 21 | |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 22 | import com.google.devtools.build.lib.testutil.TestUtils; |
ajmichael | ad32f62 | 2018-02-09 10:19:29 -0800 | [diff] [blame] | 23 | import com.google.devtools.build.lib.util.OS; |
ccalvarin | 8794308 | 2018-08-20 06:56:54 -0700 | [diff] [blame] | 24 | import com.google.devtools.build.lib.vfs.DigestHashFunction; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 25 | import com.google.devtools.build.lib.vfs.FileSystem; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 26 | import com.google.devtools.build.lib.vfs.Path; |
Philipp Wollermann | e219a24 | 2016-08-18 14:39:37 +0000 | [diff] [blame] | 27 | import java.io.File; |
| 28 | import java.io.FileNotFoundException; |
| 29 | import java.io.IOException; |
ajmichael | ad32f62 | 2018-02-09 10:19:29 -0800 | [diff] [blame] | 30 | import java.nio.file.Files; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 31 | import org.junit.Before; |
| 32 | import org.junit.Test; |
| 33 | import org.junit.runner.RunWith; |
| 34 | import org.junit.runners.JUnit4; |
| 35 | |
Benjamin Peterson | be9fbec | 2019-03-27 05:25:18 -0700 | [diff] [blame] | 36 | /** Tests for the {@link NativePosixFiles} class. */ |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 37 | @RunWith(JUnit4.class) |
Lukacs Berki | 7ecb2ce | 2016-01-26 15:40:42 +0000 | [diff] [blame] | 38 | public class NativePosixFilesTest { |
Ed Schouten | 05650ff | 2020-09-17 10:01:25 -0700 | [diff] [blame] | 39 | |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 40 | private Path workingDir; |
| 41 | private Path testFile; |
| 42 | |
| 43 | @Before |
Florian Weikert | c4975fa | 2015-12-03 10:27:10 +0000 | [diff] [blame] | 44 | public final void createFileSystem() throws Exception { |
Ed Schouten | 05650ff | 2020-09-17 10:01:25 -0700 | [diff] [blame] | 45 | FileSystem testFS = new UnixFileSystem(DigestHashFunction.SHA256, /*hashAttributeName=*/ ""); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 46 | workingDir = testFS.getPath(new File(TestUtils.tmpDir()).getCanonicalPath()); |
| 47 | testFile = workingDir.getRelative("test"); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 48 | } |
| 49 | |
Philipp Wollermann | 1d50375 | 2015-06-30 16:36:01 +0000 | [diff] [blame] | 50 | @Test |
| 51 | public void throwsFileNotFoundException() throws Exception { |
jcater | 6cfebc9 | 2019-05-01 12:40:08 -0700 | [diff] [blame] | 52 | FileNotFoundException e = |
| 53 | assertThrows( |
Googler | 541f056 | 2019-10-10 13:41:38 -0700 | [diff] [blame] | 54 | FileNotFoundException.class, () -> NativePosixFiles.stat(testFile.getPathString())); |
jcater | 6cfebc9 | 2019-05-01 12:40:08 -0700 | [diff] [blame] | 55 | assertThat(e).hasMessageThat().isEqualTo(testFile + " (No such file or directory)"); |
Philipp Wollermann | 1d50375 | 2015-06-30 16:36:01 +0000 | [diff] [blame] | 56 | } |
| 57 | |
| 58 | @Test |
| 59 | public void throwsFilePermissionException() throws Exception { |
| 60 | File foo = new File("/bin"); |
| 61 | try { |
jmmv | 8d24345c | 2019-04-09 09:41:21 -0700 | [diff] [blame] | 62 | NativePosixFiles.chmod( |
| 63 | foo.getPath(), |
| 64 | NativePosixFiles.lstat(foo.getPath()).getPermissions() | FileStatus.S_IWUSR); |
Philipp Wollermann | e219a24 | 2016-08-18 14:39:37 +0000 | [diff] [blame] | 65 | fail("Expected FilePermissionException or IOException, but wasn't thrown."); |
Philipp Wollermann | c3228f4 | 2015-06-30 16:54:55 +0000 | [diff] [blame] | 66 | } catch (FilePermissionException e) { |
diamondm | ad04da6 | 2019-03-19 09:54:50 -0700 | [diff] [blame] | 67 | assertThat(e).hasMessageThat().isEqualTo(foo + " (Operation not permitted)"); |
Philipp Wollermann | e219a24 | 2016-08-18 14:39:37 +0000 | [diff] [blame] | 68 | } catch (IOException e) { |
| 69 | // When running in a sandbox, /bin might actually be a read-only file system. |
diamondm | ad04da6 | 2019-03-19 09:54:50 -0700 | [diff] [blame] | 70 | assertThat(e).hasMessageThat().isEqualTo(foo + " (Read-only file system)"); |
Philipp Wollermann | 1d50375 | 2015-06-30 16:36:01 +0000 | [diff] [blame] | 71 | } |
| 72 | } |
ajmichael | ad32f62 | 2018-02-09 10:19:29 -0800 | [diff] [blame] | 73 | |
| 74 | /** Skips the test if the file system does not support extended attributes. */ |
| 75 | private static void assumeXattrsSupported() throws Exception { |
| 76 | // The standard file systems on macOS support extended attributes by default, so we can assume |
| 77 | // that the test will work on that platform. For other systems, we currently don't have a |
| 78 | // mechanism to validate this so the tests are skipped unconditionally. |
| 79 | assumeTrue(OS.getCurrent() == OS.DARWIN); |
| 80 | } |
| 81 | |
| 82 | @Test |
jmmv | bfbd95f | 2020-08-31 13:12:38 -0700 | [diff] [blame] | 83 | public void testGetxattr_attributeFound() throws Exception { |
ajmichael | ad32f62 | 2018-02-09 10:19:29 -0800 | [diff] [blame] | 84 | assumeXattrsSupported(); |
| 85 | |
| 86 | String myfile = Files.createTempFile("getxattrtest", null).toString(); |
arostovtsev | 0212f18 | 2020-04-29 14:07:26 -0700 | [diff] [blame] | 87 | assertThat(new ProcessBuilder("xattr", "-w", "foo", "bar", myfile).start().waitFor()) |
| 88 | .isEqualTo(0); |
ajmichael | ad32f62 | 2018-02-09 10:19:29 -0800 | [diff] [blame] | 89 | |
| 90 | assertThat(new String(NativePosixFiles.getxattr(myfile, "foo"), UTF_8)).isEqualTo("bar"); |
| 91 | assertThat(new String(NativePosixFiles.lgetxattr(myfile, "foo"), UTF_8)).isEqualTo("bar"); |
| 92 | } |
| 93 | |
| 94 | @Test |
jmmv | bfbd95f | 2020-08-31 13:12:38 -0700 | [diff] [blame] | 95 | public void testGetxattr_attributeNotFoundReturnsNull() throws Exception { |
ajmichael | ad32f62 | 2018-02-09 10:19:29 -0800 | [diff] [blame] | 96 | assumeXattrsSupported(); |
| 97 | |
| 98 | String myfile = Files.createTempFile("getxattrtest", null).toString(); |
| 99 | |
| 100 | assertThat(NativePosixFiles.getxattr(myfile, "foo")).isNull(); |
| 101 | assertThat(NativePosixFiles.lgetxattr(myfile, "foo")).isNull(); |
| 102 | } |
| 103 | |
| 104 | @Test |
jmmv | bfbd95f | 2020-08-31 13:12:38 -0700 | [diff] [blame] | 105 | public void testGetxattr_fileNotFound() throws Exception { |
ajmichael | ad32f62 | 2018-02-09 10:19:29 -0800 | [diff] [blame] | 106 | String nonexistentFile = workingDir.getChild("nonexistent").toString(); |
| 107 | |
| 108 | assertThrows( |
| 109 | FileNotFoundException.class, () -> NativePosixFiles.getxattr(nonexistentFile, "foo")); |
| 110 | assertThrows( |
| 111 | FileNotFoundException.class, () -> NativePosixFiles.lgetxattr(nonexistentFile, "foo")); |
| 112 | } |
Benjamin Peterson | be9fbec | 2019-03-27 05:25:18 -0700 | [diff] [blame] | 113 | |
| 114 | @Test |
| 115 | public void writing() throws Exception { |
| 116 | java.nio.file.Path myfile = Files.createTempFile("myfile", null); |
| 117 | int fd1 = NativePosixFiles.openWrite(myfile.toString(), false); |
| 118 | assertThrows( |
| 119 | IndexOutOfBoundsException.class, |
| 120 | () -> NativePosixFiles.write(fd1, new byte[] {0, 1, 2, 3}, 5, 1)); |
| 121 | assertThrows( |
| 122 | IndexOutOfBoundsException.class, |
| 123 | () -> NativePosixFiles.write(fd1, new byte[] {0, 1, 2, 3}, -1, 1)); |
| 124 | assertThrows( |
| 125 | IndexOutOfBoundsException.class, |
| 126 | () -> NativePosixFiles.write(fd1, new byte[] {0, 1, 2, 3}, 0, -1)); |
| 127 | assertThrows( |
| 128 | IndexOutOfBoundsException.class, |
| 129 | () -> NativePosixFiles.write(fd1, new byte[] {0, 1, 2, 3}, 0, 5)); |
| 130 | NativePosixFiles.write(fd1, new byte[] {0, 1, 2, 3}, 0, 4); |
| 131 | NativePosixFiles.close(fd1, null); |
| 132 | assertThat(Files.readAllBytes(myfile)).isEqualTo(new byte[] {0, 1, 2, 3}); |
| 133 | // Try appending. |
| 134 | int fd2 = NativePosixFiles.openWrite(myfile.toString(), true); |
| 135 | NativePosixFiles.write(fd2, new byte[] {5, 6, 7, 8, 9}, 1, 3); |
| 136 | NativePosixFiles.close(fd2, null); |
| 137 | assertThat(Files.readAllBytes(myfile)).isEqualTo(new byte[] {0, 1, 2, 3, 6, 7, 8}); |
| 138 | } |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 139 | } |