Skip to content

Commit 498a862

Browse files
committed
feature(cram): add [setup_script] to cram tests
Signed-off-by: Rudi Grinberg <[email protected]> refactor: my personal tweaks Signed-off-by: Rudi Grinberg <[email protected]>
1 parent d01ebf2 commit 498a862

File tree

11 files changed

+378
-16
lines changed

11 files changed

+378
-16
lines changed

src/dune_rules/cram/cram_exec.ml

Lines changed: 50 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ let cram_commmands commands =
324324
Buffer.contents buf
325325
;;
326326

327-
let create_sh_script cram_stanzas ~temp_dir : sh_script Fiber.t =
327+
let create_sh_script cram_stanzas ~temp_dir ~setup_scripts : sh_script Fiber.t =
328328
let script = Path.relative temp_dir "main.sh" in
329329
let oc = Io.open_out ~binary:true script in
330330
Fiber.finalize ~finally:(fun () -> Fiber.return @@ close_out oc)
@@ -373,6 +373,15 @@ let create_sh_script cram_stanzas ~temp_dir : sh_script Fiber.t =
373373
}
374374
in
375375
fprln oc "trap 'exit 0' EXIT";
376+
let* () =
377+
Fiber.sequential_iter setup_scripts ~f:(fun (script_path : Path.t) ->
378+
let+ script_sh_path = sh_path script_path in
379+
fprln oc ". %s" script_sh_path;
380+
match script_path with
381+
| In_source_tree _ -> assert false
382+
| External _ -> ()
383+
| In_build_dir _ -> fprln oc "rm -f %s" script_sh_path)
384+
in
376385
let+ cram_to_output = Fiber.sequential_map ~f:loop cram_stanzas in
377386
let command_count = !i in
378387
let metadata_file = Option.some_if (command_count > 0) metadata_file in
@@ -412,9 +421,9 @@ let make_temp_dir ~script =
412421
temp_dir
413422
;;
414423

415-
let run_cram_test env ~src ~script ~cram_stanzas ~temp_dir ~cwd ~timeout =
424+
let run_cram_test env ~src ~script ~cram_stanzas ~temp_dir ~cwd ~timeout ~setup_scripts =
416425
let open Fiber.O in
417-
let* sh_script = create_sh_script cram_stanzas ~temp_dir in
426+
let* sh_script = create_sh_script cram_stanzas ~temp_dir ~setup_scripts in
418427
let env = make_run_env env ~temp_dir ~cwd in
419428
let open Fiber.O in
420429
let sh =
@@ -482,13 +491,13 @@ let run_cram_test env ~src ~script ~cram_stanzas ~temp_dir ~cwd ~timeout =
482491
(timeout_msg @ [ timeout_set_message ])
483492
;;
484493

485-
let run_produce_correction ~conflict ~src ~env ~script ~timeout lexbuf =
494+
let run_produce_correction ~conflict ~src ~env ~script ~timeout ~setup_scripts lexbuf =
486495
let temp_dir = make_temp_dir ~script in
487496
let cram_stanzas = cram_stanzas lexbuf ~conflict in
488497
let cwd = Path.parent_exn script in
489498
let env = make_run_env env ~temp_dir ~cwd in
490499
let open Fiber.O in
491-
run_cram_test env ~src ~script ~cram_stanzas ~temp_dir ~cwd ~timeout
500+
run_cram_test env ~src ~script ~cram_stanzas ~temp_dir ~cwd ~timeout ~setup_scripts
492501
>>| compose_cram_output
493502
;;
494503

@@ -501,7 +510,16 @@ module Script = Persistent.Make (struct
501510
let test_example () = []
502511
end)
503512

504-
let run_and_produce_output ~conflict ~src ~env ~dir:cwd ~script ~dst ~timeout =
513+
let run_and_produce_output
514+
~conflict
515+
~src
516+
~env
517+
~dir:cwd
518+
~script
519+
~dst
520+
~timeout
521+
~setup_scripts
522+
=
505523
let script_contents = Io.read_file ~binary:false script in
506524
let lexbuf = Lexbuf.from_string script_contents ~fname:(Path.to_string script) in
507525
let temp_dir = make_temp_dir ~script in
@@ -511,7 +529,7 @@ let run_and_produce_output ~conflict ~src ~env ~dir:cwd ~script ~dst ~timeout =
511529
let env = make_run_env env ~temp_dir ~cwd in
512530
let open Fiber.O in
513531
let+ commands =
514-
run_cram_test env ~src ~script ~cram_stanzas ~temp_dir ~cwd ~timeout
532+
run_cram_test env ~src ~script ~cram_stanzas ~temp_dir ~cwd ~timeout ~setup_scripts
515533
>>| List.filter_map ~f:(function
516534
| Cram_lexer.Command c -> Some c
517535
| Comment _ -> None)
@@ -529,28 +547,42 @@ module Run = struct
529547
; script : 'path
530548
; output : 'target
531549
; timeout : (Loc.t * float) option
550+
; setup_scripts : 'path list
532551
}
533552

