(* Tests for UTF16 *)
open CamomileLibraryTest.Camomile
open UPervasives
open Blender
open Bigarray

module UTF16Conv = CharEncoding.Make (UTF16)
module UTF16Test = UStorageTest.Make (UTF16)

let char_gen _ =
  let n = match Random.int 3 with
      0 -> Random.int 0xd800
    | 1 -> 0xe000 + Random.int (0xfffe - 0xe000)
    | 2 -> 0x10000 + Random.int (0x110000 - 0x10000)
    | _ -> assert false in
  uchar_of_int n

let _ = UTF16Test.test ~desc:"UTF16 test" ~log:"base_utf16" ~char_gen ()

let string_of_int16array a =
  let s = Bytes.create (2 + 2 * Bigarray.Array1.dim a) in
  Bytes.set s 0 (Char.chr 0xfe); Bytes.set s 1 (Char.chr 0xff);
  for i = 0 to Bigarray.Array1.dim a - 1 do
    Bytes.set s (2 * i + 2) (Char.chr (a.{i} lsr 8));
    Bytes.set s (2 * i + 3) (Char.chr (a.{i} land 255))
  done;
  Bytes.to_string s

let _ = random_test
    ~desc:"UTF16 validate"
    ~log:"base_utf16_validate"
    ~data:(fun size -> Array.init size char_gen)
    ~body:(fun a -> expect_pass ~body:(fun () ->
        let s = UTF16.init (Array.length a) (fun i -> a.(i)) in
        let s' = UTF16Conv.encode CharEncoding.utf16be s in
        expect_true (s' = string_of_int16array s);
        (*      UTF16.validate s *)
        expect_equal_app UTF16.validate s (fun () -> ()) ()))

let _ = test ~desc:"Malformed utf16 1" ~body:(fun () ->
    expect_pass ~body:(fun () ->
        let a = Array1.create int16_unsigned c_layout 2 in
        a.{0} <- 0xdc01; a.{1} <- 0xd801;
        expect_equal_app 
          UTF16.validate a (fun _ -> raise UTF16.Malformed_code) ()))

let _ = test ~desc:"Malformed utf16 2" ~body:(fun () ->
    expect_pass ~body:(fun () ->
        let a = Array1.create int16_unsigned c_layout 2 in
        a.{0} <- 0xd801; a.{1} <- 0x0300;
        expect_equal_app 
          UTF16.validate a (fun _ -> raise UTF16.Malformed_code) ()))

let _ = test ~desc:"Malformed utf16 3" ~body:(fun () ->
    expect_pass ~body:(fun () ->
        let a = Array1.create int16_unsigned c_layout 2 in
        a.{0} <- 0xfffe; a.{1} <- 0xfeff;
        expect_equal_app 
          UTF16.validate a (fun _ -> raise UTF16.Malformed_code) ()))

let _ = test ~desc:"Out_of_range  utf16 1" ~body:(fun () ->
    expect_pass ~body:(fun () ->
        expect_equal_app
          (UTF16.init 1) (fun _ -> uchar_of_int 0xd801)
          (fun _ -> raise UTF16.Out_of_range) ()))

let _ = test ~desc:"Out_of_range  utf16 2" ~body:(fun () ->
    expect_pass ~body:(fun () ->
        expect_equal_app
          (UTF16.init 1) (fun _ -> uchar_of_int 0xdfff)
          (fun _ -> raise UTF16.Out_of_range) ()))

let _ = test ~desc:"Out_of_range  utf16 3" ~body:(fun () ->
    expect_pass ~body:(fun () ->
        expect_equal_app
          (UTF16.init 1) (fun _ -> uchar_of_int 0xfffe)
          (fun _ -> raise UTF16.Out_of_range) ()))

let _ = test ~desc:"Out_of_range  utf16 1" ~body:(fun () ->
    expect_pass ~body:(fun () ->
        expect_equal_app
          (UTF16.init 1) (fun _ -> uchar_of_int 0x4fffffff)
          (fun _ -> raise UTF16.Out_of_range) ()))
