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> |
11 | 11 |
12 #include "nacl_io/fuse.h" | 12 #include "nacl_io/fuse.h" |
13 #include "nacl_io/fusefs/fuse_fs.h" | 13 #include "nacl_io/fusefs/fuse_fs.h" |
14 #include "nacl_io/kernel_handle.h" | 14 #include "nacl_io/kernel_handle.h" |
15 #include "nacl_io/kernel_intercept.h" | 15 #include "nacl_io/kernel_intercept.h" |
16 #include "nacl_io/kernel_proxy.h" | 16 #include "nacl_io/kernel_proxy.h" |
| 17 #include "nacl_io/ostime.h" |
17 | 18 |
18 using namespace nacl_io; | 19 using namespace nacl_io; |
19 | 20 |
20 namespace { | 21 namespace { |
21 | 22 |
22 class FuseFsForTesting : public FuseFs { | 23 class FuseFsForTesting : public FuseFs { |
23 public: | 24 public: |
24 explicit FuseFsForTesting(fuse_operations* fuse_ops) { | 25 explicit FuseFsForTesting(fuse_operations* fuse_ops) { |
25 FsInitArgs args; | 26 FsInitArgs args; |
26 args.fuse_ops = fuse_ops; | 27 args.fuse_ops = fuse_ops; |
27 EXPECT_EQ(0, Init(args)); | 28 EXPECT_EQ(0, Init(args)); |
28 } | 29 } |
29 }; | 30 }; |
30 | 31 |
31 // Implementation of a simple flat memory filesystem. | 32 // Implementation of a simple flat memory filesystem. |
32 struct File { | 33 struct File { |
| 34 File() { |
| 35 memset(×, 0, sizeof(times)); |
| 36 } |
| 37 |
33 std::string name; | 38 std::string name; |
34 std::vector<uint8_t> data; | 39 std::vector<uint8_t> data; |
| 40 timespec times[2]; |
35 }; | 41 }; |
36 | 42 |
37 typedef std::vector<File> Files; | 43 typedef std::vector<File> Files; |
38 Files g_files; | 44 Files g_files; |
39 mode_t last_create_mode = 0666; | 45 mode_t last_create_mode = 0666; |
40 | 46 |
41 bool IsValidPath(const char* path) { | 47 bool IsValidPath(const char* path) { |
42 if (path == NULL) | 48 if (path == NULL) |
43 return false; | 49 return false; |
44 | 50 |
(...skipping 25 matching lines...) Expand all Loading... |
70 stbuf->st_mode = S_IFDIR | 0755; | 76 stbuf->st_mode = S_IFDIR | 0755; |
71 return 0; | 77 return 0; |
72 } | 78 } |
73 | 79 |
74 File* file = FindFile(path); | 80 File* file = FindFile(path); |
75 if (file == NULL) | 81 if (file == NULL) |
76 return -ENOENT; | 82 return -ENOENT; |
77 | 83 |
78 stbuf->st_mode = S_IFREG | last_create_mode; | 84 stbuf->st_mode = S_IFREG | last_create_mode; |
79 stbuf->st_size = file->data.size(); | 85 stbuf->st_size = file->data.size(); |
| 86 stbuf->st_atime = file->times[0].tv_sec; |
| 87 stbuf->st_atimensec = file->times[0].tv_nsec; |
| 88 stbuf->st_mtime = file->times[1].tv_sec; |
| 89 stbuf->st_mtimensec = file->times[1].tv_nsec; |
80 return 0; | 90 return 0; |
81 } | 91 } |
82 | 92 |
83 int testfs_readdir(const char* path, | 93 int testfs_readdir(const char* path, |
84 void* buf, | 94 void* buf, |
85 fuse_fill_dir_t filler, | 95 fuse_fill_dir_t filler, |
86 off_t offset, | 96 off_t offset, |
87 struct fuse_file_info*) { | 97 struct fuse_file_info*) { |
88 if (strcmp(path, "/") != 0) | 98 if (strcmp(path, "/") != 0) |
89 return -ENOENT; | 99 return -ENOENT; |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
153 | 163 |
154 size_t filesize = file->data.size(); | 164 size_t filesize = file->data.size(); |
155 | 165 |
156 if (offset + size > filesize) | 166 if (offset + size > filesize) |
157 file->data.resize(offset + size); | 167 file->data.resize(offset + size); |
158 | 168 |
159 memcpy(file->data.data() + offset, buf, size); | 169 memcpy(file->data.data() + offset, buf, size); |
160 return size; | 170 return size; |
161 } | 171 } |
162 | 172 |
| 173 int testfs_utimens(const char* path, const struct timespec times[2]) { |
| 174 File* file = FindFile(path); |
| 175 if (file == NULL) |
| 176 return -ENOENT; |
| 177 |
| 178 file->times[0] = times[0]; |
| 179 file->times[1] = times[1]; |
| 180 return 0; |
| 181 } |
| 182 |
163 const char hello_world[] = "Hello, World!\n"; | 183 const char hello_world[] = "Hello, World!\n"; |
164 | 184 |
165 fuse_operations g_fuse_operations = { | 185 fuse_operations g_fuse_operations = { |
166 0, // flag_nopath | 186 0, // flag_nopath |
167 0, // flag_reserved | 187 0, // flag_reserved |
168 NULL, // init | 188 NULL, // init |
169 NULL, // destroy | 189 NULL, // destroy |
170 NULL, // access | 190 NULL, // access |
171 testfs_create, // create | 191 testfs_create, // create |
172 NULL, // fgetattr | 192 NULL, // fgetattr |
173 NULL, // fsync | 193 NULL, // fsync |
174 NULL, // ftruncate | 194 NULL, // ftruncate |
175 testfs_getattr, // getattr | 195 testfs_getattr, // getattr |
176 NULL, // mkdir | 196 NULL, // mkdir |
177 NULL, // mknod | 197 NULL, // mknod |
178 testfs_open, // open | 198 testfs_open, // open |
179 NULL, // opendir | 199 NULL, // opendir |
180 testfs_read, // read | 200 testfs_read, // read |
181 testfs_readdir, // readdir | 201 testfs_readdir, // readdir |
182 NULL, // release | 202 NULL, // release |
183 NULL, // releasedir | 203 NULL, // releasedir |
184 NULL, // rename | 204 NULL, // rename |
185 NULL, // rmdir | 205 NULL, // rmdir |
186 NULL, // truncate | 206 NULL, // truncate |
187 NULL, // unlink | 207 NULL, // unlink |
188 testfs_write, // write | 208 testfs_write, // write |
| 209 testfs_utimens, // utimens |
189 }; | 210 }; |
190 | 211 |
191 class FuseFsTest : public ::testing::Test { | 212 class FuseFsTest : public ::testing::Test { |
192 public: | 213 public: |
193 FuseFsTest(); | 214 FuseFsTest(); |
194 | 215 |
195 void SetUp(); | 216 void SetUp(); |
196 | 217 |
197 protected: | 218 protected: |
198 FuseFsForTesting fs_; | 219 FuseFsForTesting fs_; |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
313 ScopedNode node; | 334 ScopedNode node; |
314 ASSERT_EQ(0, fs_.Open(Path("/foobar"), O_RDWR | O_CREAT, &node)); | 335 ASSERT_EQ(0, fs_.Open(Path("/foobar"), O_RDWR | O_CREAT, &node)); |
315 ASSERT_EQ(0, root->GetDents(0, &entries[0], sizeof(entries), &bytes_read)); | 336 ASSERT_EQ(0, root->GetDents(0, &entries[0], sizeof(entries), &bytes_read)); |
316 ASSERT_EQ(4 * sizeof(dirent), bytes_read); | 337 ASSERT_EQ(4 * sizeof(dirent), bytes_read); |
317 EXPECT_STREQ(".", entries[0].d_name); | 338 EXPECT_STREQ(".", entries[0].d_name); |
318 EXPECT_STREQ("..", entries[1].d_name); | 339 EXPECT_STREQ("..", entries[1].d_name); |
319 EXPECT_STREQ("hello", entries[2].d_name); | 340 EXPECT_STREQ("hello", entries[2].d_name); |
320 EXPECT_STREQ("foobar", entries[3].d_name); | 341 EXPECT_STREQ("foobar", entries[3].d_name); |
321 } | 342 } |
322 | 343 |
| 344 TEST_F(FuseFsTest, Utimens) { |
| 345 struct stat statbuf; |
| 346 ScopedNode node; |
| 347 |
| 348 struct timespec times[2]; |
| 349 times[0].tv_sec = 1000; |
| 350 times[0].tv_nsec = 2000; |
| 351 times[1].tv_sec = 3000; |
| 352 times[1].tv_nsec = 4000; |
| 353 |
| 354 ASSERT_EQ(0, fs_.Open(Path("/hello"), O_RDONLY, &node)); |
| 355 EXPECT_EQ(0, node->Futimens(times)); |
| 356 |
| 357 EXPECT_EQ(0, node->GetStat(&statbuf)); |
| 358 EXPECT_EQ(times[0].tv_sec, statbuf.st_atime); |
| 359 EXPECT_EQ(times[0].tv_nsec, statbuf.st_atimensec); |
| 360 EXPECT_EQ(times[1].tv_sec, statbuf.st_mtime); |
| 361 EXPECT_EQ(times[1].tv_nsec, statbuf.st_mtimensec); |
| 362 } |
| 363 |
323 namespace { | 364 namespace { |
324 | 365 |
325 class KernelProxyFuseTest : public ::testing::Test { | 366 class KernelProxyFuseTest : public ::testing::Test { |
326 public: | 367 public: |
327 KernelProxyFuseTest() {} | 368 KernelProxyFuseTest() {} |
328 | 369 |
329 void SetUp(); | 370 void SetUp(); |
330 void TearDown(); | 371 void TearDown(); |
331 | 372 |
332 private: | 373 private: |
(...skipping 30 matching lines...) Expand all Loading... |
363 // Then read it back in. | 404 // Then read it back in. |
364 fd = ki_open("/hello", O_RDONLY, 0); | 405 fd = ki_open("/hello", O_RDONLY, 0); |
365 ASSERT_GT(fd, -1); | 406 ASSERT_GT(fd, -1); |
366 | 407 |
367 char buffer[30]; | 408 char buffer[30]; |
368 memset(buffer, 0, sizeof(buffer)); | 409 memset(buffer, 0, sizeof(buffer)); |
369 ASSERT_EQ(sizeof(hello_world), ki_read(fd, buffer, sizeof(buffer))); | 410 ASSERT_EQ(sizeof(hello_world), ki_read(fd, buffer, sizeof(buffer))); |
370 EXPECT_STREQ(hello_world, buffer); | 411 EXPECT_STREQ(hello_world, buffer); |
371 EXPECT_EQ(0, ki_close(fd)); | 412 EXPECT_EQ(0, ki_close(fd)); |
372 } | 413 } |
OLD | NEW |