1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.htmlunit.javascript.background;
16
17 import java.util.ArrayList;
18 import java.util.Collections;
19 import java.util.List;
20
21 import org.htmlunit.MockWebConnection;
22 import org.htmlunit.SimpleWebTestCase;
23 import org.htmlunit.TopLevelWindow;
24 import org.htmlunit.html.HtmlAnchor;
25 import org.htmlunit.html.HtmlInlineFrame;
26 import org.htmlunit.html.HtmlPage;
27 import org.junit.jupiter.api.Test;
28
29
30
31
32
33
34
35
36 public class JavaScriptJobManagerTest extends SimpleWebTestCase {
37 private long startTime_;
38
39 private void startTimedTest() {
40 startTime_ = System.currentTimeMillis();
41 }
42
43 private void assertMaxTestRunTime(final long maxRunTimeMilliseconds) {
44 final long endTime = System.currentTimeMillis();
45 final long runTime = endTime - startTime_;
46 assertTrue("\nTest took too long to run and results may not be accurate. Please try again. "
47 + "\n Actual Run Time: "
48 + runTime
49 + "\n Max Run Time: "
50 + maxRunTimeMilliseconds, runTime < maxRunTimeMilliseconds);
51 }
52
53
54
55
56 @Test
57 public void setClearTimeoutUsesManager() throws Exception {
58 final String content = DOCTYPE_HTML
59 + "<html>\n"
60 + "<head>\n"
61 + " <title>test</title>\n"
62 + " <script>\n"
63 + " var threadID;\n"
64 + " function test() {\n"
65 + " threadID = setTimeout(doAlert, 10000);\n"
66 + " }\n"
67 + " function doAlert() {\n"
68 + " alert('blah');\n"
69 + " }\n"
70 + " </script>\n"
71 + "</head>\n"
72 + "<body onload='test()'>\n"
73 + "<a onclick='clearTimeout(threadID);' id='clickme'/>\n"
74 + "</body>\n"
75 + "</html>";
76
77 final List<String> collectedAlerts = Collections.synchronizedList(new ArrayList<String>());
78 startTimedTest();
79 final HtmlPage page = loadPage(content, collectedAlerts);
80 final JavaScriptJobManager jobManager = page.getEnclosingWindow().getJobManager();
81 assertNotNull(jobManager);
82 assertEquals(1, jobManager.getJobCount());
83 final HtmlAnchor a = page.getHtmlElementById("clickme");
84 a.click();
85 jobManager.waitForJobs(7000);
86 assertEquals(0, jobManager.getJobCount());
87 assertEquals(Collections.EMPTY_LIST, collectedAlerts);
88 assertMaxTestRunTime(10_000);
89 }
90
91
92
93
94 @Test
95 public void setClearIntervalUsesManager() throws Exception {
96 final String content = DOCTYPE_HTML
97 + "<html>\n"
98 + "<head>\n"
99 + " <title>test</title>\n"
100 + " <script>\n"
101 + " var threadID;\n"
102 + " function test() {\n"
103 + " threadID = setInterval(doAlert, 100);\n"
104 + " }\n"
105 + " var iterationNumber = 0;\n"
106 + " function doAlert() {\n"
107 + " alert('blah');\n"
108 + " if (++iterationNumber >= 3) {\n"
109 + " clearInterval(threadID);\n"
110 + " }\n"
111 + " }\n"
112 + " </script>\n"
113 + "</head>\n"
114 + "<body onload='test()'>\n"
115 + "</body>\n"
116 + "</html>";
117
118 final List<String> collectedAlerts = Collections.synchronizedList(new ArrayList<String>());
119 final HtmlPage page = loadPage(content, collectedAlerts);
120
121
122
123 startTimedTest();
124
125 final JavaScriptJobManager jobManager = page.getEnclosingWindow().getJobManager();
126 assertNotNull(jobManager);
127 assertEquals(1, jobManager.getJobCount());
128 jobManager.waitForJobs(DEFAULT_WAIT_TIME.toMillis());
129 assertEquals(0, jobManager.getJobCount());
130 assertEquals(Collections.nCopies(3, "blah"), collectedAlerts);
131
132 assertMaxTestRunTime(DEFAULT_WAIT_TIME.toMillis() + 100);
133 }
134
135
136
137
138 @Test
139 public void navigationStopThreadsInChildWindows() throws Exception {
140 final String firstContent = DOCTYPE_HTML
141 + "<html><head><title>First</title></head><body>\n"
142 + "<iframe id='iframe1' src='"
143 + URL_SECOND
144 + "'></iframe>\n"
145 + "<a href='"
146 + URL_THIRD.toExternalForm()
147 + "' id='clickme'>click me</a>\n"
148 + "</body></html>";
149 final String secondContent = DOCTYPE_HTML
150 + "<html><head><title>Second</title></head><body>\n"
151 + "<script>\n"
152 + "setInterval('', 30000);\n"
153 + "</script>\n"
154 + "</body></html>";
155 final String thirdContent = DOCTYPE_HTML
156 + "<html><head><title>Third</title></head><body></body></html>";
157
158 final MockWebConnection webConnection = getMockWebConnection();
159 webConnection.setResponse(URL_SECOND, secondContent);
160 webConnection.setResponse(URL_THIRD, thirdContent);
161
162 final HtmlPage page = loadPage(firstContent);
163 final HtmlInlineFrame iframe = page.getHtmlElementById("iframe1");
164 final JavaScriptJobManager mgr = iframe.getEnclosedWindow().getJobManager();
165 assertEquals("inner frame should show child thread", 1, mgr.getJobCount());
166
167 final HtmlAnchor anchor = page.getHtmlElementById("clickme");
168 final HtmlPage newPage = anchor.click();
169 assertEquals("new page should load", "Third", newPage.getTitleText());
170 assertTrue("frame should be gone", newPage.getFrames().isEmpty());
171
172 mgr.waitForJobs(10_000);
173 assertEquals("job manager should have no jobs left", 0, mgr.getJobCount());
174 }
175
176
177
178
179
180
181
182 @Test
183 public void interruptAllWithRecursiveSetTimeout() throws Exception {
184 final String content = DOCTYPE_HTML
185 + "<html>\n"
186 + "<head>\n"
187 + " <title>test</title>\n"
188 + " <script>\n"
189 + " var threadID;\n"
190 + " function test() {\n"
191 + " alert('ping');\n"
192 + " threadID = setTimeout(test, 5);\n"
193 + " }\n"
194 + " </script>\n"
195 + "</head>\n"
196 + "<body onload='test()'>\n"
197 + "</body>\n"
198 + "</html>";
199
200 final List<String> collectedAlerts = Collections.synchronizedList(new ArrayList<String>());
201 final HtmlPage page = loadPage(content, collectedAlerts);
202 final JavaScriptJobManager jobManager = page.getEnclosingWindow().getJobManager();
203 assertNotNull(jobManager);
204
205
206 Thread.sleep(500);
207
208 assertFalse("At least one alert should have fired by now", collectedAlerts.isEmpty());
209 ((TopLevelWindow) page.getEnclosingWindow()).close();
210
211
212 jobManager.waitForJobs(500);
213
214 final int finalValue = collectedAlerts.size();
215
216
217 jobManager.waitForJobs(500);
218
219 assertEquals("No new alerts should have happened", finalValue, collectedAlerts.size());
220 }
221 }