TestCase는 깔끔하고 쓰기 편해야 하는데.. 이 부분에 대한 희망이 Tomcat TestCase를 보면서 기분이 좋아졌다. 이런 테스트 케이스가 나올 수 있도록 프레임워크는 잘 짜여져야 할 것 같다.


참고
http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/catalina/loader/TestWebappClassLoaderMemoryLeak.java?view=markup&pathrev=937733


17 package org.apache.catalina.loader;
18
19 import java.io.IOException;
20 import java.util.Timer;
21 import java.util.TimerTask;
22
23 import javax.servlet.ServletException;
24 import javax.servlet.http.HttpServlet;
25 import javax.servlet.http.HttpServletRequest;
26 import javax.servlet.http.HttpServletResponse;
27
28 import org.apache.catalina.Context;
29 import org.apache.catalina.startup.Tomcat;
30 import org.apache.catalina.startup.TomcatBaseTest;
31
32 public class TestWebappClassLoaderMemoryLeak extends TomcatBaseTest {
33
34 public void testTimerThreadLeak() throws Exception {
35 Tomcat tomcat = getTomcatInstance();
36
37 // Must have a real docBase - just use temp
38 Context ctx =
39 tomcat.addContext("/", System.getProperty("java.io.tmpdir"));
40
41 Tomcat.addServlet(ctx, "taskServlet", new TaskServlet());
42 ctx.addServletMapping("/", "taskServlet");
43
44 tomcat.start();
45
46 // This will trigger the timer & thread creation
47 getUrl("http://localhost:" + getPort() + "/");
48
49 // Stop the context
50 ctx.stop();
51
52 // If the thread still exists, we have a thread/memory leak
53 try {
54 Thread.sleep(1000);
55 } catch(InterruptedException ie) {
56 // ignore
57 }
58 Thread[] threads = getThreads();
59 for (Thread thread : threads) {
60 if (thread != null &&
61 TaskServlet.TIMER_THREAD_NAME.equals(thread.getName())) {
62 fail("Timer thread still running");
63 }
64 }
65 }
66
67 /*
68 * Get the set of current threads as an array.
69 * Copied from WebappClassLoader
70 */
71 private Thread[] getThreads() {
72 // Get the current thread group
73 ThreadGroup tg = Thread.currentThread( ).getThreadGroup( );
74 // Find the root thread group
75 while (tg.getParent() != null) {
76 tg = tg.getParent();
77 }
78
79 int threadCountGuess = tg.activeCount() + 50;
80 Thread[] threads = new Thread[threadCountGuess];
81 int threadCountActual = tg.enumerate(threads);
82 // Make sure we don't miss any threads
83 while (threadCountActual == threadCountGuess) {
84 threadCountGuess *=2;
85 threads = new Thread[threadCountGuess];
86 // Note tg.enumerate(Thread[]) silently ignores any threads that
87 // can't fit into the array
88 threadCountActual = tg.enumerate(threads);
89 }
90
91 return threads;
92 }
93
94 private static final class TaskServlet extends HttpServlet {
95
96 private static final long serialVersionUID = 1L;
97 private static final String TIMER_THREAD_NAME = "leaked-thread";
98
99 @Override
100 protected void doGet(HttpServletRequest req, HttpServletResponse resp)
101 throws ServletException, IOException {
102 Timer timer = new Timer(TIMER_THREAD_NAME);
103 timer.schedule(new LocalTask(), 0, 10000);
104 }
105
106 }
107
108 private static final class LocalTask extends TimerTask {
109
110 @Override
111 public void run() {
112 // Doesn't actually need to do anything.
113 }
114
115 }
116 }
Posted by 김용환 '김용환'

댓글을 달아 주세요