1 /*
2  *  Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License, version 2.0,
6  *  as published by the Free Software Foundation.
7  *
8  *  This program is also distributed with certain software (including
9  *  but not limited to OpenSSL) that is licensed under separate terms,
10  *  as designated in a particular file or component or in included license
11  *  documentation.  The authors of MySQL hereby grant you an additional
12  *  permission to link the program and your derivative works with the
13  *  separately licensed software that they have included with MySQL.
14  *
15  *  This program is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU General Public License, version 2.0, for more details.
19  *
20  *  You should have received a copy of the GNU General Public License
21  *  along with this program; if not, write to the Free Software
22  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
23 */
24 
25 package testsuite.clusterj;
26 
27 import java.util.Arrays;
28 import java.util.List;
29 import java.util.Properties;
30 
31 import testsuite.clusterj.model.Employee;
32 
33 import com.mysql.clusterj.ClusterJFatalUserException;
34 import com.mysql.clusterj.ClusterJHelper;
35 import com.mysql.clusterj.Constants;
36 import com.mysql.clusterj.Session;
37 import com.mysql.clusterj.SessionFactory;
38 import com.mysql.clusterj.core.SessionFactoryImpl;
39 
40 
41 public class ConnectionPoolTest extends AbstractClusterJTest {
42 
43     @Override
getDebug()44     public boolean getDebug() {
45         return false;
46     }
47 
runSpecificNodeIdTests()48     protected boolean runSpecificNodeIdTests() {
49         return false;
50     }
51 
52     @Override
localSetUp()53     public void localSetUp() {
54         loadProperties();
55         // close the existing session factory because it uses one of the cluster connection (api) nodes
56         if (sessionFactory != null) {
57             sessionFactory.close();
58             sessionFactory = null;
59         }
60     }
61 
testNoPooling()62     public void testNoPooling() {
63         Properties modifiedProperties = new Properties();
64         modifiedProperties.putAll(props);
65         SessionFactory sessionFactory1 = null;
66         SessionFactory sessionFactory2 = null;
67 
68         // with connection.pool.size set to 1 each session factory should be the same
69         modifiedProperties.put(Constants.PROPERTY_CONNECTION_POOL_SIZE, 1);
70         sessionFactory1 = ClusterJHelper.getSessionFactory(modifiedProperties);
71         sessionFactory2 = ClusterJHelper.getSessionFactory(modifiedProperties);
72         sessionFactory1.close();
73         sessionFactory2.close();
74         errorIfNotEqual("With connection pooling, SessionFactory1 should be the same object as SessionFactory2",
75                 true, sessionFactory1 == sessionFactory2);
76 
77         // with connection.pool.size set to 0 each session factory should be unique
78         modifiedProperties.put(Constants.PROPERTY_CONNECTION_POOL_SIZE, 0);
79         sessionFactory1 = ClusterJHelper.getSessionFactory(modifiedProperties);
80         sessionFactory2 = ClusterJHelper.getSessionFactory(modifiedProperties);
81         try {
82             SessionFactory sessionFactory3 = ClusterJHelper.getSessionFactory(modifiedProperties);
83             sessionFactory3.close();
84         } catch (ClusterJFatalUserException ex) {
85             // good catch
86         }
87         sessionFactory1.close();
88         sessionFactory2.close();
89         errorIfNotEqual("With no connection pooling, SessionFactory1 should not be the same object as SessionFactory2",
90                 false, sessionFactory1 == sessionFactory2);
91 
92         failOnError();
93     }
94 
testConnectionPoolSize()95     public void testConnectionPoolSize() {
96         Properties modifiedProperties = new Properties();
97         modifiedProperties.putAll(props);
98         modifiedProperties.put(Constants.PROPERTY_CONNECTION_POOL_SIZE, 2);
99         checkConnectionPoolSize2("testConnectionPoolSize", modifiedProperties);
100         failOnError();
101     }
102 
testConnectionPoolSizeAndNodeIds()103     public void testConnectionPoolSizeAndNodeIds() {
104         if (!runSpecificNodeIdTests()) {
105             return;
106         }
107         Properties modifiedProperties = new Properties();
108         modifiedProperties.putAll(props);
109         modifiedProperties.put(Constants.PROPERTY_CONNECTION_POOL_SIZE, 2);
110         modifiedProperties.put(Constants.PROPERTY_CONNECTION_POOL_NODEIDS, "4;5");
111         checkConnectionPoolSize2("testConnectionPoolSizeAndNodeIds", modifiedProperties);
112         failOnError();
113     }
114 
testConnectionNodeIds()115     public void testConnectionNodeIds() {
116         if (!runSpecificNodeIdTests()) {
117             return;
118         }
119         Properties modifiedProperties = new Properties();
120         modifiedProperties.putAll(props);
121         modifiedProperties.put(Constants.PROPERTY_CONNECTION_POOL_NODEIDS, "4,5");
122         checkConnectionPoolSize2("testConnectionNodeIds", modifiedProperties);
123         failOnError();
124     }
125 
testConnectionSingleNodeIdAndConnectionPoolSize()126     public void testConnectionSingleNodeIdAndConnectionPoolSize() {
127         if (!runSpecificNodeIdTests()) {
128             return;
129         }
130         Properties modifiedProperties = new Properties();
131         modifiedProperties.putAll(props);
132         modifiedProperties.put(Constants.PROPERTY_CONNECTION_POOL_SIZE, 2);
133         modifiedProperties.put(Constants.PROPERTY_CONNECTION_POOL_NODEIDS, "4");
134         checkConnectionPoolSize2("testConnectionNodeIds", modifiedProperties);
135         failOnError();
136     }
137 
checkConnectionPoolSize2(String where, Properties modifiedProperties)138     private void checkConnectionPoolSize2(String where, Properties modifiedProperties) {
139         SessionFactory sessionFactory1 = null;
140         SessionFactory sessionFactory2 = null;
141         SessionFactory sessionFactory3 = null;
142         sessionFactory1 = ClusterJHelper.getSessionFactory(modifiedProperties);
143         sessionFactory2 = ClusterJHelper.getSessionFactory(modifiedProperties);
144         sessionFactory3 = ClusterJHelper.getSessionFactory(modifiedProperties);
145         errorIfNotEqual(where + " SessionFactory1 should be the same object as SessionFactory2", true,
146                 sessionFactory1 == sessionFactory2);
147         errorIfNotEqual(where + " SessionFactory1 should be the same object as SessionFactory3", true,
148                 sessionFactory1 == sessionFactory3);
149         Session session1 = sessionFactory1.getSession();
150         Employee e1 = session1.find(Employee.class, 0);
151         checkSessions(where + " after get session1", sessionFactory1, new Integer[] {1, 0});
152         Session session2 = sessionFactory1.getSession();
153         Employee e2 = session2.find(Employee.class, 0);
154         checkSessions(where + " after get session2", sessionFactory1, new Integer[] {1, 1});
155         Session session3 = sessionFactory1.getSession();
156         checkSessions(where + " nafter get session3", sessionFactory1, new Integer[] {2, 1});
157         Session session4 = sessionFactory1.getSession();
158         checkSessions(where + " after get session4", sessionFactory1, new Integer[] {2, 2});
159         Session session5 = sessionFactory1.getSession();
160         checkSessions(where + " after get session5", sessionFactory1, new Integer[] {3, 2});
161         Session session6 = sessionFactory1.getSession();
162         checkSessions(where + " after get session6", sessionFactory1, new Integer[] {3, 3});
163 
164         session1.close();
165         checkSessions(where + " after close session1", sessionFactory1, new Integer[] {2, 3});
166         session4.close();
167         checkSessions(where + " after close session4", sessionFactory1, new Integer[] {2, 2});
168         session5.close();
169         checkSessions(where + " after close session5", sessionFactory1, new Integer[] {1, 2});
170         Session session7 = sessionFactory1.getSession();
171         checkSessions(where + " after get session7", sessionFactory1, new Integer[] {2, 2});
172 
173         session2.close();
174         session3.close();
175         session6.close();
176         session7.close();
177         sessionFactory1.close();
178     }
179 
testNegativeMismatchConnectionPoolSizeAndConnectionPoolNodeids()180     public void testNegativeMismatchConnectionPoolSizeAndConnectionPoolNodeids() {
181         Properties modifiedProperties = new Properties();
182         modifiedProperties.putAll(props);
183         modifiedProperties.put(Constants.PROPERTY_CONNECTION_POOL_SIZE, 3);
184         modifiedProperties.put(Constants.PROPERTY_CONNECTION_POOL_NODEIDS, "4\t5");
185         try {
186             ClusterJHelper.getSessionFactory(modifiedProperties);
187         } catch (ClusterJFatalUserException ex) {
188             if (getDebug()) ex.printStackTrace();
189             // good catch
190             String expected = "4\t5";
191             if (!ex.getMessage().contains(expected)) {
192                 error("Mismatch error message should contain " + expected);
193             }
194         }
195         failOnError();
196     }
197 
testNegativeConnectionPoolNodeidsFormatError()198     public void testNegativeConnectionPoolNodeidsFormatError() {
199         Properties modifiedProperties = new Properties();
200         modifiedProperties.putAll(props);
201         modifiedProperties.put(Constants.PROPERTY_CONNECTION_POOL_SIZE, 2);
202         modifiedProperties.put(Constants.PROPERTY_CONNECTION_POOL_NODEIDS, "7 t");
203         try {
204             ClusterJHelper.getSessionFactory(modifiedProperties);
205         } catch (ClusterJFatalUserException ex) {
206             if (getDebug()) ex.printStackTrace();
207             // good catch
208             String expected = "NumberFormatException";
209             if (!ex.getMessage().contains(expected)) {
210                 error("Mismatch error message '" + ex.getMessage() + "' should contain '" + expected + '"');
211             }
212         }
213         failOnError();
214     }
215 
testNegativeConnectionPoolIllegalNodeids()216     public void testNegativeConnectionPoolIllegalNodeids() {
217         Properties modifiedProperties = new Properties();
218         modifiedProperties.putAll(props);
219         modifiedProperties.put(Constants.PROPERTY_CONNECTION_POOL_NODEIDS, "256");
220         try {
221             ClusterJHelper.getSessionFactory(modifiedProperties);
222         } catch (ClusterJFatalUserException ex) {
223             if (getDebug()) ex.printStackTrace();
224             // good catch
225             String expected = "illegal";
226             if (!ex.getMessage().contains(expected)) {
227                 error("Mismatch error message '" + ex.getMessage() + "' should contain '" + expected + '"');
228             }
229         }
230         failOnError();
231     }
232 
testNegativeConnectionPoolNoNodeId()233     public void testNegativeConnectionPoolNoNodeId() {
234         if (!runSpecificNodeIdTests()) {
235             return;
236         }
237         Properties modifiedProperties = new Properties();
238         modifiedProperties.putAll(props);
239         modifiedProperties.put(Constants.PROPERTY_CONNECTION_POOL_NODEIDS, "48");
240         try {
241             ClusterJHelper.getSessionFactory(modifiedProperties);
242         } catch (ClusterJFatalUserException ex) {
243             if (getDebug()) ex.printStackTrace();
244             // good catch
245             String expected = "No node defined";
246             if (!ex.getMessage().contains(expected)) {
247                 error("Mismatch error message '" + ex.getMessage() + "' should contain '" + expected + '"');
248             }
249         }
250         failOnError();
251     }
252 
checkSessions(String where, SessionFactory sessionFactory1, Integer[] expected)253     private void checkSessions(String where, SessionFactory sessionFactory1, Integer[] expected) {
254         SessionFactoryImpl sessionFactoryImpl = (SessionFactoryImpl)sessionFactory1;
255         List<Integer> connectionCounts = sessionFactoryImpl.getConnectionPoolSessionCounts();
256         if (expected.length != connectionCounts.size()) {
257             error(where + " wrong number of connections in pool\n"
258                     + "Expected: " + Arrays.toString(expected)
259                     + " Actual: " + connectionCounts);
260             return;
261         }
262         int i = 0;
263         for (Integer connectionCount: connectionCounts) {
264             if (getDebug()) System.out.println("Connection " + i + " has " + connectionCount + " sessions.");
265             if (i >= expected.length) break;
266             errorIfNotEqual(where + " wrong count on connection " + i, expected[i], connectionCount);
267             i++;
268         }
269         if (getDebug()) System.out.println();
270     }
271 }
272