| OLD | NEW |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "core/frame/DOMTimer.h" | 5 #include "core/frame/DOMTimer.h" |
| 6 | 6 |
| 7 #include <vector> | 7 #include <vector> |
| 8 | 8 |
| 9 #include "bindings/core/v8/ScriptController.h" | 9 #include "bindings/core/v8/ScriptController.h" |
| 10 #include "bindings/core/v8/ScriptSourceCode.h" | 10 #include "bindings/core/v8/ScriptSourceCode.h" |
| 11 #include "bindings/core/v8/V8Binding.h" | 11 #include "bindings/core/v8/V8Binding.h" |
| 12 #include "core/dom/Document.h" | 12 #include "core/dom/Document.h" |
| 13 #include "core/layout/LayoutTestHelper.h" | 13 #include "core/layout/LayoutTestHelper.h" |
| 14 #include "platform/testing/TestingPlatformSupport.h" | 14 #include "platform/testing/TestingPlatformSupport.h" |
| 15 #include "testing/gmock/include/gmock/gmock.h" | 15 #include "testing/gmock/include/gmock/gmock.h" |
| 16 #include "testing/gtest/include/gtest/gtest.h" | 16 #include "testing/gtest/include/gtest/gtest.h" |
| 17 | 17 |
| 18 using testing::DoubleNear; | 18 using testing::DoubleNear; |
| 19 using testing::ElementsAreArray; | 19 using testing::ElementsAreArray; |
| 20 using testing::Matcher; | 20 using testing::Matcher; |
| 21 | 21 |
| 22 namespace blink { | 22 namespace blink { |
| 23 | 23 |
| 24 namespace { | 24 namespace { |
| 25 | 25 |
| 26 const double kThreshold = 0.000001; |
| 27 |
| 26 class DOMTimerTest : public RenderingTest { | 28 class DOMTimerTest : public RenderingTest { |
| 27 public: | 29 public: |
| 28 ScopedTestingPlatformSupport<TestingPlatformSupportWithMockScheduler> | 30 ScopedTestingPlatformSupport<TestingPlatformSupportWithMockScheduler> |
| 29 platform_; | 31 platform_; |
| 30 | 32 |
| 31 // Expected time between each iterator for setInterval(..., 1) or nested | 33 // Expected time between each iterator for setInterval(..., 1) or nested |
| 32 // setTimeout(..., 1) are 1, 1, 1, 1, 4, 4, ... as a minumum clamp of 4m | 34 // setTimeout(..., 1) are 1, 1, 1, 1, 4, 4, ... as a minumum clamp of 4m |
| 33 // is applied from the 5th iteration onwards. | 35 // is applied from the 5th iteration onwards. |
| 34 const std::vector<Matcher<double>> kExpectedTimings = { | 36 const std::vector<Matcher<double>> kExpectedTimings = { |
| 35 DoubleNear(1., 0.000001), DoubleNear(1., 0.000001), | 37 DoubleNear(1., kThreshold), DoubleNear(1., kThreshold), |
| 36 DoubleNear(1., 0.000001), DoubleNear(1., 0.000001), | 38 DoubleNear(1., kThreshold), DoubleNear(1., kThreshold), |
| 37 DoubleNear(4., 0.000001), DoubleNear(4., 0.000001), | 39 DoubleNear(4., kThreshold), DoubleNear(4., kThreshold), |
| 38 }; | 40 }; |
| 39 | 41 |
| 40 void SetUp() override { | 42 void SetUp() override { |
| 41 platform_->SetAutoAdvanceNowToPendingTasks(true); | 43 platform_->SetAutoAdvanceNowToPendingTasks(true); |
| 42 // Advance timer manually as RenderingTest expects the time to be non-zero. | 44 // Advance timer manually as RenderingTest expects the time to be non-zero. |
| 43 platform_->AdvanceClockSeconds(1.); | 45 platform_->AdvanceClockSeconds(1.); |
| 44 RenderingTest::SetUp(); | 46 RenderingTest::SetUp(); |
| 45 // Advance timer again as otherwise the time between the first call to | 47 // Advance timer again as otherwise the time between the first call to |
| 46 // setInterval and it running will be off by 5us. | 48 // setInterval and it running will be off by 5us. |
| 47 platform_->AdvanceClockSeconds(1); | 49 platform_->AdvanceClockSeconds(1); |
| 48 GetDocument().GetSettings()->SetScriptEnabled(true); | 50 GetDocument().GetSettings()->SetScriptEnabled(true); |
| 49 } | 51 } |
| 50 | 52 |
| 51 v8::Local<v8::Value> EvalExpression(const char* expr) { | 53 v8::Local<v8::Value> EvalExpression(const char* expr) { |
| 52 return GetDocument() | 54 return GetDocument() |
| 53 .GetFrame() | 55 .GetFrame() |
| 54 ->Script() | 56 ->Script() |
| 55 .ExecuteScriptInMainWorldAndReturnValue(ScriptSourceCode(expr)); | 57 .ExecuteScriptInMainWorldAndReturnValue(ScriptSourceCode(expr)); |
| 56 } | 58 } |
| 57 | 59 |
| 58 Vector<double> ToDoubleArray(v8::Local<v8::Value> value, | 60 Vector<double> ToDoubleArray(v8::Local<v8::Value> value, |
| 59 v8::HandleScope& scope) { | 61 v8::HandleScope& scope) { |
| 60 NonThrowableExceptionState exception_state; | 62 NonThrowableExceptionState exception_state; |
| 61 return ToImplArray<Vector<double>>(value, 0, scope.GetIsolate(), | 63 return ToImplArray<Vector<double>>(value, 0, scope.GetIsolate(), |
| 62 exception_state); | 64 exception_state); |
| 63 } | 65 } |
| 64 | 66 |
| 67 double ToDoubleValue(v8::Local<v8::Value> value, v8::HandleScope& scope) { |
| 68 NonThrowableExceptionState exceptionState; |
| 69 return ToDouble(scope.GetIsolate(), value, exceptionState); |
| 70 } |
| 71 |
| 65 void ExecuteScriptAndWaitUntilIdle(const char* script_text) { | 72 void ExecuteScriptAndWaitUntilIdle(const char* script_text) { |
| 66 ScriptSourceCode script(script_text); | 73 ScriptSourceCode script(script_text); |
| 67 GetDocument().GetFrame()->Script().ExecuteScriptInMainWorld(script); | 74 GetDocument().GetFrame()->Script().ExecuteScriptInMainWorld(script); |
| 68 platform_->RunUntilIdle(); | 75 platform_->RunUntilIdle(); |
| 69 } | 76 } |
| 70 }; | 77 }; |
| 71 | 78 |
| 72 const char* g_k_set_timeout_script_text = | 79 const char* const kSetTimeout0ScriptText = |
| 73 "var id;" | 80 "var last = performance.now();" |
| 81 "var elapsed;" |
| 82 "function setTimeoutCallback() {" |
| 83 " var current = performance.now();" |
| 84 " elapsed = current - last;" |
| 85 " times.push(elapsed);" |
| 86 "}" |
| 87 "setTimeout(setTimeoutCallback, 0);"; |
| 88 |
| 89 TEST_F(DOMTimerTest, setTimeout_ZeroIsNotClampedToOne) { |
| 90 v8::HandleScope scope(v8::Isolate::GetCurrent()); |
| 91 |
| 92 ExecuteScriptAndWaitUntilIdle(kSetTimeout0ScriptText); |
| 93 |
| 94 double time = ToDoubleValue(EvalExpression("elapsed"), scope); |
| 95 |
| 96 EXPECT_THAT(time, DoubleNear(0., kThreshold)); |
| 97 } |
| 98 |
| 99 const char* const kSetTimeoutNestedScriptText = |
| 74 "var last = performance.now();" | 100 "var last = performance.now();" |
| 75 "var times = [];" | 101 "var times = [];" |
| 76 "function nestSetTimeouts() {" | 102 "function nestSetTimeouts() {" |
| 77 " var current = performance.now();" | 103 " var current = performance.now();" |
| 78 " var elapsed = current - last;" | 104 " var elapsed = current - last;" |
| 79 " last = current;" | 105 " last = current;" |
| 80 " times.push(elapsed);" | 106 " times.push(elapsed);" |
| 81 " if (times.length < 6) {" | 107 " if (times.length < 6) {" |
| 82 " setTimeout(nestSetTimeouts, 1);" | 108 " setTimeout(nestSetTimeouts, 1);" |
| 83 " }" | 109 " }" |
| 84 "}" | 110 "}" |
| 85 "setTimeout(nestSetTimeouts, 1);"; | 111 "setTimeout(nestSetTimeouts, 1);"; |
| 86 | 112 |
| 87 TEST_F(DOMTimerTest, setTimeout_ClampsAfter4Nestings) { | 113 TEST_F(DOMTimerTest, setTimeout_ClampsAfter4Nestings) { |
| 88 v8::HandleScope scope(v8::Isolate::GetCurrent()); | 114 v8::HandleScope scope(v8::Isolate::GetCurrent()); |
| 89 | 115 |
| 90 ExecuteScriptAndWaitUntilIdle(g_k_set_timeout_script_text); | 116 ExecuteScriptAndWaitUntilIdle(kSetTimeoutNestedScriptText); |
| 91 | 117 |
| 92 auto times(ToDoubleArray(EvalExpression("times"), scope)); | 118 auto times(ToDoubleArray(EvalExpression("times"), scope)); |
| 93 | 119 |
| 94 EXPECT_THAT(times, ElementsAreArray(kExpectedTimings)); | 120 EXPECT_THAT(times, ElementsAreArray(kExpectedTimings)); |
| 95 } | 121 } |
| 96 | 122 |
| 97 const char* g_k_set_interval_script_text = | 123 const char* const kSetIntervalScriptText = |
| 98 "var last = performance.now();" | 124 "var last = performance.now();" |
| 99 "var times = [];" | 125 "var times = [];" |
| 100 "var id = setInterval(function() {" | 126 "var id = setInterval(function() {" |
| 101 " var current = performance.now();" | 127 " var current = performance.now();" |
| 102 " var elapsed = current - last;" | 128 " var elapsed = current - last;" |
| 103 " last = current;" | 129 " last = current;" |
| 104 " times.push(elapsed);" | 130 " times.push(elapsed);" |
| 105 " if (times.length > 5) {" | 131 " if (times.length > 5) {" |
| 106 " clearInterval(id);" | 132 " clearInterval(id);" |
| 107 " }" | 133 " }" |
| 108 "}, 1);"; | 134 "}, 1);"; |
| 109 | 135 |
| 110 TEST_F(DOMTimerTest, setInterval_ClampsAfter4Iterations) { | 136 TEST_F(DOMTimerTest, setInterval_ClampsAfter4Iterations) { |
| 111 v8::HandleScope scope(v8::Isolate::GetCurrent()); | 137 v8::HandleScope scope(v8::Isolate::GetCurrent()); |
| 112 | 138 |
| 113 ExecuteScriptAndWaitUntilIdle(g_k_set_interval_script_text); | 139 ExecuteScriptAndWaitUntilIdle(kSetIntervalScriptText); |
| 114 | 140 |
| 115 auto times(ToDoubleArray(EvalExpression("times"), scope)); | 141 auto times(ToDoubleArray(EvalExpression("times"), scope)); |
| 116 | 142 |
| 117 EXPECT_THAT(times, ElementsAreArray(kExpectedTimings)); | 143 EXPECT_THAT(times, ElementsAreArray(kExpectedTimings)); |
| 118 } | 144 } |
| 119 | 145 |
| 120 TEST_F(DOMTimerTest, setInterval_NestingResetsForLaterCalls) { | 146 TEST_F(DOMTimerTest, setInterval_NestingResetsForLaterCalls) { |
| 121 v8::HandleScope scope(v8::Isolate::GetCurrent()); | 147 v8::HandleScope scope(v8::Isolate::GetCurrent()); |
| 122 | 148 |
| 123 ExecuteScriptAndWaitUntilIdle(g_k_set_interval_script_text); | 149 ExecuteScriptAndWaitUntilIdle(kSetIntervalScriptText); |
| 124 | 150 |
| 125 // Run the setIntervalScript again to verify that the clamp imposed for | 151 // Run the setIntervalScript again to verify that the clamp imposed for |
| 126 // nesting beyond 4 levels is reset when setInterval is called again in the | 152 // nesting beyond 4 levels is reset when setInterval is called again in the |
| 127 // original scope but after the original setInterval has completed. | 153 // original scope but after the original setInterval has completed. |
| 128 ExecuteScriptAndWaitUntilIdle(g_k_set_interval_script_text); | 154 ExecuteScriptAndWaitUntilIdle(kSetIntervalScriptText); |
| 129 | 155 |
| 130 auto times(ToDoubleArray(EvalExpression("times"), scope)); | 156 auto times(ToDoubleArray(EvalExpression("times"), scope)); |
| 131 | 157 |
| 132 EXPECT_THAT(times, ElementsAreArray(kExpectedTimings)); | 158 EXPECT_THAT(times, ElementsAreArray(kExpectedTimings)); |
| 133 } | 159 } |
| 134 | 160 |
| 135 } // namespace | 161 } // namespace |
| 136 | 162 |
| 137 } // namespace blink | 163 } // namespace blink |
| OLD | NEW |