1 /*
2 * Copyright (c) 2023-2025 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 #include <chrono>
16 #include <ctime>
17 #include <gtest/gtest.h>
18 #include <iostream>
19 #include <unistd.h>
20
21 #include "accesstoken_kit.h"
22 #include "file_util.h"
23 #include "nativetoken_kit.h"
24 #include "parameter_ex.h"
25 #include "token_setproc.h"
26 #include "trace_collector_client.h"
27
28 using namespace testing::ext;
29 using namespace OHOS::HiviewDFX;
30 using namespace OHOS::HiviewDFX::UCollectClient;
31 using namespace OHOS::HiviewDFX::UCollect;
32
33 namespace {
34 constexpr int SLEEP_DURATION = 10;
35 const std::vector<std::string> TAG_GROUPS = {"scene_performance"};
36
NativeTokenGet(const char * perms[],int size)37 void NativeTokenGet(const char* perms[], int size)
38 {
39 uint64_t tokenId;
40 NativeTokenInfoParams infoInstance = {
41 .dcapsNum = 0,
42 .permsNum = size,
43 .aclsNum = 0,
44 .dcaps = nullptr,
45 .perms = perms,
46 .acls = nullptr,
47 .aplStr = "system_basic",
48 };
49
50 infoInstance.processName = "UCollectionClientUnitTest";
51 tokenId = GetAccessTokenId(&infoInstance);
52 SetSelfTokenID(tokenId);
53 OHOS::Security::AccessToken::AccessTokenKit::ReloadNativeTokenInfo();
54 }
55
EnablePermissionAccess()56 void EnablePermissionAccess()
57 {
58 const char* perms[] = {
59 "ohos.permission.WRITE_HIVIEW_SYSTEM",
60 "ohos.permission.READ_HIVIEW_SYSTEM",
61 "ohos.permission.DUMP",
62 };
63 NativeTokenGet(perms, 3); // 3 is the size of the array which consists of required permissions.
64 }
65
DisablePermissionAccess()66 void DisablePermissionAccess()
67 {
68 NativeTokenGet(nullptr, 0); // empty permission array.
69 }
70
Sleep()71 void Sleep()
72 {
73 sleep(SLEEP_DURATION);
74 }
75
IsCommonState()76 bool IsCommonState()
77 {
78 bool isBetaVersion = Parameter::IsBetaVersion();
79 bool isUCollectionSwitchOn = Parameter::IsUCollectionSwitchOn();
80 bool isTraceCollectionSwitchOn = Parameter::IsTraceCollectionSwitchOn();
81 bool isFrozeSwitchOn = Parameter::GetBoolean("persist.hiview.freeze_detector", false);
82 if (!isBetaVersion && !isFrozeSwitchOn && !isUCollectionSwitchOn && !isTraceCollectionSwitchOn) {
83 return false;
84 }
85 if (isTraceCollectionSwitchOn) {
86 return false;
87 }
88 return true;
89 }
90 }
91
92 class TraceCollectorTest : public testing::Test {
93 public:
SetUp()94 void SetUp() {}
TearDown()95 void TearDown() {}
SetUpTestCase()96 static void SetUpTestCase() {}
TearDownTestCase()97 static void TearDownTestCase() {}
98 };
99
100 /**
101 * @tc.name: TraceCollectorTest001
102 * @tc.desc: use trace in command state.
103 * @tc.type: FUNC
104 */
105 HWTEST_F(TraceCollectorTest, TraceCollectorTest001, TestSize.Level1)
106 {
107 auto traceCollector = TraceCollector::Create();
108 ASSERT_TRUE(traceCollector != nullptr);
109 EnablePermissionAccess();
110 auto openRet = traceCollector->OpenSnapshot(TAG_GROUPS);
111 ASSERT_EQ(openRet.retCode, UcError::SUCCESS);
112 Sleep();
113 auto dumpRes = traceCollector->DumpSnapshot(UCollect::TraceClient::COMMAND);
114 ASSERT_TRUE(dumpRes.retCode == UcError::SUCCESS);
115 ASSERT_TRUE(dumpRes.data.size() >= 0);
116 auto dumpRes2 = traceCollector->DumpSnapshot(); // dump common trace in command state return fail
117 ASSERT_EQ(dumpRes2.retCode, UcError::TRACE_STATE_ERROR);
118 auto closeRet = traceCollector->Close();
119 ASSERT_TRUE(closeRet.retCode == UcError::SUCCESS);
120
121 DisablePermissionAccess();
122 }
123
124 /**
125 * @tc.name: TraceCollectorTest002
126 * @tc.desc: use trace in recording mode.
127 * @tc.type: FUNC
128 */
129 HWTEST_F(TraceCollectorTest, TraceCollectorTest002, TestSize.Level1)
130 {
131 auto traceCollector = TraceCollector::Create();
132 ASSERT_TRUE(traceCollector != nullptr);
133 EnablePermissionAccess();
134 std::string args = "tags:sched clockType:boot bufferSize:1024 overwrite:1 output:/data/log/test.sys";
135 auto openRet = traceCollector->OpenRecording(args);
136 if (openRet.retCode == UcError::SUCCESS) {
137 auto recOnRet = traceCollector->RecordingOn();
138 ASSERT_TRUE(recOnRet.retCode == UcError::SUCCESS);
139 Sleep();
140 auto recOffRet = traceCollector->RecordingOff();
141 ASSERT_TRUE(recOffRet.data.size() >= 0);
142 }
143 traceCollector->Close();
144 DisablePermissionAccess();
145 }
146
147 /**
148 * @tc.name: TraceCollectorTest003
149 * @tc.desc: dump trace in common state.
150 * @tc.type: FUNC
151 */
152 HWTEST_F(TraceCollectorTest, TraceCollectorTest003, TestSize.Level1)
153 {
154 auto traceCollector = TraceCollector::Create();
155 ASSERT_TRUE(traceCollector != nullptr);
156 EnablePermissionAccess();
157 auto ret = traceCollector->DumpSnapshot();
158 if (IsCommonState()) {
159 ASSERT_TRUE(ret.retCode == UcError::SUCCESS);
160 ASSERT_TRUE(ret.data.size() >= 0);
161 } else {
162 ASSERT_EQ(ret.retCode, UcError::TRACE_STATE_ERROR);
163 }
164 DisablePermissionAccess();
165 }
166
GetMilliseconds()167 static uint64_t GetMilliseconds()
168 {
169 auto now = std::chrono::system_clock::now();
170 auto millisecs = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch());
171 return millisecs.count();
172 }
173
174 /**
175 * @tc.name: TraceCollectorTest003
176 * @tc.desc: start app trace.
177 * @tc.type: FUNC
178 */
179 HWTEST_F(TraceCollectorTest, TraceCollectorTest004, TestSize.Level1)
180 {
181 auto traceCollector = TraceCollector::Create();
182 ASSERT_TRUE(traceCollector != nullptr);
183 EnablePermissionAccess();
184 AppCaller appCaller;
185 appCaller.actionId = ACTION_ID_START_TRACE;
186 appCaller.bundleName = "com.example.helloworld";
187 appCaller.bundleVersion = "2.0.1";
188 appCaller.foreground = 1;
189 appCaller.threadName = "mainThread";
190 appCaller.uid = 20020143; // 20020143: user uid
191 appCaller.pid = 100; // 100: pid
192 appCaller.happenTime = GetMilliseconds();
193 appCaller.beginTime = appCaller.happenTime - 100; // 100: ms
194 appCaller.endTime = appCaller.happenTime + 100; // 100: ms
195 auto result = traceCollector->CaptureDurationTrace(appCaller);
196 std::cout << "retCode=" << result.retCode << ", data=" << result.data << std::endl;
197 ASSERT_TRUE(result.data == 0);
198
199 AppCaller appCaller2;
200 appCaller2.actionId = ACTION_ID_DUMP_TRACE;
201 appCaller2.bundleName = "com.example.helloworld";
202 appCaller2.bundleVersion = "2.0.1";
203 appCaller2.foreground = 1;
204 appCaller2.threadName = "mainThread";
205 appCaller2.uid = 20020143; // 20020143: user id
206 appCaller2.pid = 100; // 100: pid
207 appCaller2.happenTime = GetMilliseconds();
208 appCaller2.beginTime = appCaller.happenTime - 100; // 100: ms
209 appCaller2.endTime = appCaller.happenTime + 100; // 100: ms
210 auto result2 = traceCollector->CaptureDurationTrace(appCaller2);
211 std::cout << "retCode=" << result2.retCode << ", data=" << result2.data << std::endl;
212 ASSERT_NE(result2.retCode, UcError::TRACE_STATE_ERROR);
213 DisablePermissionAccess();
214 Sleep();
215 }
216