@@ -806,6 +806,45 @@ describe(generateManifest.name, () => {
806806 } ) ;
807807 } ) ;
808808
809+ describe ( "reclamation" , ( ) => {
810+ it . each ( [
811+ [ "24h" , "86400" ] ,
812+ [ "30m" , "1800" ] ,
813+ [ "720h" , "2592000" ] ,
814+ [ "8760h" , "31536000" ] ,
815+ ] ) ( "surfaces min_window %j as a proto Duration (%s seconds)" , ( minWindow , seconds ) => {
816+ const { result } = setup ( { sdl : createBasicSdl ( { reclamation : { min_window : minWindow } } ) } ) ;
817+ expect ( result . reclamation ?. minWindow ?. seconds . toString ( ) ) . toBe ( seconds ) ;
818+ expect ( result . reclamation ?. minWindow ?. nanos ) . toBe ( 0 ) ;
819+ } ) ;
820+
821+ it ( "leaves reclamation undefined when no block is present" , ( ) => {
822+ const { result } = setup ( ) ;
823+ expect ( result . reclamation ) . toBeUndefined ( ) ;
824+ } ) ;
825+
826+ // Compound ("1h30m"), fractional ("1.5h") and sub-second ("500ms") forms are
827+ // accepted by Go's `time.ParseDuration` but rejected by the stricter SDL
828+ // schema pattern (`^[1-9][0-9]*(s|m|h)$`).
829+ it . each ( [ "abc" , "0s" , "-1h" , "100" , "1h30m" , "1.5h" , "500ms" ] ) ( "rejects an invalid min_window %j" , ( minWindow ) => {
830+ const result = generateManifest ( createBasicSdl ( { reclamation : { min_window : minWindow } } ) ) ;
831+ expect ( result . ok ) . toBe ( false ) ;
832+ if ( ! result . ok ) {
833+ expect ( result . value ) . toContainEqual ( expect . objectContaining ( {
834+ instancePath : "/reclamation/min_window" ,
835+ } ) ) ;
836+ }
837+ } ) ;
838+
839+ it ( "exposes reclamation as a lazy, memoized getter" , ( ) => {
840+ const { result } = setup ( { sdl : createBasicSdl ( { reclamation : { min_window : "24h" } } ) } ) ;
841+ // It's a getter (computed on access, not eagerly)...
842+ expect ( Object . getOwnPropertyDescriptor ( result , "reclamation" ) ?. get ) . toBeTypeOf ( "function" ) ;
843+ // ...and memoized: repeated reads return the same instance.
844+ expect ( result . reclamation ) . toBe ( result . reclamation ) ;
845+ } ) ;
846+ } ) ;
847+
809848 function setup ( input ?: {
810849 sdl : SDLInput ;
811850 } ) {
@@ -837,6 +876,7 @@ describe(generateManifest.name, () => {
837876 credentials ?: SDLInput [ "services" ] [ string ] [ "credentials" ] ;
838877 expose ?: SDLInput [ "services" ] [ string ] [ "expose" ] ;
839878 endpoints ?: SDLInput [ "endpoints" ] ;
879+ reclamation ?: SDLInput [ "reclamation" ] ;
840880 } = { } ) : SDLInput {
841881 const {
842882 port = 80 ,
@@ -880,6 +920,7 @@ describe(generateManifest.name, () => {
880920 profile: web
881921 count: 1
882922 endpoints: ${ input . endpoints }
923+ reclamation: ${ input . reclamation }
883924 ` ;
884925 }
885926
0 commit comments