basic architecture for the doc tests

This commit is contained in:
Lesenechal Remi 2019-12-23 15:18:32 +01:00
parent 2bff4eef6a
commit 08471ba246
9 changed files with 242 additions and 56 deletions

5
.gitignore vendored
View File

@ -8,7 +8,6 @@ Version.ml
**/.DS_Store **/.DS_Store
.vscode/ .vscode/
/ligo.install /ligo.install
*.coverage
/_coverage/ /_coverage/
/_coverage_all/ /_coverage_*/
/_coverage_ligo/
/_coverage_cli/

View File

@ -45,9 +45,12 @@ coverage-ligo: clean
bisect-ppx-report html -o ./_coverage_ligo --title="LIGO test coverage" bisect-ppx-report html -o ./_coverage_ligo --title="LIGO test coverage"
bisect-ppx-report summary --per-file bisect-ppx-report summary --per-file
coverage-doc: clean
BISECT_ENABLE=yes dune build @doc-test --force
bisect-ppx-report html -o ./_coverage_doc --title="LIGO doc coverage"
bisect-ppx-report summary --per-file
coverage-cli: clean coverage-cli: clean
BISECT_ENABLE=yes dune runtest src/bin/expect_tests BISECT_ENABLE=yes dune runtest src/bin/expect_tests
bisect-ppx-report html -o ./_coverage_cli --title="CLI test coverage" bisect-ppx-report html -o ./_coverage_cli --title="CLI test coverage"
bisect-ppx-report summary --per-file bisect-ppx-report summary --per-file
# PRE="CLI coverage: "
# bisect-ppx-report summary --per-file | grep 'src/bin/cli.ml\|src/bin/cli_helpers.ml' | awk -v ORS=" " '{print $1}' | awk -v PRE=${PRE} -v POST="%" '{print PRE ($1 + $2 / NF) POST}'

View File