534553
let name = "cram-run"
535-
let version = 2
536-
537-
let bimap ({ src = _; dir; script; output; timeout } as t) f g =
538-
{ t with dir = f dir; script = f script; output = g output; timeout }
554+
let version = 3
555+
556+
let bimap ({ src = _; dir; script; output; timeout; setup_scripts } as t) f g =
557+
{ t with
558+
dir = f dir
559+
; script = f script
560+
; output = g output
561+
; timeout
562+
; setup_scripts = List.map ~f setup_scripts
563+
}
539564
;;
540565

541566
let is_useful_to ~memoize:_ = true
542567

543-
let encode { src = _; dir; script; output; timeout } path target : Sexp.t =
568+
let encode { src = _; dir; script; output; timeout; setup_scripts } path target
569+
: Sexp.t
570+
=
544571
List
545572
[ path dir
546573
; path script
547574
; target output
548575
; Dune_sexp.Encoder.(option float (Option.map ~f:snd timeout))
549576
|> Dune_sexp.to_sexp
577+
; List (List.map ~f:path setup_scripts)
550578
]
551579
;;
552580

553-
let action { src; dir; script; output; timeout } ~ectx:_ ~(eenv : Action.env) =
581+
let action
582+
{ src; dir; script; output; timeout; setup_scripts }
583+
~ectx:_
584+
~(eenv : Action.env)
585+
=
554586
run_and_produce_output
555587
~conflict:Ignore
556588
~src
@@ -559,14 +591,15 @@ module Run = struct
559591
~script
560592
~dst:output
561593
~timeout
594+
~setup_scripts
562595
;;
563596
end
564597

565598
include Action_ext.Make (Spec)
566599
end
567600

568-
let run ~src ~dir ~script ~output ~timeout =
569-
Run.action { src; dir; script; output; timeout }
601+
let run ~src ~dir ~script ~output ~timeout ~setup_scripts =
602+
Run.action { src; dir; script; output; timeout; setup_scripts }
570603
;;
571604

572605
module Make_script = struct
@@ -687,7 +720,8 @@ module Action = struct
687720
~src:script
688721
~env:eenv.env
689722
~script
690-
~timeout:None)
723+
~timeout:None
724+
~setup_scripts:[])
691725
;;
692726
end
693727

src/dune_rules/cram/cram_exec.mli

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ val run
1414
-> script:Path.t
1515
-> output:Path.Build.t
1616
-> timeout:(Loc.t * float) option
17+
-> setup_scripts:Path.t list
1718
-> Action.t
1819

1920
(** Produces a diff if [src] needs to be updated *)

src/dune_rules/cram/cram_rules.ml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ module Spec = struct
1313
; packages : Package.Name.Set.t
1414
; timeout : (Loc.t * float) option
1515
; conflict : Cram_stanza.Conflict.t
16+
; setup_scripts : Path.t list
1617
}
1718

1819
let make_empty ~test_name_alias =
@@ -26,6 +27,7 @@ module Spec = struct
2627
; packages = Package.Name.Set.empty
2728
; timeout = None
2829
; conflict = Ignore
30+
; setup_scripts = []
2931
}
3032
;;
3133
end
@@ -61,6 +63,7 @@ let test_rule
6163
; packages = _
6264
; timeout
6365
; conflict
66+
; setup_scripts
6467
} :
6568
Spec.t)
6669
(test : (Cram_test.t, error) result)
@@ -132,6 +135,7 @@ let test_rule
132135
in
133136
let+ (_ : Path.Set.t) = Action_builder.dyn_memo_deps deps in
134137
()
138+
and+ () = Action_builder.paths setup_scripts
135139
and+ locks = locks >>| Path.Set.to_list in
136140
Cram_exec.run
137141
~src:(Path.build script)
@@ -143,6 +147,7 @@ let test_rule
143147
~script:(Path.build script_sh)
144148
~output
145149
~timeout
150+
~setup_scripts
146151
|> Action.Full.make ~locks ~sandbox)
147152
|> Action_builder.with_file_targets ~file_targets:[ output ]
148153
|> Super_context.add_rule sctx ~dir ~loc
@@ -292,6 +297,14 @@ let rules ~sctx ~dir tests =
292297
~f:(Ordering.min (fun x y -> Float.compare (snd x) (snd y)))
293298
in
294299
let conflict = Option.value ~default:acc.conflict stanza.conflict in
300+
let setup_scripts =
301+
List.map stanza.setup_scripts ~f:(fun (_loc, script) ->
302+
(* Handle both relative and absolute paths *)
303+
if Filename.is_relative script
304+
then Path.build (Path.Build.relative dir script)
305+
else Path.external_ (Path.External.of_string script))
306+
@ acc.setup_scripts
307+
in
295308
( runtest_alias
296309
, { acc with
297310
enabled_if
@@ -303,6 +316,7 @@ let rules ~sctx ~dir tests =
303316
; sandbox
304317
; timeout
305318
; conflict
319+
; setup_scripts
306320
} ))
307321
in
308322
let extra_aliases =

