diff options
author | binji@chromium.org <binji@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-07-01 21:56:21 +0000 |
---|---|---|
committer | binji@chromium.org <binji@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-07-01 21:56:21 +0000 |
commit | aaa269340ebd7e630e895afbdc5479fcc97bd0fe (patch) | |
tree | aefc5f17ab3b651374a645897bf08d42582bcecf /native_client_sdk | |
parent | f7ebc11ae5c44a771d470f313aef5f35e6ad888f (diff) | |
download | chromium_src-aaa269340ebd7e630e895afbdc5479fcc97bd0fe.zip chromium_src-aaa269340ebd7e630e895afbdc5479fcc97bd0fe.tar.gz chromium_src-aaa269340ebd7e630e895afbdc5479fcc97bd0fe.tar.bz2 |
[NaCl SDK] nacl_io: Add test for write/read fix.
I've also changed the MountFactory used by the KernelProxy into an object
instead of a function. This makes it easier to replace in tests.
I've also added MountMock and MountNodeMock which are gmock wrappers for Mount
and MountNode, respectively.
BUG=254675
R=noelallen@chromium.org
Review URL: https://codereview.chromium.org/17955003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@209510 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'native_client_sdk')
23 files changed, 361 insertions, 104 deletions
diff --git a/native_client_sdk/src/build_tools/sdk_files.list b/native_client_sdk/src/build_tools/sdk_files.list index fd6fc1f..ffc959a 100644 --- a/native_client_sdk/src/build_tools/sdk_files.list +++ b/native_client_sdk/src/build_tools/sdk_files.list @@ -265,6 +265,7 @@ include/nacl_io/kernel_wrap.h include/nacl_io/kernel_wrap_real.h include/nacl_io/mount_dev.h include/nacl_io/mount.h +include/nacl_io/mount_factory.h include/nacl_io/mount_html5fs.h include/nacl_io/mount_http.h include/nacl_io/mount_mem.h @@ -288,6 +289,7 @@ include/nacl_io/pepper/define_empty_macros.h include/nacl_io/pepper_interface.h include/nacl_io/pepper/undef_macros.h include/nacl_io/real_pepper_interface.h +include/nacl_io/typed_mount_factory.h include/ppapi/c/dev/deprecated_bool.h include/ppapi/c/dev/ppb_audio_input_dev.h include/ppapi/c/dev/ppb_buffer_dev.h diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc b/native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc index bc62c37..8d5655a 100644 --- a/native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc +++ b/native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc @@ -25,6 +25,7 @@ #include "nacl_io/osstat.h" #include "nacl_io/path.h" #include "nacl_io/pepper_interface.h" +#include "nacl_io/typed_mount_factory.h" #include "sdk_util/auto_lock.h" #include "sdk_util/ref_object.h" @@ -38,18 +39,27 @@ KernelProxy::KernelProxy() : dev_(0), ppapi_(NULL) {} -KernelProxy::~KernelProxy() { delete ppapi_; } +KernelProxy::~KernelProxy() { + // Clean up the MountFactories. + for (MountFactoryMap_t::iterator i = factories_.begin(); + i != factories_.end(); + ++i) { + delete i->second; + } + + delete ppapi_; +} void KernelProxy::Init(PepperInterface* ppapi) { ppapi_ = ppapi; cwd_ = "/"; dev_ = 1; - factories_["memfs"] = MountMem::Create<MountMem>; - factories_["dev"] = MountDev::Create<MountDev>; - factories_["html5fs"] = MountHtml5Fs::Create<MountHtml5Fs>; - factories_["httpfs"] = MountHttp::Create<MountHttp>; - factories_["passthroughfs"] = MountPassthrough::Create<MountPassthrough>; + factories_["memfs"] = new TypedMountFactory<MountMem>; + factories_["dev"] = new TypedMountFactory<MountDev>; + factories_["html5fs"] = new TypedMountFactory<MountHtml5Fs>; + factories_["httpfs"] = new TypedMountFactory<MountHttp>; + factories_["passthroughfs"] = new TypedMountFactory<MountPassthrough>; int result; result = mount("", "/", "passthroughfs", 0, NULL); @@ -91,7 +101,6 @@ int KernelProxy::open(const char* path, int oflags) { return AllocateFD(handle); } - int KernelProxy::close(int fd) { ScopedKernelHandle handle; Error error = AcquireHandle(fd, &handle); @@ -302,7 +311,8 @@ int KernelProxy::mount(const char* source, free(str); } - Error error = factory->second(dev_++, smap, ppapi_, &mounts_[abs_targ]); + Error error = + factory->second->CreateMount(dev_++, smap, ppapi_, &mounts_[abs_targ]); if (error) { errno = error; return -1; diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_proxy.h b/native_client_sdk/src/libraries/nacl_io/kernel_proxy.h index ac3b936..554a75ca 100644 --- a/native_client_sdk/src/libraries/nacl_io/kernel_proxy.h +++ b/native_client_sdk/src/libraries/nacl_io/kernel_proxy.h @@ -5,22 +5,14 @@ #ifndef LIBRARIES_NACL_IO_KERNEL_PROXY_H_ #define LIBRARIES_NACL_IO_KERNEL_PROXY_H_ -#include <ppapi/c/pp_instance.h> -#include <ppapi/c/ppb.h> -#include <pthread.h> #include <map> #include <string> -#include <vector> #include "nacl_io/kernel_object.h" -#include "nacl_io/mount.h" +#include "nacl_io/mount_factory.h" #include "nacl_io/ostypes.h" #include "nacl_io/osutime.h" -#include "nacl_io/path.h" -class KernelHandle; -class Mount; -class MountNode; class PepperInterface; // KernelProxy provide one-to-one mapping for libc kernel calls. Calls to the @@ -30,12 +22,7 @@ class PepperInterface; // other classes should return Error (as defined by nacl_io/error.h). class KernelProxy : protected KernelObject { public: - typedef Error (*MountFactory_t)(int, - StringMap_t&, - PepperInterface*, - ScopedMount*); - typedef std::map<std::string, std::string> StringMap_t; - typedef std::map<std::string, MountFactory_t> MountFactoryMap_t; + typedef std::map<std::string, MountFactory*> MountFactoryMap_t; KernelProxy(); virtual ~KernelProxy(); diff --git a/native_client_sdk/src/libraries/nacl_io/library.dsc b/native_client_sdk/src/libraries/nacl_io/library.dsc index c582991..eef0ac6 100644 --- a/native_client_sdk/src/libraries/nacl_io/library.dsc +++ b/native_client_sdk/src/libraries/nacl_io/library.dsc @@ -48,6 +48,7 @@ "kernel_wrap_real.h", "mount.h", "mount_dev.h", + "mount_factory.h", "mount_html5fs.h", "mount_http.h", "mount_mem.h", @@ -68,6 +69,7 @@ "path.h", "pepper_interface.h", "real_pepper_interface.h", + "typed_mount_factory.h", ], 'DEST': 'include/nacl_io', }, diff --git a/native_client_sdk/src/libraries/nacl_io/mount.h b/native_client_sdk/src/libraries/nacl_io/mount.h index 89f9b88..58cf1a4 100644 --- a/native_client_sdk/src/libraries/nacl_io/mount.h +++ b/native_client_sdk/src/libraries/nacl_io/mount.h @@ -24,7 +24,6 @@ class PepperInterface; typedef ScopedRef<Mount> ScopedMount; typedef std::map<std::string, std::string> StringMap_t; - // NOTE: The KernelProxy is the only class that should be setting errno. All // other classes should return Error (as defined by nacl_io/error.h). class Mount : public RefObject { @@ -41,13 +40,6 @@ class Mount : public RefObject { virtual void Destroy(); public: - template <class M> - // Assumes that |out_mount| is non-NULL. - static Error Create(int dev, - StringMap_t& args, - PepperInterface* ppapi, - ScopedMount* out_mount); - PepperInterface* ppapi() { return ppapi_; } // All paths in functions below are expected to containing a leading "/". @@ -98,20 +90,4 @@ class Mount : public RefObject { DISALLOW_COPY_AND_ASSIGN(Mount); }; -/*static*/ -template <class M> -Error Mount::Create(int dev, - StringMap_t& args, - PepperInterface* ppapi, - ScopedMount* out_mount) { - ScopedMount mnt(new M()); - Error error = mnt->Init(dev, args, ppapi); - if (error) - return error; - - *out_mount = mnt; - return 0; -} - - #endif // LIBRARIES_NACL_IO_MOUNT_H_ diff --git a/native_client_sdk/src/libraries/nacl_io/mount_dev.h b/native_client_sdk/src/libraries/nacl_io/mount_dev.h index 2d57102..5d47838 100644 --- a/native_client_sdk/src/libraries/nacl_io/mount_dev.h +++ b/native_client_sdk/src/libraries/nacl_io/mount_dev.h @@ -6,6 +6,7 @@ #define LIBRARIES_NACL_IO_MOUNT_DEV_H_ #include "nacl_io/mount.h" +#include "nacl_io/typed_mount_factory.h" class MountNode; @@ -26,7 +27,8 @@ class MountDev : public Mount { private: ScopedMountNode root_; - friend class Mount; + friend class TypedMountFactory<MountDev>; + DISALLOW_COPY_AND_ASSIGN(MountDev); }; #endif // LIBRARIES_NACL_IO_MOUNT_DEV_H_ diff --git a/native_client_sdk/src/libraries/nacl_io/mount_factory.h b/native_client_sdk/src/libraries/nacl_io/mount_factory.h new file mode 100644 index 0000000..35f77d7 --- /dev/null +++ b/native_client_sdk/src/libraries/nacl_io/mount_factory.h @@ -0,0 +1,29 @@ +/* Copyright (c) 2013 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +#ifndef LIBRARIES_NACL_IO_MOUNT_FACTORY_H_ +#define LIBRARIES_NACL_IO_MOUNT_FACTORY_H_ + +#include <map> +#include <string> + +#include "nacl_io/error.h" +#include "sdk_util/scoped_ref.h" + +class PepperInterface; +class Mount; + +typedef std::map<std::string, std::string> StringMap_t; + +class MountFactory { + public: + virtual ~MountFactory() {} + virtual Error CreateMount(int dev, + StringMap_t& args, + PepperInterface* ppapi, + ScopedRef<Mount>* out_mount) = 0; +}; + +#endif // LIBRARIES_NACL_IO_MOUNT_FACTORY_H_ + diff --git a/native_client_sdk/src/libraries/nacl_io/mount_html5fs.h b/native_client_sdk/src/libraries/nacl_io/mount_html5fs.h index ff25e53..d2e1b08 100644 --- a/native_client_sdk/src/libraries/nacl_io/mount_html5fs.h +++ b/native_client_sdk/src/libraries/nacl_io/mount_html5fs.h @@ -6,8 +6,10 @@ #define LIBRARIES_NACL_IO_MOUNT_HTML5FS_H_ #include <pthread.h> + #include "nacl_io/mount.h" #include "nacl_io/pepper_interface.h" +#include "nacl_io/typed_mount_factory.h" class MountNode; @@ -39,7 +41,7 @@ class MountHtml5Fs : public Mount { Error filesystem_open_error_; // protected by lock_. pthread_cond_t filesystem_open_cond_; - friend class Mount; + friend class TypedMountFactory<MountHtml5Fs>; }; #endif // LIBRARIES_NACL_IO_MOUNT_HTML5FS_H_ diff --git a/native_client_sdk/src/libraries/nacl_io/mount_http.h b/native_client_sdk/src/libraries/nacl_io/mount_http.h index cf3feb9..e804f37 100644 --- a/native_client_sdk/src/libraries/nacl_io/mount_http.h +++ b/native_client_sdk/src/libraries/nacl_io/mount_http.h @@ -9,10 +9,9 @@ #include <string> #include "nacl_io/mount.h" #include "nacl_io/pepper_interface.h" +#include "nacl_io/typed_mount_factory.h" class MountNode; -class MountNodeDir; -class MountNodeHttp; class MountHttpMock; std::string NormalizeHeaderKey(const std::string& s); @@ -54,7 +53,7 @@ class MountHttp : public Mount { bool cache_stat_; bool cache_content_; - friend class Mount; + friend class TypedMountFactory<MountHttp>; friend class MountNodeHttp; friend class MountHttpMock; }; diff --git a/native_client_sdk/src/libraries/nacl_io/mount_mem.h b/native_client_sdk/src/libraries/nacl_io/mount_mem.h index 523ca4f..9bd679d 100644 --- a/native_client_sdk/src/libraries/nacl_io/mount_mem.h +++ b/native_client_sdk/src/libraries/nacl_io/mount_mem.h @@ -5,10 +5,8 @@ #ifndef LIBRARIES_NACL_IO_MOUNT_MEM_H_ #define LIBRARIES_NACL_IO_MOUNT_MEM_H_ -#include <map> -#include <string> - #include "nacl_io/mount.h" +#include "nacl_io/typed_mount_factory.h" class MountMem : public Mount { protected: @@ -44,7 +42,7 @@ private: ScopedMountNode root_; - friend class Mount; + friend class TypedMountFactory<MountMem>; DISALLOW_COPY_AND_ASSIGN(MountMem); }; diff --git a/native_client_sdk/src/libraries/nacl_io/mount_node.cc b/native_client_sdk/src/libraries/nacl_io/mount_node.cc index ec77b97..424df70 100644 --- a/native_client_sdk/src/libraries/nacl_io/mount_node.cc +++ b/native_client_sdk/src/libraries/nacl_io/mount_node.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2012 The Chromium Authors. All rights reserved. -x * Use of this source code is governed by a BSD-style license that can be + * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "nacl_io/mount_node.h" @@ -48,9 +48,7 @@ void MountNode::Destroy() { Error MountNode::FSync() { return 0; } -Error MountNode::FTruncate(off_t length) { - return EINVAL; -} +Error MountNode::FTruncate(off_t length) { return EINVAL; } Error MountNode::GetDents(size_t offs, struct dirent* pdir, @@ -66,9 +64,7 @@ Error MountNode::GetStat(struct stat* pstat) { return 0; } -Error MountNode::Ioctl(int request, char* arg) { - return EINVAL; -} +Error MountNode::Ioctl(int request, char* arg) { return EINVAL; } Error MountNode::Read(size_t offs, void* buf, size_t count, int* out_bytes) { *out_bytes = 0; @@ -140,25 +136,16 @@ Error MountNode::AddChild(const std::string& name, return ENOTDIR; } -Error MountNode::RemoveChild(const std::string& name) { - return ENOTDIR; -} +Error MountNode::RemoveChild(const std::string& name) { return ENOTDIR; } -Error MountNode::FindChild(const std::string& name, - ScopedMountNode* out_node) { +Error MountNode::FindChild(const std::string& name, ScopedMountNode* out_node) { out_node->reset(NULL); return ENOTDIR; } -int MountNode::ChildCount() { - return 0; -} +int MountNode::ChildCount() { return 0; } -void MountNode::Link() { - stat_.st_nlink++; -} +void MountNode::Link() { stat_.st_nlink++; } -void MountNode::Unlink() { - stat_.st_nlink--; -} +void MountNode::Unlink() { stat_.st_nlink--; } diff --git a/native_client_sdk/src/libraries/nacl_io/mount_node.h b/native_client_sdk/src/libraries/nacl_io/mount_node.h index f790b33..fb0f14f 100644 --- a/native_client_sdk/src/libraries/nacl_io/mount_node.h +++ b/native_client_sdk/src/libraries/nacl_io/mount_node.h @@ -21,7 +21,6 @@ class MountNode; typedef ScopedRef<MountNode> ScopedMountNode; - // NOTE: The KernelProxy is the only class that should be setting errno. All // other classes should return Error (as defined by nacl_io/error.h). class MountNode : public RefObject { @@ -70,7 +69,7 @@ class MountNode : public RefObject { virtual int GetMode(); virtual int GetType(); // Assume that |out_size| is non-NULL. - virtual Error GetSize(size_t *out_size); + virtual Error GetSize(size_t* out_size); virtual bool IsaDir(); virtual bool IsaFile(); virtual bool IsaTTY(); @@ -99,7 +98,7 @@ class MountNode : public RefObject { struct stat stat_; // We use a pointer directly to avoid cycles in the ref count. - // TODO(noelallen) We should change this to it's unnecessary for the node + // TODO(noelallen) We should change this so it's unnecessary for the node // to track it's parent. When a node is unlinked, the mount should do // any cleanup it needs. Mount* mount_; diff --git a/native_client_sdk/src/libraries/nacl_io/mount_passthrough.h b/native_client_sdk/src/libraries/nacl_io/mount_passthrough.h index 7b59b05..4d441a0 100644 --- a/native_client_sdk/src/libraries/nacl_io/mount_passthrough.h +++ b/native_client_sdk/src/libraries/nacl_io/mount_passthrough.h @@ -6,6 +6,7 @@ #define LIBRARIES_NACL_IO_MOUNT_PASSTHROUGH_H_ #include "nacl_io/mount.h" +#include "nacl_io/typed_mount_factory.h" class MountPassthrough : public Mount { protected: @@ -24,8 +25,8 @@ class MountPassthrough : public Mount { virtual Error Remove(const Path& path); private: - friend class Mount; - DISALLOW_COPY_AND_ASSIGN(MountPassthrough); + friend class TypedMountFactory<MountPassthrough>; + DISALLOW_COPY_AND_ASSIGN(MountPassthrough); }; #endif // LIBRARIES_NACL_IO_MOUNT_PASSTHROUGH_H_ diff --git a/native_client_sdk/src/libraries/nacl_io/typed_mount_factory.h b/native_client_sdk/src/libraries/nacl_io/typed_mount_factory.h new file mode 100644 index 0000000..c859b0b --- /dev/null +++ b/native_client_sdk/src/libraries/nacl_io/typed_mount_factory.h @@ -0,0 +1,29 @@ +/* Copyright (c) 2013 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +#ifndef LIBRARIES_NACL_IO_TYPED_MOUNT_FACTORY_H_ +#define LIBRARIES_NACL_IO_TYPED_MOUNT_FACTORY_H_ + +#include "nacl_io/mount.h" +#include "nacl_io/mount_factory.h" + +template <typename T> +class TypedMountFactory : public MountFactory { + public: + virtual Error CreateMount(int dev, + StringMap_t& args, + PepperInterface* ppapi, + ScopedRef<Mount>* out_mount) { + ScopedRef<T> mnt(new T()); + Error error = mnt->Init(dev, args, ppapi); + if (error) + return error; + + *out_mount = mnt; + return 0; + } +}; + +#endif // LIBRARIES_NACL_IO_TYPED_MOUNT_FACTORY_H_ + diff --git a/native_client_sdk/src/libraries/nacl_io_test/example.dsc b/native_client_sdk/src/libraries/nacl_io_test/example.dsc index 63b0ef4..b26cd7c 100644 --- a/native_client_sdk/src/libraries/nacl_io_test/example.dsc +++ b/native_client_sdk/src/libraries/nacl_io_test/example.dsc @@ -15,9 +15,13 @@ 'kernel_wrap_test.cc', 'main.cc', 'mock_util.h', - 'mount_node_test.cc', 'mount_html5fs_test.cc', 'mount_http_test.cc', + 'mount_mock.cc', + 'mount_mock.h', + 'mount_node_mock.cc', + 'mount_node_mock.h', + 'mount_node_test.cc', 'mount_test.cc', 'path_test.cc', 'pepper_interface_mock.cc', diff --git a/native_client_sdk/src/libraries/nacl_io_test/example.js b/native_client_sdk/src/libraries/nacl_io_test/example.js index 3b4de45..bd17594 100644 --- a/native_client_sdk/src/libraries/nacl_io_test/example.js +++ b/native_client_sdk/src/libraries/nacl_io_test/example.js @@ -60,7 +60,7 @@ function handleMessage(event) { // in the test failure summary). var argList = msg.substr(firstColon + 1); args = []; - for (var i = 0; i < argCount; ++i) { + for (var i = 0; i < argCount - 1; ++i) { var arg; var comma = argList.indexOf(','); if (comma === -1) { @@ -78,5 +78,8 @@ function handleMessage(event) { args.push(arg); } + // Last argument is the rest of the message. + args.push(argList); + cmdFunction.apply(null, args); } diff --git a/native_client_sdk/src/libraries/nacl_io_test/kernel_proxy_mock.cc b/native_client_sdk/src/libraries/nacl_io_test/kernel_proxy_mock.cc index 279a8ea..367569e 100644 --- a/native_client_sdk/src/libraries/nacl_io_test/kernel_proxy_mock.cc +++ b/native_client_sdk/src/libraries/nacl_io_test/kernel_proxy_mock.cc @@ -6,8 +6,7 @@ #include "kernel_proxy_mock.h" #include "nacl_io/kernel_intercept.h" -KernelProxyMock::KernelProxyMock() { -} +KernelProxyMock::KernelProxyMock() {} KernelProxyMock::~KernelProxyMock() { // Uninitialize the kernel proxy so wrapped functions passthrough to their diff --git a/native_client_sdk/src/libraries/nacl_io_test/kernel_proxy_test.cc b/native_client_sdk/src/libraries/nacl_io_test/kernel_proxy_test.cc index 601f3b7..70e76e1 100644 --- a/native_client_sdk/src/libraries/nacl_io_test/kernel_proxy_test.cc +++ b/native_client_sdk/src/libraries/nacl_io_test/kernel_proxy_test.cc @@ -11,15 +11,30 @@ #include <map> #include <string> -#include "nacl_io/kernel_handle.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +#include "mount_mock.h" +#include "mount_node_mock.h" + #include "nacl_io/kernel_intercept.h" #include "nacl_io/kernel_proxy.h" #include "nacl_io/mount.h" #include "nacl_io/mount_mem.h" #include "nacl_io/osmman.h" #include "nacl_io/path.h" +#include "nacl_io/typed_mount_factory.h" -#include "gtest/gtest.h" +using ::testing::_; +using ::testing::DoAll; +using ::testing::Invoke; +using ::testing::Return; +using ::testing::SaveArg; +using ::testing::SetArgPointee; +using ::testing::StrEq; +using ::testing::WithArgs; + +namespace { class KernelProxyFriend : public KernelProxy { public: @@ -44,22 +59,24 @@ class KernelProxyTest : public ::testing::Test { KernelProxyFriend* kp_; }; +} // namespace + TEST_F(KernelProxyTest, FileLeak) { const size_t buffer_size = 1024; char filename[128]; int file_num; int garbage[buffer_size]; - MountMem* mount = (MountMem*) kp_->RootMount(); + MountMem* mount = (MountMem*)kp_->RootMount(); ScopedMountNode root; EXPECT_EQ(0, mount->Open(Path("/"), O_RDONLY, &root)); EXPECT_EQ(0, root->ChildCount()); - for (file_num=0; file_num < 4096; file_num++) { + for (file_num = 0; file_num < 4096; file_num++) { sprintf(filename, "/foo%i.tmp", file_num++); - FILE *f = fopen(filename, "w"); - EXPECT_NE((FILE *) 0, f); + FILE* f = fopen(filename, "w"); + EXPECT_NE((FILE*)0, f); EXPECT_EQ(1, root->ChildCount()); EXPECT_EQ(buffer_size, fwrite(garbage, 1, buffer_size, f)); fclose(f); @@ -227,6 +244,8 @@ TEST_F(KernelProxyTest, MemMountDup) { // fd, new_fd, dup_fd -> "/bar" } +namespace { + StringMap_t g_StringMap; class MountMockInit : public MountMem { @@ -237,13 +256,14 @@ class MountMockInit : public MountMem { return EINVAL; return 0; } - ; + + friend class TypedMountFactory<MountMockInit>; }; class KernelProxyMountMock : public KernelProxy { virtual void Init(PepperInterface* ppapi) { KernelProxy::Init(NULL); - factories_["initfs"] = MountMockInit::Create<MountMockInit>; + factories_["initfs"] = new TypedMountFactory<MountMockInit>; } }; @@ -260,6 +280,8 @@ class KernelProxyMountTest : public ::testing::Test { KernelProxy* kp_; }; +} // namespace + TEST_F(KernelProxyMountTest, MountInit) { int res1 = ki_mount("/", "/mnt1", "initfs", 0, "false,foo=bar"); @@ -326,12 +348,14 @@ class MountMockMMap : public Mount { virtual Error Mkdir(const Path& path, int permissions) { return ENOSYS; } virtual Error Rmdir(const Path& path) { return ENOSYS; } virtual Error Remove(const Path& path) { return ENOSYS; } + + friend class TypedMountFactory<MountMockMMap>; }; class KernelProxyMockMMap : public KernelProxy { virtual void Init(PepperInterface* ppapi) { KernelProxy::Init(NULL); - factories_["mmapfs"] = MountMockInit::Create<MountMockMMap>; + factories_["mmapfs"] = new TypedMountFactory<MountMockMMap>; } }; @@ -376,3 +400,103 @@ TEST_F(KernelProxyMMapTest, MMap) { EXPECT_EQ(3, g_MMapCount); } +namespace { + +class SingletonMountFactory : public MountFactory { + public: + SingletonMountFactory(const ScopedMount& mount) : mount_(mount) {} + + virtual Error CreateMount(int dev, + StringMap_t& args, + PepperInterface* ppapi, + ScopedMount* out_mount) { + *out_mount = mount_; + return 0; + } + + private: + ScopedMount mount_; +}; + +class KernelProxyError : public KernelProxy { + public: + KernelProxyError() : mnt_(new MountMock) {} + + virtual void Init(PepperInterface* ppapi) { + KernelProxy::Init(ppapi); + factories_["testfs"] = new SingletonMountFactory(mnt_); + + EXPECT_CALL(*mnt_, Destroy()).Times(1); + } + + ScopedRef<MountMock> mnt() { return mnt_; } + + private: + ScopedRef<MountMock> mnt_; +}; + +class KernelProxyErrorTest : public ::testing::Test { + public: + KernelProxyErrorTest() : kp_(new KernelProxyError) { + ki_init(kp_); + // Unmount the passthrough FS and mount a testfs. + EXPECT_EQ(0, kp_->umount("/")); + EXPECT_EQ(0, kp_->mount("", "/", "testfs", 0, NULL)); + } + + ~KernelProxyErrorTest() { + ki_uninit(); + delete kp_; + } + + ScopedRef<MountMock> mnt() { return kp_->mnt(); } + + private: + KernelProxyError* kp_; +}; + +} // namespace + +TEST_F(KernelProxyErrorTest, WriteError) { + ScopedRef<MountMock> mock_mnt(mnt()); + ScopedRef<MountNodeMock> mock_node(new MountNodeMock(&*mock_mnt)); + EXPECT_CALL(*mock_mnt, Open(_, _, _)) + .WillOnce(DoAll(SetArgPointee<2>(mock_node), Return(0))); + + EXPECT_CALL(*mock_node, Write(_, _, _, _)) + .WillOnce(DoAll(SetArgPointee<3>(0), // Wrote 0 bytes. + Return(1234))); // Returned error 1234. + + EXPECT_CALL(*mock_node, Destroy()).Times(1); + + int fd = ki_open("/dummy", O_WRONLY); + EXPECT_NE(0, fd); + + char buf[20]; + EXPECT_EQ(-1, ki_write(fd, &buf[0], 20)); + // The Mount should be able to return whatever error it wants and have it + // propagate through. + EXPECT_EQ(1234, errno); +} + +TEST_F(KernelProxyErrorTest, ReadError) { + ScopedRef<MountMock> mock_mnt(mnt()); + ScopedRef<MountNodeMock> mock_node(new MountNodeMock(&*mock_mnt)); + EXPECT_CALL(*mock_mnt, Open(_, _, _)) + .WillOnce(DoAll(SetArgPointee<2>(mock_node), Return(0))); + + EXPECT_CALL(*mock_node, Read(_, _, _, _)) + .WillOnce(DoAll(SetArgPointee<3>(0), // Read 0 bytes. + Return(1234))); // Returned error 1234. + + EXPECT_CALL(*mock_node, Destroy()).Times(1); + + int fd = ki_open("/dummy", O_RDONLY); + EXPECT_NE(0, fd); + + char buf[20]; + EXPECT_EQ(-1, ki_read(fd, &buf[0], 20)); + // The Mount should be able to return whatever error it wants and have it + // propagate through. + EXPECT_EQ(1234, errno); +} diff --git a/native_client_sdk/src/libraries/nacl_io_test/mount_mock.cc b/native_client_sdk/src/libraries/nacl_io_test/mount_mock.cc new file mode 100644 index 0000000..4b69108 --- /dev/null +++ b/native_client_sdk/src/libraries/nacl_io_test/mount_mock.cc @@ -0,0 +1,11 @@ +/* Copyright (c) 2013 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "mount_mock.h" + +MountMock::MountMock() {} + +MountMock::~MountMock() {} + diff --git a/native_client_sdk/src/libraries/nacl_io_test/mount_mock.h b/native_client_sdk/src/libraries/nacl_io_test/mount_mock.h new file mode 100644 index 0000000..7ceebc4 --- /dev/null +++ b/native_client_sdk/src/libraries/nacl_io_test/mount_mock.h @@ -0,0 +1,30 @@ +/* Copyright (c) 2013 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef LIBRARIES_NACL_IO_TEST_MOUNT_MOCK_H_ +#define LIBRARIES_NACL_IO_TEST_MOUNT_MOCK_H_ + +#include "gmock/gmock.h" + +#include "nacl_io/mount.h" + +class MountMock : public Mount { + public: + MountMock(); + virtual ~MountMock(); + + MOCK_METHOD3(Init, Error(int, StringMap_t&, PepperInterface*)); + MOCK_METHOD0(Destroy, void()); + MOCK_METHOD2(Access, Error(const Path&, int)); + MOCK_METHOD3(Open, Error(const Path&, int, ScopedMountNode*)); + MOCK_METHOD2(OpenResource, Error(const Path&, ScopedMountNode*)); + MOCK_METHOD1(Unlink, Error(const Path&)); + MOCK_METHOD2(Mkdir, Error(const Path&, int)); + MOCK_METHOD1(Rmdir, Error(const Path&)); + MOCK_METHOD1(Remove, Error(const Path&)); +}; + +#endif // LIBRARIES_NACL_IO_TEST_MOUNT_MOCK_H_ + diff --git a/native_client_sdk/src/libraries/nacl_io_test/mount_node_mock.cc b/native_client_sdk/src/libraries/nacl_io_test/mount_node_mock.cc new file mode 100644 index 0000000..b925b56 --- /dev/null +++ b/native_client_sdk/src/libraries/nacl_io_test/mount_node_mock.cc @@ -0,0 +1,11 @@ +/* Copyright (c) 2013 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "mount_node_mock.h" + +MountNodeMock::MountNodeMock(Mount* mount) : MountNode(mount) {} + +MountNodeMock::~MountNodeMock() {} + diff --git a/native_client_sdk/src/libraries/nacl_io_test/mount_node_mock.h b/native_client_sdk/src/libraries/nacl_io_test/mount_node_mock.h new file mode 100644 index 0000000..dbbfda1 --- /dev/null +++ b/native_client_sdk/src/libraries/nacl_io_test/mount_node_mock.h @@ -0,0 +1,44 @@ +/* Copyright (c) 2013 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef LIBRARIES_NACL_IO_TEST_MOUNT_NODE_MOCK_H_ +#define LIBRARIES_NACL_IO_TEST_MOUNT_NODE_MOCK_H_ + +#include "gmock/gmock.h" + +#include "nacl_io/mount.h" + +class MountNodeMock : public MountNode { + public: + explicit MountNodeMock(Mount*); + virtual ~MountNodeMock(); + + MOCK_METHOD1(Init, Error(int)); + MOCK_METHOD0(Destroy, void()); + MOCK_METHOD0(FSync, Error()); + MOCK_METHOD1(FTruncate, Error(off_t)); + MOCK_METHOD4(GetDents, Error(size_t, struct dirent*, size_t, int*)); + MOCK_METHOD1(GetStat, Error(struct stat*)); + MOCK_METHOD2(Ioctl, Error(int, char*)); + MOCK_METHOD4(Read, Error(size_t, void*, size_t, int*)); + MOCK_METHOD4(Write, Error(size_t, const void*, size_t, int*)); + MOCK_METHOD6(MMap, Error(void*, size_t, int, int, size_t, void**)); + MOCK_METHOD0(GetLinks, int()); + MOCK_METHOD0(GetMode, int()); + MOCK_METHOD0(GetType, int()); + MOCK_METHOD1(GetSize, Error(size_t*)); + MOCK_METHOD0(IsaDir, bool()); + MOCK_METHOD0(IsaFile, bool()); + MOCK_METHOD0(IsaTTY, bool()); + MOCK_METHOD0(ChildCount, int()); + MOCK_METHOD2(AddChild, Error(const std::string&, const ScopedMountNode&)); + MOCK_METHOD1(RemoveChild, Error(const std::string&)); + MOCK_METHOD2(FindChild, Error(const std::string&, ScopedMountNode*)); + MOCK_METHOD0(Link, void()); + MOCK_METHOD0(Unlink, void()); +}; + +#endif // LIBRARIES_NACL_IO_TEST_MOUNT_NODE_MOCK_H_ + diff --git a/native_client_sdk/src/libraries/sdk_util/scoped_ref.h b/native_client_sdk/src/libraries/sdk_util/scoped_ref.h index d446325..0bbba71 100644 --- a/native_client_sdk/src/libraries/sdk_util/scoped_ref.h +++ b/native_client_sdk/src/libraries/sdk_util/scoped_ref.h @@ -30,7 +30,8 @@ class ScopedRefBase { RefObject* ptr_; }; -template<class T> class ScopedRef : public ScopedRefBase { +template <class T> +class ScopedRef : public ScopedRefBase { public: ScopedRef() {} ScopedRef(const ScopedRef& ptr) { reset(ptr.get()); } @@ -41,7 +42,13 @@ template<class T> class ScopedRef : public ScopedRefBase { return *this; } - template<typename U> ScopedRef& operator=(const ScopedRef<U>& ptr) { + template <typename U> + ScopedRef(const ScopedRef<U>& ptr) { + reset(ptr.get()); + } + + template <typename U> + ScopedRef& operator=(const ScopedRef<U>& ptr) { reset(ptr.get()); return *this; } @@ -49,17 +56,19 @@ template<class T> class ScopedRef : public ScopedRefBase { void reset(T* obj = NULL) { ScopedRefBase::reset(obj); } T* get() const { return static_cast<T*>(ptr_); } - template<typename U> bool operator==(const ScopedRef<U>& p) const { + template <typename U> + bool operator==(const ScopedRef<U>& p) const { return get() == p.get(); } - template<typename U> bool operator!=(const ScopedRef<U>& p) const { + template <typename U> + bool operator!=(const ScopedRef<U>& p) const { return get() != p.get(); } public: T& operator*() const { return *get(); } - T* operator->() const { return get(); } + T* operator->() const { return get(); } #ifndef __llvm__ private: @@ -68,16 +77,15 @@ template<class T> class ScopedRef : public ScopedRefBase { public: operator bool_as_func_ptr() const { - return (ptr_ != NULL) ? - &ScopedRef::bool_as_func_impl : 0; + return (ptr_ != NULL) ? &ScopedRef::bool_as_func_impl : 0; } #else /* * TODO Remove when bug 3514 is fixed see: * https://code.google.com/p/nativeclient/issues/detail?id=3514 */ - operator T*() const { return get(); }; + operator T*() const { return get(); } #endif }; -#endif // LIBRARIES_SDK_UTIL_SCOPED_REF_H_ +#endif // LIBRARIES_SDK_UTIL_SCOPED_REF_H_ |