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.
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
;
35 class JsFsForTesting
: public JsFs
{
37 JsFsForTesting(PepperInterface
* ppapi
) {
40 Error error
= Init(args
);
45 class FakeMessagingInterfaceJsFs
: public MessagingInterface
{
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
);
58 ASSERT_FALSE(has_message_
);
62 pthread_cond_signal(&cond_
);
65 PP_Var
WaitForMessage() {
67 while (!has_message_
) {
68 pthread_cond_wait(&cond_
, lock_
.mutex());
76 VarInterface
* var_interface_
;
83 class FakePepperInterfaceJsFs
: public FakePepperInterface
{
85 FakePepperInterfaceJsFs() : messaging_interface_(GetVarInterface()) {}
87 virtual nacl_io::MessagingInterface
* GetMessagingInterface() {
88 return &messaging_interface_
;
92 FakeMessagingInterfaceJsFs messaging_interface_
;
95 class JsFsTest
: public ::testing::Test
{
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;
106 if (js_thread_started_
)
107 pthread_join(js_thread_
, NULL
);
109 for (RequestResponses::iterator it
= request_responses_
.begin(),
110 end
= request_responses_
.end();
113 ppapi_
.GetVarInterface()->Release(it
->request
);
114 ppapi_
.GetVarInterface()->Release(it
->response
);
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();
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();
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
);
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
) {
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();
240 case PP_VARTYPE_UNDEFINED
:
242 case PP_VARTYPE_NULL
:
244 case PP_VARTYPE_BOOL
:
245 return var
.value
.as_bool
? "true" : "false";
246 case PP_VARTYPE_INT32
: {
248 snprintf(buffer
, 32, "%d", var
.value
.as_int
);
251 case PP_VARTYPE_DOUBLE
: {
253 snprintf(buffer
, 32, "%g", var
.value
.as_double
);
256 case PP_VARTYPE_STRING
: {
258 const char* var_str
= var_if
->VarToUtf8(var
, &var_len
);
259 std::string
result("\"");
260 result
+= std::string(var_str
, var_len
);
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)
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
);
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)
295 var_if
->Release(var_keys
);
298 case PP_VARTYPE_ARRAY_BUFFER
: {
300 if (!array_buffer_if
->ByteLength(var
, &var_len
)) {
301 LOG_ERROR("Unable to get byte length of var.");
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
) {
310 snprintf(buffer
, 8, "%d", static_cast<uint8_t*>(var_ptr
)[i
]);
312 if (i
!= var_len
- 1)
316 array_buffer_if
->Unmap(var
);
321 ADD_FAILURE() << "Unexpected var type: " << var
.type
;
326 bool VarsAreEqual(PP_Var expected
, PP_Var var
) {
327 if (expected
.type
!= var
.type
)
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();
337 case PP_VARTYPE_UNDEFINED
:
338 case PP_VARTYPE_NULL
:
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
: {
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
)
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
)
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
);
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
);
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
);
405 var_if
->Release(var_keys
);
406 var_if
->Release(expected_keys
);
409 case PP_VARTYPE_ARRAY_BUFFER
: {
411 if (!array_buffer_if
->ByteLength(var
, &var_len
))
414 uint32_t expected_len
;
415 if (!array_buffer_if
->ByteLength(expected
, &expected_len
))
418 if (expected_len
!= var_len
)
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
);
431 ADD_FAILURE() << "Unexpected var type: " << var
.type
;
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
);
446 void FillDummyBuffer(uint8_t* buf
, size_t buf_len
) {
447 for (uint32_t i
= 0; i
< buf_len
; ++i
) {
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.",
466 FakePepperInterfaceJsFs ppapi_
;
467 ScopedRef
<JsFsForTesting
> fs_
;
469 pthread_t js_thread_
;
470 bool js_thread_started_
;
472 struct RequestResponse
{
477 typedef std::vector
<RequestResponse
> RequestResponses
;
478 RequestResponses request_responses_
;
481 class JsFsNodeTest
: public JsFsTest
{
485 virtual void SetUp() {
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
));
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();
509 EXPECT_EQ(0, fs_
->Open(Path("/foo"), O_RDONLY
, &node_
));
510 EXPECT_EQ(fd
, sdk_util::static_scoped_ref_cast
<JsFsNode
>(node_
)->fd());
517 const int JsFsNodeTest::fd
= 123;
521 TEST_F(JsFsTest
, Open
) {
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
));
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
);
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
) {
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"));
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
);
558 EXPECT_EQ(0, fs_
->Unlink(Path("/foo")));
561 TEST_F(JsFsTest
, Mkdir
) {
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));
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
);
577 EXPECT_EQ(0, fs_
->Mkdir(Path("/foo"), 0644));
580 TEST_F(JsFsTest
, Rmdir
) {
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"));
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
);
595 EXPECT_EQ(0, fs_
->Rmdir(Path("/foo")));
598 TEST_F(JsFsTest
, Remove
) {
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"));
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
);
613 EXPECT_EQ(0, fs_
->Remove(Path("/foo")));
616 TEST_F(JsFsTest
, Rename
) {
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"));
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
);
632 EXPECT_EQ(0, fs_
->Rename(Path("/foo"), Path("/bar")));
635 TEST_F(JsFsNodeTest
, GetStat
) {
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
));
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));
652 ASSERT_EQ(true, SetDictKeyValue(&response
, "st_rdev", (dev_t
) 6));
653 ASSERT_EQ(true, SetDictKeyValue(&response
, "st_size", (off_t
) 7));
655 ASSERT_EQ(true, SetDictKeyValue(&response
, "st_rdev", (int64_t) 6));
656 ASSERT_EQ(true, SetDictKeyValue(&response
, "st_size", (int64_t) 7));
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
);
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
) {
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
));
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
);
701 EXPECT_EQ(0, node_
->FSync());
704 TEST_F(JsFsNodeTest
, FTruncate
) {
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));
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
);
721 EXPECT_EQ(0, node_
->FTruncate(0));
724 TEST_F(JsFsNodeTest
, Read
) {
725 const size_t kReadLength
= 100;
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
));
733 SetDictKeyValue(&expected
, "nbyte", static_cast<int>(kReadLength
)));
734 ASSERT_EQ(true, SetDictKeyValue(&expected
, "offset", 200));
737 ASSERT_EQ(true, CreateDict(&response
));
738 ASSERT_EQ(true, SetDictKeyValue(&response
, "id", 2));
739 ASSERT_EQ(true, SetDictKeyValue(&response
, "error", 0));
742 SetDictKeyValue(&response
, "buf", CreateDummyArrayBuffer(kReadLength
)));
744 Expect(expected
, response
);
750 uint8_t buf
[kReadLength
];
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;
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
));
767 SetDictKeyValue(&expected
, "buf", CreateDummyArrayBuffer(kWriteLength
)));
770 SetDictKeyValue(&expected
, "nbyte", static_cast<int>(kWriteLength
)));
771 ASSERT_EQ(true, SetDictKeyValue(&expected
, "offset", 200));
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
);
786 uint8_t buf
[kWriteLength
];
787 FillDummyBuffer(buf
, kWriteLength
);
790 EXPECT_EQ(0, node_
->Write(attr
, buf
, kWriteLength
, &bytes_written
));
791 EXPECT_EQ(kWriteLength
, bytes_written
);
794 TEST_F(JsFsNodeTest
, GetDents
) {
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));
804 ASSERT_EQ(true, CreateDict(&entry0
));
805 ASSERT_EQ(true, SetDictKeyValue(&entry0
, "d_ino", 2));
806 ASSERT_EQ(true, SetDictKeyValue(&entry0
, "d_name", "."));
808 ASSERT_EQ(true, CreateDict(&entry1
));
809 ASSERT_EQ(true, SetDictKeyValue(&entry1
, "d_ino", 3));
810 ASSERT_EQ(true, SetDictKeyValue(&entry1
, "d_name", ".."));
812 ASSERT_EQ(true, CreateArray(&array
));
813 ASSERT_EQ(true, SetArrayValue(&array
, 0, entry0
));
814 ASSERT_EQ(true, SetArrayValue(&array
, 1, entry1
));
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
);
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
);