1
2
3
4
5
6
7 package org.mule.util.store;
8
9 import org.mule.api.lifecycle.InitialisationException;
10 import org.mule.tck.junit4.AbstractMuleTestCase;
11
12 import edu.emory.mathcs.backport.java.util.concurrent.CountDownLatch;
13 import edu.emory.mathcs.backport.java.util.concurrent.TimeUnit;
14 import org.junit.After;
15 import org.junit.Test;
16
17 import static org.junit.Assert.assertEquals;
18 import static org.junit.Assert.assertFalse;
19 import static org.junit.Assert.assertTrue;
20
21 public class InMemoryStoreTestCase extends AbstractMuleTestCase
22 {
23 private InMemoryObjectStore<String> store = null;
24
25 @After
26 public void disposeStore()
27 {
28 store.dispose();
29 }
30
31 @Test
32 public void testSimpleTimedExpiry() throws Exception
33 {
34 int entryTTL = 3000;
35 createTimedObjectStore(entryTTL);
36
37
38 storeObjects("1", "2", "3");
39
40
41 assertObjectsInStore("1", "2", "3");
42
43
44 Thread.sleep(entryTTL + 1000);
45
46
47 assertObjectsExpired("1", "2", "3");
48 }
49
50 @Test
51 public void testComplexTimedExpiry() throws Exception
52 {
53 int entryTTL = 3000;
54 createTimedObjectStore(entryTTL);
55
56
57 storeObjects("1");
58
59
60 Thread.sleep(entryTTL / 2);
61
62
63 storeObjects("2");
64
65
66 Thread.sleep((entryTTL / 2) + 500);
67
68 assertObjectsExpired("1");
69 assertObjectsInStore("2");
70 }
71
72 @Test
73 public void testStoreAndRetrieve() throws Exception
74 {
75 String key = "key";
76 String value = "hello";
77
78 createBoundedObjectStore(1);
79
80 store.store(key, value);
81 assertObjectsInStore(key);
82
83 String retrieved = store.retrieve(key);
84 assertEquals(value, retrieved);
85
86 store.remove(key);
87 assertObjectsExpired(key);
88 }
89
90 @Test
91 public void testExpiringUnboundedStore() throws Exception
92 {
93 createUnboundedObjectStore();
94
95
96 storeObjects("1", "2", "3");
97
98
99 store.expire();
100
101 assertObjectsInStore("1", "2", "3");
102 }
103
104 @Test
105 public void testMaxSize() throws Exception
106 {
107 int maxEntries = 3;
108 createBoundedObjectStore(maxEntries);
109
110 storeObjects("1", "2", "3");
111 assertObjectsInStore("1", "2", "3");
112
113
114 store.store("4", "4");
115
116
117 assertTrue(store.contains("1"));
118
119
120 store.expire();
121 assertObjectsExpired("1");
122 assertObjectsInStore("2", "3", "4");
123
124
125 storeObjects("5");
126 store.expire();
127 assertObjectsExpired("2");
128 assertObjectsInStore("3", "4", "5");
129
130
131 storeObjects("6", "7", "8", "9");
132 store.expire();
133 assertObjectsInStore("7", "8", "9");
134 assertObjectsExpired("3", "4", "5", "6");
135 }
136
137 private void storeObjects(String... objects) throws Exception
138 {
139 for (String entry : objects)
140 {
141 store.store(entry, entry);
142 }
143 }
144
145 private void assertObjectsInStore(String... identifiers) throws Exception
146 {
147 for (String id : identifiers)
148 {
149 String message = "id " + id + " not in store " + store;
150 assertTrue(message, store.contains(id));
151 }
152 }
153
154 private void assertObjectsExpired(String... identifiers) throws Exception
155 {
156 for (String id : identifiers)
157 {
158 assertFalse(store.contains(id));
159 }
160 }
161
162 private void createTimedObjectStore(int timeToLive) throws InitialisationException
163 {
164 int expireInterval = 1000;
165 assertTrue("objects' time to live must be greater than the expire interval",
166 timeToLive > expireInterval);
167
168 store = new InMemoryObjectStore<String>();
169 store.setName("timed");
170 store.setMaxEntries(3);
171 store.setEntryTTL(timeToLive);
172 store.setExpirationInterval(expireInterval);
173 store.initialise();
174 }
175
176 private void createBoundedObjectStore(int numberOfEntries) throws InitialisationException
177 {
178 createNonexpiringObjectStore();
179 store.setName("bounded");
180 store.setMaxEntries(numberOfEntries);
181 store.initialise();
182 }
183
184 private void createUnboundedObjectStore() throws InitialisationException
185 {
186 createNonexpiringObjectStore();
187 store.setMaxEntries(-1);
188 store.initialise();
189 }
190
191 private void createNonexpiringObjectStore()
192 {
193 store = new NonExpiringInMemoryObjectStore();
194 }
195
196
197
198
199
200
201
202
203 private static class NonExpiringInMemoryObjectStore extends InMemoryObjectStore<String>
204 {
205 private CountDownLatch expireLatch;
206
207 public NonExpiringInMemoryObjectStore()
208 {
209 super();
210
211 setEntryTTL(-1);
212
213 setExpirationInterval(Integer.MAX_VALUE);
214
215 expireLatch = new CountDownLatch(1);
216 }
217
218 @Override
219 public void initialise() throws InitialisationException
220 {
221 super.initialise();
222
223
224 try
225 {
226 expireLatch.await(30, TimeUnit.SECONDS);
227 }
228 catch (InterruptedException ie)
229 {
230 throw new RuntimeException("Interrupted while waiting for the first expire", ie);
231 }
232 }
233
234 @Override
235 public void expire()
236 {
237 super.expire();
238
239 expireLatch.countDown();
240 }
241 }
242 }