TEST_P(DedicatedWorkerTest, PendingActivity_SetIntervalOnMessageEvent) {
  // Start a repeated timer on a message event, and stop it when another
  // message is received. The timer needs a non-zero delay or else worker
  // activities would not run.
  const String sourceCode =
      "var count = 0;"
      "var id;"
      "addEventListener('message', function(event) {"
      "  if (count++ == 0) {"
      "    id = setInterval(function() {}, 50);"
      "  } else {"
      "    clearInterval(id);"
      "  }"
      "});";
  startWithSourceCode(sourceCode);

  // Worker initialization should be counted as a pending activity.
  EXPECT_TRUE(
      workerMessagingProxy()->workerGlobalScopeMayHavePendingActivity());
  workerMessagingProxy()->waitUntil(WaitUntilMode::PendingActivityReported);
  EXPECT_FALSE(
      workerMessagingProxy()->workerGlobalScopeMayHavePendingActivity());

  // The first message event sets the active timer that is counted as a
  // pending activity.
  dispatchMessageEvent();
  EXPECT_EQ(1u, workerMessagingProxy()->unconfirmedMessageCount());
  EXPECT_TRUE(
      workerMessagingProxy()->workerGlobalScopeMayHavePendingActivity());
  workerMessagingProxy()->waitUntil(WaitUntilMode::MessageConfirmed);
  EXPECT_EQ(0u, workerMessagingProxy()->unconfirmedMessageCount());
  EXPECT_TRUE(
      workerMessagingProxy()->workerGlobalScopeMayHavePendingActivity());

  // Run the message loop for a while to make sure the timer is counted as a
  // pending activity until it's stopped. The delay is equal to the max
  // interval so that the pending activity timer may be able to have a chance
  // to run before the next expectation check.
  const double kDelayInMs = kMaxIntervalInSec * 1000;
  testing::runDelayedTasks(kDelayInMs);
  EXPECT_TRUE(
      workerMessagingProxy()->workerGlobalScopeMayHavePendingActivity());

  // Stop the timer.
  dispatchMessageEvent();
  EXPECT_EQ(1u, workerMessagingProxy()->unconfirmedMessageCount());
  EXPECT_TRUE(
      workerMessagingProxy()->workerGlobalScopeMayHavePendingActivity());
  workerMessagingProxy()->waitUntil(WaitUntilMode::MessageConfirmed);
  EXPECT_EQ(0u, workerMessagingProxy()->unconfirmedMessageCount());
  EXPECT_TRUE(
      workerMessagingProxy()->workerGlobalScopeMayHavePendingActivity());

  // There should be no pending activities after the timer is stopped.
  workerMessagingProxy()->waitUntil(WaitUntilMode::PendingActivityReported);
  EXPECT_FALSE(
      workerMessagingProxy()->workerGlobalScopeMayHavePendingActivity());
}
TEST_P(DedicatedWorkerTest, PendingActivity_SetInterval) {
  // Start a repeated timer on initial script evaluation, and stop it when a
  // message is received. The timer needs a non-zero delay or else worker
  // activities would not run.
  const String sourceCode =
      "var id = setInterval(function() {}, 50);"
      "addEventListener('message', function(event) { clearInterval(id); });";
  startWithSourceCode(sourceCode);

  // Worker initialization should be counted as a pending activity.
  EXPECT_TRUE(
      workerMessagingProxy()->workerGlobalScopeMayHavePendingActivity());

  // Stop the timer.
  dispatchMessageEvent();
  EXPECT_EQ(1u, workerMessagingProxy()->unconfirmedMessageCount());
  EXPECT_TRUE(
      workerMessagingProxy()->workerGlobalScopeMayHavePendingActivity());
  workerMessagingProxy()->waitUntil(WaitUntilMode::MessageConfirmed);
  EXPECT_EQ(0u, workerMessagingProxy()->unconfirmedMessageCount());
  EXPECT_TRUE(
      workerMessagingProxy()->workerGlobalScopeMayHavePendingActivity());

  // There should be no pending activities after the timer is stopped.
  workerMessagingProxy()->waitUntil(WaitUntilMode::PendingActivityReported);
  EXPECT_FALSE(
      workerMessagingProxy()->workerGlobalScopeMayHavePendingActivity());
}
TEST_P(DedicatedWorkerTest, PendingActivity_SetTimeoutOnMessageEvent) {
  // Start an oneshot timer on a message event.
  const String sourceCode =
      "addEventListener('message', function(event) {"
      "  setTimeout(function() {}, 0);"
      "});";
  startWithSourceCode(sourceCode);

  // Worker initialization should be counted as a pending activity.
  EXPECT_TRUE(
      workerMessagingProxy()->workerGlobalScopeMayHavePendingActivity());
  workerMessagingProxy()->waitUntil(WaitUntilMode::PendingActivityReported);
  EXPECT_FALSE(
      workerMessagingProxy()->workerGlobalScopeMayHavePendingActivity());

  // A message starts the oneshot timer that is counted as a pending activity.
  dispatchMessageEvent();
  EXPECT_EQ(1u, workerMessagingProxy()->unconfirmedMessageCount());
  EXPECT_TRUE(
      workerMessagingProxy()->workerGlobalScopeMayHavePendingActivity());
  workerMessagingProxy()->waitUntil(WaitUntilMode::MessageConfirmed);
  EXPECT_EQ(0u, workerMessagingProxy()->unconfirmedMessageCount());
  EXPECT_TRUE(
      workerMessagingProxy()->workerGlobalScopeMayHavePendingActivity());

  // The timer is fired soon and there should be no pending activities after
  // that.
  workerMessagingProxy()->waitUntil(WaitUntilMode::PendingActivityReported);
  EXPECT_FALSE(
      workerMessagingProxy()->workerGlobalScopeMayHavePendingActivity());
}
Exemple #4
0
void EventSource::parseEventStreamLine(unsigned position, Optional<unsigned> fieldLength, unsigned lineLength)
{
    if (!lineLength) {
        if (!m_data.isEmpty())
            dispatchMessageEvent();
        m_eventName = { };
        return;
    }

    if (fieldLength && !fieldLength.value())
        return;

    StringView field { &m_receiveBuffer[position], fieldLength ? fieldLength.value() : lineLength };

    unsigned step;
    if (!fieldLength)
        step = lineLength;
    else if (m_receiveBuffer[position + fieldLength.value() + 1] != ' ')
        step = fieldLength.value() + 1;
    else
        step = fieldLength.value() + 2;
    position += step;
    unsigned valueLength = lineLength - step;

    if (field == "data") {
        m_data.append(&m_receiveBuffer[position], valueLength);
        m_data.append('\n');
    } else if (field == "event")
        m_eventName = { &m_receiveBuffer[position], valueLength };
    else if (field == "id")
        m_currentlyParsedEventId = { &m_receiveBuffer[position], valueLength };
    else if (field == "retry") {
        if (!valueLength)
            m_reconnectDelay = defaultReconnectDelay;
        else {
            // FIXME: Do we really want to ignore trailing garbage here? Should we be using the strict version instead?
            // FIXME: If we can't parse the value, should we leave m_reconnectDelay alone or set it to defaultReconnectDelay?
            bool ok;
            auto reconnectDelay = charactersToUInt64(&m_receiveBuffer[position], valueLength, &ok);
            if (ok)
                m_reconnectDelay = reconnectDelay;
        }
    }
}