View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.collections4.map;
18  
19  import static org.junit.jupiter.api.Assertions.assertAll;
20  import static org.junit.jupiter.api.Assertions.assertEquals;
21  import static org.junit.jupiter.api.Assertions.assertFalse;
22  import static org.junit.jupiter.api.Assertions.assertNotNull;
23  import static org.junit.jupiter.api.Assertions.assertNull;
24  import static org.junit.jupiter.api.Assertions.assertThrows;
25  import static org.junit.jupiter.api.Assertions.assertTrue;
26  import static org.junit.jupiter.api.Assertions.fail;
27  
28  import java.util.HashMap;
29  import java.util.Map;
30  import java.util.concurrent.TimeUnit;
31  
32  import org.apache.commons.collections4.collection.AbstractCollectionTest;
33  import org.apache.commons.collections4.map.PassiveExpiringMap.ExpirationPolicy;
34  import org.junit.jupiter.api.Test;
35  
36  /**
37   * JUnit tests.
38   */
39  public class PassiveExpiringMapTest<K, V> extends AbstractMapTest<K, V> {
40  
41      private static final class TestExpirationPolicy
42          implements ExpirationPolicy<Integer, String> {
43  
44          private static final long serialVersionUID = 1L;
45  
46          @Override
47          public long expirationTime(final Integer key, final String value) {
48              // odd keys expire immediately, even keys never expire
49              if (key == null) {
50                  return 0;
51              }
52  
53              if (key.intValue() % 2 == 0) {
54                  return -1;
55              }
56  
57              return 0;
58          }
59      }
60  
61      public PassiveExpiringMapTest() {
62          super(PassiveExpiringMapTest.class.getSimpleName());
63      }
64  
65  //    public void testCreate() throws Exception {
66  //        writeExternalFormToDisk((java.io.Serializable) makeObject(),
67  //                "src/test/resources/data/test/PassiveExpiringMap.emptyCollection.version4.obj");
68  //
69  //        writeExternalFormToDisk((java.io.Serializable) makeFullMap(),
70  //                "src/test/resources/data/test/PassiveExpiringMap.fullCollection.version4.obj");
71  //    }
72  
73      @Override
74      public String getCompatibilityVersion() {
75          return "4";
76      }
77  
78      @Override
79      protected int getIterationBehaviour() {
80          return AbstractCollectionTest.UNORDERED;
81      }
82  
83      private Map<Integer, String> makeDecoratedTestMap() {
84          final Map<Integer, String> m = new HashMap<>();
85          m.put(Integer.valueOf(1), "one");
86          m.put(Integer.valueOf(2), "two");
87          m.put(Integer.valueOf(3), "three");
88          m.put(Integer.valueOf(4), "four");
89          m.put(Integer.valueOf(5), "five");
90          m.put(Integer.valueOf(6), "six");
91          return new PassiveExpiringMap<>(new TestExpirationPolicy(), m);
92      }
93  
94      @Override
95      public Map<K, V> makeObject() {
96          return new PassiveExpiringMap<>();
97      }
98  
99      private Map<Integer, String> makeTestMap() {
100         final Map<Integer, String> m =
101                 new PassiveExpiringMap<>(new TestExpirationPolicy());
102         m.put(Integer.valueOf(1), "one");
103         m.put(Integer.valueOf(2), "two");
104         m.put(Integer.valueOf(3), "three");
105         m.put(Integer.valueOf(4), "four");
106         m.put(Integer.valueOf(5), "five");
107         m.put(Integer.valueOf(6), "six");
108         return m;
109     }
110 
111     @Test
112     public void testConstructors() {
113         assertAll(
114                 () -> assertThrows(NullPointerException.class, () -> {
115                     final Map<String, String> map = null;
116                     new PassiveExpiringMap<>(map);
117                 },
118                         "constructor - exception should have been thrown."),
119                 () -> assertThrows(NullPointerException.class, () -> {
120                     final ExpirationPolicy<String, String> policy = null;
121                     new PassiveExpiringMap<>(policy);
122                 },
123                         "constructor - exception should have been thrown."),
124                 () -> assertThrows(NullPointerException.class, () -> {
125                     final TimeUnit unit = null;
126                     new PassiveExpiringMap<String, String>(10L, unit);
127                 },
128                         "constructor - exception should have been thrown.")
129         );
130     }
131 
132     @Test
133     public void testContainsKey() {
134         final Map<Integer, String> m = makeTestMap();
135         assertFalse(m.containsKey(Integer.valueOf(1)));
136         assertFalse(m.containsKey(Integer.valueOf(3)));
137         assertFalse(m.containsKey(Integer.valueOf(5)));
138         assertTrue(m.containsKey(Integer.valueOf(2)));
139         assertTrue(m.containsKey(Integer.valueOf(4)));
140         assertTrue(m.containsKey(Integer.valueOf(6)));
141     }
142 
143     @Test
144     public void testContainsValue() {
145         final Map<Integer, String> m = makeTestMap();
146         assertFalse(m.containsValue("one"));
147         assertFalse(m.containsValue("three"));
148         assertFalse(m.containsValue("five"));
149         assertTrue(m.containsValue("two"));
150         assertTrue(m.containsValue("four"));
151         assertTrue(m.containsValue("six"));
152     }
153 
154     @Test
155     public void testDecoratedMap() {
156         // entries shouldn't expire
157         final Map<Integer, String> m = makeDecoratedTestMap();
158         assertEquals(6, m.size());
159         assertEquals("one", m.get(Integer.valueOf(1)));
160 
161         // removing a single item shouldn't affect any other items
162         assertEquals("two", m.get(Integer.valueOf(2)));
163         m.remove(Integer.valueOf(2));
164         assertEquals(5, m.size());
165         assertEquals("one", m.get(Integer.valueOf(1)));
166         assertNull(m.get(Integer.valueOf(2)));
167 
168         // adding a single, even item shouldn't affect any other items
169         assertNull(m.get(Integer.valueOf(2)));
170         m.put(Integer.valueOf(2), "two");
171         assertEquals(6, m.size());
172         assertEquals("one", m.get(Integer.valueOf(1)));
173         assertEquals("two", m.get(Integer.valueOf(2)));
174 
175         // adding a single, odd item (one that expires) shouldn't affect any
176         // other items
177         // put the entry expires immediately
178         m.put(Integer.valueOf(1), "one-one");
179         assertEquals(5, m.size());
180         assertNull(m.get(Integer.valueOf(1)));
181         assertEquals("two", m.get(Integer.valueOf(2)));
182     }
183 
184     @Test
185     public void testEntrySet() {
186         final Map<Integer, String> m = makeTestMap();
187         assertEquals(3, m.entrySet().size());
188     }
189 
190     @Test
191     public void testExpiration() {
192         validateExpiration(new PassiveExpiringMap<>(500), 500);
193         validateExpiration(new PassiveExpiringMap<>(1000), 1000);
194         validateExpiration(new PassiveExpiringMap<>(
195                 new PassiveExpiringMap.ConstantTimeToLiveExpirationPolicy<>(500)), 500);
196         validateExpiration(new PassiveExpiringMap<>(
197                 new PassiveExpiringMap.ConstantTimeToLiveExpirationPolicy<>(1, TimeUnit.SECONDS)), 1000);
198     }
199 
200     @Test
201     public void testGet() {
202         final Map<Integer, String> m = makeTestMap();
203         assertNull(m.get(Integer.valueOf(1)));
204         assertEquals("two", m.get(Integer.valueOf(2)));
205         assertNull(m.get(Integer.valueOf(3)));
206         assertEquals("four", m.get(Integer.valueOf(4)));
207         assertNull(m.get(Integer.valueOf(5)));
208         assertEquals("six", m.get(Integer.valueOf(6)));
209     }
210 
211     @Test
212     public void testIsEmpty() {
213         Map<Integer, String> m = makeTestMap();
214         assertFalse(m.isEmpty());
215 
216         // remove just evens
217         m = makeTestMap();
218         m.remove(Integer.valueOf(2));
219         m.remove(Integer.valueOf(4));
220         m.remove(Integer.valueOf(6));
221         assertTrue(m.isEmpty());
222     }
223 
224     @Test
225     public void testKeySet() {
226         final Map<Integer, String> m = makeTestMap();
227         assertEquals(3, m.size());
228     }
229 
230     @Test
231     public void testPut() {
232         final Map<Integer, String> m = makeTestMap();
233         assertNull(m.put(Integer.valueOf(1), "ONE"));
234         assertEquals("two", m.put(Integer.valueOf(2), "TWO"));
235         assertNull(m.put(Integer.valueOf(3), "THREE"));
236         assertEquals("four", m.put(Integer.valueOf(4), "FOUR"));
237         assertNull(m.put(Integer.valueOf(5), "FIVE"));
238         assertEquals("six", m.put(Integer.valueOf(6), "SIX"));
239     }
240 
241     @Test
242     public void testSize() {
243         final Map<Integer, String> m = makeTestMap();
244         assertEquals(3, m.size());
245     }
246 
247     @Test
248     public void testValues() {
249         final Map<Integer, String> m = makeTestMap();
250         assertEquals(3, m.size());
251     }
252 
253     @Test
254     public void testZeroTimeToLive() {
255         // item should not be available
256         final PassiveExpiringMap<String, String> m = new PassiveExpiringMap<>(0L);
257         m.put("a", "b");
258         assertNull(m.get("a"));
259     }
260 
261     private void validateExpiration(final Map<String, String> map, final long timeout) {
262         map.put("a", "b");
263 
264         assertNotNull(map.get("a"));
265 
266         try {
267             Thread.sleep(2 * timeout);
268         } catch (final InterruptedException e) {
269             fail();
270         }
271 
272         assertNull(map.get("a"));
273     }
274 
275 }