lean4-htt/tests/lean/Uri.lean
Markus Himmel fa5d08b7de
refactor: use String.Slice in String.take and variants (#11180)
This PR redefines `String.take` and variants to operate on
`String.Slice`. While previously functions returning a substring of the
input sometimes returned `String` and sometimes returned
`Substring.Raw`, they now uniformly return `String.Slice`.

This is a BREAKING change, because many functions now have a different
return type. So for example, if `s` is a string and `f` is a function
accepting a string, `f (s.drop 1)` will no longer compile because
`s.drop 1` is a `String.Slice`. To fix this, insert a call to `copy` to
restore the old behavior: `f (s.drop 1).copy`.

Of course, in many cases, there will be more efficient options. For
example, don't write `f <| s.drop 1 |>.copy |>.dropEnd 1 |>.copy`, write
`f <| s.drop 1 |>.dropEnd 1 |>.copy` instead. Also, instead of `(s.drop
1).copy = "Hello"`, write `s.drop 1 == "Hello".toSlice` instead.
2025-11-18 16:13:48 +00:00

147 lines
4.3 KiB
Text

open Lean
open System.Uri
------------------------------------------------------------------------------
-- see https://github.com/python/cpython/blob/main/Lib/test/test_urllib.py
def testEscaping :=
/- Uri character escaping includes UTF-8 encoding for the 😵 char! -/
assert! (pathToUri "/temp/test.xml?😵=2022") == "file:///temp/test.xml%3F%F0%9F%98%B5%3D2022"
/- tilde is NOT escaped -/
assert! (pathToUri "~/git/lean4") == "file:///~/git/lean4"
true
def testNeverEscape :=
let do_not_quote := String.join ["ABCDEFGHIJKLMNOPQRSTUVWXYZ",
"abcdefghijklmnopqrstuvwxyz",
"0123456789",
"_.-~<>\"{}|\\^`"]
let result := escapeUri do_not_quote
assert! result == do_not_quote
true
def testShouldEscape :=
let controls := String.mk ((List.range 31).map (fun c => Char.ofNat c))
let should_quote := String.join [controls,
"#%[]",
(Char.ofNat 127).toString] -- for 0x7F
assert! should_quote.data.all (λ c =>
let x := (escapeUri c.toString)
x.length == 3 && x.take 1 == "%".toSlice)
true
def testPartialEscape :=
assert! (escapeUri "ab[]cd") == "ab%5B%5Dcd"
true
def testSpaceEscape :=
assert! (escapeUri " ") == "%20"
true
def testUnicodeEscape :=
assert! (escapeUri "😵") == "%F0%9F%98%B5"
assert! (escapeUri "\u6f22\u5b57") == "%E6%BC%A2%E5%AD%97"
true
def testRoundTrip :=
assert! (fileUriToPath? (pathToUri "/temp/test.xml?😵=2022")) == "/temp/test.xml?😵=2022"
true
def testInvalidFileUri :=
assert! (fileUriToPath? "invalid") == none
true
def testUnescapePercent :=
assert! (unescapeUri "/temp/test%25.xml") == "/temp/test%.xml"
true
def testUnescapeSinglePercent :=
assert! (unescapeUri "%") == "%"
true
def testUnescapeBadHex :=
assert! (unescapeUri "%xab") == "%xab"
assert! (unescapeUri "file://test%W9/%3Fa%3D123") == "file://test%W9/?a=123"
true
def testTruncatedEscape :=
assert! (unescapeUri "lean%4") == "lean%4"
true
def testUnescapeUnicode :=
assert! (unescapeUri "%F0%9F%98%B5") == "😵"
assert! (unescapeUri "br%C3%BCckner") == "brückner"
assert! (unescapeUri "br%C3%BCckner") == "brückner"
assert! (unescapeUri "\u6f22%C3%BC") == "\u6f22\u00fc"
true
def testUnescapeMixedCase :=
assert! (unescapeUri "\u00Ab\u006A") == "«j"
true
def testShouldUnescape :=
let controls := String.mk ((List.range 31).map (fun c => Char.ofNat c))
let should_quote := String.join [controls,
"#%[]",
(Char.ofNat 127).toString] -- for 0x7F
assert! should_quote == unescapeUri (escapeUri should_quote)
true
def testWindowsDriveLetter :=
if System.Platform.isWindows then
assert! pathToUri ("c:" / "temp") == "file:///c%3A/temp"
true
else
true
def testWindowsDriveLetterRoundTrip :=
if System.Platform.isWindows then
let x : System.FilePath := "c:" / "temp" / "test.lean"
let r := pathToUri x
let result := if r == "file:///c%3A/temp/test.lean" then
match fileUriToPath? r with
| none =>
"testWindowsDriveLetterEscaping fileUriToPath? returned none"
| some y =>
if y.normalize.toString == x.normalize.toString then
""
else
s!"testWindowsDriveLetterEscaping '{x.normalize.toString}' != '{y.normalize.toString}'"
else
s!"testWindowsDriveLetterEscaping escaped to {r}"
assert! result == ""
true
else
true
def TestUncRoundTrip :=
let results := ["file:///c:", "file:////folder/test", "file:///c:/foo/bar/spam.foo"].map (fun p =>
let result := (match fileUriToPath? p with
| some uri => unescapeUri (pathToUri uri)
| none => "fileUriToPath? failed")
if result == p then
"ok"
else
s!"mismatch {result} != {p}")
let ok := (results.all (λ c => c == "ok"))
assert! ok -- s!"the results are not as expected: {results}"
true
#eval testEscaping &&
testNeverEscape &&
testShouldEscape &&
testRoundTrip &&
testPartialEscape &&
testSpaceEscape &&
testUnicodeEscape &&
testInvalidFileUri &&
testUnescapePercent &&
testUnescapeSinglePercent &&
testUnescapeBadHex &&
testTruncatedEscape &&
testUnescapeUnicode &&
testUnescapeMixedCase &&
testShouldUnescape &&
testWindowsDriveLetterRoundTrip