]> matita.cs.unibo.it Git - helm.git/blobdiff - helm/DEVEL/pxp/netstring/tests/test_neturl.ml
Initial revision
[helm.git] / helm / DEVEL / pxp / netstring / tests / test_neturl.ml
diff --git a/helm/DEVEL/pxp/netstring/tests/test_neturl.ml b/helm/DEVEL/pxp/netstring/tests/test_neturl.ml
new file mode 100644 (file)
index 0000000..633bfda
--- /dev/null
@@ -0,0 +1,969 @@
+#directory "..";;
+#load "netstring.cma";;
+
+open Neturl;;
+
+
+let expect_malformed_url f =
+  try ignore(f()); false with Malformed_URL -> true;;
+
+let works f =
+  not (expect_malformed_url f)
+;;
+
+(**********************************************************************)
+(* extract_url_scheme                                                 *)
+(**********************************************************************)
+
+let t001 () =
+  extract_url_scheme "a:bc" = "a" &&
+  extract_url_scheme "A:bc" = "a" &&
+  extract_url_scheme "a:b:c" = "a" &&
+  extract_url_scheme "a+b-c:d:e" = "a+b-c"
+;;
+
+
+let t002 () =
+  let test s =
+    try ignore(extract_url_scheme s); false with Malformed_URL -> true
+  in
+  test "a" &&
+  test "a/b:c" &&
+  test "%61:b" &&
+  test "a%3ab"
+;;
+
+(**********************************************************************)
+(* url_syntax                                                         *)
+(**********************************************************************)
+
+let hashtbl_for_all f h =
+  let b = ref true in
+  Hashtbl.iter
+    (fun k v -> b := !b && f k v)
+    h;
+  !b
+;;
+
+let t010 () =
+  url_syntax_is_valid null_url_syntax &&
+  url_syntax_is_valid ip_url_syntax &&
+  hashtbl_for_all
+    (fun _ syn ->
+       url_syntax_is_valid syn
+    )
+    common_url_syntax
+;;
+
+let t011 () =
+  url_syntax_is_valid (partial_url_syntax null_url_syntax) &&
+  url_syntax_is_valid (partial_url_syntax ip_url_syntax) &&
+  hashtbl_for_all
+    (fun _ syn ->
+       url_syntax_is_valid (partial_url_syntax syn)
+    )
+    common_url_syntax
+;;
+
+let t012 () =
+  let f = fun _ -> true in
+  let syn =
+    { url_enable_scheme    = Url_part_not_recognized;
+      url_enable_user      = Url_part_required;
+      url_enable_password  = Url_part_allowed;
+      url_enable_host      = Url_part_required;
+      url_enable_port      = Url_part_not_recognized;
+      url_enable_path      = Url_part_required;
+      url_enable_param     = Url_part_not_recognized;
+      url_enable_query     = Url_part_not_recognized;
+      url_enable_fragment  = Url_part_required;
+      url_enable_other     = Url_part_not_recognized;
+      url_accepts_8bits    = false;
+      url_is_valid         = f;
+    } in
+  let syn' = partial_url_syntax syn in
+  
+  (syn'.url_enable_scheme    = Url_part_not_recognized) &&
+  (syn'.url_enable_user      = Url_part_allowed) &&
+  (syn'.url_enable_password  = Url_part_allowed) &&
+  (syn'.url_enable_host      = Url_part_allowed) &&
+  (syn'.url_enable_port      = Url_part_not_recognized) &&
+  (syn'.url_enable_path      = Url_part_allowed) &&
+  (syn'.url_enable_param     = Url_part_not_recognized) &&
+  (syn'.url_enable_query     = Url_part_not_recognized) &&
+  (syn'.url_enable_fragment  = Url_part_allowed) &&
+  (syn'.url_enable_other     = Url_part_not_recognized) &&
+  (syn'.url_is_valid        == f) &&
+
+  url_syntax_is_valid syn &&
+  url_syntax_is_valid syn'
+;;
+
+(**********************************************************************)
+(* make_url                                                           *)
+(**********************************************************************)
+
+let t020 () =
+  (* Basic functionality: *)
+  let http_syn = Hashtbl.find common_url_syntax "http" in
+
+  let u1 = make_url
+            (* default: not encoded *)
+            ~scheme:"http"
+            ~user:"U"
+            ~password:"%()~$@"
+            ~host:"a.b.c"
+            ~port:81
+            ~path:["";"?";""]
+            http_syn in
+
+  url_provides 
+    ~scheme:true ~user:true ~password:true ~host:true ~port:true ~path:true 
+    u1 &&
+
+  not
+    (url_provides
+       ~scheme:true ~user:true ~password:true ~host:true ~port:true ~path:true 
+       ~query:true u1) &&
+
+  (url_syntax_of_url u1 == http_syn) &&
+
+  (url_scheme   u1 = "http") &&
+  (url_user     u1 = "U") &&
+  (url_password u1 = "%()~$@") &&
+  (url_host     u1 = "a.b.c") &&
+  (url_port     u1 = 81) &&
+  (url_path     u1 = ["";"?";""]) &&
+
+  (url_user     ~encoded:true u1 = "U") &&
+  (url_password ~encoded:true u1 = "%25()%7E$%40") &&
+  (url_path     ~encoded:true u1 = ["";"%3F";""]) &&
+
+  string_of_url u1 = "http://U:%25()%7E$%40@a.b.c:81/%3F/"
+;;
+
+
+let t021 () =
+  (* Basic functionality: *)
+  let http_syn = Hashtbl.find common_url_syntax "http" in
+
+  let u1 = make_url
+            ~encoded:true
+            ~scheme:"http"
+            ~user:"%55"
+            ~password:"%25()%7e$%40"
+            ~host:"a.b.c"
+            ~port:81
+            ~path:["";"%3F";""]
+            http_syn in
+
+  url_provides 
+    ~scheme:true ~user:true ~password:true ~host:true ~port:true ~path:true 
+    u1 &&
+
+  not
+    (url_provides
+       ~scheme:true ~user:true ~password:true ~host:true ~port:true ~path:true 
+       ~query:true u1) &&
+
+  (url_syntax_of_url u1 == http_syn) &&
+
+  (url_scheme   u1 = "http") &&
+  (url_user     u1 = "U") &&
+  (url_password u1 = "%()~$@") &&
+  (url_host     u1 = "a.b.c") &&
+  (url_port     u1 = 81) &&
+  (url_path     u1 = ["";"?";""]) &&
+
+  (url_user     ~encoded:true u1 = "%55") &&
+  (url_password ~encoded:true u1 = "%25()%7e$%40") &&
+  (url_path     ~encoded:true u1 = ["";"%3F";""]) &&
+
+  string_of_url u1 = "http://%55:%25()%7e$%40@a.b.c:81/%3F/"
+;;
+
+
+(* NEGATIVE TESTS *)
+
+let t030 () =
+  (* It is not possible to add a component which is not recognized *)
+  let http_syn = Hashtbl.find common_url_syntax "http" in
+
+  expect_malformed_url
+    (fun () ->
+       make_url
+        ~scheme:"http"
+        ~user:"U"
+        ~password:"%()~$@"
+        ~host:"a.b.c"
+        ~port:81
+        ~path:["";"?";""]
+        ~fragment:"abc"
+        http_syn)
+;;
+
+
+let t031 () =
+  (* It is not possible to put malformed '%'-encodings into the URL *)
+  let http_syn = Hashtbl.find common_url_syntax "http" in
+
+  works                      (* reference *)
+    (fun () ->
+       make_url
+        ~encoded:true
+        ~scheme:"http"
+        ~user:"U"
+        ~password:"XX"
+        ~host:"a.b.c"
+        ~port:81
+        ~path:["";"a";""]
+        http_syn) &&
+
+  expect_malformed_url
+    (fun () ->
+       make_url
+        ~encoded:true
+        ~scheme:"http"
+        ~user:"U"
+        ~password:"%XX"
+        ~host:"a.b.c"
+        ~port:81
+        ~path:["";"a";""]
+        http_syn) &&
+
+  expect_malformed_url
+    (fun () ->
+       make_url
+        ~encoded:true
+        ~scheme:"http"
+        ~user:"U"
+        ~password:"%X"
+        ~host:"a.b.c"
+        ~port:81
+        ~path:["";"a";""]
+        http_syn) &&
+
+  expect_malformed_url
+    (fun () ->
+       make_url
+        ~encoded:true
+        ~scheme:"http"
+        ~user:"U"
+        ~password:"%"
+        ~host:"a.b.c"
+        ~port:81
+        ~path:["";"a";""]
+        http_syn) 
+;;
+
+let t032 () =
+  (* It is not possible to put unsafe characters into the URL *)
+  let http_syn = Hashtbl.find common_url_syntax "http" in
+
+  let make c =
+    make_url
+      ~encoded:true
+      ~scheme:"http"
+      ~user:"U"
+      ~password:(String.make 1 c)
+      ~host:"a.b.c"
+      ~port:81
+      ~path:["";"a";""]
+      http_syn
+  in
+
+  works (fun () -> make 'a') &&                   (* reference *)
+
+  (* List of unsafe characters taken from RFC1738: *)
+  expect_malformed_url (fun () -> make '<') && 
+  expect_malformed_url (fun () -> make '>') && 
+  expect_malformed_url (fun () -> make '"') && 
+  expect_malformed_url (fun () -> make '#') && 
+    (* Note: '#' would be considered as reserved if fragments were enabled *)
+  expect_malformed_url (fun () -> make '%') && 
+  expect_malformed_url (fun () -> make '{') && 
+  expect_malformed_url (fun () -> make '}') && 
+  expect_malformed_url (fun () -> make '|') && 
+  expect_malformed_url (fun () -> make '\\') && 
+  expect_malformed_url (fun () -> make '^') && 
+  expect_malformed_url (fun () -> make '[') && 
+  expect_malformed_url (fun () -> make ']') && 
+  expect_malformed_url (fun () -> make '`') &&
+  expect_malformed_url (fun () -> make '~') &&
+    (* Note: '~' is considered as safe in paths: *)
+  works 
+    (fun () ->
+    make_url
+      ~encoded:true
+      ~scheme:"http"
+      ~user:"U"
+      ~password:"a"
+      ~host:"a.b.c"
+      ~port:81
+      ~path:["";"~";""]
+      http_syn)
+;;
+
+let t033 () =
+  (* It is not possible to put reserved characters into the URL *)
+  let http_syn = Hashtbl.find common_url_syntax "http" in
+
+  let make_password c =
+    make_url
+      ~encoded:true
+      ~scheme:"http"
+      ~user:"U"
+      ~password:(String.make 1 c)
+      ~host:"a.b.c"
+      ~port:81
+      ~path:["";"a";""]
+      http_syn
+  in
+  let make_path c =
+    make_url
+      ~encoded:true
+      ~scheme:"http"
+      ~user:"U"
+      ~password:"a"
+      ~host:"a.b.c"
+      ~port:81
+      ~path:["";String.make 1 c;""]
+      http_syn
+  in
+  let make_query c =
+    make_url
+      ~encoded:true
+      ~scheme:"http"
+      ~user:"U"
+      ~password:"a"
+      ~host:"a.b.c"
+      ~port:81
+      ~path:["";"a";""]
+      ~query:(String.make 1 c)
+      http_syn
+  in
+
+  (* Note: There is a difference between RFC 1738 and RFC 1808 regarding
+   * which characters are reserved. RFC 1808 defines a fixed set of characters
+   * as reserved while RFC 1738 defines the reserved characters depending
+   * on the scheme.
+   * This implementation of URLs follows RFC 1738 (because of practical
+   * reasons).
+   *)
+
+  works (fun () -> make_password 'a') &&                   (* reference *)
+  works (fun () -> make_path 'a') &&
+  works (fun () -> make_query 'a') &&
+
+  expect_malformed_url (fun () -> make_password ':') && 
+  expect_malformed_url (fun () -> make_password '@') && 
+  expect_malformed_url (fun () -> make_password '/') && 
+  works                (fun () -> make_password ';') &&
+  works                (fun () -> make_password '?') &&
+  works                (fun () -> make_password '=') &&
+  works                (fun () -> make_password '&') &&
+
+  (* Note: ';' is allowed in path and query because parameters are not
+   * recognized in HTTP syntax.
+   *)
+
+  expect_malformed_url (fun () -> make_path '/') && 
+  expect_malformed_url (fun () -> make_path '?') && 
+  works                (fun () -> make_path ':') && 
+  works                (fun () -> make_path '@') && 
+  works                (fun () -> make_path ';') && 
+  works                (fun () -> make_path '=') && 
+  works                (fun () -> make_path '&') && 
+
+  expect_malformed_url (fun () -> make_query '?') && 
+  works                (fun () -> make_query '/') && 
+  works                (fun () -> make_query ':') && 
+  works                (fun () -> make_query '@') && 
+  works                (fun () -> make_query ';') && 
+  works                (fun () -> make_query '=') && 
+  works                (fun () -> make_query '&')
+;;
+
+
+let t034 () =
+  (* It is not possible to create a URL with a password, but without user;
+   * and neither to create a URL with a port, but without host;
+   * and neither to create a URL with a user, but without host
+   *)
+
+  expect_malformed_url
+    (fun () ->
+       make_url
+        ~scheme:"http"
+        ~password:"a"
+        ~host:"a.b.c"
+        ~path:["";"a";""]
+        ip_url_syntax) &&
+
+  expect_malformed_url
+    (fun () ->
+       make_url
+        ~scheme:"http"
+        ~user:"U"
+        ~path:["";"a";""]
+        ip_url_syntax) &&
+
+  expect_malformed_url
+    (fun () ->
+       make_url
+        ~scheme:"http"
+        ~port:81
+        ~path:["";"a";""]
+        ip_url_syntax)
+;;
+
+
+let t035 () =
+  (* It is not possible to create a URL with illegal scheme prefix *)
+  
+  (* reference: *)
+  works
+    (fun () ->
+       make_url
+        ~scheme:"a"
+        ip_url_syntax) &&
+
+  expect_malformed_url
+    (fun () ->
+       make_url
+        ~scheme:":"
+        ip_url_syntax) &&
+
+  expect_malformed_url
+    (fun () ->
+       make_url
+        ~scheme:"a=b"
+        ip_url_syntax) &&
+
+  expect_malformed_url
+    (fun () ->
+       make_url
+        ~scheme:"a%62b"
+        ip_url_syntax) &&
+  expect_malformed_url
+    (fun () ->
+       make_url
+        ~scheme:"a&b"
+        ip_url_syntax)
+;;
+
+
+let t036 () =
+  (* It is not possible to have a path with double slashes *)
+  
+  (* reference: *)
+  works
+    (fun () ->
+       make_url
+        ~path:["";"a";""]
+        ip_url_syntax) &&
+
+  expect_malformed_url
+    (fun () ->
+       make_url
+        ~path:["";""]
+        ip_url_syntax) &&
+
+  expect_malformed_url
+    (fun () ->
+       make_url
+        ~path:["a";"";""]
+        ip_url_syntax) &&
+
+  expect_malformed_url
+    (fun () ->
+       make_url
+        ~path:["";"";"a"]
+        ip_url_syntax) &&
+
+  expect_malformed_url
+    (fun () ->
+       make_url
+        ~path:["a";"";"a"]
+        ip_url_syntax)
+;;
+
+
+let t037 () =
+  (* It is not possible to have port numbers outside 0..65535 *)
+  
+  (* reference: *)
+  works
+    (fun () ->
+       make_url
+        ~host:"a"
+        ~port:1
+        ip_url_syntax) &&
+
+  expect_malformed_url
+    (fun () ->
+       make_url
+        ~host:"a"
+        ~port:(-1)
+        ip_url_syntax) &&
+
+  expect_malformed_url
+    (fun () ->
+       make_url
+        ~host:"a"
+        ~port:65536
+        ip_url_syntax)
+;;
+
+
+let t038 () =
+  (* Several cases which are not allowed. *)
+  
+  expect_malformed_url
+    (fun () ->
+       make_url
+        ~host:"a"
+        ~path:["a"]
+        ip_url_syntax
+    ) &&                       (* illegal: host + relative path *)
+
+  expect_malformed_url
+    (fun () ->
+       make_url
+        ~host:"a"
+        ~path:[]
+        ~param:["x"]
+        ip_url_syntax
+    ) &&                       (* illegal: host + no path + params *)
+
+  expect_malformed_url
+    (fun () ->
+       make_url
+        ~host:"a"
+        ~path:[]
+        ~query:"x"
+        ip_url_syntax
+    )                          (* illegal: host + no path + query *)
+;;
+
+(**********************************************************************)
+(* url_of_string                                                      *)
+(**********************************************************************)
+
+let t050 () =
+  (* absolute URLs with ip_url_syntax *)
+  let identical s =
+    string_of_url (url_of_string ip_url_syntax s) = s in
+
+  let fails s =
+    try ignore(url_of_string ip_url_syntax s); false 
+    with Malformed_URL -> true
+  in
+
+  identical "http:" &&
+
+  identical "http://host" &&
+  identical "http://user@host" &&
+  identical "http://user:password@host" &&
+  identical "http://user@host:99" &&
+  identical "http://user:password@host:99" &&
+
+  identical "http://host/" &&
+  identical "http://user@host/" &&
+  identical "http://user:password@host/" &&
+  identical "http://user@host:99/" &&
+  identical "http://user:password@host:99/" &&
+
+  identical "http://host/a/b" &&
+  identical "http://user@host/a/b" &&
+  identical "http://user:password@host/a/b" &&
+  identical "http://user@host:99/a/b" &&
+  identical "http://user:password@host:99/a/b" &&
+
+  identical "http://host/a/b/" &&
+  identical "http://user@host/a/b/" &&
+  identical "http://user:password@host/a/b/" &&
+  identical "http://user@host:99/a/b/" &&
+  identical "http://user:password@host:99/a/b/" &&
+
+  identical "http://host/?a=b&c=d" &&
+  identical "http://user@host/?a=b&c=d" &&
+  identical "http://user:password@host/?a=b&c=d" &&
+  identical "http://user@host:99/?a=b&c=d" &&
+  identical "http://user:password@host:99/?a=b&c=d" &&
+
+  fails "http://host?a=b&c=d" &&
+  fails "http://user@host?a=b&c=d" &&
+  fails "http://user:password@host?a=b&c=d" &&
+  fails "http://user@host:99?a=b&c=d" &&
+  fails "http://user:password@host:99?a=b&c=d" &&
+
+  identical "http://host/?a=/&c=/" &&
+  identical "http://user@host/?a=/&c=/" &&
+  identical "http://user:password@host/?a=/&c=/" &&
+  identical "http://user@host:99/?a=/&c=/" &&
+  identical "http://user:password@host:99/?a=/&c=/" &&
+
+  identical "http://host/;a;b" &&
+  identical "http://user@host/;a;b" &&
+  identical "http://user:password@host/;a;b" &&
+  identical "http://user@host:99/;a;b" &&
+  identical "http://user:password@host:99/;a;b" &&
+
+  fails "http://host;a;b" &&
+  fails "http://user@host;a;b" &&
+  fails "http://user:password@host;a;b" &&
+  fails "http://user@host:99;a;b" &&
+  fails "http://user:password@host:99;a;b" &&
+
+  identical "http://host/;a;b?a=b&c=d" &&
+  identical "http://user@host/;a;b?a=b&c=d" &&
+  identical "http://user:password@host/;a;b?a=b&c=d" &&
+  identical "http://user@host:99/;a;b?a=b&c=d" &&
+  identical "http://user:password@host:99/;a;b?a=b&c=d" &&
+
+  identical "http:#f" &&
+
+  identical "http://host#f" &&
+  identical "http://user@host#f" &&
+  identical "http://user:password@host#f" &&
+  identical "http://user@host:99#f" &&
+  identical "http://user:password@host:99#f" &&
+
+  identical "http://host/;a;b?a=b&c=d#f" &&
+  identical "http://user@host/;a;b?a=b&c=d#f" &&
+  identical "http://user:password@host/;a;b?a=b&c=d#f" &&
+  identical "http://user@host:99/;a;b?a=b&c=d#f" &&
+  identical "http://user:password@host:99/;a;b?a=b&c=d#f" &&
+
+  true
+;;
+
+
+let t051 () =
+  (* relative URLs with ip_url_syntax *)
+  let identical s =
+    string_of_url (url_of_string ip_url_syntax s) = s in
+
+  let fails s =
+    try ignore(url_of_string ip_url_syntax s); false 
+    with Malformed_URL -> true
+  in
+
+  identical "//host" &&
+  identical "//user@host" &&
+  identical "//user:password@host" &&
+  identical "//user@host:99" &&
+  identical "//user:password@host:99" &&
+
+  identical "//host/" &&
+  identical "//user@host/" &&
+  identical "//user:password@host/" &&
+  identical "//user@host:99/" &&
+  identical "//user:password@host:99/" &&
+
+  identical "//host#f" &&
+  identical "//user@host#f" &&
+  identical "//user:password@host#f" &&
+  identical "//user@host:99#f" &&
+  identical "//user:password@host:99#f" &&
+
+  identical "/" &&
+  identical "/a" &&
+  identical "/a/" &&
+  identical "/a/a" &&
+
+  identical "/;a;b" &&
+  identical "/a;a;b" &&
+  identical "/a/;a;b" &&
+  identical "/a/a;a;b" &&
+
+  identical "/?a=b&c=d" &&
+  identical "/a?a=b&c=d" &&
+  identical "/a/?a=b&c=d" &&
+  identical "/a/a?a=b&c=d" &&
+
+  identical "/;a;b?a=b&c=d" &&
+  identical "/a;a;b?a=b&c=d" &&
+  identical "/a/;a;b?a=b&c=d" &&
+  identical "/a/a;a;b?a=b&c=d" &&
+
+  identical "/#f" &&
+  identical "/a#f" &&
+  identical "/a/#f" &&
+  identical "/a/a#f" &&
+
+  identical "/;a;b#f" &&
+  identical "/a;a;b#f" &&
+  identical "/a/;a;b#f" &&
+  identical "/a/a;a;b#f" &&
+
+  identical "/;a;b?a=b&c=d#f" &&
+  identical "/a;a;b?a=b&c=d#f" &&
+  identical "/a/;a;b?a=b&c=d#f" &&
+  identical "/a/a;a;b?a=b&c=d#f" &&
+
+  identical "" &&
+  identical "a" &&
+  identical "a/" &&
+  identical "a/a" &&
+
+  identical ";a;b" &&
+  identical "a;a;b" &&
+  identical "a/;a;b" &&
+  identical "a/a;a;b" &&
+
+  identical "?a=b&c=d" &&
+  identical "a?a=b&c=d" &&
+  identical "a/?a=b&c=d" &&
+  identical "a/a?a=b&c=d" &&
+
+  identical ";a;b?a=b&c=d" &&
+  identical "a;a;b?a=b&c=d" &&
+  identical "a/;a;b?a=b&c=d" &&
+  identical "a/a;a;b?a=b&c=d" &&
+
+  identical "#f" &&
+  identical "a#f" &&
+  identical "a/#f" &&
+  identical "a/a#f" &&
+
+  identical ";a;b#f" &&
+  identical "a;a;b#f" &&
+  identical "a/;a;b#f" &&
+  identical "a/a;a;b#f" &&
+
+  identical ";a;b?a=b&c=d#f" &&
+  identical "a;a;b?a=b&c=d#f" &&
+  identical "a/;a;b?a=b&c=d#f" &&
+  identical "a/a;a;b?a=b&c=d#f" &&
+
+  identical "." &&
+  identical "./" &&
+  identical "./a" &&
+
+  identical ".;a;b" &&
+  identical "./;a;b" &&
+  identical "./a;a;b" &&
+
+  identical ".?a=b&c=d" &&
+  identical "./?a=b&c=d" &&
+  identical "./a?a=b&c=d" &&
+
+  identical ".;a;b?a=b&c=d" &&
+  identical "./;a;b?a=b&c=d" &&
+  identical "./a;a;b?a=b&c=d" &&
+
+  identical ".#f" &&
+  identical "./#f" &&
+  identical "./a#f" &&
+
+  identical ".;a;b#f" &&
+  identical "./;a;b#f" &&
+  identical "./a;a;b#f" &&
+
+  identical ".;a;b?a=b&c=d#f" &&
+  identical "./;a;b?a=b&c=d#f" &&
+  identical "./a;a;b?a=b&c=d#f" &&
+
+  identical ".." &&
+  identical "../" &&
+  identical "../a" &&
+
+  identical "..;a;b" &&
+  identical "../;a;b" &&
+  identical "../a;a;b" &&
+
+  identical "..?a=b&c=d" &&
+  identical "../?a=b&c=d" &&
+  identical "../a?a=b&c=d" &&
+
+  identical "..;a;b?a=b&c=d" &&
+  identical "../;a;b?a=b&c=d" &&
+  identical "../a;a;b?a=b&c=d" &&
+
+  identical "..#f" &&
+  identical "../#f" &&
+  identical "../a#f" &&
+
+  identical "..;a;b#f" &&
+  identical "../;a;b#f" &&
+  identical "../a;a;b#f" &&
+
+  identical "..;a;b?a=b&c=d#f" &&
+  identical "../;a;b?a=b&c=d#f" &&
+  identical "../a;a;b?a=b&c=d#f" &&
+
+  string_of_url
+    (make_url ~path:["a:b"] ip_url_syntax) = "a%3Ab" &&
+
+  string_of_url
+    (make_url ~encoded:true ~path:["a:b"] ip_url_syntax) = "./a:b" &&
+
+  true
+;;
+
+
+let t052 () =
+  (* mailto: URLs *)
+  let mailto_syn = Hashtbl.find common_url_syntax "mailto" in
+
+  let identical s =
+    string_of_url (url_of_string mailto_syn s) = s in
+
+  let fails s =
+    try ignore(url_of_string mailto_syn s); false 
+    with Malformed_URL -> true
+  in
+
+  identical "mailto:user@host" &&
+  identical "mailto:user@host;?;?" &&
+  fails     "mailto:user@host#f"
+;;
+
+(**********************************************************************)
+(* split_path/join_path/norm_path:                                    *)
+(**********************************************************************)
+
+let t060 () =
+  (split_path "" = []) &&
+  (split_path "/" = [ "" ]) &&
+  (split_path "/a" = [ ""; "a" ]) &&
+  (split_path "a" = [ "a" ]) &&
+  (split_path "a/" = [ "a"; "" ]) &&
+  (split_path "/a/" = [ ""; "a"; "" ]) &&
+  (split_path "/a/b" = [ ""; "a"; "b" ]) &&
+  (split_path "/a/b/" = [ ""; "a"; "b"; "" ]) &&
+  (split_path "/a/b/c" = [ ""; "a"; "b"; "c" ]) &&
+
+  (join_path [] = "") &&
+  (join_path [ "" ] = "/") &&
+  (join_path [ ""; "a" ] = "/a") &&
+  (join_path [ "a" ] = "a") &&
+  (join_path [ "a"; "" ] = "a/") &&
+  (join_path [ ""; "a"; "" ] = "/a/") &&
+  (join_path [ ""; "a"; "b" ] = "/a/b") &&
+  (join_path [ ""; "a"; "b"; "" ] = "/a/b/") &&
+  (join_path [ ""; "a"; "b"; "c" ] = "/a/b/c") &&
+
+  true
+;;
+
+
+let t061 () =
+  (norm_path ["."] = []) &&
+  (norm_path ["."; ""] = []) &&
+  (norm_path ["a"; "."] = ["a"; ""]) &&
+  (norm_path ["a"; "b"; "."] = ["a"; "b"; ""]) &&
+  (norm_path ["a"; "b"; ".."] = ["a"; ""]) &&
+  (norm_path ["a"; "."; "b"; "."] = ["a"; "b"; ""]) &&
+  (norm_path [".."] = [".."; ""]) &&
+  (norm_path [".."; ""] = [".."; ""]) &&
+  (norm_path ["a"; "b"; ".."; "c" ] = ["a"; "c"]) &&
+  (norm_path ["a"; "b"; ".."; "c"; ""] = ["a"; "c"; ""]) &&
+  (norm_path ["";"";"a";"";"b"] = [""; "a"; "b"]) &&
+  (norm_path ["a"; "b"; ""; ".."; "c"; ""] = ["a"; "c"; ""]) &&
+  (norm_path ["a"; ".."] = []) &&
+  (norm_path ["";""] = [""]) &&
+  (norm_path [""] = [""]) &&
+  (norm_path [] = []) &&
+
+  true
+;;
+                 
+(**********************************************************************)
+(* apply_relative_url:                                                *)
+(**********************************************************************)
+
+let t070() =
+  (* Examples taken from RFC 1808 *)
+  let url = url_of_string ip_url_syntax in
+  let base = url "http://a/b/c/d;p?q#f" in
+  let aru = apply_relative_url base in
+
+  (aru (url "g:h")     = url "g:h") &&
+  (aru (url "g")       = url "http://a/b/c/g") &&
+  (aru (url "./g")     = url "http://a/b/c/g") &&
+  (aru (url "g/")      = url "http://a/b/c/g/") &&
+  (aru (url "/g")      = url "http://a/g") &&
+  (aru (url "//g")     = url "http://g") &&
+  (aru (url "?y")      = url "http://a/b/c/d;p?y") &&
+  (aru (url "g?y")     = url "http://a/b/c/g?y") &&
+  (aru (url "g?y/./x") = url "http://a/b/c/g?y/./x") &&
+  (aru (url "#s")      = url "http://a/b/c/d;p?q#s") &&
+  (aru (url "g#s")     = url "http://a/b/c/g#s") &&
+  (aru (url "g#s/./x") = url "http://a/b/c/g#s/./x") &&
+  (aru (url "g?y#s")   = url "http://a/b/c/g?y#s") &&
+  (aru (url ";x")      = url "http://a/b/c/d;x") &&
+  (aru (url "g;x")     = url "http://a/b/c/g;x") &&
+  (aru (url "g;x?y#s") = url "http://a/b/c/g;x?y#s") &&
+  (aru (url ".")       = url "http://a/b/c/") &&
+  (aru (url "./")      = url "http://a/b/c/") &&
+  (aru (url "..")      = url "http://a/b/") &&
+  (aru (url "../")     = url "http://a/b/") &&
+  (aru (url "../g")    = url "http://a/b/g") &&
+  (aru (url "../..")   = url "http://a/") &&
+  (aru (url "../../")  = url "http://a/") &&
+  (aru (url "../../g") = url "http://a/g") &&
+
+  (aru (url "")              = url "http://a/b/c/d;p?q#f") &&
+  (aru (url "../../../g")    = url "http://a/../g") &&
+  (aru (url "../../../../g") = url "http://a/../../g") &&
+  (aru (url "/./g")          = url "http://a/./g") &&
+  (aru (url "/../g")         = url "http://a/../g") &&
+  (aru (url "g.")            = url "http://a/b/c/g.") &&
+  (aru (url ".g")            = url "http://a/b/c/.g") &&
+  (aru (url "g..")           = url "http://a/b/c/g..") &&
+  (aru (url "..g")           = url "http://a/b/c/..g") &&
+  (aru (url "./../g")        = url "http://a/b/g") &&
+  (aru (url "./g/.")         = url "http://a/b/c/g/") &&
+  (aru (url "g/./h")         = url "http://a/b/c/g/h") &&
+  (aru (url "g/../h")        = url "http://a/b/c/h") &&
+  (aru (url "http:g")        = url "http:g") &&
+  (aru (url "http:")         = url "http:") &&
+
+  true
+;;
+  
+
+(**********************************************************************)
+
+let test f n =
+  if f() then
+    print_endline ("Test " ^ n ^ " ok")
+  else 
+    print_endline ("Test " ^ n ^ " FAILED!!!!");
+  flush stdout
+;;
+
+test t001 "001";
+test t002 "002";
+
+test t010 "010";
+test t011 "011";
+test t012 "012";
+
+test t020 "020";
+test t021 "021";
+
+test t030 "030";
+test t031 "031";
+test t032 "032";
+test t033 "033";
+test t034 "034";
+test t035 "035";
+test t036 "036";
+test t037 "037";
+test t038 "038";
+
+test t050 "050";
+test t051 "051";
+test t052 "052";
+
+test t060 "060";
+test t061 "061";
+
+test t070 "070";
+()
+;;