From ef786bdcff8f47e64de25540ba8ef43b6e7bc537 Mon Sep 17 00:00:00 2001 From: ndaliya Date: Tue, 30 Mar 2021 00:16:56 +0530 Subject: [PATCH 1/5] Refactoring trace_state to reuse common part in baggage --- .../opentelemetry/common/kv_properties.h | 239 ++++++++++++++++++ .../opentelemetry/common/string_util.h | 42 +++ api/include/opentelemetry/trace/trace_state.h | 236 ++++++----------- api/test/common/BUILD | 22 ++ api/test/common/kv_properties_test.cc | 198 +++++++++++++++ api/test/common/string_util_test.cc | 39 +++ api/test/trace/trace_state_test.cc | 111 ++++---- 7 files changed, 659 insertions(+), 228 deletions(-) create mode 100644 api/include/opentelemetry/common/kv_properties.h create mode 100644 api/include/opentelemetry/common/string_util.h create mode 100644 api/test/common/kv_properties_test.cc create mode 100644 api/test/common/string_util_test.cc diff --git a/api/include/opentelemetry/common/kv_properties.h b/api/include/opentelemetry/common/kv_properties.h new file mode 100644 index 0000000000..86cd37bfcd --- /dev/null +++ b/api/include/opentelemetry/common/kv_properties.h @@ -0,0 +1,239 @@ +// Copyright 2021, OpenTelemetry 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 "opentelemetry/common/key_value_iterable_view.h" +#include "opentelemetry/common/string_util.h" +#include "opentelemetry/nostd/function_ref.h" +#include "opentelemetry/nostd/shared_ptr.h" +#include "opentelemetry/nostd/string_view.h" +#include "opentelemetry/nostd/unique_ptr.h" +#include "opentelemetry/version.h" + +#include +#include + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace common +{ + +// Iterator for key-value headers +class KeyValueStringIterator +{ +public: + KeyValueStringIterator(nostd::string_view str, + char member_separator = ',', + char key_value_separator = '=') + : str_(str), + member_separator_(member_separator), + key_value_separator_(key_value_separator), + index_(0) + {} + + // Returns next key value in the string header + // @param valid_kv : if the found kv pair is valid or not + // @param key : key in kv pair + // @param key : value in kv pair + // @returns true if next kv pair was found, false otherwise. + bool next(bool &valid_kv, nostd::string_view &key, nostd::string_view &value) + { + valid_kv = true; + while (index_ < str_.size()) + { + size_t end = str_.find(member_separator_, index_); + if (end == std::string::npos) + { + end = str_.size() - 1; + } + else + { + end--; + } + + auto list_member = StringUtil::Trim(str_, index_, end); + if (list_member.size() == 0) + { + // empty list member. Move to next entry. For both baggage and trace_state this is valid + // behaviour. + index_ = end + 2; + continue; + } + + auto key_end_pos = list_member.find(key_value_separator_); + if (key_end_pos == std::string::npos) + { + // invalid member + valid_kv = false; + } + else + { + key = list_member.substr(0, key_end_pos); + value = list_member.substr(key_end_pos + 1); + } + + index_ = end + 2; + + return true; + } + + // no more entries remaining + return false; + } + + // Resets the iterator + void reset() noexcept { index_ = 0; } + +private: + nostd::string_view str_; + const char member_separator_; + const char key_value_separator_; + size_t index_; +}; + +// Class to store fixed size array of key-value pairs of string type +class KeyValueProperties +{ + // Class to store key-value pairs of string types +public: + class Entry + { + public: + Entry() : key_(nullptr), value_(nullptr) {} + + // Copy constructor + Entry(const Entry ©) + { + key_ = CopyStringToPointer(copy.key_.get()); + value_ = CopyStringToPointer(copy.value_.get()); + } + + // Copy assignment operator + Entry &operator=(Entry &other) + { + key_ = CopyStringToPointer(other.key_.get()); + value_ = CopyStringToPointer(other.value_.get()); + return *this; + } + + // Move contructor and assignment operator + Entry(Entry &&other) = default; + Entry &operator=(Entry &&other) = default; + + // Creates an Entry for a given key-value pair. + Entry(nostd::string_view key, nostd::string_view value) + { + key_ = CopyStringToPointer(key); + value_ = CopyStringToPointer(value); + } + + // Gets the key associated with this entry. + nostd::string_view GetKey() const { return key_.get(); } + + // Gets the value associated with this entry. + nostd::string_view GetValue() const { return value_.get(); } + + // Sets the value for this entry. This overrides the previous value. + void SetValue(nostd::string_view value) { value_ = CopyStringToPointer(value); } + + private: + // Store key and value as raw char pointers to avoid using std::string. + nostd::unique_ptr key_; + nostd::unique_ptr value_; + + // Copies string into a buffer and returns a unique_ptr to the buffer. + // This is a workaround for the fact that memcpy doesn't accept a const destination. + nostd::unique_ptr CopyStringToPointer(nostd::string_view str) + { + char *temp = new char[str.size() + 1]; + memcpy(temp, str.data(), str.size()); + temp[str.size()] = '\0'; + return nostd::unique_ptr(temp); + } + }; + + // Maintain the number of entries in entries_. + size_t num_entries_; + + // Max size of allocated array + size_t max_num_entries_; + + // Store entries in a C-style array to avoid using std::array or std::vector. + nostd::unique_ptr entries_; + +public: + // Create Key-value list of given size + // @param size : Size of list. + KeyValueProperties(size_t size) + : num_entries_(0), max_num_entries_(size), entries_(new Entry[size]) + {} + + // Create Empty Key-Value list + KeyValueProperties() : num_entries_(0), max_num_entries_(0), entries_(nullptr) {} + + template ::value>::type> + KeyValueProperties(const T &keys_and_values) + : num_entries_(0), + max_num_entries_(keys_and_values.size()), + entries_(new Entry[max_num_entries_]) + { + for (auto &e : keys_and_values) + { + Entry entry(e.first, e.second); + (entries_.get())[num_entries_++] = std::move(entry); + } + } + + // Adds new kv pair into kv properties + void AddEntry(const nostd::string_view &key, const nostd::string_view &value) + { + if (num_entries_ < max_num_entries_) + { + Entry entry(key, value); + (entries_.get())[num_entries_++] = std::move(entry); + } + } + + // Returns all kv pair entries + bool GetAllEntries( + nostd::function_ref callback) const + { + for (size_t i = 0; i < num_entries_; i++) + { + auto &entry = (entries_.get())[i]; + if (!callback(entry.GetKey(), entry.GetValue())) + { + return false; + } + } + return true; + } + + // Return value for key if exists, return false otherwise + bool GetValue(const nostd::string_view key, std::string &value) const + { + for (size_t i = 0; i < num_entries_; i++) + { + auto &entry = (entries_.get())[i]; + if (entry.GetKey() == key) + { + value = std::string(entry.GetValue()); + return true; + } + } + return false; + } + + size_t Size() const noexcept { return num_entries_; } +}; +} // namespace common +OPENTELEMETRY_END_NAMESPACE diff --git a/api/include/opentelemetry/common/string_util.h b/api/include/opentelemetry/common/string_util.h new file mode 100644 index 0000000000..353a76fbc9 --- /dev/null +++ b/api/include/opentelemetry/common/string_util.h @@ -0,0 +1,42 @@ +// Copyright 2021, OpenTelemetry 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. + +#pragma once + +#include "opentelemetry/nostd/string_view.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace common +{ + +class StringUtil +{ +public: + static nostd::string_view Trim(nostd::string_view str, size_t left, size_t right) + { + while (str[static_cast(left)] == ' ' && left <= right) + { + left++; + } + while (str[static_cast(right)] == ' ' && left <= right) + { + right--; + } + return str.substr(left, 1 + right - left); + } +}; + +} // namespace common + +OPENTELEMETRY_END_NAMESPACE diff --git a/api/include/opentelemetry/trace/trace_state.h b/api/include/opentelemetry/trace/trace_state.h index f786e719b3..c3f72e6890 100644 --- a/api/include/opentelemetry/trace/trace_state.h +++ b/api/include/opentelemetry/trace/trace_state.h @@ -25,6 +25,7 @@ # define HAVE_WORKING_REGEX 1 #endif +#include "opentelemetry/common/kv_properties.h" #include "opentelemetry/nostd/shared_ptr.h" #include "opentelemetry/nostd/span.h" #include "opentelemetry/nostd/string_view.h" @@ -51,63 +52,6 @@ class TraceState static constexpr auto kKeyValueSeparator = '='; static constexpr auto kMembersSeparator = ','; - // Class to store key-value pairs. - class Entry - { - public: - Entry() : key_(nullptr), value_(nullptr){}; - - // Copy constructor - Entry(const Entry ©) - { - key_ = CopyStringToPointer(copy.key_.get()); - value_ = CopyStringToPointer(copy.value_.get()); - } - - // Copy assignment operator - Entry &operator=(Entry &other) - { - key_ = CopyStringToPointer(other.key_.get()); - value_ = CopyStringToPointer(other.value_.get()); - return *this; - } - - // Move contructor and assignment operator - Entry(Entry &&other) = default; - Entry &operator=(Entry &&other) = default; - - // Creates an Entry for a given key-value pair. - Entry(nostd::string_view key, nostd::string_view value) noexcept - { - key_ = CopyStringToPointer(key); - value_ = CopyStringToPointer(value); - } - - // Gets the key associated with this entry. - nostd::string_view GetKey() const { return key_.get(); } - - // Gets the value associated with this entry. - nostd::string_view GetValue() const { return value_.get(); } - - // Sets the value for this entry. This overrides the previous value. - void SetValue(nostd::string_view value) { value_ = CopyStringToPointer(value); } - - private: - // Store key and value as raw char pointers to avoid using std::string. - nostd::unique_ptr key_; - nostd::unique_ptr value_; - - // Copies string into a buffer and returns a unique_ptr to the buffer. - // This is a workaround for the fact that memcpy doesn't accept a const destination. - nostd::unique_ptr CopyStringToPointer(nostd::string_view str) - { - char *temp = new char[str.size() + 1]; - memcpy(temp, str.data(), str.size()); - temp[str.size()] = '\0'; - return nostd::unique_ptr(temp); - } - }; - static nostd::shared_ptr GetDefault() { static nostd::shared_ptr ts{new TraceState()}; @@ -122,60 +66,35 @@ class TraceState */ static nostd::shared_ptr FromHeader(nostd::string_view header) { - nostd::shared_ptr ts{new TraceState()}; - std::size_t begin{0}; - std::size_t end{0}; - while (begin < header.size() && ts->num_entries_ < kMaxKeyValuePairs) + size_t cnt = 0; + common::KeyValueStringIterator kv_str_itr(header); + bool kv_valid; + nostd::string_view key, value; + while (kv_str_itr.next(kv_valid, key, value) && cnt < kMaxKeyValuePairs) { - // find list-member - end = header.find(kMembersSeparator, begin); - if (end == 0) + if (kv_valid == false) { - // special case where "," is first char, move to next list member - begin = 1; - continue; + return GetDefault(); } - if (end == std::string::npos) - { - // last list member. `end` points to end of it. - end = header.size() - 1; - } - else - { - // `end` points to end of current list member - end--; - } - auto list_member = TrimString(header, begin, end); // OWS handling - if (list_member.size() == 0) - { - // empty list member, move to next in list - begin = end + 2; // begin points to start of next member - continue; - } - auto key_end_pos = list_member.find(kKeyValueSeparator); - if (key_end_pos == std::string::npos) - { - // Error: invalid list member, return empty TraceState - ts->entries_.reset(nullptr); - ts->num_entries_ = 0; - break; - } - auto key = list_member.substr(0, key_end_pos); - auto value = list_member.substr(key_end_pos + 1); + + ++cnt; + } + + nostd::shared_ptr ts(new TraceState(cnt)); + kv_str_itr.reset(); + while (kv_str_itr.next(kv_valid, key, value) && ts->kv_properties_->Size() < cnt) + { if (!IsValidKey(key) || !IsValidValue(value)) { // invalid header. return empty TraceState - ts->entries_.reset(nullptr); - ts->num_entries_ = 0; + ts->kv_properties_.reset(new opentelemetry::common::KeyValueProperties()); break; } - Entry entry(key, value); - (ts->entries_.get())[ts->num_entries_] = entry; - ts->num_entries_++; - begin = end + 2; + ts->kv_properties_->AddEntry(key, value); } + return ts; } @@ -185,18 +104,22 @@ class TraceState std::string ToHeader() { std::string header_s; - for (size_t count = 0; count < num_entries_; count++) - { - if (count != 0) - { - header_s.append(","); - } - - auto entry = (entries_.get())[count]; - header_s.append(std::string(entry.GetKey())); - header_s.append(1, kKeyValueSeparator); - header_s.append(std::string(entry.GetValue())); - } + bool first = true; + kv_properties_->GetAllEntries( + [&header_s, &first](nostd::string_view key, nostd::string_view value) noexcept { + if (!first) + { + header_s.append(","); + } + else + { + first = false; + } + header_s.append(std::string(key)); + header_s.append(1, kKeyValueSeparator); + header_s.append(std::string(value)); + return true; + }); return header_s; } @@ -204,21 +127,14 @@ class TraceState * Returns `value` associated with `key` passed as argument * Returns empty string if key is invalid or not found */ - std::string Get(nostd::string_view key) const noexcept + bool Get(nostd::string_view key, std::string &value) const noexcept { if (!IsValidKey(key)) { - return std::string(); - } - for (size_t i = 0; i < num_entries_; i++) - { - auto entry = (entries_.get())[i]; - if (key == entry.GetKey()) - { - return std::string(entry.GetValue()); - } + return false; } - return std::string(); + + return kv_properties_->GetValue(key, value); } /** @@ -233,27 +149,28 @@ class TraceState */ nostd::shared_ptr Set(const nostd::string_view &key, const nostd::string_view &value) { - nostd::shared_ptr ts{new TraceState()}; - if ((!IsValidKey(key) || !IsValidValue(value))) + auto curr_size = kv_properties_->Size(); + if (!IsValidKey(key) || !IsValidValue(value)) { // max size reached or invalid key/value. Returning empty TraceState - return ts; // empty instance + return TraceState::GetDefault(); } - - // add new key-value pair at beginning if list is not reached to its limit - if (num_entries_ < kMaxKeyValuePairs) + auto allocate_size = curr_size; + if (curr_size < kMaxKeyValuePairs) { - Entry e(key, value); - (ts->entries_.get())[ts->num_entries_++] = e; + allocate_size += 1; } - for (size_t i = 0; i < num_entries_; i++) + nostd::shared_ptr ts(new TraceState(allocate_size)); + if (curr_size < kMaxKeyValuePairs) { - auto entry = (entries_.get())[i]; - auto key = entry.GetKey(); - auto value = entry.GetValue(); - Entry e(key, value); - (ts->entries_.get())[ts->num_entries_++] = e; + // add new field first + ts->kv_properties_->AddEntry(key, value); } + // add rest of the fields. + kv_properties_->GetAllEntries([&ts](nostd::string_view key, nostd::string_view value) { + ts->kv_properties_->AddEntry(key, value); + return true; + }); return ts; } @@ -265,35 +182,37 @@ class TraceState */ nostd::shared_ptr Delete(const nostd::string_view &key) { - nostd::shared_ptr ts{new TraceState()}; - if (!IsValidKey(key)) { - return ts; + return TraceState::GetDefault(); } - for (size_t i = 0; i < num_entries_; i++) + auto curr_size = kv_properties_->Size(); + auto allocate_size = curr_size; + std::string unused; + if (kv_properties_->GetValue(key, unused)) { - auto entry = (entries_.get())[i]; - if ((entries_.get())[i].GetKey() != key) - { - auto key = entry.GetKey(); - auto value = entry.GetValue(); - Entry e(key, value); - (ts->entries_.get())[ts->num_entries_++] = e; - } + allocate_size -= 1; } + nostd::shared_ptr ts(new TraceState(allocate_size)); + kv_properties_->GetAllEntries( + [&ts, &key](nostd::string_view e_key, nostd::string_view e_value) { + if (key != e_key) + ts->kv_properties_->AddEntry(e_key, e_value); + return true; + }); return ts; } // Returns true if there are no keys, false otherwise. - bool Empty() const noexcept { return num_entries_ == 0; } + bool Empty() const noexcept { return kv_properties_->Size() == 0; } - // Returns a span of all the entries. The TraceState object must outlive the span. - nostd::span Entries() const noexcept + // @return all key-values entris by repeatedly invoking the function reference passed as argument + // for each entry + bool GetAllEntries( + nostd::function_ref callback) const noexcept { - return nostd::span(entries_.get(), num_entries_); + return kv_properties_->GetAllEntries(callback); } - /** Returns whether key is a valid key. See https://www.w3.org/TR/trace-context/#key * Identifiers MUST begin with a lowercase letter or a digit, and can only contain * lowercase letters (a-z), digits (0-9), underscores (_), dashes (-), asterisks (*), @@ -324,8 +243,8 @@ class TraceState } private: - // Creates an empty TraceState. - TraceState() noexcept : entries_(new Entry[kMaxKeyValuePairs]), num_entries_(0) {} + TraceState() : kv_properties_(new opentelemetry::common::KeyValueProperties()){}; + TraceState(size_t size) : kv_properties_(new opentelemetry::common::KeyValueProperties(size)){}; static nostd::string_view TrimString(nostd::string_view str, size_t left, size_t right) { @@ -406,10 +325,7 @@ class TraceState private: // Store entries in a C-style array to avoid using std::array or std::vector. - nostd::unique_ptr entries_; - - // Maintain the number of entries in entries_. Must be in the range [0, kMaxKeyValuePairs]. - size_t num_entries_; + nostd::unique_ptr kv_properties_; }; } // namespace trace OPENTELEMETRY_END_NAMESPACE diff --git a/api/test/common/BUILD b/api/test/common/BUILD index 3297a9565c..b3d498a4d3 100644 --- a/api/test/common/BUILD +++ b/api/test/common/BUILD @@ -5,3 +5,25 @@ otel_cc_benchmark( srcs = ["spinlock_benchmark.cc"], deps = ["//api"], ) + +cc_test( + name = "kv_properties_test", + srcs = [ + "kv_properties_test.cc", + ], + deps = [ + "//api", + "@com_google_googletest//:gtest_main", + ], +) + +cc_test( + name = "string_util_test", + srcs = [ + "string_util_test.cc", + ], + deps = [ + "//api", + "@com_google_googletest//:gtest_main", + ], +) diff --git a/api/test/common/kv_properties_test.cc b/api/test/common/kv_properties_test.cc new file mode 100644 index 0000000000..ddf4fde1bc --- /dev/null +++ b/api/test/common/kv_properties_test.cc @@ -0,0 +1,198 @@ + +// Copyright 2021, OpenTelemetry 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 +#include + +#include +#include +#include + +// ------------------------- Entry class tests --------------------------------- + +using namespace opentelemetry; +using opentelemetry::common::KeyValueProperties; +// Test constructor that takes a key-value pair +TEST(EntryTest, KeyValueConstruction) +{ + opentelemetry::nostd::string_view key = "test_key"; + opentelemetry::nostd::string_view val = "test_value"; + KeyValueProperties::Entry e(key, val); + + EXPECT_EQ(key.size(), e.GetKey().size()); + EXPECT_EQ(key, e.GetKey()); + + EXPECT_EQ(val.size(), e.GetValue().size()); + EXPECT_EQ(val, e.GetValue()); +} + +// Test copy constructor +TEST(EntryTest, Copy) +{ + KeyValueProperties::Entry e("test_key", "test_value"); + KeyValueProperties::Entry copy(e); + EXPECT_EQ(copy.GetKey(), e.GetKey()); + EXPECT_EQ(copy.GetValue(), e.GetValue()); +} + +// Test assignment operator +TEST(EntryTest, Assignment) +{ + KeyValueProperties::Entry e("test_key", "test_value"); + KeyValueProperties::Entry empty; + empty = e; + EXPECT_EQ(empty.GetKey(), e.GetKey()); + EXPECT_EQ(empty.GetValue(), e.GetValue()); +} + +TEST(EntryTest, SetValue) +{ + KeyValueProperties::Entry e("test_key", "test_value"); + opentelemetry::nostd::string_view new_val = "new_value"; + e.SetValue(new_val); + + EXPECT_EQ(new_val.size(), e.GetValue().size()); + EXPECT_EQ(new_val, e.GetValue()); +} + +// ------------------------- KeyValueStringIterator tests --------------------------------- + +using opentelemetry::common::KeyValueStringIterator; + +TEST(KVStringIter, SinglePair) +{ + bool valid_kv; + nostd::string_view key, value; + opentelemetry::nostd::string_view str = "k1=v1"; + KeyValueStringIterator itr(str, ',', '='); + EXPECT_TRUE(itr.next(valid_kv, key, value)); + EXPECT_TRUE(valid_kv); + EXPECT_EQ(key, "k1"); + EXPECT_EQ(value, "v1"); + EXPECT_FALSE(itr.next(valid_kv, key, value)); +} + +TEST(KVStringIter, ValidPairsWithEmptyEntries) +{ + opentelemetry::nostd::string_view str = "k1:v1===k2:v2=="; + bool valid_kv; + nostd::string_view key, value; + KeyValueStringIterator itr(str, '=', ':'); + EXPECT_TRUE(itr.next(valid_kv, key, value)); + EXPECT_TRUE(valid_kv); + EXPECT_EQ(key, "k1"); + EXPECT_EQ(value, "v1"); + + EXPECT_TRUE(itr.next(valid_kv, key, value)); + EXPECT_TRUE(valid_kv); + EXPECT_EQ(key, "k2"); + EXPECT_EQ(value, "v2"); + + EXPECT_FALSE(itr.next(valid_kv, key, value)); +} + +TEST(KVStringIter, InvalidPairs) +{ + opentelemetry::nostd::string_view str = "k1=v1,invalid ,, k2=v2 ,invalid"; + KeyValueStringIterator itr(str); + bool valid_kv; + nostd::string_view key, value; + EXPECT_TRUE(itr.next(valid_kv, key, value)); + + EXPECT_TRUE(valid_kv); + EXPECT_EQ(key, "k1"); + EXPECT_EQ(value, "v1"); + + EXPECT_TRUE(itr.next(valid_kv, key, value)); + EXPECT_FALSE(valid_kv); + + EXPECT_TRUE(itr.next(valid_kv, key, value)); + EXPECT_TRUE(valid_kv); + EXPECT_EQ(key, "k2"); + EXPECT_EQ(value, "v2"); + + EXPECT_TRUE(itr.next(valid_kv, key, value)); + EXPECT_FALSE(valid_kv); + + EXPECT_FALSE(itr.next(valid_kv, key, value)); +} + +//------------------------- KeyValueProperties tests --------------------------------- + +TEST(KeyValueProperties, PopulateKVIterableContainer) +{ + std::vector> kv_pairs = {{"k1", "v1"}, {"k2", "v2"}}; + + auto kv_properties = KeyValueProperties(kv_pairs); + EXPECT_EQ(kv_properties.Size(), 2); + + std::string value; + bool present = kv_properties.GetValue("k1", value); + EXPECT_TRUE(present); + EXPECT_EQ(value, "v1"); + + present = kv_properties.GetValue("k2", value); + EXPECT_TRUE(present); + EXPECT_EQ(value, "v2"); +} + +TEST(KeyValueProperties, AddEntry) +{ + auto kv_properties = KeyValueProperties(1); + kv_properties.AddEntry("k1", "v1"); + std::string value; + bool present = kv_properties.GetValue("k1", value); + EXPECT_TRUE(present); + EXPECT_EQ(value, "v1"); + + kv_properties.AddEntry("k2", "v2"); // entry will not be added as max size reached. + EXPECT_EQ(kv_properties.Size(), 1); + present = kv_properties.GetValue("k2", value); + EXPECT_FALSE(present); +} + +TEST(KeyValueProperties, GetValue) +{ + auto kv_properties = KeyValueProperties(1); + kv_properties.AddEntry("k1", "v1"); + std::string value; + bool present = kv_properties.GetValue("k1", value); + EXPECT_TRUE(present); + EXPECT_EQ(value, "v1"); + + present = kv_properties.GetValue("k3", value); + EXPECT_FALSE(present); +} + +TEST(KeyValueProperties, GetAllEntries) +{ + std::vector> kv_pairs = { + {"k1", "v1"}, {"k2", "v2"}, {"k3", "v3"}}; + const size_t kNumPairs = 3; + opentelemetry::nostd::string_view keys[kNumPairs] = {"k1", "k2", "k3"}; + opentelemetry::nostd::string_view values[kNumPairs] = {"v1", "v2", "v3"}; + auto kv_properties = KeyValueProperties(kv_pairs); + + size_t index = 0; + kv_properties.GetAllEntries( + [&keys, &values, &index](nostd::string_view key, nostd::string_view value) { + EXPECT_EQ(key, keys[index]); + EXPECT_EQ(value, values[index]); + index++; + return true; + }); + + EXPECT_EQ(index, kNumPairs); +} diff --git a/api/test/common/string_util_test.cc b/api/test/common/string_util_test.cc new file mode 100644 index 0000000000..9a43b69ef9 --- /dev/null +++ b/api/test/common/string_util_test.cc @@ -0,0 +1,39 @@ +// Copyright 2021, OpenTelemetry 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 +#include + +#include +#include +#include + +// ------------------------- StringUtil class tests --------------------------------- + +using opentelemetry::common::StringUtil; + +TEST(StringUtilTest, TrimString) +{ + struct + { + const char *input; + const char *expected; + } testcases[] = {{"k1=v1", "k1=v1"}, {"k1=v1,k2=v2, k3=v3", "k1=v1,k2=v2, k3=v3"}, + {" k1=v1", "k1=v1"}, {"k1=v1 ", "k1=v1"}, + {" k1=v1 ", "k1=v1"}, {" ", ""}}; + for (auto &testcase : testcases) + { + EXPECT_EQ(StringUtil::Trim(testcase.input, 0, strlen(testcase.input) - 1), testcase.expected); + } +} diff --git a/api/test/trace/trace_state_test.cc b/api/test/trace/trace_state_test.cc index 62a0661999..24c6eb4f78 100644 --- a/api/test/trace/trace_state_test.cc +++ b/api/test/trace/trace_state_test.cc @@ -1,3 +1,17 @@ +// Copyright 2021, OpenTelemetry 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 "opentelemetry/trace/trace_state.h" #include @@ -7,6 +21,7 @@ namespace { using opentelemetry::trace::TraceState; +namespace nostd = opentelemetry::nostd; // Random string of length 257. Used for testing strings with max length 256. const char *kLongString = @@ -14,51 +29,6 @@ const char *kLongString = "2nmihy4vilabfts8bsxruih0urusmjnglzl3iwpjinmo835dbojcrd73p56nw80v4xxrkye59ytmu5v84ysfa24d58ovv9" "w1n54n0mhhf4z0mpv6oudywrp9vfoks6lrvxv3uihvbi2ihazf237kvt1nbsjn3kdvfdb"; -// ------------------------- Entry class tests --------------------------------- - -// Test constructor that takes a key-value pair -TEST(EntryTest, KeyValueConstruction) -{ - opentelemetry::nostd::string_view key = "test_key"; - opentelemetry::nostd::string_view val = "test_value"; - TraceState::Entry e(key, val); - - EXPECT_EQ(key.size(), e.GetKey().size()); - EXPECT_EQ(key, e.GetKey()); - - EXPECT_EQ(val.size(), e.GetValue().size()); - EXPECT_EQ(val, e.GetValue()); -} - -// Test copy constructor -TEST(EntryTest, Copy) -{ - TraceState::Entry e("test_key", "test_value"); - TraceState::Entry copy(e); - EXPECT_EQ(copy.GetKey(), e.GetKey()); - EXPECT_EQ(copy.GetValue(), e.GetValue()); -} - -// Test assignment operator -TEST(EntryTest, Assignment) -{ - TraceState::Entry e("test_key", "test_value"); - TraceState::Entry empty; - empty = e; - EXPECT_EQ(empty.GetKey(), e.GetKey()); - EXPECT_EQ(empty.GetValue(), e.GetValue()); -} - -TEST(EntryTest, SetValue) -{ - TraceState::Entry e("test_key", "test_value"); - opentelemetry::nostd::string_view new_val = "new_value"; - e.SetValue(new_val); - - EXPECT_EQ(new_val.size(), e.GetValue().size()); - EXPECT_EQ(new_val, e.GetValue()); -} - // -------------------------- TraceState class tests --------------------------- std::string create_ts_return_header(std::string header) @@ -106,7 +76,7 @@ TEST(TraceStateTest, ValidateHeaderParsing) {max_trace_state_header.data(), max_trace_state_header.data()}}; for (auto &testcase : testcases) { - EXPECT_EQ(TraceState::FromHeader(testcase.input)->ToHeader(), testcase.expected); + EXPECT_EQ(create_ts_return_header(testcase.input), testcase.expected); } } @@ -116,10 +86,14 @@ TEST(TraceStateTest, TraceStateGet) std::string trace_state_header = header_with_max_members(); auto ts = TraceState::FromHeader(trace_state_header); - EXPECT_EQ(ts->Get("key0"), "value0"); - EXPECT_EQ(ts->Get("key16"), "value16"); - EXPECT_EQ(ts->Get("key31"), "value31"); - EXPECT_EQ(ts->Get("key32"), ""); // key not found + std::string value; + EXPECT_TRUE(ts->Get("key0", value)); + EXPECT_EQ(value, "value0"); + EXPECT_TRUE(ts->Get("key16", value)); + EXPECT_EQ(value, "value16"); + EXPECT_TRUE(ts->Get("key31", value)); + EXPECT_EQ(value, "value31"); + EXPECT_FALSE(ts->Get("key32", value)); } TEST(TraceStateTest, TraceStateSet) @@ -170,20 +144,20 @@ TEST(TraceStateTest, Empty) EXPECT_FALSE(ts1->Empty()); } -TEST(TraceStateTest, Entries) +TEST(TraceStateTest, GetAllEntries) { std::string trace_state_header = "k1=v1,k2=v2,k3=v3"; auto ts1 = TraceState::FromHeader(trace_state_header); const int kNumPairs = 3; opentelemetry::nostd::string_view keys[kNumPairs] = {"k1", "k2", "k3"}; opentelemetry::nostd::string_view values[kNumPairs] = {"v1", "v2", "v3"}; - - opentelemetry::nostd::span entries = ts1->Entries(); - for (int i = 0; i < kNumPairs; i++) - { - EXPECT_EQ(entries[i].GetKey(), keys[i]); - EXPECT_EQ(entries[i].GetValue(), values[i]); - } + size_t index = 0; + ts1->GetAllEntries([&keys, &values, &index](nostd::string_view key, nostd::string_view value) { + EXPECT_EQ(key, keys[index]); + EXPECT_EQ(value, values[index]); + index++; + return true; + }); } TEST(TraceStateTest, IsValidKey) @@ -218,15 +192,16 @@ TEST(TraceStateTest, MemorySafe) opentelemetry::nostd::string_view values[kNumPairs] = { val_string.substr(0, 10), val_string.substr(10, 10), val_string.substr(20, 10)}; - auto ts1 = ts->Set(keys[2], values[2]); - auto ts2 = ts1->Set(keys[1], values[1]); - auto ts3 = ts2->Set(keys[0], values[0]); - - opentelemetry::nostd::span entries = ts3->Entries(); - for (int i = 0; i < kNumPairs; i++) - { - EXPECT_EQ(entries[i].GetKey(), keys[i]); - EXPECT_EQ(entries[i].GetValue(), values[i]); - } + auto ts1 = ts->Set(keys[2], values[2]); + auto ts2 = ts1->Set(keys[1], values[1]); + auto ts3 = ts2->Set(keys[0], values[0]); + size_t index = 0; + + ts3->GetAllEntries([&keys, &values, &index](nostd::string_view key, nostd::string_view value) { + EXPECT_EQ(key, keys[index]); + EXPECT_EQ(value, values[index]); + index++; + return true; + }); } } // namespace From 75e1eac9d49dc14cf4cad15ae4e9d8019ea9fe08 Mon Sep 17 00:00:00 2001 From: ndaliya Date: Thu, 1 Apr 2021 19:49:49 +0530 Subject: [PATCH 2/5] Addressing review comments --- .../opentelemetry/common/kv_properties.h | 62 ++++++++++---- api/include/opentelemetry/trace/trace_state.h | 19 ++--- api/test/common/CMakeLists.txt | 16 ++++ api/test/common/kv_properties_test.cc | 84 +++++++++++++++---- 4 files changed, 137 insertions(+), 44 deletions(-) create mode 100644 api/test/common/CMakeLists.txt diff --git a/api/include/opentelemetry/common/kv_properties.h b/api/include/opentelemetry/common/kv_properties.h index 86cd37bfcd..9dfd0d4e00 100644 --- a/api/include/opentelemetry/common/kv_properties.h +++ b/api/include/opentelemetry/common/kv_properties.h @@ -27,17 +27,22 @@ OPENTELEMETRY_BEGIN_NAMESPACE namespace common { -// Iterator for key-value headers -class KeyValueStringIterator +// Constructor parameter for KeyValueStringTokenizer +struct KeyValueStringTokenizerOptions +{ + char member_separator = ','; + char key_value_separator = '='; + bool ignore_empty_members = true; +}; + +// Tokenizer for key-value headers +class KeyValueStringTokenizer { public: - KeyValueStringIterator(nostd::string_view str, - char member_separator = ',', - char key_value_separator = '=') - : str_(str), - member_separator_(member_separator), - key_value_separator_(key_value_separator), - index_(0) + KeyValueStringTokenizer( + nostd::string_view str, + const KeyValueStringTokenizerOptions &opts = KeyValueStringTokenizerOptions()) + : str_(str), opts_(opts), index_(0) {} // Returns next key value in the string header @@ -50,7 +55,7 @@ class KeyValueStringIterator valid_kv = true; while (index_ < str_.size()) { - size_t end = str_.find(member_separator_, index_); + size_t end = str_.find(opts_.member_separator, index_); if (end == std::string::npos) { end = str_.size() - 1; @@ -63,13 +68,20 @@ class KeyValueStringIterator auto list_member = StringUtil::Trim(str_, index_, end); if (list_member.size() == 0) { - // empty list member. Move to next entry. For both baggage and trace_state this is valid - // behaviour. + // empty list member index_ = end + 2; - continue; + if (opts_.ignore_empty_members) + { + continue; + } + + valid_kv = true; + key = ""; + value = ""; + return true; } - auto key_end_pos = list_member.find(key_value_separator_); + auto key_end_pos = list_member.find(opts_.key_value_separator); if (key_end_pos == std::string::npos) { // invalid member @@ -90,13 +102,31 @@ class KeyValueStringIterator return false; } + // Returns total number of tokens in header string + size_t NumTokens() const noexcept + { + size_t cnt = 0, begin = 0; + while (begin < str_.size()) + { + ++cnt; + size_t end = str_.find(opts_.member_separator, begin); + if (end == std::string::npos) + { + break; + } + + begin = end + 1; + } + + return cnt; + } + // Resets the iterator void reset() noexcept { index_ = 0; } private: nostd::string_view str_; - const char member_separator_; - const char key_value_separator_; + KeyValueStringTokenizerOptions opts_; size_t index_; }; diff --git a/api/include/opentelemetry/trace/trace_state.h b/api/include/opentelemetry/trace/trace_state.h index c3f72e6890..ebcf686a25 100644 --- a/api/include/opentelemetry/trace/trace_state.h +++ b/api/include/opentelemetry/trace/trace_state.h @@ -67,24 +67,23 @@ class TraceState static nostd::shared_ptr FromHeader(nostd::string_view header) { - size_t cnt = 0; - common::KeyValueStringIterator kv_str_itr(header); + common::KeyValueStringTokenizer kv_str_tokenizer(header); + size_t cnt = kv_str_tokenizer.NumTokens(); // upper bound on number of kv pairs + if (cnt > kMaxKeyValuePairs) + { + cnt = kMaxKeyValuePairs; + } + + nostd::shared_ptr ts(new TraceState(cnt)); bool kv_valid; nostd::string_view key, value; - while (kv_str_itr.next(kv_valid, key, value) && cnt < kMaxKeyValuePairs) + while (kv_str_tokenizer.next(kv_valid, key, value) && ts->kv_properties_->Size() < cnt) { if (kv_valid == false) { return GetDefault(); } - ++cnt; - } - - nostd::shared_ptr ts(new TraceState(cnt)); - kv_str_itr.reset(); - while (kv_str_itr.next(kv_valid, key, value) && ts->kv_properties_->Size() < cnt) - { if (!IsValidKey(key) || !IsValidValue(value)) { // invalid header. return empty TraceState diff --git a/api/test/common/CMakeLists.txt b/api/test/common/CMakeLists.txt new file mode 100644 index 0000000000..f61152cb66 --- /dev/null +++ b/api/test/common/CMakeLists.txt @@ -0,0 +1,16 @@ +include(GoogleTest) + +foreach(testname kv_properties_test string_util_test) + add_executable(${testname} "${testname}.cc") + target_link_libraries( + ${testname} ${GTEST_BOTH_LIBRARIES} ${CORE_RUNTIME_LIBS} + ${CMAKE_THREAD_LIBS_INIT} opentelemetry_api) + gtest_add_tests( + TARGET ${testname} + TEST_PREFIX common. + TEST_LIST ${testname}) +endforeach() + +add_executable(spinlock_benchmark spinlock_benchmark.cc) +target_link_libraries(spinlock_benchmark benchmark::benchmark + ${CMAKE_THREAD_LIBS_INIT} opentelemetry_api) diff --git a/api/test/common/kv_properties_test.cc b/api/test/common/kv_properties_test.cc index ddf4fde1bc..4a9f1b01df 100644 --- a/api/test/common/kv_properties_test.cc +++ b/api/test/common/kv_properties_test.cc @@ -67,66 +67,114 @@ TEST(EntryTest, SetValue) EXPECT_EQ(new_val, e.GetValue()); } -// ------------------------- KeyValueStringIterator tests --------------------------------- +// ------------------------- KeyValueStringTokenizer tests --------------------------------- -using opentelemetry::common::KeyValueStringIterator; +using opentelemetry::common::KeyValueStringTokenizer; +using opentelemetry::common::KeyValueStringTokenizerOptions; -TEST(KVStringIter, SinglePair) +TEST(KVStringTokenizer, SinglePair) { bool valid_kv; nostd::string_view key, value; opentelemetry::nostd::string_view str = "k1=v1"; - KeyValueStringIterator itr(str, ',', '='); - EXPECT_TRUE(itr.next(valid_kv, key, value)); + KeyValueStringTokenizerOptions opts; + KeyValueStringTokenizer tk(str, opts); + EXPECT_TRUE(tk.next(valid_kv, key, value)); EXPECT_TRUE(valid_kv); EXPECT_EQ(key, "k1"); EXPECT_EQ(value, "v1"); - EXPECT_FALSE(itr.next(valid_kv, key, value)); + EXPECT_FALSE(tk.next(valid_kv, key, value)); } -TEST(KVStringIter, ValidPairsWithEmptyEntries) +TEST(KVStringTokenizer, AcceptEmptyEntries) +{ + bool valid_kv; + nostd::string_view key, value; + opentelemetry::nostd::string_view str = ":k1=v1::k2=v2: "; + KeyValueStringTokenizerOptions opts; + opts.member_separator = ':'; + opts.ignore_empty_members = false; + + KeyValueStringTokenizer tk(str, opts); + EXPECT_TRUE(tk.next(valid_kv, key, value)); // empty pair + EXPECT_TRUE(tk.next(valid_kv, key, value)); + EXPECT_TRUE(valid_kv); + EXPECT_EQ(key, "k1"); + EXPECT_EQ(value, "v1"); + EXPECT_TRUE(tk.next(valid_kv, key, value)); // empty pair + EXPECT_EQ(key, ""); + EXPECT_EQ(value, ""); + EXPECT_TRUE(tk.next(valid_kv, key, value)); + EXPECT_TRUE(tk.next(valid_kv, key, value)); // empty pair + EXPECT_FALSE(tk.next(valid_kv, key, value)); +} + +TEST(KVStringTokenizer, ValidPairsWithEmptyEntries) { opentelemetry::nostd::string_view str = "k1:v1===k2:v2=="; bool valid_kv; nostd::string_view key, value; - KeyValueStringIterator itr(str, '=', ':'); - EXPECT_TRUE(itr.next(valid_kv, key, value)); + KeyValueStringTokenizerOptions opts; + opts.member_separator = '='; + opts.key_value_separator = ':'; + + KeyValueStringTokenizer tk(str, opts); + EXPECT_TRUE(tk.next(valid_kv, key, value)); EXPECT_TRUE(valid_kv); EXPECT_EQ(key, "k1"); EXPECT_EQ(value, "v1"); - EXPECT_TRUE(itr.next(valid_kv, key, value)); + EXPECT_TRUE(tk.next(valid_kv, key, value)); EXPECT_TRUE(valid_kv); EXPECT_EQ(key, "k2"); EXPECT_EQ(value, "v2"); - EXPECT_FALSE(itr.next(valid_kv, key, value)); + EXPECT_FALSE(tk.next(valid_kv, key, value)); } -TEST(KVStringIter, InvalidPairs) +TEST(KVStringTokenizer, InvalidPairs) { opentelemetry::nostd::string_view str = "k1=v1,invalid ,, k2=v2 ,invalid"; - KeyValueStringIterator itr(str); + KeyValueStringTokenizer tk(str); bool valid_kv; nostd::string_view key, value; - EXPECT_TRUE(itr.next(valid_kv, key, value)); + EXPECT_TRUE(tk.next(valid_kv, key, value)); EXPECT_TRUE(valid_kv); EXPECT_EQ(key, "k1"); EXPECT_EQ(value, "v1"); - EXPECT_TRUE(itr.next(valid_kv, key, value)); + EXPECT_TRUE(tk.next(valid_kv, key, value)); EXPECT_FALSE(valid_kv); - EXPECT_TRUE(itr.next(valid_kv, key, value)); + EXPECT_TRUE(tk.next(valid_kv, key, value)); EXPECT_TRUE(valid_kv); EXPECT_EQ(key, "k2"); EXPECT_EQ(value, "v2"); - EXPECT_TRUE(itr.next(valid_kv, key, value)); + EXPECT_TRUE(tk.next(valid_kv, key, value)); EXPECT_FALSE(valid_kv); - EXPECT_FALSE(itr.next(valid_kv, key, value)); + EXPECT_FALSE(tk.next(valid_kv, key, value)); +} + +TEST(KVStringTokenizer, NumTokens) +{ + struct + { + const char *input; + size_t expected; + } testcases[] = {{"k1=v1", 1}, + {" ", 1}, + {"k1=v1,k2=v2,k3=v3", 3}, + {"k1=v1,", 1}, + {"k1=v1,k2=v2,invalidmember", 3}, + {"", 0}}; + for (auto &testcase : testcases) + { + KeyValueStringTokenizer tk(testcase.input); + EXPECT_EQ(tk.NumTokens(), testcase.expected); + } } //------------------------- KeyValueProperties tests --------------------------------- From dbd5002dae4491a53f84785276274963c5eb030d Mon Sep 17 00:00:00 2001 From: ndaliya Date: Thu, 1 Apr 2021 19:56:55 +0530 Subject: [PATCH 3/5] Updating cmakelists file --- api/test/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/api/test/CMakeLists.txt b/api/test/CMakeLists.txt index 05ed4f5720..5dfac29e4c 100644 --- a/api/test/CMakeLists.txt +++ b/api/test/CMakeLists.txt @@ -5,3 +5,4 @@ add_subdirectory(nostd) add_subdirectory(trace) add_subdirectory(metrics) add_subdirectory(logs) +add_subdirectory(common) From ae927e66ffa11d46ea7a8d5742afc9b53d1514aa Mon Sep 17 00:00:00 2001 From: ndaliya Date: Fri, 2 Apr 2021 23:07:46 +0530 Subject: [PATCH 4/5] Updating string_view to string conversion --- api/include/opentelemetry/common/kv_properties.h | 3 ++- api/include/opentelemetry/trace/trace_state.h | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/api/include/opentelemetry/common/kv_properties.h b/api/include/opentelemetry/common/kv_properties.h index 9dfd0d4e00..2124cd1528 100644 --- a/api/include/opentelemetry/common/kv_properties.h +++ b/api/include/opentelemetry/common/kv_properties.h @@ -256,7 +256,8 @@ class KeyValueProperties auto &entry = (entries_.get())[i]; if (entry.GetKey() == key) { - value = std::string(entry.GetValue()); + const auto &entry_value = entry.GetValue(); + value = std::string(entry_value.data(), entry_value.size()); return true; } } diff --git a/api/include/opentelemetry/trace/trace_state.h b/api/include/opentelemetry/trace/trace_state.h index ebcf686a25..915a71e832 100644 --- a/api/include/opentelemetry/trace/trace_state.h +++ b/api/include/opentelemetry/trace/trace_state.h @@ -114,9 +114,9 @@ class TraceState { first = false; } - header_s.append(std::string(key)); + header_s.append(std::string(key.data(), key.size())); header_s.append(1, kKeyValueSeparator); - header_s.append(std::string(value)); + header_s.append(std::string(value.data(), value.size())); return true; }); return header_s; @@ -263,7 +263,7 @@ class TraceState static std::regex reg_key("^[a-z0-9][a-z0-9*_\\-/]{0,255}$"); static std::regex reg_key_multitenant( "^[a-z0-9][a-z0-9*_\\-/]{0,240}(@)[a-z0-9][a-z0-9*_\\-/]{0,13}$"); - std::string key_s(key); + std::string key_s(key.data(), key.size()); if (std::regex_match(key_s, reg_key) || std::regex_match(key_s, reg_key_multitenant)) { return true; @@ -277,7 +277,7 @@ class TraceState static std::regex reg_value( "^[\\x20-\\x2B\\x2D-\\x3C\\x3E-\\x7E]{0,255}[\\x21-\\x2B\\x2D-\\x3C\\x3E-\\x7E]$"); // Need to benchmark without regex, as a string object is created here. - return std::regex_match(std::string(value), reg_value); + return std::regex_match(std::string(value.data(), value.size()), reg_value); } static bool IsValidKeyNonRegEx(nostd::string_view key) From c93764d5572718e118e13e38a7026e2b5bea216a Mon Sep 17 00:00:00 2001 From: ndaliya Date: Mon, 5 Apr 2021 15:15:37 +0530 Subject: [PATCH 5/5] Updating namspaces for uniformity --- api/test/trace/trace_state_test.cc | 32 +++++++++++++++--------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/api/test/trace/trace_state_test.cc b/api/test/trace/trace_state_test.cc index 24c6eb4f78..3435d43e50 100644 --- a/api/test/trace/trace_state_test.cc +++ b/api/test/trace/trace_state_test.cc @@ -40,7 +40,7 @@ std::string create_ts_return_header(std::string header) std::string header_with_max_members() { std::string header = ""; - auto max_members = opentelemetry::trace::TraceState::kMaxKeyValuePairs; + auto max_members = TraceState::kMaxKeyValuePairs; for (int i = 0; i < max_members; i++) { std::string key = "key" + std::to_string(i); @@ -146,12 +146,12 @@ TEST(TraceStateTest, Empty) TEST(TraceStateTest, GetAllEntries) { - std::string trace_state_header = "k1=v1,k2=v2,k3=v3"; - auto ts1 = TraceState::FromHeader(trace_state_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; + std::string trace_state_header = "k1=v1,k2=v2,k3=v3"; + auto ts1 = TraceState::FromHeader(trace_state_header); + const int kNumPairs = 3; + nostd::string_view keys[kNumPairs] = {"k1", "k2", "k3"}; + nostd::string_view values[kNumPairs] = {"v1", "v2", "v3"}; + size_t index = 0; ts1->GetAllEntries([&keys, &values, &index](nostd::string_view key, nostd::string_view value) { EXPECT_EQ(key, keys[index]); EXPECT_EQ(value, values[index]); @@ -182,15 +182,15 @@ TEST(TraceStateTest, IsValidValue) // Tests that keys and values don't depend on null terminators TEST(TraceStateTest, MemorySafe) { - std::string trace_state_header = ""; - auto ts = TraceState::FromHeader(trace_state_header); - const int kNumPairs = 3; - opentelemetry::nostd::string_view key_string = "test_key_1test_key_2test_key_3"; - opentelemetry::nostd::string_view val_string = "test_val_1test_val_2test_val_3"; - opentelemetry::nostd::string_view keys[kNumPairs] = { - key_string.substr(0, 10), key_string.substr(10, 10), key_string.substr(20, 10)}; - opentelemetry::nostd::string_view values[kNumPairs] = { - val_string.substr(0, 10), val_string.substr(10, 10), val_string.substr(20, 10)}; + std::string trace_state_header = ""; + auto ts = TraceState::FromHeader(trace_state_header); + const int kNumPairs = 3; + nostd::string_view key_string = "test_key_1test_key_2test_key_3"; + nostd::string_view val_string = "test_val_1test_val_2test_val_3"; + nostd::string_view keys[kNumPairs] = {key_string.substr(0, 10), key_string.substr(10, 10), + key_string.substr(20, 10)}; + nostd::string_view values[kNumPairs] = {val_string.substr(0, 10), val_string.substr(10, 10), + val_string.substr(20, 10)}; auto ts1 = ts->Set(keys[2], values[2]); auto ts2 = ts1->Set(keys[1], values[1]);