| 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 |