Skip to content

Commit e74c002

Browse files
committed
feat: add expect "..." by print ... command
Introduce a top-level command for unit-testing pretty-printer output from inside `.ec` files: expect "op foo : int = 1." by print op foo. The expected string is compared (after `String.trim` on both sides) against the captured output of the inner `print` command. On mismatch, raise an `hierror` with the expected and actual blocks; this fails the enclosing script in the standard way and is picked up by `scripts/testing/runtest`. Multi-line expected literals are supported out of the box because the existing STRING lexer rule already accepts embedded newlines. Also adds tests/expect.ec covering nullary/parametric ops, record types, axioms, and leading/trailing whitespace tolerance.
1 parent 736f20d commit e74c002

4 files changed

Lines changed: 50 additions & 0 deletions

File tree

src/ecCommands.ml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,22 @@ let check_opname_validity (scope : EcScope.scope) (x : string) =
397397
let process_print scope p =
398398
process_pr Format.std_formatter scope p
399399

400+
(* -------------------------------------------------------------------- *)
401+
let process_expect scope (expected, p) =
402+
let buf = Buffer.create 256 in
403+
let fmt = Format.formatter_of_buffer buf in
404+
process_pr fmt scope p;
405+
Format.pp_print_flush fmt ();
406+
let actual = Buffer.contents buf in
407+
if String.trim actual <> String.trim (unloc expected) then
408+
EcScope.hierror ~loc:(loc expected)
409+
"expect: output mismatch@\n\
410+
--- expected ---@\n\
411+
%s@\n\
412+
--- actual ---@\n\
413+
%s"
414+
(unloc expected) actual
415+
400416
(* -------------------------------------------------------------------- *)
401417
exception Pragma of [`Reset | `Restart]
402418

@@ -782,6 +798,7 @@ and process ?(src : string option) (ld : Loader.loader) (scope : EcScope.scope)
782798
| GsctOpen name -> `Fct (fun scope -> process_sct_open scope name)
783799
| GsctClose name -> `Fct (fun scope -> process_sct_close scope name)
784800
| Gprint p -> `Fct (fun scope -> process_print scope p; scope)
801+
| Gexpect x -> `Fct (fun scope -> process_expect scope x; scope)
785802
| Gsearch qs -> `Fct (fun scope -> process_search scope qs; scope)
786803
| Glocate x -> `Fct (fun scope -> process_locate scope x; scope)
787804
| Gtactics t -> `Fct (fun scope -> process_tactics ?src scope t)

src/ecParser.mly

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3950,6 +3950,8 @@ global_action:
39503950
| hint { Ghint $1 }
39513951
| x=loc(proofend) { Gsave x }
39523952
| PRINT p=print { Gprint p }
3953+
| EXPECT s=loc(STRING) BY PRINT p=print
3954+
{ Gexpect (s, p) }
39533955
| SEARCH x=search+ { Gsearch x }
39543956
| LOCATE x=qident { Glocate x }
39553957
| WHY3 x=STRING { GdumpWhy3 x }

src/ecParsetree.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1351,6 +1351,7 @@ type global_action =
13511351
| Greduction of puserred
13521352
| Ghint of phint
13531353
| Gprint of pprint
1354+
| Gexpect of (string located * pprint)
13541355
| Gsearch of pformula list
13551356
| Glocate of pqsymbol
13561357
| GthOpen of (is_local * bool * psymbol)

tests/expect.ec

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
(* Unit tests for the `expect "..." by print ...` command. *)
2+
3+
require import Int.
4+
5+
type point = { x : int; y : int; }.
6+
7+
op foo : int = 1.
8+
op bar (n : int) : int = n + 1.
9+
10+
axiom foo_pos : 0 < foo.
11+
12+
(* nullary op *)
13+
expect "op foo : int = 1." by print op foo.
14+
15+
(* op with arguments *)
16+
expect "op bar (n : int) : int = n + 1." by print op bar.
17+
18+
(* record type *)
19+
expect "type point = { x: int; y: int; }." by print type point.
20+
21+
(* axiom *)
22+
expect "axiom foo_pos: 0 < foo." by print axiom foo_pos.
23+
24+
(* multi-line string literal with leading/trailing whitespace is
25+
tolerated (String.trim-based comparison) *)
26+
expect "
27+
28+
op foo : int = 1.
29+
30+
" by print op foo.

0 commit comments

Comments
 (0)