(* $Id: test-charEncoding.ml,v 1.8 2006/08/13 21:23:08 yori Exp $ *)
(* Copyright 2010 Yamagata Yoriyuki *)
(* Flush test *)

open Printf
open Blender
open Camomile
open OOChannel

class buffer_io b =
  object
    method flush () = ()
    method close_out () = ()

    method output s pos len =
      Buffer.add_subbytes b s pos len;
      len

    method contents = Buffer.contents b
  end

let () =
  test ~desc:"Output Test" ~body:(fun () ->
      expect_pass ~body:(fun () ->
          let b = Buffer.create 0 in
          let bio = new buffer_io b in
          let c = new char_obj_output_channel_of (bio :> char_output_channel) in
          let c = new char_output_channel_of c in
          let put c s =
            ignore (c#output (Bytes.of_string s) 0 (String.length s))
          in
          put c "---------------\n";
          c#flush ();
          put c "1 first line  1\n";
          c#flush ();
          put c "2 second line 2\n";
          c#flush ();
          put c "3 third line  3\n";
          c#flush ();
          c#flush ();
          c#flush ();
          c#flush ();
          expect_equal
            ~msg:(lazy (sprintf "output %s\n" bio#contents))
            (Buffer.contents b)
            "---------------\n\
             1 first line  1\n\
             2 second line 2\n\
             3 third line  3\n"))

let text =
  "---------------\n1 first line  1\n2 second line 2\n3 third line  3\n"

let () =
  test ~desc:"channel_of_stream test" ~body:(fun () ->
      expect_pass ~body:(fun () ->
          let s = Stream.of_string text in
          let c = new channel_of_stream s in
          let b = Buffer.create 0 in
          (try
             while true do
               Buffer.add_char b (c#get ())
             done
           with End_of_file -> ());
          expect_equal
            ~msg:(lazy (sprintf "output differ"))
            (Buffer.contents b) text))

class otext =
  object
    val mutable counter = 0
    method close_in () = ()

    method get () =
      if counter >= String.length text then raise End_of_file
      else begin
        let v = text.[counter] in
        counter <- counter + 1;
        v
      end
  end

let () =
  test ~desc:"stream_of_channel test" ~body:(fun () ->
      expect_pass ~body:(fun () ->
          let s = stream_of_channel (new otext) in
          let b = Buffer.create 0 in
          Stream.iter (Buffer.add_char b) s;
          expect_equal
            ~msg:(lazy (sprintf "output differ"))
            (Buffer.contents b) text))

let () =
  test ~desc:"char_input_channel_of test" ~body:(fun () ->
      expect_pass ~body:(fun () ->
          let occ = new char_input_channel_of (new otext) in
          let b = Bytes.create (String.length text) in
          let n = occ#input b 0 (String.length text) in
          expect_equal
            ~msg:
              (lazy (sprintf "length %d should be %d" n (String.length text)))
            n (String.length text);
          expect_equal ~msg:(lazy "output differ") (Bytes.to_string b) text;
          expect_equal_app
            ~msg:(lazy "EOF")
            (fun () -> raise End_of_file)
            () (occ#input b 0) 1))

class otext_char =
  object
    val mutable counter = 0
    method close_in () = ()

    method input s p len =
      if counter >= String.length text then raise End_of_file
      else (
        let len' = String.length text - counter in
        let len = min len' len in
        String.blit text counter s p len;
        counter <- counter + len;
        len)
  end

let () =
  test ~desc:"char_obj_input_channel_of test" ~body:(fun () ->
      expect_pass ~body:(fun () ->
          let occ = new char_obj_input_channel_of (new otext_char) in
          let b = Buffer.create 0 in
          (try
             while true do
               Buffer.add_char b (occ#get ())
             done
           with End_of_file -> ());
          expect_equal
            ~msg:(lazy (sprintf "output differ"))
            (Buffer.contents b) text))

let () = Blender.main ()
