1
2
3
4
5
6
7
8
9
10
11 package psiprobe.tools;
12
13 import static org.junit.jupiter.api.Assertions.assertFalse;
14 import static org.junit.jupiter.api.Assertions.assertTrue;
15
16 import java.util.concurrent.CountDownLatch;
17 import java.util.concurrent.atomic.AtomicBoolean;
18
19 import org.junit.jupiter.api.Test;
20
21
22
23
24 class UpdateCommitLockTest {
25
26 @Test
27 void testLockAndReleaseUpdate() throws InterruptedException {
28 UpdateCommitLock lock = new UpdateCommitLock();
29 lock.lockForUpdate();
30 lock.releaseUpdateLock();
31
32 }
33
34 @Test
35 void testLockAndReleaseCommit() throws InterruptedException {
36 UpdateCommitLock lock = new UpdateCommitLock();
37 lock.lockForCommit();
38 lock.releaseCommitLock();
39 }
40
41 @Test
42 void testMultipleUpdatesCanProceedConcurrently() throws InterruptedException {
43 UpdateCommitLock lock = new UpdateCommitLock();
44 CountDownLatch startLatch = new CountDownLatch(1);
45 CountDownLatch bothLocked = new CountDownLatch(2);
46 AtomicBoolean bothAcquired = new AtomicBoolean(false);
47
48 Runnable task = () -> {
49 try {
50 startLatch.await();
51 lock.lockForUpdate();
52 bothLocked.countDown();
53 bothLocked.await();
54 bothAcquired.set(true);
55 lock.releaseUpdateLock();
56 } catch (InterruptedException e) {
57 Thread.currentThread().interrupt();
58 }
59 };
60
61 Thread t1 = new Thread(task);
62 Thread t2 = new Thread(task);
63 t1.start();
64 t2.start();
65
66 startLatch.countDown();
67 t1.join(3000);
68 t2.join(3000);
69
70 assertTrue(bothAcquired.get(), "Both threads should acquire update lock simultaneously");
71 }
72
73 @Test
74 void testCommitWaitsForUpdate() throws InterruptedException {
75 UpdateCommitLock lock = new UpdateCommitLock();
76 lock.lockForUpdate();
77
78 AtomicBoolean commitAcquired = new AtomicBoolean(false);
79 CountDownLatch commitStarted = new CountDownLatch(1);
80
81 Thread commitThread = new Thread(() -> {
82 try {
83 commitStarted.countDown();
84 lock.lockForCommit();
85 commitAcquired.set(true);
86 lock.releaseCommitLock();
87 } catch (InterruptedException e) {
88 Thread.currentThread().interrupt();
89 }
90 });
91 commitThread.start();
92
93 commitStarted.await();
94
95 Thread.sleep(100);
96 assertFalse(commitAcquired.get(), "Commit should be waiting for update lock");
97
98 lock.releaseUpdateLock();
99 commitThread.join(3000);
100 assertTrue(commitAcquired.get(), "Commit should have acquired lock after update released");
101 }
102
103 @Test
104 void testUpdateWaitsForCommit() throws InterruptedException {
105 UpdateCommitLock lock = new UpdateCommitLock();
106 lock.lockForCommit();
107
108 AtomicBoolean updateAcquired = new AtomicBoolean(false);
109 CountDownLatch updateStarted = new CountDownLatch(1);
110
111 Thread updateThread = new Thread(() -> {
112 try {
113 updateStarted.countDown();
114 lock.lockForUpdate();
115 updateAcquired.set(true);
116 lock.releaseUpdateLock();
117 } catch (InterruptedException e) {
118 Thread.currentThread().interrupt();
119 }
120 });
121 updateThread.start();
122
123 updateStarted.await();
124 Thread.sleep(100);
125 assertFalse(updateAcquired.get(), "Update should wait for commit to finish");
126
127 lock.releaseCommitLock();
128 updateThread.join(3000);
129 assertTrue(updateAcquired.get(), "Update should have acquired lock after commit released");
130 }
131
132 @Test
133 void testUpdateWaitsForCommitRequest() throws InterruptedException {
134 UpdateCommitLock lock = new UpdateCommitLock();
135
136 lock.lockForUpdate();
137
138 CountDownLatch commitRequesting = new CountDownLatch(1);
139 AtomicBoolean updateAcquiredAfterCommitRequest = new AtomicBoolean(false);
140
141 Thread commitRequestThread = new Thread(() -> {
142 try {
143 commitRequesting.countDown();
144 lock.lockForCommit();
145 Thread.sleep(200);
146 lock.releaseCommitLock();
147 } catch (InterruptedException e) {
148 Thread.currentThread().interrupt();
149 }
150 });
151 commitRequestThread.start();
152
153 commitRequesting.await();
154 Thread.sleep(50);
155 lock.releaseUpdateLock();
156
157 Thread updateAfterCommitReq = new Thread(() -> {
158 try {
159 lock.lockForUpdate();
160 updateAcquiredAfterCommitRequest.set(true);
161 lock.releaseUpdateLock();
162 } catch (InterruptedException e) {
163 Thread.currentThread().interrupt();
164 }
165 });
166
167
168 commitRequestThread.join(3000);
169 updateAfterCommitReq.start();
170 updateAfterCommitReq.join(3000);
171
172 assertTrue(updateAcquiredAfterCommitRequest.get());
173 }
174 }