View Javadoc

1   package com.atlassian.cache.hazelcast;
2   
3   import javax.annotation.Nonnull;
4   
5   import com.atlassian.cache.AbstractCacheLazyTest;
6   import com.atlassian.cache.Cache;
7   import com.atlassian.cache.CacheFactory;
8   import com.atlassian.cache.CacheLoader;
9   import com.atlassian.cache.CacheSettingsBuilder;
10  
11  import org.junit.Before;
12  import org.junit.ClassRule;
13  import org.junit.Test;
14  
15  import static org.hamcrest.MatcherAssert.assertThat;
16  import static org.hamcrest.Matchers.equalTo;
17  import static org.hamcrest.Matchers.is;
18  import static org.hamcrest.Matchers.nullValue;
19  
20  public class HazelcastHybridCacheLazyTest extends AbstractCacheLazyTest
21  {
22      @ClassRule
23      public static InitOnceHazelcastCluster cluster = InitOnceHazelcastCluster.getInstance();
24  
25      private Cache<String, Long> cacheNode1;
26      private Cache<String, Long> cacheNode2;
27  
28      @Before
29      public void setUp() throws Exception
30      {
31          cluster.reset();
32          factory = HazelcastTestSupport.createDistributedFactory(cluster.getNode(0));
33          CacheFactory factory2 = HazelcastTestSupport.createDistributedFactory(cluster.getNode(1));
34  
35          // create a loader that never creates the same value twice. Used to verify indirectly that the cache has been
36          // invalidated
37          CacheLoader<String, Long> loader = new BadLoader();
38          // create two caches backed by the same version map, but different local caches.
39          cacheNode1 = factory.getCache("test", loader, settingsBuilder().build());
40          cacheNode2 = factory2.getCache("test", loader, settingsBuilder().build());
41      }
42  
43      @Override
44      protected CacheSettingsBuilder settingsBuilder()
45      {
46          return new CacheSettingsBuilder().remote().replicateViaInvalidation();
47      }
48  
49      @Test
50      public void testLazyCreationDoestNotInvalidateCache()
51      {
52          // verify that the value is cached properly
53          assertThat(cacheNode1.get("key"), equalTo(1L));
54          assertThat(cacheNode1.get("key"), equalTo(1L));
55  
56          // retrieve the same key from the other cache - should be a local cache miss and trigger a call to BadLoader
57          assertThat(cacheNode2.get("key"), equalTo(2L));
58  
59          // but this should not trigger a cache eviction for cacheNode1
60          assertThat(cacheNode1.get("key"), equalTo(1L));
61      }
62  
63      @Test
64      public void testPutInvalidatesCache()
65      {
66          // fill the cache on node1
67          assertThat(cacheNode1.get("key"), equalTo(1L));
68  
69          cacheNode2.put("key", 99L);
70          assertThat(cacheNode2.get("key"), equalTo(99L));
71  
72          // verify that cache1 has been invalidated
73          assertThat(cacheNode1.get("key"), equalTo(2L));
74          assertThat(cacheNode2.get("key"), equalTo(99L));
75      }
76  
77      @Test
78      public void testPutIfAbsentInvalidatesCache()
79      {
80          // fill the cache on node1
81          assertThat(cacheNode1.get("key"), equalTo(1L));
82  
83          Long oldValue = cacheNode2.putIfAbsent("key", 99L);
84          assertThat(oldValue, nullValue());
85          assertThat(cacheNode2.get("key"), equalTo(99L));
86  
87          // verify that cache1 has been invalidated
88          assertThat(cacheNode1.get("key"), equalTo(2L));
89          assertThat(cacheNode2.get("key"), equalTo(99L));
90  
91          // verify that putIfAbsent does not invalidate cache when there's a value
92          oldValue = cacheNode2.putIfAbsent("key", 101L);
93          assertThat(oldValue, equalTo(99L));
94          assertThat(cacheNode1.get("key"), equalTo(2L)); // should still be the same
95      }
96  
97      @Test
98      public void testReplaceInvalidatesCache()
99      {
100         // fill the caches
101         assertThat(cacheNode1.get("key"), equalTo(1L));
102         assertThat(cacheNode2.get("key"), equalTo(2L));
103 
104         cacheNode2.replace("key", 2L, 99L);
105         assertThat(cacheNode1.get("key"), equalTo(3L)); // cache 1 should have invalidated
106         assertThat(cacheNode2.get("key"), equalTo(99L));
107 
108         // verify that caches don't invalidate if the value is not replaced
109         boolean replaced = cacheNode2.replace("key", 10012L, 1L);
110         assertThat(replaced, is(false));
111         assertThat(cacheNode1.get("key"), equalTo(3L)); // unchanged
112         assertThat(cacheNode2.get("key"), equalTo(99L)); // unchanged
113     }
114 
115     @Test
116     public void testRemoveInvalidatesCache()
117     {
118         // fill the caches
119         assertThat(cacheNode1.get("key"), equalTo(1L));
120         assertThat(cacheNode2.get("key"), equalTo(2L));
121 
122         cacheNode2.remove("key");
123         assertThat(cacheNode1.get("key"), equalTo(3L)); // invalidated
124         assertThat(cacheNode2.get("key"), equalTo(4L)); // invalidated
125 
126         // test conditional remove
127         boolean removed = cacheNode2.remove("key", 3L);
128         assertThat(removed, is(false));
129         assertThat(cacheNode1.get("key"), equalTo(3L)); // unchanged
130         assertThat(cacheNode2.get("key"), equalTo(4L)); // unchanged
131 
132         removed = cacheNode2.remove("key", 4L);
133         assertThat(removed, is(true));
134         assertThat(cacheNode1.get("key"), equalTo(5L)); // invalidated
135         assertThat(cacheNode2.get("key"), equalTo(6L)); // invalidated
136     }
137 
138     @Test
139     public void testRemoveAllInvalidatesCache()
140     {
141         // fill the caches
142         assertThat(cacheNode1.get("key"), equalTo(1L));
143         assertThat(cacheNode2.get("key"), equalTo(2L));
144 
145         cacheNode2.removeAll();
146         assertThat(cacheNode1.get("key"), equalTo(3L)); // invalidated
147         assertThat(cacheNode2.get("key"), equalTo(4L)); // invalidated
148     }
149 
150     private static class BadLoader implements CacheLoader<String, Long>
151     {
152         private long value;
153 
154         @Nonnull
155         @Override
156         public Long load(@Nonnull String key)
157         {
158             return ++value;
159         }
160     }
161 }