(Test_pipeline : TEST_PIPELINE) = struct

  let write_file file ~content =
    let out_file = open_out file in
    try
      output_string out_file content;
      close_out out_file
    with _ ->
      close_out out_file

  let cmdf fmt =
    ksprintf (fun s ->
        printf "CMD: %s\n%!" s;
        match Sys.command s with
        | 0 -> ()
        | other -> ksprintf failwith "non-zero-exit: %s -> %d" s other) fmt

  let (//) = Filename.concat
  let test_dir = "_build/ttfi-test-results/"

  let main prefix =
    let start_time = Unix.gettimeofday () in
    cmdf "mkdir -p %s" test_dir;
    let results = ref [] in
    let add_result fmt = ksprintf (fun s -> results := s :: !results) fmt in
    let add_result_file name path =
      let size =
        let s = Unix.stat path  in
        match s.Unix.st_size with
        | 0 -> "EMPTY"
        | small when small < 1024 -> sprintf "%d B" small
        | avg when avg < (1024 * 1024) ->
          sprintf "%.2f KB" (float avg /. 1024.)
        | big ->
          sprintf "%.2f MB" (float big /. (1024. *. 1024.))
      in
      add_result "%s: `%s` (%s)" name path size;
    in
    let output_path suffix = test_dir // prefix ^ suffix in
    begin
      let module Display_pipeline = Test_pipeline(Biokepi.EDSL.Compile.To_displayin
      let pseudocode = output_path "-pseudocode.txt" in
      write_file pseudocode
        ~content:(Display_pipeline.run () |> SmartPrint.to_string 80 2);
      add_result_file "Pseudo-code" pseudocode;
    end;
    begin
      let module Jsonize_pipeline =
        Test_pipeline(Biokepi.EDSL.Compile.To_jsonin
      let json = output_path ".json" in
      write_file json
        ~content:(Jsonize_pipeline.run ()
                  |> Yojson.Basic.pretty_to_string ~std:true);
      add_result_file "JSON" json;
    end;
    let output_dot sm dot png =
      try
        let out = open_out dot in
        SmartPrint.to_out_channel  80 2 out sm;
        close_out out;
        add_result_file "DOT" dot;
        let dotlog = png ^ ".log" in
        cmdf "dot -v -x -Tpng  %s -o %s > %s 2>&1" dot png dotlog;
        add_result_file "PNG" png;
      with e ->
        add_result "FAILED TO OUTPUT: %s (%s)" dot (Printexc.to_string e);
    in
    begin
      let module Dotize_pipeline = Test_pipeline(Biokepi.EDSL.Compile.To_dotin
      let sm_dot = Dotize_pipeline.run () in
      let dot = output_path "-1.dot" in
      let png = output_path "-1.png" in
      output_dot sm_dot dot png
    end;
    begin
      let module Dotize_twice_beta_reduced_pipeline =
        Test_pipeline(
          Biokepi.EDSL.Transform.Apply_functions(
            Biokepi.EDSL.Transform.Apply_functions(
              Biokepi.EDSL.Compile.To_dot
            )
          )
        )
      in
      let dot = output_path "-double-beta.dot" in
      let sm_dot = Dotize_twice_beta_reduced_pipeline.run () in
      let png = output_path "-double-beta.png" in
      output_dot sm_dot dot png
    end;
    begin
      let module Workflow_compiler =
        Biokepi.EDSL.Compile.To_workflow.Make(struct
          include Biokepi.EDSL.Compile.To_workflow.Defaults
          let processors = 42
          let work_dir = "/work/dir/"
          let machine =
            Biokepi.Setup.Build_machine.create
              "ssh://example.com/tmp/KT/"
        end)
      in
      let module Ketrew_pipeline = Test_pipeline(Workflow_compilerin
      let workflow =
        Ketrew_pipeline.run ()
        |> Biokepi.EDSL.Compile.To_workflow.File_type_specification.get_unit_workflow
          ~name:"Biokepi TTFI test top-level node"
      in
      ignore workflow
    end;
    let end_time = Unix.gettimeofday () in
    add_result "Total-time: %.2f s" (end_time -. start_time);
    List.rev !results

end