// Tests that v8::Isolate and WebThread are correctly set-up if a worker is created while another is terminating.
TEST_F(CompositorWorkerThreadTest, CreatingSecondDuringTerminationOfFirst)
{
    OwnPtr<WaitableEvent> firstCreationEvent = adoptPtr(new WaitableEvent());
    OwnPtr<TestCompositorWorkerThread> firstWorker = createCompositorWorker(firstCreationEvent.get());
    waitForWaitableEventAfterIteratingCurrentLoop(firstCreationEvent.get());
    v8::Isolate* firstIsolate = firstWorker->isolate();
    ASSERT(firstIsolate);

    // Request termination of the first worker, and set-up to make sure the second worker is created right as
    // the first worker terminates its isolate.
    OwnPtr<WaitableEvent> secondCreationEvent = adoptPtr(new WaitableEvent());
    OwnPtr<CompositorWorkerThread> secondWorker;
    firstWorker->setCallbackAfterV8Termination(bind(&CompositorWorkerThreadTest::createWorkerAdapter, this, &secondWorker, secondCreationEvent.get()));
    firstWorker->terminateAndWait();
    ASSERT(secondWorker);

    waitForWaitableEventAfterIteratingCurrentLoop(secondCreationEvent.get());
    v8::Isolate* secondIsolate = secondWorker->isolate();
    ASSERT(secondIsolate);
    EXPECT_EQ(firstIsolate, secondIsolate);

    // Verify that the isolate can run some scripts correctly in the second worker.
    checkWorkerCanExecuteScript(secondWorker.get());
    secondWorker->terminateAndWait();
}
// Tests that a new WebThread is created if all existing workers are terminated before a new worker is created.
TEST_F(CompositorWorkerThreadTest, TerminateFirstAndCreateSecond)
{
    // Create the first worker, wait until it is initialized, and terminate it.
    OwnPtr<WaitableEvent> creationEvent = adoptPtr(new WaitableEvent());
    OwnPtr<CompositorWorkerThread> compositorWorker = createCompositorWorker(creationEvent.get());
    WebThreadSupportingGC* firstThread = CompositorWorkerThread::sharedBackingThread();
    waitForWaitableEventAfterIteratingCurrentLoop(creationEvent.get());
    ASSERT(compositorWorker->isolate());
    compositorWorker->terminateAndWait();

    // Create the second worker. Verify that the second worker lives in a different WebThread since the first
    // thread will have been destroyed after destroying the first worker.
    creationEvent = adoptPtr(new WaitableEvent());
    compositorWorker = createCompositorWorker(creationEvent.get());
    WebThreadSupportingGC* secondThread = CompositorWorkerThread::sharedBackingThread();
    EXPECT_NE(firstThread, secondThread);
    waitForWaitableEventAfterIteratingCurrentLoop(creationEvent.get());

    // Jump over to the worker's thread to verify that the Isolate is set up correctly and execute script.
    OwnPtr<WaitableEvent> checkEvent = adoptPtr(new WaitableEvent());
    secondThread->platformThread().getWebTaskRunner()->postTask(BLINK_FROM_HERE, threadSafeBind(&checkCurrentIsolate, AllowCrossThreadAccess(compositorWorker->isolate()), AllowCrossThreadAccess(checkEvent.get())));
    waitForWaitableEventAfterIteratingCurrentLoop(checkEvent.get());
    checkWorkerCanExecuteScript(compositorWorker.get());

    compositorWorker->terminateAndWait();
}
// Tests that the same WebThread is used for new workers if the WebThread is still alive.
TEST_F(CompositorWorkerThreadTest, CreateSecondAndTerminateFirst)
{
    // Create the first worker and wait until it is initialized.
    OwnPtr<WaitableEvent> firstCreationEvent = adoptPtr(new WaitableEvent());
    OwnPtr<CompositorWorkerThread> firstWorker = createCompositorWorker(firstCreationEvent.get());
    WebThreadSupportingGC* firstThread = CompositorWorkerThread::sharedBackingThread();
    ASSERT(firstThread);
    waitForWaitableEventAfterIteratingCurrentLoop(firstCreationEvent.get());
    v8::Isolate* firstIsolate = firstWorker->isolate();
    ASSERT(firstIsolate);

    // Create the second worker and immediately destroy the first worker.
    OwnPtr<WaitableEvent> secondCreationEvent = adoptPtr(new WaitableEvent());
    OwnPtr<CompositorWorkerThread> secondWorker = createCompositorWorker(secondCreationEvent.get());
    firstWorker->terminateAndWait();

    // Wait until the second worker is initialized. Verify that the second worker is using the same
    // thread and Isolate as the first worker.
    WebThreadSupportingGC* secondThread = CompositorWorkerThread::sharedBackingThread();
    ASSERT(secondThread);
    waitForWaitableEventAfterIteratingCurrentLoop(secondCreationEvent.get());
    EXPECT_EQ(firstThread, secondThread);

    v8::Isolate* secondIsolate = secondWorker->isolate();
    ASSERT(secondIsolate);
    EXPECT_EQ(firstIsolate, secondIsolate);

    // Verify that the worker can still successfully execute script.
    checkWorkerCanExecuteScript(secondWorker.get());

    secondWorker->terminateAndWait();
}
TEST_F(CompositorWorkerThreadTest, Basic)
{
    OwnPtr<WaitableEvent> creationEvent = adoptPtr(new WaitableEvent());
    OwnPtr<CompositorWorkerThread> compositorWorker = createCompositorWorker(creationEvent.get());
    waitForWaitableEventAfterIteratingCurrentLoop(creationEvent.get());
    checkWorkerCanExecuteScript(compositorWorker.get());
    compositorWorker->terminateAndWait();
}
TEST_F(CompositorWorkerManagerTest, Basic)
{
    OwnPtr<WebWaitableEvent> creationEvent = adoptPtr(Platform::current()->createWaitableEvent());
    RefPtr<CompositorWorkerThread> compositorWorker = createCompositorWorker(creationEvent.get());
    waitForWaitableEventAfterIteratingCurrentLoop(creationEvent.get());
    checkWorkerCanExecuteScript(compositorWorker.get());
    compositorWorker->terminateAndWait();
}