-
Notifications
You must be signed in to change notification settings - Fork 71
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
1654f56
commit 26f14f7
Showing
8 changed files
with
293 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
; We compile by hand because dune is a little broken w.r.t to | ||
; separate compilation, js_of_ocaml and effects. | ||
(executable | ||
(name index) | ||
(modes js) | ||
(js_of_ocaml (flags --target-env=nodejs --enable=effects --debug-info --source-map --pretty)) | ||
(libraries eio_browser)) | ||
|
||
(rule | ||
(alias default) | ||
(deps index.html index.bc.js) | ||
(targets index.js) | ||
(action (copy index.bc.js index.js))) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8"> | ||
<meta http-equiv="X-UA-Compatible" content="IE=edge"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
<title>Eio in the Browser</title> | ||
</head> | ||
<body> | ||
<div id="counter"></div> | ||
<textarea name="text" id="text" cols="30" rows="10"></textarea> | ||
<div id="output"></div> | ||
<script src="index.js"></script> | ||
</body> | ||
</html> |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,17 @@ | ||
; We compile by hand because dune is a little broken w.r.t to | ||
; separate compilation, js_of_ocaml and effects. | ||
(library | ||
(name eio_test) | ||
(modules eio_test) | ||
(libraries eio alcotest)) | ||
|
||
(executable | ||
(name index) | ||
(name test) | ||
(modules test) | ||
(modes js) | ||
(js_of_ocaml (flags --target-env=nodejs --enable=effects --debug-info --source-map --pretty)) | ||
(libraries eio_browser)) | ||
(js_of_ocaml (flags --target-env=nodejs --enable=effects --setenv=ALCOTEST_COLOR=always)) | ||
(libraries alcotest ansi eio_test eio_browser)) | ||
|
||
(rule | ||
(alias default) | ||
(deps index.html index.bc.js) | ||
(targets index.js) | ||
(action (copy index.bc.js index.js))) | ||
(deps index.html test.bc.js) | ||
(targets test.js) | ||
(action (copy test.bc.js test.js))) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
open Eio | ||
|
||
(* Filesystem tests *) | ||
module Fs = struct | ||
let ( / ) = Path.(/) | ||
let test_read_write env () = | ||
let test_file = "test.txt" in | ||
let text = "abcdefgh" in | ||
let len = String.length text in | ||
let _write = | ||
Path.with_open_out ~create:(`If_missing 0o644) (env#fs / test_file) @@ fun sink -> | ||
Flow.copy_string text sink | ||
in | ||
let buf = Cstruct.create len in | ||
let _read = | ||
Path.with_open_in (env#fs / test_file) @@ fun source -> | ||
Flow.read_exact source buf | ||
in | ||
Path.unlink (env#fs / test_file); | ||
Alcotest.(check string) "same string" text (Cstruct.to_string buf) | ||
|
||
let test_append env () = | ||
let test_file = "test.txt" in | ||
let text = "abcdefgh" in | ||
let len = String.length text in | ||
let _write = | ||
Path.with_open_out ~create:(`If_missing 0o644) (env#fs / test_file) @@ fun sink -> | ||
Flow.copy_string text sink | ||
in | ||
let _write2 = | ||
Path.with_open_out ~append:true ~create:(`If_missing 0o644) (env#fs / test_file) @@ fun sink -> | ||
Flow.copy_string text sink | ||
in | ||
let buf = Cstruct.create (2 * len) in | ||
let _read = | ||
Path.with_open_in (env#fs / test_file) @@ fun source -> | ||
Flow.read_exact source buf | ||
in | ||
Path.unlink (env#fs / test_file); | ||
Alcotest.(check string) "same string" (text ^ text) (Cstruct.to_string buf) | ||
|
||
let optint_int63 = Alcotest.testable Optint.Int63.pp Optint.Int63.equal | ||
|
||
let test_fails_if_exists env () = | ||
let test_file = "./test.txt" in | ||
let text = "abcdefgh" in | ||
let _write = | ||
Path.with_open_out ~create:(`If_missing 0o644) (env#fs / test_file) @@ fun sink -> | ||
Flow.copy_string text sink | ||
in | ||
Fun.protect | ||
(fun () -> | ||
try | ||
Path.with_open_out ~create:(`Exclusive 0o644) (env#fs / test_file) @@ fun _ -> | ||
Alcotest.failf "Expected to fail with already exists" | ||
with | ||
| Eio.Exn.Io (Eio.Fs.E (Fs.Already_exists _), _) -> () | ||
| exn -> Alcotest.failf "Expected already exists exception, got: %a" Fmt.exn exn | ||
) ~finally:(fun () -> Path.unlink (env#fs / test_file)) | ||
|
||
let test_read_write env () = | ||
let test_file = "test.txt" in | ||
let text = "abcdefgh" in | ||
let len = String.length text in | ||
let _write = | ||
Path.with_open_out ~create:(`If_missing 0o644) (env#fs / test_file) @@ fun sink -> | ||
Flow.copy_string text sink | ||
in | ||
let stat = | ||
Eio.Switch.run @@ fun sw -> | ||
let fd = Path.open_in ~sw (env#fs / test_file) in | ||
File.stat fd | ||
in | ||
let is_file = stat.kind = `Regular_file in | ||
Alcotest.(check bool) "is file" true is_file; | ||
Alcotest.(check optint_int63) "same size" (Optint.Int63.of_int len) stat.size; | ||
Path.unlink (env#fs / test_file) | ||
|
||
let tests env = [ | ||
Alcotest.test_case "read and write" `Quick (test_read_write env); | ||
Alcotest.test_case "append" `Quick (test_append env); | ||
Alcotest.test_case "fail if exists" `Quick (test_fails_if_exists env); | ||
Alcotest.test_case "fstat" `Quick (test_fails_if_exists env); | ||
] | ||
end | ||
|
||
module Fibers = struct | ||
let test_yield () = | ||
let expect = [1; 2] in | ||
let res = ref [] in | ||
Fiber.both | ||
(fun () -> Fiber.yield (); res := 1 :: !res) | ||
(fun () -> res := 2 :: !res); | ||
Alcotest.(check (list int)) "same list" expect !res | ||
|
||
let test_simple_cancel () = | ||
let res = | ||
Fiber.first | ||
(fun () -> "a") | ||
(fun () -> Fiber.yield (); failwith "b crashed") | ||
in | ||
Alcotest.(check string) "same string" "a" res; | ||
let p, _r = Promise.create () in | ||
let res = Fiber.first | ||
(fun () -> "a") | ||
(fun () -> Promise.await p) | ||
in | ||
Alcotest.(check string) "promise cancelled" "a" res | ||
|
||
|
||
let tests = [ | ||
Alcotest.test_case "yielding" `Quick test_yield; | ||
Alcotest.test_case "fiber first cancel" `Quick test_simple_cancel; | ||
] | ||
end | ||
|
||
module Stream = struct | ||
type op = [ `Add of int | `Take of int ] | ||
|
||
let pp_op ppf = function | ||
| `Add i -> Fmt.pf ppf "add %i" i | ||
| `Take i -> Fmt.pf ppf "take %i" i | ||
|
||
let op = Alcotest.of_pp pp_op | ||
|
||
let test_stream () = | ||
let l = ref [] in | ||
let add s v = | ||
Stream.add s v; | ||
l := (`Add v) :: !l | ||
in | ||
let take s = | ||
l := (`Take (Stream.take s)) :: !l | ||
in | ||
let t = Stream.create 3 in | ||
add t 1; | ||
Fiber.both | ||
(fun () -> | ||
add t 2; | ||
add t 3; | ||
add t 4; | ||
) | ||
(fun () -> | ||
take t; | ||
take t; | ||
take t; | ||
take t | ||
); | ||
let actual = List.rev !l in | ||
let expected = [ `Add 1; `Add 2; `Add 3; `Take 1; `Take 2; `Take 3; `Take 4; `Add 4 ] in | ||
Alcotest.(check (list op)) "same sequence" expected actual | ||
|
||
let tests = [ | ||
Alcotest.test_case "stream1" `Quick test_stream | ||
] | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
(* Avoiding dependency on js_of_ocaml *) | ||
external set_channel_output' : | ||
out_channel -> Jv.t -> unit | ||
= "caml_ml_set_channel_output" | ||
|
||
let set_channel_flusher (out_channel : out_channel) (f : string -> unit) = | ||
let f' = | ||
Jv.callback ~arity:1 (fun s -> f (Jstr.binary_to_octets s)) | ||
in | ||
set_channel_output' out_channel f' | ||
|
||
let init () = | ||
let open Brr in | ||
let parser = Ansi.create () in | ||
let output = | ||
let out = El.div [ El.h1 [ El.txt' "Eio_browser" ] ] in | ||
El.set_at (Jstr.v "style") | ||
(Some | ||
(Jstr.v | ||
"font-family: monospace; color: #e8e8e8; background: #131212; \ | ||
padding: 2em;")) | ||
out; | ||
El.(set_prop Prop.id (Jstr.v "output") out); | ||
let style = El.style [ El.txt' Ansi.css ] in | ||
El.append_children (Document.body G.document) [ style; out ]; | ||
out | ||
in | ||
let get_or_make name = | ||
match Document.find_el_by_id G.document (Jstr.v name) with | ||
| Some v -> v | ||
| None -> | ||
let d = El.div [] in | ||
El.append_children output [ d ]; | ||
El.(set_prop Prop.id (Jstr.v name) d); | ||
d | ||
in | ||
let append name s = | ||
Brr.Console.log [ s ]; | ||
let s = Ansi.process parser s in | ||
let p = El.pre [] in | ||
El.to_jv p |> fun jv -> | ||
Jv.set jv "innerHTML" (Jv.of_string s); | ||
El.append_children (get_or_make name) [ p ] | ||
in | ||
set_channel_flusher stdout (fun content -> append "stdout" content); | ||
set_channel_flusher stderr (fun content -> append "stderr" content); | ||
() | ||
|
||
module Browser_tests = struct | ||
open Eio | ||
|
||
let test_timeout_cancel () = | ||
let v = | ||
Fiber.first | ||
(fun () -> Eio_browser.Timeout.sleep ~ms:5000; "A") | ||
(fun () -> "B") | ||
in | ||
Alcotest.(check string) "timeout cancelled" "B" v | ||
|
||
let test_fut_cancel () = | ||
let p, _ = Fut.create () in | ||
let v = | ||
Fiber.first | ||
(fun () -> Eio_browser.await p; "A") | ||
(fun () -> "B") | ||
in | ||
Alcotest.(check string) "fut cancelled" "B" v | ||
|
||
let tests = [ | ||
Alcotest.test_case "timeout cancelled" `Quick test_timeout_cancel; | ||
Alcotest.test_case "fut cancelled" `Quick test_fut_cancel | ||
] | ||
end | ||
|
||
|
||
let () = | ||
init (); | ||
let main = | ||
Eio_browser.run @@ fun env -> | ||
try Alcotest.run "eio" [ | ||
"fibers", Eio_test.Fibers.tests; | ||
"stream", Eio_test.Stream.tests; | ||
"browser", Browser_tests.tests | ||
] with Exit -> () | ||
in | ||
Fut.await main (fun () -> ()) |