1(* test/dospath.sml 6 -- for DOS -- incomplete, 1995-06-16 *)
2
3use "auxil.sml";
4
5local
6    open Path
7in
8
9val test1a =
10    check'(fn _ => fromString "" = {isAbs=false, vol = "", arcs = []});
11val test1b =
12    check'(fn _ => fromString "/" = {isAbs=true, vol="", arcs=[""]});
13val test1c =
14    check'(fn _ => fromString "//" = {isAbs=true, vol="", arcs=["", ""]});
15val test1d =
16    check'(fn _ => fromString "a" = {isAbs=false, vol = "", arcs = ["a"]});
17val test1e =
18    check'(fn _ => fromString "/a" = {isAbs=true, vol="", arcs=["a"]});
19val test1f =
20    check'(fn _ => fromString "//a" = {isAbs=true, vol="", arcs=["","a"]});
21val test1g =
22    check'(fn _ => fromString "a/" = {isAbs=false, vol = "", arcs = ["a", ""]});
23val test1h =
24    check'(fn _ => fromString "a//" = {isAbs=false, vol = "", arcs = ["a", "", ""]});
25val test1i =
26    check'(fn _ => fromString "a/b" = {isAbs=false, vol = "", arcs = ["a", "b"]});
27val test1j =
28    check'(fn _ => fromString "a.b/c" = {isAbs=false, vol = "", arcs = ["a.b", "c"]});
29val test1k =
30    check'(fn _ => fromString "a.b/c/" = {isAbs=false, vol = "", arcs = ["a.b", "c", ""]});
31val test1l =
32    check'(fn _ => fromString "a/./c" = {isAbs=false, vol = "", arcs = ["a", ".", "c"]});
33val test1m =
34    check'(fn _ => fromString "a/../c" = {isAbs=false, vol = "", arcs = ["a", "..", "c"]});
35val test1n =
36    check'(fn _ => fromString "." = {isAbs=false, vol = "", arcs = ["."]});
37
38val test2a =
39    check'(fn _ => toString {isAbs=false, vol = "", arcs = []} = "");
40val test2b =
41    check'(fn _ => toString {isAbs=true, vol="", arcs=[]} = "/");
42val test2c =
43    check'(fn _ => toString {isAbs=true, vol="", arcs=["", ""]} = "//");
44val test2d =
45    check'(fn _ => toString {isAbs=false, vol = "", arcs = ["a"]} = "a");
46val test2e =
47    check'(fn _ => toString {isAbs=true, vol="", arcs=["a"]} = "/a");
48val test2f =
49    check'(fn _ => toString {isAbs=true, vol="", arcs=["","a"]} = "//a");
50val test2g =
51    check'(fn _ => toString {isAbs=false, vol = "", arcs = ["a", ""]} = "a/");
52val test2h =
53    check'(fn _ => toString {isAbs=false, vol = "", arcs = ["a", "", ""]} = "a//");
54val test2i =
55    check'(fn _ => toString {isAbs=false, vol = "", arcs = ["a", "b"]} = "a/b");
56val test2j =
57    check'(fn _ => toString {isAbs=false, vol = "", arcs = ["a.b", "c"]} = "a.b/c");
58val test2k =
59    check'(fn _ => toString {isAbs=false, vol = "", arcs = ["a.b", "c", ""]} = "a.b/c/");
60val test2l =
61    check'(fn _ => toString {isAbs=false, vol = "", arcs = ["a", ".", "c"]} = "a/./c");
62val test2m =
63    check'(fn _ => toString {isAbs=false, vol = "", arcs = ["a", "..", "c"]} = "a/../c");
64val test2n =
65    check'(fn _ => toString {isAbs=true, vol="", arcs=["a", "..", "c"]} = "/a/../c");
66val test2o = (toString {isAbs=false, vol = "", arcs =  ["", "a"]} seq "WRONG")
67             handle Path => "OK" | _ => "WRONG";
68val test2p =
69    check'(fn _ =>
70   (toString {isAbs=true, vol = "C:", arcs =  ["windows"]} = "C:/windows"));
71
72val test3b =
73    check'(fn _ => getVolume "/" = "");
74val test3c =
75    check'(fn _ => getVolume "//" = "");
76val test3d =
77    check'(fn _ => getVolume "a//b/c/" = "");
78val test3e =
79    check'(fn _ => getVolume "./" = "");
80val test3f =
81    check'(fn _ => getVolume "../" = "");
82val test3g =
83    check'(fn _ => getVolume "" = "");
84val test3h =
85    check'(fn _ => getVolume "C:" = "C:");
86
87val test4a =
88    check'(fn _ =>
89	   List.all isRelative ["", ".", "..", "a//"]
90	   andalso not (List.exists isRelative ["/", "/a", "//"]));
91val test4b =
92    check'(fn _ =>
93	   List.all isAbsolute ["/", "/a", "//", "/.", "/.."]
94	   andalso not (List.exists isAbsolute ["", ".", "..", "a//"]));
95
96val test5a =
97    check'(fn _ =>
98	   getParent "/" = "/"
99	   andalso getParent "a" = "."
100	   andalso getParent "a/" = "a/.."
101	   andalso getParent "a///" = "a///.."
102	   andalso getParent "a/b" = "a"
103	   andalso getParent "a/b/" = "a/b/.."
104	   andalso getParent "/a/b" = "/a"
105	   andalso getParent "/a/b/" = "/a/b/.."
106	   andalso getParent ".." = "../.."
107	   andalso getParent "." = ".."
108	   andalso getParent "../" = "../.."
109	   andalso getParent "./" = "./.."
110	   andalso getParent "" = "..");
111
112val test6a =
113    check'(fn _ =>
114	   concat("a", "b") = "a/b"
115	   andalso concat("a", "b/c") = "a/b/c"
116	   andalso concat("/", "b/c") = "/b/c"
117	   andalso concat("", "b/c") = "b/c"
118	   andalso concat("/a", "b/c") = "/a/b/c"
119	   andalso concat("a/", "b/c") = "a/b/c"
120	   andalso concat("a//", "b/c") = "a//b/c"
121	   andalso concat(".", "b/c") = "./b/c"
122	   andalso concat("a/b", "..") = "a/b/.."
123	   andalso concat("a/b", "../c") = "a/b/../c");
124val test6b = (concat ("a", "/b") seq "WRONG")
125             handle Path => "OK" | _ => "WRONG";
126
127val test7a =
128    check'(fn _ =>
129	   mkAbsolute("/a/b", "/c/d") = "/a/b"
130	   andalso mkAbsolute("/", "/c/d") = "/"
131	   andalso mkAbsolute("a/b", "/c/d") = "/c/d/a/b");
132val test7b = (mkAbsolute("a", "c/d") seq "WRONG")
133             handle Path => "OK" | _ => "WRONG";
134val test7c = (mkAbsolute("/a", "c/d") seq "WRONG")
135              handle Path => "OK" | _ => "WRONG";
136
137val test8a =
138    check'(fn _ =>
139	   mkRelative("a/b", "/c/d") = "a/b"
140	   andalso mkRelative("/", "/a/b/c")	   = "../../.."
141	   andalso mkRelative("/a/", "/a/b/c")	   = "../../"
142	   andalso mkRelative("/a/b/", "/a/c")	   = "../b/"
143	   andalso mkRelative("/a/b", "/a/c/")	   = "../b"
144	   andalso mkRelative("/a/b/", "/a/c/")	   = "../b/"
145	   andalso mkRelative("/", "/")		   = "."
146	   andalso mkRelative("/", "/.")	   = "."
147	   andalso mkRelative("/", "/..")	   = "."
148	   andalso mkRelative("/", "/a")	   = ".."
149	   andalso mkRelative("/a/b/../c", "/a/d") = "../b/../c"
150	   andalso mkRelative("/a/b", "/c/d")      = "../../a/b"
151	   andalso mkRelative("/c/a/b", "/c/d")    = "../a/b"
152	   andalso mkRelative("/c/d/a/b", "/c/d")  = "a/b");
153val test8b = (mkRelative("/a", "c/d") seq "WRONG")
154              handle Path => "OK" | _ => "WRONG";
155val test8c = (mkRelative("a", "c/d") seq "WRONG")
156              handle Path => "OK" | _ => "WRONG";
157
158val test9a = let
159    fun chkCanon (a, b) =
160	  (mkCanonical a = b)
161	  andalso (mkCanonical b = b)
162	  andalso (isCanonical b)
163    in
164      check'(fn _ =>
165	   chkCanon("", ".")
166	   andalso chkCanon(".", ".")
167	   andalso chkCanon("./.", ".")
168	   andalso chkCanon("/.", "/")
169	   andalso chkCanon("..", "..")
170	   andalso chkCanon("../..", "../..")
171	   andalso chkCanon("b", "b")
172	   andalso chkCanon("a/b", "a/b")
173	   andalso chkCanon("/a/b", "/a/b")
174	   andalso chkCanon("a/b/", "a/b")
175	   andalso chkCanon("a/b//", "a/b")
176	   andalso chkCanon("a/../b", "b")
177	   andalso chkCanon("a/..", ".")
178	   andalso chkCanon("a/.", "a")
179	   andalso chkCanon("a/", "a")
180	   andalso chkCanon("/a/../b/", "/b")
181	   andalso chkCanon("/..", "/")
182	   andalso chkCanon("/../../a/b", "/a/b")
183	   andalso chkCanon("/./../../a/b", "/a/b")
184	   andalso chkCanon("/./../..", "/")
185	   andalso chkCanon("a/../b", "b")
186	   andalso chkCanon("a/./b", "a/b")
187	   andalso chkCanon("a////b", "a/b")
188           andalso chkCanon("a////b", "a/b"))
189    end
190
191val test10a =
192    check'(fn _ =>
193	   not (isCanonical "./."
194		orelse isCanonical "/.."
195		orelse isCanonical "/."
196		orelse isCanonical "//"
197		orelse isCanonical "a/.."
198		orelse isCanonical "a//b"
199		orelse isCanonical "a/."
200	        orelse isCanonical "a/b/"
201		orelse isCanonical "a/.."))
202
203val test11a =
204    check'(fn _ =>
205	   splitDirFile "" = {dir = "", file = ""}
206	   andalso splitDirFile "." = {dir = "", file = "."}
207	   andalso splitDirFile ".." = {dir = "", file = ".."}
208	   andalso splitDirFile "b" = {dir = "", file = "b"}
209	   andalso splitDirFile "b/" = {dir = "b", file = ""}
210	   andalso splitDirFile "a/b" = {dir = "a", file = "b"}
211	   andalso splitDirFile "/a" = {dir = "/", file = "a"}
212	   andalso splitDirFile "/a/b" = {dir = "/a", file = "b"}
213	   andalso splitDirFile "/c/a/b" = {dir = "/c/a", file = "b"}
214	   andalso splitDirFile "/c/a/b/" = {dir = "/c/a/b", file = ""}
215	   andalso splitDirFile "/c/a/b.foo.bar" = {dir = "/c/a", file="b.foo.bar"}
216	   andalso splitDirFile "/c/a/b.foo" = {dir = "/c/a", file = "b.foo"});
217
218(*
219val test11b = (splitDirFile "" seq "WRONG")
220              handle Path => "OK" | _ => "WRONG";
221*)
222
223val test12 =
224    check'(fn _ =>
225	   "" = joinDirFile {dir = "", file = ""}
226	   andalso "b" = joinDirFile {dir = "", file = "b"}
227	   andalso "/" = joinDirFile {dir = "/", file = ""}
228	   andalso "/b" = joinDirFile {dir = "/", file = "b"}
229	   andalso "a/b" = joinDirFile {dir = "a", file = "b"}
230	   andalso "/a/b" = joinDirFile {dir = "/a", file = "b"}
231	   andalso "/c/a/b" = joinDirFile {dir = "/c/a", file = "b"}
232	   andalso "/c/a/b/" = joinDirFile {dir = "/c/a/b", file = ""}
233	   andalso "/c/a/b.foo.bar" = joinDirFile {dir = "/c/a", file="b.foo.bar"}
234	   andalso "/c/a/b.foo" = joinDirFile {dir = "/c/a", file = "b.foo"});
235
236val test13 =
237    check'(fn _ =>
238	   dir "b" = ""
239	   andalso dir "a/b" = "a"
240	   andalso dir "/" = "/"
241	   andalso dir "/b" = "/"
242	   andalso dir "/a/b" = "/a"
243	   andalso dir "/c/a/b" = "/c/a"
244	   andalso dir "/c/a/b/" = "/c/a/b"
245	   andalso dir "/c/a/b.foo.bar" = "/c/a"
246	   andalso dir "/c/a/b.foo" = "/c/a");
247
248val test14 =
249    check'(fn _ =>
250	   file "b" = "b"
251	   andalso file "a/b" = "b"
252	   andalso file "/" = ""
253	   andalso file "/b" = "b"
254	   andalso file "/a/b" = "b"
255	   andalso file "/c/a/b" = "b"
256	   andalso file "/c/a/b/" = ""
257	   andalso file "/c/a/b.foo.bar" = "b.foo.bar"
258	   andalso file "/c/a/b.foo" = "b.foo");
259
260val test15 =
261    check'(fn _ =>
262	   splitBaseExt "" = {base = "", ext = NONE}
263	   andalso splitBaseExt ".login" = {base = ".login", ext = NONE}
264	   andalso splitBaseExt "/.login" = {base = "/.login", ext = NONE}
265	   andalso splitBaseExt "a" = {base = "a", ext = NONE}
266	   andalso splitBaseExt "a." = {base = "a.", ext = NONE}
267	   andalso splitBaseExt "a.b" = {base = "a", ext = SOME "b"}
268	   andalso splitBaseExt "a.b.c" = {base = "a.b", ext = SOME "c"}
269	   andalso splitBaseExt "/a.b" = {base = "/a", ext = SOME "b"}
270	   andalso splitBaseExt "/c/a.b" = {base = "/c/a", ext = SOME "b"}
271	   andalso splitBaseExt "/c/a/b/.d" = {base = "/c/a/b/.d", ext = NONE}
272	   andalso splitBaseExt "/c.a/b.d" = {base = "/c.a/b", ext = SOME "d"}
273	   andalso splitBaseExt "/c.a/bd" = {base = "/c.a/bd", ext = NONE}
274	   andalso splitBaseExt "/c/a/b.foo.bar" = {base="/c/a/b.foo",ext=SOME "bar"}
275	   andalso splitBaseExt "/c/a/b.foo" = {base = "/c/a/b", ext = SOME "foo"});
276
277val test16 =
278    check'(fn _ =>
279	   "" = joinBaseExt {base = "", ext = NONE}
280	   andalso ".login" = joinBaseExt {base = ".login", ext = NONE}
281	   andalso "a" = joinBaseExt {base = "a", ext = NONE}
282	   andalso "a." = joinBaseExt {base = "a", ext = SOME ""}
283	   andalso "a.b" = joinBaseExt {base = "a", ext = SOME "b"}
284	   andalso "a.b.c" = joinBaseExt {base = "a.b", ext = SOME "c"}
285	   andalso "a.b.c.d" = joinBaseExt {base = "a.b", ext = SOME "c.d"}
286	   andalso "/a.b" = joinBaseExt {base = "/a", ext = SOME "b"}
287	   andalso "/c/a.b" = joinBaseExt {base = "/c/a", ext = SOME "b"}
288	   andalso "/c/a/b/.d" = joinBaseExt {base = "/c/a/b/", ext = SOME "d"}
289	   andalso "/c/a/b.foo.bar" = joinBaseExt {base="/c/a/b",ext=SOME "foo.bar"}
290	   andalso "/c/a/b.foo" = joinBaseExt {base = "/c/a/b", ext = SOME "foo"});
291
292val test17 =
293    check'(fn _ =>
294	   ext "" = NONE
295	   andalso ext ".login" = NONE
296	   andalso ext "/.login" = NONE
297	   andalso ext "a" = NONE
298	   andalso ext "a." = NONE
299	   andalso ext "a.b" = SOME "b"
300	   andalso ext "a.b.c" = SOME "c"
301	   andalso ext "a.b.c.d" = SOME "d"
302	   andalso ext "/a.b" = SOME "b"
303	   andalso ext "/c/a.b" = SOME "b"
304	   andalso ext "/c/a/b/.d" = NONE
305	   andalso ext "/c.a/b.d" = SOME "d"
306	   andalso ext "/c.a/bd" = NONE
307	   andalso ext "/c/a/b.foo.bar" = SOME "bar"
308	   andalso ext "/c/a/b.foo" = SOME "foo");
309
310val test18 =
311    check'(fn _ =>
312	   base "" = ""
313	   andalso base ".d" = ".d"
314	   andalso base ".login" = ".login"
315	   andalso base "/.login" = "/.login"
316	   andalso base "a" = "a"
317	   andalso base "a." = "a."
318	   andalso base "a.b" = "a"
319	   andalso base "a.b.c" = "a.b"
320	   andalso base "a.b.c.d" = "a.b.c"
321	   andalso base "/a.b" = "/a"
322	   andalso base "/c/a.b" = "/c/a"
323	   andalso base "/c/a/b/.d" = "/c/a/b/.d"
324	   andalso base "/c.a/b.d" = "/c.a/b"
325	   andalso base "/c.a/bd" = "/c.a/bd"
326	   andalso base "/c/a/b.foo.bar" = "/c/a/b.foo"
327	   andalso base "/c/a/b.foo" = "/c/a/b");
328
329val test19 =
330    check'(fn () => validVolume{isAbs=false, vol=""}
331	   andalso validVolume{isAbs=true, vol=""}
332	   andalso validVolume{isAbs=true, vol="C:"}
333	   andalso validVolume{isAbs=false, vol="C:"}
334	   andalso not (validVolume{isAbs=true, vol="/"}
335			orelse validVolume{isAbs=false, vol="/"}
336			orelse validVolume{isAbs=true, vol=" "}
337			orelse validVolume{isAbs=false, vol=" "}));
338end
339