1
1
package com.datadog.iast.util
2
2
3
- import datadog.trace.test.util.DDSpecification
3
+
4
4
import groovy.transform.CompileDynamic
5
+ import spock.lang.Specification
5
6
6
7
import java.util.concurrent.Callable
7
8
import java.util.concurrent.CountDownLatch
8
9
import java.util.concurrent.Executors
9
10
import java.util.concurrent.TimeUnit
10
11
11
12
@CompileDynamic
12
- class NonBlockingSemaphoreTest extends DDSpecification {
13
+ class NonBlockingSemaphoreTest extends Specification {
13
14
14
15
void 'test that the semaphore controls access to a shared resource (#permitCount )' (final int permitCount) {
15
16
given:
@@ -71,6 +72,40 @@ class NonBlockingSemaphoreTest extends DDSpecification {
71
72
2 | _
72
73
}
73
74
75
+ void ' can never acquire more permits than the total' (final int permitCount) {
76
+ given:
77
+ final semaphore = NonBlockingSemaphore.withPermitCount(permitCount)
78
+
79
+ when:
80
+ final acquired = semaphore.acquire(permitCount+1)
81
+
82
+ then:
83
+ !acquired
84
+
85
+ where:
86
+ permitCount | _
87
+ 1 | _
88
+ 2 | _
89
+ }
90
+
91
+ void ' can perform extra releases' (final int permitCount) {
92
+ given:
93
+ final semaphore = NonBlockingSemaphore.withPermitCount(permitCount)
94
+
95
+ when:
96
+ for (int i = 0; i < permitCount * 2; i++) {
97
+ assert semaphore.release() == permitCount
98
+ }
99
+
100
+ then:
101
+ semaphore.available() == permitCount
102
+
103
+ where:
104
+ permitCount | _
105
+ 1 | _
106
+ 2 | _
107
+ }
108
+
74
109
void ' reset helps recover when there is starvation (#permitCount)' (final int permitCount) {
75
110
given:
76
111
final semaphore = NonBlockingSemaphore.withPermitCount(permitCount)
@@ -97,24 +132,41 @@ class NonBlockingSemaphoreTest extends DDSpecification {
97
132
given:
98
133
final int threads = 100
99
134
final semaphore = NonBlockingSemaphore.unlimited()
100
- final latch = new CountDownLatch(threads)
101
- final executors = Executors.newFixedThreadPool(threads)
102
135
103
136
when:
104
137
final acquired = (1..threads).collect {
105
- executors.submit({
106
- latch.countDown()
107
- if (semaphore.acquire()) {
108
- TimeUnit.MILLISECONDS.sleep(100)
109
- semaphore.release()
110
- return 1
111
- }
112
- return 0
113
- } as Callable<Integer>)
114
- }.collect { it.get() }.sum()
138
+ semaphore.acquire()? 1 : 0
139
+ }.collect { it }.sum()
115
140
116
141
then:
117
142
acquired == threads
118
143
semaphore.available() == Integer.MAX_VALUE
144
+
145
+ when:
146
+ int availableAfterRelease = semaphore.release()
147
+
148
+ then:
149
+ availableAfterRelease == Integer.MAX_VALUE
150
+ semaphore.available() == Integer.MAX_VALUE
151
+
152
+ when:
153
+ semaphore.reset()
154
+
155
+ then:
156
+ semaphore.available() == Integer.MAX_VALUE
157
+ }
158
+
159
+ void ' cannot create a semaphore without at least 1 permit' () {
160
+ when:
161
+ NonBlockingSemaphore.withPermitCount(0)
162
+
163
+ then:
164
+ thrown(AssertionError)
165
+
166
+ when:
167
+ NonBlockingSemaphore.withPermitCount(-1)
168
+
169
+ then:
170
+ thrown(AssertionError)
119
171
}
120
172
}
0 commit comments