My agentic slop goes here. Not intended for anyone else!
at jsont 12 kB view raw
1open Cookeio 2 3let cookie_testable : Cookeio.t Alcotest.testable = 4 Alcotest.testable 5 (fun ppf c -> 6 Format.fprintf ppf 7 "{ name=%S; value=%S; domain=%S; path=%S; secure=%b; http_only=%b; \ 8 expires=%a; same_site=%a }" 9 (Cookeio.name c) (Cookeio.value c) (Cookeio.domain c) (Cookeio.path c) (Cookeio.secure c) (Cookeio.http_only c) 10 (Format.pp_print_option Ptime.pp) 11 (Cookeio.expires c) 12 (Format.pp_print_option (fun ppf -> function 13 | `Strict -> Format.pp_print_string ppf "Strict" 14 | `Lax -> Format.pp_print_string ppf "Lax" 15 | `None -> Format.pp_print_string ppf "None")) 16 (Cookeio.same_site c)) 17 (fun c1 c2 -> 18 Cookeio.name c1 = Cookeio.name c2 && Cookeio.value c1 = Cookeio.value c2 && Cookeio.domain c1 = Cookeio.domain c2 19 && Cookeio.path c1 = Cookeio.path c2 && Cookeio.secure c1 = Cookeio.secure c2 20 && Cookeio.http_only c1 = Cookeio.http_only c2 21 && Option.equal Ptime.equal (Cookeio.expires c1) (Cookeio.expires c2) 22 && Option.equal ( = ) (Cookeio.same_site c1) (Cookeio.same_site c2)) 23 24let test_load_mozilla_cookies () = 25 let content = 26 {|# Netscape HTTP Cookie File 27# http://curl.haxx.se/rfc/cookie_spec.html 28# This is a generated file! Do not edit. 29 30example.com FALSE /foo/ FALSE 0 cookie-1 v$1 31.example.com TRUE /foo/ FALSE 0 cookie-2 v$2 32example.com FALSE /foo/ FALSE 1257894000 cookie-3 v$3 33example.com FALSE /foo/ FALSE 1257894000 cookie-4 v$4 34example.com FALSE /foo/ TRUE 1257894000 cookie-5 v$5 35#HttpOnly_example.com FALSE /foo/ FALSE 1257894000 cookie-6 v$6 36#HttpOnly_.example.com TRUE /foo/ FALSE 1257894000 cookie-7 v$7 37|} 38 in 39 let jar = from_mozilla_format content in 40 let cookies = get_all_cookies jar in 41 42 (* Check total number of cookies (should skip commented lines) *) 43 Alcotest.(check int) "cookie count" 5 (List.length cookies); 44 Alcotest.(check int) "count function" 5 (count jar); 45 Alcotest.(check bool) "not empty" false (is_empty jar); 46 47 let find_cookie name = List.find (fun c -> Cookeio.name c = name) cookies in 48 49 (* Test cookie-1: session cookie on exact domain *) 50 let cookie1 = find_cookie "cookie-1" in 51 Alcotest.(check string) "cookie-1 domain" "example.com" (Cookeio.domain cookie1); 52 Alcotest.(check string) "cookie-1 path" "/foo/" (Cookeio.path cookie1); 53 Alcotest.(check string) "cookie-1 name" "cookie-1" (Cookeio.name cookie1); 54 Alcotest.(check string) "cookie-1 value" "v$1" (Cookeio.value cookie1); 55 Alcotest.(check bool) "cookie-1 secure" false (Cookeio.secure cookie1); 56 Alcotest.(check bool) "cookie-1 http_only" false (Cookeio.http_only cookie1); 57 Alcotest.(check (option (Alcotest.testable Ptime.pp Ptime.equal))) 58 "cookie-1 expires" None (Cookeio.expires cookie1); 59 Alcotest.( 60 check 61 (option 62 (Alcotest.testable 63 (fun ppf -> function 64 | `Strict -> Format.pp_print_string ppf "Strict" 65 | `Lax -> Format.pp_print_string ppf "Lax" 66 | `None -> Format.pp_print_string ppf "None") 67 ( = )))) 68 "cookie-1 same_site" None (Cookeio.same_site cookie1); 69 70 (* Test cookie-2: session cookie on subdomain pattern *) 71 let cookie2 = find_cookie "cookie-2" in 72 Alcotest.(check string) "cookie-2 domain" ".example.com" (Cookeio.domain cookie2); 73 Alcotest.(check string) "cookie-2 path" "/foo/" (Cookeio.path cookie2); 74 Alcotest.(check string) "cookie-2 name" "cookie-2" (Cookeio.name cookie2); 75 Alcotest.(check string) "cookie-2 value" "v$2" (Cookeio.value cookie2); 76 Alcotest.(check bool) "cookie-2 secure" false (Cookeio.secure cookie2); 77 Alcotest.(check bool) "cookie-2 http_only" false (Cookeio.http_only cookie2); 78 Alcotest.(check (option (Alcotest.testable Ptime.pp Ptime.equal))) 79 "cookie-2 expires" None (Cookeio.expires cookie2); 80 81 (* Test cookie-3: non-session cookie with expiry *) 82 let cookie3 = find_cookie "cookie-3" in 83 let expected_expiry = Ptime.of_float_s 1257894000.0 in 84 Alcotest.(check string) "cookie-3 domain" "example.com" (Cookeio.domain cookie3); 85 Alcotest.(check string) "cookie-3 path" "/foo/" (Cookeio.path cookie3); 86 Alcotest.(check string) "cookie-3 name" "cookie-3" (Cookeio.name cookie3); 87 Alcotest.(check string) "cookie-3 value" "v$3" (Cookeio.value cookie3); 88 Alcotest.(check bool) "cookie-3 secure" false (Cookeio.secure cookie3); 89 Alcotest.(check bool) "cookie-3 http_only" false (Cookeio.http_only cookie3); 90 Alcotest.(check (option (Alcotest.testable Ptime.pp Ptime.equal))) 91 "cookie-3 expires" expected_expiry (Cookeio.expires cookie3); 92 93 (* Test cookie-4: another non-session cookie *) 94 let cookie4 = find_cookie "cookie-4" in 95 Alcotest.(check string) "cookie-4 domain" "example.com" (Cookeio.domain cookie4); 96 Alcotest.(check string) "cookie-4 path" "/foo/" (Cookeio.path cookie4); 97 Alcotest.(check string) "cookie-4 name" "cookie-4" (Cookeio.name cookie4); 98 Alcotest.(check string) "cookie-4 value" "v$4" (Cookeio.value cookie4); 99 Alcotest.(check bool) "cookie-4 secure" false (Cookeio.secure cookie4); 100 Alcotest.(check bool) "cookie-4 http_only" false (Cookeio.http_only cookie4); 101 Alcotest.(check (option (Alcotest.testable Ptime.pp Ptime.equal))) 102 "cookie-4 expires" expected_expiry (Cookeio.expires cookie4); 103 104 (* Test cookie-5: secure cookie *) 105 let cookie5 = find_cookie "cookie-5" in 106 Alcotest.(check string) "cookie-5 domain" "example.com" (Cookeio.domain cookie5); 107 Alcotest.(check string) "cookie-5 path" "/foo/" (Cookeio.path cookie5); 108 Alcotest.(check string) "cookie-5 name" "cookie-5" (Cookeio.name cookie5); 109 Alcotest.(check string) "cookie-5 value" "v$5" (Cookeio.value cookie5); 110 Alcotest.(check bool) "cookie-5 secure" true (Cookeio.secure cookie5); 111 Alcotest.(check bool) "cookie-5 http_only" false (Cookeio.http_only cookie5); 112 Alcotest.(check (option (Alcotest.testable Ptime.pp Ptime.equal))) 113 "cookie-5 expires" expected_expiry (Cookeio.expires cookie5) 114 115let test_load_from_file env = 116 (* This test loads from the actual test/cookies.txt file using the load function *) 117 let cwd = Eio.Stdenv.cwd env in 118 let cookie_path = Eio.Path.(cwd / "cookies.txt") in 119 let jar = load cookie_path in 120 let cookies = get_all_cookies jar in 121 122 (* Should have the same 5 cookies as the string test *) 123 Alcotest.(check int) "file load cookie count" 5 (List.length cookies); 124 125 let find_cookie name = List.find (fun c -> Cookeio.name c = name) cookies in 126 127 (* Verify a few key cookies are loaded correctly *) 128 let cookie1 = find_cookie "cookie-1" in 129 Alcotest.(check string) "file cookie-1 value" "v$1" (Cookeio.value cookie1); 130 Alcotest.(check string) "file cookie-1 domain" "example.com" (Cookeio.domain cookie1); 131 Alcotest.(check bool) "file cookie-1 secure" false (Cookeio.secure cookie1); 132 Alcotest.(check (option (Alcotest.testable Ptime.pp Ptime.equal))) 133 "file cookie-1 expires" None (Cookeio.expires cookie1); 134 135 let cookie5 = find_cookie "cookie-5" in 136 Alcotest.(check string) "file cookie-5 value" "v$5" (Cookeio.value cookie5); 137 Alcotest.(check bool) "file cookie-5 secure" true (Cookeio.secure cookie5); 138 let expected_expiry = Ptime.of_float_s 1257894000.0 in 139 Alcotest.(check (option (Alcotest.testable Ptime.pp Ptime.equal))) 140 "file cookie-5 expires" expected_expiry (Cookeio.expires cookie5); 141 142 (* Verify subdomain cookie *) 143 let cookie2 = find_cookie "cookie-2" in 144 Alcotest.(check string) "file cookie-2 domain" ".example.com" (Cookeio.domain cookie2); 145 Alcotest.(check (option (Alcotest.testable Ptime.pp Ptime.equal))) 146 "file cookie-2 expires" None (Cookeio.expires cookie2) 147 148let test_cookie_matching () = 149 let jar = create () in 150 151 (* Add test cookies with different domain patterns *) 152 let exact_cookie = 153 Cookeio.make ~domain:"example.com" ~path:"/" ~name:"exact" ~value:"test1" 154 ~secure:false ~http_only:false ?expires:None ?same_site:None 155 ~creation_time:Ptime.epoch ~last_access:Ptime.epoch () 156 in 157 let subdomain_cookie = 158 Cookeio.make ~domain:".example.com" ~path:"/" ~name:"subdomain" ~value:"test2" 159 ~secure:false ~http_only:false ?expires:None ?same_site:None 160 ~creation_time:Ptime.epoch ~last_access:Ptime.epoch () 161 in 162 let secure_cookie = 163 Cookeio.make ~domain:"example.com" ~path:"/" ~name:"secure" ~value:"test3" 164 ~secure:true ~http_only:false ?expires:None ?same_site:None 165 ~creation_time:Ptime.epoch ~last_access:Ptime.epoch () 166 in 167 168 add_cookie jar exact_cookie; 169 add_cookie jar subdomain_cookie; 170 add_cookie jar secure_cookie; 171 172 (* Test exact domain matching *) 173 let cookies_http = 174 get_cookies jar ~domain:"example.com" ~path:"/" ~is_secure:false 175 in 176 Alcotest.(check int) "http cookies count" 2 (List.length cookies_http); 177 178 let cookies_https = 179 get_cookies jar ~domain:"example.com" ~path:"/" ~is_secure:true 180 in 181 Alcotest.(check int) "https cookies count" 3 (List.length cookies_https); 182 183 (* Test subdomain matching *) 184 let cookies_sub = 185 get_cookies jar ~domain:"sub.example.com" ~path:"/" ~is_secure:false 186 in 187 Alcotest.(check int) "subdomain cookies count" 1 (List.length cookies_sub); 188 let sub_cookie = List.hd cookies_sub in 189 Alcotest.(check string) "subdomain cookie name" "subdomain" (Cookeio.name sub_cookie) 190 191let test_empty_jar () = 192 let jar = create () in 193 Alcotest.(check bool) "empty jar" true (is_empty jar); 194 Alcotest.(check int) "empty count" 0 (count jar); 195 Alcotest.(check (list cookie_testable)) 196 "empty cookies" [] (get_all_cookies jar); 197 198 let cookies = 199 get_cookies jar ~domain:"example.com" ~path:"/" ~is_secure:false 200 in 201 Alcotest.(check int) "no matching cookies" 0 (List.length cookies) 202 203let test_round_trip_mozilla_format () = 204 let jar = create () in 205 206 let test_cookie = 207 Cookeio.make ~domain:"example.com" ~path:"/test/" ~name:"test" ~value:"value" 208 ~secure:true ~http_only:false ?expires:(Ptime.of_float_s 1257894000.0) 209 ~same_site:`Strict ~creation_time:Ptime.epoch ~last_access:Ptime.epoch () 210 in 211 212 add_cookie jar test_cookie; 213 214 (* Convert to Mozilla format and back *) 215 let mozilla_format = to_mozilla_format jar in 216 let jar2 = from_mozilla_format mozilla_format in 217 let cookies2 = get_all_cookies jar2 in 218 219 Alcotest.(check int) "round trip count" 1 (List.length cookies2); 220 let cookie2 = List.hd cookies2 in 221 Alcotest.(check string) "round trip name" "test" (Cookeio.name cookie2); 222 Alcotest.(check string) "round trip value" "value" (Cookeio.value cookie2); 223 Alcotest.(check string) "round trip domain" "example.com" (Cookeio.domain cookie2); 224 Alcotest.(check string) "round trip path" "/test/" (Cookeio.path cookie2); 225 Alcotest.(check bool) "round trip secure" true (Cookeio.secure cookie2); 226 (* Note: http_only and same_site are lost in Mozilla format *) 227 Alcotest.(check (option (Alcotest.testable Ptime.pp Ptime.equal))) 228 "round trip expires" 229 (Ptime.of_float_s 1257894000.0) 230 (Cookeio.expires cookie2) 231 232let () = 233 Eio_main.run @@ fun env -> 234 let open Alcotest in 235 run "Cookeio Tests" 236 [ 237 ( "mozilla_format", 238 [ 239 test_case "Load Mozilla format from string" `Quick 240 test_load_mozilla_cookies; 241 test_case "Load Mozilla format from file" `Quick (fun () -> 242 test_load_from_file env); 243 test_case "Round trip Mozilla format" `Quick 244 test_round_trip_mozilla_format; 245 ] ); 246 ( "cookie_matching", 247 [ test_case "Domain and security matching" `Quick test_cookie_matching ] 248 ); 249 ( "basic_operations", 250 [ test_case "Empty jar operations" `Quick test_empty_jar ] ); 251 ]