11package  com.datadog.iast.util 
22
3- import   datadog.trace.test.util.DDSpecification 
3+ 
44import  groovy.transform.CompileDynamic 
5+ import  spock.lang.Specification 
56
67import  java.util.concurrent.Callable 
78import  java.util.concurrent.CountDownLatch 
89import  java.util.concurrent.Executors 
910import  java.util.concurrent.TimeUnit 
1011
1112@CompileDynamic 
12- class  NonBlockingSemaphoreTest  extends  DDSpecification  {
13+ class  NonBlockingSemaphoreTest  extends  Specification  {
1314
1415  void  'test that the semaphore controls access to a shared resource  (#permitCount )' (final int permitCount) {
1516    given: 
@@ -71,6 +72,40 @@ class NonBlockingSemaphoreTest extends DDSpecification {
7172    2           | _ 
7273  } 
7374
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+ 
74109  void '  reset helps recover when there is starvation (#permitCount)' (final int permitCount) {
75110    given: 
76111    final semaphore = NonBlockingSemaphore.withPermitCount(permitCount) 
@@ -97,24 +132,41 @@ class NonBlockingSemaphoreTest extends DDSpecification {
97132    given: 
98133    final int threads = 100 
99134    final semaphore = NonBlockingSemaphore.unlimited() 
100-     final latch = new CountDownLatch(threads) 
101-     final executors = Executors.newFixedThreadPool(threads) 
102135
103136    when: 
104137    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() 
115140
116141    then: 
117142    acquired == threads 
118143    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) 
119171  } 
120172} 
0 commit comments