core/unittest/ebpf/NetworkObserverEventUnittest.cpp (224 lines of code) (raw):
// Copyright 2024 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 "ebpf/type/NetworkObserverEvent.h"
#include "unittest/Unittest.h"
namespace logtail {
namespace ebpf {
class NetworkObserverEventUnittest : public ::testing::Test {
public:
void TestConnId();
void TestConnIdHash();
void TestCaseInsensitiveLess();
void TestHeadersMap();
void TestConnStatsRecord();
void TestHttpRecord();
void TestAppMetricData();
void TestNetMetricData();
void TestConnIdMove();
void TestConnIdFromConnectId();
void TestHeadersMapCaseInsensitive();
void TestHttpRecordTimestamps();
void TestHttpRecordStatus();
void TestAbstractNetRecord();
protected:
std::shared_ptr<Connection> CreateTestTracker() {
ConnId connId(1, 1000, 123456);
return std::make_shared<Connection>(connId);
}
void SetUp() override {}
void TearDown() override {}
};
void NetworkObserverEventUnittest::TestConnId() {
// 测试构造函数
ConnId id1(1, 1000, 123456);
APSARA_TEST_EQUAL(id1.fd, 1);
APSARA_TEST_EQUAL(id1.tgid, 1000U);
APSARA_TEST_EQUAL(id1.start, 123456UL);
// 测试拷贝构造
ConnId id2(id1);
APSARA_TEST_EQUAL(id2.fd, id1.fd);
APSARA_TEST_EQUAL(id2.tgid, id1.tgid);
APSARA_TEST_EQUAL(id2.start, id1.start);
// 测试移动构造
ConnId id3(ConnId(2, 2000, 234567));
APSARA_TEST_EQUAL(id3.fd, 2);
APSARA_TEST_EQUAL(id3.tgid, 2000U);
APSARA_TEST_EQUAL(id3.start, 234567UL);
// 测试相等运算符
APSARA_TEST_TRUE(id1 == id2);
APSARA_TEST_FALSE(id1 == id3);
}
void NetworkObserverEventUnittest::TestConnIdHash() {
ConnId id1(1, 1000, 123456);
ConnId id2(1, 1000, 123456);
ConnId id3(2, 2000, 234567);
ConnIdHash hasher;
// 相同的 ConnId 应该有相同的哈希值
APSARA_TEST_EQUAL(hasher(id1), hasher(id2));
// 不同的 ConnId 应该有不同的哈希值
APSARA_TEST_TRUE(hasher(id1) != hasher(id3));
}
void NetworkObserverEventUnittest::TestCaseInsensitiveLess() {
CaseInsensitiveLess comparator;
// 测试相同字符串的不同大小写
APSARA_TEST_FALSE(comparator(std::string("hello"), std::string("HELLO")));
APSARA_TEST_FALSE(comparator(std::string("HELLO"), std::string("hello")));
// 测试不同字符串
APSARA_TEST_TRUE(comparator(std::string("hello"), std::string("world")));
APSARA_TEST_TRUE(comparator(std::string("HELLO"), std::string("WORLD")));
}
void NetworkObserverEventUnittest::TestHeadersMap() {
HeadersMap headers;
// 测试大小写不敏感的键
headers.insert({"Content-Type", "application/json"});
headers.insert({"CONTENT-TYPE", "text/plain"});
// 验证插入的值
auto range = headers.equal_range("content-type");
std::vector<std::string> values;
for (auto it = range.first; it != range.second; ++it) {
values.push_back(it->second);
}
APSARA_TEST_EQUAL(values.size(), 2UL);
APSARA_TEST_TRUE(std::find(values.begin(), values.end(), "application/json") != values.end());
APSARA_TEST_TRUE(std::find(values.begin(), values.end(), "text/plain") != values.end());
}
void NetworkObserverEventUnittest::TestConnStatsRecord() {
// ConnId id(1, 1000, 123456);
auto conn = CreateTestTracker();
ConnStatsRecord record(conn);
// 测试基本属性
APSARA_TEST_FALSE(record.IsError());
APSARA_TEST_FALSE(record.IsSlow());
APSARA_TEST_EQUAL(record.GetStatusCode(), 0);
}
void NetworkObserverEventUnittest::TestHttpRecord() {
auto conn = CreateTestTracker();
HttpRecord record(conn);
record.SetPath("/api/v1/test");
record.SetMethod("GET");
record.SetStatusCode(200);
record.SetProtocolVersion("HTTP/1.1");
APSARA_TEST_EQUAL(record.GetPath(), "/api/v1/test");
APSARA_TEST_EQUAL(record.GetMethod(), "GET");
APSARA_TEST_EQUAL(record.GetStatusCode(), 200);
APSARA_TEST_EQUAL(record.GetProtocolVersion(), "HTTP/1.1");
APSARA_TEST_FALSE(record.IsError());
record.SetStatusCode(404);
APSARA_TEST_TRUE(record.IsError());
APSARA_TEST_EQUAL(record.GetStatusCode(), 404);
// 测试请求头
HeadersMap reqHeaders;
reqHeaders.insert({"Content-Type", "application/json"});
record.SetReqHeaderMap(std::move(reqHeaders));
APSARA_TEST_EQUAL(record.GetReqHeaderMap().size(), 1UL);
// 测试响应头
HeadersMap respHeaders;
respHeaders.insert({"Content-Length", "100"});
record.SetRespHeaderMap(std::move(respHeaders));
APSARA_TEST_EQUAL(record.GetRespHeaderMap().size(), 1UL);
}
void NetworkObserverEventUnittest::TestAppMetricData() {
auto conn = CreateTestTracker();
std::shared_ptr<SourceBuffer> sourceBuffer = std::make_shared<SourceBuffer>();
AppMetricData data(conn, sourceBuffer, "test_span");
// 测试基本属性设置和获取
data.mCount = 100;
data.mSum = 1000.0;
data.mSlowCount = 5;
data.mErrCount = 2;
data.m2xxCount = 80;
data.m3xxCount = 10;
data.m4xxCount = 8;
data.m5xxCount = 2;
APSARA_TEST_EQUAL(data.mCount, 100UL);
APSARA_TEST_EQUAL(data.mSum, 1000.0);
APSARA_TEST_EQUAL(data.mSlowCount, 5UL);
APSARA_TEST_EQUAL(data.mErrCount, 2UL);
APSARA_TEST_EQUAL(data.m2xxCount, 80UL);
APSARA_TEST_EQUAL(data.m3xxCount, 10UL);
APSARA_TEST_EQUAL(data.m4xxCount, 8UL);
APSARA_TEST_EQUAL(data.m5xxCount, 2UL);
}
void NetworkObserverEventUnittest::TestNetMetricData() {
auto conn = CreateTestTracker();
auto sourceBuffer = std::make_shared<SourceBuffer>();
NetMetricData data(conn, sourceBuffer);
// 测试基本属性设置和获取
data.mDropCount = 10;
data.mRetransCount = 5;
data.mRtt = 100;
data.mRecvBytes = 1024;
data.mSendBytes = 2048;
data.mRecvPkts = 100;
data.mSendPkts = 200;
APSARA_TEST_EQUAL(data.mDropCount, 10UL);
APSARA_TEST_EQUAL(data.mRetransCount, 5UL);
APSARA_TEST_EQUAL(data.mRtt, 100UL);
APSARA_TEST_EQUAL(data.mRecvBytes, 1024UL);
APSARA_TEST_EQUAL(data.mSendBytes, 2048UL);
APSARA_TEST_EQUAL(data.mRecvPkts, 100UL);
APSARA_TEST_EQUAL(data.mSendPkts, 200UL);
}
void NetworkObserverEventUnittest::TestConnIdMove() {
ConnId id1(1, 1000, 123456);
ConnId id2(std::move(id1));
APSARA_TEST_EQUAL(id2.fd, 1);
APSARA_TEST_EQUAL(id2.tgid, 1000U);
APSARA_TEST_EQUAL(id2.start, 123456UL);
}
void NetworkObserverEventUnittest::TestConnIdFromConnectId() {
connect_id_t conn_id;
conn_id.fd = 5;
conn_id.tgid = 2000;
conn_id.start = 789012;
ConnId id(conn_id);
APSARA_TEST_EQUAL(id.fd, 5);
APSARA_TEST_EQUAL(id.tgid, 2000U);
APSARA_TEST_EQUAL(id.start, 789012UL);
}
void NetworkObserverEventUnittest::TestHeadersMapCaseInsensitive() {
HeadersMap headers;
headers.insert({"Content-Type", "application/json"});
// 测试大小写不敏感的键查找
auto res = headers.find("content-type");
APSARA_TEST_NOT_EQUAL(res, headers.end());
APSARA_TEST_STREQ(res->second.c_str(), "application/json");
res = headers.find("CONTENT-TYPE");
APSARA_TEST_NOT_EQUAL(res, headers.end());
APSARA_TEST_STREQ(res->second.c_str(), "application/json");
// 测试多值插入
headers.insert({"Accept", "text/plain"});
headers.insert({"ACCEPT", "application/xml"});
APSARA_TEST_EQUAL(headers.size(), 3UL);
// 测试不存在的键
APSARA_TEST_TRUE(headers.find("nonexistent") == headers.end());
}
void NetworkObserverEventUnittest::TestHttpRecordTimestamps() {
auto conn = CreateTestTracker();
HttpRecord record(conn);
record.SetStartTsNs(1000000);
record.SetEndTsNs(2000000);
APSARA_TEST_EQUAL(record.GetStartTimeStamp(), 1000000UL);
APSARA_TEST_EQUAL(record.GetEndTimeStamp(), 2000000UL);
APSARA_TEST_EQUAL(record.GetLatencyNs(), 1000000.0);
APSARA_TEST_EQUAL(record.GetLatencyMs(), 1.0);
}
void NetworkObserverEventUnittest::TestHttpRecordStatus() {
auto conn = CreateTestTracker();
HttpRecord record(conn);
record.SetStatusCode(200);
APSARA_TEST_FALSE(record.IsError());
record.SetStatusCode(500);
APSARA_TEST_TRUE(record.IsError());
record.SetStartTsNs(0);
record.SetEndTsNs(600000000); // 600ms
APSARA_TEST_TRUE(record.IsSlow());
HeadersMap reqHeaders;
reqHeaders.insert({"Content-Type", "application/json"});
record.SetReqHeaderMap(std::move(reqHeaders));
HeadersMap respHeaders;
respHeaders.insert({"Content-Length", "100"});
record.SetRespHeaderMap(std::move(respHeaders));
APSARA_TEST_EQUAL(record.GetReqHeaderMap().size(), 1UL);
APSARA_TEST_EQUAL(record.GetRespHeaderMap().size(), 1UL);
}
void NetworkObserverEventUnittest::TestAbstractNetRecord() {
auto conn = CreateTestTracker();
ConnStatsRecord record(conn);
}
UNIT_TEST_CASE(NetworkObserverEventUnittest, TestConnId);
UNIT_TEST_CASE(NetworkObserverEventUnittest, TestConnIdHash);
UNIT_TEST_CASE(NetworkObserverEventUnittest, TestCaseInsensitiveLess);
UNIT_TEST_CASE(NetworkObserverEventUnittest, TestHeadersMap);
UNIT_TEST_CASE(NetworkObserverEventUnittest, TestConnStatsRecord);
UNIT_TEST_CASE(NetworkObserverEventUnittest, TestHttpRecord);
UNIT_TEST_CASE(NetworkObserverEventUnittest, TestAppMetricData);
UNIT_TEST_CASE(NetworkObserverEventUnittest, TestNetMetricData);
UNIT_TEST_CASE(NetworkObserverEventUnittest, TestConnIdMove);
UNIT_TEST_CASE(NetworkObserverEventUnittest, TestConnIdFromConnectId);
UNIT_TEST_CASE(NetworkObserverEventUnittest, TestHeadersMapCaseInsensitive);
UNIT_TEST_CASE(NetworkObserverEventUnittest, TestHttpRecordTimestamps);
UNIT_TEST_CASE(NetworkObserverEventUnittest, TestHttpRecordStatus);
UNIT_TEST_CASE(NetworkObserverEventUnittest, TestAbstractNetRecord);
} // namespace ebpf
} // namespace logtail
UNIT_TEST_MAIN