1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.pool2.proxy;
18
19 import static org.junit.jupiter.api.Assertions.assertEquals;
20 import static org.junit.jupiter.api.Assertions.assertNotNull;
21 import static org.junit.jupiter.api.Assertions.assertThrows;
22 import static org.junit.jupiter.api.Assertions.assertTrue;
23
24 import java.io.PrintWriter;
25 import java.io.StringWriter;
26 import java.time.Duration;
27
28 import org.apache.commons.pool2.BaseKeyedPooledObjectFactory;
29 import org.apache.commons.pool2.KeyedObjectPool;
30 import org.apache.commons.pool2.KeyedPooledObjectFactory;
31 import org.apache.commons.pool2.PooledObject;
32 import org.apache.commons.pool2.impl.AbandonedConfig;
33 import org.apache.commons.pool2.impl.DefaultPooledObject;
34 import org.apache.commons.pool2.impl.GenericKeyedObjectPool;
35 import org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig;
36 import org.junit.jupiter.api.BeforeEach;
37 import org.junit.jupiter.api.Test;
38
39 public abstract class AbstractTestProxiedKeyedObjectPool {
40
41 private static final class TestKeyedObjectFactory extends BaseKeyedPooledObjectFactory<String, TestObject> {
42
43 @Override
44 public TestObject create(final String key) {
45 return new TestObjectImpl();
46 }
47
48 @Override
49 public PooledObject<TestObject> wrap(final TestObject value) {
50 return new DefaultPooledObject<>(value);
51 }
52 }
53
54 protected interface TestObject {
55 String getData();
56 void setData(String data);
57 }
58
59 private static final class TestObjectImpl implements TestObject {
60
61 private String data;
62
63 @Override
64 public String getData() {
65 return data;
66 }
67
68 @Override
69 public void setData(final String data) {
70 this.data = data;
71 }
72 }
73
74 private static final String KEY1 = "key1";
75
76 private static final String DATA1 = "data1";
77
78 private static final Duration ABANDONED_TIMEOUT_SECS = Duration.ofSeconds(3);
79
80 private KeyedObjectPool<String, TestObject> pool;
81
82 private StringWriter log;
83
84 protected abstract ProxySource<TestObject> getproxySource();
85
86 @BeforeEach
87 public void setUp() {
88 log = new StringWriter();
89
90 final PrintWriter pw = new PrintWriter(log);
91 final AbandonedConfig abandonedConfig = new AbandonedConfig();
92 abandonedConfig.setLogAbandoned(true);
93 abandonedConfig.setRemoveAbandonedOnBorrow(true);
94 abandonedConfig.setUseUsageTracking(true);
95 abandonedConfig.setRemoveAbandonedTimeout(ABANDONED_TIMEOUT_SECS);
96 abandonedConfig.setLogWriter(pw);
97
98 final GenericKeyedObjectPoolConfig<TestObject> config = new GenericKeyedObjectPoolConfig<>();
99 config.setMaxTotal(3);
100
101 final KeyedPooledObjectFactory<String, TestObject> factory = new TestKeyedObjectFactory();
102
103 @SuppressWarnings("resource")
104 final KeyedObjectPool<String, TestObject> innerPool = new GenericKeyedObjectPool<>(factory, config, abandonedConfig);
105
106 pool = new ProxiedKeyedObjectPool<>(innerPool, getproxySource());
107 }
108
109 @Test
110 void testAccessAfterInvalidate() throws Exception {
111 final TestObject obj = pool.borrowObject(KEY1);
112 assertNotNull(obj);
113
114
115 obj.setData(DATA1);
116 assertEquals(DATA1, obj.getData());
117
118 pool.invalidateObject(KEY1, obj);
119
120 assertNotNull(obj);
121
122 assertThrows(IllegalStateException.class,
123 obj::getData);
124
125 }
126
127 @Test
128 void testAccessAfterReturn() throws Exception {
129 final TestObject obj = pool.borrowObject(KEY1);
130 assertNotNull(obj);
131
132
133 obj.setData(DATA1);
134 assertEquals(DATA1, obj.getData());
135
136 pool.returnObject(KEY1, obj);
137
138 assertNotNull(obj);
139 assertThrows(IllegalStateException.class,
140 obj::getData);
141 }
142
143 @Test
144 void testBorrowObject() throws Exception {
145 final TestObject obj = pool.borrowObject(KEY1);
146 assertNotNull(obj);
147
148
149 obj.setData(DATA1);
150 assertEquals(DATA1, obj.getData());
151
152 pool.returnObject(KEY1, obj);
153 }
154
155 @Test
156 void testPassThroughMethods01() throws Exception {
157 assertEquals(0, pool.getNumActive());
158 assertEquals(0, pool.getNumIdle());
159
160 pool.addObject(KEY1);
161
162 assertEquals(0, pool.getNumActive());
163 assertEquals(1, pool.getNumIdle());
164
165 pool.clear();
166
167 assertEquals(0, pool.getNumActive());
168 assertEquals(0, pool.getNumIdle());
169 }
170
171 @Test
172 void testPassThroughMethods02() {
173 pool.close();
174 assertThrows(IllegalStateException.class,
175 () -> pool.addObject(KEY1));
176 }
177
178 @Test
179 void testUsageTracking() throws Exception {
180 final TestObject obj = pool.borrowObject(KEY1);
181 assertNotNull(obj);
182
183
184 obj.setData(DATA1);
185
186
187 Thread.sleep(ABANDONED_TIMEOUT_SECS.plusSeconds(2).toMillis());
188
189
190 pool.borrowObject(KEY1);
191
192 final String logOutput = log.getBuffer().toString();
193
194 assertTrue(logOutput.contains("Pooled object created"));
195 assertTrue(logOutput.contains("The last code to use this object was"));
196 }
197
198 }