View Javadoc
1   package com.atlassian.plugin.manager.store;
2   
3   import com.atlassian.plugin.manager.PluginPersistentState;
4   import com.atlassian.plugin.manager.PluginPersistentStateStore;
5   import com.google.common.collect.ImmutableList;
6   import org.junit.Before;
7   import org.junit.Rule;
8   import org.junit.Test;
9   import org.junit.contrib.java.lang.system.RestoreSystemProperties;
10  import org.junit.runner.RunWith;
11  import org.junit.runners.Parameterized;
12  import org.mockito.Mock;
13  import org.mockito.invocation.InvocationOnMock;
14  import org.mockito.junit.MockitoJUnitRunner;
15  import org.mockito.stubbing.Answer;
16  
17  import java.util.concurrent.locks.ReadWriteLock;
18  import java.util.concurrent.locks.ReentrantLock;
19  
20  import static com.atlassian.plugin.manager.store.SynchronizedPluginPersistentStateStore.LockMode;
21  import static com.atlassian.plugin.manager.store.SynchronizedPluginPersistentStateStore.getLockModeProperty;
22  import static org.hamcrest.MatcherAssert.assertThat;
23  import static org.hamcrest.Matchers.is;
24  import static org.mockito.Mockito.doAnswer;
25  import static org.mockito.Mockito.verify;
26  import static org.mockito.Mockito.when;
27  
28  @RunWith(MockitoJUnitRunner.class)
29  public class TestSynchronizedPluginPersistentStateStore {
30      @Mock
31      PluginPersistentStateStore delegate;
32      @Mock
33      ReadWriteLock readWriteLock;
34      @Mock
35      PluginPersistentState pluginPersistentState;
36  
37      ReentrantLock readLock;
38      ReentrantLock writeLock;
39  
40      SynchronizedPluginPersistentStateStore synchronizedPluginPersistentStateStore;
41  
42      @Before
43      public void setUp() throws Exception {
44          readLock = new ReentrantLock();
45          writeLock = new ReentrantLock();
46          when(readWriteLock.readLock()).thenReturn(readLock);
47          when(readWriteLock.writeLock()).thenReturn(writeLock);
48          synchronizedPluginPersistentStateStore = new SynchronizedPluginPersistentStateStore(delegate, readWriteLock);
49      }
50  
51      @Test
52      public void saveGetsWriteLockAndForwardsToDelegate() {
53          final Answer<Object> answer = new LockCheckingAnswer(false, true, null);
54          doAnswer(answer).when(delegate).save(pluginPersistentState);
55          synchronizedPluginPersistentStateStore.save(pluginPersistentState);
56          verify(delegate).save(pluginPersistentState);
57          assertLockState(false, false);
58      }
59  
60      @Test
61      public void loadGetsReadLockAndForwardsToDelegate() {
62          final Answer<Object> answer = new LockCheckingAnswer(true, false, pluginPersistentState);
63          when(delegate.load()).thenAnswer(answer);
64          final PluginPersistentState actual = synchronizedPluginPersistentStateStore.load();
65          assertThat(actual, is(pluginPersistentState));
66          verify(delegate).load();
67          assertLockState(false, false);
68      }
69  
70      private class LockCheckingAnswer implements Answer<Object> {
71          private final boolean readLocked;
72          private final boolean writeLocked;
73          private final Object result;
74  
75          public LockCheckingAnswer(final boolean readLocked, final boolean writeLocked, final Object result) {
76              this.readLocked = readLocked;
77              this.writeLocked = writeLocked;
78              this.result = result;
79          }
80  
81          @Override
82          public Object answer(final InvocationOnMock invocationOnMock) throws Throwable {
83              assertLockState(readLocked, writeLocked);
84              return result;
85          }
86      }
87  
88      private void assertLockState(final boolean readLocked, final boolean writeLocked) {
89          assertThat(readLock.isLocked(), is(readLocked));
90          assertThat(writeLock.isLocked(), is(writeLocked));
91      }
92  
93      public static class TestLockModeDefault {
94          @Test
95          public void defaultLockModeIsReadWrite() {
96              final LockMode lockMode = LockMode.current();
97              assertThat(lockMode, is(LockMode.READWRITE));
98          }
99      }
100 
101     @RunWith(Parameterized.class)
102     public static class TestLockMode {
103         @Rule
104         public final RestoreSystemProperties restoreSystemProperties = new RestoreSystemProperties();
105 
106         final String propertyValue;
107         final LockMode expectedMode;
108         final boolean simple;
109 
110         @Parameterized.Parameters(name = "{index}: Property {0} yields {1}")
111         public static Iterable<Object[]> data() {
112             return ImmutableList.<Object[]>builder()
113                     .add(new Object[]{"unlocked", LockMode.UNLOCKED, true})
114                     .add(new Object[]{"simple", LockMode.SIMPLE, true})
115                     .add(new Object[]{"fairsimple", LockMode.FAIRSIMPLE, true})
116                     .add(new Object[]{"readwrite", LockMode.READWRITE, false})
117                     .add(new Object[]{"fairreadwrite", LockMode.FAIRREADWRITE, false})
118                     .build();
119         }
120 
121         public TestLockMode(final String propertyValue, final LockMode expectedMode, final boolean simple) {
122             this.propertyValue = propertyValue;
123             this.expectedMode = expectedMode;
124             this.simple = simple;
125         }
126 
127         @Test
128         public void propertyValueYieldsExpectedLockMode() {
129             System.setProperty(getLockModeProperty(), propertyValue);
130 
131             final LockMode lockMode = LockMode.current();
132             assertThat(lockMode, is(expectedMode));
133             final ReadWriteLock readWriteLock = lockMode.getReadWriteLock();
134             assertThat(readWriteLock.readLock() == readWriteLock.writeLock(), is(simple));
135         }
136     }
137 }