1570af302Sopenharmony_ci#include <dlfcn.h>
2570af302Sopenharmony_ci#include <stdio.h>
3570af302Sopenharmony_ci#include <string.h>
4570af302Sopenharmony_ci#include "test.h"
5570af302Sopenharmony_ci
6570af302Sopenharmony_ci#define SO_HAS_DEPENDENCES "libdlopen_so_dep_dlopen_ns_dso.so"
7570af302Sopenharmony_ciconst char* dllName = "libdlopen_ns_dso.so";
8570af302Sopenharmony_ciconst char* dllName2 = "libdlopen_dso.so";
9570af302Sopenharmony_ciconst char* errPath_ns = "/src/common";
10570af302Sopenharmony_ciconst char* ndk_so = "libdlopen_ns_dso_ndk.so";
11570af302Sopenharmony_ciconst char* system_so = "libdlopen_ns_dso_sys.so";
12570af302Sopenharmony_citypedef void*(*CALL_DLOPEN_PTR)(const char *);
13570af302Sopenharmony_ci
14570af302Sopenharmony_ci// Test whether it is ok for main to dlopen ndk so.
15570af302Sopenharmony_civoid main_dlopen_ndk_so()
16570af302Sopenharmony_ci{
17570af302Sopenharmony_ci    void *handle = dlopen(ndk_so, RTLD_NOW);
18570af302Sopenharmony_ci    if (!handle)
19570af302Sopenharmony_ci        t_error("main dlopen ndk so %s failed: %s\n", ndk_so, dlerror());
20570af302Sopenharmony_ci    if (dlclose(handle))
21570af302Sopenharmony_ci        t_error("dlclose %s failed : %s \n", ndk_so, dlerror());
22570af302Sopenharmony_ci}
23570af302Sopenharmony_ci
24570af302Sopenharmony_ci// Test whether it is ok for system so to dlopen ndk so.
25570af302Sopenharmony_civoid system_so_dlopen_ndk_so()
26570af302Sopenharmony_ci{
27570af302Sopenharmony_ci    void *handle = dlopen(system_so, RTLD_NOW);
28570af302Sopenharmony_ci    if (!handle) {
29570af302Sopenharmony_ci        t_error("dlopen %s failed : %s \n", system_so, dlerror());
30570af302Sopenharmony_ci    }
31570af302Sopenharmony_ci    CALL_DLOPEN_PTR call_dlopen = dlsym(handle, "call_dlopen");
32570af302Sopenharmony_ci    if (!call_dlopen) {
33570af302Sopenharmony_ci        t_error("dlsym %s failed : %s \n", "call_dlopen", dlerror());
34570af302Sopenharmony_ci    }
35570af302Sopenharmony_ci    void *res = call_dlopen(ndk_so);
36570af302Sopenharmony_ci    if (!res) {
37570af302Sopenharmony_ci        t_error("default ns so(%s) can't dlopen ndk so(%s)", system_so, ndk_so);
38570af302Sopenharmony_ci    }
39570af302Sopenharmony_ci}
40570af302Sopenharmony_ci
41570af302Sopenharmony_ci// Test whether it is ok for ndk so to dlopen system so.
42570af302Sopenharmony_civoid ndk_so_dlopen_default_ns_so()
43570af302Sopenharmony_ci{
44570af302Sopenharmony_ci    Dl_namespace dlns;
45570af302Sopenharmony_ci    dlns_init(&dlns, "ndk");
46570af302Sopenharmony_ci    void *handle = dlopen_ns(&dlns, ndk_so, RTLD_NOW);
47570af302Sopenharmony_ci    if (!handle) {
48570af302Sopenharmony_ci        t_error("dlopen_ns(ns=%s, so=%s) failed : %s \n", "ndk", ndk_so, dlerror());
49570af302Sopenharmony_ci    }
50570af302Sopenharmony_ci    CALL_DLOPEN_PTR call_dlopen = dlsym(handle, "call_dlopen");
51570af302Sopenharmony_ci    if (!call_dlopen) {
52570af302Sopenharmony_ci        t_error("dlsym %s failed : %s \n", "call_dlopen", dlerror());
53570af302Sopenharmony_ci    }
54570af302Sopenharmony_ci    void *res = call_dlopen(system_so);
55570af302Sopenharmony_ci    if (!res) {
56570af302Sopenharmony_ci        t_error("ndk so(%s) can't dlopen system so(%s)", ndk_so, system_so);
57570af302Sopenharmony_ci    }
58570af302Sopenharmony_ci}
59570af302Sopenharmony_ci
60570af302Sopenharmony_ci// Test whether dlopen same so twice by same ns to get same handle.
61570af302Sopenharmony_civoid dlopen_same_so_twice_by_same_ns(char * dllPath_ns)
62570af302Sopenharmony_ci{
63570af302Sopenharmony_ci    Dl_namespace dlns1;
64570af302Sopenharmony_ci    dlns_init(&dlns1, "ns_for_dlopen_same_so_twice_by_same_ns");
65570af302Sopenharmony_ci    dlns_create(&dlns1, dllPath_ns);
66570af302Sopenharmony_ci
67570af302Sopenharmony_ci    void* handle1 = dlopen_ns(&dlns1, dllName, RTLD_NOW);
68570af302Sopenharmony_ci    if(!handle1)
69570af302Sopenharmony_ci        t_error("dlopen_ns(ns=%s, name=%s) failed : %s \n", dlns1.name, dllName, dlerror());
70570af302Sopenharmony_ci
71570af302Sopenharmony_ci    void* handle2 = dlopen_ns(&dlns1, dllName, RTLD_NOW);
72570af302Sopenharmony_ci    if(!handle2)
73570af302Sopenharmony_ci        t_error("dlopen_ns(ns=%s, name=%s) failed : %s \n", dlns1.name, dllName, dlerror());
74570af302Sopenharmony_ci
75570af302Sopenharmony_ci    if (handle1 != handle2)
76570af302Sopenharmony_ci        t_error("dlopen same so(%s) by same ns but handle is different %s \n", dllName);
77570af302Sopenharmony_ci
78570af302Sopenharmony_ci    if(dlclose(handle1))
79570af302Sopenharmony_ci        t_error("dlclose %s failed : %s \n", dllName, dlerror());
80570af302Sopenharmony_ci
81570af302Sopenharmony_ci    if(dlclose(handle2))
82570af302Sopenharmony_ci        t_error("dlclose %s failed : %s \n", dllName, dlerror());
83570af302Sopenharmony_ci}
84570af302Sopenharmony_ci
85570af302Sopenharmony_ci// Test whether dlopen same so by different ns to get different handle.
86570af302Sopenharmony_civoid dlopen_same_so_by_different_ns(char * dllPath_ns)
87570af302Sopenharmony_ci{
88570af302Sopenharmony_ci    Dl_namespace dlns1;
89570af302Sopenharmony_ci    dlns_init(&dlns1, "ns_for_dlopen_same_so_by_different_ns_1");
90570af302Sopenharmony_ci    dlns_create(&dlns1, dllPath_ns);
91570af302Sopenharmony_ci
92570af302Sopenharmony_ci    Dl_namespace dlns2;
93570af302Sopenharmony_ci    dlns_init(&dlns2, "ns_for_dlopen_same_so_by_different_ns_2");
94570af302Sopenharmony_ci    dlns_create(&dlns2, dllPath_ns);
95570af302Sopenharmony_ci
96570af302Sopenharmony_ci    void* handle1 = dlopen_ns(&dlns1, dllName, RTLD_NOW);
97570af302Sopenharmony_ci    if(!handle1)
98570af302Sopenharmony_ci        t_error("dlopen_ns(ns=%s, name=%s) failed : %s \n", dlns1.name, dllName, dlerror());
99570af302Sopenharmony_ci
100570af302Sopenharmony_ci    void* handle2 = dlopen_ns(&dlns2, dllName, RTLD_NOW);
101570af302Sopenharmony_ci    if(!handle2)
102570af302Sopenharmony_ci        t_error("dlopen_ns(ns=%s, name=%s) failed : %s \n", dlns2.name, dllName, dlerror());
103570af302Sopenharmony_ci
104570af302Sopenharmony_ci    if (handle1 == handle2)
105570af302Sopenharmony_ci        t_error("dlopen same so(%s) by same ns but handle is different %s \n", dllName);
106570af302Sopenharmony_ci
107570af302Sopenharmony_ci    if(dlclose(handle1))
108570af302Sopenharmony_ci        t_error("dlclose %s failed : %s \n", dllName, dlerror());
109570af302Sopenharmony_ci
110570af302Sopenharmony_ci    if(dlclose(handle2))
111570af302Sopenharmony_ci        t_error("dlclose %s failed : %s \n", dllName, dlerror());
112570af302Sopenharmony_ci}
113570af302Sopenharmony_ci
114570af302Sopenharmony_ci// Test whether dlopen same so by inherit ns to get same handle.
115570af302Sopenharmony_civoid dlopen_same_so_by_different_inherit_ns(char * dllPath_ns)
116570af302Sopenharmony_ci{
117570af302Sopenharmony_ci    Dl_namespace dlns1;
118570af302Sopenharmony_ci    dlns_init(&dlns1, "ns_for_dlopen_same_so_by_different_inherit_ns_1");
119570af302Sopenharmony_ci    dlns_create(&dlns1, dllPath_ns);
120570af302Sopenharmony_ci
121570af302Sopenharmony_ci    Dl_namespace dlns2;
122570af302Sopenharmony_ci    dlns_init(&dlns2, "ns_for_dlopen_same_so_by_different_inherit_ns_2");
123570af302Sopenharmony_ci    dlns_create2(&dlns2, errPath_ns, 0);
124570af302Sopenharmony_ci    dlns_inherit(&dlns2, &dlns1, dllName);
125570af302Sopenharmony_ci
126570af302Sopenharmony_ci    void* handle1 = dlopen_ns(&dlns1, dllName, RTLD_NOW);
127570af302Sopenharmony_ci    if(!handle1)
128570af302Sopenharmony_ci        t_error("dlopen_ns(ns=%s, name=%s) failed : %s \n", dlns1.name, dllName, dlerror());
129570af302Sopenharmony_ci
130570af302Sopenharmony_ci    void* handle2 = dlopen_ns(&dlns2, dllName, RTLD_NOW);
131570af302Sopenharmony_ci    if(!handle2)
132570af302Sopenharmony_ci        t_error("dlopen_ns(ns=%s, name=%s) failed : %s \n", dlns2.name, dllName, dlerror());
133570af302Sopenharmony_ci
134570af302Sopenharmony_ci    if (handle1 != handle2)
135570af302Sopenharmony_ci        t_error("dlopen same so(%s) by inherit ns but handle is different %s \n", dllName);
136570af302Sopenharmony_ci
137570af302Sopenharmony_ci    if(dlclose(handle1))
138570af302Sopenharmony_ci        t_error("dlclose %s failed : %s \n", dllName, dlerror());
139570af302Sopenharmony_ci
140570af302Sopenharmony_ci    if(dlclose(handle2))
141570af302Sopenharmony_ci        t_error("dlclose %s failed : %s \n", dllName, dlerror());
142570af302Sopenharmony_ci}
143570af302Sopenharmony_ci
144570af302Sopenharmony_civoid dlopen_seperated(char * dllPath_ns)
145570af302Sopenharmony_ci{
146570af302Sopenharmony_ci    Dl_namespace dlns_default;
147570af302Sopenharmony_ci    dlns_get(NULL, &dlns_default);
148570af302Sopenharmony_ci    Dl_namespace dlns1;
149570af302Sopenharmony_ci    dlns_init(&dlns1, "ns_for_no_seperated");
150570af302Sopenharmony_ci    dlns_create2(&dlns1, errPath_ns, 0);
151570af302Sopenharmony_ci    dlns_inherit(&dlns1, &dlns_default, "libc++.so");
152570af302Sopenharmony_ci    void* handle = NULL;
153570af302Sopenharmony_ci    // current ns can't load this so.
154570af302Sopenharmony_ci    handle = dlopen_ns(&dlns1, dllName, RTLD_NOW);
155570af302Sopenharmony_ci    if(handle)
156570af302Sopenharmony_ci        t_error("dlopen_ns(ns=%s, name=%s) failed : %s \n", dlns1.name, dllName, dlerror());
157570af302Sopenharmony_ci
158570af302Sopenharmony_ci    // current ns can load the so by absolute path.
159570af302Sopenharmony_ci    char absolute_path_1[512];
160570af302Sopenharmony_ci    snprintf(absolute_path_1, sizeof(absolute_path_1), "%s/%s", dllPath_ns, dllName);
161570af302Sopenharmony_ci    handle = dlopen_ns(&dlns1, absolute_path_1, RTLD_NOW);
162570af302Sopenharmony_ci    if (!handle)
163570af302Sopenharmony_ci        t_error("%s can load %s by absolute path but failed : %s \n", dlns1.name, absolute_path_1, dlerror());
164570af302Sopenharmony_ci
165570af302Sopenharmony_ci    if(dlclose(handle))
166570af302Sopenharmony_ci        t_error("dlclose %s failed : %s \n", absolute_path_1, dlerror());
167570af302Sopenharmony_ci
168570af302Sopenharmony_ci    // current ns can't load the so by absolute path if it has inaccessible dependent so.
169570af302Sopenharmony_ci    char absolute_path_2[512];
170570af302Sopenharmony_ci    snprintf(absolute_path_2, sizeof(absolute_path_2), "%s/%s", dllPath_ns, SO_HAS_DEPENDENCES);
171570af302Sopenharmony_ci    handle = dlopen_ns(&dlns1, absolute_path_2, RTLD_NOW);
172570af302Sopenharmony_ci    if (handle)
173570af302Sopenharmony_ci        t_error("%s can't load %s by absolute path because but it has inaccessible dependent so but succeed : %s \n", dlns1.name, absolute_path_2, dlerror());
174570af302Sopenharmony_ci}
175570af302Sopenharmony_ci
176570af302Sopenharmony_civoid dlopen_inherit(char* dllPath_ns)
177570af302Sopenharmony_ci{
178570af302Sopenharmony_ci    Dl_namespace dlns_default;
179570af302Sopenharmony_ci    dlns_get(NULL, &dlns_default);
180570af302Sopenharmony_ci    Dl_namespace inherit_A, inherit_B;
181570af302Sopenharmony_ci    dlns_init(&inherit_A, "inherir_error_lib_A");
182570af302Sopenharmony_ci    dlns_init(&inherit_B, "inherir_error_lib_B");
183570af302Sopenharmony_ci    dlns_create2(&inherit_A, NULL, 0);
184570af302Sopenharmony_ci    dlns_create2(&inherit_B, dllPath_ns, 0);
185570af302Sopenharmony_ci    dlns_inherit(&inherit_B, &dlns_default, "libc++.so");
186570af302Sopenharmony_ci
187570af302Sopenharmony_ci    // inherit_A can't load the so because search path is NULL.
188570af302Sopenharmony_ci    void* handle1 = dlopen_ns(&inherit_A, dllName, RTLD_LAZY);
189570af302Sopenharmony_ci    if(handle1){
190570af302Sopenharmony_ci        t_error("dlopen_ns_by_ini_no_inherit handle %s should not open successfully \n", dllName);
191570af302Sopenharmony_ci        dlclose(handle1);
192570af302Sopenharmony_ci    }
193570af302Sopenharmony_ci
194570af302Sopenharmony_ci    // inherit_A can load the so by inherit_B.
195570af302Sopenharmony_ci    dlns_inherit(&inherit_A, &inherit_B, dllName);
196570af302Sopenharmony_ci    void* handle2 = dlopen_ns(&inherit_A, dllName, RTLD_LAZY);
197570af302Sopenharmony_ci    if(!handle2)
198570af302Sopenharmony_ci        t_error("dlopen_ns_by_dlns_inherir handle get error %s open failed : %s \n", dllName, dlerror());
199570af302Sopenharmony_ci
200570af302Sopenharmony_ci    if(dlclose(handle2))
201570af302Sopenharmony_ci        t_error("dlclose_by_dlns_inherir handle %s close failed : %s\n", dllName, dlerror());
202570af302Sopenharmony_ci
203570af302Sopenharmony_ci    // inherit_A can't load the so by inherit ns if the so isn't in shared libs.
204570af302Sopenharmony_ci    dlns_inherit(&inherit_A, &inherit_B, dllName2);
205570af302Sopenharmony_ci    void* handle3 = dlopen_ns(&inherit_A, dllName, RTLD_LAZY);
206570af302Sopenharmony_ci    if(handle3){
207570af302Sopenharmony_ci        t_error("dlopen_ns_by_ini_no_inherit handle2 %s should not open successfully \n", dllName);
208570af302Sopenharmony_ci        dlclose(handle3);
209570af302Sopenharmony_ci    }
210570af302Sopenharmony_ci}
211570af302Sopenharmony_ci
212570af302Sopenharmony_civoid dlopen_inherit_check_can_pass(char* dllPath_ns)
213570af302Sopenharmony_ci{
214570af302Sopenharmony_ci    Dl_namespace dlns_default;
215570af302Sopenharmony_ci    dlns_get(NULL, &dlns_default);
216570af302Sopenharmony_ci    Dl_namespace transitivity_A, transitivity_B, transitivity_C;
217570af302Sopenharmony_ci    dlns_init(&transitivity_A, "transitivity_A");
218570af302Sopenharmony_ci    dlns_init(&transitivity_B, "transitivity_B");
219570af302Sopenharmony_ci    dlns_init(&transitivity_C, "transitivity_C");
220570af302Sopenharmony_ci    dlns_create2(&transitivity_A, NULL, 0);
221570af302Sopenharmony_ci    dlns_create2(&transitivity_B, NULL, 0);
222570af302Sopenharmony_ci    dlns_create2(&transitivity_C, dllPath_ns, 0);
223570af302Sopenharmony_ci    dlns_inherit(&transitivity_A, &transitivity_B, NULL);
224570af302Sopenharmony_ci    dlns_inherit(&transitivity_B, &transitivity_C, dllName);
225570af302Sopenharmony_ci    dlns_inherit(&transitivity_C, &dlns_default, "libc++.so");
226570af302Sopenharmony_ci
227570af302Sopenharmony_ci    void* handleB = dlopen_ns(&transitivity_B, dllName, RTLD_LAZY);
228570af302Sopenharmony_ci    if(!handleB)
229570af302Sopenharmony_ci        t_error("dlopen_ns_by_inherit_transitivity handleB get error %s open failed : %s \n", dllName, dlerror());
230570af302Sopenharmony_ci
231570af302Sopenharmony_ci    void* handleC = dlopen_ns(&transitivity_C, dllName, RTLD_LAZY);
232570af302Sopenharmony_ci    if(!handleC)
233570af302Sopenharmony_ci        t_error("dlopen_ns_by_inherit_transitivity handleC get error %s open failed : %s \n", dllName, dlerror());
234570af302Sopenharmony_ci
235570af302Sopenharmony_ci    if(dlclose(handleC))
236570af302Sopenharmony_ci        t_error("dlclose_by_inherit_transitivity handleC %s close failed : %s\n", dllName, dlerror());
237570af302Sopenharmony_ci    if(dlclose(handleB))
238570af302Sopenharmony_ci        t_error("dlclose_by_inherit_transitivity handleB %s close failed : %s\n", dllName, dlerror());
239570af302Sopenharmony_ci
240570af302Sopenharmony_ci    // transitivity_A can't load so because inherit can't pass.
241570af302Sopenharmony_ci    void* handleA = dlopen_ns(&transitivity_A, dllName, RTLD_LAZY);
242570af302Sopenharmony_ci    if(handleA){
243570af302Sopenharmony_ci        t_error("dlopen_ns_by_inherit_transitivity handleA %s should not open successfully \n", dllName);
244570af302Sopenharmony_ci        dlclose(handleA);
245570af302Sopenharmony_ci    }
246570af302Sopenharmony_ci}
247570af302Sopenharmony_ci
248570af302Sopenharmony_civoid dlopen_test_dlns_create2()
249570af302Sopenharmony_ci{
250570af302Sopenharmony_ci    Dl_namespace dlns;
251570af302Sopenharmony_ci    dlns_init(&dlns, "ns_for_create2");
252570af302Sopenharmony_ci    // ns_for_create2 doesn't exist, it will use default ns to search so.
253570af302Sopenharmony_ci    void* handle = dlopen_ns(&dlns, dllName, RTLD_LAZY);
254570af302Sopenharmony_ci    if(!handle)
255570af302Sopenharmony_ci        t_error("dlopen_ns %s use a non-existent ns failed: %s\n", dllName, dlerror());
256570af302Sopenharmony_ci
257570af302Sopenharmony_ci    if(dlclose(handle))
258570af302Sopenharmony_ci        t_error("dlclose %s failed : %s \n", dllName, dlerror());
259570af302Sopenharmony_ci
260570af302Sopenharmony_ci    // 0: ns_for_create2 doesn't inherit default ns.
261570af302Sopenharmony_ci    dlns_create2(&dlns, errPath_ns, 0);
262570af302Sopenharmony_ci    void* handle2 = dlopen_ns(&dlns, dllName, RTLD_LAZY);
263570af302Sopenharmony_ci    if(handle2)
264570af302Sopenharmony_ci        t_error("%s namespace can't see %s but dlopen succee.\n", "ns_for_create2", dllName);
265570af302Sopenharmony_ci}
266570af302Sopenharmony_ci
267570af302Sopenharmony_ciint main(int argc, char *argv[])
268570af302Sopenharmony_ci{
269570af302Sopenharmony_ci    char buf[512],path[512];
270570af302Sopenharmony_ci    char* i;
271570af302Sopenharmony_ci    //带so的路径
272570af302Sopenharmony_ci    if (!t_pathrel(buf, sizeof buf, argv[0], "libdlopen_ns_dso.so")) {
273570af302Sopenharmony_ci        t_error("failed to obtain relative path to libdlopen_ns_dso.so\n");
274570af302Sopenharmony_ci        return 1;
275570af302Sopenharmony_ci	}
276570af302Sopenharmony_ci    //包含so的路径
277570af302Sopenharmony_ci    if (!t_pathrel(path, sizeof path, argv[0], "")) {
278570af302Sopenharmony_ci        t_error("failed to obtain relative path to path\n");
279570af302Sopenharmony_ci        return 1;
280570af302Sopenharmony_ci	}
281570af302Sopenharmony_ci    path[strlen (path) -1 ] ='\0';
282570af302Sopenharmony_ci    main_dlopen_ndk_so();
283570af302Sopenharmony_ci    system_so_dlopen_ndk_so();
284570af302Sopenharmony_ci    ndk_so_dlopen_default_ns_so();
285570af302Sopenharmony_ci    dlopen_same_so_twice_by_same_ns(path);
286570af302Sopenharmony_ci    dlopen_same_so_by_different_ns(path);
287570af302Sopenharmony_ci    dlopen_same_so_by_different_inherit_ns(path);
288570af302Sopenharmony_ci    dlopen_seperated(path);
289570af302Sopenharmony_ci    dlopen_test_dlns_create2();
290570af302Sopenharmony_ci    dlopen_inherit(path);
291570af302Sopenharmony_ci    dlopen_inherit_check_can_pass(path);
292570af302Sopenharmony_ci
293570af302Sopenharmony_ci    return t_status;
294570af302Sopenharmony_ci}