@@ -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