mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-27 23:02:20 +00:00
Bug 1860969 - Add testcase for incomplete task and rescheduling in TaskController. r=bas
Also fix the null-check. Differential Revision: https://phabricator.services.mozilla.com/D198504
This commit is contained in:
parent
7ebfa02780
commit
2896f9ef0e
@ -9,6 +9,7 @@
|
||||
#include "JSOracleParent.h"
|
||||
#include "js/CallAndConstruct.h" // JS::Call
|
||||
#include "js/ColumnNumber.h" // JS::TaggedColumnNumberOneOrigin, JS::ColumnNumberOneOrigin
|
||||
#include "js/friend/DumpFunctions.h"
|
||||
#include "js/CharacterEncoding.h"
|
||||
#include "js/Date.h" // JS::IsISOStyleDate
|
||||
#include "js/Object.h" // JS::GetClass
|
||||
@ -633,6 +634,7 @@ static mozJSModuleLoader* GetModuleLoaderForCurrentGlobal(
|
||||
RefPtr targetModuleLoader = global->GetModuleLoader(aCx);
|
||||
if (!targetModuleLoader) {
|
||||
// Sandbox without associated window returns nullptr for GetModuleLoader.
|
||||
js::DumpBacktrace(aCx);
|
||||
JS_ReportErrorASCII(aCx, "No ModuleLoader found for the current context");
|
||||
return nullptr;
|
||||
}
|
||||
|
214
xpcom/tests/gtest/TestTaskController.cpp
Normal file
214
xpcom/tests/gtest/TestTaskController.cpp
Normal file
@ -0,0 +1,214 @@
|
||||
/* -*- 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/. */
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include <stdint.h> // uint32_t
|
||||
|
||||
#include "nsString.h" // nsACString
|
||||
#include "nsThreadUtils.h" // NS_ProcessNextEvent
|
||||
#include "mozilla/Atomics.h" // Atomic
|
||||
#include "mozilla/EventQueue.h" // EventQueuePriority
|
||||
#include "mozilla/Mutex.h" // Mutex, MutexAutoLock
|
||||
#include "mozilla/RefPtr.h" // RefPtr, do_AddRef
|
||||
#include "mozilla/TaskController.h" // TaskController, Task
|
||||
#include "prthread.h" // PR_Sleep
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
namespace TestTaskController {
|
||||
|
||||
class Logger {
|
||||
public:
|
||||
Logger() : mMutex("Logger") {}
|
||||
|
||||
void Add(const char* aText) {
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
||||
mLog += aText;
|
||||
}
|
||||
|
||||
const nsAutoCString& GetLog() const { return mLog; }
|
||||
|
||||
private:
|
||||
nsAutoCString mLog;
|
||||
Mutex mMutex;
|
||||
};
|
||||
|
||||
class ReschedulingTask : public Task {
|
||||
static constexpr uint32_t LoopCount = 3;
|
||||
|
||||
public:
|
||||
explicit ReschedulingTask(Kind aKind, Logger* aLogger, const char* aName)
|
||||
: Task(aKind, EventQueuePriority::Normal),
|
||||
mCount(0),
|
||||
mIsDone(false),
|
||||
mLogger(aLogger),
|
||||
mName(aName) {}
|
||||
|
||||
TaskResult Run() override {
|
||||
mLogger->Add(mName);
|
||||
|
||||
mCount++;
|
||||
|
||||
if (mCount < LoopCount) {
|
||||
return TaskResult::Incomplete;
|
||||
}
|
||||
|
||||
mIsDone = true;
|
||||
|
||||
return TaskResult::Complete;
|
||||
}
|
||||
|
||||
#ifdef MOZ_COLLECTING_RUNNABLE_TELEMETRY
|
||||
bool GetName(nsACString& aName) override {
|
||||
aName.AssignLiteral("AsyncScriptCompileTask");
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool IsDone() const { return mIsDone; }
|
||||
|
||||
private:
|
||||
Atomic<uint32_t> mCount;
|
||||
Atomic<bool> mIsDone;
|
||||
Logger* mLogger;
|
||||
const char* mName;
|
||||
};
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
TEST(TaskController, RescheduleOnMainThread)
|
||||
{
|
||||
Logger logger;
|
||||
|
||||
RefPtr<ReschedulingTask> mainThreadTask =
|
||||
new ReschedulingTask(Task::Kind::MainThreadOnly, &logger, "1");
|
||||
|
||||
TaskController::Get()->AddTask(do_AddRef(mainThreadTask));
|
||||
|
||||
while (NS_ProcessNextEvent(nullptr, false)) {
|
||||
}
|
||||
|
||||
ASSERT_TRUE(mainThreadTask->IsDone());
|
||||
|
||||
ASSERT_TRUE(logger.GetLog() == "111");
|
||||
}
|
||||
|
||||
TEST(TaskController, RescheduleOffMainThread)
|
||||
{
|
||||
Logger logger;
|
||||
|
||||
RefPtr<ReschedulingTask> offThreadTask =
|
||||
new ReschedulingTask(Task::Kind::OffMainThreadOnly, &logger, "1");
|
||||
|
||||
TaskController::Get()->AddTask(do_AddRef(offThreadTask));
|
||||
|
||||
uint32_t count = 0;
|
||||
while (!offThreadTask->IsDone() && count < 100) {
|
||||
PR_Sleep(PR_MillisecondsToInterval(100));
|
||||
count++;
|
||||
}
|
||||
ASSERT_TRUE(offThreadTask->IsDone());
|
||||
|
||||
ASSERT_TRUE(logger.GetLog() == "111");
|
||||
}
|
||||
|
||||
TEST(TaskController, RescheduleMainAndOffMainThreads)
|
||||
{
|
||||
Logger logger;
|
||||
|
||||
RefPtr<ReschedulingTask> offThreadTask =
|
||||
new ReschedulingTask(Task::Kind::OffMainThreadOnly, &logger, "1");
|
||||
RefPtr<ReschedulingTask> mainThreadTask =
|
||||
new ReschedulingTask(Task::Kind::MainThreadOnly, &logger, "2");
|
||||
|
||||
mainThreadTask->AddDependency(offThreadTask.get());
|
||||
|
||||
TaskController::Get()->AddTask(do_AddRef(offThreadTask));
|
||||
TaskController::Get()->AddTask(do_AddRef(mainThreadTask));
|
||||
|
||||
uint32_t count = 0;
|
||||
while (!offThreadTask->IsDone() && count < 100) {
|
||||
PR_Sleep(PR_MillisecondsToInterval(100));
|
||||
count++;
|
||||
}
|
||||
ASSERT_TRUE(offThreadTask->IsDone());
|
||||
|
||||
// At this point, the main thread task shouldn't have run.
|
||||
ASSERT_TRUE(logger.GetLog() == "111");
|
||||
|
||||
while (NS_ProcessNextEvent(nullptr, false)) {
|
||||
}
|
||||
|
||||
ASSERT_TRUE(mainThreadTask->IsDone());
|
||||
|
||||
ASSERT_TRUE(logger.GetLog() == "111222");
|
||||
}
|
||||
|
||||
TEST(TaskController, RescheduleOrder)
|
||||
{
|
||||
Logger logger;
|
||||
|
||||
RefPtr<ReschedulingTask> mainThreadTask1 =
|
||||
new ReschedulingTask(Task::Kind::MainThreadOnly, &logger, "1");
|
||||
RefPtr<ReschedulingTask> mainThreadTask2 =
|
||||
new ReschedulingTask(Task::Kind::MainThreadOnly, &logger, "2");
|
||||
RefPtr<ReschedulingTask> mainThreadTask3 =
|
||||
new ReschedulingTask(Task::Kind::MainThreadOnly, &logger, "3");
|
||||
|
||||
TaskController::Get()->AddTask(do_AddRef(mainThreadTask1));
|
||||
TaskController::Get()->AddTask(do_AddRef(mainThreadTask2));
|
||||
TaskController::Get()->AddTask(do_AddRef(mainThreadTask3));
|
||||
|
||||
while (NS_ProcessNextEvent(nullptr, false)) {
|
||||
}
|
||||
|
||||
ASSERT_TRUE(mainThreadTask1->IsDone());
|
||||
ASSERT_TRUE(mainThreadTask2->IsDone());
|
||||
ASSERT_TRUE(mainThreadTask3->IsDone());
|
||||
|
||||
// Rescheduled tasks should be added to the beginning of the queue.
|
||||
ASSERT_TRUE(logger.GetLog() == "111222333");
|
||||
}
|
||||
|
||||
TEST(TaskController, RescheduleOrderOffMainThread)
|
||||
{
|
||||
Logger logger1;
|
||||
Logger logger2;
|
||||
Logger logger3;
|
||||
|
||||
RefPtr<ReschedulingTask> offThreadTask1 =
|
||||
new ReschedulingTask(Task::Kind::OffMainThreadOnly, &logger1, "1");
|
||||
RefPtr<ReschedulingTask> offThreadTask2 =
|
||||
new ReschedulingTask(Task::Kind::OffMainThreadOnly, &logger2, "2");
|
||||
RefPtr<ReschedulingTask> offThreadTask3 =
|
||||
new ReschedulingTask(Task::Kind::OffMainThreadOnly, &logger3, "3");
|
||||
|
||||
TaskController::Get()->AddTask(do_AddRef(offThreadTask1));
|
||||
TaskController::Get()->AddTask(do_AddRef(offThreadTask2));
|
||||
TaskController::Get()->AddTask(do_AddRef(offThreadTask3));
|
||||
|
||||
uint32_t count = 0;
|
||||
while (!(offThreadTask1->IsDone() && offThreadTask2->IsDone() &&
|
||||
offThreadTask3->IsDone()) &&
|
||||
count < 100) {
|
||||
PR_Sleep(PR_MillisecondsToInterval(100));
|
||||
count++;
|
||||
}
|
||||
|
||||
ASSERT_TRUE(offThreadTask1->IsDone());
|
||||
ASSERT_TRUE(offThreadTask2->IsDone());
|
||||
ASSERT_TRUE(offThreadTask3->IsDone());
|
||||
|
||||
// Rescheduled tasks should be enqueued.
|
||||
// The order between off-thread tasks are not deterministic.
|
||||
ASSERT_TRUE(logger1.GetLog() == "111");
|
||||
ASSERT_TRUE(logger2.GetLog() == "222");
|
||||
ASSERT_TRUE(logger3.GetLog() == "333");
|
||||
}
|
||||
|
||||
} // namespace TestTaskController
|
@ -61,6 +61,7 @@ UNIFIED_SOURCES += [
|
||||
"TestSynchronization.cpp",
|
||||
"TestTArray.cpp",
|
||||
"TestTArray2.cpp",
|
||||
"TestTaskController.cpp",
|
||||
"TestTaskQueue.cpp",
|
||||
"TestTextFormatter.cpp",
|
||||
"TestThreadManager.cpp",
|
||||
|
@ -927,7 +927,9 @@ bool TaskController::DoExecuteNextTaskOnlyMainThreadInternal(
|
||||
mMainThreadTasks.insert(std::move(mCurrentTasksMT.top()));
|
||||
MOZ_ASSERT(insertion.second);
|
||||
task->mIterator = insertion.first;
|
||||
manager->WillRunTask();
|
||||
if (manager) {
|
||||
manager->WillRunTask();
|
||||
}
|
||||
} else {
|
||||
task->mCompleted = true;
|
||||
#ifdef DEBUG
|
||||
|
Loading…
Reference in New Issue
Block a user