diff options
-rw-r--r-- | absl/strings/BUILD.bazel | 58 | ||||
-rw-r--r-- | absl/strings/CMakeLists.txt | 54 | ||||
-rw-r--r-- | absl/strings/cord.cc | 55 | ||||
-rw-r--r-- | absl/strings/cord.h | 35 | ||||
-rw-r--r-- | absl/strings/cord_test.cc | 2 | ||||
-rw-r--r-- | absl/strings/cord_test_helpers.h | 1 | ||||
-rw-r--r-- | absl/strings/cordz_test.cc | 92 | ||||
-rw-r--r-- | absl/strings/cordz_test_helpers.h | 129 | ||||
-rw-r--r-- | absl/strings/internal/cordz_info_test.cc | 20 | ||||
-rw-r--r-- | absl/strings/internal/cordz_sample_token_test.cc | 33 | ||||
-rw-r--r-- | absl/strings/internal/cordz_update_scope_test.cc | 21 | ||||
-rw-r--r-- | absl/time/duration_test.cc | 4 | ||||
-rw-r--r-- | absl/time/time.h | 2 |
13 files changed, 422 insertions, 84 deletions
diff --git a/absl/strings/BUILD.bazel b/absl/strings/BUILD.bazel index 874dd390..5d4ad7e3 100644 --- a/absl/strings/BUILD.bazel +++ b/absl/strings/BUILD.bazel @@ -399,6 +399,7 @@ cc_test( deps = [ ":cord_internal", ":cordz_info", + ":cordz_test_helpers", ":cordz_update_scope", ":cordz_update_tracker", "//absl/base:config", @@ -447,8 +448,8 @@ cc_test( "internal/cordz_functions_test.cc", ], deps = [ - ":cord_test_helpers", ":cordz_functions", + ":cordz_test_helpers", "//absl/base:config", "@com_google_googletest//:gtest_main", ], @@ -482,6 +483,7 @@ cc_test( ":cordz_handle", ":cordz_info", ":cordz_statistics", + ":cordz_test_helpers", ":cordz_update_tracker", ":strings", "//absl/base:config", @@ -502,6 +504,7 @@ cc_test( ":cordz_handle", ":cordz_info", ":cordz_sample_token", + ":cordz_test_helpers", "//absl/base:config", "//absl/memory", "//absl/random", @@ -521,6 +524,25 @@ cc_library( copts = ABSL_DEFAULT_COPTS, deps = [ ":cord", + ":cord_internal", + ], +) + +cc_library( + name = "cordz_test_helpers", + testonly = 1, + hdrs = ["cordz_test_helpers.h"], + copts = ABSL_DEFAULT_COPTS, + deps = [ + ":cord", + ":cord_internal", + ":cordz_info", + ":cordz_sample_token", + ":cordz_statistics", + ":cordz_update_tracker", + "//absl/base:config", + "//absl/base:core_headers", + "@com_google_googletest//:gtest", ], ) @@ -533,6 +555,8 @@ cc_test( deps = [ ":cord", ":cord_test_helpers", + ":cordz_functions", + ":cordz_test_helpers", ":str_format", ":strings", "//absl/base", @@ -546,6 +570,38 @@ cc_test( ) cc_test( + name = "cordz_test", + size = "medium", + srcs = ["cordz_test.cc"], + copts = ABSL_TEST_COPTS, + tags = [ + "benchmark", + "no_test_android_arm", + "no_test_android_arm64", + "no_test_android_x86", + "no_test_darwin_x86_64", + "no_test_ios_x86_64", + "no_test_loonix", + "no_test_msvc_x64", + ], + visibility = ["//visibility:private"], + deps = [ + ":cord", + ":cordz_functions", + ":cordz_info", + ":cordz_sample_token", + ":cordz_statistics", + ":cordz_test_helpers", + ":cordz_update_tracker", + ":strings", + "//absl/base:config", + "//absl/base:core_headers", + "//absl/base:raw_logging_internal", + "@com_google_googletest//:gtest_main", + ], +) + +cc_test( name = "cord_ring_test", size = "medium", srcs = ["cord_ring_test.cc"], diff --git a/absl/strings/CMakeLists.txt b/absl/strings/CMakeLists.txt index f48584e0..2a8e3df2 100644 --- a/absl/strings/CMakeLists.txt +++ b/absl/strings/CMakeLists.txt @@ -626,8 +626,8 @@ absl_cc_test( "internal/cordz_functions_test.cc" DEPS absl::config - absl::cord_test_helpers absl::cordz_functions + absl::cordz_test_helpers gmock_main ) @@ -667,8 +667,8 @@ absl_cc_test( "internal/cordz_handle_test.cc" DEPS absl::config - absl::cord_test_helpers absl::cordz_handle + absl::cordz_test_helpers absl::memory absl::random_random absl::random_distributions @@ -707,10 +707,11 @@ absl_cc_test( DEPS absl::config absl::cord_internal - absl::cord_test_helpers + absl::cordz_test_helpers absl::cordz_handle absl::cordz_info absl::cordz_statistics + absl::cordz_test_helpers absl::cordz_update_tracker absl::span absl::stacktrace @@ -747,6 +748,7 @@ absl_cc_test( absl::cordz_info absl::cordz_info absl::cordz_sample_token + absl::cordz_test_helpers absl::memory absl::random_random absl::synchronization @@ -781,6 +783,7 @@ absl_cc_test( absl::config absl::cord_internal absl::cordz_info + absl::cordz_test_helpers absl::cordz_update_scope absl::cordz_update_tracker absl::core_headers @@ -825,6 +828,26 @@ absl_cc_library( ${ABSL_TEST_COPTS} DEPS absl::cord + absl::cord_internal + TESTONLY +) + +absl_cc_library( + NAME + cordz_test_helpers + HDRS + "cordz_test_helpers.h" + COPTS + ${ABSL_TEST_COPTS} + DEPS + absl::config + absl::cord + absl::cord_internal + absl::cordz_info + absl::cordz_sample_token + absl::cordz_statistics + absl::cordz_update_tracker + absl::core_headers TESTONLY ) @@ -841,6 +864,8 @@ absl_cc_test( absl::strings absl::base absl::config + absl::cord_test_helpers + absl::cordz_test_helpers absl::core_headers absl::endian absl::raw_logging_internal @@ -879,3 +904,26 @@ absl_cc_test( absl::strings gmock_main ) + +absl_cc_test( + NAME + cordz_test + SRCS + "cordz_test.cc" + COPTS + ${ABSL_TEST_COPTS} + DEPS + absl::cord + absl::cordz_test_helpers + absl::cordz_functions + absl::cordz_info + absl::cordz_sample_token + absl::cordz_statistics + absl::cordz_update_tracker + absl::base + absl::config + absl::core_headers + absl::raw_logging_internal + absl::strings + gmock_main +) diff --git a/absl/strings/cord.cc b/absl/strings/cord.cc index 44e4d464..768106d4 100644 --- a/absl/strings/cord.cc +++ b/absl/strings/cord.cc @@ -342,14 +342,37 @@ static CordRepRing* ForceRing(CordRep* rep, size_t extra) { return (rep->tag == RING) ? rep->ring() : CordRepRing::Create(rep, extra); } -void Cord::InlineRep::AppendTree(CordRep* tree) { +void Cord::InlineRep::AppendTreeToInlined(CordRep* tree, + MethodIdentifier method) { + assert(!is_tree()); + if (!data_.is_empty()) { + CordRepFlat* flat = MakeFlat(data_); + if (cord_ring_enabled()) { + tree = CordRepRing::Append(CordRepRing::Create(flat, 1), tree); + } else { + tree = Concat(flat, tree); + } + } + EmplaceTree(tree, method); +} + +void Cord::InlineRep::AppendTreeToTree(CordRep* tree, MethodIdentifier method) { + assert(is_tree()); + const CordzUpdateScope scope(data_.cordz_info(), method); + if (cord_ring_enabled()) { + tree = CordRepRing::Append(ForceRing(data_.as_tree(), 1), tree); + } else { + tree = Concat(data_.as_tree(), tree); + } + SetTree(tree, scope); +} + +void Cord::InlineRep::AppendTree(CordRep* tree, MethodIdentifier method) { if (tree == nullptr) return; - if (data_.is_empty()) { - set_tree(tree); - } else if (cord_ring_enabled()) { - set_tree(CordRepRing::Append(ForceRing(force_tree(0), 1), tree)); + if (data_.is_tree()) { + AppendTreeToTree(tree, method); } else { - set_tree(Concat(force_tree(0), tree)); + AppendTreeToInlined(tree, method); } } @@ -533,9 +556,8 @@ Cord::Cord(absl::string_view src) : contents_(InlineData::kDefaultInit) { if (n <= InlineRep::kMaxInline) { contents_.set_data(src.data(), n, true); } else { - contents_.data_.make_tree(NewTree(src.data(), n, 0)); - CordzInfo::MaybeTrackCord(contents_.data_, - CordzUpdateTracker::kConstructorString); + CordRep* rep = NewTree(src.data(), n, 0); + contents_.EmplaceTree(rep, CordzUpdateTracker::kConstructorString); } } @@ -713,9 +735,15 @@ inline CordRep* Cord::TakeRep() && { template <typename C> inline void Cord::AppendImpl(C&& src) { if (empty()) { - // In case of an empty destination avoid allocating a new node, do not copy - // data. - *this = std::forward<C>(src); + // Since destination is empty, we can avoid allocating a node, + if (src.contents_.is_tree()) { + // by taking the tree directly + CordRep* rep = std::forward<C>(src).TakeRep(); + contents_.EmplaceTree(rep, CordzUpdateTracker::kAppendCord); + } else { + // or copying over inline data + contents_.data_ = src.contents_.data_; + } return; } @@ -746,7 +774,8 @@ inline void Cord::AppendImpl(C&& src) { } // Guaranteed to be a tree (kMaxBytesToCopy > kInlinedSize) - contents_.AppendTree(std::forward<C>(src).TakeRep()); + CordRep* rep = std::forward<C>(src).TakeRep(); + contents_.AppendTree(rep, CordzUpdateTracker::kAppendCord); } void Cord::Append(const Cord& src) { AppendImpl(src); } diff --git a/absl/strings/cord.h b/absl/strings/cord.h index bca20981..dd6c3bca 100644 --- a/absl/strings/cord.h +++ b/absl/strings/cord.h @@ -670,6 +670,7 @@ class Cord { explicit constexpr Cord(strings_internal::StringConstant<T>); private: + using CordRep = absl::cord_internal::CordRep; using CordzInfo = cord_internal::CordzInfo; using CordzUpdateScope = cord_internal::CordzUpdateScope; using CordzUpdateTracker = cord_internal::CordzUpdateTracker; @@ -680,6 +681,8 @@ class Cord { friend bool operator==(const Cord& lhs, const Cord& rhs); friend bool operator==(const Cord& lhs, absl::string_view rhs); + friend const CordzInfo* GetCordzInfoForTesting(const Cord& cord); + // Calls the provided function once for each cord chunk, in order. Unlike // Chunks(), this API will not allocate memory. void ForEachChunk(absl::FunctionRef<void(absl::string_view)>) const; @@ -730,7 +733,23 @@ class Cord { void remove_prefix(size_t n); // REQUIRES: holding data void AppendArray(const char* src_data, size_t src_size); absl::string_view FindFlatStartPiece() const; - void AppendTree(absl::cord_internal::CordRep* tree); + + // Sets the tree value for this instance. `rep` must not be null. + // Requires the current instance to hold a tree, and a lock to be held on + // any CordzInfo referenced by this instance. The latter is enforced through + // the CordzUpdateScope argument. If the current instance is sampled, then + // the CordzInfo instance is updated to reference the new `rep` value. + void SetTree(CordRep* rep, const CordzUpdateScope& scope); + + // Sets the tree value for this instance, and randomly samples this cord. + // This function disregards existing contents in `data_`, and should be + // called when a Cord is 'promoted' from an 'uninitialized' or 'inlined' + // value to a non-inlined (tree / ring) value. + void EmplaceTree(CordRep* rep, MethodIdentifier method); + + void AppendTreeToInlined(CordRep* tree, MethodIdentifier method); + void AppendTreeToTree(CordRep* tree, MethodIdentifier method); + void AppendTree(CordRep* tree, MethodIdentifier method); void PrependTree(absl::cord_internal::CordRep* tree); void GetAppendRegion(char** region, size_t* size, size_t max_length); void GetAppendRegion(char** region, size_t* size); @@ -1022,6 +1041,20 @@ inline size_t Cord::InlineRep::size() const { return is_tree() ? as_tree()->length : inline_size(); } +inline void Cord::InlineRep::EmplaceTree(CordRep* rep, + MethodIdentifier method) { + data_.make_tree(rep); + CordzInfo::MaybeTrackCord(data_, method); +} + +inline void Cord::InlineRep::SetTree(CordRep* rep, + const CordzUpdateScope& scope) { + assert(rep); + assert(data_.is_tree()); + data_.set_tree(rep); + scope.SetCordRep(rep); +} + inline void Cord::InlineRep::set_tree(absl::cord_internal::CordRep* rep) { if (rep == nullptr) { if (ABSL_PREDICT_FALSE(is_profiled())) { diff --git a/absl/strings/cord_test.cc b/absl/strings/cord_test.cc index 710a1b40..74a90863 100644 --- a/absl/strings/cord_test.cc +++ b/absl/strings/cord_test.cc @@ -35,6 +35,7 @@ #include "absl/base/macros.h" #include "absl/container/fixed_array.h" #include "absl/strings/cord_test_helpers.h" +#include "absl/strings/cordz_test_helpers.h" #include "absl/strings/str_cat.h" #include "absl/strings/str_format.h" #include "absl/strings/string_view.h" @@ -239,7 +240,6 @@ TEST(GigabyteCord, FromExternal) { // caused crashes in production. We grow exponentially so that the code will // execute in a reasonable amount of time. absl::Cord c; - ABSL_RAW_LOG(INFO, "Made a Cord with %zu bytes!", c.size()); c.Append(from); while (c.size() < max_size) { c.Append(c); diff --git a/absl/strings/cord_test_helpers.h b/absl/strings/cord_test_helpers.h index f1036e3b..3815df81 100644 --- a/absl/strings/cord_test_helpers.h +++ b/absl/strings/cord_test_helpers.h @@ -18,6 +18,7 @@ #define ABSL_STRINGS_CORD_TEST_HELPERS_H_ #include "absl/strings/cord.h" +#include "absl/strings/internal/cord_internal.h" namespace absl { ABSL_NAMESPACE_BEGIN diff --git a/absl/strings/cordz_test.cc b/absl/strings/cordz_test.cc new file mode 100644 index 00000000..6e8deefd --- /dev/null +++ b/absl/strings/cordz_test.cc @@ -0,0 +1,92 @@ +// Copyright 2021 The Abseil 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 +// +// https://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 <string> + +#include "gmock/gmock.h" +#include "gtest/gtest.h" +#include "absl/base/config.h" +#include "absl/base/internal/raw_logging.h" +#include "absl/base/macros.h" +#include "absl/strings/cord.h" +#include "absl/strings/cordz_test_helpers.h" +#include "absl/strings/internal/cordz_functions.h" +#include "absl/strings/internal/cordz_info.h" +#include "absl/strings/internal/cordz_sample_token.h" +#include "absl/strings/internal/cordz_statistics.h" +#include "absl/strings/internal/cordz_update_tracker.h" +#include "absl/strings/str_cat.h" +#include "absl/strings/string_view.h" + +#ifdef ABSL_INTERNAL_CORDZ_ENABLED + +namespace absl { +ABSL_NAMESPACE_BEGIN + +using cord_internal::CordzInfo; +using cord_internal::CordzSampleToken; +using cord_internal::CordzStatistics; +using cord_internal::CordzUpdateTracker; +using Method = CordzUpdateTracker::MethodIdentifier; + +namespace { + +std::string MakeString(int length) { + std::string s(length, '.'); + for (int i = 4; i < length; i += 2) { + s[i] = '\b'; + } + return s; +} + +TEST(CordzTest, ConstructSmallStringView) { + CordzSamplingIntervalHelper sample_every(1); + Cord cord(absl::string_view(MakeString(50))); + EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kConstructorString)); +} + +TEST(CordzTest, ConstructLargeStringView) { + CordzSamplingIntervalHelper sample_every(1); + Cord cord(absl::string_view(MakeString(5000))); + EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kConstructorString)); +} + +TEST(CordzTest, CopyConstruct) { + CordzSamplingIntervalHelper sample_every(1); + Cord src = UnsampledCord(MakeString(5000)); + Cord cord(src); + EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kConstructorCord)); +} + +TEST(CordzTest, AppendLargeCordToEmpty) { + CordzSamplingIntervalHelper sample_every(1); + Cord cord; + Cord src = UnsampledCord(MakeString(5000)); + cord.Append(src); + EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kAppendCord)); +} + +TEST(CordzTest, MoveAppendLargeCordToEmpty) { + CordzSamplingIntervalHelper sample_every(1); + Cord cord; + cord.Append(UnsampledCord(MakeString(5000))); + EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kAppendCord)); +} + +} // namespace + +ABSL_NAMESPACE_END +} // namespace absl + +#endif // ABSL_INTERNAL_CORDZ_ENABLED diff --git a/absl/strings/cordz_test_helpers.h b/absl/strings/cordz_test_helpers.h new file mode 100644 index 00000000..453c2f9d --- /dev/null +++ b/absl/strings/cordz_test_helpers.h @@ -0,0 +1,129 @@ +// Copyright 2021 The Abseil 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 +// +// https://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. + +#ifndef ABSL_STRINGS_CORDZ_TEST_HELPERS_H_ +#define ABSL_STRINGS_CORDZ_TEST_HELPERS_H_ + +#include "gmock/gmock.h" +#include "gtest/gtest.h" +#include "absl/base/config.h" +#include "absl/base/macros.h" +#include "absl/strings/cord.h" +#include "absl/strings/internal/cord_internal.h" +#include "absl/strings/internal/cordz_info.h" +#include "absl/strings/internal/cordz_sample_token.h" +#include "absl/strings/internal/cordz_statistics.h" +#include "absl/strings/internal/cordz_update_tracker.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN + +// Returns the CordzInfo for the cord, or nullptr if the cord is not sampled. +inline const cord_internal::CordzInfo* GetCordzInfoForTesting( + const Cord& cord) { + return cord.contents_.cordz_info(); +} + +// Returns true if the provided cordz_info is in the list of sampled cords. +inline bool CordzInfoIsListed(const cord_internal::CordzInfo* cordz_info, + cord_internal::CordzSampleToken token = {}) { + for (const cord_internal::CordzInfo& info : token) { + if (cordz_info == &info) return true; + } + return false; +} + +// Matcher on Cord that verifies all of: +// - the cord is sampled +// - the CordzInfo of the cord is listed / discoverable. +// - the reported CordzStatistics match the cord's actual properties +// - the cord has an (initial) UpdateTracker count of 1 for `method` +MATCHER_P(HasValidCordzInfoOf, method, "CordzInfo matches cord") { + const cord_internal::CordzInfo* cord_info = GetCordzInfoForTesting(arg); + if (cord_info == nullptr) { + *result_listener << "cord is not sampled"; + return false; + } + if (!CordzInfoIsListed(cord_info)) { + *result_listener << "cord is sampled, but not listed"; + return false; + } + cord_internal::CordzStatistics stat = cord_info->GetCordzStatistics(); + if (stat.size != arg.size()) { + *result_listener << "cordz size " << stat.size + << " does not match cord size " << arg.size(); + return false; + } + if (stat.update_tracker.Value(method) != 1) { + *result_listener << "Expected method count 1 for " << method << ", found " + << stat.update_tracker.Value(method); + return false; + } + return true; +} + +// Cordz will only update with a new rate once the previously scheduled event +// has fired. When we disable Cordz, a long delay takes place where we won't +// consider profiling new Cords. CordzSampleIntervalHelper will burn through +// that interval and allow for testing that assumes that the average sampling +// interval is a particular value. +class CordzSamplingIntervalHelper { + public: + explicit CordzSamplingIntervalHelper(int32_t interval) + : orig_mean_interval_(absl::cord_internal::get_cordz_mean_interval()) { + absl::cord_internal::set_cordz_mean_interval(interval); + absl::cord_internal::cordz_set_next_sample_for_testing(interval); + } + + ~CordzSamplingIntervalHelper() { + absl::cord_internal::set_cordz_mean_interval(orig_mean_interval_); + absl::cord_internal::cordz_set_next_sample_for_testing(orig_mean_interval_); + } + + private: + int32_t orig_mean_interval_; +}; + +// Wrapper struct managing a small CordRep `rep` +struct TestCordRep { + cord_internal::CordRepFlat* rep; + + TestCordRep() { + rep = cord_internal::CordRepFlat::New(100); + rep->length = 100; + memset(rep->Data(), 1, 100); + } + ~TestCordRep() { cord_internal::CordRep::Unref(rep); } +}; + +// Wrapper struct managing a small CordRep `rep`, and +// an InlineData `data` initialized with that CordRep. +struct TestCordData { + TestCordRep rep; + cord_internal::InlineData data{rep.rep}; +}; + +// Creates a Cord that is not sampled +template <typename... Args> +Cord UnsampledCord(Args... args) { + CordzSamplingIntervalHelper never(9999); + Cord cord(std::forward<Args>(args)...); + ABSL_ASSERT(GetCordzInfoForTesting(cord) == nullptr); + return cord; +} + +ABSL_NAMESPACE_END +} // namespace absl + +#endif // ABSL_STRINGS_CORDZ_TEST_HELPERS_H_ diff --git a/absl/strings/internal/cordz_info_test.cc b/absl/strings/internal/cordz_info_test.cc index 89e5fae5..76aa20b0 100644 --- a/absl/strings/internal/cordz_info_test.cc +++ b/absl/strings/internal/cordz_info_test.cc @@ -21,8 +21,10 @@ #include "absl/base/config.h" #include "absl/debugging/stacktrace.h" #include "absl/debugging/symbolize.h" +#include "absl/strings/cordz_test_helpers.h" #include "absl/strings/internal/cord_rep_flat.h" #include "absl/strings/internal/cordz_handle.h" +#include "absl/strings/internal/cordz_statistics.h" #include "absl/strings/internal/cordz_update_tracker.h" #include "absl/strings/str_cat.h" #include "absl/types/span.h" @@ -37,24 +39,6 @@ using ::testing::Eq; using ::testing::HasSubstr; using ::testing::Ne; -struct TestCordRep { - CordRepFlat* rep; - - TestCordRep() { - rep = CordRepFlat::New(100); - rep->length = 100; - memset(rep->Data(), 1, 100); - } - ~TestCordRep() { CordRepFlat::Delete(rep); } -}; - -struct TestCordData { - TestCordRep rep; - InlineData data; - - TestCordData() { data.make_tree(rep.rep); } -}; - // Used test values auto constexpr kUnknownMethod = CordzUpdateTracker::kUnknown; auto constexpr kTrackCordMethod = CordzUpdateTracker::kConstructorString; diff --git a/absl/strings/internal/cordz_sample_token_test.cc b/absl/strings/internal/cordz_sample_token_test.cc index 5fbfd01c..80f41ca1 100644 --- a/absl/strings/internal/cordz_sample_token_test.cc +++ b/absl/strings/internal/cordz_sample_token_test.cc @@ -22,6 +22,7 @@ #include "gtest/gtest.h" #include "absl/memory/memory.h" #include "absl/random/random.h" +#include "absl/strings/cordz_test_helpers.h" #include "absl/strings/internal/cord_rep_flat.h" #include "absl/strings/internal/cordz_handle.h" #include "absl/strings/internal/cordz_info.h" @@ -39,24 +40,6 @@ using ::testing::ElementsAre; using ::testing::Eq; using ::testing::Ne; -struct TestCordRep { - CordRepFlat* rep; - - TestCordRep() { - rep = CordRepFlat::New(100); - rep->length = 100; - memset(rep->Data(), 1, 100); - } - ~TestCordRep() { CordRepFlat::Delete(rep); } -}; - -struct TestCord { - TestCordRep rep; - InlineData data; - - TestCord() { data.make_tree(rep.rep); } -}; - // Used test values auto constexpr kTrackCordMethod = CordzUpdateTracker::kConstructorString; @@ -97,7 +80,7 @@ TEST(CordzSampleTokenTest, IteratorEmpty) { } TEST(CordzSampleTokenTest, Iterator) { - TestCord cord1, cord2, cord3; + TestCordData cord1, cord2, cord3; CordzInfo::TrackCord(cord1.data, kTrackCordMethod); CordzInfo* info1 = cord1.data.cordz_info(); CordzInfo::TrackCord(cord2.data, kTrackCordMethod); @@ -119,9 +102,9 @@ TEST(CordzSampleTokenTest, Iterator) { } TEST(CordzSampleTokenTest, IteratorEquality) { - TestCord cord1; - TestCord cord2; - TestCord cord3; + TestCordData cord1; + TestCordData cord2; + TestCordData cord3; CordzInfo::TrackCord(cord1.data, kTrackCordMethod); CordzInfo* info1 = cord1.data.cordz_info(); @@ -167,7 +150,7 @@ TEST(CordzSampleTokenTest, MultiThreaded) { for (int i = 0; i < kNumThreads; ++i) { pool.Schedule([&stop]() { absl::BitGen gen; - TestCord cords[kNumCords]; + TestCordData cords[kNumCords]; std::unique_ptr<CordzSampleToken> tokens[kNumTokens]; while (!stop.HasBeenNotified()) { @@ -179,7 +162,7 @@ TEST(CordzSampleTokenTest, MultiThreaded) { // 5) Sample int index = absl::Uniform(gen, 0, kNumCords); if (absl::Bernoulli(gen, 0.5)) { - TestCord& cord = cords[index]; + TestCordData& cord = cords[index]; // Track/untrack. if (cord.data.is_profiled()) { // 1) Untrack @@ -208,7 +191,7 @@ TEST(CordzSampleTokenTest, MultiThreaded) { } } } - for (TestCord& cord : cords) { + for (TestCordData& cord : cords) { if (cord.data.is_profiled()) { CordzInfo::UntrackCord(cord.data.cordz_info()); } diff --git a/absl/strings/internal/cordz_update_scope_test.cc b/absl/strings/internal/cordz_update_scope_test.cc index 4bdc78d3..3d08c622 100644 --- a/absl/strings/internal/cordz_update_scope_test.cc +++ b/absl/strings/internal/cordz_update_scope_test.cc @@ -17,6 +17,7 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/base/config.h" +#include "absl/strings/cordz_test_helpers.h" #include "absl/strings/internal/cord_rep_flat.h" #include "absl/strings/internal/cordz_info.h" #include "absl/strings/internal/cordz_update_tracker.h" @@ -27,24 +28,6 @@ namespace cord_internal { namespace { -struct TestCordRep { - CordRepFlat* rep; - - TestCordRep() { - rep = CordRepFlat::New(100); - rep->length = 100; - memset(rep->Data(), 1, 100); - } - ~TestCordRep() { CordRepFlat::Delete(rep); } -}; - -struct TestCord { - TestCordRep rep; - InlineData data; - - TestCord() { data.make_tree(rep.rep); } -}; - // Used test values auto constexpr kTrackCordMethod = CordzUpdateTracker::kConstructorString; @@ -53,7 +36,7 @@ TEST(CordzUpdateScopeTest, ScopeNullptr) { } TEST(CordzUpdateScopeTest, ScopeSampledCord) { - TestCord cord; + TestCordData cord; CordzInfo::TrackCord(cord.data, kTrackCordMethod); CordzUpdateScope scope(cord.data.cordz_info(), kTrackCordMethod); cord.data.cordz_info()->SetCordRep(nullptr); diff --git a/absl/time/duration_test.cc b/absl/time/duration_test.cc index fb28fa98..a3617e74 100644 --- a/absl/time/duration_test.cc +++ b/absl/time/duration_test.cc @@ -1320,7 +1320,7 @@ TEST(Duration, SmallConversions) { EXPECT_EQ(absl::ZeroDuration(), absl::Seconds(0)); // TODO(bww): Is the next one OK? - EXPECT_EQ(absl::ZeroDuration(), absl::Seconds(0.124999999e-9)); + EXPECT_EQ(absl::ZeroDuration(), absl::Seconds(std::nextafter(0.125e-9, 0))); EXPECT_EQ(absl::Nanoseconds(1) / 4, absl::Seconds(0.125e-9)); EXPECT_EQ(absl::Nanoseconds(1) / 4, absl::Seconds(0.250e-9)); EXPECT_EQ(absl::Nanoseconds(1) / 2, absl::Seconds(0.375e-9)); @@ -1330,7 +1330,7 @@ TEST(Duration, SmallConversions) { EXPECT_EQ(absl::Nanoseconds(1), absl::Seconds(0.875e-9)); EXPECT_EQ(absl::Nanoseconds(1), absl::Seconds(1.000e-9)); - EXPECT_EQ(absl::ZeroDuration(), absl::Seconds(-0.124999999e-9)); + EXPECT_EQ(absl::ZeroDuration(), absl::Seconds(std::nextafter(-0.125e-9, 0))); EXPECT_EQ(-absl::Nanoseconds(1) / 4, absl::Seconds(-0.125e-9)); EXPECT_EQ(-absl::Nanoseconds(1) / 4, absl::Seconds(-0.250e-9)); EXPECT_EQ(-absl::Nanoseconds(1) / 2, absl::Seconds(-0.375e-9)); diff --git a/absl/time/time.h b/absl/time/time.h index 2df68581..48982df4 100644 --- a/absl/time/time.h +++ b/absl/time/time.h @@ -1352,7 +1352,7 @@ constexpr Duration MakeDuration(int64_t hi, int64_t lo) { inline Duration MakePosDoubleDuration(double n) { const int64_t int_secs = static_cast<int64_t>(n); const uint32_t ticks = static_cast<uint32_t>( - (n - static_cast<double>(int_secs)) * kTicksPerSecond + 0.5); + std::round((n - static_cast<double>(int_secs)) * kTicksPerSecond)); return ticks < kTicksPerSecond ? MakeDuration(int_secs, ticks) : MakeDuration(int_secs + 1, ticks - kTicksPerSecond); |