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