1
2
3
4
5
6
7
8
9
10
11 package psiprobe.tools;
12
13 import static org.junit.jupiter.api.Assertions.assertEquals;
14 import static org.junit.jupiter.api.Assertions.assertNotNull;
15 import static org.junit.jupiter.api.Assertions.assertNull;
16 import static org.junit.jupiter.api.Assertions.assertThrows;
17 import static org.junit.jupiter.api.Assertions.assertTrue;
18 import static org.mockito.Mockito.mock;
19 import static org.mockito.Mockito.when;
20
21 import jakarta.servlet.ServletContext;
22 import jakarta.servlet.http.HttpSession;
23
24 import java.util.Collections;
25 import java.util.List;
26 import java.util.Locale;
27
28 import javax.naming.NamingException;
29
30 import org.apache.catalina.Container;
31 import org.apache.catalina.Context;
32 import org.apache.catalina.Manager;
33 import org.apache.catalina.Session;
34 import org.apache.catalina.Wrapper;
35 import org.apache.catalina.core.StandardWrapper;
36 import org.junit.jupiter.api.Test;
37
38 import psiprobe.beans.ContainerWrapperBean;
39 import psiprobe.beans.ResourceResolver;
40 import psiprobe.model.Application;
41 import psiprobe.model.ApplicationResource;
42 import psiprobe.model.ApplicationSession;
43 import psiprobe.model.DataSourceInfo;
44 import psiprobe.model.ServletInfo;
45 import psiprobe.model.ServletMapping;
46
47
48
49
50 class ApplicationUtilsTest {
51
52 @Test
53 void getApplicationSessionReturnsNullForInvalidSession() {
54 Session session = mock(Session.class);
55 when(session.isValid()).thenReturn(false);
56
57 assertNull(ApplicationUtils.getApplicationSession(session, false, false));
58 }
59
60 @Test
61 void getApplicationSessionCollectsAttributesAndMetadata() {
62 Session session = mock(Session.class);
63 Manager manager = mock(Manager.class);
64 HttpSession httpSession = mock(HttpSession.class);
65
66 when(session.isValid()).thenReturn(true);
67 when(session.getId()).thenReturn("s-1");
68 when(session.getCreationTime()).thenReturn(1_000L);
69 when(session.getLastAccessedTime()).thenReturn(2_000L);
70 when(session.getMaxInactiveInterval()).thenReturn(60);
71 when(session.getManager()).thenReturn(manager);
72 when(session.getSession()).thenReturn(httpSession);
73
74 when(httpSession.getAttributeNames()).thenReturn(Collections.enumeration(List.of("name",
75 ApplicationSession.LAST_ACCESSED_BY_IP, ApplicationSession.LAST_ACCESSED_LOCALE)));
76 when(httpSession.getAttribute("name")).thenReturn("value");
77 when(httpSession.getAttribute(ApplicationSession.LAST_ACCESSED_BY_IP)).thenReturn("127.0.0.1");
78 when(httpSession.getAttribute(ApplicationSession.LAST_ACCESSED_LOCALE)).thenReturn(Locale.US);
79
80 ApplicationSession result = ApplicationUtils.getApplicationSession(session, false, true);
81
82 assertNotNull(result);
83 assertEquals("s-1", result.getId());
84 assertEquals(3, result.getObjectCount());
85 assertTrue(result.isSerializable());
86 assertEquals("127.0.0.1", result.getLastAccessedIp());
87 assertEquals(Locale.US, result.getLastAccessedIpLocale());
88 assertEquals(3, result.getAttributes().size());
89 }
90
91 @Test
92 void getApplicationSessionHandlesInvalidatedHttpSessionGracefully() {
93 Session session = mock(Session.class);
94 Manager manager = mock(Manager.class);
95 HttpSession httpSession = mock(HttpSession.class);
96
97 when(session.isValid()).thenReturn(true);
98 when(session.getId()).thenReturn("s-2");
99 when(session.getCreationTime()).thenReturn(1_000L);
100 when(session.getLastAccessedTime()).thenReturn(2_000L);
101 when(session.getMaxInactiveInterval()).thenReturn(60);
102 when(session.getManager()).thenReturn(manager);
103 when(session.getSession()).thenReturn(httpSession);
104
105 when(httpSession.getAttributeNames()).thenThrow(new IllegalStateException("invalidated"));
106
107 ApplicationSession result = ApplicationUtils.getApplicationSession(session, false, true);
108
109 assertNotNull(result);
110 assertEquals(0, result.getObjectCount());
111 assertEquals(0, result.getAttributes().size());
112 }
113
114 @Test
115 void collectApplicationServletStatsAggregatesStandardWrappers() {
116 Context context = mock(Context.class);
117 StandardWrapper sw1 = mock(StandardWrapper.class);
118 StandardWrapper sw2 = mock(StandardWrapper.class);
119 Container other = mock(Container.class);
120
121 when(context.findChildren()).thenReturn(new Container[] {sw1, other, sw2});
122
123 when(sw1.getRequestCount()).thenReturn(5);
124 when(sw1.getErrorCount()).thenReturn(1);
125 when(sw1.getProcessingTime()).thenReturn(100L);
126 when(sw1.getMinTime()).thenReturn(10L);
127 when(sw1.getMaxTime()).thenReturn(50L);
128
129 when(sw2.getRequestCount()).thenReturn(2);
130 when(sw2.getErrorCount()).thenReturn(0);
131 when(sw2.getProcessingTime()).thenReturn(200L);
132 when(sw2.getMinTime()).thenReturn(5L);
133 when(sw2.getMaxTime()).thenReturn(80L);
134
135 Application app = new Application();
136 ApplicationUtils.collectApplicationServletStats(context, app);
137
138 assertEquals(2, app.getServletCount());
139 assertEquals(7L, app.getRequestCount());
140 assertEquals(1L, app.getErrorCount());
141 assertEquals(300L, app.getProcessingTime());
142 assertEquals(5L, app.getMinTime());
143 assertEquals(80L, app.getMaxTime());
144 }
145
146 @Test
147 void getApplicationDataSourceUsageScoresUsesMaximumAcrossResources() throws NamingException {
148 Context context = mock(Context.class);
149 ResourceResolver resolver = mock(ResourceResolver.class);
150 ContainerWrapperBean containerWrapper = mock(ContainerWrapperBean.class);
151
152 ApplicationResource r1 = new ApplicationResource();
153 DataSourceInfo ds1 = new DataSourceInfo();
154 ds1.setMaxConnections(100);
155 ds1.setBusyConnections(40);
156 ds1.setEstablishedConnections(50);
157 r1.setDataSourceInfo(ds1);
158
159 ApplicationResource r2 = new ApplicationResource();
160 DataSourceInfo ds2 = new DataSourceInfo();
161 ds2.setMaxConnections(200);
162 ds2.setBusyConnections(160);
163 ds2.setEstablishedConnections(100);
164 r2.setDataSourceInfo(ds2);
165
166 ApplicationResource r3 = new ApplicationResource();
167
168 when(resolver.getApplicationResources(context, containerWrapper))
169 .thenReturn(List.of(r1, r2, r3));
170
171 int[] scores =
172 ApplicationUtils.getApplicationDataSourceUsageScores(context, resolver, containerWrapper);
173
174 assertEquals(Math.max(ds1.getBusyScore(), ds2.getBusyScore()), scores[0]);
175 assertEquals(Math.max(ds1.getEstablishedScore(), ds2.getEstablishedScore()), scores[1]);
176 }
177
178 @Test
179 void getApplicationDataSourceUsageScoresWrapsNamingException() throws NamingException {
180 Context context = mock(Context.class);
181 ResourceResolver resolver = mock(ResourceResolver.class);
182 ContainerWrapperBean containerWrapper = mock(ContainerWrapperBean.class);
183
184 when(resolver.getApplicationResources(context, containerWrapper))
185 .thenThrow(new NamingException("boom"));
186
187 assertThrows(RuntimeException.class, () -> ApplicationUtils
188 .getApplicationDataSourceUsageScores(context, resolver, containerWrapper));
189 }
190
191 @Test
192 void getApplicationAttributesCollectsServletContextAttributes() {
193 Context context = mock(Context.class);
194 ServletContext servletContext = mock(ServletContext.class);
195
196 when(context.getServletContext()).thenReturn(servletContext);
197 when(servletContext.getAttributeNames())
198 .thenReturn(Collections.enumeration(List.of("a1", "a2")));
199 when(servletContext.getAttribute("a1")).thenReturn("v1");
200 when(servletContext.getAttribute("a2")).thenReturn(42);
201
202 assertEquals(2, ApplicationUtils.getApplicationAttributes(context).size());
203 }
204
205 @Test
206 void getApplicationServletReturnsNullWhenChildIsNotWrapper() {
207 Context context = mock(Context.class);
208 Container container = mock(Container.class);
209
210 when(context.findChild("x")).thenReturn(container);
211
212 assertNull(ApplicationUtils.getApplicationServlet(context, "x"));
213 }
214
215 @Test
216 void getApplicationServletAndServletsBuildServletInfoFromWrappers() {
217 Context context = mock(Context.class);
218 Wrapper wrapper = mock(Wrapper.class);
219 Container other = mock(Container.class);
220
221 when(context.getName()).thenReturn("/app");
222 when(context.findChild("w")).thenReturn(wrapper);
223 when(wrapper.getName()).thenReturn("w");
224 when(wrapper.getServletClass()).thenReturn("com.example.Servlet");
225 when(wrapper.isUnavailable()).thenReturn(false);
226 when(wrapper.getLoadOnStartup()).thenReturn(1);
227 when(wrapper.getRunAs()).thenReturn("runAs");
228 when(wrapper.findMappings()).thenReturn(new String[] {"/w"});
229
230 ServletInfo servletInfo = ApplicationUtils.getApplicationServlet(context, "w");
231
232 assertNotNull(servletInfo);
233 assertEquals("w", servletInfo.getServletName());
234
235 when(context.findChildren()).thenReturn(new Container[] {wrapper, other});
236 assertEquals(1, ApplicationUtils.getApplicationServlets(context).size());
237 }
238
239 @Test
240 void getApplicationServletMapsSkipsNullMappingsAndAddsWrapperMetadata() {
241 Context context = mock(Context.class);
242 Wrapper wrapper = mock(Wrapper.class);
243
244 when(context.getName()).thenReturn("/app");
245 when(context.findServletMappings()).thenReturn(new String[] {"/x", null, "/y"});
246 when(context.findServletMapping("/x")).thenReturn("s1");
247 when(context.findServletMapping("/y")).thenReturn(null);
248 when(context.findChild("s1")).thenReturn(wrapper);
249 when(wrapper.getServletClass()).thenReturn("com.example.S1");
250 when(wrapper.isUnavailable()).thenReturn(false);
251
252 List<ServletMapping> mappings = ApplicationUtils.getApplicationServletMaps(context);
253
254 assertEquals(1, mappings.size());
255 assertEquals("/x", mappings.get(0).getUrl());
256 assertEquals("s1", mappings.get(0).getServletName());
257 assertEquals("com.example.S1", mappings.get(0).getServletClass());
258 }
259 }