summaryrefslogtreecommitdiff
path: root/ocamltest
diff options
context:
space:
mode:
authorTom Kelly <ctk21@cl.cam.ac.uk>2021-10-04 13:43:06 +0100
committerTom Kelly <ctk21@cl.cam.ac.uk>2021-10-04 13:43:06 +0100
commit219f0470fa12f2460953d2c2407f19e050d93f5a (patch)
tree2d7136cd7b79d8482f37e19106231f22298f9070 /ocamltest
parent23852f7800f965ac39e8cd80e04fb489e7747d87 (diff)
parent8949e28fa1995de9fa72ee377993624af0f4a616 (diff)
downloadocaml-219f0470fa12f2460953d2c2407f19e050d93f5a.tar.gz
Merge commit '8949e28fa1995de9fa72ee377993624af0f4a616' into 5.00
Diffstat (limited to 'ocamltest')
-rw-r--r--ocamltest/actions_helpers.ml4
-rw-r--r--ocamltest/environments.ml56
-rw-r--r--ocamltest/environments.mli5
-rw-r--r--ocamltest/main.ml5
-rw-r--r--ocamltest/ocaml_actions.ml17
-rw-r--r--ocamltest/ocaml_variables.ml4
-rw-r--r--ocamltest/run_unix.c2
-rw-r--r--ocamltest/run_win32.c38
-rw-r--r--ocamltest/tsl_ast.ml1
-rw-r--r--ocamltest/tsl_ast.mli1
-rw-r--r--ocamltest/tsl_lexer.mll1
-rw-r--r--ocamltest/tsl_parser.mly4
-rw-r--r--ocamltest/tsl_semantics.ml15
-rw-r--r--ocamltest/tsl_semantics.mli4
-rw-r--r--ocamltest/variables.ml7
-rw-r--r--ocamltest/variables.mli2
16 files changed, 121 insertions, 45 deletions
diff --git a/ocamltest/actions_helpers.ml b/ocamltest/actions_helpers.ml
index 840ae5fbe1..138ddaf8f6 100644
--- a/ocamltest/actions_helpers.ml
+++ b/ocamltest/actions_helpers.ml
@@ -160,9 +160,9 @@ let run_cmd
log_redirection "stdout" stdout_filename;
log_redirection "stderr" stderr_filename;
let systemenv =
- Array.append
+ Environments.append_to_system_env
environment
- (Environments.to_system_env env)
+ env
in
let timeout =
match timeout with
diff --git a/ocamltest/environments.ml b/ocamltest/environments.ml
index 423be93ce3..f71dd20c5a 100644
--- a/ocamltest/environments.ml
+++ b/ocamltest/environments.ml
@@ -19,12 +19,14 @@ open Ocamltest_stdlib
module VariableMap = Map.Make (Variables)
-type t = string VariableMap.t
+type t = string option VariableMap.t
let empty = VariableMap.empty
let to_bindings env =
- let f variable value lst = (variable, value) :: lst in
+ let f variable value lst =
+ Option.fold ~none:lst ~some:(fun value -> (variable, value) :: lst) value
+ in
VariableMap.fold f env []
let expand_aux env value =
@@ -39,16 +41,48 @@ let rec expand env value =
let expanded = expand_aux env value in
if expanded=value then value else expand env expanded
-let to_system_env env =
+let expand env = function
+ | None -> raise Not_found
+ | Some value -> expand env value
+
+let append_to_system_env environment env =
+ (* Augment env with any bindings which are only in environment. This must be
+ done here as the Windows C implementation doesn't process multiple values
+ in settings.envp. *)
+ let env =
+ let update env binding =
+ let name, value =
+ match String.index binding '=' with
+ | c ->
+ let name = String.sub binding 0 c in
+ let value =
+ String.sub binding (c + 1) (String.length binding - c - 1) in
+ (name, Some value)
+ | exception Not_found ->
+ (binding, None)
+ in
+ let var = Variables.make (name, "system env var") in
+ if not (VariableMap.mem var env) then
+ VariableMap.add var value env
+ else
+ env
+ in
+ Array.fold_left update env environment
+ in
let system_env = Array.make (VariableMap.cardinal env) "" in
let i = ref 0 in
let store variable value =
+ let some value =
+ Variables.string_of_binding variable (expand env (Some value)) in
system_env.(!i) <-
- Variables.string_of_binding variable (expand env value);
+ Option.fold ~none:(Variables.name_of_variable variable) ~some value;
incr i in
VariableMap.iter store env;
system_env
+let to_system_env env =
+ append_to_system_env [||] env
+
let lookup variable env =
try Some (expand env (VariableMap.find variable env)) with Not_found -> None
@@ -75,7 +109,7 @@ let safe_lookup variable env = match lookup variable env with
let is_variable_defined variable env =
VariableMap.mem variable env
-let add variable value env = VariableMap.add variable value env
+let add variable value env = VariableMap.add variable (Some value) env
let add_if_undefined variable value env =
if VariableMap.mem variable env then env else add variable value env
@@ -83,18 +117,24 @@ let add_if_undefined variable value env =
let append variable appened_value environment =
let previous_value = safe_lookup variable environment in
let new_value = previous_value ^ appened_value in
- VariableMap.add variable new_value environment
+ VariableMap.add variable (Some new_value) environment
let remove = VariableMap.remove
+let unsetenv variable environment =
+ VariableMap.add variable None environment
+
let add_bindings bindings env =
let f env (variable, value) = add variable value env in
List.fold_left f env bindings
let from_bindings bindings = add_bindings bindings empty
-let dump_assignment log (variable, value) =
- Printf.fprintf log "%s = %s\n%!" (Variables.name_of_variable variable) value
+let dump_assignment log = function
+ | (variable, Some value) ->
+ Printf.fprintf log "%s = %s\n%!" (Variables.name_of_variable variable) value
+ | (variable, None) ->
+ Printf.fprintf log "unsetenv %s\n%!" (Variables.name_of_variable variable)
let dump log environment =
List.iter (dump_assignment log) (VariableMap.bindings environment)
diff --git a/ocamltest/environments.mli b/ocamltest/environments.mli
index b1f2f1d651..4437c043fa 100644
--- a/ocamltest/environments.mli
+++ b/ocamltest/environments.mli
@@ -22,6 +22,7 @@ val empty : t
val from_bindings : (Variables.t * string) list -> t
val to_bindings : t -> (Variables.t * string) list
val to_system_env : t -> string array
+val append_to_system_env : string array -> t -> string array
val lookup : Variables.t -> t -> string option
val lookup_nonempty : Variables.t -> t -> string option
@@ -42,6 +43,10 @@ val add : Variables.t -> string -> t -> t
val add_if_undefined : Variables.t -> string -> t -> t
val add_bindings : (Variables.t * string) list -> t -> t
+val unsetenv : Variables.t -> t -> t
+(** [unsetenv env name] causes [name] to be ignored from the underlying system
+ environment *)
+
val append : Variables.t -> string -> t -> t
val dump : out_channel -> t -> unit
diff --git a/ocamltest/main.ml b/ocamltest/main.ml
index a1ad65d1ef..ea7a99d6bd 100644
--- a/ocamltest/main.ml
+++ b/ocamltest/main.ml
@@ -86,7 +86,7 @@ let rec run_test log common_prefix path behavior = function
let (msg, children_behavior, summary) = match behavior with
| Skip_all_tests -> "n/a", Skip_all_tests, No_failure
| Run env ->
- let testenv0 = interprete_environment_statements env testenvspec in
+ let testenv0 = interpret_environment_statements env testenvspec in
let testenv = List.fold_left apply_modifiers testenv0 env_modifiers in
let (result, newenv) = Tests.run log testenv test in
let msg = Result.string_of_result result in
@@ -193,8 +193,7 @@ let test_file test_filename =
let rootenv =
Environments.initialize Environments.Pre log initial_environment in
let rootenv =
- interprete_environment_statements
- rootenv rootenv_statements in
+ interpret_environment_statements rootenv rootenv_statements in
let rootenv = Environments.initialize Environments.Post log rootenv in
let common_prefix = " ... testing '" ^ test_basename ^ "' with" in
let initial_status =
diff --git a/ocamltest/ocaml_actions.ml b/ocamltest/ocaml_actions.ml
index 90b11ff29d..91e0fd4ba9 100644
--- a/ocamltest/ocaml_actions.ml
+++ b/ocamltest/ocaml_actions.ml
@@ -533,9 +533,9 @@ let debug log env =
program
] in
let systemenv =
- Array.append
+ Environments.append_to_system_env
default_ocaml_env
- (Environments.to_system_env (env_with_lib_unix env))
+ (env_with_lib_unix env)
in
let expected_exit_status = 0 in
let exit_status =
@@ -570,12 +570,13 @@ let objinfo log env =
] in
let ocamllib = [| (Printf.sprintf "OCAMLLIB=%s" tools_directory) |] in
let systemenv =
- Array.concat
- [
- default_ocaml_env;
- ocamllib;
- (Environments.to_system_env (env_with_lib_unix env))
- ]
+ Environments.append_to_system_env
+ (Array.concat
+ [
+ default_ocaml_env;
+ ocamllib;
+ ])
+ (env_with_lib_unix env)
in
let expected_exit_status = 0 in
let exit_status =
diff --git a/ocamltest/ocaml_variables.ml b/ocamltest/ocaml_variables.ml
index e6a251ebba..1f98b6326e 100644
--- a/ocamltest/ocaml_variables.ml
+++ b/ocamltest/ocaml_variables.ml
@@ -54,7 +54,7 @@ let export_caml_ld_library_path value =
if local_value="" then current_value else
if current_value="" then local_value else
String.concat Filename.path_sep [local_value; current_value] in
- Printf.sprintf "%s=%s" caml_ld_library_path_name new_value
+ (caml_ld_library_path_name, new_value)
let caml_ld_library_path =
make_with_exporter
@@ -183,7 +183,7 @@ let ocamlopt_opt_exit_status = make ("ocamlopt_opt_exit_status",
"Expected exit status of ocamlopt.opt")
let export_ocamlrunparam value =
- Printf.sprintf "%s=%s" "OCAMLRUNPARAM" value
+ ("OCAMLRUNPARAM", value)
let ocamlrunparam =
make_with_exporter
diff --git a/ocamltest/run_unix.c b/ocamltest/run_unix.c
index 201a309fa5..eac04e1ef3 100644
--- a/ocamltest/run_unix.c
+++ b/ocamltest/run_unix.c
@@ -149,6 +149,8 @@ static void update_environment(array local_env)
setenv(name, value, 1); /* 1 means overwrite */
free(name);
free(value);
+ } else {
+ unsetenv(*envp);
}
}
}
diff --git a/ocamltest/run_win32.c b/ocamltest/run_win32.c
index 61686aca1f..548071976f 100644
--- a/ocamltest/run_win32.c
+++ b/ocamltest/run_win32.c
@@ -163,10 +163,8 @@ static LPVOID prepare_environment(WCHAR **localenv)
/* Compute length of local environment */
localenv_length = 0;
- q = localenv;
- while (*q != NULL) {
+ for (q = localenv; *q != NULL; q++) {
localenv_length += wcslen(*q) + 1;
- q++;
}
/* Build new env that contains both process and local env */
@@ -178,19 +176,37 @@ static LPVOID prepare_environment(WCHAR **localenv)
}
r = env;
p = process_env;
+ /* Copy process_env to env only if the given names are not in localenv */
while (*p != L'\0') {
+ wchar_t *pos_eq = wcschr(p, L'=');
+ int copy = 1;
l = wcslen(p) + 1; /* also count terminating '\0' */
- memcpy(r, p, l * sizeof(WCHAR));
+ /* Temporarily change the = to \0 for wcscmp */
+ *pos_eq = L'\0';
+ for (q = localenv; *q != NULL; q++) {
+ wchar_t *pos_eq2 = wcschr(*q, L'=');
+ /* Compare this name in localenv with the current one in processenv */
+ if (pos_eq2) *pos_eq2 = L'\0';
+ if (!wcscmp(*q, p)) copy = 0;
+ if (pos_eq2) *pos_eq2 = L'=';
+ }
+ *pos_eq = L'=';
+ if (copy) {
+ /* This name is not marked for deletion/update in localenv, so copy */
+ memcpy(r, p, l * sizeof(WCHAR));
+ r += l;
+ }
p += l;
- r += l;
}
FreeEnvironmentStrings(process_env);
- q = localenv;
- while (*q != NULL) {
- l = wcslen(*q) + 1;
- memcpy(r, *q, l * sizeof(WCHAR));
- r += l;
- q++;
+ for (q = localenv; *q != NULL; q++) {
+ /* A string in localenv without '=' signals deletion, which has been done */
+ wchar_t *pos_eq = wcschr(*q, L'=');
+ if (pos_eq) {
+ l = wcslen(*q) + 1;
+ memcpy(r, *q, l * sizeof(WCHAR));
+ r += l;
+ }
}
*r = L'\0';
return env;
diff --git a/ocamltest/tsl_ast.ml b/ocamltest/tsl_ast.ml
index 47180b6641..0564019c12 100644
--- a/ocamltest/tsl_ast.ml
+++ b/ocamltest/tsl_ast.ml
@@ -24,6 +24,7 @@ type environment_statement =
| Assignment of bool * string located * string located (* variable = value *)
| Append of string located * string located
| Include of string located (* include named environment *)
+ | Unset of string located (* clear environment variable *)
type tsl_item =
| Environment_statement of environment_statement located
diff --git a/ocamltest/tsl_ast.mli b/ocamltest/tsl_ast.mli
index 06a61a194b..f835504408 100644
--- a/ocamltest/tsl_ast.mli
+++ b/ocamltest/tsl_ast.mli
@@ -24,6 +24,7 @@ type environment_statement =
| Assignment of bool * string located * string located (* variable = value *)
| Append of string located * string located (* variable += value *)
| Include of string located (* include named environment *)
+ | Unset of string located (* clear environment variable *)
type tsl_item =
| Environment_statement of environment_statement located
diff --git a/ocamltest/tsl_lexer.mll b/ocamltest/tsl_lexer.mll
index 1258c88fd4..3a7f917486 100644
--- a/ocamltest/tsl_lexer.mll
+++ b/ocamltest/tsl_lexer.mll
@@ -47,6 +47,7 @@ rule token = parse
match s with
| "include" -> INCLUDE
| "set" -> SET
+ | "unset" -> UNSET
| "with" -> WITH
| _ -> IDENTIFIER s
}
diff --git a/ocamltest/tsl_parser.mly b/ocamltest/tsl_parser.mly
index c2c0708e08..e6a875a886 100644
--- a/ocamltest/tsl_parser.mly
+++ b/ocamltest/tsl_parser.mly
@@ -37,7 +37,7 @@ let mkenvstmt envstmt =
%token <int> TEST_DEPTH
%token EQUAL PLUSEQUAL
/* %token COLON */
-%token INCLUDE SET WITH
+%token INCLUDE SET UNSET WITH
%token <string> IDENTIFIER
%token <string> STRING
@@ -76,6 +76,8 @@ env_item:
{ mkenvstmt (Append ($1, $3)) }
| SET identifier EQUAL string
{ mkenvstmt (Assignment (true, $2, $4)) }
+| UNSET identifier
+ { mkenvstmt (Unset $2) }
| INCLUDE identifier
{ mkenvstmt (Include $2) }
diff --git a/ocamltest/tsl_semantics.ml b/ocamltest/tsl_semantics.ml
index e9e163f2c8..09fb8f9917 100644
--- a/ocamltest/tsl_semantics.ml
+++ b/ocamltest/tsl_semantics.ml
@@ -67,16 +67,23 @@ let append_to_env loc variable_name value env =
with Variables.No_such_variable name ->
no_such_variable loc name
-let interprete_environment_statement env statement = match statement.node with
+let interpret_environment_statement env statement = match statement.node with
| Assignment (decl, var, value) ->
add_to_env decl statement.loc var.node value.node env
| Append (var, value) ->
append_to_env statement.loc var.node value.node env
| Include modifiers_name ->
apply_modifiers env modifiers_name
-
-let interprete_environment_statements env l =
- List.fold_left interprete_environment_statement env l
+ | Unset var ->
+ let var =
+ match Variables.find_variable var.node with
+ | None -> Variables.make (var.node,"User variable")
+ | Some var -> var
+ in
+ Environments.unsetenv var env
+
+let interpret_environment_statements env l =
+ List.fold_left interpret_environment_statement env l
type test_tree =
| Node of
diff --git a/ocamltest/tsl_semantics.mli b/ocamltest/tsl_semantics.mli
index dc0f2858e1..cbb017e681 100644
--- a/ocamltest/tsl_semantics.mli
+++ b/ocamltest/tsl_semantics.mli
@@ -19,11 +19,11 @@ open Tsl_ast
val apply_modifiers : Environments.t -> string located -> Environments.t
-val interprete_environment_statement :
+val interpret_environment_statement :
Environments.t -> Tsl_ast.environment_statement Tsl_ast.located ->
Environments.t
-val interprete_environment_statements :
+val interpret_environment_statements :
Environments.t -> Tsl_ast.environment_statement Tsl_ast.located list ->
Environments.t
diff --git a/ocamltest/variables.ml b/ocamltest/variables.ml
index e72bf1c5cc..706dc63d34 100644
--- a/ocamltest/variables.ml
+++ b/ocamltest/variables.ml
@@ -17,7 +17,7 @@
type value = string
-type exporter = value -> string
+type exporter = value -> string * string
type t = {
variable_name : string;
@@ -33,7 +33,7 @@ exception Variable_already_registered of string
exception No_such_variable of string
-let default_exporter varname value = Printf.sprintf "%s=%s" varname value
+let default_exporter varname value = (varname, value)
let make (name, description) =
if name="" then raise Empty_variable_name else {
@@ -65,7 +65,8 @@ let find_variable variable_name =
with Not_found -> None
let string_of_binding variable value =
- variable.variable_exporter value
+ let (varname, value) = variable.variable_exporter value in
+ Printf.sprintf "%s=%s" varname value
let get_registered_variables () =
let f _variable_name variable variable_list = variable::variable_list in
diff --git a/ocamltest/variables.mli b/ocamltest/variables.mli
index 8a70c7ff38..791d826407 100644
--- a/ocamltest/variables.mli
+++ b/ocamltest/variables.mli
@@ -17,7 +17,7 @@
type value = string
-type exporter = value -> string
+type exporter = value -> string * string
type t