1 (* Auxiliary functions for test cases
*)
5 fun check b
= if b
then "OK" else "WRONG";
6 fun check
' f
= (if f () then "OK" else "WRONG") handle _
=> "EXN";
8 fun range (from
, to
) p
=
11 (from
> to
) orelse (p from
) andalso (range (from
+1, to
) p
)
14 fun checkrange bounds
= check
o range bounds
;
16 fun tst0 s s
' = print (s ^
" \t" ^ s
' ^
"\n");
17 fun tst s b
= tst0
s (check b
);
18 fun tst
' s f
= tst0
s (check
' f
);
20 fun tstrange s bounds
= (tst s
) o range bounds
22 (* test
/unixpath
.sml
6 -- for Unix
, 1995-05-23 *)
24 val _
= print
"\nFile unixpath.sml: Testing structure Path...\n"
30 tst
' "test1a" (fn _
=> fromString
"" = {isAbs
=false, vol
= "", arcs
= []});
32 tst
' "test1b" (fn _
=> fromString
"/" = {isAbs
=true, vol
="", arcs
=[""]});
34 tst
' "test1c" (fn _
=> fromString
"//" = {isAbs
=true, vol
="", arcs
=["", ""]});
36 tst
' "test1d" (fn _
=> fromString
"a" = {isAbs
=false, vol
= "", arcs
= ["a"]});
38 tst
' "test1e" (fn _
=> fromString
"/a" = {isAbs
=true, vol
="", arcs
=["a"]});
40 tst
' "test1f" (fn _
=> fromString
"//a" = {isAbs
=true, vol
="", arcs
=["","a"]});
42 tst
' "test1g" (fn _
=> fromString
"a/" = {isAbs
=false, vol
= "", arcs
= ["a", ""]});
44 tst
' "test1h" (fn _
=> fromString
"a//" = {isAbs
=false, vol
= "", arcs
= ["a", "", ""]});
46 tst
' "test1i" (fn _
=> fromString
"a/b" = {isAbs
=false, vol
= "", arcs
= ["a", "b"]});
48 tst
' "test1j" (fn _
=> fromString
"a.b/c" = {isAbs
=false, vol
= "", arcs
= ["a.b", "c"]});
50 tst
' "test1k" (fn _
=> fromString
"a.b/c/" = {isAbs
=false, vol
= "", arcs
= ["a.b", "c", ""]});
52 tst
' "test1l" (fn _
=> fromString
"a/./c" = {isAbs
=false, vol
= "", arcs
= ["a", ".", "c"]});
54 tst
' "test1m" (fn _
=> fromString
"a/../c" = {isAbs
=false, vol
= "", arcs
= ["a", "..", "c"]});
56 tst
' "test1n" (fn _
=> fromString
"." = {isAbs
=false, vol
= "", arcs
= ["."]});
59 tst
' "test2a" (fn _
=> toString
{isAbs
=false, vol
= "", arcs
= []} = "");
61 tst
' "test2b" (fn _
=> toString
{isAbs
=true, vol
="", arcs
=[]} = "/");
63 tst
' "test2c" (fn _
=> toString
{isAbs
=true, vol
="", arcs
=["", ""]} = "//");
65 tst
' "test2d" (fn _
=> toString
{isAbs
=false, vol
= "", arcs
= ["a"]} = "a");
67 tst
' "test2e" (fn _
=> toString
{isAbs
=true, vol
="", arcs
=["a"]} = "/a");
69 tst
' "test2f" (fn _
=> toString
{isAbs
=true, vol
="", arcs
=["","a"]} = "//a");
71 tst
' "test2g" (fn _
=> toString
{isAbs
=false, vol
= "", arcs
= ["a", ""]} = "a/");
73 tst
' "test2h" (fn _
=> toString
{isAbs
=false, vol
= "", arcs
= ["a", "", ""]} = "a//");
75 tst
' "test2i" (fn _
=> toString
{isAbs
=false, vol
= "", arcs
= ["a", "b"]} = "a/b");
77 tst
' "test2j" (fn _
=> toString
{isAbs
=false, vol
= "", arcs
= ["a.b", "c"]} = "a.b/c");
79 tst
' "test2k" (fn _
=> toString
{isAbs
=false, vol
= "", arcs
= ["a.b", "c", ""]} = "a.b/c/");
81 tst
' "test2l" (fn _
=> toString
{isAbs
=false, vol
= "", arcs
= ["a", ".", "c"]} = "a/./c");
83 tst
' "test2m" (fn _
=> toString
{isAbs
=false, vol
= "", arcs
= ["a", "..", "c"]} = "a/../c");
85 tst
' "test2n" (fn _
=> toString
{isAbs
=true, vol
="", arcs
=["a", "..", "c"]} = "/a/../c");
86 val test2o
= tst0
"test2o" ((toString
{isAbs
=false, vol
= "", arcs
= ["", "a"]} seq
"WRONG")
87 handle Path
=> "OK" | _
=> "WRONG")
88 val test2p
= tst0
"test2p" ((toString
{isAbs
=true, vol
= "C:", arcs
= ["windows"]} seq
"WRONG")
89 handle Path
=> "OK" | _
=> "WRONG")
92 tst
' "test3b" (fn _
=> getVolume
"/" = "");
94 tst
' "test3c" (fn _
=> getVolume
"//" = "");
96 tst
' "test3d" (fn _
=> getVolume
"a//b/c/" = "");
98 tst
' "test3e" (fn _
=> getVolume
"./" = "");
100 tst
' "test3f" (fn _
=> getVolume
"../" = "");
102 tst
' "test3g" (fn _
=> getVolume
"" = "");
104 tst
' "test3h" (fn _
=> getVolume
"C:" = "");
107 tst
' "test4a" (fn _
=>
108 List.all isRelative
["", ".", "..", "a//"]
109 andalso not (List.exists isRelative
["/", "/a", "//"]));
111 tst
' "test4b" (fn _
=>
112 List.all isAbsolute
["/", "/a", "//", "/.", "/.."]
113 andalso not (List.exists isAbsolute
["", ".", "..", "a//"]));
116 tst
' "test5a" (fn _
=>
118 andalso getParent
"a" = "."
119 andalso getParent
"a/" = "a/.."
120 andalso getParent
"a///" = "a///.."
121 andalso getParent
"a/b" = "a"
122 andalso getParent
"a/b/" = "a/b/.."
123 andalso getParent
"/a/b" = "/a"
124 andalso getParent
"/a/b/" = "/a/b/.."
125 andalso getParent
".." = "../.."
126 andalso getParent
"." = ".."
127 andalso getParent
"../" = "../.."
128 andalso getParent
"./" = "./.."
129 andalso getParent
"" = "..");
132 tst
' "test6a" (fn _
=>
133 concat("a", "b") = "a/b"
134 andalso concat("a", "b/c") = "a/b/c"
135 andalso concat("/", "b/c") = "/b/c"
136 andalso concat("", "b/c") = "b/c"
137 andalso concat("/a", "b/c") = "/a/b/c"
138 andalso concat("a/", "b/c") = "a/b/c"
139 andalso concat("a//", "b/c") = "a//b/c"
140 andalso concat(".", "b/c") = "./b/c"
141 andalso concat("a/b", "..") = "a/b/.."
142 andalso concat("a/b", "../c") = "a/b/../c");
143 val test6b
= tst0
"test6b" ((concat ("a", "/b") seq
"WRONG")
144 handle Path
=> "OK" | _
=> "WRONG")
146 val mkAbsolute
= fn (p
, r
) => mkAbsolute
{path
= p
, relativeTo
= r
}
149 tst
' "test7a" (fn _
=>
150 mkAbsolute("/a/b", "/c/d") = "/a/b"
151 andalso mkAbsolute("/", "/c/d") = "/"
152 andalso mkAbsolute("a/b", "/c/d") = "/c/d/a/b");
153 val test7b
= tst0
"test7b" ((mkAbsolute("a", "c/d") seq
"WRONG")
154 handle Path
=> "OK" | _
=> "WRONG")
155 val test7c
= tst0
"test7c" ((mkAbsolute("/a", "c/d") seq
"WRONG")
156 handle Path
=> "OK" | _
=> "WRONG")
158 val mkRelative
= fn (p
, r
) => mkRelative
{path
= p
, relativeTo
= r
}
161 tst
' "test8a" (fn _
=>
162 mkRelative("a/b", "/c/d") = "a/b"
163 andalso mkRelative("/", "/a/b/c") = "../../.."
164 andalso mkRelative("/a/", "/a/b/c") = "../../"
165 andalso mkRelative("/a/b/", "/a/c") = "../b/"
166 andalso mkRelative("/a/b", "/a/c/") = "../b"
167 andalso mkRelative("/a/b/", "/a/c/") = "../b/"
168 andalso mkRelative("/", "/") = "."
169 andalso mkRelative("/", "/.") = "."
170 andalso mkRelative("/", "/..") = "."
171 andalso mkRelative("/", "/a") = ".."
172 andalso mkRelative("/a/b/../c", "/a/d") = "../b/../c"
173 andalso mkRelative("/a/b", "/c/d") = "../../a/b"
174 andalso mkRelative("/c/a/b", "/c/d") = "../a/b"
175 andalso mkRelative("/c/d/a/b", "/c/d") = "a/b");
176 val test8b
= tst0
"test8b" ((mkRelative("/a", "c/d") seq
"WRONG")
177 handle Path
=> "OK" | _
=> "WRONG")
178 val test8c
= tst0
"test8c" ((mkRelative("a", "c/d") seq
"WRONG")
179 handle Path
=> "OK" | _
=> "WRONG")
182 fun chkCanon (a
, b
) =
184 andalso (mkCanonical b
= b
)
185 andalso (isCanonical b
)
187 tst
' "test9a" (fn _
=>
189 andalso chkCanon(".", ".")
190 andalso chkCanon("./.", ".")
191 andalso chkCanon("/.", "/")
192 andalso chkCanon("..", "..")
193 andalso chkCanon("../..", "../..")
194 andalso chkCanon("b", "b")
195 andalso chkCanon("a/b", "a/b")
196 andalso chkCanon("/a/b", "/a/b")
197 andalso chkCanon("a/b/", "a/b")
198 andalso chkCanon("a/b//", "a/b")
199 andalso chkCanon("a/../b", "b")
200 andalso chkCanon("a/..", ".")
201 andalso chkCanon("a/.", "a")
202 andalso chkCanon("a/", "a")
203 andalso chkCanon("/a/../b/", "/b")
204 andalso chkCanon("/..", "/")
205 andalso chkCanon("/../../a/b", "/a/b")
206 andalso chkCanon("/./../../a/b", "/a/b")
207 andalso chkCanon("/./../..", "/")
208 andalso chkCanon("a/../b", "b")
209 andalso chkCanon("a/./b", "a/b")
210 andalso chkCanon("a////b", "a/b")
211 andalso chkCanon("a////b", "a/b"))
215 tst
' "test10a" (fn _
=>
216 not (isCanonical
"./."
217 orelse isCanonical
"/.."
218 orelse isCanonical
"/."
219 orelse isCanonical
"//"
220 orelse isCanonical
"a/.."
221 orelse isCanonical
"a//b"
222 orelse isCanonical
"a/."
223 orelse isCanonical
"a/b/"
224 orelse isCanonical
"a/.."))
227 tst
' "test11a" (fn _
=>
228 splitDirFile
"" = {dir
= "", file
= ""}
229 andalso splitDirFile
"." = {dir
= "", file
= "."}
230 andalso splitDirFile
".." = {dir
= "", file
= ".."}
231 andalso splitDirFile
"b" = {dir
= "", file
= "b"}
232 andalso splitDirFile
"b/" = {dir
= "b", file
= ""}
233 andalso splitDirFile
"a/b" = {dir
= "a", file
= "b"}
234 andalso splitDirFile
"/a" = {dir
= "/", file
= "a"}
235 andalso splitDirFile
"/a/b" = {dir
= "/a", file
= "b"}
236 andalso splitDirFile
"/c/a/b" = {dir
= "/c/a", file
= "b"}
237 andalso splitDirFile
"/c/a/b/" = {dir
= "/c/a/b", file
= ""}
238 andalso splitDirFile
"/c/a/b.foo.bar" = {dir
= "/c/a", file
="b.foo.bar"}
239 andalso splitDirFile
"/c/a/b.foo" = {dir
= "/c/a", file
= "b.foo"});
242 val test11b
= (splitDirFile
"" seq
"WRONG")
243 handle Path
=> "OK" | _
=> "WRONG";
247 tst
' "test12" (fn _
=>
248 List.all (fn (res
, dir
, file
) =>
249 res
= joinDirFile
{dir
= dir
, file
= file
})
256 ("/c/a/b", "/c/a", "b"),
257 ("/c/a/b/", "/c/a/b", ""),
258 ("/c/a/b.foo.bar", "/c/a","b.foo.bar"),
259 ("/c/a/b.foo", "/c/a", "b.foo")])
262 tst
' "test13" (fn _
=>
264 andalso dir
"a/b" = "a"
265 andalso dir
"/" = "/"
266 andalso dir
"/b" = "/"
267 andalso dir
"/a/b" = "/a"
268 andalso dir
"/c/a/b" = "/c/a"
269 andalso dir
"/c/a/b/" = "/c/a/b"
270 andalso dir
"/c/a/b.foo.bar" = "/c/a"
271 andalso dir
"/c/a/b.foo" = "/c/a");
274 tst
' "test14" (fn _
=>
276 andalso file
"a/b" = "b"
277 andalso file
"/" = ""
278 andalso file
"/b" = "b"
279 andalso file
"/a/b" = "b"
280 andalso file
"/c/a/b" = "b"
281 andalso file
"/c/a/b/" = ""
282 andalso file
"/c/a/b.foo.bar" = "b.foo.bar"
283 andalso file
"/c/a/b.foo" = "b.foo");
286 tst
' "test15" (fn _
=>
287 splitBaseExt
"" = {base
= "", ext
= NONE
}
288 andalso splitBaseExt
".login" = {base
= ".login", ext
= NONE
}
289 andalso splitBaseExt
"/.login" = {base
= "/.login", ext
= NONE
}
290 andalso splitBaseExt
"a" = {base
= "a", ext
= NONE
}
291 andalso splitBaseExt
"a." = {base
= "a.", ext
= NONE
}
292 andalso splitBaseExt
"a.b" = {base
= "a", ext
= SOME
"b"}
293 andalso splitBaseExt
"a.b.c" = {base
= "a.b", ext
= SOME
"c"}
294 andalso splitBaseExt
"/a.b" = {base
= "/a", ext
= SOME
"b"}
295 andalso splitBaseExt
"/c/a.b" = {base
= "/c/a", ext
= SOME
"b"}
296 andalso splitBaseExt
"/c/a/b/.d" = {base
= "/c/a/b/.d", ext
= NONE
}
297 andalso splitBaseExt
"/c.a/b.d" = {base
= "/c.a/b", ext
= SOME
"d"}
298 andalso splitBaseExt
"/c.a/bd" = {base
= "/c.a/bd", ext
= NONE
}
299 andalso splitBaseExt
"/c/a/b.foo.bar" = {base
="/c/a/b.foo",ext
=SOME
"bar"}
300 andalso splitBaseExt
"/c/a/b.foo" = {base
= "/c/a/b", ext
= SOME
"foo"});
303 tst
' "test16" (fn _
=>
304 "" = joinBaseExt
{base
= "", ext
= NONE
}
305 andalso ".login" = joinBaseExt
{base
= ".login", ext
= NONE
}
306 andalso "a" = joinBaseExt
{base
= "a", ext
= NONE
}
307 andalso "a" = joinBaseExt
{base
= "a", ext
= SOME
""}
308 andalso "a.b" = joinBaseExt
{base
= "a", ext
= SOME
"b"}
309 andalso "a.b.c" = joinBaseExt
{base
= "a.b", ext
= SOME
"c"}
310 andalso "a.b.c.d" = joinBaseExt
{base
= "a.b", ext
= SOME
"c.d"}
311 andalso "/a.b" = joinBaseExt
{base
= "/a", ext
= SOME
"b"}
312 andalso "/c/a.b" = joinBaseExt
{base
= "/c/a", ext
= SOME
"b"}
313 andalso "/c/a/b/.d" = joinBaseExt
{base
= "/c/a/b/", ext
= SOME
"d"}
314 andalso "/c/a/b.foo.bar" = joinBaseExt
{base
="/c/a/b",ext
=SOME
"foo.bar"}
315 andalso "/c/a/b.foo" = joinBaseExt
{base
= "/c/a/b", ext
= SOME
"foo"});
318 tst
' "test17" (fn _
=>
320 andalso ext
".login" = NONE
321 andalso ext
"/.login" = NONE
322 andalso ext
"a" = NONE
323 andalso ext
"a." = NONE
324 andalso ext
"a.b" = SOME
"b"
325 andalso ext
"a.b.c" = SOME
"c"
326 andalso ext
"a.b.c.d" = SOME
"d"
327 andalso ext
"/a.b" = SOME
"b"
328 andalso ext
"/c/a.b" = SOME
"b"
329 andalso ext
"/c/a/b/.d" = NONE
330 andalso ext
"/c.a/b.d" = SOME
"d"
331 andalso ext
"/c.a/bd" = NONE
332 andalso ext
"/c/a/b.foo.bar" = SOME
"bar"
333 andalso ext
"/c/a/b.foo" = SOME
"foo");
336 tst
' "test18" (fn _
=>
338 andalso base
".d" = ".d"
339 andalso base
".login" = ".login"
340 andalso base
"/.login" = "/.login"
341 andalso base
"a" = "a"
342 andalso base
"a." = "a."
343 andalso base
"a.b" = "a"
344 andalso base
"a.b.c" = "a.b"
345 andalso base
"a.b.c.d" = "a.b.c"
346 andalso base
"/a.b" = "/a"
347 andalso base
"/c/a.b" = "/c/a"
348 andalso base
"/c/a/b/.d" = "/c/a/b/.d"
349 andalso base
"/c.a/b.d" = "/c.a/b"
350 andalso base
"/c.a/bd" = "/c.a/bd"
351 andalso base
"/c/a/b.foo.bar" = "/c/a/b.foo"
352 andalso base
"/c/a/b.foo" = "/c/a/b");
355 tst
' "test19" (fn () => validVolume
{isAbs
=false, vol
=""}
356 andalso validVolume
{isAbs
=true, vol
=""}
357 andalso not (validVolume
{isAbs
=true, vol
="/"}
358 orelse validVolume
{isAbs
=false, vol
="/"}
359 orelse validVolume
{isAbs
=true, vol
="C:"}
360 orelse validVolume
{isAbs
=false, vol
="C:"}
361 orelse validVolume
{isAbs
=true, vol
=" "}
362 orelse validVolume
{isAbs
=false, vol
=" "}));