1 /*
2 * Copyright (c) 2002-2025 Gargoyle Software Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 * https://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 package org.htmlunit.javascript.background;
16
17 import org.htmlunit.MockWebConnection;
18 import org.htmlunit.SimpleWebTestCase;
19 import org.htmlunit.WebClient;
20 import org.htmlunit.util.MemoryLeakDetector;
21 import org.junit.jupiter.api.Test;
22
23 /**
24 * <p>Tests for memory leaks. This test passes when run independently in Eclipse or via
25 * Maven (mvn test -Dtest=MemoryLeakTest), but not when all tests are run via Maven
26 * (mvn test). Note that this probably constitutes a false positive, meaning that the
27 * window isn't leaked in this situation -- we just can't get the JVM to GC it because
28 * there is no surefire way to force complete garbage collection.</p>
29 *
30 * <p>All suspected memory leaks should be verified with a profiler before a fix and/or
31 * unit test is committed. In JProfiler, for example, you can run a unit test and tell
32 * the profiler to keep the VM alive when it has finished running; once it has finished
33 * running you can go to the Heap Walker, take a snapshot of the heap, sort the resultant
34 * table by class name and find the class you're interested in, double-click on it, choose
35 * to view References to instances of this class, then right-click on the class and choose
36 * Show Paths to GC Root. This will give you a list of references which need to be
37 * eliminated. Once you have a fix, repeat the above steps in order to verify that the
38 * fix works.</p>
39 *
40 * @author Daniel Gredler
41 */
42 public class MemoryLeakTest extends SimpleWebTestCase {
43
44 /**
45 * Empty test which keeps Maven/JUnit from complaining about a test class with no tests. This test
46 * class cannot be run automatically via Maven for the reasons outlined above.
47 * @throws Exception if an error occurs
48 */
49 @Test
50 public void leaks() throws Exception {
51 // windowLeaks();
52 }
53
54 /**
55 * Verifies that windows don't get leaked, especially when there are long-running background JS tasks
56 * scheduled via <tt>setTimeout</tt> or <tt>setInterval</tt>. See the following bugs:
57 * http://sourceforge.net/p/htmlunit/bugs/639/
58 * http://sourceforge.net/p/htmlunit/bugs/648/
59 *
60 * @throws Exception if an error occurs
61 */
62 protected void windowLeaks() throws Exception {
63 final MemoryLeakDetector detector = new MemoryLeakDetector();
64
65 try (WebClient client = new WebClient()) {
66 detector.register("w", client.getCurrentWindow());
67
68 final MockWebConnection conn = new MockWebConnection();
69 conn.setResponse(URL_FIRST,
70 DOCTYPE_HTML + "<html><body><script>setInterval('alert(1)',5000)</script></body></html>");
71 client.setWebConnection(conn);
72
73 client.getPage(URL_FIRST);
74 }
75 assertTrue("Window can't be garbage collected.", detector.canBeGCed("w"));
76 }
77
78 }