@ -15,7 +15,7 @@ Sets are similar to lists. The main difference is that elements of a `set` must
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo--> <!--Pascaligo-->
```pascaligo ```pascaligo group=a
type int_set is set(int); type int_set is set(int);
const my_set: int_set = set const my_set: int_set = set
1; 1;
@ -25,14 +25,14 @@ end
``` ```
<!--CameLIGO--> <!--CameLIGO-->
```cameligo ```cameligo group=a
type int_set = int set type int_set = int set
let my_set: int_set = let my_set: int_set =
Set.add 3 (Set.add 2 (Set.add 1 (Set.empty: int set))) Set.add 3 (Set.add 2 (Set.add 1 (Set.empty: int set)))
``` ```
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo ```reasonligo group=a
type int_set = set(int); type int_set = set(int);
let my_set: int_set = let my_set: int_set =
Set.add(3, Set.add(2, Set.add(1, Set.empty: set(int)))); Set.add(3, Set.add(2, Set.add(1, Set.empty: set(int))));
@ -44,16 +44,16 @@ let my_set: int_set =
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo--> <!--Pascaligo-->
```pascaligo ```pascaligo group=a
const my_set: int_set = set end; const my_set: int_set = set end;
const my_set_2: int_set = set_empty; const my_set_2: int_set = set_empty;
``` ```
<!--CameLIGO--> <!--CameLIGO-->
```cameligo ```cameligo group=a
let my_set: int_set = (Set.empty: int set) let my_set: int_set = (Set.empty: int set)
``` ```
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo ```reasonligo group=a
let my_set: int_set = (Set.empty: set(int)); let my_set: int_set = (Set.empty: set(int));
``` ```
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
@ -62,18 +62,18 @@ let my_set: int_set = (Set.empty: set(int));
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo--> <!--Pascaligo-->
```pascaligo ```pascaligo group=a
const contains_three: bool = my_set contains 3; const contains_three: bool = my_set contains 3;
// or alternatively // or alternatively
const contains_three_fn: bool = set_mem(3, my_set); const contains_three_fn: bool = set_mem(3, my_set);
``` ```
<!--CameLIGO--> <!--CameLIGO-->
```cameligo ```cameligo group=a
let contains_three: bool = Set.mem 3 my_set let contains_three: bool = Set.mem 3 my_set
``` ```
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo ```reasonligo group=a
let contains_three: bool = Set.mem(3, my_set); let contains_three: bool = Set.mem(3, my_set);
``` ```
@ -83,17 +83,17 @@ let contains_three: bool = Set.mem(3, my_set);
### Obtaining the size of a set ### Obtaining the size of a set
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo--> <!--Pascaligo-->
```pascaligo ```pascaligo group=a
const set_size: nat = size(my_set); const set_size: nat = size(my_set);
``` ```
<!--CameLIGO--> <!--CameLIGO-->
```cameligo ```cameligo group=a
let set_size: nat = Set.size my_set let set_size: nat = Set.size my_set
``` ```
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo ```reasonligo group=a
let set_size: nat = Set.size(my_set); let set_size: nat = Set.size(my_set);
``` ```
@ -103,21 +103,21 @@ let set_size: nat = Set.size(my_set);
### Modifying a set ### Modifying a set
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo--> <!--Pascaligo-->
```pascaligo ```pascaligo group=a
const larger_set: int_set = set_add(4, my_set); const larger_set: int_set = set_add(4, my_set);
const smaller_set: int_set = set_remove(3, my_set); const smaller_set: int_set = set_remove(3, my_set);
``` ```
<!--CameLIGO--> <!--CameLIGO-->
```cameligo ```cameligo group=a
let larger_set: int_set = Set.add 4 my_set let larger_set: int_set = Set.add 4 my_set
let smaller_set: int_set = Set.remove 3 my_set let smaller_set: int_set = Set.remove 3 my_set
``` ```
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo ```reasonligo group=a
let larger_set: int_set = Set.add(4, my_set); let larger_set: int_set = Set.add(4, my_set);
let smaller_set: int_set = Set.remove(3, my_set); let smaller_set: int_set = Set.remove(3, my_set);
``` ```
@ -128,20 +128,20 @@ let smaller_set: int_set = Set.remove(3, my_set);
### Folding a set ### Folding a set
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo--> <!--Pascaligo-->
```pascaligo ```pascaligo group=a
function sum(const result: int; const i: int): int is result + i; function sum(const result: int; const i: int): int is result + i;
// Outputs 6 // Outputs 6
const sum_of_a_set: int = set_fold(sum, my_set, 0); const sum_of_a_set: int = set_fold(sum, my_set, 0);
``` ```
<!--CameLIGO--> <!--CameLIGO-->
```cameligo ```cameligo group=a
let sum (result: int) (i: int) : int = result + i let sum (result: int) (i: int) : int = result + i
let sum_of_a_set: int = Set.fold sum my_set 0 let sum_of_a_set: int = Set.fold sum my_set 0
``` ```
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo ```reasonligo group=a
let sum = (result: int, i: int): int => result + i; let sum = (result: int, i: int): int => result + i;
let sum_of_a_set: int = Set.fold(sum, my_set, 0); let sum_of_a_set: int = Set.fold(sum, my_set, 0);
``` ```
@ -157,7 +157,7 @@ Lists are similar to sets, but their elements don't need to be unique and they d
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo--> <!--Pascaligo-->
```pascaligo ```pascaligo group=b
type int_list is list(int); type int_list is list(int);
const my_list: int_list = list const my_list: int_list = list
1; 1;
@ -167,13 +167,13 @@ end
``` ```
<!--CameLIGO--> <!--CameLIGO-->
```cameligo ```cameligo group=b
type int_list = int list type int_list = int list
let my_list: int_list = [1; 2; 3] let my_list: int_list = [1; 2; 3]
``` ```
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo ```reasonligo group=b
type int_list = list(int); type int_list = list(int);
let my_list: int_list = [1, 2, 3]; let my_list: int_list = [1, 2, 3];
``` ```
@ -185,21 +185,21 @@ let my_list: int_list = [1, 2, 3];
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo--> <!--Pascaligo-->
```pascaligo ```pascaligo group=b
const larger_list: int_list = cons(4, my_list); const larger_list: int_list = cons(4, my_list);
const even_larger_list: int_list = 5 # larger_list; const even_larger_list: int_list = 5 # larger_list;
``` ```
<!--CameLIGO--> <!--CameLIGO-->
```cameligo ```cameligo group=b
let larger_list: int_list = 4 :: my_list let larger_list: int_list = 4 :: my_list
(* CameLIGO doesn't have a List.cons *) (* CameLIGO doesn't have a List.cons *)
``` ```
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo ```reasonligo group=b
let larger_list: int_list = [4, ...my_list]; let larger_list: int_list = [4, ...my_list];
/* ReasonLIGO doesn't have a List.cons */ (* ReasonLIGO doesn't have a List.cons *)
``` ```
<!--END_DOCUSAURUS_CODE_TABS--> <!--END_DOCUSAURUS_CODE_TABS-->
@ -211,7 +211,7 @@ let larger_list: int_list = [4, ...my_list];
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo--> <!--Pascaligo-->
```pascaligo ```pascaligo group=b
function increment(const i: int): int is block { skip } with i + 1; function increment(const i: int): int is block { skip } with i + 1;
// Creates a new list with elements incremented by 1 // Creates a new list with elements incremented by 1
const incremented_list: int_list = list_map(increment, even_larger_list); const incremented_list: int_list = list_map(increment, even_larger_list);
@ -219,7 +219,7 @@ const incremented_list: int_list = list_map(increment, even_larger_list);
<!--CameLIGO--> <!--CameLIGO-->
```cameligo ```cameligo group=b
let increment (i: int) : int = i + 1 let increment (i: int) : int = i + 1
(* Creates a new list with elements incremented by 1 *) (* Creates a new list with elements incremented by 1 *)
let incremented_list: int_list = List.map increment larger_list let incremented_list: int_list = List.map increment larger_list
@ -228,9 +228,9 @@ let incremented_list: int_list = List.map increment larger_list
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo ```reasonligo group=b
let increment = (i: int): int => i + 1; let increment = (i: int): int => i + 1;
/* Creates a new list with elements incremented by 1 */ (* Creates a new list with elements incremented by 1 *)
let incremented_list: int_list = List.map(increment, larger_list); let incremented_list: int_list = List.map(increment, larger_list);
``` ```
@ -240,7 +240,7 @@ let incremented_list: int_list = List.map(increment, larger_list);
### Folding of a list: ### Folding of a list:
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo--> <!--Pascaligo-->
```pascaligo ```pascaligo group=b
function sum(const result: int; const i: int): int is block { skip } with result + i; function sum(const result: int; const i: int): int is block { skip } with result + i;
// Outputs 6 // Outputs 6
const sum_of_a_list: int = list_fold(sum, my_list, 0); const sum_of_a_list: int = list_fold(sum, my_list, 0);
@ -248,7 +248,7 @@ const sum_of_a_list: int = list_fold(sum, my_list, 0);
<!--CameLIGO--> <!--CameLIGO-->
```cameligo ```cameligo group=b
let sum (result: int) (i: int) : int = result + i let sum (result: int) (i: int) : int = result + i
// Outputs 6 // Outputs 6
let sum_of_a_list: int = List.fold sum my_list 0 let sum_of_a_list: int = List.fold sum my_list 0
@ -256,9 +256,9 @@ let sum_of_a_list: int = List.fold sum my_list 0
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo ```reasonligo group=b
let sum = (result: int, i: int): int => result + i; let sum = (result: int, i: int): int => result + i;
/* Outputs 6 */ (* Outputs 6 *)
let sum_of_a_list: int = List.fold(sum, my_list, 0); let sum_of_a_list: int = List.fold(sum, my_list, 0);
``` ```
@ -287,22 +287,22 @@ sake of illustration.
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo--> <!--Pascaligo-->
```pascaligo ```pascaligo group=c
type full_name is string * string; type full_name is string * string;
const full_name: full_name = ("Alice", "Johnson"); const full_name: full_name = ("Alice", "Johnson");
``` ```
<!--CameLIGO--> <!--CameLIGO-->
```cameligo ```cameligo group=c
type full_name = string * string type full_name = string * string
(* The parenthesis here are optional *) (* The parenthesis here are optional *)
let full_name: full_name = ("Alice", "Johnson") let full_name: full_name = ("Alice", "Johnson")
``` ```
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo ```reasonligo group=c
type full_name = (string, string); type full_name = (string, string);
/* The parenthesis here are optional */ (* The parenthesis here are optional *)
let full_name: full_name = ("Alice", "Johnson"); let full_name: full_name = ("Alice", "Johnson");
``` ```
@ -320,17 +320,17 @@ Tuple elements are one-indexed and accessed like so:
<!--DOCUSAURUS_CODE_TABS--> <!--DOCUSAURUS_CODE_TABS-->
<!--Pascaligo--> <!--Pascaligo-->
```pascaligo ```pascaligo group=c
const first_name: string = full_name.1; const first_name: string = full_name.1;
``` ```
<!--CameLIGO--> <!--CameLIGO-->
```cameligo ```cameligo group=c
let first_name: string = full_name.1 let first_name: string = full_name.1
``` ```
<!--ReasonLIGO--> <!--ReasonLIGO-->
```reasonligo ```reasonligo group=c
let first_name: string = full_name[1]; let first_name: string = full_name[1];
``` ```

View File

@ -68,15 +68,6 @@ let parsify_reasonligo = fun source ->
Simplify.Cameligo.simpl_program raw in Simplify.Cameligo.simpl_program raw in
ok simplified ok simplified
let parsify_string_reasonligo = fun source ->
let%bind raw =
trace (simple_error "parsing") @@
Parser.Reasonligo.parse_string source in
let%bind simplified =
trace (simple_error "simplifying") @@
Simplify.Cameligo.simpl_program raw in
ok simplified
let parsify_expression_reasonligo = fun source -> let parsify_expression_reasonligo = fun source ->
let%bind raw = let%bind raw =
trace (simple_error "parsing expression") @@ trace (simple_error "parsing expression") @@
@ -105,3 +96,40 @@ let parsify_expression = fun syntax source ->
let%bind parsified = parsify source in let%bind parsified = parsify source in
let%bind applied = Self_ast_simplified.all_expression parsified in let%bind applied = Self_ast_simplified.all_expression parsified in
ok applied ok applied
let parsify_string_reasonligo = fun source ->
let%bind raw =
trace (simple_error "parsing") @@
Parser.Reasonligo.parse_string source in
let%bind simplified =
trace (simple_error "simplifying") @@
Simplify.Cameligo.simpl_program raw in
ok simplified
let parsify_string_pascaligo = fun source ->
let%bind raw =
trace (simple_error "parsing") @@
Parser.Pascaligo.parse_string source in
let%bind simplified =
trace (simple_error "simplifying") @@
Simplify.Pascaligo.simpl_program raw in
ok simplified
let parsify_string_cameligo = fun source ->
let%bind raw =
trace (simple_error "parsing") @@
Parser.Cameligo.parse_string source in
let%bind simplified =
trace (simple_error "simplifying") @@
Simplify.Cameligo.simpl_program raw in
ok simplified
let parsify_string = fun (syntax : v_syntax) source_filename ->
let%bind parsify = match syntax with
| Pascaligo -> ok parsify_string_pascaligo
| Cameligo -> ok parsify_string_cameligo
| ReasonLIGO -> ok parsify_string_reasonligo
in
let%bind parsified = parsify source_filename in
let%bind applied = Self_ast_simplified.all_program parsified in
ok applied

View File

@ -6,6 +6,10 @@ let compile (source_filename:string) syntax : Ast_simplified.program result =
let%bind simplified = parsify syntax source_filename in let%bind simplified = parsify syntax source_filename in
ok simplified ok simplified
let compile_string (source:string) syntax : Ast_simplified.program result =
let%bind simplified = parsify_string syntax source in
ok simplified
let compile_expression : v_syntax -> string -> Ast_simplified.expression result = let compile_expression : v_syntax -> string -> Ast_simplified.expression result =
fun syntax exp -> fun syntax exp ->
parsify_expression syntax exp parsify_expression syntax exp

8
src/test/doc_test.ml Normal file
View File

@ -0,0 +1,8 @@
open Test_helpers
let () =
Printexc.record_backtrace true ;
run_test @@ test_suite "LIGO" [
Md_file_tests.main ;
] ;
()

View File

@ -1,5 +1,7 @@
(ocamllex md)
(executables (executables
(names test manual_test) (names test manual_test doc_test)
(libraries (libraries
simple-utils simple-utils
ligo ligo
@ -12,6 +14,12 @@
(flags (:standard -w +1..62-4-9-44-40-42-48@39@33 -open Simple_utils )) (flags (:standard -w +1..62-4-9-44-40-42-48@39@33 -open Simple_utils ))
) )
(alias
(name doc-test)
(action (run ./doc_test.exe))
(deps (source_tree ../../gitlab-pages/docs/language-basics))
)
(alias (alias
(name ligo-test) (name ligo-test)
(action (run ./test.exe)) (action (run ./test.exe))

62
src/test/md.mll Normal file
View File

@ -0,0 +1,62 @@
{
(* initial version taken from https://github.com/realworldocaml/mdx *)
type arg =
| Field of string
| NameValue of string * string
type block = {
line : int;
file : string;
arguments: arg list;
header : string option;
contents: string list;
}
exception Err of string
let line_ref = ref 1
let newline lexbuf =
Lexing.new_line lexbuf;
incr line_ref
}
let eol = '\n' | eof
let ws = ' ' | '\t'
rule text = parse
| eof { [] }
| "```" ([^' ' '\n']* as h) ws* ([^'\n']* as l) eol
{
let header = if h = "" then None else Some h in
let contents = block lexbuf in
let arguments = String.split_on_char ' ' l in
let arguments = List.map (fun a ->
if (String.contains a '=') then
( let a = String.split_on_char '=' a in
NameValue (List.nth a 0, List.nth a 1))
else
Field a
) arguments in
let file = lexbuf.Lexing.lex_start_p.Lexing.pos_fname in
newline lexbuf;
let line = !line_ref in
List.iter (fun _ -> newline lexbuf) contents;
newline lexbuf;
{ file; line; header; arguments; contents; }
:: text lexbuf }
| [^'\n']* eol
{ newline lexbuf;
text lexbuf }
and block = parse
| eof | "```" ws* eol { [] }
| ([^'\n'] * as str) eol { str :: block lexbuf }
{
let token lexbuf =
try
text lexbuf
with Failure _ ->
raise (Err "incomplete code block")
}

74
src/test/md_file_tests.ml Normal file
View File

@ -0,0 +1,74 @@
open Trace
open Test_helpers
module SnippetsGroup = Map.Make(struct type t = (string * string) let compare a b = compare a b end)
let failed_to_compile_md_file md_file (s,group,prg) =
let title () = "Failed to compile "^s^" group '"^group^"' in file '"^md_file^"'" in
let content () = "unable to compile the program down to michelson" in
let data = [
("source" , fun () -> Format.asprintf "%s" prg) ;
] in
error ~data title content
(**
binds the snippets by (syntax, group_name)
e.g. :(pascaligo, a) -> "let .. in let .. in"
(cameligo, a) -> "let .. in let .. in"
syntax and group_name being retrieved from the .md file header & arguments
e.g. : ```syntax group=group_name ...some code ... ```
**)
let get_groups md_file =
let channel = open_in md_file in
let lexbuf = Lexing.from_channel channel in
let code_blocks = Md.token lexbuf in
List.fold_left
(fun (grp_map: _ SnippetsGroup.t) (el:Md.block) ->
match el.header with
| Some s ->
List.fold_left
(fun grp_map arg -> match arg with
| Md.NameValue ("group", name) ->
SnippetsGroup.update (s,name)
(fun arg_content ->
match arg_content with
| Some ct -> Some (String.concat "\n" (ct::el.contents))
| None -> Some (String.concat "\n" el.contents)
)
grp_map
| _ -> grp_map
)
grp_map el.arguments
| None -> grp_map
)
SnippetsGroup.empty code_blocks
(**
evaluate each expression in each programs from the snippets group map
**)
let compile_groups _filename (grp_map: _ SnippetsGroup.t) =
let grp_list = SnippetsGroup.bindings grp_map in
let%bind _michelsons = bind_map_list
(fun ((s,_grp),contents) ->
(*TODO: hierarchical error ?*)
trace_strong (failed_to_compile_md_file _filename (s,_grp,contents)) @@
let%bind v_syntax = Compile.Helpers.syntax_to_variant (Syntax_name s) None in
let%bind simplified = Compile.Of_source.compile_string contents v_syntax in
let%bind typed,_ = Compile.Of_simplified.compile simplified in
let%bind mini_c = Compile.Of_typed.compile typed in
bind_map_list
(fun ((_,exp),_) -> Compile.Of_mini_c.aggregate_and_compile_expression mini_c exp)
mini_c
)
grp_list in
ok ()
let compile filename () =
let groups = get_groups filename in
let%bind () = compile_groups filename groups in
ok ()
let md_root = "../../gitlab-pages/docs/language-basics/"
let main = test_suite "Markdown files" [
test "sets_lists_touples" (compile (md_root^"sets-lists-touples.md")) ;
]