View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.pool2.impl;
19  
20  import static org.junit.jupiter.api.Assertions.assertEquals;
21  
22  import java.lang.management.ManagementFactory;
23  import java.time.Duration;
24  import java.util.ArrayList;
25  import java.util.concurrent.TimeUnit;
26  import java.util.concurrent.atomic.AtomicInteger;
27  
28  import javax.management.MBeanServer;
29  import javax.management.ObjectName;
30  
31  import org.apache.commons.pool2.Waiter;
32  import org.apache.commons.pool2.WaiterFactory;
33  import org.apache.commons.pool2.impl.TestGenericObjectPool.SimpleFactory;
34  import org.junit.jupiter.api.AfterEach;
35  import org.junit.jupiter.api.BeforeEach;
36  import org.junit.jupiter.api.Test;
37  import org.junit.jupiter.api.Timeout;
38  
39  /**
40   */
41  public class TestBaseGenericObjectPool {
42  
43      BaseGenericObjectPool<String> pool;
44      SimpleFactory factory;
45  
46      @BeforeEach
47      public void setUp() {
48          factory = new SimpleFactory();
49          pool = new GenericObjectPool<>(factory);
50      }
51  
52      @AfterEach
53      public void tearDown() {
54          pool.close();
55          pool = null;
56          factory = null;
57      }
58  
59      @Test
60      public void testActiveTimeStatistics() {
61          for (int i = 0; i < 99; i++) { // must be < MEAN_TIMING_STATS_CACHE_SIZE
62              pool.updateStatsReturn(Duration.ofMillis(i));
63          }
64          assertEquals(49, pool.getMeanActiveTimeMillis(), Double.MIN_VALUE);
65      }
66  
67      @Test
68      public void testBorrowWaitStatistics() {
69          final DefaultPooledObject<String> p = (DefaultPooledObject<String>) factory.makeObject();
70          pool.updateStatsBorrow(p, Duration.ofMillis(10));
71          pool.updateStatsBorrow(p, Duration.ofMillis(20));
72          pool.updateStatsBorrow(p, Duration.ofMillis(20));
73          pool.updateStatsBorrow(p, Duration.ofMillis(30));
74          assertEquals(20, pool.getMeanBorrowWaitTimeMillis(), Double.MIN_VALUE);
75          assertEquals(30, pool.getMaxBorrowWaitTimeMillis(), 0);
76      }
77  
78      public void testBorrowWaitStatisticsMax() {
79          final DefaultPooledObject<String> p = (DefaultPooledObject<String>) factory.makeObject();
80          assertEquals(0, pool.getMaxBorrowWaitTimeMillis(), Double.MIN_VALUE);
81          pool.updateStatsBorrow(p, Duration.ZERO);
82          assertEquals(0, pool.getMaxBorrowWaitTimeMillis(), Double.MIN_VALUE);
83          pool.updateStatsBorrow(p, Duration.ofMillis(20));
84          assertEquals(20, pool.getMaxBorrowWaitTimeMillis(), Double.MIN_VALUE);
85          pool.updateStatsBorrow(p, Duration.ofMillis(20));
86          assertEquals(20, pool.getMaxBorrowWaitTimeMillis(), Double.MIN_VALUE);
87          pool.updateStatsBorrow(p, Duration.ofMillis(10));
88          assertEquals(20, pool.getMaxBorrowWaitTimeMillis(), Double.MIN_VALUE);
89      }
90  
91      @Test
92      public void testEvictionTimerMultiplePools() throws InterruptedException {
93          final AtomicIntegerFactory factory = new AtomicIntegerFactory();
94          factory.setValidateLatency(50);
95          try (final GenericObjectPool<AtomicInteger> evictingPool = new GenericObjectPool<>(factory)) {
96              evictingPool.setTimeBetweenEvictionRuns(Duration.ofMillis(100));
97              evictingPool.setNumTestsPerEvictionRun(5);
98              evictingPool.setTestWhileIdle(true);
99              evictingPool.setMinEvictableIdleTime(Duration.ofMillis(50));
100             for (int i = 0; i < 10; i++) {
101                 try {
102                     evictingPool.addObject();
103                 } catch (final Exception e) {
104                     e.printStackTrace();
105                 }
106             }
107 
108             for (int i = 0; i < 1000; i++) {
109                 try (final GenericObjectPool<AtomicInteger> nonEvictingPool = new GenericObjectPool<>(factory)) {
110                     // empty
111                 }
112             }
113 
114             Thread.sleep(1000);
115             assertEquals(0, evictingPool.getNumIdle());
116         }
117     }
118 
119     /**
120      * POOL-393
121      * Tests JMX registration does not add too much latency to pool creation.
122      */
123     @SuppressWarnings("resource") // pools closed in finally block
124     @Test
125     @Timeout(value = 10_000, unit = TimeUnit.MILLISECONDS)
126     public void testJMXRegistrationLatency() {
127         final int numPools = 1000;
128         final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
129         final ArrayList<GenericObjectPool<Waiter>> pools = new ArrayList<>();
130         try {
131             // final long startTime = System.currentTimeMillis();
132             for (int i = 0; i < numPools; i++) {
133                 pools.add(new GenericObjectPool<>(new WaiterFactory<>(0, 0, 0, 0, 0, 0), new GenericObjectPoolConfig<>()));
134             }
135             // System.out.println("Duration: " + (System.currentTimeMillis() - startTime));
136             final ObjectName oname = pools.get(numPools - 1).getJmxName();
137             assertEquals(1, mbs.queryNames(oname, null).size());
138         } finally {
139             pools.forEach(GenericObjectPool::close);
140         }
141     }
142 }