File: test_helpers.ml

package info (click to toggle)
ocaml-obuild 0.2.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,456 kB
  • sloc: ml: 14,491; sh: 211; ansic: 34; makefile: 11
file content (173 lines) | stat: -rw-r--r-- 6,184 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
open Test_framework
open Printf

(** Test helpers for parser testing *)

(** {1 META Parser Helpers} *)

let parse_meta_string content name =
  Meta.parse (Filepath.fp name) content name

let assert_meta_parses ~content ~name =
  try
    let _ = parse_meta_string content name in
    Success
  with exn ->
    TestFailure (sprintf "META parsing failed: %s\nInput:\n%s"
             (Printexc.to_string exn) content)

let assert_meta_parse_error ~content ~expected_msg ~name =
  try
    let _ = parse_meta_string content name in
    TestFailure (sprintf "Expected META parse error, but parsing succeeded.\nInput:\n%s" content)
  with
  | Meta.MetaParseError (_, msg) ->
      assert_string_contains ~haystack:msg ~needle:expected_msg ~name
  | exn ->
      TestFailure (sprintf "Expected MetaParseError containing '%s', got: %s"
               expected_msg (Printexc.to_string exn))

let assert_meta_field ~content ~pkg_name ~field_name ~expected_value ~test_name =
  try
    let pkg = parse_meta_string content pkg_name in
    let actual = match field_name with
      | "version" -> pkg.Meta.Pkg.version
      | "description" -> pkg.Meta.Pkg.description
      | "directory" -> pkg.Meta.Pkg.directory
      | _ -> failwith ("Unknown field: " ^ field_name)
    in
    assert_equal ~expected:expected_value ~actual ~name:test_name
  with exn ->
    TestFailure (sprintf "Failed to get field '%s': %s" field_name (Printexc.to_string exn))

(** {1 Expression Parser Helpers} *)

let parse_expr_string name expr_str =
  Expr.parse name expr_str

let assert_expr_parses ~content ~name =
  try
    let _ = parse_expr_string name content in
    Success
  with exn ->
    TestFailure (sprintf "Expression parsing failed: %s\nInput: %s"
             (Printexc.to_string exn) content)

let assert_expr_parse_error ~content ~expected_msg ~name =
  try
    let _ = parse_expr_string name content in
    TestFailure (sprintf "Expected expression parse error, but parsing succeeded.\nInput: %s" content)
  with
  | Expr.CannotParseConstraints (_, msg) ->
      assert_string_contains ~haystack:msg ~needle:expected_msg ~name
  | exn ->
      TestFailure (sprintf "Expected CannotParseConstraints containing '%s', got: %s"
               expected_msg (Printexc.to_string exn))

let assert_expr_eval ~expr ~version ~expected ~name =
  match expr with
  | None ->
      if expected then Success
      else TestFailure "Expression is None but expected to evaluate to false"
  | Some e ->
      let actual = Expr.eval version e in
      if actual = expected then Success
      else TestFailure (sprintf "Expected %b, got %b for version %s" expected actual version)

(** {1 Project Parser Helpers} *)

(* Note: Project parser needs special handling because it reads from files.
   We'll create temporary files for testing. *)

let with_temp_project_file content test_func =
  (* Use a unique temp directory so findPath() sees exactly one .obuild file *)
  let temp_base = Filename.temp_file "test_project_dir" "" in
  Sys.remove temp_base;
  Unix.mkdir temp_base 0o700;
  let temp_file = Filename.concat temp_base "test.obuild" in
  let old_dir = Sys.getcwd () in
  try
    let oc = open_out temp_file in
    output_string oc content;
    close_out oc;
    Sys.chdir temp_base;
    let result = test_func () in
    Sys.chdir old_dir;
    Sys.remove temp_file;
    Unix.rmdir temp_base;
    result
  with exn ->
    (try Sys.chdir old_dir with _ -> ());
    (try Sys.remove temp_file with _ -> ());
    (try Unix.rmdir temp_base with _ -> ());
    raise exn

let assert_project_parses ~content ~name =
  try
    with_temp_project_file content (fun () ->
      let _ = Project_read.read () in
      Success)
  with exn ->
    TestFailure (sprintf "Project parsing failed: %s\nInput:\n%s"
             (Printexc.to_string exn) content)

let assert_project_parse_error ~content ~expected_msg ~name =
  try
    with_temp_project_file content (fun () ->
      let _ = Project_read.read () in
      TestFailure (sprintf "Expected project parse error, but parsing succeeded.\nInput:\n%s" content))
  with
  | Project.MissingField field ->
      assert_string_contains ~haystack:("Missing field: " ^ field) ~needle:expected_msg ~name
  | Project.InvalidConfFile msg ->
      assert_string_contains ~haystack:msg ~needle:expected_msg ~name
  | Project.BlockSectionAsValue field ->
      assert_string_contains ~haystack:("Block section as value: " ^ field) ~needle:expected_msg ~name
  | exn ->
      let msg = Printexc.to_string exn in
      assert_string_contains ~haystack:msg ~needle:expected_msg ~name

(** {1 Libname Helpers} *)

let assert_libname_parse ~input ~expected_main ~expected_subs ~name =
  try
    let libname = Libname.of_string input in
    let main_ok = libname.Libname.main_name = expected_main in
    let subs_ok = libname.Libname.subnames = expected_subs in
    if main_ok && subs_ok then Success
    else
      TestFailure (sprintf "Libname parse mismatch.\nExpected: %s.%s\nGot: %s.%s"
               expected_main (String.concat "." expected_subs)
               libname.Libname.main_name (String.concat "." libname.Libname.subnames))
  with exn ->
    TestFailure (sprintf "Libname parsing failed: %s" (Printexc.to_string exn))

(** {1 Common Test Data} *)

(** Minimal valid META file *)
let minimal_meta = "\
version = \"1.0.0\"\n\
description = \"Test package\"\n"

(** Minimal valid .obuild file *)
let minimal_project = "\
name: test\n\
version: 1.0.0\n\
obuild-ver: 1\n"

(** Complete example META file *)
let example_meta = "\
version = \"2.0.0\"\n\
description = \"Example package with all features\"\n\
requires = \"unix, str\"\n\
directory = \"^\"\n\
archive(byte) = \"example.cma\"\n\
archive(native) = \"example.cmxa\"\n\
archive(byte,mt) = \"example_mt.cma\"\n\
package \"sub\" (\n\
  description = \"Subpackage\"\n\
  archive(byte) = \"sub.cma\"\n\
)\n"

(** Complete example .obuild file *)
let example_project = "name = example\nversion = 2.0.0\nobuild-ver = 1\nsynopsis = \"An example project\"\ndescription = \"This is a complete example project\"\n\nlibrary mylib\n  modules: Foo, Bar\n  build-deps: unix\n\nexecutable myexe\n  main-is: main.ml\n  build-deps: mylib\n"