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