• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <gtest/gtest.h>
18 
19 #include <set>
20 #include <unordered_map>
21 
22 #include <android-base/file.h>
23 #include <android-base/strings.h>
24 #include <android-base/test_utils.h>
25 
26 #include "command.h"
27 #include "get_test_data.h"
28 #include "perf_regs.h"
29 #include "read_apk.h"
30 #include "test_util.h"
31 
ReportCmd()32 static std::unique_ptr<Command> ReportCmd() {
33   return CreateCommandInstance("report");
34 }
35 
36 class ReportCommandTest : public ::testing::Test {
37  protected:
Report(const std::string & perf_data,const std::vector<std::string> & add_args=std::vector<std::string> ())38   void Report(
39       const std::string& perf_data,
40       const std::vector<std::string>& add_args = std::vector<std::string>()) {
41     ReportRaw(GetTestData(perf_data), add_args);
42   }
43 
ReportRaw(const std::string & perf_data,const std::vector<std::string> & add_args=std::vector<std::string> ())44   void ReportRaw(
45       const std::string& perf_data,
46       const std::vector<std::string>& add_args = std::vector<std::string>()) {
47     success = false;
48     TemporaryFile tmp_file;
49     std::vector<std::string> args = {
50         "-i", perf_data, "--symfs", GetTestDataDir(), "-o", tmp_file.path};
51     args.insert(args.end(), add_args.begin(), add_args.end());
52     ASSERT_TRUE(ReportCmd()->Run(args));
53     ASSERT_TRUE(android::base::ReadFileToString(tmp_file.path, &content));
54     ASSERT_TRUE(!content.empty());
55     std::vector<std::string> raw_lines = android::base::Split(content, "\n");
56     lines.clear();
57     for (const auto& line : raw_lines) {
58       std::string s = android::base::Trim(line);
59       if (!s.empty()) {
60         lines.push_back(s);
61       }
62     }
63     ASSERT_GE(lines.size(), 2u);
64     success = true;
65   }
66 
67   std::string content;
68   std::vector<std::string> lines;
69   bool success;
70 };
71 
TEST_F(ReportCommandTest,no_option)72 TEST_F(ReportCommandTest, no_option) {
73   Report(PERF_DATA);
74   ASSERT_TRUE(success);
75   ASSERT_NE(content.find("GlobalFunc"), std::string::npos);
76 }
77 
TEST_F(ReportCommandTest,report_symbol_from_elf_file_with_mini_debug_info)78 TEST_F(ReportCommandTest, report_symbol_from_elf_file_with_mini_debug_info) {
79   Report(PERF_DATA_WITH_MINI_DEBUG_INFO);
80   ASSERT_TRUE(success);
81   ASSERT_NE(content.find("GlobalFunc"), std::string::npos);
82 }
83 
TEST_F(ReportCommandTest,sort_option_pid)84 TEST_F(ReportCommandTest, sort_option_pid) {
85   Report(PERF_DATA, {"--sort", "pid"});
86   ASSERT_TRUE(success);
87   size_t line_index = 0;
88   while (line_index < lines.size() &&
89          lines[line_index].find("Pid") == std::string::npos) {
90     line_index++;
91   }
92   ASSERT_LT(line_index + 2, lines.size());
93 }
94 
TEST_F(ReportCommandTest,sort_option_more_than_one)95 TEST_F(ReportCommandTest, sort_option_more_than_one) {
96   Report(PERF_DATA, {"--sort", "comm,pid,dso,symbol"});
97   ASSERT_TRUE(success);
98   size_t line_index = 0;
99   while (line_index < lines.size() &&
100          lines[line_index].find("Overhead") == std::string::npos) {
101     line_index++;
102   }
103   ASSERT_LT(line_index + 1, lines.size());
104   ASSERT_NE(lines[line_index].find("Command"), std::string::npos);
105   ASSERT_NE(lines[line_index].find("Pid"), std::string::npos);
106   ASSERT_NE(lines[line_index].find("Shared Object"), std::string::npos);
107   ASSERT_NE(lines[line_index].find("Symbol"), std::string::npos);
108   ASSERT_EQ(lines[line_index].find("Tid"), std::string::npos);
109 }
110 
TEST_F(ReportCommandTest,children_option)111 TEST_F(ReportCommandTest, children_option) {
112   Report(CALLGRAPH_FP_PERF_DATA, {"--children", "--sort", "symbol"});
113   ASSERT_TRUE(success);
114   std::unordered_map<std::string, std::pair<double, double>> map;
115   for (size_t i = 0; i < lines.size(); ++i) {
116     char name[1024];
117     std::pair<double, double> pair;
118     if (sscanf(lines[i].c_str(), "%lf%%%lf%%%s", &pair.first, &pair.second,
119                name) == 3) {
120       map.insert(std::make_pair(name, pair));
121     }
122   }
123   ASSERT_NE(map.find("GlobalFunc"), map.end());
124   ASSERT_NE(map.find("main"), map.end());
125   auto func_pair = map["GlobalFunc"];
126   auto main_pair = map["main"];
127   ASSERT_GE(main_pair.first, func_pair.first);
128   ASSERT_GE(func_pair.first, func_pair.second);
129   ASSERT_GE(func_pair.second, main_pair.second);
130 }
131 
CheckCalleeMode(std::vector<std::string> & lines)132 static bool CheckCalleeMode(std::vector<std::string>& lines) {
133   bool found = false;
134   for (size_t i = 0; i + 2 < lines.size(); ++i) {
135     if (lines[i].find("GlobalFunc") != std::string::npos &&
136         lines[i + 1].find('|') != std::string::npos &&
137         lines[i + 2].find("main") != std::string::npos) {
138       found = true;
139       break;
140     }
141   }
142   return found;
143 }
144 
CheckCallerMode(std::vector<std::string> & lines)145 static bool CheckCallerMode(std::vector<std::string>& lines) {
146   bool found = false;
147   for (size_t i = 0; i + 2 < lines.size(); ++i) {
148     if (lines[i].find("main") != std::string::npos &&
149         lines[i + 1].find('|') != std::string::npos &&
150         lines[i + 2].find("GlobalFunc") != std::string::npos) {
151       found = true;
152       break;
153     }
154   }
155   return found;
156 }
157 
TEST_F(ReportCommandTest,callgraph_option)158 TEST_F(ReportCommandTest, callgraph_option) {
159   Report(CALLGRAPH_FP_PERF_DATA, {"-g"});
160   ASSERT_TRUE(success);
161   ASSERT_TRUE(CheckCallerMode(lines));
162   Report(CALLGRAPH_FP_PERF_DATA, {"-g", "callee"});
163   ASSERT_TRUE(success);
164   ASSERT_TRUE(CheckCalleeMode(lines));
165   Report(CALLGRAPH_FP_PERF_DATA, {"-g", "caller"});
166   ASSERT_TRUE(success);
167   ASSERT_TRUE(CheckCallerMode(lines));
168 }
169 
AllItemsWithString(std::vector<std::string> & lines,const std::vector<std::string> & strs)170 static bool AllItemsWithString(std::vector<std::string>& lines,
171                                const std::vector<std::string>& strs) {
172   size_t line_index = 0;
173   while (line_index < lines.size() &&
174          lines[line_index].find("Overhead") == std::string::npos) {
175     line_index++;
176   }
177   if (line_index == lines.size() || line_index + 1 == lines.size()) {
178     return false;
179   }
180   line_index++;
181   for (; line_index < lines.size(); ++line_index) {
182     bool exist = false;
183     for (auto& s : strs) {
184       if (lines[line_index].find(s) != std::string::npos) {
185         exist = true;
186         break;
187       }
188     }
189     if (!exist) {
190       return false;
191     }
192   }
193   return true;
194 }
195 
TEST_F(ReportCommandTest,pid_filter_option)196 TEST_F(ReportCommandTest, pid_filter_option) {
197   Report(PERF_DATA_WITH_MULTIPLE_PIDS_AND_TIDS, {"--sort", "pid"});
198   ASSERT_TRUE(success);
199   ASSERT_FALSE(AllItemsWithString(lines, {"17441"}));
200   ASSERT_FALSE(AllItemsWithString(lines, {"17441", "17443"}));
201   Report(PERF_DATA_WITH_MULTIPLE_PIDS_AND_TIDS,
202          {"--sort", "pid", "--pids", "17441"});
203   ASSERT_TRUE(success);
204   ASSERT_TRUE(AllItemsWithString(lines, {"17441"}));
205   Report(PERF_DATA_WITH_MULTIPLE_PIDS_AND_TIDS,
206          {"--sort", "pid", "--pids", "17441,17443"});
207   ASSERT_TRUE(success);
208   ASSERT_TRUE(AllItemsWithString(lines, {"17441", "17443"}));
209 
210   // Test that --pids option is not the same as --tids option.
211   // Thread 17445 and 17441 are in process 17441.
212   Report(PERF_DATA_WITH_MULTIPLE_PIDS_AND_TIDS,
213          {"--sort", "tid", "--pids", "17441"});
214   ASSERT_TRUE(success);
215   ASSERT_NE(content.find("17441"), std::string::npos);
216   ASSERT_NE(content.find("17445"), std::string::npos);
217 }
218 
TEST_F(ReportCommandTest,wrong_pid_filter_option)219 TEST_F(ReportCommandTest, wrong_pid_filter_option) {
220   ASSERT_EXIT(
221       {
222         Report(PERF_DATA_WITH_MULTIPLE_PIDS_AND_TIDS, {"--pids", "2,bogus"});
223         exit(success ? 0 : 1);
224       },
225       testing::ExitedWithCode(1), "invalid id in --pids option: bogus");
226 }
227 
TEST_F(ReportCommandTest,tid_filter_option)228 TEST_F(ReportCommandTest, tid_filter_option) {
229   Report(PERF_DATA_WITH_MULTIPLE_PIDS_AND_TIDS, {"--sort", "tid"});
230   ASSERT_TRUE(success);
231   ASSERT_FALSE(AllItemsWithString(lines, {"17441"}));
232   ASSERT_FALSE(AllItemsWithString(lines, {"17441", "17445"}));
233   Report(PERF_DATA_WITH_MULTIPLE_PIDS_AND_TIDS,
234          {"--sort", "tid", "--tids", "17441"});
235   ASSERT_TRUE(success);
236   ASSERT_TRUE(AllItemsWithString(lines, {"17441"}));
237   Report(PERF_DATA_WITH_MULTIPLE_PIDS_AND_TIDS,
238          {"--sort", "tid", "--tids", "17441,17445"});
239   ASSERT_TRUE(success);
240   ASSERT_TRUE(AllItemsWithString(lines, {"17441", "17445"}));
241 }
242 
TEST_F(ReportCommandTest,wrong_tid_filter_option)243 TEST_F(ReportCommandTest, wrong_tid_filter_option) {
244   ASSERT_EXIT(
245       {
246         Report(PERF_DATA_WITH_MULTIPLE_PIDS_AND_TIDS, {"--tids", "2,bogus"});
247         exit(success ? 0 : 1);
248       },
249       testing::ExitedWithCode(1), "invalid id in --tids option: bogus");
250 }
251 
TEST_F(ReportCommandTest,comm_filter_option)252 TEST_F(ReportCommandTest, comm_filter_option) {
253   Report(PERF_DATA, {"--sort", "comm"});
254   ASSERT_TRUE(success);
255   ASSERT_FALSE(AllItemsWithString(lines, {"t1"}));
256   ASSERT_FALSE(AllItemsWithString(lines, {"t1", "t2"}));
257   Report(PERF_DATA, {"--sort", "comm", "--comms", "t1"});
258   ASSERT_TRUE(success);
259   ASSERT_TRUE(AllItemsWithString(lines, {"t1"}));
260   Report(PERF_DATA, {"--sort", "comm", "--comms", "t1,t2"});
261   ASSERT_TRUE(success);
262   ASSERT_TRUE(AllItemsWithString(lines, {"t1", "t2"}));
263 }
264 
TEST_F(ReportCommandTest,dso_filter_option)265 TEST_F(ReportCommandTest, dso_filter_option) {
266   Report(PERF_DATA, {"--sort", "dso"});
267   ASSERT_TRUE(success);
268   ASSERT_FALSE(AllItemsWithString(lines, {"/t1"}));
269   ASSERT_FALSE(AllItemsWithString(lines, {"/t1", "/t2"}));
270   Report(PERF_DATA, {"--sort", "dso", "--dsos", "/t1"});
271   ASSERT_TRUE(success);
272   ASSERT_TRUE(AllItemsWithString(lines, {"/t1"}));
273   Report(PERF_DATA, {"--sort", "dso", "--dsos", "/t1,/t2"});
274   ASSERT_TRUE(success);
275   ASSERT_TRUE(AllItemsWithString(lines, {"/t1", "/t2"}));
276 }
277 
TEST_F(ReportCommandTest,symbol_filter_option)278 TEST_F(ReportCommandTest, symbol_filter_option) {
279   Report(PERF_DATA_WITH_SYMBOLS, {"--sort", "symbol"});
280   ASSERT_TRUE(success);
281   ASSERT_FALSE(AllItemsWithString(lines, {"func2(int, int)"}));
282   ASSERT_FALSE(AllItemsWithString(lines, {"main", "func2(int, int)"}));
283   Report(PERF_DATA_WITH_SYMBOLS,
284          {"--sort", "symbol", "--symbols", "func2(int, int)"});
285   ASSERT_TRUE(success);
286   ASSERT_TRUE(AllItemsWithString(lines, {"func2(int, int)"}));
287   Report(PERF_DATA_WITH_SYMBOLS,
288          {"--sort", "symbol", "--symbols", "main;func2(int, int)"});
289   ASSERT_TRUE(success);
290   ASSERT_TRUE(AllItemsWithString(lines, {"main", "func2(int, int)"}));
291 }
292 
TEST_F(ReportCommandTest,use_branch_address)293 TEST_F(ReportCommandTest, use_branch_address) {
294   Report(BRANCH_PERF_DATA, {"-b", "--sort", "symbol_from,symbol_to"});
295   std::set<std::pair<std::string, std::string>> hit_set;
296   bool after_overhead = false;
297   for (const auto& line : lines) {
298     if (!after_overhead && line.find("Overhead") != std::string::npos) {
299       after_overhead = true;
300     } else if (after_overhead) {
301       char from[80];
302       char to[80];
303       if (sscanf(line.c_str(), "%*f%%%s%s", from, to) == 2) {
304         hit_set.insert(std::make_pair<std::string, std::string>(from, to));
305       }
306     }
307   }
308   ASSERT_NE(hit_set.find(std::make_pair<std::string, std::string>(
309                 "GlobalFunc", "CalledFunc")),
310             hit_set.end());
311   ASSERT_NE(hit_set.find(std::make_pair<std::string, std::string>(
312                 "CalledFunc", "GlobalFunc")),
313             hit_set.end());
314 }
315 
TEST_F(ReportCommandTest,report_symbols_of_nativelib_in_apk)316 TEST_F(ReportCommandTest, report_symbols_of_nativelib_in_apk) {
317   Report(NATIVELIB_IN_APK_PERF_DATA);
318   ASSERT_TRUE(success);
319   ASSERT_NE(content.find(GetUrlInApk(APK_FILE, NATIVELIB_IN_APK)),
320             std::string::npos);
321   ASSERT_NE(content.find("Func2"), std::string::npos);
322 }
323 
TEST_F(ReportCommandTest,report_more_than_one_event_types)324 TEST_F(ReportCommandTest, report_more_than_one_event_types) {
325   Report(PERF_DATA_WITH_TWO_EVENT_TYPES);
326   ASSERT_TRUE(success);
327   size_t pos = 0;
328   ASSERT_NE(pos = content.find("cpu-cycles", pos), std::string::npos);
329   ASSERT_NE(pos = content.find("Samples:", pos), std::string::npos);
330   ASSERT_NE(pos = content.find("cpu-clock", pos), std::string::npos);
331   ASSERT_NE(pos = content.find("Samples:", pos), std::string::npos);
332 }
333 
TEST_F(ReportCommandTest,report_kernel_symbol)334 TEST_F(ReportCommandTest, report_kernel_symbol) {
335   Report(PERF_DATA_WITH_KERNEL_SYMBOL);
336   ASSERT_TRUE(success);
337   ASSERT_NE(content.find("perf_event_aux"), std::string::npos);
338 }
339 
TEST_F(ReportCommandTest,report_dumped_symbols)340 TEST_F(ReportCommandTest, report_dumped_symbols) {
341   Report(PERF_DATA_WITH_SYMBOLS);
342   ASSERT_TRUE(success);
343   ASSERT_NE(content.find("main"), std::string::npos);
344   Report(PERF_DATA_WITH_SYMBOLS_FOR_NONZERO_MINVADDR_DSO);
345   ASSERT_TRUE(success);
346   ASSERT_NE(content.find("memcpy"), std::string::npos);
347 }
348 
TEST_F(ReportCommandTest,report_dumped_symbols_with_symfs_dir)349 TEST_F(ReportCommandTest, report_dumped_symbols_with_symfs_dir) {
350   // Check if we can report symbols when they appear both in perf.data and symfs dir.
351   Report(PERF_DATA_WITH_SYMBOLS, {"--symfs", GetTestDataDir()});
352   ASSERT_TRUE(success);
353   ASSERT_NE(content.find("main"), std::string::npos);
354 }
355 
TEST_F(ReportCommandTest,report_sort_vaddr_in_file)356 TEST_F(ReportCommandTest, report_sort_vaddr_in_file) {
357   Report(PERF_DATA, {"--sort", "vaddr_in_file"});
358   ASSERT_TRUE(success);
359   ASSERT_NE(content.find("VaddrInFile"), std::string::npos);
360 }
361 
TEST_F(ReportCommandTest,check_build_id)362 TEST_F(ReportCommandTest, check_build_id) {
363   Report(PERF_DATA_FOR_BUILD_ID_CHECK,
364          {"--symfs", GetTestData(CORRECT_SYMFS_FOR_BUILD_ID_CHECK)});
365   ASSERT_TRUE(success);
366   ASSERT_NE(content.find("main"), std::string::npos);
367   ASSERT_EXIT(
368       {
369         Report(PERF_DATA_FOR_BUILD_ID_CHECK,
370                {"--symfs", GetTestData(WRONG_SYMFS_FOR_BUILD_ID_CHECK)});
371         if (!success) {
372           exit(1);
373         }
374         if (content.find("main") != std::string::npos) {
375           exit(2);
376         }
377         exit(0);
378       },
379       testing::ExitedWithCode(0), "Build id mismatch");
380 }
381 
TEST_F(ReportCommandTest,no_show_ip_option)382 TEST_F(ReportCommandTest, no_show_ip_option) {
383   Report(PERF_DATA);
384   ASSERT_TRUE(success);
385   ASSERT_EQ(content.find("unknown"), std::string::npos);
386   Report(PERF_DATA, {"--no-show-ip"});
387   ASSERT_TRUE(success);
388   ASSERT_NE(content.find("unknown"), std::string::npos);
389 }
390 
TEST_F(ReportCommandTest,no_symbol_table_warning)391 TEST_F(ReportCommandTest, no_symbol_table_warning) {
392   ASSERT_EXIT(
393       {
394         Report(PERF_DATA,
395                {"--symfs", GetTestData(SYMFS_FOR_NO_SYMBOL_TABLE_WARNING)});
396         if (!success) {
397           exit(1);
398         }
399         if (content.find("GlobalFunc") != std::string::npos) {
400           exit(2);
401         }
402         exit(0);
403       },
404       testing::ExitedWithCode(0), "elf doesn't contain symbol table");
405 }
406 
TEST_F(ReportCommandTest,read_elf_file_warning)407 TEST_F(ReportCommandTest, read_elf_file_warning) {
408   ASSERT_EXIT(
409       {
410         Report(PERF_DATA,
411                {"--symfs", GetTestData(SYMFS_FOR_READ_ELF_FILE_WARNING)});
412         if (!success) {
413           exit(1);
414         }
415         if (content.find("GlobalFunc") != std::string::npos) {
416           exit(2);
417         }
418         exit(0);
419       },
420       testing::ExitedWithCode(0), "elf: Read failed");
421 }
422 
TEST_F(ReportCommandTest,report_data_generated_by_linux_perf)423 TEST_F(ReportCommandTest, report_data_generated_by_linux_perf) {
424   Report(PERF_DATA_GENERATED_BY_LINUX_PERF);
425   ASSERT_TRUE(success);
426 }
427 
TEST_F(ReportCommandTest,max_stack_and_percent_limit_option)428 TEST_F(ReportCommandTest, max_stack_and_percent_limit_option) {
429   Report(PERF_DATA_MAX_STACK_AND_PERCENT_LIMIT, {"-g"});
430   ASSERT_TRUE(success);
431   ASSERT_NE(content.find("89.03"), std::string::npos);
432 
433   Report(PERF_DATA_MAX_STACK_AND_PERCENT_LIMIT, {"-g", "--max-stack", "0"});
434   ASSERT_TRUE(success);
435   ASSERT_EQ(content.find("89.03"), std::string::npos);
436   Report(PERF_DATA_MAX_STACK_AND_PERCENT_LIMIT, {"-g", "--max-stack", "1"});
437   ASSERT_TRUE(success);
438   ASSERT_NE(content.find("89.03"), std::string::npos);
439 
440   Report(PERF_DATA_MAX_STACK_AND_PERCENT_LIMIT,
441          {"-g", "--percent-limit", "90"});
442   ASSERT_TRUE(success);
443   ASSERT_EQ(content.find("89.03"), std::string::npos);
444   Report(PERF_DATA_MAX_STACK_AND_PERCENT_LIMIT,
445          {"-g", "--percent-limit", "70"});
446   ASSERT_TRUE(success);
447   ASSERT_NE(content.find("89.03"), std::string::npos);
448 }
449 
TEST_F(ReportCommandTest,kallsyms_option)450 TEST_F(ReportCommandTest, kallsyms_option) {
451   Report(PERF_DATA, {"--kallsyms", GetTestData("kallsyms")});
452   ASSERT_TRUE(success);
453   ASSERT_NE(content.find("FakeKernelSymbol"), std::string::npos);
454 }
455 
TEST_F(ReportCommandTest,invalid_perf_data)456 TEST_F(ReportCommandTest, invalid_perf_data) {
457   ASSERT_FALSE(ReportCmd()->Run({"-i", GetTestData(INVALID_PERF_DATA)}));
458 }
459 
TEST_F(ReportCommandTest,raw_period_option)460 TEST_F(ReportCommandTest, raw_period_option) {
461   Report(PERF_DATA, {"--raw-period"});
462   ASSERT_TRUE(success);
463   ASSERT_NE(content.find("GlobalFunc"), std::string::npos);
464   ASSERT_EQ(content.find("%"), std::string::npos);
465 }
466 
467 #if defined(__linux__)
468 #include "event_selection_set.h"
469 
RecordCmd()470 static std::unique_ptr<Command> RecordCmd() {
471   return CreateCommandInstance("record");
472 }
473 
TEST_F(ReportCommandTest,dwarf_callgraph)474 TEST_F(ReportCommandTest, dwarf_callgraph) {
475   if (IsDwarfCallChainSamplingSupported()) {
476     std::vector<std::unique_ptr<Workload>> workloads;
477     CreateProcesses(1, &workloads);
478     std::string pid = std::to_string(workloads[0]->GetPid());
479     TemporaryFile tmp_file;
480     ASSERT_TRUE(
481         RecordCmd()->Run({"-p", pid, "-g", "-o", tmp_file.path, "sleep", SLEEP_SEC}));
482     ReportRaw(tmp_file.path, {"-g"});
483     ASSERT_TRUE(success);
484   } else {
485     GTEST_LOG_(INFO) << "This test does nothing as dwarf callchain sampling is "
486                         "not supported on this device.";
487   }
488 }
489 
TEST_F(ReportCommandTest,report_dwarf_callgraph_of_nativelib_in_apk)490 TEST_F(ReportCommandTest, report_dwarf_callgraph_of_nativelib_in_apk) {
491   // NATIVELIB_IN_APK_PERF_DATA is recorded on arm64, so can only report
492   // callgraph on arm64.
493   if (GetBuildArch() == ARCH_ARM64) {
494     Report(NATIVELIB_IN_APK_PERF_DATA, {"-g"});
495     ASSERT_NE(content.find(GetUrlInApk(APK_FILE, NATIVELIB_IN_APK)),
496               std::string::npos);
497     ASSERT_NE(content.find("Func2"), std::string::npos);
498     ASSERT_NE(content.find("Func1"), std::string::npos);
499     ASSERT_NE(content.find("GlobalFunc"), std::string::npos);
500   } else {
501     GTEST_LOG_(INFO)
502         << "This test does nothing as it is only run on arm64 devices";
503   }
504 }
505 
506 #endif
507