Skip to content

Commit 77840bf

Browse files
committed
Add tests
1 parent 42c6f9a commit 77840bf

File tree

1 file changed

+155
-0
lines changed

1 file changed

+155
-0
lines changed

dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/api/security/ApiSecuritySamplerTest.groovy

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,161 @@ class ApiSecuritySamplerTest extends DDSpecification {
209209
}
210210
}
211211

212+
void 'preSampleRequest with tracing disabled updates access map immediately'() {
213+
given:
214+
injectSysConfig('dd.apm.tracing.enabled', 'false')
215+
rebuildConfig()
216+
def ctx = createContext('route1', 'GET', 200)
217+
final timeSource = new ControllableTimeSource()
218+
timeSource.set(0)
219+
final long expirationTimeInMs = 10_000
220+
def sampler = new ApiSecuritySamplerImpl(10, expirationTimeInMs, timeSource)
221+
222+
when: 'first request is presampled with tracing disabled'
223+
def preSampled = sampler.preSampleRequest(ctx)
224+
225+
then: 'request is sampled and access map is updated immediately'
226+
preSampled
227+
sampler.accessMap.size() == 1
228+
sampler.accessMap.containsKey(ctx.getApiSecurityEndpointHash())
229+
230+
when: 'second request for same endpoint is attempted'
231+
def ctx2 = createContext('route1', 'GET', 200)
232+
sampler.releaseOne()
233+
def preSampled2 = sampler.preSampleRequest(ctx2)
234+
235+
then: 'second request is not sampled because endpoint was already updated in first preSampleRequest'
236+
!preSampled2
237+
}
238+
239+
void 'sampleRequest with tracing disabled returns true without updating access map'() {
240+
given:
241+
injectSysConfig('dd.apm.tracing.enabled', 'false')
242+
rebuildConfig()
243+
def ctx = createContext('route1', 'GET', 200)
244+
ctx.setApiSecurityEndpointHash(42L)
245+
ctx.setKeepOpenForApiSecurityPostProcessing(true)
246+
final timeSource = new ControllableTimeSource()
247+
timeSource.set(0)
248+
final long expirationTimeInMs = 10_000
249+
def sampler = new ApiSecuritySamplerImpl(10, expirationTimeInMs, timeSource)
250+
251+
when: 'sampleRequest is called with tracing disabled'
252+
def sampled = sampler.sampleRequest(ctx)
253+
254+
then: 'request is sampled without updating access map'
255+
sampled
256+
sampler.accessMap.size() == 0
257+
}
258+
259+
void 'preSampleRequest with tracing enabled does not update access map immediately'() {
260+
given:
261+
injectSysConfig('dd.apm.tracing.enabled', 'true')
262+
rebuildConfig()
263+
def ctx = createContext('route1', 'GET', 200)
264+
final timeSource = new ControllableTimeSource()
265+
timeSource.set(0)
266+
final long expirationTimeInMs = 10_000
267+
def sampler = new ApiSecuritySamplerImpl(10, expirationTimeInMs, timeSource)
268+
269+
when: 'request is presampled with tracing enabled'
270+
def preSampled = sampler.preSampleRequest(ctx)
271+
272+
then: 'request is sampled but access map is NOT updated yet'
273+
preSampled
274+
sampler.accessMap.size() == 0
275+
276+
when: 'sampleRequest is called to finalize sampling'
277+
def sampled = sampler.sampleRequest(ctx)
278+
279+
then: 'access map is updated in sampleRequest'
280+
sampled
281+
sampler.accessMap.size() == 1
282+
sampler.accessMap.containsKey(ctx.getApiSecurityEndpointHash())
283+
}
284+
285+
void 'sampleRequest with tracing enabled updates access map'() {
286+
given:
287+
injectSysConfig('dd.apm.tracing.enabled', 'true')
288+
rebuildConfig()
289+
def ctx = createContext('route1', 'GET', 200)
290+
ctx.setApiSecurityEndpointHash(42L)
291+
ctx.setKeepOpenForApiSecurityPostProcessing(true)
292+
final timeSource = new ControllableTimeSource()
293+
timeSource.set(0)
294+
final long expirationTimeInMs = 10_000
295+
def sampler = new ApiSecuritySamplerImpl(10, expirationTimeInMs, timeSource)
296+
297+
when: 'sampleRequest is called with tracing enabled'
298+
def sampled = sampler.sampleRequest(ctx)
299+
300+
then: 'request is sampled and access map is updated'
301+
sampled
302+
sampler.accessMap.size() == 1
303+
sampler.accessMap.containsKey(42L)
304+
305+
when: 'second request for same endpoint is made'
306+
def sampled2 = sampler.sampleRequest(ctx)
307+
308+
then: 'second request is not sampled'
309+
!sampled2
310+
}
311+
312+
void 'concurrent requests with tracing disabled do not see expired state'() {
313+
given:
314+
injectSysConfig('dd.apm.tracing.enabled', 'false')
315+
rebuildConfig()
316+
def ctx1 = createContext('route1', 'GET', 200)
317+
def ctx2 = createContext('route1', 'GET', 200)
318+
final timeSource = new ControllableTimeSource()
319+
timeSource.set(0)
320+
final long expirationTimeInMs = 10_000
321+
def sampler = new ApiSecuritySamplerImpl(10, expirationTimeInMs, timeSource)
322+
323+
when: 'first request is presampled'
324+
def preSampled1 = sampler.preSampleRequest(ctx1)
325+
326+
then: 'first request is sampled and access map is updated immediately'
327+
preSampled1
328+
ctx1.getApiSecurityEndpointHash() != null
329+
sampler.accessMap.size() == 1
330+
331+
when: 'concurrent second request tries to presample same endpoint'
332+
sampler.releaseOne()
333+
def preSampled2 = sampler.preSampleRequest(ctx2)
334+
335+
then: 'second request is not sampled because endpoint is already in access map'
336+
!preSampled2
337+
}
338+
339+
void 'full flow with tracing disabled updates map only in preSampleRequest'() {
340+
given:
341+
injectSysConfig('dd.apm.tracing.enabled', 'false')
342+
rebuildConfig()
343+
def ctx = createContext('route1', 'GET', 200)
344+
final timeSource = new ControllableTimeSource()
345+
timeSource.set(0)
346+
final long expirationTimeInMs = 10_000
347+
def sampler = new ApiSecuritySamplerImpl(10, expirationTimeInMs, timeSource)
348+
349+
when: 'request goes through full sampling flow with tracing disabled'
350+
def preSampled = sampler.preSampleRequest(ctx)
351+
352+
then: 'preSampleRequest returns true and updates access map'
353+
preSampled
354+
sampler.accessMap.size() == 1
355+
def hash = ctx.getApiSecurityEndpointHash()
356+
sampler.accessMap.containsKey(hash)
357+
358+
when: 'sampleRequest is called'
359+
def sampled = sampler.sampleRequest(ctx)
360+
361+
then: 'sampleRequest returns true without modifying access map'
362+
sampled
363+
sampler.accessMap.size() == 1
364+
sampler.accessMap.get(hash) == 0L // Still has the value from preSampleRequest
365+
}
366+
212367
private static AppSecRequestContext createContext(final String route, final String method, int statusCode) {
213368
final AppSecRequestContext ctx = new AppSecRequestContext()
214369
ctx.setRoute(route)

0 commit comments

Comments
 (0)