src/dune_rules/cram/cram_stanza.ml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ type t =
4545
; package : Package.t option
4646
; runtest_alias : (Loc.t * bool) option
4747
; timeout : (Loc.t * float) option
48+
; setup_scripts : (Loc.t * string) list
4849
}
4950

5051
include Stanza.Make (struct
@@ -100,6 +101,13 @@ let decode =
100101
field_o
101102
"conflict"
102103
(Dune_lang.Syntax.since Stanza.syntax (3, 21) >>> Conflict.decode)
104+
and+ setup_scripts =
105+
let+ scripts =
106+
field_o
107+
"setup_scripts"
108+
(Dune_lang.Syntax.since Stanza.syntax (3, 21) >>> repeat (located string))
109+
in
110+
Option.value scripts ~default:[]
103111
in
104112
{ loc
105113
; alias
@@ -111,5 +119,6 @@ let decode =
111119
; runtest_alias
112120
; timeout
113121
; conflict
122+
; setup_scripts
114123
})
115124
;;

src/dune_rules/cram/cram_stanza.mli

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ type t =
2323
; package : Package.t option
2424
; runtest_alias : (Loc.t * bool) option
2525
; timeout : (Loc.t * float) option
26+
; setup_scripts : (Loc.t * string) list
2627
}
2728

2829
val decode : t Dune_lang.Decoder.t
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
Test if setup scripts are visible in test directory
2+
3+
$ cat > dune-project << EOF
4+
> (lang dune 3.21)
5+
> (cram enable)
6+
> EOF
7+
8+
$ cat > secret.sh << 'EOF'
9+
> MY_SECRET="should_not_be_visible"
10+
> EOF
11+
12+
$ cat > dune << EOF
13+
> (cram
14+
> (setup_scripts secret.sh))
15+
> EOF
16+
17+
$ cat > check.t << 'EOF'
18+
> $ ls *.sh 2>&1 || echo "No .sh files found"
19+
> No .sh files found
20+
> EOF
21+
22+
$ dune runtest
23+
File "check.t", line 1, characters 0-0:
24+
Error: Files _build/default/check.t and _build/default/check.t.corrected
25+
differ.
26+
[1]
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
Test that external (absolute path) setup scripts work and are NOT deleted
2+
3+
First, create an external script in /tmp:
4+
5+
$ EXTERNAL_SCRIPT="/tmp/dune_test_external_helper_$$.sh"
6+
$ cat > "$EXTERNAL_SCRIPT" << 'EOF'
7+
> #!/bin/sh
8+
> external_helper() {
9+
> echo "External helper called"
10+
> }
11+
> export EXTERNAL_VAR="from_external_script"
12+
> EOF
13+
$ chmod +x "$EXTERNAL_SCRIPT"
14+
15+
Create a project that uses the external script:
16+
17+
$ cat > dune-project << EOF
18+
> (lang dune 3.21)
19+
> (cram enable)
20+
> EOF
21+
22+
$ cat > dune << EOF
23+
> (cram
24+
> (setup_scripts $EXTERNAL_SCRIPT))
25+
> EOF
26+
27+
Create a test that uses the external helper:
28+
29+
$ cat > external.t << 'EOF'
30+
> Test that external helper is available
31+
>
32+
> $ external_helper
33+
> External helper called
34+
>
35+
> $ echo $EXTERNAL_VAR
36+
> from_external_script
37+
> EOF
38+
39+
Run the test:
40+
41+
$ dune runtest
42+
43+
Verify the external script still exists (was NOT deleted):
44+
45+
$ if [ -f "$EXTERNAL_SCRIPT" ]; then
46+
> echo "External script still exists"
47+
> else
48+
> echo "External script was deleted"
49+
> fi
50+
External script still exists

0 commit comments

Comments
 (0)