Automatically generated with:
cp dom/.clang-format xpcom/ && mach format xpcom/**.{cpp,h}
Manual changes:
* nsTDependentSubstring.cpp was relying on include order, prevent that
from being changed by clang-format.
* Missing nsAtom.h include from nsGkAtoms.h
* nsWindowsHelpers.h needed to keep the include order
* MemoryPressureLevelMac.h needed mozilla/Attributes.h
Differential Revision: https://phabricator.services.mozilla.com/D311687
221 lines
5.4 KiB
C++
221 lines
5.4 KiB
C++
/* 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/. */
|
|
|
|
#include "Helpers.h"
|
|
#include "mozilla/RefPtr.h"
|
|
#include "mozilla/StopGapEventTarget.h"
|
|
#include "mozilla/gtest/MozAssertions.h"
|
|
#include "nsIRunnable.h"
|
|
#include "nsThreadUtils.h"
|
|
|
|
using mozilla::CancelableRunnable;
|
|
using mozilla::MakeRefPtr;
|
|
using mozilla::StopGapEventTarget;
|
|
|
|
namespace TestStopGapEventTarget {
|
|
|
|
static void Enqueue(nsIEventTarget* target, std::function<void()>&& aCallable) {
|
|
nsresult rv = target->Dispatch(
|
|
NS_NewRunnableFunction("SGQ GTest", std::move(aCallable)));
|
|
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(rv));
|
|
}
|
|
|
|
class TestCancelable final : public CancelableRunnable {
|
|
public:
|
|
explicit TestCancelable() : CancelableRunnable("TestCancelable") {}
|
|
NS_IMETHOD Run() override {
|
|
mHasRun = true;
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult Cancel() override {
|
|
mHasCanceled = true;
|
|
return NS_OK;
|
|
}
|
|
|
|
bool mHasRun = false;
|
|
bool mHasCanceled = false;
|
|
|
|
private:
|
|
virtual ~TestCancelable() = default;
|
|
};
|
|
|
|
} // namespace TestStopGapEventTarget
|
|
|
|
using namespace TestStopGapEventTarget;
|
|
using testing::RunnableQueue;
|
|
|
|
TEST(StopGapEventTarget, SimpleDispatch)
|
|
{
|
|
std::string log;
|
|
|
|
RefPtr<StopGapEventTarget> stopgap = MakeRefPtr<StopGapEventTarget>();
|
|
|
|
Enqueue(stopgap, [&]() { log += 'a'; });
|
|
ASSERT_EQ(log, "");
|
|
|
|
auto base = MakeRefPtr<RunnableQueue>();
|
|
stopgap->SetRealEventTarget(base);
|
|
ASSERT_NS_SUCCEEDED(base->Run());
|
|
|
|
ASSERT_EQ(log, "a");
|
|
|
|
ASSERT_TRUE(base->IsEmpty());
|
|
}
|
|
|
|
TEST(StopGapEventTarget, RunnableNeverRun)
|
|
{
|
|
std::string log;
|
|
|
|
RefPtr<StopGapEventTarget> stopgap = MakeRefPtr<StopGapEventTarget>();
|
|
|
|
Enqueue(stopgap, [&]() { log += 'a'; });
|
|
ASSERT_EQ(log, "");
|
|
stopgap = nullptr;
|
|
ASSERT_EQ(log, "");
|
|
}
|
|
|
|
TEST(StopGapEventTarget, CancelableIsRun)
|
|
{
|
|
RefPtr<StopGapEventTarget> stopgap = MakeRefPtr<StopGapEventTarget>();
|
|
RefPtr<TestCancelable> cancelable(new TestCancelable);
|
|
|
|
stopgap->Dispatch(do_AddRef(cancelable));
|
|
|
|
ASSERT_FALSE(cancelable->mHasRun);
|
|
ASSERT_FALSE(cancelable->mHasCanceled);
|
|
|
|
auto base = MakeRefPtr<RunnableQueue>();
|
|
stopgap->SetRealEventTarget(base);
|
|
ASSERT_NS_SUCCEEDED(base->Run());
|
|
|
|
stopgap = nullptr;
|
|
|
|
ASSERT_TRUE(cancelable->mHasRun);
|
|
ASSERT_FALSE(cancelable->mHasCanceled);
|
|
}
|
|
|
|
TEST(StopGapEventTarget, CancelableNeverRun)
|
|
{
|
|
RefPtr<StopGapEventTarget> stopgap = MakeRefPtr<StopGapEventTarget>();
|
|
RefPtr<TestCancelable> cancelable(new TestCancelable);
|
|
|
|
stopgap->Dispatch(do_AddRef(cancelable));
|
|
|
|
ASSERT_FALSE(cancelable->mHasRun);
|
|
ASSERT_FALSE(cancelable->mHasCanceled);
|
|
|
|
stopgap = nullptr;
|
|
|
|
ASSERT_FALSE(cancelable->mHasRun);
|
|
ASSERT_TRUE(cancelable->mHasCanceled);
|
|
}
|
|
|
|
TEST(StopGapEventTarget, EnqueueFromRun)
|
|
{
|
|
std::string log;
|
|
|
|
auto base = MakeRefPtr<RunnableQueue>();
|
|
RefPtr<StopGapEventTarget> stopgap = MakeRefPtr<StopGapEventTarget>();
|
|
|
|
Enqueue(base, [&]() { log += 'a'; });
|
|
Enqueue(stopgap, [&]() {
|
|
log += 'b';
|
|
Enqueue(stopgap, [&]() { log += 'c'; });
|
|
Enqueue(base, [&]() { log += 'd'; });
|
|
});
|
|
Enqueue(stopgap, [&]() { log += 'e'; });
|
|
|
|
ASSERT_NS_SUCCEEDED(base->Run());
|
|
ASSERT_EQ(log, "a");
|
|
ASSERT_TRUE(base->IsEmpty());
|
|
|
|
stopgap->SetRealEventTarget(base);
|
|
ASSERT_EQ(base->Length(), 2U);
|
|
ASSERT_NS_SUCCEEDED(base->Run());
|
|
|
|
ASSERT_EQ(log, "abecd");
|
|
ASSERT_TRUE(base->IsEmpty());
|
|
}
|
|
|
|
TEST(StopGapEventTarget, RunFromRun)
|
|
{
|
|
std::string log;
|
|
|
|
auto base = MakeRefPtr<RunnableQueue>();
|
|
RefPtr<StopGapEventTarget> stopgap = MakeRefPtr<StopGapEventTarget>();
|
|
|
|
Enqueue(base, [&]() { log += 'a'; });
|
|
|
|
// Running the event queue from within an event (i.e., a nested event loop)
|
|
// does not stall the StopGapEventTarget.
|
|
Enqueue(stopgap, [&]() {
|
|
log += '(';
|
|
Enqueue(stopgap, [&]() { log += 'b'; });
|
|
// This should run subsequent events from stopgap.
|
|
ASSERT_NS_SUCCEEDED(base->Run());
|
|
log += ')';
|
|
});
|
|
|
|
Enqueue(stopgap, [&]() { log += 'c'; });
|
|
|
|
ASSERT_EQ(log, "");
|
|
stopgap->SetRealEventTarget(base);
|
|
ASSERT_NS_SUCCEEDED(base->Run());
|
|
ASSERT_EQ(log, "a(cb)");
|
|
|
|
ASSERT_TRUE(base->IsEmpty());
|
|
}
|
|
|
|
TEST(StopGapEventTarget, SetEventTargetFromRun)
|
|
{
|
|
std::string log;
|
|
|
|
auto base = MakeRefPtr<RunnableQueue>();
|
|
RefPtr<StopGapEventTarget> stopgap = MakeRefPtr<StopGapEventTarget>();
|
|
|
|
Enqueue(stopgap, [&]() {
|
|
// This is running during the first Run() call, and enqueueing these will
|
|
// result in them being run too during this call
|
|
log += 'd';
|
|
Enqueue(stopgap, [&]() { log += 'e'; });
|
|
Enqueue(stopgap, [&]() { log += 'f'; });
|
|
});
|
|
|
|
Enqueue(base, [&]() {
|
|
log += 'a';
|
|
// This will enqueue the d task from above; Run() is currently running...
|
|
stopgap->SetRealEventTarget(base);
|
|
log += 'b';
|
|
// ...but we call Run inside Run; *this* call to Run will take over, running
|
|
// d, then e and f
|
|
ASSERT_NS_SUCCEEDED(base->Run());
|
|
log += 'c';
|
|
});
|
|
|
|
ASSERT_EQ(log, "");
|
|
ASSERT_NS_SUCCEEDED(base->Run());
|
|
ASSERT_EQ(log, "abdefc");
|
|
|
|
ASSERT_TRUE(base->IsEmpty());
|
|
}
|
|
|
|
TEST(StopGapEventTarget, DropWhileRunning)
|
|
{
|
|
std::string log;
|
|
|
|
auto base = MakeRefPtr<RunnableQueue>();
|
|
|
|
// If we drop the event queue while it still has events, they still run.
|
|
{
|
|
RefPtr<StopGapEventTarget> stopgap = MakeRefPtr<StopGapEventTarget>();
|
|
Enqueue(stopgap, [&]() { log += 'a'; });
|
|
stopgap->SetRealEventTarget(base);
|
|
}
|
|
|
|
ASSERT_EQ(log, "");
|
|
ASSERT_NS_SUCCEEDED(base->Run());
|
|
ASSERT_EQ(log, "a");
|
|
}
|