OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <fcntl.h> | 5 #include <fcntl.h> |
6 | 6 |
7 #include <gtest/gtest.h> | 7 #include <gtest/gtest.h> |
8 | 8 |
9 #include <string> | 9 #include <string> |
10 #include <vector> | 10 #include <vector> |
(...skipping 13 matching lines...) Expand all Loading... |
24 public: | 24 public: |
25 explicit FuseFsForTesting(fuse_operations* fuse_ops) { | 25 explicit FuseFsForTesting(fuse_operations* fuse_ops) { |
26 FsInitArgs args; | 26 FsInitArgs args; |
27 args.fuse_ops = fuse_ops; | 27 args.fuse_ops = fuse_ops; |
28 EXPECT_EQ(0, Init(args)); | 28 EXPECT_EQ(0, Init(args)); |
29 } | 29 } |
30 }; | 30 }; |
31 | 31 |
32 // Implementation of a simple flat memory filesystem. | 32 // Implementation of a simple flat memory filesystem. |
33 struct File { | 33 struct File { |
34 File() { | 34 File() : mode(0666) { memset(×, 0, sizeof(times)); } |
35 memset(×, 0, sizeof(times)); | |
36 } | |
37 | 35 |
38 std::string name; | 36 std::string name; |
39 std::vector<uint8_t> data; | 37 std::vector<uint8_t> data; |
| 38 mode_t mode; |
40 timespec times[2]; | 39 timespec times[2]; |
41 }; | 40 }; |
42 | 41 |
43 typedef std::vector<File> Files; | 42 typedef std::vector<File> Files; |
44 Files g_files; | 43 Files g_files; |
45 mode_t last_create_mode = 0666; | |
46 | 44 |
47 bool IsValidPath(const char* path) { | 45 bool IsValidPath(const char* path) { |
48 if (path == NULL) | 46 if (path == NULL) |
49 return false; | 47 return false; |
50 | 48 |
51 if (strlen(path) <= 1) | 49 if (strlen(path) <= 1) |
52 return false; | 50 return false; |
53 | 51 |
54 if (path[0] != '/') | 52 if (path[0] != '/') |
55 return false; | 53 return false; |
(...skipping 18 matching lines...) Expand all Loading... |
74 | 72 |
75 if (strcmp(path, "/") == 0) { | 73 if (strcmp(path, "/") == 0) { |
76 stbuf->st_mode = S_IFDIR | 0755; | 74 stbuf->st_mode = S_IFDIR | 0755; |
77 return 0; | 75 return 0; |
78 } | 76 } |
79 | 77 |
80 File* file = FindFile(path); | 78 File* file = FindFile(path); |
81 if (file == NULL) | 79 if (file == NULL) |
82 return -ENOENT; | 80 return -ENOENT; |
83 | 81 |
84 stbuf->st_mode = S_IFREG | last_create_mode; | 82 stbuf->st_mode = S_IFREG | file->mode; |
85 stbuf->st_size = file->data.size(); | 83 stbuf->st_size = file->data.size(); |
86 stbuf->st_atime = file->times[0].tv_sec; | 84 stbuf->st_atime = file->times[0].tv_sec; |
87 stbuf->st_atimensec = file->times[0].tv_nsec; | 85 stbuf->st_atimensec = file->times[0].tv_nsec; |
88 stbuf->st_mtime = file->times[1].tv_sec; | 86 stbuf->st_mtime = file->times[1].tv_sec; |
89 stbuf->st_mtimensec = file->times[1].tv_nsec; | 87 stbuf->st_mtimensec = file->times[1].tv_nsec; |
90 return 0; | 88 return 0; |
91 } | 89 } |
92 | 90 |
93 int testfs_readdir(const char* path, | 91 int testfs_readdir(const char* path, |
94 void* buf, | 92 void* buf, |
(...skipping 17 matching lines...) Expand all Loading... |
112 | 110 |
113 File* file = FindFile(path); | 111 File* file = FindFile(path); |
114 if (file != NULL) { | 112 if (file != NULL) { |
115 if (fi->flags & O_EXCL) | 113 if (fi->flags & O_EXCL) |
116 return -EEXIST; | 114 return -EEXIST; |
117 } else { | 115 } else { |
118 g_files.push_back(File()); | 116 g_files.push_back(File()); |
119 file = &g_files.back(); | 117 file = &g_files.back(); |
120 file->name = &path[1]; // Skip initial / | 118 file->name = &path[1]; // Skip initial / |
121 } | 119 } |
122 last_create_mode = mode; | 120 file->mode = mode; |
123 | 121 |
124 return 0; | 122 return 0; |
125 } | 123 } |
126 | 124 |
127 int testfs_open(const char* path, struct fuse_file_info*) { | 125 int testfs_open(const char* path, struct fuse_file_info*) { |
128 // open is only called to open an existing file, otherwise create is | 126 // open is only called to open an existing file, otherwise create is |
129 // called. We don't need to do any additional work here, the path will be | 127 // called. We don't need to do any additional work here, the path will be |
130 // passed to any other operations. | 128 // passed to any other operations. |
131 return FindFile(path) != NULL; | 129 return FindFile(path) != NULL; |
132 } | 130 } |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
173 int testfs_utimens(const char* path, const struct timespec times[2]) { | 171 int testfs_utimens(const char* path, const struct timespec times[2]) { |
174 File* file = FindFile(path); | 172 File* file = FindFile(path); |
175 if (file == NULL) | 173 if (file == NULL) |
176 return -ENOENT; | 174 return -ENOENT; |
177 | 175 |
178 file->times[0] = times[0]; | 176 file->times[0] = times[0]; |
179 file->times[1] = times[1]; | 177 file->times[1] = times[1]; |
180 return 0; | 178 return 0; |
181 } | 179 } |
182 | 180 |
| 181 int testfs_chmod(const char* path, mode_t mode) { |
| 182 File* file = FindFile(path); |
| 183 if (file == NULL) |
| 184 return -ENOENT; |
| 185 |
| 186 file->mode = mode; |
| 187 return 0; |
| 188 } |
| 189 |
183 const char hello_world[] = "Hello, World!\n"; | 190 const char hello_world[] = "Hello, World!\n"; |
184 | 191 |
185 fuse_operations g_fuse_operations = { | 192 fuse_operations g_fuse_operations = { |
186 0, // flag_nopath | 193 0, // flag_nopath |
187 0, // flag_reserved | 194 0, // flag_reserved |
| 195 testfs_getattr, // getattr |
| 196 NULL, // readlink |
| 197 NULL, // mknod |
| 198 NULL, // mkdir |
| 199 NULL, // unlink |
| 200 NULL, // rmdir |
| 201 NULL, // symlink |
| 202 NULL, // rename |
| 203 NULL, // link |
| 204 testfs_chmod, // chmod |
| 205 NULL, // chown |
| 206 NULL, // truncate |
| 207 testfs_open, // open |
| 208 testfs_read, // read |
| 209 testfs_write, // write |
| 210 NULL, // statfs |
| 211 NULL, // flush |
| 212 NULL, // release |
| 213 NULL, // fsync |
| 214 NULL, // setxattr |
| 215 NULL, // getxattr |
| 216 NULL, // listxattr |
| 217 NULL, // removexattr |
| 218 NULL, // opendir |
| 219 testfs_readdir, // readdir |
| 220 NULL, // releasedir |
| 221 NULL, // fsyncdir |
188 NULL, // init | 222 NULL, // init |
189 NULL, // destroy | 223 NULL, // destroy |
190 NULL, // access | 224 NULL, // access |
191 testfs_create, // create | 225 testfs_create, // create |
| 226 NULL, // ftruncate |
192 NULL, // fgetattr | 227 NULL, // fgetattr |
193 NULL, // fsync | 228 NULL, // lock |
194 NULL, // ftruncate | |
195 testfs_getattr, // getattr | |
196 NULL, // mkdir | |
197 NULL, // mknod | |
198 testfs_open, // open | |
199 NULL, // opendir | |
200 testfs_read, // read | |
201 testfs_readdir, // readdir | |
202 NULL, // release | |
203 NULL, // releasedir | |
204 NULL, // rename | |
205 NULL, // rmdir | |
206 NULL, // truncate | |
207 NULL, // unlink | |
208 testfs_write, // write | |
209 testfs_utimens, // utimens | 229 testfs_utimens, // utimens |
| 230 NULL, // bmap |
| 231 NULL, // ioctl |
| 232 NULL, // poll |
| 233 NULL, // write_buf |
| 234 NULL, // read_buf |
| 235 NULL, // flock |
| 236 NULL, // fallocate |
210 }; | 237 }; |
211 | 238 |
212 class FuseFsTest : public ::testing::Test { | 239 class FuseFsTest : public ::testing::Test { |
213 public: | 240 public: |
214 FuseFsTest(); | 241 FuseFsTest(); |
215 | 242 |
216 void SetUp(); | 243 void SetUp(); |
217 | 244 |
218 protected: | 245 protected: |
219 FuseFsForTesting fs_; | 246 FuseFsForTesting fs_; |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
354 ASSERT_EQ(0, fs_.Open(Path("/hello"), O_RDONLY, &node)); | 381 ASSERT_EQ(0, fs_.Open(Path("/hello"), O_RDONLY, &node)); |
355 EXPECT_EQ(0, node->Futimens(times)); | 382 EXPECT_EQ(0, node->Futimens(times)); |
356 | 383 |
357 EXPECT_EQ(0, node->GetStat(&statbuf)); | 384 EXPECT_EQ(0, node->GetStat(&statbuf)); |
358 EXPECT_EQ(times[0].tv_sec, statbuf.st_atime); | 385 EXPECT_EQ(times[0].tv_sec, statbuf.st_atime); |
359 EXPECT_EQ(times[0].tv_nsec, statbuf.st_atimensec); | 386 EXPECT_EQ(times[0].tv_nsec, statbuf.st_atimensec); |
360 EXPECT_EQ(times[1].tv_sec, statbuf.st_mtime); | 387 EXPECT_EQ(times[1].tv_sec, statbuf.st_mtime); |
361 EXPECT_EQ(times[1].tv_nsec, statbuf.st_mtimensec); | 388 EXPECT_EQ(times[1].tv_nsec, statbuf.st_mtimensec); |
362 } | 389 } |
363 | 390 |
| 391 TEST_F(FuseFsTest, Fchmod) { |
| 392 struct stat statbuf; |
| 393 ScopedNode node; |
| 394 |
| 395 ASSERT_EQ(0, fs_.Open(Path("/hello"), O_RDONLY, &node)); |
| 396 ASSERT_EQ(0, node->GetStat(&statbuf)); |
| 397 EXPECT_EQ(0666, statbuf.st_mode & ~S_IFMT); |
| 398 |
| 399 ASSERT_EQ(0, node->Fchmod(0777)); |
| 400 |
| 401 ASSERT_EQ(0, node->GetStat(&statbuf)); |
| 402 EXPECT_EQ(0777, statbuf.st_mode & ~S_IFMT); |
| 403 } |
| 404 |
364 namespace { | 405 namespace { |
365 | 406 |
366 class KernelProxyFuseTest : public ::testing::Test { | 407 class KernelProxyFuseTest : public ::testing::Test { |
367 public: | 408 public: |
368 KernelProxyFuseTest() {} | 409 KernelProxyFuseTest() {} |
369 | 410 |
370 void SetUp(); | 411 void SetUp(); |
371 void TearDown(); | 412 void TearDown(); |
372 | 413 |
373 private: | 414 private: |
(...skipping 30 matching lines...) Expand all Loading... |
404 // Then read it back in. | 445 // Then read it back in. |
405 fd = ki_open("/hello", O_RDONLY, 0); | 446 fd = ki_open("/hello", O_RDONLY, 0); |
406 ASSERT_GT(fd, -1); | 447 ASSERT_GT(fd, -1); |
407 | 448 |
408 char buffer[30]; | 449 char buffer[30]; |
409 memset(buffer, 0, sizeof(buffer)); | 450 memset(buffer, 0, sizeof(buffer)); |
410 ASSERT_EQ(sizeof(hello_world), ki_read(fd, buffer, sizeof(buffer))); | 451 ASSERT_EQ(sizeof(hello_world), ki_read(fd, buffer, sizeof(buffer))); |
411 EXPECT_STREQ(hello_world, buffer); | 452 EXPECT_STREQ(hello_world, buffer); |
412 EXPECT_EQ(0, ki_close(fd)); | 453 EXPECT_EQ(0, ki_close(fd)); |
413 } | 454 } |
OLD | NEW |