summaryrefslogtreecommitdiff
path: root/lib/kernel/test/code_SUITE.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/kernel/test/code_SUITE.erl')
-rw-r--r--lib/kernel/test/code_SUITE.erl118
1 files changed, 103 insertions, 15 deletions
diff --git a/lib/kernel/test/code_SUITE.erl b/lib/kernel/test/code_SUITE.erl
index 7059d477d9..8eadcf9cb3 100644
--- a/lib/kernel/test/code_SUITE.erl
+++ b/lib/kernel/test/code_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2021. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -40,7 +40,7 @@
on_load_deleted/1,
big_boot_embedded/1,
module_status/1,
- get_mode/1,
+ get_mode/1, code_path_cache/1,
normalized_paths/1, mult_embedded_flags/1]).
-export([init_per_testcase/2, end_per_testcase/2,
@@ -62,7 +62,7 @@ all() ->
replace_path, load_file, load_abs, ensure_loaded,
delete, purge, purge_many_exits, soft_purge, is_loaded, all_loaded,
all_available, load_binary, dir_req, object_code, set_path_file,
- upgrade,
+ upgrade, code_path_cache,
sticky_dir, pa_pz_option, add_del_path, dir_disappeared,
ext_mod_dep, clash, where_is_file,
purge_stacktrace, mult_lib_roots,
@@ -316,6 +316,68 @@ replace_path(Config) when is_list(Config) ->
ok.
+code_path_cache(Config) ->
+ PrivDir = proplists:get_value(priv_dir, Config),
+
+ non_existing = code:which(?TESTMOD), % verify dummy name not in path
+ code:purge(?TESTMOD), % ensure no previous version in memory
+ code:delete(?TESTMOD),
+ code:purge(?TESTMOD),
+
+ Original = code:get_path(),
+ Dir = filename:join(PrivDir, "myebin"),
+ filelib:ensure_path(Dir),
+ ToBeReplacedDir1 = filename:join(PrivDir, "tobereplaced-1/ebin"),
+ ToBeReplacedDir2 = filename:join(PrivDir, "tobereplaced-2/ebin"),
+ filelib:ensure_path(ToBeReplacedDir1),
+ filelib:ensure_path(ToBeReplacedDir2),
+
+ File = filename:join(Dir, ?TESTMODOBJ),
+ {ok,?TESTMOD,Bin} = compile:forms(dummy_ast(), []),
+
+ %% Adding a cached path and re-adding for clearing
+ [begin
+ error = code:get_object_code(?TESTMOD),
+ true = code:Fun(Dir, cache),
+ error = code:get_object_code(?TESTMOD),
+ ok = file:write_file(File, Bin),
+ error = code:get_object_code(?TESTMOD),
+ true = code:Fun(Dir, cache),
+ {_,_,_} = code:get_object_code(?TESTMOD),
+ code:del_path(Dir),
+ ok = file:delete(File)
+ end || Fun <- [add_path, add_patha, add_pathz]],
+
+ Original = code:get_path(),
+
+ %% Adding several cached paths and explicit cache clearing
+ [begin
+ error = code:get_object_code(?TESTMOD),
+ ok = code:Fun([Dir, ToBeReplacedDir1], cache),
+ error = code:get_object_code(?TESTMOD),
+ ok = file:write_file(File, Bin),
+ error = code:get_object_code(?TESTMOD),
+ ok = code:clear_cache(),
+ {_,_,_} = code:get_object_code(?TESTMOD),
+ ok = code:del_paths([Dir, ToBeReplacedDir1]),
+ ok = file:delete(File)
+ end || Fun <- [add_paths, add_pathsa, add_pathsz]],
+
+ Original = code:get_path(),
+
+ %% Replacing a non-cached path with cache and set_path for clearing
+ error = code:get_object_code(?TESTMOD),
+ true = code:add_path(ToBeReplacedDir1),
+ true = code:replace_path(tobereplaced, ToBeReplacedDir2, cache),
+ error = code:get_object_code(?TESTMOD),
+ ok = file:write_file(filename:join(ToBeReplacedDir2, ?TESTMODOBJ), Bin),
+ error = code:get_object_code(?TESTMOD),
+ true = code:set_path(code:get_path(), nocache),
+ {_,_,_} = code:get_object_code(?TESTMOD),
+
+ true = code:set_path(Original),
+ ok.
+
%% OTP-3977.
dir_disappeared(Config) when is_list(Config) ->
PrivDir = proplists:get_value(priv_dir, Config),
@@ -997,8 +1059,12 @@ purge_stacktrace_test(Config) when is_list(Config) ->
mult_lib_roots(Config) when is_list(Config) ->
DataDir = filename:join(proplists:get_value(data_dir, Config), "mult_lib_roots"),
mult_lib_compile(DataDir, "my_dummy_app-b/ebin/lists"),
- mult_lib_compile(DataDir,
- "my_dummy_app-c/ebin/code_SUITE_mult_root_module"),
+
+ %% We will use this module to test both code path loading and
+ %% code path caching. So we ensure its beam file does not exist.
+ CodeSuiteMultRootBeam =
+ filename:join(DataDir, "first_root/my_dummy_app-c/ebin/code_SUITE_mult_root_module.beam"),
+ file:delete(CodeSuiteMultRootBeam),
%% Set up ERL_LIBS and start a peer node.
ErlLibs = filename:join(DataDir, "first_root") ++ mult_lib_sep() ++
@@ -1026,9 +1092,31 @@ mult_lib_roots(Config) when is_list(Config) ->
E <- lists:sort([Lib1,Lib2,Lib3,Lib4,Lib5])],
io:format("~p\n", [Path]),
+ %% Now let's attempt to dynamically add a module,
+ %% this will fail due to the boot paths cache.
+ error = rpc:call(Node, code, get_object_code, [code_SUITE_mult_root_module]),
+ mult_lib_compile(DataDir, "my_dummy_app-c/ebin/code_SUITE_mult_root_module"),
+ error = rpc:call(Node, code, get_object_code, [code_SUITE_mult_root_module]),
+ %% Test that the CWD is not cached
+ File = filename:join([DataDir, "first_root/my_dummy_app-c/ebin/code_SUITE_mult_root_module"]),
+ {ok, _} = compile:file(File, [{outdir, "."}]),
+ {_,_,_} = rpc:call(Node, code, get_object_code, [code_SUITE_mult_root_module]),
true = rpc:call(Node, code_SUITE_mult_root_module, works_fine, []),
+ file:delete("code_SUITE_mult_root_module.beam"),
+ %% Clean up so we can start again
+ file:delete(CodeSuiteMultRootBeam),
peer:stop(Peer),
+ NoCacheArgs = ["-env", "ERL_LIBS", ErlLibs, "-cache_boot_paths", "false"],
+ {ok, NoCachePeer, NoCacheNode} = ?CT_PEER(NoCacheArgs),
+
+ %% Now the same code should work
+ error = rpc:call(NoCacheNode, code, get_object_code, [code_SUITE_mult_root_module]),
+ mult_lib_compile(DataDir, "my_dummy_app-c/ebin/code_SUITE_mult_root_module"),
+ {_,_,_} = rpc:call(NoCacheNode, code, get_object_code, [code_SUITE_mult_root_module]),
+ true = rpc:call(NoCacheNode, code_SUITE_mult_root_module, works_fine, []),
+
+ peer:stop(NoCachePeer),
ok.
mult_lib_compile(Root, Last) ->
@@ -1660,9 +1748,9 @@ on_load_self_call(_Config) ->
ok.
on_load_do_load(Mod, Code) ->
- spawn(fun() ->
- {module,Mod} = code:load_binary(Mod, "", Code)
- end),
+ spawn_link(fun() ->
+ {module,Mod} = code:load_binary(Mod, "", Code)
+ end),
receive
Any -> Any
end.
@@ -1753,9 +1841,9 @@ on_load_deleted(_Config) ->
" receive _ -> ok end.\n"]),
merl:print(Tree),
{ok,Mod,Code} = merl:compile(Tree),
- spawn(fun() ->
- {module,Mod} = code:load_binary(Mod, "", Code)
- end),
+ spawn_link(fun() ->
+ {module,Mod} = code:load_binary(Mod, "", Code)
+ end),
receive after 1 -> ok end,
{module,OtherMod} = code:load_binary(OtherMod, "",
OtherCode),
@@ -1778,10 +1866,10 @@ delete_before_reload(Mod, Reload) ->
{ok,Mod,Code1} = merl:compile(Tree1),
Self = self(),
- spawn(fun() ->
- {module,Mod} = code:load_binary(Mod, "", Code1),
- Mod:f(Self)
- end),
+ spawn_link(fun() ->
+ {module,Mod} = code:load_binary(Mod, "", Code1),
+ Mod:f(Self)
+ end),
receive started -> ok end,
true = code:delete(Mod),