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 |