open Xstr_search
open Xstr_split
open Xstr_match


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 v = var "" in
  let cs = mknegset " " in
  let ml = [ Lazystring; 
	     Record (v,[Anychar_from cs; Anystring_from cs]);
	     Anystring ] in
  let _ = match_string ml s1 in
  if found_string_of_var v <> "mouse" then failwith "Bad result"
;;
  

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

let test_1_2() =
  let v = var "" in
  let cs = mknegset " " in
  let ml = [ Lazystring; 
	     Record (v,[Anychar_from cs; Anystring_from cs]);
	     Anystring ] in
  let _ = match_string ml s2 in
  if found_string_of_var v <> "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 v = var "" in
  let cshex = mkset "0-9a-f" in
  let csoct = mkset "0-7" in
  let csbin = mkset "0-1" in
  let ml = [ Lazystring; 
	     Record (v, [ Alternative
			    [ [ Literal "0x"; 
				Anychar_from cshex; Anystring_from cshex ];
			      [ Literal "0o";
				Anychar_from csoct; Anystring_from csoct ];
			      [ Literal "0b";
				Anychar_from csbin; Anystring_from csbin ] ]]);
	   ] in
			      
  let _ = match_string ml s3 in
  if found_string_of_var v <> "0b10010" then failwith "Bad result"
;;
  



(* REPLACE PATTERNS *)

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

let test_2_1() =
  let s1 = String.make 5000 ' ' ^ "mouse" ^ String.make 5000 ' ' in
  let cs = mknegset " " in
  let ml = [ Anychar_from cs; Anystring_from cs ] in
  let (r,_) = replace_matched_substrings ml [ ReplaceLiteral "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 cs = mknegset " " in
  let ml = [ Anychar_from cs; Anystring_from cs ] in
  let (r,_) = replace_matched_substrings ml [ ReplaceLiteral "cat" ] [] s4 in
  if String.sub r (25*4-1) 5 <> " cat " then failwith "Bad result"
;;



(* SPLITTING *)


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

let test_3_1() =
  let r = split_string "" false false [" "] 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_string "" false false [" "] s5 in
  if List.hd r <> "mouse" then failwith "Bad result"
;;

(* SUBSTRING SEARCHING *)

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

let test_4_1() =
  let k = index_of_substring s1 "mouse" in
  if k <> 5000 then failwith "Bad result"
;;


(* CHARCTER REPLACING *)

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

let test_5_1() =
  let s = s6 in
  let l = String.length s in
  let r =
    replace_char 
      s 
      (fun c k ->
	match c with
	  '\\' -> 
	    begin
	      if k+1 < l then 
		raise (Replace_phrase (2, String.make 1 (s.[k+1])))
	      else
		raise Not_found
	    end)
  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 l = String.length s in
  let r =
    replace_char 
      s 
      (fun c k ->
	match c with
	  '\\' -> 
	    begin
	      if k+1 < l then 
		raise (Replace_phrase (2, String.make 1 (s.[k+1])))
	      else
		raise Not_found
	    end)
  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 ();


()
