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 <cinttypes> 16 #include <fstream> 17 #include <gtest/gtest.h> 18 #include <random> 19 #include <string> 20 21 #include "logging.h" 22 #include "printk_formats_parser.h" 23 24 using FTRACE_NS::PrintkFormatsParser; 25 using namespace testing::ext; 26 namespace { 27 constexpr int ROUNDS = 20; 28 constexpr int ADDR_MAX_SIZE = 8; 29 constexpr int SYMBOL_MAX_SIZE = 16; 30 constexpr int HEX_BASE = 16; 31 32 constexpr char RANDOM_HEX_TABLE[] = "0123456789ABCDEF"; 33 constexpr long RANDOM_HEX_NUMBER = std::size(RANDOM_HEX_TABLE) - 1; 34 constexpr char RANDOM_CHAR_TABLE[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; 35 constexpr long RANDOM_CHAR_NUMBER = std::size(RANDOM_CHAR_TABLE) - 1; 36 37 constexpr uint64_t CPU_ON_ADDR = 0xc0b01947; 38 const std::string CPU_ON_STR = "CPU_ON"; 39 const std::string NORMAL_PRINTK_FORMATS = R"( 40 0xc0aff2a9 : "CPU wakeup interrupts" 41 0xc0aff2bf : "Timer broadcast interrupts" 42 0xc0aff2da : "Rescheduling interrupts" 43 0xc0aff2f2 : "Function call interrupts" 44 0xc0aff30b : "CPU stop interrupts" 45 0xc0aff31f : "IRQ work interrupts" 46 0xc0aff333 : "completion interrupts" 47 0xc0b018e0 : "CPU_OFF" 48 0xc0b01947 : "CPU_ON" 49 0xc0b068a6 : "thaw_processes" 50 0xc0b068a6 : "thaw_processes" 51 0xc0b06a3a : "resume_console" 52 0xc0b06a3a : "resume_console" 53 0xc0b06b38 : "machine_suspend" 54 0xc0b06b38 : "machine_suspend" 55 0xc0b06b38 : "machine_suspend" 56 0xc0b06b38 : "machine_suspend" 57 0xc0b06b48 : "suspend_enter" 58 0xc0b06b56 : "sync_filesystems" 59 0xc0b06b56 : "sync_filesystems" 60 0xc0b06b48 : "suspend_enter" 61 0xc0b06b86 : "freeze_processes" 62 0xc0b06b86 : "freeze_processes" 63 0xc0e18840 : "rcu_sched" 64 0xc0e18b00 : "rcu_bh" 65 0xc0b08096 : "Start context switch" 66 0xc0b080ab : "End context switch" 67 0xc0b08144 : "Start scheduler-tick" 68 0xc0b08159 : "End scheduler-tick" 69 0xc0b0817e : "Startleaf" 70 0xc0b08188 : "Prestarted" 71 0xc0b08193 : "Startedleaf" 72 0xc0b0819f : "Startedleafroot" 73 0xc0b081af : "Startedroot" 74 0xc0b081bb : "NoGPkthread" 75 0xc0b6a70d : "Begin" 76 0xc0b084b7 : "EarlyExit" 77 0xc0b084c1 : "Inc1" 78 0xc0b084c6 : "OfflineNoCB" 79 0xc0b084d2 : "OnlineNoCB" 80 0xc0b084dd : "OnlineQ" 81 0xc0b084e5 : "OnlineNQ" 82 0xc0b084ee : "Inc2" 83 0xc0b0850c : "LastCB" 84 0xc0b084cf : "CB" 85 0xc0b01ebb : "IRQ" 86 0xc0b08513 : "IRQNQ" 87 0xc0b0868a : "CleanupMore" 88 0xc0b0868a : "CleanupMore" 89 0xc0b08696 : "Cleanup" 90 0xc0b0879f : "Start RCU core" 91 0xc0b087ae : "End RCU core" 92 )"; 93 94 class PrintkFormatsParserTest : public ::testing::Test { 95 std::mt19937 gen_; 96 97 protected: SetUp()98 void SetUp() override 99 { 100 PrintkFormatsParser::GetInstance().printkFormats_.clear(); 101 } 102 TearDown()103 void TearDown() override 104 { 105 PrintkFormatsParser::GetInstance().printkFormats_.clear(); 106 } 107 RandomInt(int a,int b)108 int RandomInt(int a, int b) 109 { 110 std::uniform_int_distribution<int> distrib(a, b); 111 return distrib(gen_); 112 } 113 RandomChar()114 char RandomChar() 115 { 116 return RANDOM_CHAR_TABLE[RandomInt(0, RANDOM_CHAR_NUMBER - 1)]; 117 } 118 RandomHex()119 char RandomHex() 120 { 121 return RANDOM_HEX_TABLE[RandomInt(0, RANDOM_HEX_NUMBER - 1)]; 122 } 123 RandomAddr(int len)124 std::string RandomAddr(int len) 125 { 126 std::string str = "0x0"; 127 str.reserve(str.size() + len); 128 for (int i = 0; i < len; i++) { 129 str.push_back(RandomHex()); 130 } 131 return str; 132 } 133 RandomString(int len)134 std::string RandomString(int len) 135 { 136 std::string str; 137 str.reserve(len); 138 for (int i = 0; i < len; i++) { 139 str.push_back(RandomChar()); 140 } 141 return str; 142 } 143 BuildPrintkLine(std::string randNumber,std::string randomString)144 std::string BuildPrintkLine(std::string randNumber, std::string randomString) 145 { 146 std::string str = randNumber + " : " + randomString; 147 return str; 148 } 149 }; 150 151 /* 152 * @tc.name: false PrintkFormatsParser size 153 * @tc.desc: test PrintkFormatsParser::PrintkFormatsParser with false case 154 * @tc.type: FUNC 155 */ 156 HWTEST_F(PrintkFormatsParserTest, PrintkFormatsParserFalse, TestSize.Level1) 157 { 158 std::string input = "test"; 159 EXPECT_FALSE(PrintkFormatsParser::GetInstance().Parse(input)); 160 161 std::string symbol = PrintkFormatsParser::GetInstance().GetSymbol(0); 162 EXPECT_EQ(symbol, "NULL"); 163 } 164 165 /* 166 * @tc.name: normal PrintkFormatsParser size 167 * @tc.desc: test PrintkFormatsParser:: normal with normal case. 168 * @tc.type: FUNC 169 */ 170 HWTEST_F(PrintkFormatsParserTest, PrintkFormatsParserNormal, TestSize.Level1) 171 { 172 EXPECT_TRUE(PrintkFormatsParser::GetInstance().Parse(NORMAL_PRINTK_FORMATS)); 173 174 for (auto& entry : PrintkFormatsParser::GetInstance().printkFormats_) { 175 uint64_t addr = entry.first; 176 std::string symbol = entry.second; 177 PROFILER_LOG_INFO(LOG_CORE, "%" PRIx64 " : %s", addr, symbol.c_str()); 178 } 179 std::string symbol = PrintkFormatsParser::GetInstance().GetSymbol(CPU_ON_ADDR); 180 EXPECT_EQ(symbol, CPU_ON_STR); 181 } 182 183 /* 184 * @tc.name: normal PrintkFormatsParser size 185 * @tc.desc: test PrintkFormatsParser:: normal with Symbols case. 186 * @tc.type: FUNC 187 */ 188 HWTEST_F(PrintkFormatsParserTest, PrintkFormatsParserSymbolsNormal, TestSize.Level1) 189 { 190 std::string input = "1 : \"test\""; 191 EXPECT_NE(input, ""); 192 193 EXPECT_TRUE(PrintkFormatsParser::GetInstance().Parse(input)); 194 195 std::string symbol = PrintkFormatsParser::GetInstance().GetSymbol(1); 196 EXPECT_EQ(symbol, "test"); 197 } 198 199 /* 200 * @tc.name: rand PrintkFormatsParser size 201 * @tc.desc: test PrintkFormatsParser:: normal with rand case. 202 * @tc.type: FUNC 203 */ 204 HWTEST_F(PrintkFormatsParserTest, PrintkFormatsParserNormalRand, TestSize.Level1) 205 { 206 for (int i = 0; i < ROUNDS; i++) { 207 // 组成 208 std::string addr = RandomAddr(RandomInt(1, ADDR_MAX_SIZE)); 209 std::string symbol = RandomString(RandomInt(1, SYMBOL_MAX_SIZE)); 210 std::string line = BuildPrintkLine(addr, symbol); 211 EXPECT_TRUE(PrintkFormatsParser::GetInstance().Parse(line)); 212 213 std::string symbolGot = PrintkFormatsParser::GetInstance().GetSymbol(strtoull(addr.c_str(), nullptr, HEX_BASE)); 214 EXPECT_EQ(symbolGot, symbol); 215 } 216 } 217 } // namespace