core/unittest/ebpf/CommonUtilUnittest.cpp (233 lines of code) (raw):

// Copyright 2025 iLogtail Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include <cstddef> #include <array> #include <iomanip> #include <random> #include <regex> #include <set> #include <string> #include "ebpf/util/FrequencyManager.h" #include "ebpf/util/TraceId.h" #include "unittest/Unittest.h" namespace logtail { namespace ebpf { class CommonUtilUnittest : public ::testing::Test { public: void TestTraceIDGeneration(); void TestTraceIDFormat(); void TestTraceIDUniqueness(); void TestSpanIDGeneration(); void TestSpanIDFormat(); void TestSpanIDUniqueness(); void TestTraceIDConversion(); void TestSpanIDConversion(); void TraceIDBenchmark(); void FromTraceIDBenchmark(); void TestInitialState(); void TestPeriodSetting(); void TestExpiredCheck(); void TestReset(); void TestCycleCount(); void TestMultipleCycles(); protected: void SetUp() override {} void TearDown() override {} bool IsValidHexString(const std::string& str) { std::regex hexRegex("^[0-9a-f]+$"); return std::regex_match(str, hexRegex); } }; void CommonUtilUnittest::TestTraceIDGeneration() { auto traceId = GenerateTraceID(); APSARA_TEST_EQUAL(traceId.size(), 4UL); bool allZero = true; for (const auto& byte : traceId) { if (byte != 0) { allZero = false; break; } } APSARA_TEST_FALSE(allZero); } void CommonUtilUnittest::TestTraceIDFormat() { auto traceId = GenerateTraceID(); std::string hexString = TraceIDToString(traceId); APSARA_TEST_EQUAL(hexString.length(), 64UL); APSARA_TEST_TRUE(IsValidHexString(hexString)); } void CommonUtilUnittest::TestTraceIDUniqueness() { std::set<std::string> traceIds; const int numIds = 1000; for (int i = 0; i < numIds; ++i) { auto traceId = GenerateTraceID(); std::string hexString = TraceIDToString(traceId); traceIds.insert(hexString); } APSARA_TEST_EQUAL(traceIds.size(), size_t(numIds)); } void CommonUtilUnittest::TestSpanIDGeneration() { auto spanId = GenerateSpanID(); APSARA_TEST_EQUAL(spanId.size(), 2UL); bool allZero = true; for (const auto& byte : spanId) { if (byte != 0) { allZero = false; break; } } APSARA_TEST_FALSE(allZero); } void CommonUtilUnittest::TestSpanIDFormat() { auto spanId = GenerateSpanID(); std::string hexString = SpanIDToString(spanId); LOG_INFO(sLogger, ("spanId", hexString)); APSARA_TEST_EQUAL(hexString.length(), 32UL); APSARA_TEST_TRUE(IsValidHexString(hexString)); } void CommonUtilUnittest::TestSpanIDUniqueness() { // 生成多个 SpanID 并验证唯一性 std::set<std::string> spanIds; const int numIds = 1000; for (int i = 0; i < numIds; ++i) { auto spanId = GenerateSpanID(); std::string hexString = SpanIDToString(spanId); spanIds.insert(hexString); } // 验证没有重复的 SpanID APSARA_TEST_EQUAL(spanIds.size(), size_t(numIds)); } void CommonUtilUnittest::TestTraceIDConversion() { // 创建一个已知的 TraceID 数组 std::array<uint64_t, 4> traceId = {}; for (size_t i = 0; i < traceId.size(); ++i) { traceId[i] = static_cast<uint64_t>(i); } // 转换为字符串 std::string hexString = TraceIDToString(traceId); // 验证转换结果 std::string expected; for (size_t i = 0; i < traceId.size(); ++i) { char buf[17]; snprintf(buf, sizeof(buf), "%016lx", traceId[i]); expected += buf; } APSARA_TEST_EQUAL(hexString, expected); } void CommonUtilUnittest::TestSpanIDConversion() { // 创建一个已知的 SpanID 数组 std::array<uint64_t, 2> spanId = {}; for (size_t i = 0; i < spanId.size(); ++i) { spanId[i] = static_cast<uint64_t>(i); } // 转换为字符串 std::string hexString = SpanIDToString(spanId); // 验证转换结果 std::string expected; for (size_t i = 0; i < spanId.size(); ++i) { char buf[17]; snprintf(buf, sizeof(buf), "%016lx", spanId[i]); expected += buf; } APSARA_TEST_EQUAL(hexString, expected); } void CommonUtilUnittest::TestInitialState() { // 测试初始状态 FrequencyManager manager; // 验证初始周期为0 APSARA_TEST_EQUAL(manager.Period().count(), 0); // 验证初始计数为0 APSARA_TEST_EQUAL(manager.Count(), 0U); // 验证初始状态下已过期(因为周期为0) auto now = std::chrono::steady_clock::now(); APSARA_TEST_TRUE(manager.Expired(now)); } void CommonUtilUnittest::TestPeriodSetting() { // 测试周期设置 FrequencyManager manager; // 设置1秒的周期 std::chrono::milliseconds period(1000); manager.SetPeriod(period); // 验证周期设置正确 APSARA_TEST_EQUAL(manager.Period().count(), 1000); } void CommonUtilUnittest::TestExpiredCheck() { FrequencyManager manager; // 设置100ms的周期 std::chrono::milliseconds period(100); manager.SetPeriod(period); auto now = std::chrono::steady_clock::now(); manager.Reset(now); // 验证刚重置后未过期 APSARA_TEST_FALSE(manager.Expired(now)); // 验证周期内未过期 APSARA_TEST_FALSE(manager.Expired(now + std::chrono::milliseconds(50))); // 验证到达周期后过期 APSARA_TEST_TRUE(manager.Expired(now + std::chrono::milliseconds(100))); // 验证超过周期后过期 APSARA_TEST_TRUE(manager.Expired(now + std::chrono::milliseconds(150))); } void CommonUtilUnittest::TestReset() { FrequencyManager manager; // 设置100ms的周期 std::chrono::milliseconds period(100); manager.SetPeriod(period); auto now = std::chrono::steady_clock::now(); // 第一次重置 manager.Reset(now); APSARA_TEST_EQUAL(manager.Next(), now + period); APSARA_TEST_EQUAL(manager.Count(), 1U); // 第二次重置 auto nextTime = now + std::chrono::milliseconds(200); manager.Reset(nextTime); APSARA_TEST_EQUAL(manager.Next(), nextTime + period); APSARA_TEST_EQUAL(manager.Count(), 2U); } void CommonUtilUnittest::TestCycleCount() { FrequencyManager manager; // 设置100ms的周期 std::chrono::milliseconds period(100); manager.SetPeriod(period); auto now = std::chrono::steady_clock::now(); // 验证初始计数 APSARA_TEST_EQUAL(manager.Count(), 0U); // 连续重置几次,验证计数增加 manager.Reset(now); APSARA_TEST_EQUAL(manager.Count(), 1U); manager.Reset(now + std::chrono::milliseconds(100)); APSARA_TEST_EQUAL(manager.Count(), 2U); manager.Reset(now + std::chrono::milliseconds(200)); APSARA_TEST_EQUAL(manager.Count(), 3U); } void CommonUtilUnittest::TestMultipleCycles() { FrequencyManager manager; // 设置100ms的周期 std::chrono::milliseconds period(100); manager.SetPeriod(period); auto now = std::chrono::steady_clock::now(); manager.Reset(now); // 模拟多个周期的场景 for (int i = 1; i <= 5; i++) { auto cycleTime = now + std::chrono::milliseconds(i * 100); APSARA_TEST_TRUE(manager.Expired(cycleTime)); manager.Reset(cycleTime); APSARA_TEST_EQUAL(manager.Count(), uint32_t(i + 1)); APSARA_TEST_EQUAL(manager.Next(), cycleTime + period); } } void CommonUtilUnittest::TraceIDBenchmark() { auto tid = GenerateTraceID(); auto str = TraceIDToString(tid); LOG_INFO(sLogger, ("origin traceID", str)); auto start = std::chrono::high_resolution_clock::now(); for (int i = 0; i < 1000000; i++) { GenerateTraceID(); } auto end = std::chrono::high_resolution_clock::now(); std::chrono::duration<double> elapsed = end - start; std::cout << "[GenerateTraceID] elapsed: " << elapsed.count() << " seconds" << std::endl; } void CommonUtilUnittest::FromTraceIDBenchmark() { auto tid = GenerateTraceID(); auto str = TraceIDToString(tid); std::vector<std::array<uint64_t, 4>> traceIDs; for (int i = 0; i < 1000000; i++) { traceIDs.push_back(GenerateTraceID()); } auto start = std::chrono::high_resolution_clock::now(); for (int i = 0; i < 1000000; i++) { TraceIDToString(traceIDs[i]); } auto end = std::chrono::high_resolution_clock::now(); std::chrono::duration<double> elapsed = end - start; std::cout << "[FromTraceID] elapsed: " << elapsed.count() << " seconds" << std::endl; } // for trace id util UNIT_TEST_CASE(CommonUtilUnittest, TestTraceIDGeneration); UNIT_TEST_CASE(CommonUtilUnittest, TestTraceIDFormat); UNIT_TEST_CASE(CommonUtilUnittest, TestTraceIDUniqueness); UNIT_TEST_CASE(CommonUtilUnittest, TestSpanIDGeneration); UNIT_TEST_CASE(CommonUtilUnittest, TestSpanIDFormat); UNIT_TEST_CASE(CommonUtilUnittest, TestSpanIDUniqueness); UNIT_TEST_CASE(CommonUtilUnittest, TestTraceIDConversion); UNIT_TEST_CASE(CommonUtilUnittest, TestSpanIDConversion); UNIT_TEST_CASE(CommonUtilUnittest, TraceIDBenchmark); UNIT_TEST_CASE(CommonUtilUnittest, FromTraceIDBenchmark); // for freq manager UNIT_TEST_CASE(CommonUtilUnittest, TestInitialState); UNIT_TEST_CASE(CommonUtilUnittest, TestPeriodSetting); UNIT_TEST_CASE(CommonUtilUnittest, TestExpiredCheck); UNIT_TEST_CASE(CommonUtilUnittest, TestReset); UNIT_TEST_CASE(CommonUtilUnittest, TestCycleCount); UNIT_TEST_CASE(CommonUtilUnittest, TestMultipleCycles); // for exec id util } // namespace ebpf } // namespace logtail UNIT_TEST_MAIN