blob: 85c06d9aa96519ce4f3a7f680010c105b9c61d1e [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "platform/testing/UnitTestHelpers.h"
#include "public/platform/Platform.h"
#include "public/platform/WebViewScheduler.h"
#include "public/web/WebLocalFrame.h"
#include "public/web/WebScriptExecutionCallback.h"
#include "public/web/WebScriptSource.h"
#include "public/web/WebView.h"
#include "web/tests/sim/SimRequest.h"
#include "web/tests/sim/SimTest.h"
namespace blink {
namespace {
class ScriptExecutionCallbackHelper : public WebScriptExecutionCallback {
public:
const String result() const { return m_result; }
private:
void completed(const WebVector<v8::Local<v8::Value>>& values) override
{
if (!values.isEmpty() && !values[0].IsEmpty() && values[0]->IsString()) {
m_result = toCoreString(v8::Local<v8::String>::Cast(values[0]));
}
}
String m_result;
};
} // namespace
class VirtualTimeTest : public SimTest {
protected:
String ExecuteJavaScript(String scriptSource)
{
ScriptExecutionCallbackHelper callbackHelper;
webView().mainFrame()->toWebLocalFrame()->requestExecuteScriptAndReturnValue(
WebScriptSource(WebString(scriptSource)), false, &callbackHelper);
testing::runPendingTasks();
return callbackHelper.result();
}
};
TEST_F(VirtualTimeTest, DOMTimersFireInExpectedOrder)
{
webView().scheduler()->enableVirtualTime();
ExecuteJavaScript(
"var run_order = [];"
"function timerFn(delay, value) {"
" setTimeout(function() { run_order.push(value); }, delay);"
"};"
"var one_hour = 60 * 60 * 1000;"
"timerFn(one_hour * 100, 'a');"
"timerFn(one_hour * 10, 'b');"
"timerFn(one_hour, 'c');");
// Normally the JS runs pretty much instantly but the timer callbacks will
// take 100h to fire, but thanks to timer fast forwarding we can make them
// fire immediatly.
EXPECT_EQ("c, b, a", ExecuteJavaScript("run_order.join(', ')"));
}
TEST_F(VirtualTimeTest, SetInterval)
{
webView().scheduler()->enableVirtualTime();
ExecuteJavaScript(
"var run_order = [];"
"var count = 10;"
"var interval_handle = setInterval(function() {"
" if (--window.count == 0) {"
" clearInterval(interval_handle);"
" }"
" run_order.push(count);"
"}, 1000);"
"setTimeout(function() { run_order.push('timer'); }, 1500);");
// If virtual time is not supplied to TimerBase then the setInterval
// won't fire 10x.
EXPECT_EQ("9, timer, 8, 7, 6, 5, 4, 3, 2, 1, 0", ExecuteJavaScript("run_order.join(', ')"));
}
TEST_F(VirtualTimeTest, AllowVirtualTimeToAdvance)
{
webView().scheduler()->enableVirtualTime();
webView().scheduler()->setVirtualTimePolicy(WebViewScheduler::VirtualTimePolicy::PAUSE);
ExecuteJavaScript(
"var run_order = [];"
"timerFn = function(delay, value) {"
" setTimeout(function() { run_order.push(value); }, delay);"
"};"
"timerFn(100, 'a');"
"timerFn(10, 'b');"
"timerFn(1, 'c');");
EXPECT_EQ("", ExecuteJavaScript("run_order.join(', ')"));
webView().scheduler()->setVirtualTimePolicy(WebViewScheduler::VirtualTimePolicy::ADVANCE);
testing::runPendingTasks();
EXPECT_EQ("c, b, a", ExecuteJavaScript("run_order.join(', ')"));
}
TEST_F(VirtualTimeTest, VirtualTimeNotAllowedToAdvanceWhileResourcesLoading)
{
webView().scheduler()->enableVirtualTime();
webView().scheduler()->setVirtualTimePolicy(WebViewScheduler::VirtualTimePolicy::DETERMINISTIC_LOADING);
EXPECT_TRUE(webView().scheduler()->virtualTimeAllowedToAdvance());
SimRequest mainResource("https://example.com/test.html", "text/html");
SimRequest cssResource("https://example.com/test.css", "text/css");
// Not loading, virtual time should be able to advance.
EXPECT_TRUE(webView().scheduler()->virtualTimeAllowedToAdvance());
// Loading, virtual time should not advance.
loadURL("https://example.com/test.html");
EXPECT_FALSE(webView().scheduler()->virtualTimeAllowedToAdvance());
mainResource.start();
// Still Loading, virtual time should not advance.
mainResource.write("<!DOCTYPE html><link rel=stylesheet href=test.css>");
EXPECT_FALSE(webView().scheduler()->virtualTimeAllowedToAdvance());
// Still Loading, virtual time should not advance.
cssResource.start();
cssResource.write("a { color: red; }");
EXPECT_FALSE(webView().scheduler()->virtualTimeAllowedToAdvance());
// Still Loading, virtual time should not advance.
cssResource.finish();
EXPECT_FALSE(webView().scheduler()->virtualTimeAllowedToAdvance());
// Still Loading, virtual time should not advance.
mainResource.write("<body>");
EXPECT_FALSE(webView().scheduler()->virtualTimeAllowedToAdvance());
// Finished loading, virtual time should be able to advance.
mainResource.finish();
EXPECT_TRUE(webView().scheduler()->virtualTimeAllowedToAdvance());
}
} // namespace blink