| Index: native_client_sdk/src/libraries/nacl_io_test/mount_html5fs_test.cc
|
| diff --git a/native_client_sdk/src/libraries/nacl_io_test/mount_html5fs_test.cc b/native_client_sdk/src/libraries/nacl_io_test/mount_html5fs_test.cc
|
| index d6a15308d792c862f802a40861c8696895c6cc74..5b5d19668cc4c8ce27aea5a9c8bdbe50a04f172c 100644
|
| --- a/native_client_sdk/src/libraries/nacl_io_test/mount_html5fs_test.cc
|
| +++ b/native_client_sdk/src/libraries/nacl_io_test/mount_html5fs_test.cc
|
| @@ -9,6 +9,9 @@
|
| #include <ppapi/c/ppb_file_io.h>
|
| #include <ppapi/c/pp_errors.h>
|
| #include <ppapi/c/pp_instance.h>
|
| +#if defined(WIN32)
|
| +#include <windows.h> // For Sleep()
|
| +#endif
|
|
|
| #include "mock_util.h"
|
| #include "nacl_io/mount_html5fs.h"
|
| @@ -19,6 +22,7 @@ using ::testing::_;
|
| using ::testing::DoAll;
|
| using ::testing::Invoke;
|
| using ::testing::Return;
|
| +using ::testing::SaveArg;
|
| using ::testing::SetArgPointee;
|
| using ::testing::StrEq;
|
| using ::testing::WithArgs;
|
| @@ -40,32 +44,44 @@ class MountHtml5FsTest : public ::testing::Test {
|
| public:
|
| MountHtml5FsTest();
|
| ~MountHtml5FsTest();
|
| - void SetUpFilesystem(PP_FileSystemType, int);
|
| + void SetUpFilesystemExpectations(PP_FileSystemType, int,
|
| + bool async_callback=false);
|
|
|
| protected:
|
| PepperInterfaceMock* ppapi_;
|
| + PP_CompletionCallback open_filesystem_callback_;
|
|
|
| static const PP_Instance instance_ = 123;
|
| static const PP_Resource filesystem_resource_ = 234;
|
| };
|
|
|
| MountHtml5FsTest::MountHtml5FsTest()
|
| - : ppapi_(NULL) {
|
| + : ppapi_(new PepperInterfaceMock(instance_)) {
|
| }
|
|
|
| MountHtml5FsTest::~MountHtml5FsTest() {
|
| delete ppapi_;
|
| }
|
|
|
| -void MountHtml5FsTest::SetUpFilesystem(PP_FileSystemType fstype,
|
| - int expected_size) {
|
| - ppapi_ = new PepperInterfaceMock(instance_);
|
| +void MountHtml5FsTest::SetUpFilesystemExpectations(
|
| + PP_FileSystemType fstype,
|
| + int expected_size,
|
| + bool async_callback) {
|
| FileSystemInterfaceMock* filesystem = ppapi_->GetFileSystemInterface();
|
| EXPECT_CALL(*filesystem, Create(instance_, fstype))
|
| .Times(1)
|
| .WillOnce(Return(filesystem_resource_));
|
| - EXPECT_CALL(*filesystem, Open(filesystem_resource_, expected_size, _))
|
| - .WillOnce(CallCallback<2>(int32_t(PP_OK)));
|
| +
|
| + if (async_callback) {
|
| + EXPECT_CALL(*filesystem, Open(filesystem_resource_, expected_size, _))
|
| + .WillOnce(DoAll(SaveArg<2>(&open_filesystem_callback_),
|
| + Return(int32_t(PP_OK))));
|
| + EXPECT_CALL(*ppapi_, IsMainThread()).WillOnce(Return(PP_TRUE));
|
| + } else {
|
| + EXPECT_CALL(*filesystem, Open(filesystem_resource_, expected_size, _))
|
| + .WillOnce(CallCallback<2>(int32_t(PP_OK)));
|
| + EXPECT_CALL(*ppapi_, IsMainThread()).WillOnce(Return(PP_FALSE));
|
| + }
|
|
|
| EXPECT_CALL(*ppapi_, ReleaseResource(filesystem_resource_));
|
| }
|
| @@ -76,6 +92,10 @@ class MountHtml5FsNodeTest : public MountHtml5FsTest {
|
| virtual void SetUp();
|
| virtual void TearDown();
|
|
|
| + void SetUpNodeExpectations();
|
| + void InitFilesystem();
|
| + void InitNode();
|
| +
|
| protected:
|
| MountHtml5FsMock* mnt_;
|
| MountNode* node_;
|
| @@ -99,13 +119,18 @@ MountHtml5FsNodeTest::MountHtml5FsNodeTest()
|
| }
|
|
|
| void MountHtml5FsNodeTest::SetUp() {
|
| - SetUpFilesystem(PP_FILESYSTEMTYPE_LOCALPERSISTENT, 0);
|
| - StringMap_t map;
|
| - mnt_ = new MountHtml5FsMock(map, ppapi_);
|
| -
|
| fileref_ = ppapi_->GetFileRefInterface();
|
| fileio_ = ppapi_->GetFileIoInterface();
|
| +}
|
| +
|
| +void MountHtml5FsNodeTest::TearDown() {
|
| + if (mnt_) {
|
| + mnt_->ReleaseNode(node_);
|
| + delete mnt_;
|
| + }
|
| +}
|
|
|
| +void MountHtml5FsNodeTest::SetUpNodeExpectations() {
|
| // Open.
|
| EXPECT_CALL(*fileref_, Create(filesystem_resource_, StrEq(&path_[0])))
|
| .WillOnce(Return(fileref_resource_));
|
| @@ -121,14 +146,31 @@ void MountHtml5FsNodeTest::SetUp() {
|
| EXPECT_CALL(*ppapi_, ReleaseResource(fileref_resource_));
|
| EXPECT_CALL(*ppapi_, ReleaseResource(fileio_resource_));
|
| EXPECT_CALL(*fileio_, Flush(fileio_resource_, _));
|
| +}
|
| +
|
| +void MountHtml5FsNodeTest::InitFilesystem() {
|
| + StringMap_t map;
|
| + mnt_ = new MountHtml5FsMock(map, ppapi_);
|
| +}
|
|
|
| +void MountHtml5FsNodeTest::InitNode() {
|
| node_ = mnt_->Open(Path(path_), O_CREAT | O_RDWR);
|
| ASSERT_NE((MountNode*)NULL, node_);
|
| }
|
|
|
| -void MountHtml5FsNodeTest::TearDown() {
|
| - mnt_->ReleaseNode(node_);
|
| - delete mnt_;
|
| +// Node test where the filesystem is opened synchronously; that is, the
|
| +// creation of the mount blocks until the filesystem is ready.
|
| +class MountHtml5FsNodeSyncTest : public MountHtml5FsNodeTest {
|
| + public:
|
| + virtual void SetUp();
|
| +};
|
| +
|
| +void MountHtml5FsNodeSyncTest::SetUp() {
|
| + MountHtml5FsNodeTest::SetUp();
|
| + SetUpFilesystemExpectations(PP_FILESYSTEMTYPE_LOCALPERSISTENT, 0);
|
| + InitFilesystem();
|
| + SetUpNodeExpectations();
|
| + InitNode();
|
| }
|
|
|
| void ReadEntriesAction(const PP_ArrayOutput& output) {
|
| @@ -146,11 +188,101 @@ void ReadEntriesAction(const PP_ArrayOutput& output) {
|
| memcpy(dest, &entries[0], sizeof(PP_DirectoryEntry_Dev) * 2);
|
| }
|
|
|
| +class MountHtml5FsNodeAsyncTest : public MountHtml5FsNodeTest {
|
| + public:
|
| + virtual void SetUp();
|
| + virtual void TearDown();
|
| +
|
| + private:
|
| + static void* ThreadThunk(void* param);
|
| + void Thread();
|
| +
|
| + enum {
|
| + STATE_INIT,
|
| + STATE_INIT_NODE,
|
| + STATE_INIT_NODE_FINISHED,
|
| + } state_;
|
| +
|
| + pthread_t thread_;
|
| + pthread_cond_t cond_;
|
| + pthread_mutex_t mutex_;
|
| +};
|
| +
|
| +void MountHtml5FsNodeAsyncTest::SetUp() {
|
| + MountHtml5FsNodeTest::SetUp();
|
| +
|
| + state_ = STATE_INIT;
|
| +
|
| + pthread_create(&thread_, NULL, &MountHtml5FsNodeAsyncTest::ThreadThunk, this);
|
| + pthread_mutex_init(&mutex_, NULL);
|
| + pthread_cond_init(&cond_, NULL);
|
| +
|
| + // This test shows that even if the filesystem open callback happens after an
|
| + // attempt to open a node, it still works (opening the node blocks until the
|
| + // filesystem is ready).
|
| + // true => asynchronous filesystem open.
|
| + SetUpFilesystemExpectations(PP_FILESYSTEMTYPE_LOCALPERSISTENT, 0, true);
|
| + InitFilesystem();
|
| + SetUpNodeExpectations();
|
| +
|
| + // Signal the other thread to try opening a Node.
|
| + pthread_mutex_lock(&mutex_);
|
| + state_ = STATE_INIT_NODE;
|
| + pthread_cond_signal(&cond_);
|
| + pthread_mutex_unlock(&mutex_);
|
| +
|
| + // Wait for a bit...
|
| + // TODO(binji): this will be flaky. How to test this better?
|
| +#if defined(WIN32)
|
| + Sleep(500); // milliseconds
|
| +#else
|
| + usleep(500*1000); // microseconds
|
| +#endif
|
| +
|
| + // Call the filesystem open callback.
|
| + (*open_filesystem_callback_.func)(open_filesystem_callback_.user_data, PP_OK);
|
| +
|
| + // Wait for the other thread to unblock and signal us.
|
| + pthread_mutex_lock(&mutex_);
|
| + while (state_ != STATE_INIT_NODE_FINISHED)
|
| + pthread_cond_wait(&cond_, &mutex_);
|
| + pthread_mutex_unlock(&mutex_);
|
| +}
|
| +
|
| +void MountHtml5FsNodeAsyncTest::TearDown() {
|
| + pthread_cond_destroy(&cond_);
|
| + pthread_mutex_destroy(&mutex_);
|
| +
|
| + MountHtml5FsNodeTest::TearDown();
|
| +}
|
| +
|
| +void* MountHtml5FsNodeAsyncTest::ThreadThunk(void* param) {
|
| + static_cast<MountHtml5FsNodeAsyncTest*>(param)->Thread();
|
| + return NULL;
|
| +}
|
| +
|
| +void MountHtml5FsNodeAsyncTest::Thread() {
|
| + // Wait for the "main" thread to tell us to open the Node.
|
| + pthread_mutex_lock(&mutex_);
|
| + while (state_ != STATE_INIT_NODE)
|
| + pthread_cond_wait(&cond_, &mutex_);
|
| + pthread_mutex_unlock(&mutex_);
|
| +
|
| + // Opening the node blocks until the filesystem is open...
|
| + InitNode();
|
| +
|
| + // Signal the "main" thread to tell it we're unblocked.
|
| + pthread_mutex_lock(&mutex_);
|
| + state_ = STATE_INIT_NODE_FINISHED;
|
| + pthread_cond_signal(&cond_);
|
| + pthread_mutex_unlock(&mutex_);
|
| +}
|
| +
|
| } // namespace
|
|
|
|
|
| TEST_F(MountHtml5FsTest, FilesystemType) {
|
| - SetUpFilesystem(PP_FILESYSTEMTYPE_LOCALPERSISTENT, 100);
|
| + SetUpFilesystemExpectations(PP_FILESYSTEMTYPE_LOCALPERSISTENT, 100);
|
|
|
| StringMap_t map;
|
| map["type"] = "PERSISTENT";
|
| @@ -163,7 +295,7 @@ TEST_F(MountHtml5FsTest, Mkdir) {
|
| const PP_Resource fileref_resource = 235;
|
|
|
| // These are the default values.
|
| - SetUpFilesystem(PP_FILESYSTEMTYPE_LOCALPERSISTENT, 0);
|
| + SetUpFilesystemExpectations(PP_FILESYSTEMTYPE_LOCALPERSISTENT, 0);
|
|
|
| FileRefInterfaceMock* fileref = ppapi_->GetFileRefInterface();
|
|
|
| @@ -186,7 +318,7 @@ TEST_F(MountHtml5FsTest, Remove) {
|
| const PP_Resource fileref_resource = 235;
|
|
|
| // These are the default values.
|
| - SetUpFilesystem(PP_FILESYSTEMTYPE_LOCALPERSISTENT, 0);
|
| + SetUpFilesystemExpectations(PP_FILESYSTEMTYPE_LOCALPERSISTENT, 0);
|
|
|
| FileRefInterfaceMock* fileref = ppapi_->GetFileRefInterface();
|
|
|
| @@ -203,10 +335,13 @@ TEST_F(MountHtml5FsTest, Remove) {
|
| ASSERT_EQ(0, result);
|
| }
|
|
|
| -TEST_F(MountHtml5FsNodeTest, OpenAndClose) {
|
| +TEST_F(MountHtml5FsNodeAsyncTest, AsyncFilesystemOpen) {
|
| +}
|
| +
|
| +TEST_F(MountHtml5FsNodeSyncTest, OpenAndClose) {
|
| }
|
|
|
| -TEST_F(MountHtml5FsNodeTest, Write) {
|
| +TEST_F(MountHtml5FsNodeSyncTest, Write) {
|
| const int offset = 10;
|
| const int count = 20;
|
| const char buffer[30] = {0};
|
| @@ -218,7 +353,7 @@ TEST_F(MountHtml5FsNodeTest, Write) {
|
| EXPECT_EQ(count, result);
|
| }
|
|
|
| -TEST_F(MountHtml5FsNodeTest, Read) {
|
| +TEST_F(MountHtml5FsNodeSyncTest, Read) {
|
| const int offset = 10;
|
| const int count = 20;
|
| char buffer[30] = {0};
|
| @@ -230,7 +365,7 @@ TEST_F(MountHtml5FsNodeTest, Read) {
|
| EXPECT_EQ(count, result);
|
| }
|
|
|
| -TEST_F(MountHtml5FsNodeTest, GetStat) {
|
| +TEST_F(MountHtml5FsNodeSyncTest, GetStat) {
|
| const int size = 123;
|
| const int creation_time = 1000;
|
| const int access_time = 2000;
|
| @@ -259,7 +394,7 @@ TEST_F(MountHtml5FsNodeTest, GetStat) {
|
| EXPECT_EQ(creation_time, statbuf.st_ctime);
|
| }
|
|
|
| -TEST_F(MountHtml5FsNodeTest, Truncate) {
|
| +TEST_F(MountHtml5FsNodeSyncTest, Truncate) {
|
| const int size = 123;
|
| EXPECT_CALL(*fileio_, SetLength(fileio_resource_, size, _))
|
| .WillOnce(Return(int32_t(PP_OK)));
|
| @@ -268,7 +403,7 @@ TEST_F(MountHtml5FsNodeTest, Truncate) {
|
| EXPECT_EQ(0, result);
|
| }
|
|
|
| -TEST_F(MountHtml5FsNodeTest, GetDents) {
|
| +TEST_F(MountHtml5FsNodeSyncTest, GetDents) {
|
| const int dir_reader_resource = 237;
|
| const int fileref_resource_1 = 238;
|
| const int fileref_resource_2 = 239;
|
|
|