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"
|