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