diff options
Diffstat (limited to 'dom/fs/test/gtest/FileSystemMocks.h')
-rw-r--r-- | dom/fs/test/gtest/FileSystemMocks.h | 343 |
1 files changed, 343 insertions, 0 deletions
diff --git a/dom/fs/test/gtest/FileSystemMocks.h b/dom/fs/test/gtest/FileSystemMocks.h new file mode 100644 index 0000000000..867302908b --- /dev/null +++ b/dom/fs/test/gtest/FileSystemMocks.h @@ -0,0 +1,343 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef DOM_FS_TEST_GTEST_FILESYSTEMMOCKS_H_ +#define DOM_FS_TEST_GTEST_FILESYSTEMMOCKS_H_ + +#include <memory> // We don't have a mozilla shared pointer for pod types + +#include "TestHelpers.h" +#include "fs/FileSystemChildFactory.h" +#include "fs/FileSystemRequestHandler.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" +#include "js/Promise.h" +#include "js/RootingAPI.h" +#include "jsapi.h" +#include "mozilla/ErrorResult.h" +#include "mozilla/ScopeExit.h" +#include "mozilla/UniquePtr.h" +#include "mozilla/dom/BindingDeclarations.h" +#include "mozilla/dom/BindingUtils.h" +#include "mozilla/dom/DOMException.h" +#include "mozilla/dom/DOMExceptionBinding.h" +#include "mozilla/dom/FileSystemManagerChild.h" +#include "mozilla/dom/Promise.h" +#include "mozilla/dom/PromiseNativeHandler.h" +#include "mozilla/dom/ScriptSettings.h" +#include "mozilla/ipc/PBackgroundSharedTypes.h" +#include "nsIGlobalObject.h" +#include "nsISupports.h" +#include "nsISupportsImpl.h" +#include "nsITimer.h" + +namespace mozilla::dom::fs { + +inline std::ostream& operator<<(std::ostream& aOut, + const FileSystemEntryMetadata& aMetadata) { + return aOut; +} + +namespace test { + +nsIGlobalObject* GetGlobal(); + +nsresult GetAsString(const RefPtr<Promise>& aPromise, nsAString& aString); + +mozilla::ipc::PrincipalInfo GetPrincipalInfo(); + +class MockFileSystemRequestHandler : public FileSystemRequestHandler { + public: + MOCK_METHOD(void, GetRootHandle, + (RefPtr<FileSystemManager> aManager, RefPtr<Promise> aPromise, + ErrorResult& aError), + (override)); + + MOCK_METHOD(void, GetDirectoryHandle, + (RefPtr<FileSystemManager> & aManager, + const FileSystemChildMetadata& aDirectory, bool aCreate, + RefPtr<Promise> aPromise, ErrorResult& aError), + (override)); + + MOCK_METHOD(void, GetFileHandle, + (RefPtr<FileSystemManager> & aManager, + const FileSystemChildMetadata& aFile, bool aCreate, + RefPtr<Promise> aPromise, ErrorResult& aError), + (override)); + + MOCK_METHOD(void, GetFile, + (RefPtr<FileSystemManager> & aManager, + const FileSystemEntryMetadata& aFile, RefPtr<Promise> aPromise, + ErrorResult& aError), + (override)); + + MOCK_METHOD(void, GetEntries, + (RefPtr<FileSystemManager> & aManager, const EntryId& aDirectory, + PageNumber aPage, RefPtr<Promise> aPromise, + RefPtr<FileSystemEntryMetadataArray>& aSink, + ErrorResult& aError), + (override)); + + MOCK_METHOD(void, RemoveEntry, + (RefPtr<FileSystemManager> & aManager, + const FileSystemChildMetadata& aEntry, bool aRecursive, + RefPtr<Promise> aPromise, ErrorResult& aError), + (override)); + + MOCK_METHOD(void, MoveEntry, + (RefPtr<FileSystemManager> & aManager, FileSystemHandle* aHandle, + const FileSystemEntryMetadata& aEntry, + const FileSystemChildMetadata& aNewEntry, + RefPtr<Promise> aPromise, ErrorResult& aError), + (override)); + + MOCK_METHOD(void, RenameEntry, + (RefPtr<FileSystemManager> & aManager, FileSystemHandle* aHandle, + const FileSystemEntryMetadata& aEntry, const Name& aName, + RefPtr<Promise> aPromise, ErrorResult& aError), + (override)); + + MOCK_METHOD(void, Resolve, + (RefPtr<FileSystemManager> & aManager, + const FileSystemEntryPair& aEndpoints, RefPtr<Promise> aPromise, + ErrorResult& aError), + (override)); +}; + +class WaitablePromiseListener { + public: + NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING + + virtual void ClearDone() = 0; + + virtual bool IsDone() const = 0; + + virtual PromiseNativeHandler* AsHandler() = 0; + + protected: + virtual ~WaitablePromiseListener() = default; +}; + +template <class SuccessHandler, class ErrorHandler, + uint32_t MilliSeconds = 2000u> +class TestPromiseListener : public PromiseNativeHandler, + public WaitablePromiseListener { + public: + TestPromiseListener() + : mIsDone(std::make_shared<bool>(false)), + mTimer(), + mOnSuccess(), + mOnError() { + ClearDone(); + } + + // nsISupports implementation + + NS_IMETHODIMP QueryInterface(REFNSIID aIID, void** aInstancePtr) override { + nsresult rv = NS_ERROR_UNEXPECTED; + NS_INTERFACE_TABLE0(TestPromiseListener) + + return rv; + } + + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TestPromiseListener, override) + + // PromiseNativeHandler implementation + + void ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue, + ErrorResult& aError) override { + mozilla::ScopeExit flagAsDone([isDone = mIsDone, timer = mTimer] { + timer->Cancel(); + *isDone = true; + }); + + mOnSuccess(); + } + + void RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue, + ErrorResult& aError) override { + mozilla::ScopeExit flagAsDone([isDone = mIsDone, timer = mTimer] { + timer->Cancel(); + *isDone = true; + }); + + if (aValue.isInt32()) { + mOnError(static_cast<nsresult>(aValue.toInt32())); + return; + } + + ASSERT_TRUE(aValue.isObject()); + JS::Rooted<JSObject*> exceptionObject(aCx, &aValue.toObject()); + + RefPtr<Exception> exception; + UNWRAP_OBJECT(Exception, exceptionObject, exception); + if (exception) { + mOnError(static_cast<nsresult>(exception->Result())); + return; + } + } + + // WaitablePromiseListener implementation + + void ClearDone() override { + *mIsDone = false; + if (mTimer) { + mTimer->Cancel(); + } + auto timerCallback = [isDone = mIsDone](nsITimer* aTimer) { + *isDone = true; + FAIL() << "Timed out!"; + }; + const char* timerName = "fs::TestPromiseListener::ClearDone"; + auto res = NS_NewTimerWithCallback(timerCallback, MilliSeconds, + nsITimer::TYPE_ONE_SHOT, timerName); + if (res.isOk()) { + mTimer = res.unwrap(); + } + } + + bool IsDone() const override { return *mIsDone; } + + PromiseNativeHandler* AsHandler() override { return this; } + + SuccessHandler& GetSuccessHandler() { return mOnSuccess; } + + SuccessHandler& GetErrorHandler() { return mOnError; } + + protected: + virtual ~TestPromiseListener() = default; + + std::shared_ptr<bool> mIsDone; // We pass this to a callback + + nsCOMPtr<nsITimer> mTimer; + + SuccessHandler mOnSuccess; + + ErrorHandler mOnError; +}; + +class TestFileSystemManagerChild : public FileSystemManagerChild { + public: + MOCK_METHOD(void, SendGetRootHandle, + (mozilla::ipc::ResolveCallback<FileSystemGetHandleResponse> && + aResolve, + mozilla::ipc::RejectCallback&& aReject), + (override)); + + MOCK_METHOD( + void, SendGetDirectoryHandle, + (const FileSystemGetHandleRequest& request, + mozilla::ipc::ResolveCallback<FileSystemGetHandleResponse>&& aResolve, + mozilla::ipc::RejectCallback&& aReject), + (override)); + + MOCK_METHOD( + void, SendGetFileHandle, + (const FileSystemGetHandleRequest& request, + mozilla::ipc::ResolveCallback<FileSystemGetHandleResponse>&& aResolve, + mozilla::ipc::RejectCallback&& aReject), + (override)); + + MOCK_METHOD( + void, SendGetAccessHandle, + (const FileSystemGetAccessHandleRequest& request, + mozilla::ipc::ResolveCallback<FileSystemGetAccessHandleResponse>&& + aResolve, + mozilla::ipc::RejectCallback&& aReject), + (override)); + + MOCK_METHOD( + void, SendGetWritable, + (const FileSystemGetWritableRequest& request, + mozilla::ipc::ResolveCallback<FileSystemGetWritableFileStreamResponse>&& + aResolve, + mozilla::ipc::RejectCallback&& aReject), + (override)); + + MOCK_METHOD( + void, SendGetFile, + (const FileSystemGetFileRequest& request, + mozilla::ipc::ResolveCallback<FileSystemGetFileResponse>&& aResolve, + mozilla::ipc::RejectCallback&& aReject), + (override)); + + MOCK_METHOD( + void, SendResolve, + (const FileSystemResolveRequest& request, + mozilla::ipc::ResolveCallback<FileSystemResolveResponse>&& aResolve, + mozilla::ipc::RejectCallback&& aReject), + (override)); + + MOCK_METHOD( + void, SendGetEntries, + (const FileSystemGetEntriesRequest& request, + mozilla::ipc::ResolveCallback<FileSystemGetEntriesResponse>&& aResolve, + mozilla::ipc::RejectCallback&& aReject), + (override)); + + MOCK_METHOD( + void, SendRemoveEntry, + (const FileSystemRemoveEntryRequest& request, + mozilla::ipc::ResolveCallback<FileSystemRemoveEntryResponse>&& aResolve, + mozilla::ipc::RejectCallback&& aReject), + (override)); + + MOCK_METHOD(void, Shutdown, (), (override)); + + protected: + virtual ~TestFileSystemManagerChild() = default; +}; + +class TestFileSystemChildFactory final : public FileSystemChildFactory { + public: + explicit TestFileSystemChildFactory(TestFileSystemManagerChild* aChild) + : mChild(aChild) {} + + already_AddRefed<FileSystemManagerChild> Create() const override { + return RefPtr<TestFileSystemManagerChild>(mChild).forget(); + } + + ~TestFileSystemChildFactory() = default; + + private: + TestFileSystemManagerChild* mChild; +}; + +struct MockExpectMe { + MOCK_METHOD0(InvokeMe, void()); + + template <class... Args> + void operator()(Args...) { + InvokeMe(); + } +}; + +template <nsresult Expected> +struct NSErrorMatcher { + void operator()(nsresult aErr) { ASSERT_NSEQ(Expected, aErr); } +}; + +struct FailOnCall { + template <class... Args> + void operator()(Args...) { + FAIL(); + } +}; + +} // namespace test +} // namespace mozilla::dom::fs + +#define MOCK_PROMISE_LISTENER(name, ...) \ + using name = mozilla::dom::fs::test::TestPromiseListener<__VA_ARGS__>; + +MOCK_PROMISE_LISTENER( + ExpectNotImplemented, mozilla::dom::fs::test::FailOnCall, + mozilla::dom::fs::test::NSErrorMatcher<NS_ERROR_NOT_IMPLEMENTED>); + +MOCK_PROMISE_LISTENER(ExpectResolveCalled, mozilla::dom::fs::test::MockExpectMe, + mozilla::dom::fs::test::FailOnCall); + +#endif // DOM_FS_TEST_GTEST_FILESYSTEMMOCKS_H_ |