|
1 | 1 | (* This file is part of Lwt, released under the MIT license. See LICENSE.md for
|
2 | 2 | details, or visit https://github.com/ocsigen/lwt/blob/master/LICENSE.md. *)
|
3 | 3 |
|
4 |
| - |
| 4 | +exception Skip |
5 | 5 |
|
6 | 6 | type test = {
|
7 | 7 | test_name : string;
|
8 | 8 | skip_if_this_is_false : unit -> bool;
|
9 |
| - sequential : bool; |
10 |
| - run : unit -> bool Lwt.t; |
| 9 | + sequential : bool; (* Sequential is ignored in Alcotest *) |
| 10 | + run : [`Lwt of unit -> bool Lwt.t | `Direct of unit -> bool ]; |
11 | 11 | }
|
12 | 12 |
|
| 13 | +let test_direct test_name ?(only_if = fun () -> true) run = |
| 14 | + { test_name; skip_if_this_is_false = only_if; sequential = false; run = `Direct run; } |
| 15 | +
|
| 16 | +let test test_name ?(only_if = fun () -> true) ?(sequential = false) run = |
| 17 | + { test_name; skip_if_this_is_false = only_if; sequential; run = `Lwt run; } |
| 18 | +
|
| 19 | +
|
| 20 | +#if OCAML_VERSION < (4, 05, 0) |
| 21 | +
|
13 | 22 | type outcome =
|
14 | 23 | | Passed
|
15 | 24 | | Failed
|
16 | 25 | | Exception of exn
|
17 | 26 | | Skipped
|
18 | 27 |
|
19 |
| -exception Skip |
20 | 28 | exception Duplicate_Test_Names of string
|
21 | 29 |
|
22 |
| -let test_direct test_name ?(only_if = fun () -> true) run = |
23 |
| - let run = |
24 |
| - fun () -> |
25 |
| - Lwt.return (run ()) |
26 |
| - in |
27 |
| - {test_name; skip_if_this_is_false = only_if; sequential = false; run} |
28 |
| -
|
29 |
| -let test test_name ?(only_if = fun () -> true) ?(sequential = false) run = |
30 |
| - {test_name; skip_if_this_is_false = only_if; sequential; run} |
31 |
| -
|
32 | 30 | module Log =
|
33 | 31 | struct
|
34 | 32 | let log_file =
|
@@ -82,7 +80,9 @@ let run_test : test -> outcome Lwt.t = fun test ->
|
82 | 80 | let test_completion_promise =
|
83 | 81 | Lwt.try_bind
|
84 | 82 | (fun () ->
|
85 |
| - test.run ()) |
| 83 | + match test.run with |
| 84 | + | `Lwt run -> run () |
| 85 | + | `Direct run -> Lwt.return (run ())) |
86 | 86 |
|
87 | 87 | (fun test_did_pass ->
|
88 | 88 | if test_did_pass then
|
@@ -340,6 +340,134 @@ let concurrent library_name suites =
|
340 | 340 | let concurrent library_name suites =
|
341 | 341 | Lwt_main.run (concurrent library_name suites)
|
342 | 342 |
|
| 343 | +#else |
| 344 | +
|
| 345 | +(* Alcotest_lwt 1.5.0 |
| 346 | + * |
| 347 | + * Copyright (c) 2017 Thomas Gazagnaire <[email protected]> |
| 348 | + * |
| 349 | + * Permission to use, copy, modify, and distribute this software for any |
| 350 | + * purpose with or without fee is hereby granted, provided that the above |
| 351 | + * copyright notice and this permission notice appear in all copies. |
| 352 | + * |
| 353 | + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
| 354 | + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
| 355 | + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
| 356 | + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
| 357 | + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
| 358 | + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
| 359 | + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
| 360 | +*) |
| 361 | +
|
| 362 | +module Alcotest_lwt_intf = struct |
| 363 | + module type V1 = sig |
| 364 | + include Alcotest_engine.V1.Cli.S with type return = unit Lwt.t |
| 365 | +
|
| 366 | + val test_case : |
| 367 | + string -> |
| 368 | + Alcotest.speed_level -> |
| 369 | + (Lwt_switch.t -> 'a -> unit Lwt.t) -> |
| 370 | + 'a test_case |
| 371 | +
|
| 372 | + val test_case_sync : |
| 373 | + string -> Alcotest.speed_level -> ('a -> unit) -> 'a test_case |
| 374 | + end |
| 375 | +
|
| 376 | + module type Alcotest_lwt = sig |
| 377 | + include V1 |
| 378 | +
|
| 379 | + (** {1 Versioned APIs} *) |
| 380 | +
|
| 381 | + module V1 : V1 |
| 382 | + (** An alias of the above API that provides a stability guarantees over major |
| 383 | + version changes. *) |
| 384 | + end |
| 385 | +end |
| 386 | +
|
| 387 | +module Alcotest_lwt : sig |
| 388 | + include Alcotest_lwt_intf.Alcotest_lwt |
| 389 | +end = struct |
| 390 | + let run_test fn args = |
| 391 | + let async_ex, async_waker = Lwt.wait () in |
| 392 | + let handle_exn ex = |
| 393 | + Printf.eprintf "Uncaught async exception: %s\n%s" (Printexc.to_string ex) (Printexc.get_backtrace ()); |
| 394 | + if Lwt.state async_ex = Lwt.Sleep then Lwt.wakeup_exn async_waker ex |
| 395 | + in |
| 396 | + Lwt.async_exception_hook := handle_exn; |
| 397 | + Lwt_switch.with_switch (fun sw -> Lwt.pick [ fn sw args; async_ex ]) |
| 398 | +
|
| 399 | + module V1 = struct |
| 400 | + module Tester = Alcotest_engine.V1.Cli.Make (Alcotest.Unix_platform) (Lwt) |
| 401 | + include Tester |
| 402 | +
|
| 403 | + let test_case_sync n s f = test_case n s (fun x -> Lwt.return (f x)) |
| 404 | + let test_case n s f = test_case n s (run_test f) |
| 405 | + end |
| 406 | +
|
| 407 | + include V1 |
| 408 | +end |
| 409 | +
|
| 410 | +
|
| 411 | +module List = struct |
| 412 | + include List |
| 413 | +
|
| 414 | + let filter_map f = |
| 415 | + let rec aux accu = function |
| 416 | + | [] -> rev accu |
| 417 | + | x :: l -> |
| 418 | + match f x with |
| 419 | + | None -> aux accu l |
| 420 | + | Some v -> aux (v :: accu) l |
| 421 | + in |
| 422 | + aux [] |
| 423 | +end |
| 424 | +
|
| 425 | +
|
| 426 | +open Lwt.Infix |
| 427 | +
|
| 428 | +type suite = { |
| 429 | + suite_name : string; |
| 430 | + suite_tests : unit Alcotest_lwt.test_case list; |
| 431 | + skip_suite_if_this_is_false : unit -> bool; |
| 432 | +} |
| 433 | +
|
| 434 | +let suite name ?(only_if = fun () -> true) tests = |
| 435 | + let to_test_case test = |
| 436 | + match test.run with |
| 437 | + | `Lwt run -> |
| 438 | + Alcotest_lwt.test_case test.test_name `Quick (fun _switch () -> |
| 439 | + run () >|= fun b -> |
| 440 | + Alcotest.(check bool) "success" b true) |
| 441 | + | `Direct run -> |
| 442 | + Alcotest_lwt.test_case_sync test.test_name `Quick (fun () -> |
| 443 | + let b = run () in |
| 444 | + Alcotest.(check bool) "success" b true) |
| 445 | + in |
| 446 | + let tests = |
| 447 | + List.filter_map (fun test -> |
| 448 | + if test.skip_if_this_is_false () then |
| 449 | + Some (to_test_case test) |
| 450 | + else None) |
| 451 | + tests |
| 452 | + in |
| 453 | + {suite_name = name; |
| 454 | + suite_tests = tests; |
| 455 | + skip_suite_if_this_is_false = only_if} |
| 456 | +
|
| 457 | +let run library_name suites = |
| 458 | + let tests = |
| 459 | + List.filter_map (fun suite -> |
| 460 | + if suite.skip_suite_if_this_is_false () then |
| 461 | + Some (suite.suite_name, suite.suite_tests) |
| 462 | + else None) |
| 463 | + suites in |
| 464 | + Alcotest_lwt.run library_name tests |
| 465 | +
|
| 466 | +let run library_name suites = Lwt_main.run @@ run library_name suites |
| 467 | +let concurrent = run |
| 468 | +
|
| 469 | +#endif |
| 470 | +
|
343 | 471 | let with_async_exception_hook hook f =
|
344 | 472 | let old_hook = !Lwt.async_exception_hook in
|
345 | 473 | Lwt.async_exception_hook := hook;
|
|
0 commit comments