A batteries included HTTP/1.1 client in OCaml
at main 249 lines 10 kB view raw
1(*--------------------------------------------------------------------------- 2 Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved. 3 SPDX-License-Identifier: ISC 4 ---------------------------------------------------------------------------*) 5 6(** Tests for Cache_control module - RFC 9111 compliance *) 7 8module Cache_control = Requests.Cache_control 9 10(** {1 Response Parsing Tests} *) 11 12let test_parse_max_age () = 13 let cc = Cache_control.parse_response "max-age=3600" in 14 Alcotest.(check (option int)) "max_age" (Some 3600) cc.max_age 15 16let test_no_cache_no_store () = 17 let cc = Cache_control.parse_response "no-cache, no-store" in 18 Alcotest.(check bool) "no_cache present" true (Option.is_some cc.no_cache); 19 Alcotest.(check bool) "no_store" true cc.no_store 20 21let test_public_max_age_immutable () = 22 let cc = Cache_control.parse_response "public, max-age=604800, immutable" in 23 Alcotest.(check bool) "public" true cc.public; 24 Alcotest.(check (option int)) "max_age" (Some 604800) cc.max_age; 25 Alcotest.(check bool) "immutable" true cc.immutable 26 27let test_parse_private_must_revalidate () = 28 let cc = Cache_control.parse_response "private, must-revalidate" in 29 Alcotest.(check bool) "private_ present" true (Option.is_some cc.private_); 30 Alcotest.(check bool) "must_revalidate" true cc.must_revalidate 31 32let test_parse_s_maxage () = 33 let cc = Cache_control.parse_response "s-maxage=600" in 34 Alcotest.(check (option int)) "s_maxage" (Some 600) cc.s_maxage 35 36let test_parse_no_transform () = 37 let cc = Cache_control.parse_response "no-transform" in 38 Alcotest.(check bool) "no_transform" true cc.no_transform 39 40let test_parse_proxy_revalidate () = 41 let cc = Cache_control.parse_response "proxy-revalidate" in 42 Alcotest.(check bool) "proxy_revalidate" true cc.proxy_revalidate 43 44let test_parse_stale_while_revalidate () = 45 let cc = Cache_control.parse_response "stale-while-revalidate=60" in 46 Alcotest.(check (option int)) 47 "stale_while_revalidate" (Some 60) cc.stale_while_revalidate 48 49let test_parse_stale_if_error () = 50 let cc = Cache_control.parse_response "stale-if-error=300" in 51 Alcotest.(check (option int)) "stale_if_error" (Some 300) cc.stale_if_error 52 53let test_parse_must_understand () = 54 let cc = Cache_control.parse_response "must-understand" in 55 Alcotest.(check bool) "must_understand" true cc.must_understand 56 57(** {1 Request Parsing Tests} *) 58 59let test_request_max_age_zero () = 60 let cc = Cache_control.parse_request "max-age=0" in 61 Alcotest.(check (option int)) "req_max_age" (Some 0) cc.req_max_age 62 63let test_request_no_cache () = 64 let cc = Cache_control.parse_request "no-cache" in 65 Alcotest.(check bool) "req_no_cache" true cc.req_no_cache 66 67let test_request_no_store () = 68 let cc = Cache_control.parse_request "no-store" in 69 Alcotest.(check bool) "req_no_store" true cc.req_no_store 70 71let test_request_no_transform () = 72 let cc = Cache_control.parse_request "no-transform" in 73 Alcotest.(check bool) "req_no_transform" true cc.req_no_transform 74 75let test_request_only_if_cached () = 76 let cc = Cache_control.parse_request "only-if-cached" in 77 Alcotest.(check bool) "req_only_if_cached" true cc.req_only_if_cached 78 79let test_request_min_fresh () = 80 let cc = Cache_control.parse_request "min-fresh=120" in 81 Alcotest.(check (option int)) "req_min_fresh" (Some 120) cc.req_min_fresh 82 83(** {1 Cacheability Tests} *) 84 85let test_cacheable_200_max_age () = 86 let cc = Cache_control.parse_response "max-age=3600" in 87 Alcotest.(check bool) 88 "cacheable 200 with max-age" true 89 (Cache_control.is_cacheable ~response_cc:cc ~status:200) 90 91let test_is_cacheable_no_store () = 92 let cc = Cache_control.parse_response "no-store" in 93 Alcotest.(check bool) 94 "not cacheable with no-store" false 95 (Cache_control.is_cacheable ~response_cc:cc ~status:200) 96 97let test_is_cacheable_default_status () = 98 let cc = Cache_control.empty_response in 99 Alcotest.(check bool) 100 "cacheable 200 default" true 101 (Cache_control.is_cacheable ~response_cc:cc ~status:200) 102 103let test_cacheable_non_default_status () = 104 let cc = Cache_control.empty_response in 105 Alcotest.(check bool) 106 "non-cacheable 500 without directives" false 107 (Cache_control.is_cacheable ~response_cc:cc ~status:500) 108 109let test_is_cacheable_301 () = 110 let cc = Cache_control.empty_response in 111 Alcotest.(check bool) 112 "cacheable 301 by default" true 113 (Cache_control.is_cacheable ~response_cc:cc ~status:301) 114 115let test_is_cacheable_404 () = 116 let cc = Cache_control.empty_response in 117 Alcotest.(check bool) 118 "cacheable 404 by default" true 119 (Cache_control.is_cacheable ~response_cc:cc ~status:404) 120 121(** {1 Predicate Tests} *) 122 123let test_must_revalidate_flag () = 124 let cc = Cache_control.parse_response "must-revalidate" in 125 Alcotest.(check bool) 126 "must_revalidate" true 127 (Cache_control.must_revalidate ~response_cc:cc) 128 129let test_revalidate_with_no_cache () = 130 let cc = Cache_control.parse_response "no-cache" in 131 Alcotest.(check bool) 132 "must_revalidate via no-cache" true 133 (Cache_control.must_revalidate ~response_cc:cc) 134 135let test_revalidate_with_proxy () = 136 let cc = Cache_control.parse_response "proxy-revalidate" in 137 Alcotest.(check bool) 138 "must_revalidate via proxy-revalidate" true 139 (Cache_control.must_revalidate ~response_cc:cc) 140 141let test_must_revalidate_false () = 142 let cc = Cache_control.parse_response "max-age=3600" in 143 Alcotest.(check bool) 144 "must_revalidate false" false 145 (Cache_control.must_revalidate ~response_cc:cc) 146 147let test_is_public () = 148 let cc = Cache_control.parse_response "public" in 149 Alcotest.(check bool) 150 "is_public" true 151 (Cache_control.is_public ~response_cc:cc) 152 153let test_is_public_false () = 154 let cc = Cache_control.parse_response "private" in 155 Alcotest.(check bool) 156 "is_public false" false 157 (Cache_control.is_public ~response_cc:cc) 158 159let test_is_private () = 160 let cc = Cache_control.parse_response "private" in 161 Alcotest.(check bool) 162 "is_private" true 163 (Cache_control.is_private ~response_cc:cc) 164 165let test_is_private_false () = 166 let cc = Cache_control.parse_response "public" in 167 Alcotest.(check bool) 168 "is_private false" false 169 (Cache_control.is_private ~response_cc:cc) 170 171(** {1 Freshness Lifetime Tests} *) 172 173let test_freshness_lifetime_max_age () = 174 let cc = Cache_control.parse_response "max-age=3600" in 175 let fl = Cache_control.freshness_lifetime ~response_cc:cc () in 176 Alcotest.(check (option int)) "freshness_lifetime from max-age" (Some 3600) fl 177 178let test_freshness_lifetime_no_directives () = 179 let cc = Cache_control.empty_response in 180 let fl = Cache_control.freshness_lifetime ~response_cc:cc () in 181 Alcotest.(check (option int)) "freshness_lifetime none" None fl 182 183(** {1 Empty Values Tests} *) 184 185let test_empty_response () = 186 let cc = Cache_control.empty_response in 187 Alcotest.(check (option int)) "max_age" None cc.max_age; 188 Alcotest.(check (option int)) "s_maxage" None cc.s_maxage; 189 Alcotest.(check bool) "no_store" false cc.no_store; 190 Alcotest.(check bool) "must_revalidate" false cc.must_revalidate; 191 Alcotest.(check bool) "public" false cc.public; 192 Alcotest.(check bool) "immutable" false cc.immutable 193 194let test_empty_request () = 195 let cc = Cache_control.empty_request in 196 Alcotest.(check (option int)) "req_max_age" None cc.req_max_age; 197 Alcotest.(check bool) "req_no_cache" false cc.req_no_cache; 198 Alcotest.(check bool) "req_no_store" false cc.req_no_store 199 200(** {1 Test Suite} *) 201 202let suite = 203 ( "cache_control", 204 [ 205 Alcotest.test_case "max-age=3600" `Quick test_parse_max_age; 206 Alcotest.test_case "no-cache, no-store" `Quick test_no_cache_no_store; 207 Alcotest.test_case "public, max-age, immutable" `Quick 208 test_public_max_age_immutable; 209 Alcotest.test_case "private, must-revalidate" `Quick 210 test_parse_private_must_revalidate; 211 Alcotest.test_case "s-maxage=600" `Quick test_parse_s_maxage; 212 Alcotest.test_case "no-transform" `Quick test_parse_no_transform; 213 Alcotest.test_case "proxy-revalidate" `Quick test_parse_proxy_revalidate; 214 Alcotest.test_case "stale-while-revalidate" `Quick 215 test_parse_stale_while_revalidate; 216 Alcotest.test_case "stale-if-error" `Quick test_parse_stale_if_error; 217 Alcotest.test_case "must-understand" `Quick test_parse_must_understand; 218 Alcotest.test_case "max-age=0" `Quick test_request_max_age_zero; 219 Alcotest.test_case "no-cache" `Quick test_request_no_cache; 220 Alcotest.test_case "no-store" `Quick test_request_no_store; 221 Alcotest.test_case "no-transform" `Quick test_request_no_transform; 222 Alcotest.test_case "only-if-cached" `Quick test_request_only_if_cached; 223 Alcotest.test_case "min-fresh=120" `Quick test_request_min_fresh; 224 Alcotest.test_case "200 with max-age" `Quick test_cacheable_200_max_age; 225 Alcotest.test_case "no-store not cacheable" `Quick 226 test_is_cacheable_no_store; 227 Alcotest.test_case "200 default status" `Quick 228 test_is_cacheable_default_status; 229 Alcotest.test_case "500 non-default" `Quick 230 test_cacheable_non_default_status; 231 Alcotest.test_case "301 cacheable by default" `Quick test_is_cacheable_301; 232 Alcotest.test_case "404 cacheable by default" `Quick test_is_cacheable_404; 233 Alcotest.test_case "must-revalidate" `Quick test_must_revalidate_flag; 234 Alcotest.test_case "must-revalidate via no-cache" `Quick 235 test_revalidate_with_no_cache; 236 Alcotest.test_case "must-revalidate via proxy-revalidate" `Quick 237 test_revalidate_with_proxy; 238 Alcotest.test_case "must-revalidate false" `Quick 239 test_must_revalidate_false; 240 Alcotest.test_case "is_public" `Quick test_is_public; 241 Alcotest.test_case "is_public false" `Quick test_is_public_false; 242 Alcotest.test_case "is_private" `Quick test_is_private; 243 Alcotest.test_case "is_private false" `Quick test_is_private_false; 244 Alcotest.test_case "from max-age" `Quick test_freshness_lifetime_max_age; 245 Alcotest.test_case "no directives" `Quick 246 test_freshness_lifetime_no_directives; 247 Alcotest.test_case "empty_response" `Quick test_empty_response; 248 Alcotest.test_case "empty_request" `Quick test_empty_request; 249 ] )