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 <filesystem>
20 
21 #include <android-base/file.h>
22 
23 #include "dso.h"
24 #include "environment.h"
25 #include "get_test_data.h"
26 #include "test_util.h"
27 #include "thread_tree.h"
28 
29 namespace fs = std::filesystem;
30 using namespace simpleperf;
31 
TEST(environment,PrepareVdsoFile)32 TEST(environment, PrepareVdsoFile) {
33   std::string content;
34   ASSERT_TRUE(android::base::ReadFileToString("/proc/self/maps", &content));
35   if (content.find("[vdso]") == std::string::npos) {
36     // Vdso isn't used, no need to test.
37     return;
38   }
39   TemporaryDir tmpdir;
40   auto scoped_temp_files = ScopedTempFiles::Create(tmpdir.path);
41   ASSERT_TRUE(scoped_temp_files);
42   PrepareVdsoFile();
43   std::unique_ptr<Dso> dso =
44       Dso::CreateDso(DSO_ELF_FILE, "[vdso]", sizeof(size_t) == sizeof(uint64_t));
45   ASSERT_TRUE(dso != nullptr);
46   ASSERT_NE(dso->GetDebugFilePath(), "[vdso]");
47 }
48 
TEST(environment,GetHardwareFromCpuInfo)49 TEST(environment, GetHardwareFromCpuInfo) {
50   std::string cpu_info =
51       "CPU revision : 10\n\n"
52       "Hardware : Symbol i.MX6 Freeport_Plat Quad/DualLite (Device Tree)\n";
53   ASSERT_EQ("Symbol i.MX6 Freeport_Plat Quad/DualLite (Device Tree)",
54             GetHardwareFromCpuInfo(cpu_info));
55 }
56 
TEST(environment,MappedFileOnlyExistInMemory)57 TEST(environment, MappedFileOnlyExistInMemory) {
58   ASSERT_TRUE(MappedFileOnlyExistInMemory(""));
59   ASSERT_TRUE(MappedFileOnlyExistInMemory("[stack]"));
60   ASSERT_TRUE(MappedFileOnlyExistInMemory("[anon:.bss]"));
61   ASSERT_FALSE(MappedFileOnlyExistInMemory("[vdso]"));
62   ASSERT_TRUE(MappedFileOnlyExistInMemory("/dev/__properties__/u:object_r"));
63   ASSERT_TRUE(MappedFileOnlyExistInMemory("//anon"));
64   ASSERT_TRUE(MappedFileOnlyExistInMemory("/memfd:/jit-cache"));
65   ASSERT_FALSE(MappedFileOnlyExistInMemory("./TemporaryFile-12345"));
66   ASSERT_FALSE(MappedFileOnlyExistInMemory("/system/lib64/libc.so"));
67 }
68 
TEST(environment,SetPerfEventLimits)69 TEST(environment, SetPerfEventLimits) {
70 #if defined(__ANDROID__)
71   if (GetAndroidVersion() <= kAndroidVersionP) {
72     return;
73   }
74   uint64_t orig_freq = 100000;
75   size_t orig_percent = 25;
76   uint64_t orig_mlock_kb = 516;
77   bool has_freq = GetMaxSampleFrequency(&orig_freq);
78   bool has_percent = GetCpuTimeMaxPercent(&orig_percent);
79   bool has_mlock_kb = GetPerfEventMlockKb(&orig_mlock_kb);
80 
81   ASSERT_TRUE(SetPerfEventLimits(orig_freq + 1, orig_percent + 1, orig_mlock_kb + 1));
82   if (has_freq) {
83     uint64_t value;
84     ASSERT_TRUE(GetMaxSampleFrequency(&value));
85     ASSERT_EQ(value, orig_freq + 1);
86   }
87   if (has_percent) {
88     size_t value;
89     ASSERT_TRUE(GetCpuTimeMaxPercent(&value));
90     ASSERT_EQ(value, orig_percent + 1);
91   }
92   if (has_mlock_kb) {
93     uint64_t value;
94     ASSERT_TRUE(GetPerfEventMlockKb(&value));
95     ASSERT_EQ(value, orig_mlock_kb + 1);
96   }
97   // Restore the environment.
98   ASSERT_TRUE(SetPerfEventLimits(orig_freq, orig_percent, orig_mlock_kb));
99 #else  // !defined(__ANDROID__)
100   GTEST_LOG_(INFO) << "This test tests setting properties on Android.";
101 #endif
102 }
103 
TEST(environment,GetKernelVersion)104 TEST(environment, GetKernelVersion) {
105   ASSERT_TRUE(GetKernelVersion());
106 }
107 
TEST(environment,GetModuleBuildId)108 TEST(environment, GetModuleBuildId) {
109   BuildId build_id;
110   fs::path dir(GetTestData("sysfs/module/fake_kernel_module/notes"));
111   ASSERT_TRUE(fs::copy_file(dir / "note.gnu.build-id", dir / ".note.gnu.build-id",
112                             fs::copy_options::overwrite_existing));
113   ASSERT_TRUE(GetModuleBuildId("fake_kernel_module", &build_id, GetTestData("sysfs")));
114   ASSERT_EQ(build_id, BuildId("3e0ba155286f3454"));
115 }
116 
TEST(environment,GetKernelAndModuleMmaps)117 TEST(environment, GetKernelAndModuleMmaps) {
118   TEST_REQUIRE_ROOT();
119   KernelMmap kernel_mmap;
120   std::vector<KernelMmap> module_mmaps;
121   GetKernelAndModuleMmaps(&kernel_mmap, &module_mmaps);
122   // The kernel map should contain the kernel start address.
123   ASSERT_EQ(kernel_mmap.name, std::string(DEFAULT_KERNEL_MMAP_NAME) + "_stext");
124   ASSERT_GT(kernel_mmap.start_addr, 0);
125 }
126 
TEST(environment,GetProcessUid)127 TEST(environment, GetProcessUid) {
128   std::optional<uid_t> uid = GetProcessUid(getpid());
129   ASSERT_TRUE(uid.has_value());
130   ASSERT_EQ(uid.value(), getuid());
131 }
132 
TEST(environment,GetAppType)133 TEST(environment, GetAppType) {
134   TEST_REQUIRE_APPS();
135   ASSERT_EQ(GetAppType("com.android.simpleperf.debuggable"), "debuggable");
136   ASSERT_EQ(GetAppType("com.android.simpleperf.profileable"), "profileable");
137   ASSERT_EQ(GetAppType("com.android.simpleperf.app_not_exist"), "not_exist");
138 }
139