mirror of
https://github.com/c-cube/nanoev.git
synced 2025-12-06 11:15:48 -05:00
basic tests for CPS
This commit is contained in:
parent
dba25e6c00
commit
2713f92dcf
2 changed files with 109 additions and 0 deletions
4
tests/cps/dune
Normal file
4
tests/cps/dune
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
|
||||||
|
(tests
|
||||||
|
(names t_readline)
|
||||||
|
(libraries nanoev.cps))
|
||||||
105
tests/cps/t_readline.ml
Normal file
105
tests/cps/t_readline.ml
Normal file
|
|
@ -0,0 +1,105 @@
|
||||||
|
module CPS = Nanoev_cps
|
||||||
|
|
||||||
|
let spf = Printf.sprintf
|
||||||
|
let pf = Printf.printf
|
||||||
|
|
||||||
|
module St = struct
|
||||||
|
type t = {
|
||||||
|
mutable bs: bytes;
|
||||||
|
mutable len: int;
|
||||||
|
}
|
||||||
|
|
||||||
|
let create () : t = { bs = Bytes.create 32; len = 0 }
|
||||||
|
|
||||||
|
let add_bytes (self : t) buf i len : unit =
|
||||||
|
if Bytes.length self.bs < len + self.len then (
|
||||||
|
let new_bs = Bytes.create (max (self.len * 2) (self.len + len + 2)) in
|
||||||
|
Bytes.blit self.bs 0 new_bs 0 self.len;
|
||||||
|
self.bs <- new_bs
|
||||||
|
);
|
||||||
|
assert (self.len + len <= Bytes.length self.bs);
|
||||||
|
Bytes.blit buf i self.bs self.len len;
|
||||||
|
self.len <- self.len + len
|
||||||
|
|
||||||
|
let shift_left (self : t) n =
|
||||||
|
if n = self.len then
|
||||||
|
self.len <- 0
|
||||||
|
else (
|
||||||
|
Bytes.blit self.bs n self.bs 0 (self.len - n);
|
||||||
|
self.len <- self.len - n
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
open struct
|
||||||
|
exception Found of int
|
||||||
|
end
|
||||||
|
|
||||||
|
type input =
|
||||||
|
[ `End_of_input
|
||||||
|
| `Input of bytes * int * int
|
||||||
|
]
|
||||||
|
|
||||||
|
let readline () : ([ `Yield of string ], input, unit, CPS.void) CPS.t =
|
||||||
|
let self = St.create () in
|
||||||
|
CPS.create_rec @@ fun ~aq ~recurse ->
|
||||||
|
match
|
||||||
|
for i = 0 to self.len - 1 do
|
||||||
|
if Bytes.get self.bs i = '\n' then raise_notrace (Found i)
|
||||||
|
done
|
||||||
|
with
|
||||||
|
| () ->
|
||||||
|
CPS.await @@ fun input ->
|
||||||
|
(match input with
|
||||||
|
| `End_of_input when self.len = 0 -> CPS.return ()
|
||||||
|
| `End_of_input ->
|
||||||
|
let line = Bytes.sub_string self.bs 0 self.len in
|
||||||
|
St.shift_left self self.len;
|
||||||
|
CPS.perform ~aq (`Yield line);
|
||||||
|
CPS.return ()
|
||||||
|
| `Input (buf, i, len) ->
|
||||||
|
St.add_bytes self buf i len;
|
||||||
|
recurse ())
|
||||||
|
| exception Found i ->
|
||||||
|
let line = Bytes.sub_string self.bs 0 i in
|
||||||
|
St.shift_left self (i + 1);
|
||||||
|
CPS.perform ~aq (`Yield line);
|
||||||
|
recurse ()
|
||||||
|
|
||||||
|
let test (inputs : string list) =
|
||||||
|
pf "## test on [%s]\n%!" (String.concat ";" @@ List.map (spf "%S") inputs);
|
||||||
|
|
||||||
|
let inputs = Queue.of_seq @@ List.to_seq inputs in
|
||||||
|
let rd = readline () in
|
||||||
|
|
||||||
|
let work () =
|
||||||
|
(match CPS.work rd with
|
||||||
|
| Ok () -> pf "done\n"
|
||||||
|
| Error _ -> .
|
||||||
|
| Working -> ());
|
||||||
|
CPS.pop_actions rd (function `Yield line -> pf "yielded line %S\n%!" line)
|
||||||
|
in
|
||||||
|
|
||||||
|
work ();
|
||||||
|
while not (Queue.is_empty inputs) do
|
||||||
|
let s = Queue.pop inputs in
|
||||||
|
pf "feed input %S\n%!" s;
|
||||||
|
CPS.add_input rd (`Input (Bytes.of_string s, 0, String.length s));
|
||||||
|
work ()
|
||||||
|
done;
|
||||||
|
CPS.add_input rd `End_of_input;
|
||||||
|
work ();
|
||||||
|
|
||||||
|
pf "## end test\n"
|
||||||
|
|
||||||
|
let () =
|
||||||
|
test [ "hello\nwor"; "ld\n\n123\n" ];
|
||||||
|
test
|
||||||
|
[
|
||||||
|
"a very very long";
|
||||||
|
" line over here, wow, ";
|
||||||
|
"damn!\noh well\n";
|
||||||
|
"\nanother ";
|
||||||
|
"one?\n";
|
||||||
|
"all done\n";
|
||||||
|
];
|
||||||
|
()
|
||||||
Loading…
Add table
Reference in a new issue