Shells in OCaml
at main 121 lines 4.7 kB view raw
1(* Thorough testing of word expansion *) 2open Merry 3module C = Merry.Eval.Make (Merry_posix.State) (Merry_posix.Exec) 4 5let expand ctx cst = C.word_expansion ctx cst |> snd |> List.concat 6let fragment = Alcotest.of_pp Merry.Ast.Fragment.pp 7let fragments = Alcotest.list fragment 8let frags = List.map Ast.Fragment.make 9 10let with_default_ctx ?(args = []) ?(params = []) ?(home = "/home/merry/") env fn 11 = 12 let executor = Merry_posix.Exec.{ mgr = env#process_mgr } in 13 let interactive = false in 14 let pos_zero = "msh" in 15 Eio.Switch.run @@ fun async_switch -> 16 let signal_handler f = Eio_posix.run @@ fun _ -> f () in 17 let state = Merry_posix.State.make ~home (Fpath.v (Merry.Eunix.cwd ())) in 18 let state = 19 List.fold_left 20 (fun s (k, v) -> Merry_posix.State.update s ~param:k v |> Result.get_ok) 21 state params 22 in 23 let ctx = 24 C.make_ctx ~interactive state executor ~fs:env#fs ~stdin:env#stdin 25 ~stdout:env#stdout ~async_switch ~argv:(Array.of_list args) 26 ~program:pos_zero ~signal_handler 27 in 28 fn ctx 29 30module W = struct 31 let name s = Ast.WordName s 32 let lit s = Ast.WordLiteral s 33 let dquote c = Ast.WordDoubleQuoted c 34 let glob_all = Ast.WordGlobAll 35 let tilde s = Ast.WordTildePrefix s 36 37 (* let squote c = Ast.WordSingleQuoted c *) 38 (* let arith a = Ast.WordArithmeticExpression a *) 39 let var v = Ast.WordVariable (Ast.VariableAtom (v, Ast.NoAttribute)) 40end 41 42let test_no_expansions env () = 43 let args = [ "echo"; "hello" ] in 44 let cargs = W.[ name "echo"; lit "hello" ] in 45 with_default_ctx ~args env @@ fun ctx -> 46 let expected = frags args in 47 let actual = expand ctx cargs in 48 Alcotest.check fragments "same fragments" expected actual 49 50let test_dquote env () = 51 let args = [ "echo"; "\"hello there\"" ] in 52 let cargs = W.[ name "echo"; dquote [ lit "hello there" ] ] in 53 with_default_ctx ~args env @@ fun ctx -> 54 let expected = 55 Ast.[ Fragment.make "echo"; Fragment.make ~join:`No "hello there" ] 56 in 57 let actual = expand ctx cargs in 58 Alcotest.check fragments "same fragments" expected actual 59 60let test_dquote_expansion env () = 61 let args = [ "echo"; "\"hello $FOO...\"" ] in 62 let cargs = 63 W.[ name "echo"; dquote [ lit "hello "; var "FOO"; lit "..." ] ] 64 in 65 with_default_ctx ~args ~params:[ ("FOO", "there") ] env @@ fun ctx -> 66 let expected = Ast.Fragment.[ make "echo"; make "hello there..." ] in 67 let actual = expand ctx cargs in 68 Alcotest.check fragments "same fragments" expected actual 69 70let test_single_expansion env () = 71 let args = [ "echo"; "$FOO" ] in 72 let cargs = W.[ name "echo"; var "FOO" ] in 73 with_default_ctx ~args ~params:[ ("FOO", "bar") ] env @@ fun ctx -> 74 let expected = [ Ast.Fragment.make "echo"; Ast.Fragment.make "bar" ] in 75 let actual = expand ctx cargs in 76 Alcotest.check fragments "same fragments" expected actual 77 78let test_argv_expansion env () = 79 let cargs = W.[ name "echo"; var "@" ] in 80 with_default_ctx ~args:[ "echo"; "a"; "b"; "c d" ] env @@ fun ctx -> 81 let expected = frags [ "echo"; "a"; "b"; "c"; "d" ] in 82 let actual = expand ctx cargs in 83 Alcotest.check fragments "same fragments" expected actual 84 85let test_argv_in_quotes_expansion env () = 86 let cargs = W.[ name "echo"; dquote [ lit "got ["; var "@"; lit "]" ] ] in 87 with_default_ctx ~args:[ "echo"; "a"; "b"; "c" ] env @@ fun ctx -> 88 let expected = 89 Ast.Fragment.[ make "echo"; make "got [a"; make "b"; make "c]" ] 90 in 91 let actual = expand ctx cargs in 92 Alcotest.check fragments "same fragments" expected actual 93 94let test_glob env () = 95 let cargs = W.[ glob_all; lit ".ml" ] in 96 with_default_ctx ~args:[ "*.ml" ] env @@ fun ctx -> 97 let expected = Ast.Fragment.[ make "test_merry.ml"; make "wordexp.ml" ] in 98 let actual = expand ctx cargs in 99 Alcotest.check fragments "same fragments" expected actual 100 101let test_tilde env () = 102 let cargs = W.[ tilde "~"; lit "documents" ] in 103 with_default_ctx ~args:[ "~/documents" ] env @@ fun ctx -> 104 let expected = Ast.Fragment.[ make "/home/merry/documents" ] in 105 let actual = expand ctx cargs in 106 Alcotest.check fragments "same fragments" expected actual 107 108let simple env = 109 [ 110 ("no expansions", `Quick, test_no_expansions env); 111 ("double quote", `Quick, test_dquote env); 112 ("double quote expansion", `Quick, test_dquote_expansion env); 113 ("single expansion", `Quick, test_single_expansion env); 114 ("argv expansion", `Quick, test_argv_expansion env); 115 ("argv expansion dquote", `Quick, test_argv_in_quotes_expansion env); 116 ("glob all", `Quick, test_glob env); 117 ("tilde", `Quick, test_tilde env); 118 ] 119 120let () = 121 Eio_posix.run @@ fun env -> Alcotest.run "wordexp" [ ("simple", simple env) ]