1 package com.atlassian.util.concurrent;
2
3 import static junit.framework.Assert.fail;
4 import static org.junit.Assert.assertEquals;
5 import static org.junit.Assert.assertTrue;
6
7 import org.junit.Test;
8
9 import java.util.concurrent.Callable;
10 import java.util.concurrent.atomic.AtomicBoolean;
11 import java.util.concurrent.atomic.AtomicReference;
12 import java.util.concurrent.locks.Lock;
13 import java.util.concurrent.locks.ReentrantLock;
14
15 public class LockManagerTest {
16 private final Function<String, String> reverser = new Function<String, String>() {
17 public String get(final String input) {
18 final StringBuilder result = new StringBuilder();
19 for (int i = input.length(); i > 0; i--) {
20 result.append(input.charAt(i - 1));
21 }
22 return result.toString();
23 };
24 };
25
26 @Test public void testLockManagerLocksAndUnlocksAndReturnsValue() throws Exception {
27 final AtomicReference<String> ref = new AtomicReference<String>();
28 final AtomicBoolean called = new AtomicBoolean();
29 final AtomicBoolean locked = new AtomicBoolean();
30 final AtomicBoolean unlocked = new AtomicBoolean();
31 final LockManager<String> manager = new LockManagers.Manager<String, String>(new Function<String, Lock>() {
32 public Lock get(final String input) {
33 ref.set(input);
34 return new ReentrantLock() {
35 @Override public void lock() {
36 locked.set(true);
37 super.lock();
38 }
39
40 @Override public void unlock() {
41 unlocked.set(true);
42 super.unlock();
43 }
44 };
45 };
46 }, reverser);
47
48 assertEquals("blah", manager.withLock("input", new Callable<String>() {
49 public String call() {
50 called.set(true);
51 return "blah";
52 }
53 }));
54
55 assertTrue(called.get());
56 assertTrue(locked.get());
57 assertTrue(unlocked.get());
58 assertEquals("tupni", ref.get());
59 }
60
61 @Test public void testLockManagerLocksAndUnlocksAndThrows() throws Exception {
62 final AtomicReference<String> ref = new AtomicReference<String>();
63 final AtomicBoolean called = new AtomicBoolean();
64 final AtomicBoolean locked = new AtomicBoolean();
65 final AtomicBoolean unlocked = new AtomicBoolean();
66 final LockManager<String> manager = new LockManagers.Manager<String, String>(new Function<String, Lock>() {
67 public Lock get(final String input) {
68 ref.set(input);
69 return new ReentrantLock() {
70 @Override public void lock() {
71 locked.set(true);
72 super.lock();
73 }
74
75 @Override public void unlock() {
76 unlocked.set(true);
77 super.unlock();
78 }
79 };
80 };
81 }, reverser);
82
83 class StupidException extends Exception {}
84
85 try {
86 manager.withLock("input", new Callable<String>() {
87 public String call() throws StupidException {
88 called.set(true);
89 throw new StupidException();
90 }
91 });
92 fail("StupidException expected");
93 }
94 catch (final StupidException ignore) {}
95
96 assertTrue(called.get());
97 assertTrue(locked.get());
98 assertTrue(unlocked.get());
99 assertEquals("tupni", ref.get());
100 }
101
102 @Test public void testLockManagerLocksAndUnlocksAndRuns() throws Exception {
103 final AtomicReference<String> ref = new AtomicReference<String>();
104 final AtomicBoolean called = new AtomicBoolean();
105 final AtomicBoolean locked = new AtomicBoolean();
106 final AtomicBoolean unlocked = new AtomicBoolean();
107 final LockManager<String> manager = new LockManagers.Manager<String, String>(new Function<String, Lock>() {
108 public Lock get(final String input) {
109 ref.set(input);
110 return new ReentrantLock() {
111 @Override public void lock() {
112 locked.set(true);
113 super.lock();
114 }
115
116 @Override public void unlock() {
117 unlocked.set(true);
118 super.unlock();
119 }
120 };
121 };
122 }, reverser);
123
124 manager.withLock("input", new Runnable() {
125 public void run() {
126 called.set(true);
127 }
128 });
129
130 assertTrue(called.get());
131 assertTrue(locked.get());
132 assertTrue(unlocked.get());
133 assertEquals("tupni", ref.get());
134 }
135
136 @Test public void testLockManagerLocksAndUnlocksAndThrowsRuntime() throws Exception {
137 final AtomicReference<String> ref = new AtomicReference<String>();
138 final AtomicBoolean called = new AtomicBoolean();
139 final AtomicBoolean locked = new AtomicBoolean();
140 final AtomicBoolean unlocked = new AtomicBoolean();
141 final LockManager<String> manager = new LockManagers.Manager<String, String>(new Function<String, Lock>() {
142 public Lock get(final String input) {
143 ref.set(input);
144 return new ReentrantLock() {
145 @Override public void lock() {
146 locked.set(true);
147 super.lock();
148 }
149
150 @Override public void unlock() {
151 unlocked.set(true);
152 super.unlock();
153 }
154 };
155 };
156 }, reverser);
157
158 class StupidException extends RuntimeException {}
159
160 try {
161 manager.withLock("input", new Runnable() {
162 public void run() throws StupidException {
163 called.set(true);
164 throw new StupidException();
165 }
166 });
167 fail("StupidException expected");
168 }
169 catch (final StupidException ignore) {}
170
171 assertTrue(called.get());
172 assertTrue(locked.get());
173 assertTrue(unlocked.get());
174 assertEquals("tupni", ref.get());
175 }
176 }