mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-09-08 07:42:55 +02:00
222 lines
7.6 KiB
C++
222 lines
7.6 KiB
C++
// Copyright The OpenTelemetry Authors
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
#include <assert.h>
|
|
#include <gtest/gtest.h>
|
|
#include <stddef.h>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "opentelemetry/baggage/baggage.h"
|
|
#include "opentelemetry/common/kv_properties.h"
|
|
#include "opentelemetry/nostd/function_ref.h"
|
|
#include "opentelemetry/nostd/shared_ptr.h"
|
|
#include "opentelemetry/nostd/string_view.h"
|
|
|
|
using namespace opentelemetry::baggage;
|
|
|
|
std::string header_with_custom_entries(size_t num_entries)
|
|
{
|
|
std::string header;
|
|
for (size_t i = 0; i < num_entries; i++)
|
|
{
|
|
std::string key = "key" + std::to_string(i);
|
|
std::string value = "value" + std::to_string(i);
|
|
header.append(key).append("=").append(value);
|
|
if (i != num_entries - 1)
|
|
{
|
|
header += ",";
|
|
}
|
|
}
|
|
return header;
|
|
}
|
|
|
|
std::string header_with_custom_size(size_t key_value_size, size_t num_entries)
|
|
{
|
|
std::string header = "";
|
|
for (size_t i = 0; i < num_entries; i++)
|
|
{
|
|
std::string str = std::to_string(i + 1);
|
|
str += "=";
|
|
assert(key_value_size > str.size());
|
|
for (size_t j = str.size(); j < key_value_size; j++)
|
|
{
|
|
str += "a";
|
|
}
|
|
|
|
header += str + ',';
|
|
}
|
|
|
|
header.pop_back();
|
|
return header;
|
|
}
|
|
|
|
TEST(BaggageTest, ValidateExtractHeader)
|
|
{
|
|
auto invalid_key_value_size_header = header_with_custom_size(Baggage::kMaxKeyValueSize + 5, 1);
|
|
|
|
struct
|
|
{
|
|
const char *input;
|
|
std::vector<const char *> keys;
|
|
std::vector<const char *> values;
|
|
} testcases[] = {
|
|
{"k1=v1", {"k1"}, {"v1"}},
|
|
{"k1=V1,K2=v2;metadata,k3=v3",
|
|
{"k1", "K2", "k3"},
|
|
{"V1", "v2;metadata", "v3"}}, // metadata is part of value
|
|
{",k1 =v1,k2=v2 ; metadata,",
|
|
{"k1", "k2"},
|
|
{"v1", "v2; metadata"}}, // key and value are trimmed
|
|
{"1a-2f%40foo=bar%251,a%2A%2Ffoo-_%2Fbar=bar+4",
|
|
{"1a-2f@foo", "a*/foo-_/bar"},
|
|
{"bar%1", "bar 4"}}, // decoding is done properly
|
|
{"k1=v1,invalidmember,k2=v2", {"k1", "k2"}, {"v1", "v2"}}, // invalid member is skipped
|
|
{",", {}, {}},
|
|
{",=,", {}, {}},
|
|
{"", {}, {}},
|
|
{"k1=%5zv", {}, {}}, // invalid hex : invalid second digit
|
|
{"k1=%5", {}, {}}, // invalid hex : missing two digits
|
|
{"k%z2=v1", {}, {}}, // invalid hex : invalid first digit
|
|
{"k%00=v1", {}, {}}, // key not valid
|
|
{"k=v%7f", {}, {}}, // value not valid
|
|
{invalid_key_value_size_header.data(), {}, {}}};
|
|
for (auto &testcase : testcases)
|
|
{
|
|
auto baggage = Baggage::FromHeader(testcase.input);
|
|
size_t index = 0;
|
|
baggage->GetAllEntries([&testcase, &index](opentelemetry::nostd::string_view key,
|
|
opentelemetry::nostd::string_view value) {
|
|
EXPECT_EQ(key, testcase.keys[index]);
|
|
EXPECT_EQ(value, testcase.values[index]);
|
|
index++;
|
|
return true;
|
|
});
|
|
}
|
|
|
|
// For header with maximum threshold pairs, no pair is dropped
|
|
auto max_pairs_header = header_with_custom_entries(Baggage::kMaxKeyValuePairs);
|
|
EXPECT_EQ(Baggage::FromHeader(max_pairs_header.data())->ToHeader(), max_pairs_header.data());
|
|
|
|
// Entries beyond threshold are dropped
|
|
auto baggage = Baggage::FromHeader(header_with_custom_entries(Baggage::kMaxKeyValuePairs + 1));
|
|
auto header = baggage->ToHeader();
|
|
opentelemetry::common::KeyValueStringTokenizer kv_str_tokenizer(header);
|
|
int expected_tokens = Baggage::kMaxKeyValuePairs;
|
|
EXPECT_EQ(kv_str_tokenizer.NumTokens(), expected_tokens);
|
|
|
|
// For header with total size more than threshold, baggage is empty
|
|
int num_pairs_with_max_size = Baggage::kMaxSize / Baggage::kMaxKeyValueSize;
|
|
auto invalid_total_size_header =
|
|
header_with_custom_size(Baggage::kMaxKeyValueSize, num_pairs_with_max_size + 1);
|
|
EXPECT_EQ(Baggage::FromHeader(invalid_total_size_header.data())->ToHeader(), "");
|
|
}
|
|
|
|
TEST(BaggageTest, ValidateInjectHeader)
|
|
{
|
|
struct
|
|
{
|
|
std::vector<const char *> keys;
|
|
std::vector<const char *> values;
|
|
const char *header;
|
|
} testcases[] = {{{"k1"}, {"v1"}, "k1=v1"},
|
|
{{"k3", "k2", "k1"}, {"", "v2", "v1"}, "k1=v1,k2=v2,k3="}, // empty value
|
|
{{"1a-2f@foo", "a*/foo-_/bar"},
|
|
{"bar%1", "bar 4"},
|
|
"a%2A%2Ffoo-_%2Fbar=bar+4,1a-2f%40foo=bar%251"}, // encoding is done properly
|
|
{{"foo 1"},
|
|
{"bar 1; metadata ; ;;"},
|
|
"foo+1=bar+1; metadata ; ;;"}}; // metadata is added without encoding
|
|
|
|
for (auto &testcase : testcases)
|
|
{
|
|
opentelemetry::nostd::shared_ptr<Baggage> baggage(new Baggage{});
|
|
for (size_t i = 0; i < testcase.keys.size(); i++)
|
|
{
|
|
baggage = baggage->Set(testcase.keys[i], testcase.values[i]);
|
|
}
|
|
EXPECT_EQ(baggage->ToHeader(), testcase.header);
|
|
}
|
|
}
|
|
|
|
TEST(BaggageTest, BaggageGet)
|
|
{
|
|
auto header = header_with_custom_entries(Baggage::kMaxKeyValuePairs);
|
|
auto baggage = Baggage::FromHeader(header);
|
|
|
|
std::string value;
|
|
EXPECT_TRUE(baggage->GetValue("key0", value));
|
|
EXPECT_EQ(value, "value0");
|
|
EXPECT_TRUE(baggage->GetValue("key16", value));
|
|
EXPECT_EQ(value, "value16");
|
|
|
|
EXPECT_TRUE(baggage->GetValue("key31", value));
|
|
EXPECT_EQ(value, "value31");
|
|
|
|
EXPECT_FALSE(baggage->GetValue("key181", value));
|
|
}
|
|
|
|
TEST(BaggageTest, BaggageSet)
|
|
{
|
|
std::string header = "k1=v1,k2=v2";
|
|
auto baggage = Baggage::FromHeader(header);
|
|
|
|
std::string value;
|
|
baggage = baggage->Set("k3", "v3");
|
|
EXPECT_TRUE(baggage->GetValue("k3", value));
|
|
EXPECT_EQ(value, "v3");
|
|
|
|
baggage = baggage->Set("k3", "v3_1"); // key should be updated with the latest value
|
|
EXPECT_TRUE(baggage->GetValue("k3", value));
|
|
EXPECT_EQ(value, "v3_1");
|
|
|
|
header = header_with_custom_entries(Baggage::kMaxKeyValuePairs);
|
|
baggage = Baggage::FromHeader(header);
|
|
baggage = baggage->Set("key0", "0"); // updating on max list should work
|
|
EXPECT_TRUE(baggage->GetValue("key0", value));
|
|
EXPECT_EQ(value, "0");
|
|
|
|
header = "k1=v1,k2=v2";
|
|
baggage = Baggage::FromHeader(header);
|
|
baggage = baggage->Set("", "n_v1"); // adding invalid key, should return copy of same baggage
|
|
EXPECT_EQ(baggage->ToHeader(), header);
|
|
|
|
header = "k1=v1,k2=v2";
|
|
baggage = Baggage::FromHeader(header);
|
|
baggage = baggage->Set("k1", "\x1A"); // adding invalid value, should return copy of same baggage
|
|
EXPECT_EQ(baggage->ToHeader(), header);
|
|
}
|
|
|
|
TEST(BaggageTest, BaggageRemove)
|
|
{
|
|
auto header = header_with_custom_entries(Baggage::kMaxKeyValuePairs);
|
|
auto baggage = Baggage::FromHeader(header);
|
|
std::string value;
|
|
|
|
// existing key is removed
|
|
EXPECT_TRUE(baggage->GetValue("key0", value));
|
|
auto new_baggage = baggage->Delete("key0");
|
|
EXPECT_FALSE(new_baggage->GetValue("key0", value));
|
|
|
|
// trying Delete on non existent key
|
|
EXPECT_FALSE(baggage->GetValue("key181", value));
|
|
auto new_baggage_2 = baggage->Delete("key181");
|
|
EXPECT_FALSE(new_baggage_2->GetValue("key181", value));
|
|
}
|
|
|
|
TEST(BaggageTest, BaggageGetAll)
|
|
{
|
|
std::string baggage_header = "k1=v1,k2=v2,k3=v3";
|
|
auto baggage = Baggage::FromHeader(baggage_header);
|
|
const int kNumPairs = 3;
|
|
opentelemetry::nostd::string_view keys[kNumPairs] = {"k1", "k2", "k3"};
|
|
opentelemetry::nostd::string_view values[kNumPairs] = {"v1", "v2", "v3"};
|
|
size_t index = 0;
|
|
baggage->GetAllEntries([&keys, &values, &index](opentelemetry::nostd::string_view key,
|
|
opentelemetry::nostd::string_view value) {
|
|
EXPECT_EQ(key, keys[index]);
|
|
EXPECT_EQ(value, values[index]);
|
|
index++;
|
|
return true;
|
|
});
|
|
}
|