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