1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <array>
17 #include "../tests/test_helper.h"
18 #include "defect_scan_aux_api.h"
19
20 namespace panda::defect_scan_aux::test {
21 class DefectScanAuxTest {
22 public:
DefectScanAuxTest(std::string_view abc_filename)23 explicit DefectScanAuxTest(std::string_view abc_filename)
24 {
25 abc_file_ = AbcFile::Open(abc_filename);
26 TestHelper::ExpectTrue(abc_file_ != nullptr);
27 }
28
29 ~DefectScanAuxTest() = default;
30
GetAbcFileInstance() const31 const std::unique_ptr<const AbcFile> &GetAbcFileInstance() const
32 {
33 return abc_file_;
34 }
35
CheckFunction(std::string_view func_name) const36 const Function *CheckFunction(std::string_view func_name) const
37 {
38 auto func0 = abc_file_->GetFunctionByName(func_name);
39 TestHelper::ExpectTrue(func0 != nullptr);
40 TestHelper::ExpectEqual(func0->GetFunctionName(), func_name);
41 TestHelper::ExpectTrue(func0->GetAbcFileInstance() == abc_file_.get());
42 return func0;
43 }
44
ContainDefinedFunction(const Function * par_func,std::string_view func_name) const45 bool ContainDefinedFunction(const Function *par_func, std::string_view func_name) const
46 {
47 size_t df_cnt0 = par_func->GetDefinedFunctionCount();
48 for (size_t i = 0; i < df_cnt0; ++i) {
49 auto df = par_func->GetDefinedFunctionByIndex(i);
50 if (df->GetFunctionName() == func_name) {
51 TestHelper::ExpectTrue(df->GetParentFunction() == par_func);
52 return true;
53 }
54 }
55 return false;
56 }
57
ContainMemberFunction(const Class * class0,std::string_view func_name) const58 bool ContainMemberFunction(const Class *class0, std::string_view func_name) const
59 {
60 size_t mf_func_count = class0->GetMemberFunctionCount();
61 for (size_t i = 0; i < mf_func_count; ++i) {
62 auto mf = class0->GetMemberFunctionByIndex(i);
63 if (mf->GetFunctionName() == func_name) {
64 TestHelper::ExpectTrue(class0->GetMemberFunctionByName(func_name) == mf);
65 return true;
66 }
67 }
68
69 auto par_class = class0->GetParentClass();
70 if (par_class != nullptr) {
71 return ContainMemberFunction(par_class, func_name);
72 }
73 return false;
74 }
75
CheckClass(std::string_view class_name) const76 const Class *CheckClass(std::string_view class_name) const
77 {
78 auto *class0 = abc_file_->GetClassByName(class_name);
79 TestHelper::ExpectTrue(class0 != nullptr);
80 TestHelper::ExpectEqual(class0->GetClassName(), class_name);
81 TestHelper::ExpectTrue(class0->GetAbcFileInstance() == abc_file_.get());
82 size_t mf_func_count = class0->GetMemberFunctionCount();
83 TestHelper::ExpectTrue(mf_func_count >= 1);
84 auto mf_func0 = class0->GetMemberFunctionByIndex(0);
85 TestHelper::ExpectTrue(abc_file_->GetFunctionByName(class_name) == mf_func0);
86 TestHelper::ExpectTrue(class0->GetMemberFunctionByName(class_name) == mf_func0);
87 TestHelper::ExpectTrue(mf_func0->GetClass() == class0);
88 CheckFunction(class_name);
89 return class0;
90 }
91
92 private:
93 std::unique_ptr<const AbcFile> abc_file_ {nullptr};
94 };
95 } // namespace panda::defect_scan_aux::test
96
97 // TODO(wangyantian): use the test framework to refactor these codes
98 using TestHelper = panda::defect_scan_aux::test::TestHelper;
99 using Inst = panda::defect_scan_aux::Inst;
100 using InstType = panda::defect_scan_aux::InstType;
101 using DefectScanAuxTest = panda::defect_scan_aux::test::DefectScanAuxTest;
main()102 int main()
103 {
104 constexpr size_t TESTCASE_NUM = 5;
105 constexpr std::array<std::string_view, TESTCASE_NUM> TEST_CASE_LIST = {
106 "defectscanaux_tests/unittest/module_info_test.abc", "defectscanaux_tests/unittest/define_info_test.abc",
107 "defectscanaux_tests/unittest/callee_info_test.abc", "defectscanaux_tests/unittest/debug_info_test.abc",
108 "defectscanaux_tests/unittest/graph_test.abc",
109
110 };
111
112 std::cout << "===== [libark_defect_scan_aux] Running Unittest =====" << std::endl;
113 {
114 constexpr size_t MODULE_INFO_TEST_INDEX = 0;
115 std::cout << " --- Running Testcase: " << TEST_CASE_LIST[MODULE_INFO_TEST_INDEX] << " ---" << std::endl;
116 DefectScanAuxTest ds_test(TEST_CASE_LIST[MODULE_INFO_TEST_INDEX]);
117 auto &abc_file = ds_test.GetAbcFileInstance();
118 size_t def_func_cnt = abc_file->GetDefinedFunctionCount();
119 TestHelper::ExpectEqual(def_func_cnt, 8);
120 size_t def_class_cnt = abc_file->GetDefinedClassCount();
121 TestHelper::ExpectEqual(def_class_cnt, 2);
122
123 // check module info
124 TestHelper::ExpectTrue(abc_file->IsModule());
125 // check exported class
126 std::string inter_name0 = abc_file->GetInternalNameByExportName("UInput");
127 TestHelper::ExpectEqual(inter_name0, "UserInput");
128 auto ex_class = abc_file->GetExportClassByExportName("UInput");
129 TestHelper::ExpectEqual(ex_class->GetClassName(), "#2#UserInput");
130 ds_test.CheckClass("#2#UserInput");
131 size_t mf_func_count0 = ex_class->GetMemberFunctionCount();
132 TestHelper::ExpectEqual(mf_func_count0, 2);
133 auto mf_func0_1 = ex_class->GetMemberFunctionByIndex(1);
134 TestHelper::ExpectEqual(mf_func0_1->GetFunctionName(), "getText");
135 TestHelper::ExpectTrue(mf_func0_1->GetClass() == ex_class);
136 ds_test.CheckFunction("getText");
137 auto par_class = ex_class->GetParentClass();
138 TestHelper::ExpectTrue(par_class != nullptr);
139 TestHelper::ExpectEqual(par_class->GetClassName(), "#1#InnerUserInput");
140 ds_test.CheckClass("#1#InnerUserInput");
141 size_t mf_func_count1 = par_class->GetMemberFunctionCount();
142 TestHelper::ExpectEqual(mf_func_count1, 2);
143 auto mf_func1_1 = par_class->GetMemberFunctionByIndex(1);
144 TestHelper::ExpectEqual(mf_func1_1->GetFunctionName(), "getTextBase");
145 TestHelper::ExpectTrue(mf_func1_1->GetClass() == par_class);
146 ds_test.CheckFunction("getTextBase");
147
148 // check exported func
149 // func3
150 std::string inter_name1 = abc_file->GetInternalNameByExportName("exFunc3");
151 TestHelper::ExpectEqual(inter_name1, "func3");
152 auto ex_func1 = abc_file->GetExportFunctionByExportName("exFunc3");
153 TestHelper::ExpectEqual(ex_func1->GetFunctionName(), "func3");
154 ds_test.CheckFunction("func3");
155 // func1
156 std::string inter_name2 = abc_file->GetInternalNameByExportName("default");
157 TestHelper::ExpectEqual(inter_name2, "func1");
158 auto ex_func2 = abc_file->GetExportFunctionByExportName("default");
159 TestHelper::ExpectEqual(ex_func2->GetFunctionName(), "func1");
160 ds_test.CheckFunction(inter_name2);
161 // func2
162 std::string inter_name3 = abc_file->GetInternalNameByExportName("func2");
163 TestHelper::ExpectEqual(inter_name3, "func2");
164 auto ex_func3 = abc_file->GetExportFunctionByExportName("func2");
165 TestHelper::ExpectEqual(ex_func3->GetFunctionName(), "func2");
166 ds_test.CheckFunction(inter_name3);
167
168 // GetModuleNameByInternalName
169 std::string mod_name0 = abc_file->GetModuleNameByInternalName("var1");
170 TestHelper::ExpectEqual(mod_name0, "./mod1");
171 std::string mod_name1 = abc_file->GetModuleNameByInternalName("ns");
172 TestHelper::ExpectEqual(mod_name1, "./mod2");
173 std::string mod_name2 = abc_file->GetModuleNameByInternalName("var3");
174 TestHelper::ExpectEqual(mod_name2, "../mod3");
175 std::string mod_name3 = abc_file->GetModuleNameByInternalName("local_var4");
176 TestHelper::ExpectEqual(mod_name3, "../../mod4");
177
178 // GetImportNameByInternalName
179 std::string im_name0 = abc_file->GetImportNameByInternalName("var1");
180 TestHelper::ExpectEqual(im_name0, "default");
181 std::string im_name1 = abc_file->GetImportNameByInternalName("var3");
182 TestHelper::ExpectEqual(im_name1, "var3");
183 std::string im_name2 = abc_file->GetImportNameByInternalName("local_var4");
184 TestHelper::ExpectEqual(im_name2, "var4");
185 // GetImportNameByExportName
186 std::string ind_im_name0 = abc_file->GetImportNameByExportName("v");
187 TestHelper::ExpectEqual(ind_im_name0, "v5");
188 std::string ind_im_name1 = abc_file->GetImportNameByExportName("foo");
189 TestHelper::ExpectEqual(ind_im_name1, "foo");
190 // GetModuleNameByExportName
191 std::string ind_mod_name0 = abc_file->GetModuleNameByExportName("v");
192 TestHelper::ExpectEqual(ind_mod_name0, "./mod5");
193 std::string ind_mod_name1 = abc_file->GetModuleNameByExportName("foo");
194 TestHelper::ExpectEqual(ind_mod_name1, "../../mod7");
195 std::cout << " --- Pass ---" << std::endl << std::endl;
196 }
197
198 {
199 constexpr size_t DEFINE_INFO_TEST_INDEX = 1;
200 std::cout << " --- Running Testcase: " << TEST_CASE_LIST[DEFINE_INFO_TEST_INDEX] << " ---" << std::endl;
201 DefectScanAuxTest ds_test(TEST_CASE_LIST[DEFINE_INFO_TEST_INDEX]);
202 auto &abc_file = ds_test.GetAbcFileInstance();
203 TestHelper::ExpectTrue(abc_file->IsModule());
204 size_t def_func_cnt = abc_file->GetDefinedFunctionCount();
205 TestHelper::ExpectEqual(def_func_cnt, 30);
206 size_t def_class_cnt = abc_file->GetDefinedClassCount();
207 TestHelper::ExpectEqual(def_class_cnt, 10);
208
209 // check each defined func
210 // func_main_0
211 auto f0 = ds_test.CheckFunction("func_main_0");
212 TestHelper::ExpectTrue(f0->GetClass() == nullptr);
213 TestHelper::ExpectTrue(f0->GetParentFunction() == nullptr);
214 size_t dc_cnt0 = f0->GetDefinedClassCount();
215 TestHelper::ExpectEqual(dc_cnt0, 2);
216 TestHelper::ExpectEqual(f0->GetDefinedClassByIndex(0)->GetClassName(), "#1#Bar");
217 TestHelper::ExpectEqual(f0->GetDefinedClassByIndex(1)->GetClassName(), "#6#ExampleClass1");
218 size_t df_cnt0 = f0->GetDefinedFunctionCount();
219 TestHelper::ExpectEqual(df_cnt0, 12);
220 TestHelper::ExpectTrue(ds_test.ContainDefinedFunction(f0, "func1"));
221 TestHelper::ExpectTrue(ds_test.ContainDefinedFunction(f0, "func2"));
222 TestHelper::ExpectFalse(ds_test.ContainDefinedFunction(f0, "func3"));
223 TestHelper::ExpectTrue(ds_test.ContainDefinedFunction(f0, "func6"));
224 TestHelper::ExpectTrue(ds_test.ContainDefinedFunction(f0, "getName"));
225 TestHelper::ExpectTrue(ds_test.ContainDefinedFunction(f0, "setName"));
226 TestHelper::ExpectTrue(ds_test.ContainDefinedFunction(f0, "func9"));
227 TestHelper::ExpectTrue(ds_test.ContainDefinedFunction(f0, "func10"));
228 TestHelper::ExpectTrue(ds_test.ContainDefinedFunction(f0, "func17"));
229 // func2
230 auto f1 = ds_test.CheckFunction("func2");
231 TestHelper::ExpectEqual(f1->GetArgCount(), 5);
232 size_t df_cnt1 = f1->GetDefinedFunctionCount();
233 TestHelper::ExpectEqual(df_cnt1, 2);
234 TestHelper::ExpectTrue(ds_test.ContainDefinedFunction(f1, "func4"));
235 // func10
236 auto f2 = ds_test.CheckFunction("func10");
237 TestHelper::ExpectEqual(f2->GetArgCount(), 3);
238 size_t dc_cnt2 = f2->GetDefinedClassCount();
239 TestHelper::ExpectEqual(dc_cnt2, 2);
240 TestHelper::ExpectEqual(f2->GetDefinedClassByIndex(0)->GetClassName(), "#2#Bar");
241 TestHelper::ExpectEqual(f2->GetDefinedClassByIndex(1)->GetClassName(), "#3#Bar2");
242 size_t df_cnt2 = f2->GetDefinedFunctionCount();
243 TestHelper::ExpectEqual(df_cnt2, 7);
244 TestHelper::ExpectTrue(ds_test.ContainDefinedFunction(f2, "baseFoo1"));
245 TestHelper::ExpectTrue(ds_test.ContainDefinedFunction(f2, "func12"));
246 TestHelper::ExpectTrue(ds_test.ContainDefinedFunction(f2, "#4#"));
247 TestHelper::ExpectTrue(ds_test.ContainDefinedFunction(f2, "#5#"));
248 TestHelper::ExpectTrue(ds_test.ContainDefinedFunction(f2, "func15"));
249
250 // check each defined class
251 // #1#Bar
252 auto class0 = ds_test.CheckClass("#1#Bar");
253 TestHelper::ExpectTrue(class0->GetParentClass() == nullptr);
254 TestHelper::ExpectTrue(class0->GetDefineFunction() == f0);
255 size_t mf_count0 = class0->GetMemberFunctionCount();
256 TestHelper::ExpectEqual(mf_count0, 5);
257 TestHelper::ExpectTrue(ds_test.ContainMemberFunction(class0, "func6"));
258 TestHelper::ExpectTrue(ds_test.ContainMemberFunction(class0, "getName"));
259 TestHelper::ExpectTrue(ds_test.ContainMemberFunction(class0, "setName"));
260 TestHelper::ExpectTrue(ds_test.ContainMemberFunction(class0, "func9"));
261 // #3#Bar2
262 auto class1 = ds_test.CheckClass("#3#Bar2");
263 TestHelper::ExpectTrue(class1->GetParentClass() != nullptr);
264 TestHelper::ExpectTrue(class1->GetDefineFunction() == abc_file->GetFunctionByName("func10"));
265 size_t mf_count1 = class1->GetMemberFunctionCount();
266 TestHelper::ExpectEqual(mf_count1, 5);
267 TestHelper::ExpectTrue(ds_test.ContainMemberFunction(class1, "baseFoo1"));
268 TestHelper::ExpectTrue(ds_test.ContainMemberFunction(class1, "func12"));
269 TestHelper::ExpectTrue(ds_test.ContainMemberFunction(class1, "func15"));
270 // #8#ExampleClass2
271 auto class2 = ds_test.CheckClass("#8#ExampleClass2");
272 TestHelper::ExpectTrue(class2->GetParentClass() == abc_file->GetClassByName("#7#ExampleClass1"));
273 TestHelper::ExpectFalse(ds_test.ContainMemberFunction(class2, "func17"));
274 TestHelper::ExpectTrue(ds_test.ContainMemberFunction(class2, "func19"));
275 // #9#ExtendService
276 auto class3 = ds_test.CheckClass("#9#ExtendService");
277 TestHelper::ExpectTrue(class3->GetParentClass() == nullptr);
278 TestHelper::ExpectEqual(class3->GetParentClassName(), "BaseService");
279 TestHelper::ExpectEqual(class3->GetParClassExternalModuleName(), "../base/service");
280 TestHelper::ExpectTrue(class3->GetParClassGlobalVarName().empty());
281 // #10#ExtendPhoneService
282 auto class4 = ds_test.CheckClass("#10#ExtendPhoneService");
283 TestHelper::ExpectTrue(class4->GetParentClass() == nullptr);
284 TestHelper::ExpectEqual(class4->GetParentClassName(), "PhoneService");
285 TestHelper::ExpectEqual(class4->GetParClassExternalModuleName(), "../mod1");
286 TestHelper::ExpectTrue(class4->GetParClassGlobalVarName().empty());
287 // #11#ExtendDataSource
288 auto class5 = ds_test.CheckClass("#11#ExtendDataSource");
289 TestHelper::ExpectTrue(class5->GetParentClass() == nullptr);
290 TestHelper::ExpectEqual(class5->GetParentClassName(), "BasicDataSource");
291 TestHelper::ExpectTrue(class5->GetParClassExternalModuleName().empty());
292 TestHelper::ExpectEqual(class5->GetParClassGlobalVarName(), "globalvar");
293 // #12#ExtendDataItem
294 auto class6 = ds_test.CheckClass("#12#ExtendDataItem");
295 TestHelper::ExpectTrue(class6->GetParentClass() == nullptr);
296 TestHelper::ExpectEqual(class6->GetParentClassName(), "DataItem");
297 TestHelper::ExpectTrue(class6->GetParClassExternalModuleName().empty());
298 TestHelper::ExpectEqual(class6->GetParClassGlobalVarName(), "globalvar2.Data");
299 std::cout << " --- Pass ---" << std::endl << std::endl;
300 }
301
302 {
303 constexpr size_t CALLEE_INFO_TEST_INDEX = 2;
304 std::cout << " --- Running Testcase: " << TEST_CASE_LIST[CALLEE_INFO_TEST_INDEX] << " ---" << std::endl;
305 DefectScanAuxTest ds_test(TEST_CASE_LIST[CALLEE_INFO_TEST_INDEX]);
306 auto &abc_file = ds_test.GetAbcFileInstance();
307 TestHelper::ExpectTrue(abc_file->IsModule());
308 size_t def_func_cnt = abc_file->GetDefinedFunctionCount();
309 TestHelper::ExpectEqual(def_func_cnt, 19);
310 size_t def_class_cnt = abc_file->GetDefinedClassCount();
311 TestHelper::ExpectEqual(def_class_cnt, 2);
312
313 // check callee info of each func
314 // foo
315 auto f0 = abc_file->GetFunctionByName("foo");
316 size_t ci_cnt0 = f0->GetCalleeInfoCount();
317 TestHelper::ExpectEqual(ci_cnt0, 6);
318 auto ci0_0 = f0->GetCalleeInfoByIndex(0);
319 TestHelper::ExpectTrue(f0->GetCalleeInfoByCallInst(ci0_0->GetCallInst()) == ci0_0);
320 TestHelper::ExpectTrue(ci0_0->IsCalleeDefinite());
321 TestHelper::ExpectEqual(ci0_0->GetCalleeArgCount(), 1);
322 TestHelper::ExpectTrue(ci0_0->GetCaller() == f0);
323 TestHelper::ExpectTrue(ci0_0->GetCallee() == abc_file->GetFunctionByName("func2"));
324 auto ci0_1 = f0->GetCalleeInfoByIndex(1);
325 TestHelper::ExpectEqual(f0->GetCalleeInfoByCallInst(ci0_1->GetCallInst()), ci0_1);
326 TestHelper::ExpectFalse(ci0_1->IsCalleeDefinite());
327 TestHelper::ExpectEqual(ci0_1->GetCalleeArgCount(), 1);
328 TestHelper::ExpectTrue(ci0_1->GetCallee() == nullptr);
329 TestHelper::ExpectEqual(ci0_1->GetFunctionName(), "log");
330 TestHelper::ExpectEqual(ci0_1->GetGlobalVarName(), "console");
331 auto ci0_2 = f0->GetCalleeInfoByIndex(2);
332 TestHelper::ExpectFalse(ci0_2->IsCalleeDefinite());
333 TestHelper::ExpectEqual(ci0_2->GetCalleeArgCount(), 1);
334 TestHelper::ExpectTrue(ci0_2->GetCallee() == nullptr);
335 TestHelper::ExpectEqual(ci0_2->GetFunctionName(), "logd");
336 TestHelper::ExpectEqual(ci0_2->GetGlobalVarName(), "globalvar.hilog");
337 auto ci0_3 = f0->GetCalleeInfoByIndex(3);
338 TestHelper::ExpectTrue(ci0_3->IsCalleeDefinite());
339 TestHelper::ExpectTrue(ci0_3->GetCallee() == abc_file->GetFunctionByName("func2"));
340 auto ci0_4 = f0->GetCalleeInfoByIndex(4);
341 TestHelper::ExpectTrue(ci0_4->IsCalleeDefinite());
342 TestHelper::ExpectEqual(ci0_4->GetCalleeArgCount(), 2);
343 TestHelper::ExpectTrue(ci0_4->GetCallee() == abc_file->GetFunctionByName("func1"));
344 auto ci0_5 = f0->GetCalleeInfoByIndex(5);
345 TestHelper::ExpectFalse(ci0_5->IsCalleeDefinite());
346 TestHelper::ExpectEqual(ci0_5->GetFunctionName(), "bar");
347 // foo1
348 auto f1 = abc_file->GetFunctionByName("foo1");
349 size_t ci_cnt1 = f1->GetCalleeInfoCount();
350 TestHelper::ExpectEqual(ci_cnt1, 3);
351 auto ci1_0 = f1->GetCalleeInfoByIndex(0);
352 TestHelper::ExpectTrue(ci1_0->IsCalleeDefinite());
353 TestHelper::ExpectTrue(ci1_0->GetCallee() == abc_file->GetFunctionByName("fn"));
354 auto ci1_1 = f1->GetCalleeInfoByIndex(1);
355 TestHelper::ExpectTrue(ci1_1->IsCalleeDefinite());
356 TestHelper::ExpectTrue(ci1_1->GetCallee() == abc_file->GetFunctionByName("fn"));
357 auto ci1_2 = f1->GetCalleeInfoByIndex(2);
358 TestHelper::ExpectFalse(ci1_2->IsCalleeDefinite());
359 TestHelper::ExpectEqual(ci1_2->GetFunctionName(), "bind");
360 // #2#ColorPoint
361 auto f2 = abc_file->GetFunctionByName("#2#ColorPoint");
362 size_t ci_cnt2 = f2->GetCalleeInfoCount();
363 TestHelper::ExpectEqual(ci_cnt2, 1);
364 auto ci2_0 = f2->GetCalleeInfoByIndex(0);
365 TestHelper::ExpectTrue(ci2_0->IsCalleeDefinite());
366 TestHelper::ExpectTrue(ci2_0->GetClass() == abc_file->GetClassByName("#1#Point"));
367 TestHelper::ExpectTrue(ci2_0->GetCallee() == abc_file->GetFunctionByName("#1#Point"));
368 // func6
369 auto f3 = abc_file->GetFunctionByName("func6");
370 size_t ci_cnt3 = f3->GetCalleeInfoCount();
371 TestHelper::ExpectEqual(ci_cnt3, 1);
372 auto ci3_0 = f3->GetCalleeInfoByIndex(0);
373 TestHelper::ExpectFalse(ci3_0->IsCalleeDefinite());
374 TestHelper::ExpectEqual(ci3_0->GetFunctionName(), "bar");
375 TestHelper::ExpectEqual(ci3_0->GetExternalModuleName(), "./mod2");
376 // func7
377 auto f4 = abc_file->GetFunctionByName("func7");
378 size_t ci_cnt4 = f4->GetCalleeInfoCount();
379 TestHelper::ExpectEqual(ci_cnt4, 2);
380 auto ci4_0 = f4->GetCalleeInfoByIndex(0);
381 TestHelper::ExpectFalse(ci4_0->IsCalleeDefinite());
382 TestHelper::ExpectEqual(ci4_0->GetCalleeArgCount(), 2);
383 TestHelper::ExpectEqual(ci4_0->GetFunctionName(), "sum");
384 TestHelper::ExpectEqual(ci4_0->GetExternalModuleName(), "../../mod1");
385 auto ci4_1 = f4->GetCalleeInfoByIndex(1);
386 TestHelper::ExpectFalse(ci4_1->IsCalleeDefinite());
387 TestHelper::ExpectEqual(ci4_1->GetCalleeArgCount(), 2);
388 TestHelper::ExpectEqual(ci4_1->GetFunctionName(), "sub");
389 TestHelper::ExpectEqual(ci4_1->GetExternalModuleName(), "../../mod1");
390 // callMemberFunc1
391 auto f5 = abc_file->GetFunctionByName("callMemberFunc1");
392 size_t ci_cnt5 = f5->GetCalleeInfoCount();
393 TestHelper::ExpectEqual(ci_cnt5, 2);
394 auto ci5_0 = f5->GetCalleeInfoByIndex(0);
395 TestHelper::ExpectTrue(ci5_0->IsCalleeDefinite());
396 TestHelper::ExpectTrue(ci5_0->GetClass() != nullptr);
397 TestHelper::ExpectEqual(ci5_0->GetClass(), abc_file->GetClassByName("#1#Point"));
398 TestHelper::ExpectTrue(ci5_0->GetCallee() != nullptr);
399 TestHelper::ExpectEqual(ci5_0->GetCallee(), abc_file->GetFunctionByName("getCoordinateX"));
400 auto ci5_1 = f5->GetCalleeInfoByIndex(1);
401 TestHelper::ExpectTrue(ci5_1->IsCalleeDefinite());
402 TestHelper::ExpectTrue(ci5_1->GetClass() != nullptr);
403 TestHelper::ExpectEqual(ci5_1->GetClass(), abc_file->GetClassByName("#1#Point"));
404 TestHelper::ExpectTrue(ci5_1->GetCallee() != nullptr);
405 TestHelper::ExpectEqual(ci5_1->GetCallee(), abc_file->GetFunctionByName("setCoordinateX"));
406 // callMemberFunc2
407 auto f6 = abc_file->GetFunctionByName("callMemberFunc2");
408 size_t ci_cnt6 = f6->GetCalleeInfoCount();
409 TestHelper::ExpectEqual(ci_cnt6, 2);
410 auto ci6_0 = f6->GetCalleeInfoByIndex(0);
411 TestHelper::ExpectTrue(ci6_0->IsCalleeDefinite());
412 TestHelper::ExpectTrue(ci6_0->GetClass() != nullptr);
413 TestHelper::ExpectEqual(ci6_0->GetClass(), abc_file->GetClassByName("#1#Point"));
414 TestHelper::ExpectTrue(ci6_0->GetCallee() != nullptr);
415 TestHelper::ExpectEqual(ci6_0->GetCallee(), abc_file->GetFunctionByName("plus"));
416 auto ci6_1 = f6->GetCalleeInfoByIndex(1);
417 TestHelper::ExpectFalse(ci6_1->IsCalleeDefinite());
418 TestHelper::ExpectEqual(ci6_1->GetFunctionName(), "sub");
419 TestHelper::ExpectEqual(ci6_1->GetExternalModuleName(), "");
420 TestHelper::ExpectEqual(ci6_1->GetGlobalVarName(), "");
421 // callExClassMemberFunc1
422 auto f7 = abc_file->GetFunctionByName("callExClassMemberFunc1");
423 size_t ci_cnt7 = f7->GetCalleeInfoCount();
424 TestHelper::ExpectEqual(ci_cnt7, 1);
425 auto ci7_0 = f7->GetCalleeInfoByIndex(0);
426 TestHelper::ExpectFalse(ci7_0->IsCalleeDefinite());
427 TestHelper::ExpectTrue(ci7_0->GetClass() == nullptr);
428 TestHelper::ExpectEqual(ci7_0->GetFunctionName(), "makePhoneCall");
429 TestHelper::ExpectEqual(ci7_0->GetExternalModuleName(), "../../mod1");
430 TestHelper::ExpectEqual(ci7_0->GetGlobalVarName(), "");
431 std::cout << " --- Pass ---" << std::endl << std::endl;
432 }
433
434 {
435 constexpr size_t DEBUG_INFO_TEST_INDEX = 3;
436 std::cout << " --- Running Testcase: " << TEST_CASE_LIST[DEBUG_INFO_TEST_INDEX] << " ---" << std::endl;
437 DefectScanAuxTest ds_test(TEST_CASE_LIST[DEBUG_INFO_TEST_INDEX]);
438 auto &abc_file = ds_test.GetAbcFileInstance();
439 TestHelper::ExpectFalse(abc_file->IsModule());
440
441 // check debug info, whether the line number obtained from call inst is correct
442 auto f0 = abc_file->GetFunctionByName("foo");
443 TestHelper::ExpectEqual(f0->GetCalleeInfoCount(), 3);
444 auto ci0_0 = f0->GetCalleeInfoByIndex(0);
445 // callarg0
446 TestHelper::ExpectEqual(abc_file->GetLineNumberByInst(f0, ci0_0->GetCallInst()), 33);
447 auto ci0_1 = f0->GetCalleeInfoByIndex(1);
448 // callspread
449 TestHelper::ExpectEqual(abc_file->GetLineNumberByInst(f0, ci0_1->GetCallInst()), 37);
450 auto ci0_2 = f0->GetCalleeInfoByIndex(2);
451 // callirange
452 TestHelper::ExpectEqual(abc_file->GetLineNumberByInst(f0, ci0_2->GetCallInst()), 39);
453 // ctor of Data
454 auto f1 = abc_file->GetFunctionByName("#2#Data");
455 TestHelper::ExpectEqual(f1->GetCalleeInfoCount(), 1);
456 auto ci1_0 = f1->GetCalleeInfoByIndex(0);
457 // supercall
458 TestHelper::ExpectEqual(abc_file->GetLineNumberByInst(f1, ci1_0->GetCallInst()), 59);
459 // bar
460 auto f2 = abc_file->GetFunctionByName("bar");
461 TestHelper::ExpectEqual(f2->GetCalleeInfoCount(), 2);
462 auto ci2_0 = f2->GetCalleeInfoByIndex(0);
463 // callithisrange
464 TestHelper::ExpectEqual(abc_file->GetLineNumberByInst(f2, ci2_0->GetCallInst()), 69);
465 auto ci2_1 = f2->GetCalleeInfoByIndex(1);
466 // callithisrange
467 TestHelper::ExpectEqual(abc_file->GetLineNumberByInst(f2, ci2_1->GetCallInst()), 74);
468 std::cout << " --- Pass ---" << std::endl << std::endl;
469 }
470
471 {
472 constexpr size_t GRAPH_TEST_INDEX = 4;
473 std::cout << " --- Running Testcase: " << TEST_CASE_LIST[GRAPH_TEST_INDEX] << " ---" << std::endl;
474 DefectScanAuxTest ds_test(TEST_CASE_LIST[GRAPH_TEST_INDEX]);
475 auto f0 = ds_test.CheckFunction("foo");
476
477 // check api of graph
478 auto &graph = f0->GetGraph();
479 auto bb_list = graph.GetBasicBlockList();
480 TestHelper::ExpectEqual(bb_list.size(), 8);
481 TestHelper::ExpectEqual(bb_list.front(), graph.GetStartBasicBlock());
482 TestHelper::ExpectEqual(bb_list.back(), graph.GetEndBasicBlock());
483 std::unordered_map<InstType, uint32_t> inst_cnt_table;
484 graph.VisitAllInstructions([&inst_cnt_table](const Inst &inst) {
485 auto type = inst.GetType();
486 inst_cnt_table.insert_or_assign(type, inst_cnt_table[type] + 1);
487 });
488 uint32_t newobj_cnt = inst_cnt_table[InstType::NEWOBJRANGE_IMM8_IMM8_V8] +
489 inst_cnt_table[InstType::NEWOBJRANGE_IMM16_IMM8_V8] +
490 inst_cnt_table[InstType::WIDE_NEWOBJRANGE_PREF_IMM16_V8];
491 TestHelper::ExpectEqual(newobj_cnt, 2);
492 uint32_t ldlex_cnt = inst_cnt_table[InstType::LDLEXVAR_IMM4_IMM4] +
493 inst_cnt_table[InstType::LDLEXVAR_IMM8_IMM8] +
494 inst_cnt_table[InstType::WIDE_LDLEXVAR_PREF_IMM16_IMM16];
495 TestHelper::ExpectEqual(ldlex_cnt, 7);
496 TestHelper::ExpectEqual(
497 inst_cnt_table[InstType::LDOBJBYNAME_IMM8_ID16] + inst_cnt_table[InstType::LDOBJBYNAME_IMM16_ID16], 4);
498 TestHelper::ExpectEqual(inst_cnt_table[InstType::CALLTHIS1_IMM8_V8_V8], 3);
499 TestHelper::ExpectEqual(inst_cnt_table[InstType::CALLTHIS2_IMM8_V8_V8_V8], 1);
500 TestHelper::ExpectEqual(inst_cnt_table[InstType::DEFINEFUNC_IMM8_ID16_IMM8] +
501 inst_cnt_table[InstType::DEFINEFUNC_IMM16_ID16_IMM8],
502 1);
503 TestHelper::ExpectEqual(inst_cnt_table[InstType::CALLARG0_IMM8], 1);
504 TestHelper::ExpectEqual(inst_cnt_table[InstType::CALLARG1_IMM8_V8], 1);
505 TestHelper::ExpectEqual(inst_cnt_table[InstType::LDEXTERNALMODULEVAR_IMM8] +
506 inst_cnt_table[InstType::WIDE_LDEXTERNALMODULEVAR_PREF_IMM16],
507 1);
508 TestHelper::ExpectEqual(inst_cnt_table[InstType::GETMODULENAMESPACE_IMM8] +
509 inst_cnt_table[InstType::WIDE_GETMODULENAMESPACE_PREF_IMM16],
510 0);
511 TestHelper::ExpectEqual(inst_cnt_table[InstType::OPCODE_PARAMETER], 5);
512
513 // check api of basic block
514 auto bb0 = graph.GetStartBasicBlock();
515 TestHelper::ExpectEqual(bb0.GetPredBlocks().size(), 0);
516 TestHelper::ExpectEqual(bb0.GetSuccBlocks().size(), 1);
517 auto bb1 = bb0.GetSuccBlocks()[0];
518 TestHelper::ExpectEqual(bb1.GetPredBlocks().size(), 1);
519 TestHelper::ExpectEqual(bb1.GetPredBlocks()[0], bb0);
520 auto bb1_succ_bb = bb1.GetSuccBlocks();
521 TestHelper::ExpectEqual(bb1_succ_bb.size(), 2);
522 TestHelper::ExpectTrue(
523 (bb1_succ_bb[0].GetSuccBlocks().size() == 2 && bb1_succ_bb[1].GetSuccBlocks().size() == 1) ||
524 (bb1_succ_bb[0].GetSuccBlocks().size() == 1 && bb1_succ_bb[1].GetSuccBlocks().size() == 2));
525 auto bb2 = graph.GetEndBasicBlock();
526 auto bb2_pred_bb = bb2.GetPredBlocks();
527 TestHelper::ExpectEqual(bb2_pred_bb.size(), 2);
528 auto bb3 = bb2_pred_bb[0];
529 auto bb4 = bb2_pred_bb[1];
530 if (bb3.GetPredBlocks().size() < bb4.GetPredBlocks().size()) {
531 std::swap(bb3, bb4);
532 }
533 TestHelper::ExpectEqual(bb3.GetPredBlocks().size(), 2);
534 TestHelper::ExpectEqual(bb4.GetPredBlocks().size(), 1);
535 TestHelper::ExpectEqual(bb4.GetPredBlocks()[0], bb1);
536
537 // check api of inst
538 size_t ci_cnt = f0->GetCalleeInfoCount();
539 TestHelper::ExpectEqual(ci_cnt, 6);
540 auto ci0 = f0->GetCalleeInfoByIndex(ci_cnt - 1);
541 auto call_inst0 = ci0->GetCallInst();
542 auto call_inst0_ins = call_inst0.GetInputInsts();
543 TestHelper::ExpectEqual(call_inst0_ins.size(), 4);
544 auto call_inst0_in1_type = call_inst0_ins[1].GetType();
545 TestHelper::ExpectEqual(call_inst0_in1_type, InstType::CALLARG0_IMM8);
546 TestHelper::ExpectEqual(call_inst0_ins[1].GetUserInsts().size(), 1);
547 TestHelper::ExpectEqual(call_inst0_ins[1].GetUserInsts()[0], call_inst0);
548 auto call_inst0_in2_type = call_inst0_ins[2].GetType();
549 TestHelper::ExpectEqual(call_inst0_in2_type, InstType::OPCODE_PARAMETER);
550 TestHelper::ExpectEqual(call_inst0_ins[2].GetArgIndex(), 4);
551 auto param1_usrs = call_inst0_ins[2].GetUserInsts();
552 TestHelper::ExpectTrue(std::find(param1_usrs.begin(), param1_usrs.end(), call_inst0) != param1_usrs.end());
553 auto call_inst0_in3_type = call_inst0_ins[3].GetType();
554 TestHelper::ExpectTrue(call_inst0_in3_type == InstType::LDOBJBYNAME_IMM8_ID16 ||
555 call_inst0_in3_type == InstType::LDOBJBYNAME_IMM16_ID16);
556 TestHelper::ExpectEqual(call_inst0_ins[3].GetUserInsts().size(), 1);
557 TestHelper::ExpectEqual(call_inst0_ins[3].GetUserInsts()[0], call_inst0);
558
559 auto ci1 = f0->GetCalleeInfoByIndex(ci_cnt - 2);
560 auto call_inst1 = ci1->GetCallInst();
561 auto call_inst1_ins = call_inst1.GetInputInsts();
562 TestHelper::ExpectEqual(call_inst1_ins.size(), 2);
563 auto call_inst1_in0_type = call_inst1_ins[1].GetType();
564 TestHelper::ExpectTrue(call_inst1_in0_type == InstType::LDEXTERNALMODULEVAR_IMM8 ||
565 call_inst1_in0_type == InstType::WIDE_LDEXTERNALMODULEVAR_PREF_IMM16);
566 TestHelper::ExpectEqual(call_inst1_ins[1].GetUserInsts().size(), 2);
567 TestHelper::ExpectTrue((call_inst1_ins[1].GetUserInsts()[0] == call_inst1) ||
568 (call_inst1_ins[1].GetUserInsts()[1] == call_inst1));
569 auto phi_inst = call_inst1_ins[0];
570 TestHelper::ExpectEqual(phi_inst.GetType(), InstType::OPCODE_PHI);
571 auto phi_inst_ins = phi_inst.GetInputInsts();
572 TestHelper::ExpectEqual(phi_inst_ins.size(), 2);
573 auto phi_inst_in0 = phi_inst_ins[0];
574 auto phi_inst_in1 = phi_inst_ins[1];
575 if (phi_inst_in0.GetType() != InstType::OPCODE_PARAMETER) {
576 std::swap(phi_inst_in0, phi_inst_in1);
577 }
578 TestHelper::ExpectEqual(phi_inst_in0.GetType(), InstType::OPCODE_PARAMETER);
579 TestHelper::ExpectEqual(phi_inst_in0.GetArgIndex(), 3);
580 auto param0_usrs = phi_inst_in0.GetUserInsts();
581 TestHelper::ExpectTrue(std::find(param0_usrs.begin(), param0_usrs.end(), phi_inst) != param0_usrs.end());
582 TestHelper::ExpectEqual(phi_inst_in1.GetType(), InstType::ADD2_IMM8_V8);
583 auto add2_inst_ins = phi_inst_in1.GetInputInsts();
584 TestHelper::ExpectEqual(add2_inst_ins.size(), 2);
585 TestHelper::ExpectEqual(add2_inst_ins[0].GetType(), InstType::OPCODE_PARAMETER);
586 TestHelper::ExpectEqual(add2_inst_ins[1].GetType(), InstType::OPCODE_PARAMETER);
587 std::cout << " --- Pass ---" << std::endl;
588 }
589 std::cout << "===== [libark_defect_scan_aux] Unittest Pass =====" << std::endl;
590
591 return 0;
592 }