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  package org.apache.commons.pool2.impl;
18  
19  import static org.hamcrest.MatcherAssert.assertThat;
20  import static org.hamcrest.Matchers.lessThan;
21  import static org.hamcrest.Matchers.lessThanOrEqualTo;
22  import static org.junit.jupiter.api.Assertions.assertEquals;
23  import static org.junit.jupiter.api.Assertions.assertFalse;
24  import static org.junit.jupiter.api.Assertions.assertNotNull;
25  
26  import java.time.Duration;
27  import java.util.ArrayList;
28  import java.util.List;
29  import java.util.concurrent.ExecutorService;
30  import java.util.concurrent.Executors;
31  import java.util.concurrent.Future;
32  import java.util.concurrent.atomic.AtomicBoolean;
33  
34  import org.apache.commons.pool2.PooledObject;
35  import org.junit.jupiter.api.Test;
36  
37  /**
38   * Tests {@link DefaultPooledObject}.
39   */
40  public class TestDefaultPooledObject {
41  
42      /**
43       * JIRA: POOL-279
44       *
45       * @throws Exception May occur in some failure modes
46       */
47      @Test
48      public void testGetIdleTimeMillis() throws Exception {
49          final DefaultPooledObject<Object> dpo = new DefaultPooledObject<>(new Object());
50          final AtomicBoolean negativeIdleTimeReturned = new AtomicBoolean(false);
51          final ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 3);
52          final Runnable allocateAndDeallocateTask = () -> {
53              for (int i1 = 0; i1 < 10000; i1++) {
54                  if (dpo.getIdleDuration().isNegative() || dpo.getIdleTime().isNegative()) {
55                      negativeIdleTimeReturned.set(true);
56                      break;
57                  }
58                  if (dpo.getIdleDuration().isNegative() || dpo.getIdleTime().isNegative()) {
59                      negativeIdleTimeReturned.set(true);
60                      break;
61                  }
62              }
63              dpo.allocate();
64              for (int i2 = 0; i2 < 10000; i2++) {
65                  if (dpo.getIdleDuration().isNegative() || dpo.getIdleTime().isNegative()) {
66                      negativeIdleTimeReturned.set(true);
67                      break;
68                  }
69              }
70              dpo.deallocate();
71          };
72          final Runnable getIdleTimeTask = () -> {
73              for (int i = 0; i < 10000; i++) {
74                  if (dpo.getIdleDuration().isNegative() || dpo.getIdleTime().isNegative()) {
75                      negativeIdleTimeReturned.set(true);
76                      break;
77                  }
78              }
79          };
80          final double probabilityOfAllocationTask = 0.7;
81          final List<Future<?>> futures = new ArrayList<>();
82          for (int i = 1; i <= 10000; i++) {
83              final Runnable randomTask = Math.random() < probabilityOfAllocationTask ? allocateAndDeallocateTask : getIdleTimeTask;
84              futures.add(executor.submit(randomTask));
85          }
86          for (final Future<?> future : futures) {
87              future.get();
88          }
89          assertFalse(negativeIdleTimeReturned.get(), "DefaultPooledObject.getIdleTimeMillis() returned a negative value");
90      }
91  
92      @Test
93      public void testInitialStateActiveDuration() throws InterruptedException {
94          final PooledObject<Object> dpo = new DefaultPooledObject<>(new Object());
95          // Sleep MUST be "long enough" to test that we are not returning a negative time.
96          // Need an API in Java 8 to get the clock granularity.
97          Thread.sleep(200);
98          // In the initial state, all instants are the creation instant: last borrow, last use, last return.
99          // In the initial state, the active duration is the time between "now" and the creation time.
100         // In the initial state, the idle duration is the time between "now" and the last return, which is the creation time.
101         assertFalse(dpo.getActiveDuration().isNegative());
102         assertFalse(dpo.getActiveDuration().isZero());
103         // We use greaterThanOrEqualTo instead of equal because "now" many be different when each argument is evaluated.
104         assertThat(1L, lessThanOrEqualTo(2L)); // sanity check
105         assertThat(Duration.ZERO, lessThanOrEqualTo(Duration.ZERO.plusNanos(1))); // sanity check
106         assertThat(dpo.getActiveDuration(), lessThanOrEqualTo(dpo.getIdleDuration()));
107         // Deprecated
108         assertThat(dpo.getActiveDuration().toMillis(), lessThanOrEqualTo(dpo.getActiveTimeMillis()));
109         assertThat(dpo.getActiveDuration(), lessThanOrEqualTo(dpo.getActiveTime()));
110         assertThat(dpo.getActiveDuration(), lessThanOrEqualTo(dpo.getIdleTime()));
111         assertThat(dpo.getActiveDuration().toMillis(), lessThanOrEqualTo(dpo.getIdleTimeMillis()));
112     }
113 
114     @Test
115     public void testInitialStateCreateInstant() {
116         final PooledObject<Object> dpo = new DefaultPooledObject<>(new Object());
117 
118         // In the initial state, all instants are the creation instant: last borrow, last use, last return.
119 
120         // Instant vs. Instant
121         assertEquals(dpo.getCreateInstant(), dpo.getLastBorrowInstant());
122         assertEquals(dpo.getCreateInstant(), dpo.getLastReturnInstant());
123         assertEquals(dpo.getCreateInstant(), dpo.getLastUsedInstant());
124 
125         // Instant vs. long (deprecated)
126         assertEquals(dpo.getCreateInstant().toEpochMilli(), dpo.getCreateTime());
127 
128         // long vs. long (deprecated)
129         assertEquals(dpo.getCreateTime(), dpo.getLastBorrowTime());
130         assertEquals(dpo.getCreateTime(), dpo.getLastReturnTime());
131         assertEquals(dpo.getCreateTime(), dpo.getLastUsedTime());
132     }
133 
134     @Test
135     public void testInitialStateDuration() throws InterruptedException {
136         final PooledObject<Object> dpo = new DefaultPooledObject<>(new Object());
137         final Duration duration1 = dpo.getFullDuration();
138         assertNotNull(duration1);
139         assertFalse(duration1.isNegative());
140         Thread.sleep(100);
141         final Duration duration2 = dpo.getFullDuration();
142         assertNotNull(duration2);
143         assertFalse(duration2.isNegative());
144         assertThat(duration1, lessThan(duration2));
145     }
146 
147     @Test
148     public void testInitialStateIdleDuration() throws InterruptedException {
149         final PooledObject<Object> dpo = new DefaultPooledObject<>(new Object());
150         // Sleep MUST be "long enough" to test that we are not returning a negative time.
151         Thread.sleep(200);
152         // In the initial state, all instants are the creation instant: last borrow, last use, last return.
153         // In the initial state, the active duration is the time between "now" and the creation time.
154         // In the initial state, the idle duration is the time between "now" and the last return, which is the creation time.
155         assertFalse(dpo.getIdleDuration().isNegative());
156         assertFalse(dpo.getIdleDuration().isZero());
157         // We use greaterThanOrEqualTo instead of equal because "now" many be different when each argument is evaluated.
158         assertThat(dpo.getIdleDuration(), lessThanOrEqualTo(dpo.getActiveDuration()));
159         // Deprecated
160         // assertThat(dpo.getIdleDuration().toMillis(), lessThanOrEqualTo(dpo.getIdleTimeMillis()));
161         // assertThat(dpo.getIdleDuration(), lessThanOrEqualTo(dpo.getIdleTime()));
162         assertThat(dpo.getIdleDuration(), lessThanOrEqualTo(dpo.getActiveTime()));
163         assertThat(dpo.getIdleDuration().toMillis(), lessThanOrEqualTo(dpo.getActiveTimeMillis()));
164     }
165 }