View Javadoc

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