@@ -244,6 +244,10 @@ pub enum CliCommand {
244244 /// Required cached-object HTTP status. May be repeated.
245245 #[ arg( long = "expect-status" , value_name = "STATUS" ) ]
246246 expect_statuses : Vec < u16 > ,
247+
248+ /// Required cached-object storage tier. May be repeated: memory, disk.
249+ #[ arg( long = "expect-tier" , value_name = "TIER" ) ]
250+ expect_tiers : Vec < String > ,
247251 } ,
248252}
249253
@@ -472,6 +476,7 @@ fn run_command(
472476 require_object,
473477 expect_freshness_states,
474478 expect_statuses,
479+ expect_tiers,
475480 } => run_cache_lookup_command ( CacheLookupOptions {
476481 config_path,
477482 host : host. clone ( ) ,
@@ -482,6 +487,7 @@ fn run_command(
482487 require_object : * require_object,
483488 expect_freshness_states : expect_freshness_states. clone ( ) ,
484489 expect_statuses : expect_statuses. clone ( ) ,
490+ expect_tiers : expect_tiers. clone ( ) ,
485491 } ) ,
486492 }
487493}
@@ -526,6 +532,7 @@ struct CacheLookupOptions<'a> {
526532 require_object : bool ,
527533 expect_freshness_states : Vec < String > ,
528534 expect_statuses : Vec < u16 > ,
535+ expect_tiers : Vec < String > ,
529536}
530537
531538#[ cfg( feature = "cache" ) ]
@@ -850,6 +857,7 @@ fn run_cache_lookup_command(
850857 } ;
851858 let require_object = options. require_object ;
852859 let expected_states = parse_cache_lookup_freshness_states ( & options. expect_freshness_states ) ?;
860+ let expected_tiers = parse_cache_lookup_tiers ( & options. expect_tiers ) ?;
853861 validate_cache_lookup_expected_statuses ( & options. expect_statuses ) ?;
854862 let ( config, request) = cache_key_command_request ( & cache_key_options) ?;
855863 let proxy = crate :: proxy:: FluxProxy :: from_config ( & config) ?;
@@ -861,6 +869,7 @@ fn run_cache_lookup_command(
861869 require_object,
862870 & expected_states,
863871 & options. expect_statuses ,
872+ & expected_tiers,
864873 ) ?;
865874
866875 println ! ( "cache object lookup:" ) ;
@@ -940,12 +949,30 @@ fn parse_cache_lookup_freshness_states(
940949 . collect ( )
941950}
942951
952+ #[ cfg( all( feature = "cache" , feature = "proxy" ) ) ]
953+ fn parse_cache_lookup_tiers (
954+ tiers : & [ String ] ,
955+ ) -> Result < Vec < crate :: cache:: CacheObjectTier > , Box < dyn Error + Send + Sync > > {
956+ tiers
957+ . iter ( )
958+ . map ( |tier| match tier. as_str ( ) {
959+ "memory" => Ok ( crate :: cache:: CacheObjectTier :: Memory ) ,
960+ "disk" => Ok ( crate :: cache:: CacheObjectTier :: Disk ) ,
961+ other => Err ( format ! (
962+ "cache-lookup --expect-tier must be memory or disk; got {other:?}"
963+ )
964+ . into ( ) ) ,
965+ } )
966+ . collect ( )
967+ }
968+
943969#[ cfg( all( feature = "cache" , feature = "proxy" ) ) ]
944970fn validate_cache_lookup_expectations (
945971 lookup : & crate :: proxy:: CacheObjectLookup ,
946972 require_object : bool ,
947973 expected_states : & [ crate :: cache:: CacheObjectFreshnessState ] ,
948974 expected_statuses : & [ u16 ] ,
975+ expected_tiers : & [ crate :: cache:: CacheObjectTier ] ,
949976) -> Result < ( ) , Box < dyn Error + Send + Sync > > {
950977 if require_object && lookup. objects . is_empty ( ) {
951978 return Err ( "cache-lookup expected at least one cached object, found none" . into ( ) ) ;
@@ -1000,6 +1027,30 @@ fn validate_cache_lookup_expectations(
10001027 return Err ( format ! ( "cache-lookup expected status {expected}, found {found}" ) . into ( ) ) ;
10011028 }
10021029 }
1030+ if !expected_tiers. is_empty ( ) {
1031+ let matched = lookup
1032+ . objects
1033+ . iter ( )
1034+ . any ( |object| expected_tiers. contains ( & object. tier ) ) ;
1035+ if !matched {
1036+ let expected = expected_tiers
1037+ . iter ( )
1038+ . map ( |tier| tier. as_str ( ) )
1039+ . collect :: < Vec < _ > > ( )
1040+ . join ( "," ) ;
1041+ let found = if lookup. objects . is_empty ( ) {
1042+ "none" . to_owned ( )
1043+ } else {
1044+ lookup
1045+ . objects
1046+ . iter ( )
1047+ . map ( |object| object. tier . as_str ( ) )
1048+ . collect :: < Vec < _ > > ( )
1049+ . join ( "," )
1050+ } ;
1051+ return Err ( format ! ( "cache-lookup expected tier {expected}, found {found}" ) . into ( ) ) ;
1052+ }
1053+ }
10031054 Ok ( ( ) )
10041055}
10051056
@@ -1046,9 +1097,15 @@ fn run_cache_lookup_command(
10461097 require_object,
10471098 expect_freshness_states,
10481099 expect_statuses,
1100+ expect_tiers,
10491101 } = options;
10501102 let _ = ( config_path, host, headers, method, path, query) ;
1051- let _ = ( require_object, expect_freshness_states, expect_statuses) ;
1103+ let _ = (
1104+ require_object,
1105+ expect_freshness_states,
1106+ expect_statuses,
1107+ expect_tiers,
1108+ ) ;
10521109 Err ( "cache-lookup requires the proxy and cache features" . into ( ) )
10531110}
10541111
@@ -2725,37 +2782,61 @@ mod tests {
27252782 fn cache_lookup_expectations_validate_object_and_freshness_state ( ) {
27262783 let lookup = cache_lookup_with_state ( crate :: cache:: CacheObjectFreshnessState :: Stale ) ;
27272784 let states = super :: parse_cache_lookup_freshness_states ( & [ "stale" . to_owned ( ) ] ) . unwrap ( ) ;
2785+ let tiers = super :: parse_cache_lookup_tiers ( & [ "memory" . to_owned ( ) ] ) . unwrap ( ) ;
27282786
2729- assert ! ( super :: validate_cache_lookup_expectations( & lookup, true , & states, & [ 200 ] ) . is_ok( ) ) ;
2787+ assert ! (
2788+ super :: validate_cache_lookup_expectations( & lookup, true , & states, & [ 200 ] , & tiers)
2789+ . is_ok( )
2790+ ) ;
27302791 assert ! (
27312792 super :: validate_cache_lookup_expectations(
27322793 & lookup,
27332794 false ,
27342795 & [ crate :: cache:: CacheObjectFreshnessState :: Fresh ] ,
2796+ & [ ] ,
27352797 & [ ]
27362798 )
27372799 . unwrap_err( )
27382800 . to_string( )
27392801 . contains( "expected freshness state fresh, found stale" )
27402802 ) ;
27412803 assert ! (
2742- super :: validate_cache_lookup_expectations( & lookup, false , & [ ] , & [ 404 ] )
2804+ super :: validate_cache_lookup_expectations( & lookup, false , & [ ] , & [ 404 ] , & [ ] )
27432805 . unwrap_err( )
27442806 . to_string( )
27452807 . contains( "expected status 404, found 200" )
27462808 ) ;
2809+ assert ! (
2810+ super :: validate_cache_lookup_expectations(
2811+ & lookup,
2812+ false ,
2813+ & [ ] ,
2814+ & [ ] ,
2815+ & [ crate :: cache:: CacheObjectTier :: Disk ]
2816+ )
2817+ . unwrap_err( )
2818+ . to_string( )
2819+ . contains( "expected tier disk, found memory" )
2820+ ) ;
27472821 assert ! (
27482822 super :: parse_cache_lookup_freshness_states( & [ "invalid" . to_owned( ) ] )
27492823 . unwrap_err( )
27502824 . to_string( )
27512825 . contains( "fresh, stale, or expired" )
27522826 ) ;
2827+ assert ! (
2828+ super :: parse_cache_lookup_tiers( & [ "invalid" . to_owned( ) ] )
2829+ . unwrap_err( )
2830+ . to_string( )
2831+ . contains( "memory or disk" )
2832+ ) ;
27532833 assert ! ( super :: validate_cache_lookup_expected_statuses( & [ 99 ] ) . is_err( ) ) ;
27542834 assert ! (
27552835 super :: validate_cache_lookup_expectations(
27562836 & cache_lookup_without_objects( ) ,
27572837 true ,
27582838 & [ ] ,
2839+ & [ ] ,
27592840 & [ ]
27602841 )
27612842 . unwrap_err( )
0 commit comments