1 /*
2 * Copyright (c) 2024 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 "spe_decoder_test.h"
16
17 #include "command.h"
18 #include "subcommand_dump.h"
19 #include "subcommand_record.h"
20 #include "utilities_test.h"
21
22 using namespace testing::ext;
23 using namespace std;
24 using namespace OHOS::HiviewDFX;
25 namespace OHOS {
26 namespace Developtools {
27 namespace HiPerf {
28
29 class SpeDecoderTest : public testing::Test {
30 public:
31 static void SetUpTestCase(void);
32 static void TearDownTestCase(void);
33 void SetUp();
34 void TearDown();
35 };
36
SetUpTestCase()37 void SpeDecoderTest::SetUpTestCase() {}
38
TearDownTestCase()39 void SpeDecoderTest::TearDownTestCase() {}
40
SetUp()41 void SpeDecoderTest::SetUp()
42 {
43 SubCommand::ClearSubCommands(); // clear the subCommands left from other UT
44 ASSERT_EQ(SubCommand::GetSubCommands().size(), 0u);
45 SubCommandRecord::RegisterSubCommandRecord();
46 SubCommandDump::RegisterSubCommandDump();
47 ASSERT_EQ(SubCommand::GetSubCommands().size(), 2u); // 2u: 2 size
48 }
49
TearDown()50 void SpeDecoderTest::TearDown()
51 {
52 ASSERT_EQ(SubCommand::GetSubCommands().size(), 2u); // 2u: 2 size
53 SubCommand::ClearSubCommands();
54 ASSERT_EQ(SubCommand::GetSubCommands().size(), 0u);
55 MemoryHold::Get().Clean();
56 }
57
58 /**
59 * @tc.name: TestGetSpeEventNameByType
60 * @tc.desc:
61 * @tc.type: FUNC
62 */
63 HWTEST_F(SpeDecoderTest, TestGetSpeEventNameByType, TestSize.Level1)
64 {
65 std::string eventName = "";
66 GetSpeEventNameByType(PERF_SPE_L1D_ACCESS, eventName);
67 ASSERT_EQ(eventName, "l1d-access");
68 GetSpeEventNameByType(PERF_SPE_L1D_MISS, eventName);
69 ASSERT_EQ(eventName, "l1d-miss");
70 GetSpeEventNameByType(PERF_SPE_LLC_ACCESS, eventName);
71 ASSERT_EQ(eventName, "llc-access");
72 GetSpeEventNameByType(PERF_SPE_LLC_MISS, eventName);
73 ASSERT_EQ(eventName, "llc-miss");
74 GetSpeEventNameByType(PERF_SPE_TLB_ACCESS, eventName);
75 ASSERT_EQ(eventName, "tlb-access");
76 GetSpeEventNameByType(PERF_SPE_TLB_MISS, eventName);
77 ASSERT_EQ(eventName, "tlb-miss");
78 GetSpeEventNameByType(PERF_SPE_BRANCH_MISS, eventName);
79 ASSERT_EQ(eventName, "branch-miss");
80 GetSpeEventNameByType(PERF_SPE_REMOTE_ACCESS, eventName);
81 ASSERT_EQ(eventName, "remote-access");
82 GetSpeEventNameByType(PERF_SPE_SVE_PARTIAL_PRED, eventName);
83 ASSERT_EQ(eventName, "paritial_read");
84 GetSpeEventNameByType(PERF_SPE_SVE_EMPTY_PRED, eventName);
85 ASSERT_EQ(eventName, "empty_read");
86 GetSpeEventNameByType(1 << 10, eventName); // 10: displacement
87 ASSERT_EQ(eventName, "unknow");
88 }
89
90 /**
91 * @tc.name: TestRecord
92 * @tc.desc:
93 * @tc.type: FUNC
94 */
95 HWTEST_F(SpeDecoderTest, TestRecord, TestSize.Level1)
96 {
97 StdoutRecord stdoutRecord;
98
99 std::string cmdString = "record -e arm_spe_0/load_filter=1,min_latency=100/ -d 10 --app ";
100 cmdString += " " + TEST_PROCESSES;
101 printf("command : %s\n", cmdString.c_str());
102
103 // it need load some symbols and much more log
104 stdoutRecord.Start();
105 const auto startTime = chrono::steady_clock::now();
106 bool ret = Command::DispatchCommand(cmdString);
107 const auto costMs = std::chrono::duration_cast<std::chrono::milliseconds>(
108 chrono::steady_clock::now() - startTime);
109 std::string stringOut = stdoutRecord.Stop();
110 printf("run %" PRId64 " ms return %d\n", (uint64_t)costMs.count(), static_cast<int>(ret));
111 EXPECT_EQ(true, ret);
112 }
113
114 /**
115 * @tc.name: TestDump
116 * @tc.desc:
117 * @tc.type: FUNC
118 */
119 HWTEST_F(SpeDecoderTest, TestDump, TestSize.Level1)
120 {
121 if (access("/data/test/resource/testdata/spe_perf.data", R_OK) == 0) {
122 StdoutRecord stdoutRecord;
123
124 std::string cmdString = "dump -i /data/test/resource/testdata/spe_perf.data";
125
126 // it need load some symbols and much more log
127 ScopeDebugLevel tempLogLevel {LEVEL_DEBUG};
128
129 stdoutRecord.Start();
130 const auto startTime = chrono::steady_clock::now();
131 bool ret = Command::DispatchCommand(cmdString);
132 const auto costMs = std::chrono::duration_cast<std::chrono::milliseconds>(
133 chrono::steady_clock::now() - startTime);
134 std::string stringOut = stdoutRecord.Stop();
135
136 printf("command : %s(run %" PRId64 " ms) return %d\n", cmdString.c_str(),
137 static_cast<uint64_t>(costMs.count()), static_cast<int>(ret));
138 EXPECT_EQ(true, ret);
139 } else {
140 printf("spe_perf.data not exist.\n");
141 }
142 }
143
144 /**
145 * @tc.name: TestSpeDecoder
146 * @tc.desc:
147 * @tc.type: FUNC
148 */
149 HWTEST_F(SpeDecoderTest, TestSpeDecoder, TestSize.Level1)
150 {
151 const size_t dataDize = 192;
152 const u8 rawData[dataDize] = {0xb0, 0x68, 0xe0, 0x20, 0x84, 0xc0, 0xff, 0xff,
153 0xa0, 0x99, 0x06, 0x00, 0x98, 0x08, 0x00, 0x62,
154 0x16, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00,
155 0xb2, 0xb0, 0x80, 0xad, 0xae, 0xe5, 0xff, 0xff,
156 0x00, 0x9a, 0x01, 0x00, 0x00, 0x00, 0x00, 0x71,
157 0x46, 0xf9, 0xd5, 0x4a, 0x10, 0x62, 0x01, 0x00,
158 0xb0, 0x0c, 0x27, 0xb9, 0xf2, 0x59, 0x00, 0x00,
159 0x80, 0x99, 0x07, 0x00, 0x98, 0x0a, 0x00, 0x62,
160 0x12, 0x00, 0x00, 0x00, 0x49, 0x01, 0x00, 0x00,
161 0xb2, 0x60, 0x73, 0x2b, 0x81, 0x5a, 0x00, 0x00,
162 0x00, 0x9a, 0x01, 0x00, 0x00, 0x00, 0x00, 0x71,
163 0x20, 0x43, 0xd6, 0x4a, 0x10, 0x62, 0x01, 0x00,
164 0xb0, 0x68, 0x54, 0xf9, 0xf4, 0x59, 0x00, 0x00,
165 0x80, 0x99, 0x02, 0x00, 0x98, 0x03, 0x00, 0x62,
166 0x42, 0x00, 0x00, 0x00, 0x4a, 0x01, 0x00, 0x00,
167 0xb1, 0x6c, 0x54, 0xf9, 0xf4, 0x59, 0x00, 0x00,
168 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x71,
169 0xa1, 0x6c, 0xd6, 0x4a, 0x10, 0x62, 0x01, 0x00,
170 0xb0, 0xb4, 0x2b, 0x20, 0x84, 0xc0, 0xff, 0xff,
171 0xa0, 0x99, 0x02, 0x00, 0x98, 0x03, 0x00, 0x62,
172 0x02, 0x00, 0x00, 0x00, 0x4a, 0x02, 0x00, 0x00,
173 0xb1, 0xac, 0x5c, 0x35, 0x84, 0xc0, 0xff, 0xff,
174 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x71,
175 0xcc, 0x99, 0xd6, 0x4a, 0x10, 0x62, 0x01, 0x00};
176 SpeDecoder *decoder = SpeDecoderDataNew(rawData, dataDize);
177 EXPECT_EQ(decoder != nullptr, true);
178 std::vector<SpeRecord> records;
179 while (true) {
180 int ret = SpeDecode(decoder);
181 if (ret <= 0) {
182 break;
183 }
184 struct SpeRecord record = SpeRecord(decoder->record);
185 records.emplace_back(record);
186 }
187 EXPECT_EQ(records.empty(), false);
188 SpeDecoderFree(decoder);
189 }
190 } // namespace HiPerf
191 } // namespace Developtools
192 } // namespace OHOS