402 lines
12 KiB
C++
402 lines
12 KiB
C++
/* -*- 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"
|
|
|
|
class MockGlobalObject;
|
|
|
|
namespace mozilla::dom::fs {
|
|
|
|
inline std::ostream& operator<<(std::ostream& aOut,
|
|
const FileSystemEntryMetadata& aMetadata) {
|
|
return aOut;
|
|
}
|
|
|
|
namespace test {
|
|
|
|
nsIGlobalObject* GetGlobal();
|
|
|
|
MockGlobalObject* GetMockGlobal();
|
|
|
|
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,
|
|
FileSystemEntryMetadata* const aEntry,
|
|
const FileSystemChildMetadata& aNewEntry,
|
|
RefPtr<Promise> aPromise, ErrorResult& aError),
|
|
(override));
|
|
|
|
MOCK_METHOD(void, RenameEntry,
|
|
(RefPtr<FileSystemManager> & aManager, FileSystemHandle* aHandle,
|
|
FileSystemEntryMetadata* const 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)), 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);
|
|
|
|
#define MOCKGLOBALOBJECT_IID \
|
|
{/* c0a93d91-9c15-49e1-abed-890b3679ac6e */ \
|
|
0xc0a93d91, \
|
|
0x9c15, \
|
|
0x49e1, \
|
|
{0xab, 0xed, 0x89, 0x0b, 0x36, 0x79, 0xac, 0x6e}}
|
|
|
|
class MockGlobalObject : public nsIGlobalObject, public nsWrapperCache {
|
|
public:
|
|
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
|
NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(MockGlobalObject)
|
|
|
|
NS_INLINE_DECL_STATIC_IID(MOCKGLOBALOBJECT_IID)
|
|
|
|
explicit MockGlobalObject(nsCOMPtr<nsIGlobalObject>&& aGlobal)
|
|
: mGlobal(std::move(aGlobal)) {}
|
|
|
|
JSObject* GetGlobalJSObject() override {
|
|
return mGlobal->GetGlobalJSObject();
|
|
}
|
|
|
|
JSObject* GetGlobalJSObjectPreserveColor() const override {
|
|
return mGlobal->GetGlobalJSObjectPreserveColor();
|
|
}
|
|
|
|
MOCK_METHOD(JSObject*, WrapObject,
|
|
(JSContext * aCx, JS::Handle<JSObject*> aGivenProto), (override));
|
|
|
|
MOCK_METHOD(nsICookieJarSettings*, GetCookieJarSettings, (), (override));
|
|
|
|
MOCK_METHOD(nsIPrincipal*, PrincipalOrNull, (), (const));
|
|
|
|
MOCK_METHOD(mozilla::StorageAccess, GetStorageAccess, (), (override));
|
|
|
|
JS::loader::ModuleLoaderBase* GetModuleLoader(JSContext* aCx) override {
|
|
return mGlobal->GetModuleLoader(aCx);
|
|
}
|
|
|
|
bool ShouldResistFingerprinting(RFPTarget aTarget) const override {
|
|
return mGlobal->ShouldResistFingerprinting(std::move(aTarget));
|
|
}
|
|
|
|
nsISerialEventTarget* SerialEventTarget() const override {
|
|
return mGlobal->SerialEventTarget();
|
|
}
|
|
|
|
nsresult Dispatch(already_AddRefed<nsIRunnable>&& aRunnable) const override {
|
|
return mGlobal->Dispatch(std::move(aRunnable));
|
|
}
|
|
|
|
mozilla::OriginTrials Trials() const override { return mGlobal->Trials(); }
|
|
|
|
protected:
|
|
~MockGlobalObject() = default;
|
|
|
|
nsCOMPtr<nsIGlobalObject> mGlobal;
|
|
};
|
|
|
|
#endif // DOM_FS_TEST_GTEST_FILESYSTEMMOCKS_H_
|