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.beans;
12  
13  import static org.junit.jupiter.api.Assertions.*;
14  import static org.mockito.Mockito.*;
15  
16  import java.io.StringReader;
17  import java.util.List;
18  import java.util.Set;
19  
20  import javax.management.MBeanServer;
21  import javax.management.ObjectName;
22  import javax.naming.NamingException;
23  import javax.xml.parsers.DocumentBuilderFactory;
24  
25  import org.apache.catalina.Context;
26  import org.junit.jupiter.api.Test;
27  import org.mockito.ArgumentMatchers;
28  import org.w3c.dom.Element;
29  import org.xml.sax.InputSource;
30  
31  import psiprobe.model.ApplicationResource;
32  
33  /** Tests for {@link JBossResourceResolverBean}. */
34  class JBossResourceResolverBeanTest {
35  
36    @Test
37    void supportsFlagsMatchJbossCapabilities() {
38      JBossResourceResolverBean bean = new JBossResourceResolverBean();
39  
40      assertFalse(bean.supportsPrivateResources());
41      assertTrue(bean.supportsGlobalResources());
42      assertFalse(bean.supportsDataSourceLookup());
43    }
44  
45    @Test
46    void getApplicationResourcesMapsJmxDataToProbeModel() throws Exception {
47      MBeanServer server = mock(MBeanServer.class);
48      ObjectName poolObjectName =
49          new ObjectName("jboss.jca:service=ManagedConnectionPool,name=ExamplePool");
50      ObjectName factoryObjectName =
51          new ObjectName("jboss.jca:service=ManagedConnectionFactory,name=ExamplePool");
52  
53      when(server.queryNames(new ObjectName("jboss.jca:service=ManagedConnectionPool,*"), null))
54          .thenReturn(Set.of(poolObjectName));
55  
56      when(server.getAttribute(poolObjectName, "Criteria")).thenReturn("ByContainerAndApplication");
57      when(server.getAttribute(poolObjectName, "MaxSize")).thenReturn(32);
58      when(server.getAttribute(poolObjectName, "ConnectionCount")).thenReturn(12);
59      when(server.getAttribute(poolObjectName, "InUseConnectionCount")).thenReturn(4L);
60      when(server.getAttribute(factoryObjectName, "ManagedConnectionFactoryProperties"))
61          .thenReturn(parseProperties(
62              "<props>" + "<property name='ConnectionURL'>jdbc:postgresql://localhost/db</property>"
63                  + "<property name='UserName'>app-user</property>"
64                  + "<property name='JmsProviderAdapterJNDI'>jms/connectionFactory</property>"
65                  + "</props>"));
66  
67      JBossResourceResolverBean bean = new TestableJBossResourceResolverBean(server);
68  
69      List<ApplicationResource> resources = bean.getApplicationResources();
70  
71      assertEquals(1, resources.size());
72      ApplicationResource resource = resources.get(0);
73      assertEquals("ExamplePool", resource.getName());
74      assertEquals("Both", resource.getAuth());
75      assertEquals("jms", resource.getType());
76      assertNotNull(resource.getDataSourceInfo());
77      assertEquals(32, resource.getDataSourceInfo().getMaxConnections());
78      assertEquals(12, resource.getDataSourceInfo().getEstablishedConnections());
79      assertEquals(4, resource.getDataSourceInfo().getBusyConnections());
80      assertEquals("app-user", resource.getDataSourceInfo().getUsername());
81      assertEquals("jms/connectionFactory", resource.getDataSourceInfo().getJdbcUrl());
82      assertTrue(resource.getDataSourceInfo().isResettable());
83    }
84  
85    @Test
86    void getApplicationResourcesReturnsEmptyWhenNoMBeanServerPresent() throws Exception {
87      JBossResourceResolverBean bean = new TestableJBossResourceResolverBean(null);
88  
89      assertEquals(List.of(), bean.getApplicationResources());
90    }
91  
92    @Test
93    void getApplicationResourcesReturnsEmptyWhenServerThrows() throws Exception {
94      MBeanServer server = mock(MBeanServer.class);
95      when(server.queryNames(ArgumentMatchers.any(), isNull()))
96          .thenThrow(new RuntimeException("boom"));
97  
98      JBossResourceResolverBean bean = new TestableJBossResourceResolverBean(server);
99  
100     assertEquals(List.of(), bean.getApplicationResources());
101   }
102 
103   @Test
104   void getApplicationResourcesContextMethodReturnsEmptyList() throws Exception {
105     JBossResourceResolverBean bean = new JBossResourceResolverBean();
106 
107     assertTrue(bean.getApplicationResources(mock(Context.class)).isEmpty());
108   }
109 
110   @Test
111   void getApplicationResourcesContextWithWrapperIsUnsupported() {
112     JBossResourceResolverBean bean = new JBossResourceResolverBean();
113 
114     assertThrows(UnsupportedOperationException.class,
115         () -> bean.getApplicationResources(mock(Context.class), mock(ContainerWrapperBean.class)));
116   }
117 
118   @Test
119   void resetResourceStopsAndStartsConnectionPool() throws Exception {
120     MBeanServer server = mock(MBeanServer.class);
121     JBossResourceResolverBean bean = new TestableJBossResourceResolverBean(server);
122 
123     boolean reset = bean.resetResource(null, "ExamplePool", null);
124 
125     assertTrue(reset);
126     ObjectName expected =
127         new ObjectName("jboss.jca:service=ManagedConnectionPool,name=ExamplePool");
128     verify(server).invoke(expected, "stop", null, null);
129     verify(server).invoke(expected, "start", null, null);
130   }
131 
132   @Test
133   void resetResourceReturnsFalseWhenServerMissing() throws Exception {
134     JBossResourceResolverBean bean = new TestableJBossResourceResolverBean(null);
135 
136     assertFalse(bean.resetResource(null, "ExamplePool", null));
137   }
138 
139   @Test
140   void resetResourceReturnsFalseWhenInvokeFails() throws Exception {
141     MBeanServer server = mock(MBeanServer.class);
142     doThrow(new RuntimeException("failed")).when(server).invoke(any(), eq("stop"), isNull(),
143         isNull());
144 
145     JBossResourceResolverBean bean = new TestableJBossResourceResolverBean(server);
146 
147     assertFalse(bean.resetResource(null, "ExamplePool", null));
148   }
149 
150   @Test
151   void resetResourceWithMalformedNameThrowsNamingException() {
152     JBossResourceResolverBean bean = new JBossResourceResolverBean();
153 
154     NamingException exception =
155         assertThrows(NamingException.class, () -> bean.resetResource(null, "bad:name", null));
156 
157     assertTrue(exception.getMessage().contains("malformed ObjectName"));
158   }
159 
160   @Test
161   void lookupDataSourceIsUnsupported() {
162     JBossResourceResolverBean bean = new JBossResourceResolverBean();
163 
164     assertThrows(UnsupportedOperationException.class,
165         () -> bean.lookupDataSource(null, "resource", null));
166   }
167 
168   private static Element parseProperties(String xml) throws Exception {
169     return DocumentBuilderFactory.newInstance().newDocumentBuilder()
170         .parse(new InputSource(new StringReader(xml))).getDocumentElement();
171   }
172 
173   private static class TestableJBossResourceResolverBean extends JBossResourceResolverBean {
174 
175     private final MBeanServer server;
176 
177     private TestableJBossResourceResolverBean(MBeanServer server) {
178       this.server = server;
179     }
180 
181     @Override
182     public MBeanServer getMBeanServer() {
183       return server;
184     }
185   }
186 }