| OLD | NEW |
| (Empty) |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "files/public/c/lib/directory_wrapper.h" | |
| 6 | |
| 7 #include <errno.h> | |
| 8 | |
| 9 #include <memory> | |
| 10 | |
| 11 #include "files/public/c/lib/fd_impl.h" | |
| 12 #include "files/public/c/mojio_fcntl.h" | |
| 13 #include "files/public/c/mojio_sys_stat.h" | |
| 14 #include "files/public/c/tests/mock_errno_impl.h" | |
| 15 #include "files/public/c/tests/mojio_impl_test_base.h" | |
| 16 #include "files/public/c/tests/test_utils.h" | |
| 17 | |
| 18 namespace mojio { | |
| 19 namespace { | |
| 20 | |
| 21 using DirectoryWrapperTest = mojio::test::MojioImplTestBase; | |
| 22 | |
| 23 const int kLastErrorSentinel = -12345; | |
| 24 | |
| 25 // Note: |Open()|'s |mode| is currently basically ignored, so there's nothing to | |
| 26 // test yet. If this ever changes, we'll have to test it. | |
| 27 | |
| 28 // TODO(vtl): Currently, the Files service/interface doesn't report | |
| 29 // complete/thorough errors, hence our errno checks are bit wacky. | |
| 30 TEST_F(DirectoryWrapperTest, OpenCreate) { | |
| 31 test::MockErrnoImpl errno_impl(kLastErrorSentinel); | |
| 32 DirectoryWrapper dw(&errno_impl, directory().Pass()); | |
| 33 | |
| 34 // Opening a nonexistent file without MOJIO_O_CREAT should fail. | |
| 35 EXPECT_FALSE(dw.Open("my_file", MOJIO_O_RDWR, MOJIO_S_IRWXU)); | |
| 36 EXPECT_EQ(EIO, errno_impl.Get()); | |
| 37 | |
| 38 // Opening it with MOJIO_O_CREAT should work though. | |
| 39 errno_impl.Reset(kLastErrorSentinel); | |
| 40 EXPECT_TRUE(dw.Open("my_file", MOJIO_O_RDWR | MOJIO_O_CREAT, MOJIO_S_IRWXU)); | |
| 41 EXPECT_EQ(kLastErrorSentinel, errno_impl.Get()); // No error. | |
| 42 EXPECT_EQ(0, test::GetFileSize(&dw.directory(), "my_file")); | |
| 43 | |
| 44 // And again. | |
| 45 errno_impl.Reset(kLastErrorSentinel); | |
| 46 EXPECT_TRUE( | |
| 47 dw.Open("my_file", MOJIO_O_WRONLY | MOJIO_O_CREAT, MOJIO_S_IRWXU)); | |
| 48 EXPECT_EQ(kLastErrorSentinel, errno_impl.Get()); // No error. | |
| 49 | |
| 50 // But not with MOJIO_O_EXCL. | |
| 51 errno_impl.Reset(kLastErrorSentinel); | |
| 52 EXPECT_FALSE(dw.Open("my_file", MOJIO_O_WRONLY | MOJIO_O_CREAT | MOJIO_O_EXCL, | |
| 53 MOJIO_S_IRWXU)); | |
| 54 EXPECT_EQ(EIO, errno_impl.Get()); | |
| 55 | |
| 56 // Make a subdirectory. | |
| 57 test::MakeDirAt(&dw.directory(), "my_dir"); | |
| 58 | |
| 59 // Can't create a file of that name, even with MOJIO_O_CREAT. | |
| 60 errno_impl.Reset(kLastErrorSentinel); | |
| 61 EXPECT_FALSE( | |
| 62 dw.Open("my_dir", MOJIO_O_WRONLY | MOJIO_O_CREAT, MOJIO_S_IRWXU)); | |
| 63 EXPECT_EQ(EIO, errno_impl.Get()); | |
| 64 | |
| 65 // Create a file in that subdirectory, let's say with MOJIO_O_EXCL. | |
| 66 errno_impl.Reset(kLastErrorSentinel); | |
| 67 EXPECT_TRUE(dw.Open("my_dir/foo", | |
| 68 MOJIO_O_WRONLY | MOJIO_O_CREAT | MOJIO_O_EXCL, | |
| 69 MOJIO_S_IRWXU)); | |
| 70 EXPECT_EQ(kLastErrorSentinel, errno_impl.Get()); // No error. | |
| 71 EXPECT_EQ(0, test::GetFileSize(&dw.directory(), "my_dir/foo")); | |
| 72 } | |
| 73 | |
| 74 TEST_F(DirectoryWrapperTest, OpenTruncate) { | |
| 75 test::MockErrnoImpl errno_impl(kLastErrorSentinel); | |
| 76 DirectoryWrapper dw(&errno_impl, directory().Pass()); | |
| 77 | |
| 78 // Can't open a nonexistent file with only MOJIO_O_TRUNC. | |
| 79 EXPECT_FALSE( | |
| 80 dw.Open("nonexistent", MOJIO_O_WRONLY | MOJIO_O_TRUNC, MOJIO_S_IRWXU)); | |
| 81 EXPECT_EQ(EIO, errno_impl.Get()); | |
| 82 | |
| 83 // But can with MOJIO_O_CREAT. | |
| 84 errno_impl.Reset(kLastErrorSentinel); | |
| 85 EXPECT_TRUE(dw.Open("to_create", | |
| 86 MOJIO_O_WRONLY | MOJIO_O_CREAT | MOJIO_O_TRUNC, | |
| 87 MOJIO_S_IRWXU)); | |
| 88 EXPECT_EQ(kLastErrorSentinel, errno_impl.Get()); // No error. | |
| 89 EXPECT_EQ(0, test::GetFileSize(&dw.directory(), "to_create")); | |
| 90 | |
| 91 test::CreateTestFileAt(&dw.directory(), "my_file", 123); | |
| 92 | |
| 93 // Opening without MOJIO_O_TRUNC doesn't change the file size, with or without | |
| 94 // MOJIO_O_CREAT. | |
| 95 errno_impl.Reset(kLastErrorSentinel); | |
| 96 EXPECT_TRUE( | |
| 97 dw.Open("my_file", MOJIO_O_WRONLY | MOJIO_O_CREAT, MOJIO_S_IRWXU)); | |
| 98 EXPECT_EQ(kLastErrorSentinel, errno_impl.Get()); // No error. | |
| 99 EXPECT_EQ(123, test::GetFileSize(&dw.directory(), "my_file")); | |
| 100 | |
| 101 errno_impl.Reset(kLastErrorSentinel); | |
| 102 EXPECT_TRUE( | |
| 103 dw.Open("my_file", MOJIO_O_WRONLY | MOJIO_O_CREAT, MOJIO_S_IRWXU)); | |
| 104 EXPECT_EQ(kLastErrorSentinel, errno_impl.Get()); // No error. | |
| 105 EXPECT_EQ(123, test::GetFileSize(&dw.directory(), "my_file")); | |
| 106 | |
| 107 // But with MOJIO_O_TRUNC, it truncates (only test without MOJIO_O_CREAT). | |
| 108 errno_impl.Reset(kLastErrorSentinel); | |
| 109 EXPECT_TRUE( | |
| 110 dw.Open("my_file", MOJIO_O_WRONLY | MOJIO_O_TRUNC, MOJIO_S_IRWXU)); | |
| 111 EXPECT_EQ(kLastErrorSentinel, errno_impl.Get()); // No error. | |
| 112 EXPECT_EQ(0, test::GetFileSize(&dw.directory(), "my_file")); | |
| 113 } | |
| 114 | |
| 115 TEST_F(DirectoryWrapperTest, OpenExisting) { | |
| 116 test::CreateTestFileAt(&directory(), "my_file", 123); | |
| 117 | |
| 118 test::MockErrnoImpl errno_impl(kLastErrorSentinel); | |
| 119 DirectoryWrapper dw(&errno_impl, directory().Pass()); | |
| 120 | |
| 121 // Test various flags: | |
| 122 EXPECT_TRUE(dw.Open("my_file", MOJIO_O_RDONLY, MOJIO_S_IRWXU)); | |
| 123 EXPECT_EQ(kLastErrorSentinel, errno_impl.Get()); // No error. | |
| 124 EXPECT_EQ(123, test::GetFileSize(&dw.directory(), "my_file")); | |
| 125 | |
| 126 errno_impl.Reset(kLastErrorSentinel); | |
| 127 EXPECT_TRUE(dw.Open("my_file", MOJIO_O_RDWR, MOJIO_S_IRWXU)); | |
| 128 EXPECT_EQ(kLastErrorSentinel, errno_impl.Get()); // No error. | |
| 129 EXPECT_EQ(123, test::GetFileSize(&dw.directory(), "my_file")); | |
| 130 | |
| 131 errno_impl.Reset(kLastErrorSentinel); | |
| 132 EXPECT_TRUE(dw.Open("my_file", MOJIO_O_WRONLY, MOJIO_S_IRWXU)); | |
| 133 EXPECT_EQ(kLastErrorSentinel, errno_impl.Get()); // No error. | |
| 134 EXPECT_EQ(123, test::GetFileSize(&dw.directory(), "my_file")); | |
| 135 | |
| 136 errno_impl.Reset(kLastErrorSentinel); | |
| 137 EXPECT_TRUE( | |
| 138 dw.Open("my_file", MOJIO_O_WRONLY | MOJIO_O_CREAT, MOJIO_S_IRWXU)); | |
| 139 EXPECT_EQ(kLastErrorSentinel, errno_impl.Get()); // No error. | |
| 140 EXPECT_EQ(123, test::GetFileSize(&dw.directory(), "my_file")); | |
| 141 | |
| 142 errno_impl.Reset(kLastErrorSentinel); | |
| 143 EXPECT_TRUE( | |
| 144 dw.Open("my_file", MOJIO_O_WRONLY | MOJIO_O_APPEND, MOJIO_S_IRWXU)); | |
| 145 EXPECT_EQ(kLastErrorSentinel, errno_impl.Get()); // No error. | |
| 146 EXPECT_EQ(123, test::GetFileSize(&dw.directory(), "my_file")); | |
| 147 } | |
| 148 | |
| 149 // Note: This necessarily also involves the returned |FDImpl|'s |Write()|. | |
| 150 TEST_F(DirectoryWrapperTest, OpenAppend) { | |
| 151 test::CreateTestFileAt(&directory(), "my_file", 123); | |
| 152 | |
| 153 test::MockErrnoImpl errno_impl(kLastErrorSentinel); | |
| 154 DirectoryWrapper dw(&errno_impl, directory().Pass()); | |
| 155 | |
| 156 std::unique_ptr<FDImpl> fdi = | |
| 157 dw.Open("my_file", MOJIO_O_WRONLY | MOJIO_O_APPEND, MOJIO_S_IRWXU); | |
| 158 EXPECT_TRUE(fdi); | |
| 159 EXPECT_EQ(kLastErrorSentinel, errno_impl.Get()); // No error. | |
| 160 | |
| 161 // Write some stuff to it. | |
| 162 errno_impl.Reset(kLastErrorSentinel); | |
| 163 const char kWriteBuffer[45] = {'x', 'y', 'z'}; | |
| 164 EXPECT_EQ(45, fdi->Write(kWriteBuffer, sizeof(kWriteBuffer))); | |
| 165 EXPECT_EQ(kLastErrorSentinel, errno_impl.Get()); // No error. | |
| 166 | |
| 167 EXPECT_EQ(123 + 45, test::GetFileSize(&dw.directory(), "my_file")); | |
| 168 } | |
| 169 | |
| 170 TEST_F(DirectoryWrapperTest, OpenInvalidFlags) { | |
| 171 test::MockErrnoImpl errno_impl(kLastErrorSentinel); | |
| 172 DirectoryWrapper dw(&errno_impl, directory().Pass()); | |
| 173 | |
| 174 // Invalid access mode (masked by MOJIO_O_ACCMODE). | |
| 175 // | |
| 176 // Note: POSIX "requires" that exactly one of MOJIO_O_RDONLY, MOJIO_O_RDWR, or | |
| 177 // MOJIO_O_WRONLY be included. However, we follow Linux and let MOJIO_O_RDONLY | |
| 178 // have value 0, so this can't be detected (POSIX allows this by saying that | |
| 179 // missing one of these flags *may* result in EINVAL). | |
| 180 // | |
| 181 // However, the or of all three isn't valid, and we do give EINVAL for that. | |
| 182 EXPECT_FALSE(dw.Open("my_file", | |
| 183 MOJIO_O_RDONLY | MOJIO_O_RDWR | MOJIO_O_WRONLY, | |
| 184 MOJIO_S_IRWXU)); | |
| 185 EXPECT_EQ(EINVAL, errno_impl.Get()); | |
| 186 } | |
| 187 | |
| 188 TEST_F(DirectoryWrapperTest, Efault) { | |
| 189 test::MockErrnoImpl errno_impl(kLastErrorSentinel); | |
| 190 DirectoryWrapper dw(&errno_impl, directory().Pass()); | |
| 191 | |
| 192 EXPECT_FALSE(dw.Open(nullptr, MOJIO_O_WRONLY | MOJIO_O_CREAT, MOJIO_S_IRWXU)); | |
| 193 EXPECT_EQ(EFAULT, errno_impl.Get()); | |
| 194 | |
| 195 errno_impl.Reset(kLastErrorSentinel); | |
| 196 EXPECT_FALSE(dw.Chdir(nullptr)); | |
| 197 EXPECT_EQ(EFAULT, errno_impl.Get()); | |
| 198 } | |
| 199 | |
| 200 } // namespace | |
| 201 } // namespace mojio | |
| OLD | NEW |