diff options
Diffstat (limited to 'lib/kernel/test/code_SUITE.erl')
-rw-r--r-- | lib/kernel/test/code_SUITE.erl | 118 |
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), |