1 /* 2 * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. 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 <fcntl.h> 17 #include <gtest/gtest.h> 18 #include <thread> 19 #include <unistd.h> 20 21 #include "file_utils.h" 22 #include "ftrace_fs_ops.h" 23 #include "ftrace_parser.h" 24 #include "securec.h" 25 #include "sub_event_parser.h" 26 27 using FTRACE_NS::EventFormat; 28 using FTRACE_NS::FtraceFsOps; 29 using FTRACE_NS::FtraceParser; 30 using FTRACE_NS::SubEventParser; 31 using testing::ext::TestSize; 32 33 namespace { 34 #ifndef PAGE_SIZE 35 constexpr uint32_t PAGE_SIZE = 4096; 36 #endif 37 constexpr auto TEST_DELAY = std::chrono::milliseconds(10); 38 constexpr uint32_t SCHED_SWITCH_EVENT_ID = 189; 39 const std::string SCHED_SWITCH_FORMAT_DESC = R"( 40 name: sched_switch 41 ID: 189 42 format: 43 field:unsigned short common_type; offset:0; size:2; signed:0; 44 field:unsigned char common_flags; offset:2; size:1; signed:0; 45 field:unsigned char common_preempt_count; offset:3; size:1; signed:0; 46 field:int common_pid; offset:4; size:4; signed:1; 47 48 field:char prev_comm[16]; offset:8; size:16; signed:0; 49 field:pid_t prev_pid; offset:24; size:4; signed:1; 50 field:int prev_prio; offset:28; size:4; signed:1; 51 field:long prev_state; offset:32; size:4; signed:1; 52 field:char next_comm[16]; offset:36; size:16; signed:0; 53 field:pid_t next_pid; offset:52; size:4; signed:1; 54 field:int next_prio; offset:56; size:4; signed:1; 55 56 print fmt: "prev_comm=%s prev_pid=%d prev_prio=%d prev_state=%s%s ==> next_comm=%s next_pid=%d next_prio=%d", ... 57 )"; 58 59 using SubEventParser = SubEventParser<FtraceEvent>; 60 61 class SubEventParserTest : public ::testing::Test { 62 protected: SetUp()63 void SetUp() override 64 { 65 SubEventParser::GetInstance().idToFunctions_.clear(); 66 } 67 TearDown()68 void TearDown() override 69 { 70 SubEventParser::GetInstance().idToFunctions_.clear(); 71 } 72 }; 73 74 /* 75 * @tc.name: IsSupportName 76 * @tc.desc: test SubEventParser::IsSupport with normal case. 77 * @tc.type: FUNC 78 */ 79 HWTEST_F(SubEventParserTest, IsSupportName, TestSize.Level1) 80 { 81 EXPECT_FALSE(SubEventParser::GetInstance().IsSupport("xxx")); 82 EXPECT_TRUE(SubEventParser::GetInstance().IsSupport("sched_switch")); 83 } 84 85 /* 86 * @tc.name: SetupEvent 87 * @tc.desc: test SubEventParser::SetupEvent with normal case. 88 * @tc.type: FUNC 89 */ 90 HWTEST_F(SubEventParserTest, SetupEvent, TestSize.Level1) 91 { 92 EventFormat format; 93 FtraceParser ftraceParser; 94 format.eventType = "sched"; 95 format.eventName = "sched_switch"; 96 EXPECT_TRUE(ftraceParser.ParseEventFormat(SCHED_SWITCH_FORMAT_DESC, format)); 97 98 EXPECT_TRUE(nullptr == SubEventParser::GetInstance().GetParseEventCtx(format.eventId)); 99 EXPECT_TRUE(SubEventParser::GetInstance().SetupEvent(format)); 100 EXPECT_TRUE(nullptr != SubEventParser::GetInstance().GetParseEventCtx(format.eventId)); 101 } 102 103 /* 104 * @tc.name: IsSupportId 105 * @tc.desc: test SubEventParser::IsSupport with normal case. 106 * @tc.type: FUNC 107 */ 108 HWTEST_F(SubEventParserTest, IsSupportId, TestSize.Level1) 109 { 110 EventFormat format; 111 FtraceParser ftraceParser; 112 format.eventType = "sched"; 113 format.eventName = "sched_switch"; 114 EXPECT_TRUE(ftraceParser.ParseEventFormat(SCHED_SWITCH_FORMAT_DESC, format)); 115 116 SubEventParser::GetInstance().schedSwitchCtx = nullptr; 117 EXPECT_TRUE(nullptr == SubEventParser::GetInstance().GetParseEventCtx(format.eventId)); 118 EXPECT_TRUE(SubEventParser::GetInstance().SetupEvent(format)); 119 EXPECT_TRUE(nullptr != SubEventParser::GetInstance().GetParseEventCtx(format.eventId)); 120 } 121 122 /* 123 * @tc.name: ParseEvent 124 * @tc.desc: test SubEventParser::ParseEvent with normal case. 125 * @tc.type: FUNC 126 */ 127 HWTEST_F(SubEventParserTest, ParseEvent, TestSize.Level1) 128 { 129 EventFormat format; 130 FtraceParser ftraceParser; 131 format.eventType = "sched"; 132 format.eventName = "sched_switch"; 133 EXPECT_TRUE(ftraceParser.ParseEventFormat(SCHED_SWITCH_FORMAT_DESC, format)); 134 EXPECT_TRUE(SubEventParser::GetInstance().SetupEvent(format)); 135 EXPECT_EQ(format.eventId, SCHED_SWITCH_EVENT_ID); 136 137 std::vector<uint8_t> buffer(PAGE_SIZE, 0); 138 std::vector<uint8_t> zeros(PAGE_SIZE, 0); 139 std::string traceRaw; 140 if (FtraceFsOps::GetInstance().IsHmKernel()) { 141 traceRaw = FtraceFsOps::GetInstance().GetHmRawTracePath(); 142 } else { 143 traceRaw = FtraceFsOps::GetInstance().GetRawTracePath(0); 144 } 145 int fd = open(traceRaw.c_str(), O_EXCL); 146 EXPECT_NE(fd, -1); 147 148 EXPECT_TRUE(FtraceFsOps::GetInstance().ClearTraceBuffer()); 149 EXPECT_TRUE(FtraceFsOps::GetInstance().EnableEvent("sched", "sched_switch")); 150 EXPECT_TRUE(FtraceFsOps::GetInstance().EnableTracing()); 151 152 std::this_thread::sleep_for(TEST_DELAY); 153 EXPECT_EQ(read(fd, buffer.data(), buffer.size()), static_cast<int>(PAGE_SIZE)); 154 EXPECT_TRUE(FtraceFsOps::GetInstance().DisableTracing()); 155 EXPECT_EQ(close(fd), 0); 156 EXPECT_NE(buffer, zeros); 157 158 FtraceEvent event = {}; 159 auto* ctx = SubEventParser::GetInstance().GetParseEventCtx(format.eventId); 160 EXPECT_TRUE(ctx != nullptr); 161 SubEventParser::GetInstance().ParseEvent(event, buffer.data(), buffer.size(), ctx); 162 } 163 } // namespace 164