View Javadoc
1   /*
2    * Licensed under the GPL License. You may not use this file except in compliance with the License.
3    * You may obtain a copy of the License at
4    *
5    *   https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
6    *
7    * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
8    * WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
9    * PURPOSE.
10   */
11  package psiprobe;
12  
13  import static org.junit.jupiter.api.Assertions.assertEquals;
14  import static org.junit.jupiter.api.Assertions.assertFalse;
15  import static org.junit.jupiter.api.Assertions.assertNotNull;
16  import static org.junit.jupiter.api.Assertions.assertNull;
17  import static org.junit.jupiter.api.Assertions.assertThrows;
18  import static org.junit.jupiter.api.Assertions.assertTrue;
19  
20  import jakarta.servlet.ServletContext;
21  
22  import java.io.IOException;
23  import java.util.ArrayList;
24  import java.util.Collections;
25  import java.util.Enumeration;
26  import java.util.List;
27  
28  import org.apache.catalina.Context;
29  import org.apache.catalina.Valve;
30  import org.apache.catalina.WebResource;
31  import org.apache.catalina.WebResourceRoot;
32  import org.apache.catalina.deploy.NamingResourcesImpl;
33  import org.apache.jasper.EmbeddedServletOptions;
34  import org.apache.jasper.JspCompilationContext;
35  import org.apache.naming.ContextAccessController;
36  import org.apache.tomcat.util.descriptor.web.ApplicationParameter;
37  import org.apache.tomcat.util.descriptor.web.ContextResource;
38  import org.apache.tomcat.util.descriptor.web.ContextResourceLink;
39  import org.apache.tomcat.util.descriptor.web.FilterDef;
40  import org.apache.tomcat.util.descriptor.web.FilterMap;
41  import org.junit.jupiter.api.Test;
42  import org.junit.jupiter.api.extension.ExtendWith;
43  import org.junit.jupiter.params.ParameterizedTest;
44  import org.junit.jupiter.params.provider.ValueSource;
45  import org.mockito.Mock;
46  import org.mockito.MockedStatic;
47  import org.mockito.Mockito;
48  import org.mockito.junit.jupiter.MockitoExtension;
49  
50  import psiprobe.model.ApplicationResource;
51  
52  /**
53   * The Class Tomcat10ContainerAdapterTest.
54   */
55  @ExtendWith(MockitoExtension.class)
56  class Tomcat10ContainerAdapterTest {
57  
58    /** The context. */
59    @Mock
60    Context context;
61  
62    /** The embedded servlet options. */
63    @Mock
64    EmbeddedServletOptions options;
65  
66    /**
67     * Creates the valve.
68     */
69    @Test
70    void createValve() {
71      final Tomcat10ContainerAdapter adapter = new Tomcat10ContainerAdapter();
72      Valve valve = adapter.createValve();
73      assertEquals("Tomcat10AgentValve[Container is null]", valve.toString());
74    }
75  
76    /**
77     * Can bound to null.
78     */
79    @Test
80    void canBoundToNull() {
81      final Tomcat10ContainerAdapter adapter = new Tomcat10ContainerAdapter();
82      assertFalse(adapter.canBoundTo(null));
83    }
84  
85    /**
86     * Can bound to tomcat 10.1, tomee 10.0, nsjsp 10.1, vmware tc 10.1.
87     *
88     * @param container the container
89     */
90    @ParameterizedTest
91    @ValueSource(strings = {"Apache Tomcat/10.1", "Apache Tomcat (TomEE)/10.0",
92        "NonStop(tm) Servlets For JavaServer Pages(tm) v10.1", "Vmware tc..../10.1"})
93    void canBoundTo(String container) {
94      final Tomcat10ContainerAdapter adapter = new Tomcat10ContainerAdapter();
95      assertTrue(adapter.canBoundTo(container));
96    }
97  
98    /**
99     * Can not bound to other containers.
100    *
101    * @param container the container
102    */
103   @ParameterizedTest
104   @ValueSource(strings = {"Vmware tc", "Other"})
105   void cannotBoundToOthers(String container) {
106     final Tomcat10ContainerAdapter adapter = new Tomcat10ContainerAdapter();
107     assertFalse(adapter.canBoundTo(container));
108   }
109 
110   /**
111    * Filter mappings.
112    */
113   @Test
114   void filterMappings() {
115     final Tomcat10ContainerAdapter adapter = new Tomcat10ContainerAdapter();
116     FilterMap map = new FilterMap();
117     map.addServletName("psi-probe");
118     map.addURLPattern("/psi-probe");
119     assertEquals(2, adapter.getFilterMappings(map, "dispatcherMap", "filterClass").size());
120   }
121 
122   /**
123    * Creates the jsp compilation context.
124    */
125   @Test
126   void createJspCompilationContext() {
127     final Tomcat10ContainerAdapter adapter = new Tomcat10ContainerAdapter();
128     Mockito.when(this.options.getGeneratedJspPackageName()).thenReturn("org.apache.jsp");
129     JspCompilationContext jspContext = adapter.createJspCompilationContext("name", this.options,
130         null, null, ClassLoader.getSystemClassLoader());
131     assertEquals("org.apache.jsp.name", jspContext.getFQCN());
132   }
133 
134   /**
135    * Adds the context resource link.
136    */
137   @Test
138   void addContextResourceLink() {
139     NamingResourcesImpl namingResources = Mockito.mock(NamingResourcesImpl.class);
140     Mockito.when(context.getNamingResources()).thenReturn(namingResources);
141     Mockito.when(namingResources.findResourceLinks())
142         .thenReturn(new ContextResourceLink[] {new ContextResourceLink()});
143 
144     final Tomcat10ContainerAdapter adapter = new Tomcat10ContainerAdapter();
145     final List<ApplicationResource> list = new ArrayList<ApplicationResource>();
146     adapter.addContextResourceLink(context, list);
147     assertFalse(list.isEmpty());
148   }
149 
150   /**
151    * Adds the context resource.
152    */
153   @Test
154   void addContextResource() {
155     NamingResourcesImpl namingResources = Mockito.mock(NamingResourcesImpl.class);
156     Mockito.when(context.getNamingResources()).thenReturn(namingResources);
157     Mockito.when(namingResources.findResources())
158         .thenReturn(new ContextResource[] {new ContextResource()});
159 
160     final Tomcat10ContainerAdapter adapter = new Tomcat10ContainerAdapter();
161     final List<ApplicationResource> list = new ArrayList<ApplicationResource>();
162     adapter.addContextResource(context, list);
163     assertFalse(list.isEmpty());
164   }
165 
166   /**
167    * Gets the application filter maps.
168    */
169   @Test
170   void applicationFilterMaps() {
171     Mockito.when(context.findFilterMaps()).thenReturn(new FilterMap[] {new FilterMap()});
172 
173     final Tomcat10ContainerAdapter adapter = new Tomcat10ContainerAdapter();
174     assertEquals(0, adapter.getApplicationFilterMaps(context).size());
175   }
176 
177   /**
178    * Gets the application filter maps async.
179    *
180    * @param dispatcher the dispatcher
181    */
182   @ParameterizedTest
183   @ValueSource(strings = {"ASYNC", "ERROR", "FORWARD", "INCLUDE", "NONE"})
184   void applicationFilterMapsTypes(String dispatcher) {
185     FilterMap filterMap = new FilterMap();
186     filterMap.setDispatcher(dispatcher);
187     Mockito.when(context.findFilterMaps()).thenReturn(new FilterMap[] {filterMap});
188 
189     Mockito.when(context.findFilterDef(Mockito.any())).thenReturn(new FilterDef());
190 
191     final Tomcat10ContainerAdapter adapter = new Tomcat10ContainerAdapter();
192     assertEquals(0, adapter.getApplicationFilterMaps(context).size());
193   }
194 
195   /**
196    * Gets the application filter maps throws on unknown dispatcher mapping.
197    */
198   @Test
199   void applicationFilterMapsThrowsOnUnknownDispatcherMapping() {
200     Context mockContext = Mockito.mock(Context.class);
201     FilterMap filterMap = Mockito.mock(FilterMap.class);
202 
203     // Return an invalid dispatcher mapping value
204     Mockito.when(filterMap.getDispatcherMapping()).thenReturn(-1);
205     Mockito.when(mockContext.findFilterMaps()).thenReturn(new FilterMap[] {filterMap});
206 
207     Tomcat10ContainerAdapter adapter = new Tomcat10ContainerAdapter();
208 
209     assertThrows(IllegalArgumentException.class,
210         () -> adapter.getApplicationFilterMaps(mockContext));
211   }
212 
213   /**
214    * Application filters.
215    */
216   @Test
217   void applicationFilters() {
218     Mockito.when(context.findFilterDefs()).thenReturn(new FilterDef[] {new FilterDef()});
219 
220     final Tomcat10ContainerAdapter adapter = new Tomcat10ContainerAdapter();
221     assertEquals(1, adapter.getApplicationFilters(context).size());
222   }
223 
224   /**
225    * Application init params.
226    */
227   @Test
228   void applicationInitParams() {
229     Mockito.when(context.findApplicationParameters())
230         .thenReturn(new ApplicationParameter[] {new ApplicationParameter()});
231 
232     ServletContext servletContext = Mockito.mock(ServletContext.class);
233     Mockito.when(context.getServletContext()).thenReturn(servletContext);
234 
235     List<String> initParams = new ArrayList<>();
236     initParams.add("name");
237     Enumeration<String> initParameterNames = Collections.enumeration(initParams);
238     Mockito.when(servletContext.getInitParameterNames()).thenReturn(initParameterNames);
239 
240     final Tomcat10ContainerAdapter adapter = new Tomcat10ContainerAdapter();
241     assertEquals(1, adapter.getApplicationInitParams(context).size());
242   }
243 
244   /**
245    * Application init params none.
246    */
247   @Test
248   void applicationInitParamsNone() {
249     Mockito.when(context.findApplicationParameters())
250         .thenReturn(new ApplicationParameter[] {(ApplicationParameter) null});
251 
252     ServletContext servletContext = Mockito.mock(ServletContext.class);
253     Mockito.when(context.getServletContext()).thenReturn(servletContext);
254 
255     List<String> initParams = new ArrayList<>();
256     initParams.add("name");
257     Enumeration<String> initParameterNames = Collections.enumeration(initParams);
258     Mockito.when(servletContext.getInitParameterNames()).thenReturn(initParameterNames);
259 
260     Mockito.when(context.findParameter(Mockito.any())).thenReturn(null);
261 
262     final Tomcat10ContainerAdapter adapter = new Tomcat10ContainerAdapter();
263     assertEquals(1, adapter.getApplicationInitParams(context).size());
264   }
265 
266   /**
267    * Application init params not override attempt.
268    */
269   @Test
270   void applicationInitParamsNotOverrideAttempt() {
271     ApplicationParameter appParam = new ApplicationParameter();
272     appParam.setName("noOverride");
273     appParam.setOverride(false);
274     Mockito.when(context.findApplicationParameters())
275         .thenReturn(new ApplicationParameter[] {appParam});
276 
277     ServletContext servletContext = Mockito.mock(ServletContext.class);
278     Mockito.when(context.getServletContext()).thenReturn(servletContext);
279 
280     List<String> initParams = new ArrayList<>();
281     initParams.add("name");
282     Enumeration<String> initParameterNames = Collections.enumeration(initParams);
283     Mockito.when(servletContext.getInitParameterNames()).thenReturn(initParameterNames);
284 
285     Mockito.when(context.findParameter(Mockito.any())).thenReturn("name");
286 
287     final Tomcat10ContainerAdapter adapter = new Tomcat10ContainerAdapter();
288     assertEquals(1, adapter.getApplicationInitParams(context).size());
289   }
290 
291   /**
292    * Application init params not override attempt.
293    */
294   @Test
295   void applicationInitParamsOverrideAttempt() {
296     ApplicationParameter appParam = new ApplicationParameter();
297     appParam.setName("override");
298     appParam.setOverride(false);
299     Mockito.when(context.findApplicationParameters())
300         .thenReturn(new ApplicationParameter[] {appParam});
301 
302     ServletContext servletContext = Mockito.mock(ServletContext.class);
303     Mockito.when(context.getServletContext()).thenReturn(servletContext);
304 
305     List<String> initParams = new ArrayList<>();
306     initParams.add("override");
307     Enumeration<String> initParameterNames = Collections.enumeration(initParams);
308     Mockito.when(servletContext.getInitParameterNames()).thenReturn(initParameterNames);
309 
310     Mockito.when(context.findParameter(Mockito.any())).thenReturn("override");
311 
312     final Tomcat10ContainerAdapter adapter = new Tomcat10ContainerAdapter();
313     assertEquals(1, adapter.getApplicationInitParams(context).size());
314   }
315 
316   /**
317    * Resource exists.
318    */
319   @Test
320   void resourceExists() {
321     WebResourceRoot webResourceRoot = Mockito.mock(WebResourceRoot.class);
322     Mockito.when(context.getResources()).thenReturn(webResourceRoot);
323 
324     final Tomcat10ContainerAdapter adapter = new Tomcat10ContainerAdapter();
325     assertFalse(adapter.resourceExists("name", context));
326   }
327 
328   /**
329    * Resource exists when true.
330    */
331   @Test
332   void resourceExistsWhenTrue() {
333     WebResourceRoot webResourceRoot = Mockito.mock(WebResourceRoot.class);
334     Mockito.when(context.getResources()).thenReturn(webResourceRoot);
335 
336     WebResource webResource = Mockito.mock(WebResource.class);
337     Mockito.when(webResourceRoot.getResource("name")).thenReturn(webResource);
338 
339     final Tomcat10ContainerAdapter adapter = new Tomcat10ContainerAdapter();
340     assertTrue(adapter.resourceExists("name", context));
341   }
342 
343   /**
344    * Resource stream.
345    *
346    * @throws IOException Signals that an I/O exception has occurred.
347    */
348   @Test
349   void resourceStream() throws IOException {
350     WebResourceRoot webResourceRoot = Mockito.mock(WebResourceRoot.class);
351     Mockito.when(context.getResources()).thenReturn(webResourceRoot);
352 
353     WebResource webResource = Mockito.mock(WebResource.class);
354     Mockito.when(webResourceRoot.getResource("name")).thenReturn(webResource);
355 
356     final Tomcat10ContainerAdapter adapter = new Tomcat10ContainerAdapter();
357     assertNull(adapter.getResourceStream("name", context));
358   }
359 
360   /**
361    * Resource attributes.
362    */
363   @Test
364   void resourceAttributes() {
365     WebResourceRoot webResourceRoot = Mockito.mock(WebResourceRoot.class);
366     Mockito.when(context.getResources()).thenReturn(webResourceRoot);
367 
368     WebResource webResource = Mockito.mock(WebResource.class);
369     Mockito.when(webResourceRoot.getResource("name")).thenReturn(webResource);
370 
371     final Tomcat10ContainerAdapter adapter = new Tomcat10ContainerAdapter();
372     assertNotNull(adapter.getResourceAttributes("name", context));
373   }
374 
375   /**
376    * Gets the naming token.
377    */
378   @Test
379   void namingToken() {
380     Mockito.when(context.getNamingToken()).thenReturn(new Object());
381 
382     final Tomcat10ContainerAdapter adapter = new Tomcat10ContainerAdapter();
383     assertNotNull(adapter.getNamingToken(context));
384   }
385 
386   /**
387    * Gets the naming token with security token check false.
388    */
389   @Test
390   void namingTokenWithSecurityTokenCheckFalse() {
391     Mockito.when(context.getNamingToken()).thenReturn(new Object());
392 
393     try (MockedStatic<ContextAccessController> mocked =
394         Mockito.mockStatic(ContextAccessController.class)) {
395       mocked.when(() -> ContextAccessController.checkSecurityToken(Mockito.any(), Mockito.any()))
396           .thenReturn(false);
397 
398       final Tomcat10ContainerAdapter adapter = new Tomcat10ContainerAdapter();
399       assertNotNull(adapter.getNamingToken(context));
400     }
401   }
402 
403   /**
404    * Application filters when none.
405    */
406   @Test
407   void applicationFiltersWhenNone() {
408     Mockito.when(context.findFilterDefs()).thenReturn(new FilterDef[] {(FilterDef) null});
409 
410     final Tomcat10ContainerAdapter adapter = new Tomcat10ContainerAdapter();
411     assertTrue(adapter.getApplicationFilters(context).isEmpty());
412   }
413 
414   /**
415    * Application filter maps when none.
416    */
417   @Test
418   void applicationFilterMapsWhenNone() {
419     Mockito.when(context.findFilterMaps()).thenReturn(new FilterMap[] {(FilterMap) null});
420 
421     final Tomcat10ContainerAdapter adapter = new Tomcat10ContainerAdapter();
422     assertTrue(adapter.getApplicationFilterMaps(context).isEmpty());
423   }
424 
425 }