Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / native_client_sdk / src / tests / nacl_io_test / js_fs_test.cc
blobfb2194d23b653e003ad909799df96053cf437849
1 // Copyright 2014 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.
5 #include <errno.h>
6 #include <fcntl.h>
7 #include <pthread.h>
9 #include <set>
10 #include <string>
12 #include <gmock/gmock.h>
13 #include <ppapi/c/pp_errors.h>
14 #include <ppapi/c/pp_instance.h>
16 #include "fake_ppapi/fake_messaging_interface.h"
17 #include "fake_ppapi/fake_pepper_interface.h"
18 #include "nacl_io/ioctl.h"
19 #include "nacl_io/jsfs/js_fs.h"
20 #include "nacl_io/jsfs/js_fs_node.h"
21 #include "nacl_io/kernel_intercept.h"
22 #include "nacl_io/kernel_proxy.h"
23 #include "nacl_io/log.h"
24 #include "nacl_io/osdirent.h"
25 #include "nacl_io/osunistd.h"
26 #include "sdk_util/auto_lock.h"
27 #include "sdk_util/scoped_ref.h"
28 #include "sdk_util/simple_lock.h"
30 using namespace nacl_io;
31 using namespace sdk_util;
33 namespace {
35 class JsFsForTesting : public JsFs {
36 public:
37 JsFsForTesting(PepperInterface* ppapi) {
38 FsInitArgs args;
39 args.ppapi = ppapi;
40 Error error = Init(args);
41 EXPECT_EQ(0, error);
45 class FakeMessagingInterfaceJsFs : public MessagingInterface {
46 public:
47 explicit FakeMessagingInterfaceJsFs(VarInterface* var_interface)
48 : var_interface_(var_interface), has_message_(false) {
49 pthread_cond_init(&cond_, NULL);
52 ~FakeMessagingInterfaceJsFs() { pthread_cond_destroy(&cond_); }
54 virtual void PostMessage(PP_Instance instance, PP_Var message) {
55 var_interface_->AddRef(message);
57 AUTO_LOCK(lock_);
58 ASSERT_FALSE(has_message_);
60 message_ = message;
61 has_message_ = true;
62 pthread_cond_signal(&cond_);
65 PP_Var WaitForMessage() {
66 AUTO_LOCK(lock_);
67 while (!has_message_) {
68 pthread_cond_wait(&cond_, lock_.mutex());
71 has_message_ = false;
72 return message_;
75 private:
76 VarInterface* var_interface_;
77 SimpleLock lock_;
78 pthread_cond_t cond_;
79 PP_Var message_;
80 bool has_message_;
83 class FakePepperInterfaceJsFs : public FakePepperInterface {
84 public:
85 FakePepperInterfaceJsFs() : messaging_interface_(GetVarInterface()) {}
87 virtual nacl_io::MessagingInterface* GetMessagingInterface() {
88 return &messaging_interface_;
91 private:
92 FakeMessagingInterfaceJsFs messaging_interface_;
95 class JsFsTest : public ::testing::Test {
96 public:
97 void SetUp() {
98 ASSERT_EQ(0, ki_push_state_for_testing());
99 ASSERT_EQ(0, ki_init_interface(&kp_, &ppapi_));
100 fs_.reset(new JsFsForTesting(&ppapi_));
102 js_thread_started_ = false;
105 void TearDown() {
106 if (js_thread_started_)
107 pthread_join(js_thread_, NULL);
109 for (RequestResponses::iterator it = request_responses_.begin(),
110 end = request_responses_.end();
111 it != end;
112 ++it) {
113 ppapi_.GetVarInterface()->Release(it->request);
114 ppapi_.GetVarInterface()->Release(it->response);
118 ki_uninit();
121 void StartJsThread() {
122 ASSERT_EQ(0, pthread_create(&js_thread_, NULL, JsThreadMainThunk, this));
123 js_thread_started_ = true;
126 static void* JsThreadMainThunk(void* arg) {
127 static_cast<JsFsTest*>(arg)->JsThreadMain();
128 return NULL;
131 PP_Var WaitForRequest() {
132 FakeMessagingInterfaceJsFs* messaging_if =
133 static_cast<FakeMessagingInterfaceJsFs*>(
134 ppapi_.GetMessagingInterface());
135 return messaging_if->WaitForMessage();
138 void JsThreadMain() {
139 for (RequestResponses::iterator it = request_responses_.begin(),
140 end = request_responses_.end();
141 it != end;
142 ++it) {
143 PP_Var request = WaitForRequest();
144 EXPECT_TRUE(VarsAreEqual(it->request, request))
145 << "Vars are not equal: " << VarToString(it->request)
146 << " != " << VarToString(request);
147 ppapi_.GetVarInterface()->Release(request);
148 EXPECT_EQ(0,
149 fs_->Filesystem_Ioctl(NACL_IOC_HANDLEMESSAGE, &it->response));
150 // Passed ownership of response_ to filesystem, so set this to undefined
151 // so it isn't double-released in TearDown().
152 it->response = PP_MakeUndefined();
156 void Expect(PP_Var request, PP_Var response) {
157 RequestResponse rr;
158 // Pass ownership of both vars from caller to callee.
159 rr.request = request;
160 rr.response = response;
161 request_responses_.push_back(rr);
164 bool CreateDict(PP_Var* out_var) {
165 *out_var = ppapi_.GetVarDictionaryInterface()->Create();
166 return out_var->type == PP_VARTYPE_DICTIONARY;
169 bool SetDictKeyValue(PP_Var* var, const char* key, int32_t value) {
170 return SetDictKeyValue(var, key, PP_MakeInt32(value));
173 bool SetDictKeyValue(PP_Var* var, const char* key, size_t value) {
174 return SetDictKeyValue(var, key, PP_MakeInt32(static_cast<size_t>(value)));
177 bool SetDictKeyValue(PP_Var* var, const char* key, int64_t value) {
178 VarArrayInterface* array_if = ppapi_.GetVarArrayInterface();
179 PP_Var value_var = array_if->Create();
180 return array_if->Set(value_var, 0, PP_MakeInt32(value >> 32)) &&
181 array_if->Set(value_var, 1, PP_MakeInt32(value & 0xffffffff)) &&
182 SetDictKeyValue(var, key, value_var);
185 bool SetDictKeyValue(PP_Var* var, const char* key, const char* value) {
186 VarInterface* var_if = ppapi_.GetVarInterface();
187 PP_Var value_var = var_if->VarFromUtf8(value, strlen(value));
188 return SetDictKeyValue(var, key, value_var);
191 bool SetDictKeyValue(PP_Var* var, const char* key, PP_Var value_var) {
192 VarDictionaryInterface* dict_if = ppapi_.GetVarDictionaryInterface();
193 VarInterface* var_if = ppapi_.GetVarInterface();
194 PP_Var key_var = var_if->VarFromUtf8(key, strlen(key));
195 PP_Bool result = dict_if->Set(*var, key_var, value_var);
196 var_if->Release(key_var);
197 var_if->Release(value_var);
198 return result == PP_TRUE;
201 bool CreateArray(PP_Var* out_var) {
202 *out_var = ppapi_.GetVarArrayInterface()->Create();
203 return out_var->type == PP_VARTYPE_ARRAY;
206 bool SetArrayValue(PP_Var* var, uint32_t i, int32_t value) {
207 return SetArrayValue(var, i, PP_MakeInt32(value));
210 bool SetArrayValue(PP_Var* var, uint32_t i, const char* value) {
211 VarInterface* var_if = ppapi_.GetVarInterface();
212 PP_Var value_var = var_if->VarFromUtf8(value, strlen(value));
213 return SetArrayValue(var, i, value_var);
216 bool SetArrayValue(PP_Var* var, uint32_t i, int64_t value) {
217 VarArrayInterface* array_if = ppapi_.GetVarArrayInterface();
218 PP_Var value_var = array_if->Create();
219 return array_if->Set(value_var, 0, PP_MakeInt32(value >> 32)) &&
220 array_if->Set(value_var, 1, PP_MakeInt32(value & 0xffffffff)) &&
221 SetArrayValue(var, i, value_var);
224 bool SetArrayValue(PP_Var* var, uint32_t i, PP_Var value_var) {
225 VarArrayInterface* array_if = ppapi_.GetVarArrayInterface();
226 VarInterface* var_if = ppapi_.GetVarInterface();
227 PP_Bool result = array_if->Set(*var, i, value_var);
228 var_if->Release(value_var);
229 return result == PP_TRUE;
232 std::string VarToString(PP_Var var) {
233 VarDictionaryInterface* dict_if = ppapi_.GetVarDictionaryInterface();
234 VarArrayInterface* array_if = ppapi_.GetVarArrayInterface();
235 VarInterface* var_if = ppapi_.GetVarInterface();
236 VarArrayBufferInterface* array_buffer_if =
237 ppapi_.GetVarArrayBufferInterface();
239 switch (var.type) {
240 case PP_VARTYPE_UNDEFINED:
241 return "undefined";
242 case PP_VARTYPE_NULL:
243 return "null";
244 case PP_VARTYPE_BOOL:
245 return var.value.as_bool ? "true" : "false";
246 case PP_VARTYPE_INT32: {
247 char buffer[32];
248 snprintf(buffer, 32, "%d", var.value.as_int);
249 return buffer;
251 case PP_VARTYPE_DOUBLE: {
252 char buffer[32];
253 snprintf(buffer, 32, "%g", var.value.as_double);
254 return buffer;
256 case PP_VARTYPE_STRING: {
257 uint32_t var_len;
258 const char* var_str = var_if->VarToUtf8(var, &var_len);
259 std::string result("\"");
260 result += std::string(var_str, var_len);
261 result += "\"";
262 return result;
264 case PP_VARTYPE_ARRAY: {
265 std::string result("[");
266 uint32_t var_len = array_if->GetLength(var);
268 for (uint32_t i = 0; i < var_len; ++i) {
269 PP_Var var_item = array_if->Get(var, i);
270 result += VarToString(var_item);
271 var_if->Release(var_item);
272 if (i != var_len - 1)
273 result += ", ";
275 result += "]";
276 return result;
278 case PP_VARTYPE_DICTIONARY: {
279 std::string result("{");
280 PP_Var var_keys = dict_if->GetKeys(var);
281 uint32_t var_len = array_if->GetLength(var_keys);
283 for (uint32_t i = 0; i < var_len; ++i) {
284 PP_Var key = array_if->Get(var_keys, i);
285 result += VarToString(key);
286 result += ": ";
287 PP_Var var_value = dict_if->Get(var, key);
288 result += VarToString(var_value);
289 var_if->Release(key);
290 var_if->Release(var_value);
291 if (i != var_len - 1)
292 result += ", ";
294 result += "}";
295 var_if->Release(var_keys);
296 return result;
298 case PP_VARTYPE_ARRAY_BUFFER: {
299 uint32_t var_len;
300 if (!array_buffer_if->ByteLength(var, &var_len)) {
301 LOG_ERROR("Unable to get byte length of var.");
302 return "undefined";
305 std::string result("new Uint8Array([");
307 void* var_ptr = array_buffer_if->Map(var);
308 for (uint32_t i = 0; i < var_len; ++i) {
309 char buffer[8];
310 snprintf(buffer, 8, "%d", static_cast<uint8_t*>(var_ptr)[i]);
311 result += buffer;
312 if (i != var_len - 1)
313 result += ", ";
315 result += "])";
316 array_buffer_if->Unmap(var);
317 return result;
320 default:
321 ADD_FAILURE() << "Unexpected var type: " << var.type;
322 return "undefined";
326 bool VarsAreEqual(PP_Var expected, PP_Var var) {
327 if (expected.type != var.type)
328 return false;
330 VarDictionaryInterface* dict_if = ppapi_.GetVarDictionaryInterface();
331 VarArrayInterface* array_if = ppapi_.GetVarArrayInterface();
332 VarInterface* var_if = ppapi_.GetVarInterface();
333 VarArrayBufferInterface* array_buffer_if =
334 ppapi_.GetVarArrayBufferInterface();
336 switch (var.type) {
337 case PP_VARTYPE_UNDEFINED:
338 case PP_VARTYPE_NULL:
339 return true;
340 case PP_VARTYPE_BOOL:
341 return expected.value.as_bool == var.value.as_bool;
342 case PP_VARTYPE_INT32:
343 return expected.value.as_int == var.value.as_int;
344 case PP_VARTYPE_DOUBLE:
345 return expected.value.as_double == var.value.as_double;
346 case PP_VARTYPE_STRING: {
347 uint32_t var_len;
348 uint32_t expected_len;
349 const char* var_str = var_if->VarToUtf8(var, &var_len);
350 const char* expected_str = var_if->VarToUtf8(expected, &expected_len);
352 if (expected_len != var_len)
353 return false;
355 return memcmp(expected_str, var_str, var_len) == 0;
357 case PP_VARTYPE_ARRAY: {
358 uint32_t var_len = array_if->GetLength(var);
359 uint32_t expected_len = array_if->GetLength(expected);
361 if (expected_len != var_len)
362 return false;
364 for (uint32_t i = 0; i < var_len; ++i) {
365 PP_Var var_item = array_if->Get(var, i);
366 PP_Var expected_item = array_if->Get(expected, i);
367 bool equal = VarsAreEqual(expected_item, var_item);
368 var_if->Release(var_item);
369 var_if->Release(expected_item);
371 if (!equal)
372 return false;
375 return true;
377 case PP_VARTYPE_DICTIONARY: {
378 PP_Var var_keys = dict_if->GetKeys(var);
379 PP_Var expected_keys = dict_if->GetKeys(expected);
381 uint32_t var_len = array_if->GetLength(var_keys);
382 uint32_t expected_len = array_if->GetLength(expected_keys);
384 bool result = true;
386 if (expected_len == var_len) {
387 for (uint32_t i = 0; i < var_len; ++i) {
388 PP_Var key = array_if->Get(var_keys, i);
389 PP_Var var_value = dict_if->Get(var, key);
390 PP_Var expected_value = dict_if->Get(expected, key);
391 bool equal = VarsAreEqual(expected_value, var_value);
392 var_if->Release(key);
393 var_if->Release(var_value);
394 var_if->Release(expected_value);
396 if (!equal) {
397 result = false;
398 break;
401 } else {
402 result = false;
405 var_if->Release(var_keys);
406 var_if->Release(expected_keys);
407 return result;
409 case PP_VARTYPE_ARRAY_BUFFER: {
410 uint32_t var_len;
411 if (!array_buffer_if->ByteLength(var, &var_len))
412 return false;
414 uint32_t expected_len;
415 if (!array_buffer_if->ByteLength(expected, &expected_len))
416 return false;
418 if (expected_len != var_len)
419 return false;
421 void* var_ptr = array_buffer_if->Map(var);
422 void* expected_ptr = array_buffer_if->Map(expected);
423 bool equal = memcmp(var_ptr, expected_ptr, var_len) == 0;
424 array_buffer_if->Unmap(var);
425 array_buffer_if->Unmap(expected);
427 return equal;
430 default:
431 ADD_FAILURE() << "Unexpected var type: " << var.type;
432 return false;
436 PP_Var CreateDummyArrayBuffer(uint32_t length) {
437 VarArrayBufferInterface* array_buffer_if =
438 ppapi_.GetVarArrayBufferInterface();
439 PP_Var var = array_buffer_if->Create(length);
440 uint8_t* data = static_cast<uint8_t*>(array_buffer_if->Map(var));
441 FillDummyBuffer(data, length);
442 array_buffer_if->Unmap(var);
443 return var;
446 void FillDummyBuffer(uint8_t* buf, size_t buf_len) {
447 for (uint32_t i = 0; i < buf_len; ++i) {
448 buf[i] = i & 255;
452 bool EqualsDummyArrayBuffer(uint8_t* buf, size_t buf_len) {
453 for (uint32_t i = 0; i < buf_len; ++i) {
454 if (buf[i] != (i & 255)) {
455 LOG_ERROR("Byte %d of ArrayBuffer doesn't match: %d != %d.",
457 buf[i],
458 i & 255);
459 return false;
462 return true;
465 protected:
466 FakePepperInterfaceJsFs ppapi_;
467 ScopedRef<JsFsForTesting> fs_;
468 KernelProxy kp_;
469 pthread_t js_thread_;
470 bool js_thread_started_;
472 struct RequestResponse {
473 PP_Var request;
474 PP_Var response;
477 typedef std::vector<RequestResponse> RequestResponses;
478 RequestResponses request_responses_;
481 class JsFsNodeTest : public JsFsTest {
482 public:
483 static const int fd;
485 virtual void SetUp() {
486 JsFsTest::SetUp();
488 PP_Var expected;
489 ASSERT_EQ(true, CreateDict(&expected));
490 ASSERT_EQ(true, SetDictKeyValue(&expected, "id", 1));
491 ASSERT_EQ(true, SetDictKeyValue(&expected, "cmd", "open"));
492 ASSERT_EQ(true, SetDictKeyValue(&expected, "path", "/foo"));
493 ASSERT_EQ(true, SetDictKeyValue(&expected, "oflag", O_RDONLY));
495 PP_Var response;
496 ASSERT_EQ(true, CreateDict(&response));
497 ASSERT_EQ(true, SetDictKeyValue(&response, "id", 1));
498 ASSERT_EQ(true, SetDictKeyValue(&response, "error", 0));
499 ASSERT_EQ(true, SetDictKeyValue(&response, "fd", fd));
501 Expect(expected, response);
504 virtual void TearDown() {
505 JsFsTest::TearDown();
508 void OpenNode() {
509 EXPECT_EQ(0, fs_->Open(Path("/foo"), O_RDONLY, &node_));
510 EXPECT_EQ(fd, sdk_util::static_scoped_ref_cast<JsFsNode>(node_)->fd());
513 protected:
514 ScopedNode node_;
517 const int JsFsNodeTest::fd = 123;
519 } // namespace
521 TEST_F(JsFsTest, Open) {
522 PP_Var expected;
523 ASSERT_EQ(true, CreateDict(&expected));
524 ASSERT_EQ(true, SetDictKeyValue(&expected, "id", 1));
525 ASSERT_EQ(true, SetDictKeyValue(&expected, "cmd", "open"));
526 ASSERT_EQ(true, SetDictKeyValue(&expected, "path", "/foo"));
527 ASSERT_EQ(true, SetDictKeyValue(&expected, "oflag", O_RDONLY));
529 PP_Var response;
530 ASSERT_EQ(true, CreateDict(&response));
531 ASSERT_EQ(true, SetDictKeyValue(&response, "id", 1));
532 ASSERT_EQ(true, SetDictKeyValue(&response, "error", 0));
533 ASSERT_EQ(true, SetDictKeyValue(&response, "fd", 123));
535 Expect(expected, response);
536 StartJsThread();
538 ScopedNode node;
539 EXPECT_EQ(0, fs_->Open(Path("/foo"), O_RDONLY, &node));
540 EXPECT_EQ(123, sdk_util::static_scoped_ref_cast<JsFsNode>(node)->fd());
543 TEST_F(JsFsTest, Unlink) {
544 PP_Var expected;
545 ASSERT_EQ(true, CreateDict(&expected));
546 ASSERT_EQ(true, SetDictKeyValue(&expected, "id", 1));
547 ASSERT_EQ(true, SetDictKeyValue(&expected, "cmd", "unlink"));
548 ASSERT_EQ(true, SetDictKeyValue(&expected, "path", "/foo"));
550 PP_Var response;
551 ASSERT_EQ(true, CreateDict(&response));
552 ASSERT_EQ(true, SetDictKeyValue(&response, "id", 1));
553 ASSERT_EQ(true, SetDictKeyValue(&response, "error", 0));
555 Expect(expected, response);
556 StartJsThread();
558 EXPECT_EQ(0, fs_->Unlink(Path("/foo")));
561 TEST_F(JsFsTest, Mkdir) {
562 PP_Var expected;
563 ASSERT_EQ(true, CreateDict(&expected));
564 ASSERT_EQ(true, SetDictKeyValue(&expected, "id", 1));
565 ASSERT_EQ(true, SetDictKeyValue(&expected, "cmd", "mkdir"));
566 ASSERT_EQ(true, SetDictKeyValue(&expected, "path", "/foo"));
567 ASSERT_EQ(true, SetDictKeyValue(&expected, "mode", 0644));
569 PP_Var response;
570 ASSERT_EQ(true, CreateDict(&response));
571 ASSERT_EQ(true, SetDictKeyValue(&response, "id", 1));
572 ASSERT_EQ(true, SetDictKeyValue(&response, "error", 0));
574 Expect(expected, response);
575 StartJsThread();
577 EXPECT_EQ(0, fs_->Mkdir(Path("/foo"), 0644));
580 TEST_F(JsFsTest, Rmdir) {
581 PP_Var expected;
582 ASSERT_EQ(true, CreateDict(&expected));
583 ASSERT_EQ(true, SetDictKeyValue(&expected, "id", 1));
584 ASSERT_EQ(true, SetDictKeyValue(&expected, "cmd", "rmdir"));
585 ASSERT_EQ(true, SetDictKeyValue(&expected, "path", "/foo"));
587 PP_Var response;
588 ASSERT_EQ(true, CreateDict(&response));
589 ASSERT_EQ(true, SetDictKeyValue(&response, "id", 1));
590 ASSERT_EQ(true, SetDictKeyValue(&response, "error", 0));
592 Expect(expected, response);
593 StartJsThread();
595 EXPECT_EQ(0, fs_->Rmdir(Path("/foo")));
598 TEST_F(JsFsTest, Remove) {
599 PP_Var expected;
600 ASSERT_EQ(true, CreateDict(&expected));
601 ASSERT_EQ(true, SetDictKeyValue(&expected, "id", 1));
602 ASSERT_EQ(true, SetDictKeyValue(&expected, "cmd", "remove"));
603 ASSERT_EQ(true, SetDictKeyValue(&expected, "path", "/foo"));
605 PP_Var response;
606 ASSERT_EQ(true, CreateDict(&response));
607 ASSERT_EQ(true, SetDictKeyValue(&response, "id", 1));
608 ASSERT_EQ(true, SetDictKeyValue(&response, "error", 0));
610 Expect(expected, response);
611 StartJsThread();
613 EXPECT_EQ(0, fs_->Remove(Path("/foo")));
616 TEST_F(JsFsTest, Rename) {
617 PP_Var expected;
618 ASSERT_EQ(true, CreateDict(&expected));
619 ASSERT_EQ(true, SetDictKeyValue(&expected, "id", 1));
620 ASSERT_EQ(true, SetDictKeyValue(&expected, "cmd", "rename"));
621 ASSERT_EQ(true, SetDictKeyValue(&expected, "old", "/foo"));
622 ASSERT_EQ(true, SetDictKeyValue(&expected, "new", "/bar"));
624 PP_Var response;
625 ASSERT_EQ(true, CreateDict(&response));
626 ASSERT_EQ(true, SetDictKeyValue(&response, "id", 1));
627 ASSERT_EQ(true, SetDictKeyValue(&response, "error", 0));
629 Expect(expected, response);
630 StartJsThread();
632 EXPECT_EQ(0, fs_->Rename(Path("/foo"), Path("/bar")));
635 TEST_F(JsFsNodeTest, GetStat) {
636 PP_Var expected;
637 ASSERT_EQ(true, CreateDict(&expected));
638 ASSERT_EQ(true, SetDictKeyValue(&expected, "id", 2));
639 ASSERT_EQ(true, SetDictKeyValue(&expected, "cmd", "fstat"));
640 ASSERT_EQ(true, SetDictKeyValue(&expected, "fildes", fd));
642 PP_Var response;
643 ASSERT_EQ(true, CreateDict(&response));
644 ASSERT_EQ(true, SetDictKeyValue(&response, "id", 2));
645 ASSERT_EQ(true, SetDictKeyValue(&response, "error", 0));
646 ASSERT_EQ(true, SetDictKeyValue(&response, "st_ino", (int64_t) 1));
647 ASSERT_EQ(true, SetDictKeyValue(&response, "st_mode", 2));
648 ASSERT_EQ(true, SetDictKeyValue(&response, "st_nlink", 3));
649 ASSERT_EQ(true, SetDictKeyValue(&response, "st_uid", 4));
650 ASSERT_EQ(true, SetDictKeyValue(&response, "st_gid", 5));
651 #ifdef __APPLE__
652 ASSERT_EQ(true, SetDictKeyValue(&response, "st_rdev", (dev_t) 6));
653 ASSERT_EQ(true, SetDictKeyValue(&response, "st_size", (off_t) 7));
654 #else
655 ASSERT_EQ(true, SetDictKeyValue(&response, "st_rdev", (int64_t) 6));
656 ASSERT_EQ(true, SetDictKeyValue(&response, "st_size", (int64_t) 7));
657 #endif
658 ASSERT_EQ(true, SetDictKeyValue(&response, "st_blksize", 8));
659 ASSERT_EQ(true, SetDictKeyValue(&response, "st_blocks", 9));
660 ASSERT_EQ(true, SetDictKeyValue(&response, "st_atime", (int64_t) 10));
661 ASSERT_EQ(true, SetDictKeyValue(&response, "st_mtime", (int64_t) 11));
662 ASSERT_EQ(true, SetDictKeyValue(&response, "st_ctime", (int64_t) 12));
664 Expect(expected, response);
665 StartJsThread();
666 OpenNode();
668 struct stat statbuf;
669 EXPECT_EQ(0, node_->GetStat(&statbuf));
670 EXPECT_EQ(fs_->dev(), statbuf.st_dev);
671 EXPECT_EQ(1, statbuf.st_ino);
672 EXPECT_EQ(2, statbuf.st_mode);
673 EXPECT_EQ(3, statbuf.st_nlink);
674 EXPECT_EQ(4, statbuf.st_uid);
675 EXPECT_EQ(5, statbuf.st_gid);
676 EXPECT_EQ(6, statbuf.st_rdev);
677 EXPECT_EQ(7, statbuf.st_size);
678 EXPECT_EQ(8, statbuf.st_blksize);
679 EXPECT_EQ(9, statbuf.st_blocks);
680 EXPECT_EQ(10, statbuf.st_atime);
681 EXPECT_EQ(11, statbuf.st_mtime);
682 EXPECT_EQ(12, statbuf.st_ctime);
685 TEST_F(JsFsNodeTest, FSync) {
686 PP_Var expected;
687 ASSERT_EQ(true, CreateDict(&expected));
688 ASSERT_EQ(true, SetDictKeyValue(&expected, "id", 2));
689 ASSERT_EQ(true, SetDictKeyValue(&expected, "cmd", "fsync"));
690 ASSERT_EQ(true, SetDictKeyValue(&expected, "fildes", fd));
692 PP_Var response;
693 ASSERT_EQ(true, CreateDict(&response));
694 ASSERT_EQ(true, SetDictKeyValue(&response, "id", 2));
695 ASSERT_EQ(true, SetDictKeyValue(&response, "error", 0));
697 Expect(expected, response);
698 StartJsThread();
699 OpenNode();
701 EXPECT_EQ(0, node_->FSync());
704 TEST_F(JsFsNodeTest, FTruncate) {
705 PP_Var expected;
706 ASSERT_EQ(true, CreateDict(&expected));
707 ASSERT_EQ(true, SetDictKeyValue(&expected, "id", 2));
708 ASSERT_EQ(true, SetDictKeyValue(&expected, "cmd", "ftruncate"));
709 ASSERT_EQ(true, SetDictKeyValue(&expected, "fildes", fd));
710 ASSERT_EQ(true, SetDictKeyValue(&expected, "length", 0));
712 PP_Var response;
713 ASSERT_EQ(true, CreateDict(&response));
714 ASSERT_EQ(true, SetDictKeyValue(&response, "id", 2));
715 ASSERT_EQ(true, SetDictKeyValue(&response, "error", 0));
717 Expect(expected, response);
718 StartJsThread();
719 OpenNode();
721 EXPECT_EQ(0, node_->FTruncate(0));
724 TEST_F(JsFsNodeTest, Read) {
725 const size_t kReadLength = 100;
727 PP_Var expected;
728 ASSERT_EQ(true, CreateDict(&expected));
729 ASSERT_EQ(true, SetDictKeyValue(&expected, "id", 2));
730 ASSERT_EQ(true, SetDictKeyValue(&expected, "cmd", "pread"));
731 ASSERT_EQ(true, SetDictKeyValue(&expected, "fildes", fd));
732 ASSERT_EQ(true,
733 SetDictKeyValue(&expected, "nbyte", static_cast<int>(kReadLength)));
734 ASSERT_EQ(true, SetDictKeyValue(&expected, "offset", 200));
736 PP_Var response;
737 ASSERT_EQ(true, CreateDict(&response));
738 ASSERT_EQ(true, SetDictKeyValue(&response, "id", 2));
739 ASSERT_EQ(true, SetDictKeyValue(&response, "error", 0));
740 ASSERT_EQ(
741 true,
742 SetDictKeyValue(&response, "buf", CreateDummyArrayBuffer(kReadLength)));
744 Expect(expected, response);
745 StartJsThread();
746 OpenNode();
748 HandleAttr attr;
749 attr.offs = 200;
750 uint8_t buf[kReadLength];
751 int bytes_read;
752 EXPECT_EQ(0, node_->Read(attr, buf, kReadLength, &bytes_read));
753 EXPECT_EQ(kReadLength, bytes_read);
754 EXPECT_TRUE(EqualsDummyArrayBuffer(buf, kReadLength));
757 TEST_F(JsFsNodeTest, Write) {
758 const size_t kWriteLength = 100;
760 PP_Var expected;
761 ASSERT_EQ(true, CreateDict(&expected));
762 ASSERT_EQ(true, SetDictKeyValue(&expected, "id", 2));
763 ASSERT_EQ(true, SetDictKeyValue(&expected, "cmd", "pwrite"));
764 ASSERT_EQ(true, SetDictKeyValue(&expected, "fildes", fd));
765 ASSERT_EQ(
766 true,
767 SetDictKeyValue(&expected, "buf", CreateDummyArrayBuffer(kWriteLength)));
768 ASSERT_EQ(
769 true,
770 SetDictKeyValue(&expected, "nbyte", static_cast<int>(kWriteLength)));
771 ASSERT_EQ(true, SetDictKeyValue(&expected, "offset", 200));
773 PP_Var response;
774 ASSERT_EQ(true, CreateDict(&response));
775 ASSERT_EQ(true, SetDictKeyValue(&response, "id", 2));
776 ASSERT_EQ(true, SetDictKeyValue(&response, "error", 0));
777 ASSERT_EQ(true, SetDictKeyValue(&response, "nwrote", kWriteLength));
779 Expect(expected, response);
780 StartJsThread();
781 OpenNode();
783 HandleAttr attr;
784 attr.offs = 200;
786 uint8_t buf[kWriteLength];
787 FillDummyBuffer(buf, kWriteLength);
789 int bytes_written;
790 EXPECT_EQ(0, node_->Write(attr, buf, kWriteLength, &bytes_written));
791 EXPECT_EQ(kWriteLength, bytes_written);
794 TEST_F(JsFsNodeTest, GetDents) {
795 PP_Var expected;
796 ASSERT_EQ(true, CreateDict(&expected));
797 ASSERT_EQ(true, SetDictKeyValue(&expected, "id", 2));
798 ASSERT_EQ(true, SetDictKeyValue(&expected, "cmd", "getdents"));
799 ASSERT_EQ(true, SetDictKeyValue(&expected, "fildes", fd));
800 ASSERT_EQ(true, SetDictKeyValue(&expected, "offs", 0));
801 ASSERT_EQ(true, SetDictKeyValue(&expected, "count", 2));
803 PP_Var entry0;
804 ASSERT_EQ(true, CreateDict(&entry0));
805 ASSERT_EQ(true, SetDictKeyValue(&entry0, "d_ino", 2));
806 ASSERT_EQ(true, SetDictKeyValue(&entry0, "d_name", "."));
807 PP_Var entry1;
808 ASSERT_EQ(true, CreateDict(&entry1));
809 ASSERT_EQ(true, SetDictKeyValue(&entry1, "d_ino", 3));
810 ASSERT_EQ(true, SetDictKeyValue(&entry1, "d_name", ".."));
811 PP_Var array;
812 ASSERT_EQ(true, CreateArray(&array));
813 ASSERT_EQ(true, SetArrayValue(&array, 0, entry0));
814 ASSERT_EQ(true, SetArrayValue(&array, 1, entry1));
815 PP_Var response;
816 ASSERT_EQ(true, CreateDict(&response));
817 ASSERT_EQ(true, SetDictKeyValue(&response, "id", 2));
818 ASSERT_EQ(true, SetDictKeyValue(&response, "error", 0));
819 ASSERT_EQ(true, SetDictKeyValue(&response, "dirents", array));
821 Expect(expected, response);
822 StartJsThread();
823 OpenNode();
825 dirent buf[2];
826 int bytes_written;
827 EXPECT_EQ(0, node_->GetDents(0, buf, sizeof(dirent) * 2, &bytes_written));
828 EXPECT_EQ(sizeof(dirent) * 2, bytes_written);
829 EXPECT_EQ(2, buf[0].d_ino);
830 EXPECT_EQ(sizeof(dirent), buf[0].d_reclen);
831 EXPECT_STREQ(".", buf[0].d_name);
832 EXPECT_EQ(3, buf[1].d_ino);
833 EXPECT_EQ(sizeof(dirent), buf[1].d_reclen);
834 EXPECT_STREQ("..", buf[1].d_name);