open Str

let invoke f name n x =
  let t1 = Sys.time() in
  for i = 1 to n do
    f x
  done;
  let t2 = Sys.time() in
  Printf.printf "Test %s lasts %f seconds\n" name ((t2 -. t1) /. float n);
  flush stdout
;;


(* TEST DATA *)

let rec rep n =
  if n = 0 then [] else "mouse" :: rep (n-1);;

let s1 = String.make 5000 ' ' ^ "mouse" ^ String.make 5000 ' ';;
let s2 = String.make 25 ' ' ^ "mouse" ^ String.make 25 ' ';;
let s3 = String.make 500 '0' ^ "0b10010";;
let s4 = String.concat " " (rep 1000);;
let s5 = String.concat " " (rep 10);;
let s6 = String.concat "\\" (rep 1000);;
let s7 = String.concat "\\" (rep 10);;


(* PATTERN MATCHING: *)

(* Test 1.1.
 * Find a word in a big string (10K)
 *)

let test_1_1() =
  let test_1_1_re = regexp "[^ ]+" in
  let _ = search_forward test_1_1_re s1 0 in
  if matched_string s1 <> "mouse" then failwith "Bad result"
;;
  

(* Test 1.2.
 * Find a word in a small string (50 bytes)
 *)

let test_1_2() =
  let test_1_2_re = regexp "[^ ]+" in
  let _ = search_forward test_1_2_re s2 0 in
  if matched_string s2 <> "mouse" then failwith "Bad result"
;;


(* Test 1.3.
 * Backtracking test: Find either hexadecimal, octal, or
 * binary constants in a string of digits
 *)

let test_1_3() =
  let test_1_3_re = regexp "0x[0-9a-f]+\\|0o[0-7]+\\|0b[0-1]+" in
  let _ = search_forward test_1_3_re s3 0 in
  if matched_string s3 <> "0b10010" then failwith "Bad result"
;;



(* Test 2.1:
 * Replace a word in a big string
 *)

let test_2_1() =
  let test_2_1_re = regexp "[^ ]+" in
  let r = global_replace test_2_1_re "cat" s1 in
  if String.sub r 4999 5 <> " cat " then failwith "Bad result"
;;


(* Test 2.2:
 * Replace lots of words in a big string
 *)

let test_2_2() =
  let test_2_2_re = regexp "[^ ]+" in
  let r = global_replace test_2_2_re "cat" s4 in
  if String.sub r (25*4-1) 5 <> " cat " then failwith "Bad result"
;;


(* Test 3.1:
 * Split a big string into space-separated words
 *)

let test_3_1() =
  let r = split_delim (regexp " ") s4 in
  if List.hd r <> "mouse" then failwith "Bad result"
;;

(* Test 3.2:
 * Split a small string into words
 *)


let test_3_2() =
  let r = split_delim (regexp " ") s5 in
  if List.hd r <> "mouse" then failwith "Bad result"
;;


(* Test 4.1:
 * Find a certain substring 
 *)

let test_4_1() =
  let k = search_forward (regexp (quote "mouse")) s1 0 in
  if k <> 5000 then failwith "Bad result"
;;

(* Test 5.1:
 * Unquote backslashes in a big string
 *)

let test_5_1() =
  let s = s6 in
  let r =
    global_substitute 
      (regexp "\\\\.") 
      (fun s ->
	String.make 1 (s.[match_beginning()+1]))
      s in
    if String.sub r 0 10 <> "mousemouse" then failwith "Bad result"
;;


(* Test 5.2:
 * Unquote backslashes in a small string
 *)

let test_5_2() =
  let s = s7 in
  let r =
    global_substitute 
      (regexp "\\\\.") 
      (fun s ->
	String.make 1 (s.[match_beginning()+1]))
      s in
    if String.sub r 0 10 <> "mousemouse" then failwith "Bad result"
;;


(********* invoke tests ************)

invoke test_1_1 "Pattern matching 1" 100 ();
invoke test_1_2 "Pattern matching 2" 10000 ();
invoke test_1_3 "Pattern matching 3" 1000 ();
invoke test_2_1 "Pattern replacing 1" 100 ();
invoke test_2_2 "Pattern replacing 2" 100 ();
invoke test_3_1 "Splitting 1" 100 ();
invoke test_3_2 "Splitting 2" 1000 ();
invoke test_4_1 "Substring searching" 1000 ();
invoke test_5_1 "Unquoting 1" 100 ();
invoke test_5_2 "Unquoting 2" 10000 ();

()
