| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222 |
- // 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;
- });
- }
|