tvl-depot/absl/container/inlined_vector_test.cc

1812 lines
54 KiB
C++
Raw Normal View History

// Copyright 2019 The Abseil Authors.
2017-09-19 22:54:40 +02:00
//
// 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
2017-09-19 22:54:40 +02:00
//
// 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 "absl/container/inlined_vector.h"
#include <algorithm>
2017-09-19 22:54:40 +02:00
#include <forward_list>
#include <list>
#include <memory>
#include <scoped_allocator>
#include <sstream>
#include <stdexcept>
#include <string>
#include <vector>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "absl/base/attributes.h"
#include "absl/base/internal/exception_testing.h"
#include "absl/base/internal/raw_logging.h"
#include "absl/base/macros.h"
Export of internal Abseil changes -- 79913a12f0cad4baf948430315aabf53f03b6475 by Abseil Team <absl-team@google.com>: Don't inline (Un)LockSlow. PiperOrigin-RevId: 302502344 -- 6b340e80f0690655f24799c8de6707b3a95b8579 by Derek Mauro <dmauro@google.com>: Add hardening assertions to absl::optional's dereference operators PiperOrigin-RevId: 302492862 -- a9951bf4852d8c1aec472cb4b539830411270e4c by Derek Mauro <dmauro@google.com>: Correctly add hardware AES compiler flags under Linux X86-64 Fixes #643 PiperOrigin-RevId: 302490673 -- 314c3621ee4d57b6bc8d64338a1f1d48a69741d1 by Derek Mauro <dmauro@google.com>: Upgrade to hardening assertions in absl::Span::remove_prefix and absl::Span::remove_suffix PiperOrigin-RevId: 302481191 -- a142b8c6c62705c5f0d4fe3113150f0c0b7822b9 by Derek Mauro <dmauro@google.com>: Update docker containers to Bazel 2.2.0, GCC 9.3, and new Clang snapshot PiperOrigin-RevId: 302454042 -- afedeb70a2adc87010030c9ba6f06fe35ec26407 by Derek Mauro <dmauro@google.com>: Add hardening assertions for the preconditions of absl::FixedArray PiperOrigin-RevId: 302441767 -- 44442bfbc0a9a742df32f07cee86a47712efb8b4 by Derek Mauro <dmauro@google.com>: Fix new Clang warning about SpinLock doing operations on enums of different types PiperOrigin-RevId: 302430387 -- 69eaff7f97231779f696321c2ba8b88debf6dd9e by Derek Mauro <dmauro@google.com>: Convert precondition assertions to ABSL_HARDENING_ASSERT for absl::InlinedVector PiperOrigin-RevId: 302427894 -- 26b6db906a0942fd18583dc2cdd1bab32919d964 by Gennadiy Rozental <rogeeff@google.com>: Internal change PiperOrigin-RevId: 302425283 -- e62e81422979e922505d2cd9000e1de58123c088 by Derek Mauro <dmauro@google.com>: Add an option to build Abseil in hardened mode In hardened mode, the ABSL_HARDENING_ASSERT() macro is active even when NDEBUG is defined. This allows Abseil to perform runtime checks even in release mode. This should be used to implement things like bounds checks that could otherwise lead to security vulnerabilities. Use the new assertion in absl::string_view and absl::Span to test it. PiperOrigin-RevId: 302119187 GitOrigin-RevId: 79913a12f0cad4baf948430315aabf53f03b6475 Change-Id: I0cc3341fd333a1df313167bab72dc5a759c4a048
2020-03-23 21:16:18 +01:00
#include "absl/base/options.h"
Export of internal Abseil changes. -- 5f1cf6547231f1b1daad6d1b785df6b0b999b3c9 by Samuel Benzaquen <sbenza@google.com>: Fix uninitialized member in the `iterator` class by using a union of the two possible states of the iterator. This silences a Wuninitialized warning in gcc>=7. PiperOrigin-RevId: 228175148 -- 98b4e3204c0ec3cfd4cb037e24d443ea4b63fc84 by CJ Johnson <johnsoncj@google.com>: Factors out the implementation of InlinedVector::swap(...) into a private member function PiperOrigin-RevId: 228173383 -- f1432ad3a8b05285c6d55bc4754cfae765485b7f by Abseil Team <absl-team@google.com>: Import of CCTZ from GitHub. PiperOrigin-RevId: 227891984 -- 03fc00c7a4efc6000e6d9125cb2e252bffda76fe by Andy Getzendanner <durandal@google.com>: Add a missing linebreak to a comment and markdownify two unordered lists. PiperOrigin-RevId: 227861389 -- 0d66c9afba4fc9aa52e61d9fb410e165018a7b48 by Abseil Team <absl-team@google.com>: Add an API to register a new source for the cycle clock. PiperOrigin-RevId: 227779218 -- 14d3f9b70c8818b8541e5fb2f6ca4c59d479de31 by Andy Getzendanner <durandal@google.com>: Correct a typo in a stripping marker. PiperOrigin-RevId: 227750014 -- 59df88740f4e315beb57a8772f8bcf7879440c74 by Matt Kulukundis <kfm@google.com>: Switch thread local handling to be more cross platform PiperOrigin-RevId: 227695133 -- 75deed5bfcb5c42534e933f104aa7d94e11e348d by Abseil Team <absl-team@google.com>: Rollback workaround toolchain bug for incorrect handling of thread_local in inline functions PiperOrigin-RevId: 227689133 -- 54994bf0afec026e6e0e7a199df0bbb4b7d9a4aa by Derek Mauro <dmauro@google.com>: Add -pthread to linkopts where it actually belongs, on the library that uses it. Fixes https://github.com/abseil/abseil-cpp/issues/240. PiperOrigin-RevId: 227612492 -- 893875f3536b7e0a1bad993aa6b2e083abb3b25a by Derek Mauro <dmauro@google.com>: Internal change PiperOrigin-RevId: 227582833 -- 506c9b8e9002ca3389c7040473b68d4cbf94bdcc by Matt Kulukundis <kfm@google.com>: Workaround toolchain bug for incorrect handling of thread_local in inline functions PiperOrigin-RevId: 227561449 -- 29ee90d96dfe3114cf93f9bb92ea0cc9e768a407 by Derek Mauro <dmauro@google.com>: Internal change PiperOrigin-RevId: 227054634 GitOrigin-RevId: 5f1cf6547231f1b1daad6d1b785df6b0b999b3c9 Change-Id: Ibc90566d92ee6e0ad7e150f513ec7f5d22ec0a94
2019-01-07 18:01:16 +01:00
#include "absl/container/internal/counting_allocator.h"
2017-09-19 22:54:40 +02:00
#include "absl/container/internal/test_instance_tracker.h"
Export of internal Abseil changes. -- 1c1d6e2404dfc6caa022b335df5acdac6da50fe1 by Derek Mauro <dmauro@google.com>: Fix the internal namespacing in unaligned_access.h PiperOrigin-RevId: 215434506 -- 17d4400aebf025a230690fc1c7a968ef8d85bbba by Eric Fiselier <ericwf@google.com>: gtest depends on the GCC extension allowing variadic macros to be passed a empty parameter pack for ..., but LLVM diagnoses this as a GNU extension. This patch suppresses the warning when building the absl tests. PiperOrigin-RevId: 215426161 -- f2c49dde23a9f445b9de963f1bbe840ebb568b30 by Eric Fiselier <ericwf@google.com>: Use EXPECT_DEATH_IF_SUPPORTED instead of EXPECT_DEATH. This avoids breaking the test when gtest doesn't support death tests. PiperOrigin-RevId: 215423849 -- cd687c1e121709603f4fc3726b534f6a9c52cc89 by Eric Fiselier <ericwf@google.com>: Disable LLVM's -Wmissing-variable-declarations in tests. GCC's configuration already disables this via -Wno-missing-declarations, this change makes LLVM do the same. The warning would otherwise flag most tests which use ABSL_FLAG. PiperOrigin-RevId: 215407429 -- d14098824c84e3a8c8f6fb920e0335fb48fe2010 by Eric Fiselier <ericwf@google.com>: Fix local variable shadowing in city hash implementation. PiperOrigin-RevId: 215407249 -- 4b5e140ba743f0d231790a26c49083abb4329e2c by Abseil Team <absl-team@google.com>: Make raw_hash_set::reserve 2X fast when reserve doesn't do any allocation. Make raw_hash_set::reserve ~1% faster when reserve does some (128~4k) allocation. PiperOrigin-RevId: 215348727 -- 461161e65e04b801480aa117af2534c594654ccf by Eric Fiselier <ericwf@google.com>: Internal change PiperOrigin-RevId: 215272283 -- 50413ae31ad3d3a177257416acd8ede47a17bff2 by Eric Fiselier <ericwf@google.com>: Internal Change PiperOrigin-RevId: 215233183 -- 477be54c43d61019a8fe4e190e340eb52737d383 by Abseil Team <absl-team@google.com>: Clarify misleading comment on ABSL_ATTRIBUTE_UNUSED PiperOrigin-RevId: 215185496 -- 2cafa2b5287507d3a946682aee9ab13af6d471c9 by Matt Kulukundis <kfm@google.com>: Add support for absl::Hash to various absl in types. PiperOrigin-RevId: 215039569 -- 082248901991aa3d29be0ea3689c7f213cf0fd83 by Derek Mauro <dmauro@google.com>: Remove an instance of HAS_GLOBAL_STRING from hash_function_defaults.h PiperOrigin-RevId: 214989094 -- b929f61907f0786a6133e3a9d7287e339c0a0acb by Derek Mauro <dmauro@google.com>: Internal import of Github #174 Fix code snippet in comment https://github.com/abseil/abseil-cpp/pull/174 PiperOrigin-RevId: 214958849 -- f2c5e829eca11c352e121f56eefbf87083305023 by Derek Mauro <dmauro@google.com>: Internal import of GitHub #173 Fix CMake build for absl::container. https://github.com/abseil/abseil-cpp/pull/173 PiperOrigin-RevId: 214957796 -- d704f860f9fddafb99e34e6c5032e49f73874e10 by Abseil Team <absl-team@google.com>: Internal change PiperOrigin-RevId: 214828181 GitOrigin-RevId: 1c1d6e2404dfc6caa022b335df5acdac6da50fe1 Change-Id: I551de2b1ba0cbaf6856cd5959358cf6651179dea
2018-10-02 21:09:18 +02:00
#include "absl/hash/hash_testing.h"
2017-09-19 22:54:40 +02:00
#include "absl/memory/memory.h"
#include "absl/strings/str_cat.h"
namespace {
Export of internal Abseil changes. -- 5f1cf6547231f1b1daad6d1b785df6b0b999b3c9 by Samuel Benzaquen <sbenza@google.com>: Fix uninitialized member in the `iterator` class by using a union of the two possible states of the iterator. This silences a Wuninitialized warning in gcc>=7. PiperOrigin-RevId: 228175148 -- 98b4e3204c0ec3cfd4cb037e24d443ea4b63fc84 by CJ Johnson <johnsoncj@google.com>: Factors out the implementation of InlinedVector::swap(...) into a private member function PiperOrigin-RevId: 228173383 -- f1432ad3a8b05285c6d55bc4754cfae765485b7f by Abseil Team <absl-team@google.com>: Import of CCTZ from GitHub. PiperOrigin-RevId: 227891984 -- 03fc00c7a4efc6000e6d9125cb2e252bffda76fe by Andy Getzendanner <durandal@google.com>: Add a missing linebreak to a comment and markdownify two unordered lists. PiperOrigin-RevId: 227861389 -- 0d66c9afba4fc9aa52e61d9fb410e165018a7b48 by Abseil Team <absl-team@google.com>: Add an API to register a new source for the cycle clock. PiperOrigin-RevId: 227779218 -- 14d3f9b70c8818b8541e5fb2f6ca4c59d479de31 by Andy Getzendanner <durandal@google.com>: Correct a typo in a stripping marker. PiperOrigin-RevId: 227750014 -- 59df88740f4e315beb57a8772f8bcf7879440c74 by Matt Kulukundis <kfm@google.com>: Switch thread local handling to be more cross platform PiperOrigin-RevId: 227695133 -- 75deed5bfcb5c42534e933f104aa7d94e11e348d by Abseil Team <absl-team@google.com>: Rollback workaround toolchain bug for incorrect handling of thread_local in inline functions PiperOrigin-RevId: 227689133 -- 54994bf0afec026e6e0e7a199df0bbb4b7d9a4aa by Derek Mauro <dmauro@google.com>: Add -pthread to linkopts where it actually belongs, on the library that uses it. Fixes https://github.com/abseil/abseil-cpp/issues/240. PiperOrigin-RevId: 227612492 -- 893875f3536b7e0a1bad993aa6b2e083abb3b25a by Derek Mauro <dmauro@google.com>: Internal change PiperOrigin-RevId: 227582833 -- 506c9b8e9002ca3389c7040473b68d4cbf94bdcc by Matt Kulukundis <kfm@google.com>: Workaround toolchain bug for incorrect handling of thread_local in inline functions PiperOrigin-RevId: 227561449 -- 29ee90d96dfe3114cf93f9bb92ea0cc9e768a407 by Derek Mauro <dmauro@google.com>: Internal change PiperOrigin-RevId: 227054634 GitOrigin-RevId: 5f1cf6547231f1b1daad6d1b785df6b0b999b3c9 Change-Id: Ibc90566d92ee6e0ad7e150f513ec7f5d22ec0a94
2019-01-07 18:01:16 +01:00
using absl::container_internal::CountingAllocator;
2017-09-19 22:54:40 +02:00
using absl::test_internal::CopyableMovableInstance;
using absl::test_internal::CopyableOnlyInstance;
using absl::test_internal::InstanceTracker;
using testing::AllOf;
using testing::Each;
using testing::ElementsAre;
using testing::ElementsAreArray;
using testing::Eq;
using testing::Gt;
using testing::PrintToString;
using IntVec = absl::InlinedVector<int, 8>;
MATCHER_P(SizeIs, n, "") {
return testing::ExplainMatchResult(n, arg.size(), result_listener);
}
MATCHER_P(CapacityIs, n, "") {
return testing::ExplainMatchResult(n, arg.capacity(), result_listener);
}
MATCHER_P(ValueIs, e, "") {
return testing::ExplainMatchResult(e, arg.value(), result_listener);
}
// TODO(bsamwel): Add support for movable-only types.
// Test fixture for typed tests on BaseCountedInstance derived classes, see
// test_instance_tracker.h.
template <typename T>
class InstanceTest : public ::testing::Test {};
TYPED_TEST_SUITE_P(InstanceTest);
2017-09-19 22:54:40 +02:00
// A simple reference counted class to make sure that the proper elements are
// destroyed in the erase(begin, end) test.
class RefCounted {
public:
RefCounted(int value, int* count) : value_(value), count_(count) { Ref(); }
2017-09-19 22:54:40 +02:00
RefCounted(const RefCounted& v) : value_(v.value_), count_(v.count_) {
2017-09-19 22:54:40 +02:00
Ref();
}
~RefCounted() {
Unref();
count_ = nullptr;
}
friend void swap(RefCounted& a, RefCounted& b) {
using std::swap;
swap(a.value_, b.value_);
swap(a.count_, b.count_);
}
RefCounted& operator=(RefCounted v) {
using std::swap;
swap(*this, v);
return *this;
}
void Ref() const {
ABSL_RAW_CHECK(count_ != nullptr, "");
++(*count_);
}
void Unref() const {
--(*count_);
ABSL_RAW_CHECK(*count_ >= 0, "");
}
int value_;
int* count_;
};
using RefCountedVec = absl::InlinedVector<RefCounted, 8>;
// A class with a vtable pointer
class Dynamic {
public:
virtual ~Dynamic() {}
};
using DynamicVec = absl::InlinedVector<Dynamic, 8>;
// Append 0..len-1 to *v
template <typename Container>
static void Fill(Container* v, int len, int offset = 0) {
for (int i = 0; i < len; i++) {
v->push_back(i + offset);
}
}
static IntVec Fill(int len, int offset = 0) {
IntVec v;
Fill(&v, len, offset);
return v;
}
TEST(IntVec, SimpleOps) {
for (int len = 0; len < 20; len++) {
IntVec v;
const IntVec& cv = v; // const alias
Fill(&v, len);
EXPECT_EQ(len, v.size());
EXPECT_LE(len, v.capacity());
for (int i = 0; i < len; i++) {
EXPECT_EQ(i, v[i]);
EXPECT_EQ(i, v.at(i));
}
EXPECT_EQ(v.begin(), v.data());
EXPECT_EQ(cv.begin(), cv.data());
int counter = 0;
for (IntVec::iterator iter = v.begin(); iter != v.end(); ++iter) {
EXPECT_EQ(counter, *iter);
counter++;
}
EXPECT_EQ(counter, len);
counter = 0;
for (IntVec::const_iterator iter = v.begin(); iter != v.end(); ++iter) {
EXPECT_EQ(counter, *iter);
counter++;
}
EXPECT_EQ(counter, len);
counter = 0;
for (IntVec::const_iterator iter = v.cbegin(); iter != v.cend(); ++iter) {
EXPECT_EQ(counter, *iter);
counter++;
}
EXPECT_EQ(counter, len);
if (len > 0) {
EXPECT_EQ(0, v.front());
EXPECT_EQ(len - 1, v.back());
v.pop_back();
EXPECT_EQ(len - 1, v.size());
for (int i = 0; i < v.size(); ++i) {
EXPECT_EQ(i, v[i]);
EXPECT_EQ(i, v.at(i));
}
}
}
}
Export of internal Abseil changes. -- 7a6ff16a85beb730c172d5d25cf1b5e1be885c56 by Laramie Leavitt <lar@google.com>: Internal change. PiperOrigin-RevId: 254454546 -- ff8f9bafaefc26d451f576ea4a06d150aed63f6f by Andy Soffer <asoffer@google.com>: Internal changes PiperOrigin-RevId: 254451562 -- deefc5b651b479ce36f0b4ef203e119c0c8936f2 by CJ Johnson <johnsoncj@google.com>: Account for subtracting unsigned values from the size of InlinedVector PiperOrigin-RevId: 254450625 -- 3c677316a27bcadc17e41957c809ca472d5fef14 by Andy Soffer <asoffer@google.com>: Add C++17's std::make_from_tuple to absl/utility/utility.h PiperOrigin-RevId: 254411573 -- 4ee3536a918830eeec402a28fc31a62c7c90b940 by CJ Johnson <johnsoncj@google.com>: Adds benchmark for the rest of the InlinedVector public API PiperOrigin-RevId: 254408378 -- e5a21a00700ee83498ff1efbf649169756463ee4 by CJ Johnson <johnsoncj@google.com>: Updates the definition of InlinedVector::shrink_to_fit() to be exception safe and adds exception safety tests for it. PiperOrigin-RevId: 254401387 -- 2ea82e72b86d82d78b4e4712a63a55981b53c64b by Laramie Leavitt <lar@google.com>: Use absl::InsecureBitGen in place of std::mt19937 in tests absl/random/...distribution_test.cc PiperOrigin-RevId: 254289444 -- fa099e02c413a7ffda732415e8105cad26a90337 by Andy Soffer <asoffer@google.com>: Internal changes PiperOrigin-RevId: 254286334 -- ce34b7f36933b30cfa35b9c9a5697a792b5666e4 by Andy Soffer <asoffer@google.com>: Internal changes PiperOrigin-RevId: 254273059 -- 6f9c473da7c2090c2e85a37c5f00622e8a912a89 by Jorg Brown <jorg@google.com>: Change absl::container_internal::CompressedTuple to instantiate its internal Storage class with the name of the type it's holding, rather than the name of the Tuple. This is not an externally-visible change, other than less compiler memory is used and less debug information is generated. PiperOrigin-RevId: 254269285 -- 8bd3c186bf2fc0c55d8a2dd6f28a5327502c9fba by Andy Soffer <asoffer@google.com>: Adding short-hand IntervalClosed for IntervalClosedClosed and IntervalOpen for IntervalOpenOpen. PiperOrigin-RevId: 254252419 -- ea957f99b6a04fccd42aa05605605f3b44b1ecfd by Abseil Team <absl-team@google.com>: Do not directly use __SIZEOF_INT128__. In order to avoid linker errors when building with clang-cl (__fixunsdfti, __udivti3 and __fixunssfti are undefined), this CL uses ABSL_HAVE_INTRINSIC_INT128 which is not defined for clang-cl. PiperOrigin-RevId: 254250739 -- 89ab385cd26b34d64130bce856253aaba96d2345 by Andy Soffer <asoffer@google.com>: Internal changes PiperOrigin-RevId: 254242321 -- cffc793d93eca6d6bdf7de733847b6ab4a255ae9 by CJ Johnson <johnsoncj@google.com>: Adds benchmark for InlinedVector::reserve(size_type) PiperOrigin-RevId: 254199226 -- c90c7a9fa3c8f0c9d5114036979548b055ea2f2a by Gennadiy Rozental <rogeeff@google.com>: Import of CCTZ from GitHub. PiperOrigin-RevId: 254072387 -- c4c388beae016c9570ab54ffa1d52660e4a85b7b by Laramie Leavitt <lar@google.com>: Internal cleanup. PiperOrigin-RevId: 254062381 -- d3c992e221cc74e5372d0c8fa410170b6a43c062 by Tom Manshreck <shreck@google.com>: Update distributions.h to Abseil standards PiperOrigin-RevId: 254054946 -- d15ad0035c34ef11b14fadc5a4a2d3ec415f5518 by CJ Johnson <johnsoncj@google.com>: Removes functions with only one caller from the implementation details of InlinedVector by manually inlining the definitions PiperOrigin-RevId: 254005427 -- 2f37e807efc3a8ef1f4b539bdd379917d4151520 by Andy Soffer <asoffer@google.com>: Initial release of Abseil Random PiperOrigin-RevId: 253999861 -- 24ed1694b6430791d781ed533a8f8ccf6cac5856 by CJ Johnson <johnsoncj@google.com>: Updates the definition of InlinedVector::assign(...)/InlinedVector::operator=(...) to new, exception-safe implementations with exception safety tests to boot PiperOrigin-RevId: 253993691 -- 5613d95f5a7e34a535cfaeadce801441e990843e by CJ Johnson <johnsoncj@google.com>: Adds benchmarks for InlinedVector::shrink_to_fit() PiperOrigin-RevId: 253989647 -- 2a96ddfdac40bbb8cb6a7f1aeab90917067c6e63 by Abseil Team <absl-team@google.com>: Initial release of Abseil Random PiperOrigin-RevId: 253927497 -- bf1aff8fc9ffa921ad74643e9525ecf25b0d8dc1 by Andy Soffer <asoffer@google.com>: Initial release of Abseil Random PiperOrigin-RevId: 253920512 -- bfc03f4a3dcda3cf3a4b84bdb84cda24e3394f41 by Laramie Leavitt <lar@google.com>: Internal change. PiperOrigin-RevId: 253886486 -- 05036cfcc078ca7c5f581a00dfb0daed568cbb69 by Eric Fiselier <ericwf@google.com>: Don't include `winsock2.h` because it drags in `windows.h` and friends, and they define awful macros like OPAQUE, ERROR, and more. This has the potential to break abseil users. Instead we only forward declare `timeval` and require Windows users include `winsock2.h` themselves. This is both inconsistent and poor QoI, but so including 'windows.h' is bad too. PiperOrigin-RevId: 253852615 GitOrigin-RevId: 7a6ff16a85beb730c172d5d25cf1b5e1be885c56 Change-Id: Icd6aff87da26f29ec8915da856f051129987cef6
2019-06-21 22:11:42 +02:00
TEST(IntVec, PopBackNoOverflow) {
IntVec v = {1};
v.pop_back();
EXPECT_EQ(v.size(), 0);
}
2017-09-19 22:54:40 +02:00
TEST(IntVec, AtThrows) {
IntVec v = {1, 2, 3};
EXPECT_EQ(v.at(2), 3);
ABSL_BASE_INTERNAL_EXPECT_FAIL(v.at(3), std::out_of_range,
"failed bounds check");
}
TEST(IntVec, ReverseIterator) {
for (int len = 0; len < 20; len++) {
IntVec v;
Fill(&v, len);
int counter = len;
for (IntVec::reverse_iterator iter = v.rbegin(); iter != v.rend(); ++iter) {
counter--;
EXPECT_EQ(counter, *iter);
}
EXPECT_EQ(counter, 0);
counter = len;
for (IntVec::const_reverse_iterator iter = v.rbegin(); iter != v.rend();
++iter) {
counter--;
EXPECT_EQ(counter, *iter);
}
EXPECT_EQ(counter, 0);
counter = len;
for (IntVec::const_reverse_iterator iter = v.crbegin(); iter != v.crend();
++iter) {
counter--;
EXPECT_EQ(counter, *iter);
}
EXPECT_EQ(counter, 0);
}
}
TEST(IntVec, Erase) {
for (int len = 1; len < 20; len++) {
for (int i = 0; i < len; ++i) {
IntVec v;
Fill(&v, len);
v.erase(v.begin() + i);
EXPECT_EQ(len - 1, v.size());
for (int j = 0; j < i; ++j) {
EXPECT_EQ(j, v[j]);
}
for (int j = i; j < len - 1; ++j) {
EXPECT_EQ(j + 1, v[j]);
}
}
}
}
Export of internal Abseil changes -- 79913a12f0cad4baf948430315aabf53f03b6475 by Abseil Team <absl-team@google.com>: Don't inline (Un)LockSlow. PiperOrigin-RevId: 302502344 -- 6b340e80f0690655f24799c8de6707b3a95b8579 by Derek Mauro <dmauro@google.com>: Add hardening assertions to absl::optional's dereference operators PiperOrigin-RevId: 302492862 -- a9951bf4852d8c1aec472cb4b539830411270e4c by Derek Mauro <dmauro@google.com>: Correctly add hardware AES compiler flags under Linux X86-64 Fixes #643 PiperOrigin-RevId: 302490673 -- 314c3621ee4d57b6bc8d64338a1f1d48a69741d1 by Derek Mauro <dmauro@google.com>: Upgrade to hardening assertions in absl::Span::remove_prefix and absl::Span::remove_suffix PiperOrigin-RevId: 302481191 -- a142b8c6c62705c5f0d4fe3113150f0c0b7822b9 by Derek Mauro <dmauro@google.com>: Update docker containers to Bazel 2.2.0, GCC 9.3, and new Clang snapshot PiperOrigin-RevId: 302454042 -- afedeb70a2adc87010030c9ba6f06fe35ec26407 by Derek Mauro <dmauro@google.com>: Add hardening assertions for the preconditions of absl::FixedArray PiperOrigin-RevId: 302441767 -- 44442bfbc0a9a742df32f07cee86a47712efb8b4 by Derek Mauro <dmauro@google.com>: Fix new Clang warning about SpinLock doing operations on enums of different types PiperOrigin-RevId: 302430387 -- 69eaff7f97231779f696321c2ba8b88debf6dd9e by Derek Mauro <dmauro@google.com>: Convert precondition assertions to ABSL_HARDENING_ASSERT for absl::InlinedVector PiperOrigin-RevId: 302427894 -- 26b6db906a0942fd18583dc2cdd1bab32919d964 by Gennadiy Rozental <rogeeff@google.com>: Internal change PiperOrigin-RevId: 302425283 -- e62e81422979e922505d2cd9000e1de58123c088 by Derek Mauro <dmauro@google.com>: Add an option to build Abseil in hardened mode In hardened mode, the ABSL_HARDENING_ASSERT() macro is active even when NDEBUG is defined. This allows Abseil to perform runtime checks even in release mode. This should be used to implement things like bounds checks that could otherwise lead to security vulnerabilities. Use the new assertion in absl::string_view and absl::Span to test it. PiperOrigin-RevId: 302119187 GitOrigin-RevId: 79913a12f0cad4baf948430315aabf53f03b6475 Change-Id: I0cc3341fd333a1df313167bab72dc5a759c4a048
2020-03-23 21:16:18 +01:00
TEST(IntVec, Hardened) {
IntVec v;
Fill(&v, 10);
EXPECT_EQ(v[9], 9);
#if !defined(NDEBUG) || ABSL_OPTION_HARDENED
EXPECT_DEATH_IF_SUPPORTED(v[10], "");
EXPECT_DEATH_IF_SUPPORTED(v[-1], "");
#endif
}
2017-09-19 22:54:40 +02:00
// At the end of this test loop, the elements between [erase_begin, erase_end)
// should have reference counts == 0, and all others elements should have
// reference counts == 1.
TEST(RefCountedVec, EraseBeginEnd) {
for (int len = 1; len < 20; ++len) {
for (int erase_begin = 0; erase_begin < len; ++erase_begin) {
for (int erase_end = erase_begin; erase_end <= len; ++erase_end) {
std::vector<int> counts(len, 0);
RefCountedVec v;
for (int i = 0; i < len; ++i) {
v.push_back(RefCounted(i, &counts[i]));
}
int erase_len = erase_end - erase_begin;
v.erase(v.begin() + erase_begin, v.begin() + erase_end);
EXPECT_EQ(len - erase_len, v.size());
// Check the elements before the first element erased.
for (int i = 0; i < erase_begin; ++i) {
EXPECT_EQ(i, v[i].value_);
}
// Check the elements after the first element erased.
for (int i = erase_begin; i < v.size(); ++i) {
EXPECT_EQ(i + erase_len, v[i].value_);
}
// Check that the elements at the beginning are preserved.
for (int i = 0; i < erase_begin; ++i) {
EXPECT_EQ(1, counts[i]);
}
// Check that the erased elements are destroyed
for (int i = erase_begin; i < erase_end; ++i) {
EXPECT_EQ(0, counts[i]);
}
// Check that the elements at the end are preserved.
for (int i = erase_end; i < len; ++i) {
2017-09-19 22:54:40 +02:00
EXPECT_EQ(1, counts[i]);
}
}
}
}
}
struct NoDefaultCtor {
explicit NoDefaultCtor(int) {}
};
struct NoCopy {
NoCopy() {}
NoCopy(const NoCopy&) = delete;
};
struct NoAssign {
NoAssign() {}
NoAssign& operator=(const NoAssign&) = delete;
};
struct MoveOnly {
MoveOnly() {}
MoveOnly(MoveOnly&&) = default;
MoveOnly& operator=(MoveOnly&&) = default;
};
TEST(InlinedVectorTest, NoDefaultCtor) {
absl::InlinedVector<NoDefaultCtor, 1> v(10, NoDefaultCtor(2));
(void)v;
}
TEST(InlinedVectorTest, NoCopy) {
absl::InlinedVector<NoCopy, 1> v(10);
(void)v;
}
TEST(InlinedVectorTest, NoAssign) {
absl::InlinedVector<NoAssign, 1> v(10);
(void)v;
}
TEST(InlinedVectorTest, MoveOnly) {
absl::InlinedVector<MoveOnly, 2> v;
v.push_back(MoveOnly{});
v.push_back(MoveOnly{});
v.push_back(MoveOnly{});
v.erase(v.begin());
v.push_back(MoveOnly{});
v.erase(v.begin(), v.begin() + 1);
v.insert(v.begin(), MoveOnly{});
v.emplace(v.begin());
v.emplace(v.begin(), MoveOnly{});
}
TEST(InlinedVectorTest, Noexcept) {
EXPECT_TRUE(std::is_nothrow_move_constructible<IntVec>::value);
EXPECT_TRUE((std::is_nothrow_move_constructible<
absl::InlinedVector<MoveOnly, 2>>::value));
struct MoveCanThrow {
MoveCanThrow(MoveCanThrow&&) {}
};
EXPECT_EQ(absl::default_allocator_is_nothrow::value,
(std::is_nothrow_move_constructible<
absl::InlinedVector<MoveCanThrow, 2>>::value));
}
TEST(InlinedVectorTest, EmplaceBack) {
absl::InlinedVector<std::pair<std::string, int>, 1> v;
auto& inlined_element = v.emplace_back("answer", 42);
EXPECT_EQ(&inlined_element, &v[0]);
EXPECT_EQ(inlined_element.first, "answer");
EXPECT_EQ(inlined_element.second, 42);
auto& allocated_element = v.emplace_back("taxicab", 1729);
EXPECT_EQ(&allocated_element, &v[1]);
EXPECT_EQ(allocated_element.first, "taxicab");
EXPECT_EQ(allocated_element.second, 1729);
}
2017-09-19 22:54:40 +02:00
TEST(InlinedVectorTest, ShrinkToFitGrowingVector) {
absl::InlinedVector<std::pair<std::string, int>, 1> v;
v.shrink_to_fit();
EXPECT_EQ(v.capacity(), 1);
v.emplace_back("answer", 42);
v.shrink_to_fit();
EXPECT_EQ(v.capacity(), 1);
v.emplace_back("taxicab", 1729);
EXPECT_GE(v.capacity(), 2);
v.shrink_to_fit();
EXPECT_EQ(v.capacity(), 2);
v.reserve(100);
EXPECT_GE(v.capacity(), 100);
v.shrink_to_fit();
EXPECT_EQ(v.capacity(), 2);
}
TEST(InlinedVectorTest, ShrinkToFitEdgeCases) {
{
absl::InlinedVector<std::pair<std::string, int>, 1> v;
v.emplace_back("answer", 42);
v.emplace_back("taxicab", 1729);
EXPECT_GE(v.capacity(), 2);
v.pop_back();
v.shrink_to_fit();
EXPECT_EQ(v.capacity(), 1);
EXPECT_EQ(v[0].first, "answer");
EXPECT_EQ(v[0].second, 42);
}
{
absl::InlinedVector<std::string, 2> v(100);
v.resize(0);
v.shrink_to_fit();
EXPECT_EQ(v.capacity(), 2); // inlined capacity
}
{
absl::InlinedVector<std::string, 2> v(100);
v.resize(1);
v.shrink_to_fit();
EXPECT_EQ(v.capacity(), 2); // inlined capacity
}
{
absl::InlinedVector<std::string, 2> v(100);
v.resize(2);
v.shrink_to_fit();
EXPECT_EQ(v.capacity(), 2);
}
{
absl::InlinedVector<std::string, 2> v(100);
v.resize(3);
v.shrink_to_fit();
EXPECT_EQ(v.capacity(), 3);
}
}
2017-09-19 22:54:40 +02:00
TEST(IntVec, Insert) {
for (int len = 0; len < 20; len++) {
for (int pos = 0; pos <= len; pos++) {
{
// Single element
std::vector<int> std_v;
Fill(&std_v, len);
IntVec v;
Fill(&v, len);
std_v.insert(std_v.begin() + pos, 9999);
IntVec::iterator it = v.insert(v.cbegin() + pos, 9999);
EXPECT_THAT(v, ElementsAreArray(std_v));
EXPECT_EQ(it, v.cbegin() + pos);
}
{
// n elements
std::vector<int> std_v;
Fill(&std_v, len);
IntVec v;
Fill(&v, len);
IntVec::size_type n = 5;
std_v.insert(std_v.begin() + pos, n, 9999);
IntVec::iterator it = v.insert(v.cbegin() + pos, n, 9999);
EXPECT_THAT(v, ElementsAreArray(std_v));
EXPECT_EQ(it, v.cbegin() + pos);
}
{
// Iterator range (random access iterator)
std::vector<int> std_v;
Fill(&std_v, len);
IntVec v;
Fill(&v, len);
const std::vector<int> input = {9999, 8888, 7777};
std_v.insert(std_v.begin() + pos, input.cbegin(), input.cend());
IntVec::iterator it =
v.insert(v.cbegin() + pos, input.cbegin(), input.cend());
EXPECT_THAT(v, ElementsAreArray(std_v));
EXPECT_EQ(it, v.cbegin() + pos);
}
{
// Iterator range (forward iterator)
std::vector<int> std_v;
Fill(&std_v, len);
IntVec v;
Fill(&v, len);
const std::forward_list<int> input = {9999, 8888, 7777};
std_v.insert(std_v.begin() + pos, input.cbegin(), input.cend());
IntVec::iterator it =
v.insert(v.cbegin() + pos, input.cbegin(), input.cend());
EXPECT_THAT(v, ElementsAreArray(std_v));
EXPECT_EQ(it, v.cbegin() + pos);
}
{
// Iterator range (input iterator)
std::vector<int> std_v;
Fill(&std_v, len);
IntVec v;
Fill(&v, len);
std_v.insert(std_v.begin() + pos, {9999, 8888, 7777});
std::istringstream input("9999 8888 7777");
IntVec::iterator it =
v.insert(v.cbegin() + pos, std::istream_iterator<int>(input),
std::istream_iterator<int>());
EXPECT_THAT(v, ElementsAreArray(std_v));
EXPECT_EQ(it, v.cbegin() + pos);
}
{
// Initializer list
std::vector<int> std_v;
Fill(&std_v, len);
IntVec v;
Fill(&v, len);
std_v.insert(std_v.begin() + pos, {9999, 8888});
IntVec::iterator it = v.insert(v.cbegin() + pos, {9999, 8888});
EXPECT_THAT(v, ElementsAreArray(std_v));
EXPECT_EQ(it, v.cbegin() + pos);
}
}
}
}
TEST(RefCountedVec, InsertConstructorDestructor) {
// Make sure the proper construction/destruction happen during insert
// operations.
for (int len = 0; len < 20; len++) {
SCOPED_TRACE(len);
for (int pos = 0; pos <= len; pos++) {
SCOPED_TRACE(pos);
std::vector<int> counts(len, 0);
int inserted_count = 0;
RefCountedVec v;
for (int i = 0; i < len; ++i) {
SCOPED_TRACE(i);
v.push_back(RefCounted(i, &counts[i]));
}
EXPECT_THAT(counts, Each(Eq(1)));
RefCounted insert_element(9999, &inserted_count);
EXPECT_EQ(1, inserted_count);
v.insert(v.begin() + pos, insert_element);
EXPECT_EQ(2, inserted_count);
// Check that the elements at the end are preserved.
EXPECT_THAT(counts, Each(Eq(1)));
EXPECT_EQ(2, inserted_count);
}
}
}
TEST(IntVec, Resize) {
for (int len = 0; len < 20; len++) {
IntVec v;
Fill(&v, len);
// Try resizing up and down by k elements
static const int kResizeElem = 1000000;
for (int k = 0; k < 10; k++) {
// Enlarging resize
v.resize(len + k, kResizeElem);
EXPECT_EQ(len + k, v.size());
EXPECT_LE(len + k, v.capacity());
for (int i = 0; i < len + k; i++) {
2017-09-19 22:54:40 +02:00
if (i < len) {
EXPECT_EQ(i, v[i]);
} else {
EXPECT_EQ(kResizeElem, v[i]);
}
}
// Shrinking resize
v.resize(len, kResizeElem);
EXPECT_EQ(len, v.size());
EXPECT_LE(len, v.capacity());
for (int i = 0; i < len; i++) {
EXPECT_EQ(i, v[i]);
}
}
}
}
TEST(IntVec, InitWithLength) {
for (int len = 0; len < 20; len++) {
IntVec v(len, 7);
EXPECT_EQ(len, v.size());
EXPECT_LE(len, v.capacity());
for (int i = 0; i < len; i++) {
EXPECT_EQ(7, v[i]);
}
}
}
TEST(IntVec, CopyConstructorAndAssignment) {
for (int len = 0; len < 20; len++) {
IntVec v;
Fill(&v, len);
EXPECT_EQ(len, v.size());
EXPECT_LE(len, v.capacity());
IntVec v2(v);
EXPECT_TRUE(v == v2) << PrintToString(v) << PrintToString(v2);
for (int start_len = 0; start_len < 20; start_len++) {
IntVec v3;
Fill(&v3, start_len, 99); // Add dummy elements that should go away
v3 = v;
EXPECT_TRUE(v == v3) << PrintToString(v) << PrintToString(v3);
}
}
}
TEST(IntVec, AliasingCopyAssignment) {
for (int len = 0; len < 20; ++len) {
IntVec original;
Fill(&original, len);
IntVec dup = original;
2018-04-18 14:56:39 +02:00
dup = *&dup;
EXPECT_EQ(dup, original);
}
}
2017-09-19 22:54:40 +02:00
TEST(IntVec, MoveConstructorAndAssignment) {
for (int len = 0; len < 20; len++) {
IntVec v_in;
const int inlined_capacity = v_in.capacity();
Fill(&v_in, len);
EXPECT_EQ(len, v_in.size());
EXPECT_LE(len, v_in.capacity());
{
IntVec v_temp(v_in);
auto* old_data = v_temp.data();
IntVec v_out(std::move(v_temp));
EXPECT_TRUE(v_in == v_out) << PrintToString(v_in) << PrintToString(v_out);
if (v_in.size() > inlined_capacity) {
// Allocation is moved as a whole, data stays in place.
EXPECT_TRUE(v_out.data() == old_data);
} else {
EXPECT_FALSE(v_out.data() == old_data);
}
}
for (int start_len = 0; start_len < 20; start_len++) {
IntVec v_out;
Fill(&v_out, start_len, 99); // Add dummy elements that should go away
IntVec v_temp(v_in);
auto* old_data = v_temp.data();
v_out = std::move(v_temp);
EXPECT_TRUE(v_in == v_out) << PrintToString(v_in) << PrintToString(v_out);
if (v_in.size() > inlined_capacity) {
// Allocation is moved as a whole, data stays in place.
EXPECT_TRUE(v_out.data() == old_data);
} else {
EXPECT_FALSE(v_out.data() == old_data);
}
}
}
}
class NotTriviallyDestructible {
public:
NotTriviallyDestructible() : p_(new int(1)) {}
explicit NotTriviallyDestructible(int i) : p_(new int(i)) {}
NotTriviallyDestructible(const NotTriviallyDestructible& other)
: p_(new int(*other.p_)) {}
NotTriviallyDestructible& operator=(const NotTriviallyDestructible& other) {
p_ = absl::make_unique<int>(*other.p_);
return *this;
}
bool operator==(const NotTriviallyDestructible& other) const {
return *p_ == *other.p_;
}
private:
std::unique_ptr<int> p_;
};
TEST(AliasingTest, Emplace) {
for (int i = 2; i < 20; ++i) {
absl::InlinedVector<NotTriviallyDestructible, 10> vec;
for (int j = 0; j < i; ++j) {
vec.push_back(NotTriviallyDestructible(j));
}
vec.emplace(vec.begin(), vec[0]);
EXPECT_EQ(vec[0], vec[1]);
vec.emplace(vec.begin() + i / 2, vec[i / 2]);
EXPECT_EQ(vec[i / 2], vec[i / 2 + 1]);
vec.emplace(vec.end() - 1, vec.back());
EXPECT_EQ(vec[vec.size() - 2], vec.back());
}
}
TEST(AliasingTest, InsertWithCount) {
for (int i = 1; i < 20; ++i) {
absl::InlinedVector<NotTriviallyDestructible, 10> vec;
for (int j = 0; j < i; ++j) {
vec.push_back(NotTriviallyDestructible(j));
}
for (int n = 0; n < 5; ++n) {
// We use back where we can because it's guaranteed to become invalidated
vec.insert(vec.begin(), n, vec.back());
auto b = vec.begin();
EXPECT_TRUE(
std::all_of(b, b + n, [&vec](const NotTriviallyDestructible& x) {
return x == vec.back();
}));
auto m_idx = vec.size() / 2;
vec.insert(vec.begin() + m_idx, n, vec.back());
auto m = vec.begin() + m_idx;
EXPECT_TRUE(
std::all_of(m, m + n, [&vec](const NotTriviallyDestructible& x) {
return x == vec.back();
}));
// We want distinct values so the equality test is meaningful,
// vec[vec.size() - 1] is also almost always invalidated.
auto old_e = vec.size() - 1;
auto val = vec[old_e];
vec.insert(vec.end(), n, vec[old_e]);
auto e = vec.begin() + old_e;
EXPECT_TRUE(std::all_of(
e, e + n,
[&val](const NotTriviallyDestructible& x) { return x == val; }));
}
}
}
2017-09-19 22:54:40 +02:00
TEST(OverheadTest, Storage) {
// Check for size overhead.
// In particular, ensure that std::allocator doesn't cost anything to store.
// The union should be absorbing some of the allocation bookkeeping overhead
// in the larger vectors, leaving only the size_ field as overhead.
EXPECT_EQ(2 * sizeof(int*),
sizeof(absl::InlinedVector<int*, 1>) - 1 * sizeof(int*));
EXPECT_EQ(1 * sizeof(int*),
sizeof(absl::InlinedVector<int*, 2>) - 2 * sizeof(int*));
EXPECT_EQ(1 * sizeof(int*),
sizeof(absl::InlinedVector<int*, 3>) - 3 * sizeof(int*));
EXPECT_EQ(1 * sizeof(int*),
sizeof(absl::InlinedVector<int*, 4>) - 4 * sizeof(int*));
EXPECT_EQ(1 * sizeof(int*),
sizeof(absl::InlinedVector<int*, 5>) - 5 * sizeof(int*));
EXPECT_EQ(1 * sizeof(int*),
sizeof(absl::InlinedVector<int*, 6>) - 6 * sizeof(int*));
EXPECT_EQ(1 * sizeof(int*),
sizeof(absl::InlinedVector<int*, 7>) - 7 * sizeof(int*));
EXPECT_EQ(1 * sizeof(int*),
sizeof(absl::InlinedVector<int*, 8>) - 8 * sizeof(int*));
}
TEST(IntVec, Clear) {
for (int len = 0; len < 20; len++) {
SCOPED_TRACE(len);
IntVec v;
Fill(&v, len);
v.clear();
EXPECT_EQ(0, v.size());
EXPECT_EQ(v.begin(), v.end());
}
}
TEST(IntVec, Reserve) {
for (int len = 0; len < 20; len++) {
IntVec v;
Fill(&v, len);
for (int newlen = 0; newlen < 100; newlen++) {
const int* start_rep = v.data();
v.reserve(newlen);
const int* final_rep = v.data();
if (newlen <= len) {
EXPECT_EQ(start_rep, final_rep);
}
EXPECT_LE(newlen, v.capacity());
// Filling up to newlen should not change rep
while (v.size() < newlen) {
v.push_back(0);
}
EXPECT_EQ(final_rep, v.data());
}
}
}
TEST(StringVec, SelfRefPushBack) {
std::vector<std::string> std_v;
absl::InlinedVector<std::string, 4> v;
const std::string s = "A quite long string to ensure heap.";
2017-09-19 22:54:40 +02:00
std_v.push_back(s);
v.push_back(s);
for (int i = 0; i < 20; ++i) {
EXPECT_THAT(v, ElementsAreArray(std_v));
v.push_back(v.back());
std_v.push_back(std_v.back());
}
EXPECT_THAT(v, ElementsAreArray(std_v));
}
TEST(StringVec, SelfRefPushBackWithMove) {
std::vector<std::string> std_v;
absl::InlinedVector<std::string, 4> v;
const std::string s = "A quite long string to ensure heap.";
2017-09-19 22:54:40 +02:00
std_v.push_back(s);
v.push_back(s);
for (int i = 0; i < 20; ++i) {
EXPECT_EQ(v.back(), std_v.back());
v.push_back(std::move(v.back()));
std_v.push_back(std::move(std_v.back()));
}
EXPECT_EQ(v.back(), std_v.back());
}
TEST(StringVec, SelfMove) {
const std::string s = "A quite long string to ensure heap.";
2017-09-19 22:54:40 +02:00
for (int len = 0; len < 20; len++) {
SCOPED_TRACE(len);
absl::InlinedVector<std::string, 8> v;
for (int i = 0; i < len; ++i) {
SCOPED_TRACE(i);
v.push_back(s);
}
// Indirection necessary to avoid compiler warning.
v = std::move(*(&v));
// Ensure that the inlined vector is still in a valid state by copying it.
// We don't expect specific contents since a self-move results in an
// unspecified valid state.
std::vector<std::string> copy(v.begin(), v.end());
}
}
TEST(IntVec, Swap) {
for (int l1 = 0; l1 < 20; l1++) {
SCOPED_TRACE(l1);
for (int l2 = 0; l2 < 20; l2++) {
SCOPED_TRACE(l2);
IntVec a = Fill(l1, 0);
IntVec b = Fill(l2, 100);
{
using std::swap;
swap(a, b);
}
EXPECT_EQ(l1, b.size());
EXPECT_EQ(l2, a.size());
for (int i = 0; i < l1; i++) {
SCOPED_TRACE(i);
EXPECT_EQ(i, b[i]);
}
for (int i = 0; i < l2; i++) {
SCOPED_TRACE(i);
EXPECT_EQ(100 + i, a[i]);
}
}
}
}
TYPED_TEST_P(InstanceTest, Swap) {
using Instance = TypeParam;
using InstanceVec = absl::InlinedVector<Instance, 8>;
for (int l1 = 0; l1 < 20; l1++) {
SCOPED_TRACE(l1);
for (int l2 = 0; l2 < 20; l2++) {
SCOPED_TRACE(l2);
InstanceTracker tracker;
InstanceVec a, b;
const size_t inlined_capacity = a.capacity();
Export of internal Abseil changes. -- ba4dd47492748bd630462eb68b7959037fc6a11a by Abseil Team <absl-team@google.com>: Work around nvcc 9.0 compiler bug for open-source Tensorflow build. With the current implementation, when I (unintentionally and transitively) include absl/types/optional.h in a CUDA compilation unit, I get the following nvcc error message: INFO: From Compiling tensorflow/core/kernels/crop_and_resize_op_gpu.cu.cc: external/com_google_absl/absl/types/optional.h: In member function 'void absl::optional_internal::optional_data_dtor_base<T, <anonymous> >::destruct()': external/com_google_absl/absl/types/optional.h:185:50: error: '__T0' was not declared in this scope data_.~T(); I've also seen similar compilation failures online, for flat_hash_map: https://devtalk.nvidia.com/default/topic/1042599/nvcc-preprocessor-bug-causes-compilation-failure/ The bug is always around unnamed template parameters. Therefore, the workaround is to make them named. PiperOrigin-RevId: 219208288 -- dad2f40cb2e8d5017660985ef6fb57f3c3cdcc80 by CJ Johnson <johnsoncj@google.com>: Adds internal macros for catching and throwing unknown exception types PiperOrigin-RevId: 219207362 -- 0a9840328d2d86e8420b853435fdbf1f7a19d931 by Abseil Team <absl-team@google.com>: Fix typo in mutex.h comments. PiperOrigin-RevId: 219199397 -- 0d576dc7597564210bfdf91518075064756f0bf4 by Matt Calabrese <calabrese@google.com>: Internal change. PiperOrigin-RevId: 219185475 -- 66be156095571959fb19a76da8ad0b53ec37658e by Abseil Team <absl-team@google.com>: Fix alignment conformance for VS 2017 >= 15.8 (fix #193) PiperOrigin-RevId: 219129894 -- a6e1825a12587945f8194677ccfdcaba6f7aad1d by Abseil Team <absl-team@google.com>: Reapply PR #173 PiperOrigin-RevId: 219129361 -- cf72ade4881b25acc6ccaea468f69793a0fdce32 by Abseil Team <absl-team@google.com>: Update .gitignore PiperOrigin-RevId: 219127495 -- 0537490c6348a2cb489abe15638928ac5aa6982a by Jon Cohen <cohenjon@google.com>: Small refactor and reformat of error messages from the exception safety test framework. PiperOrigin-RevId: 218927773 -- 4c556ca45fa25698ad12002a00c713aeceefab73 by CJ Johnson <johnsoncj@google.com>: Updates the inlined vector swap tests to check for number of moves that took place if available PiperOrigin-RevId: 218900777 -- dcbfda0021a1e6dfa9586986b1269c06ec394053 by Mark Barolak <mbar@google.com>: Add parens around calls to std::numeric_limits<>::min and std::numeric_limits<>::max to prevent compilation errors on Windows platforms where min and max are defined as macros. PiperOrigin-RevId: 218888700 GitOrigin-RevId: ba4dd47492748bd630462eb68b7959037fc6a11a Change-Id: I0e393958eb8cb501b85f6114979f6d4d86ed996c
2018-10-29 23:53:34 +01:00
auto min_len = std::min(l1, l2);
auto max_len = std::max(l1, l2);
2017-09-19 22:54:40 +02:00
for (int i = 0; i < l1; i++) a.push_back(Instance(i));
for (int i = 0; i < l2; i++) b.push_back(Instance(100 + i));
2017-09-19 22:54:40 +02:00
EXPECT_EQ(tracker.instances(), l1 + l2);
tracker.ResetCopiesMovesSwaps();
{
using std::swap;
swap(a, b);
}
EXPECT_EQ(tracker.instances(), l1 + l2);
if (a.size() > inlined_capacity && b.size() > inlined_capacity) {
EXPECT_EQ(tracker.swaps(), 0); // Allocations are swapped.
EXPECT_EQ(tracker.moves(), 0);
} else if (a.size() <= inlined_capacity && b.size() <= inlined_capacity) {
Export of internal Abseil changes. -- ba4dd47492748bd630462eb68b7959037fc6a11a by Abseil Team <absl-team@google.com>: Work around nvcc 9.0 compiler bug for open-source Tensorflow build. With the current implementation, when I (unintentionally and transitively) include absl/types/optional.h in a CUDA compilation unit, I get the following nvcc error message: INFO: From Compiling tensorflow/core/kernels/crop_and_resize_op_gpu.cu.cc: external/com_google_absl/absl/types/optional.h: In member function 'void absl::optional_internal::optional_data_dtor_base<T, <anonymous> >::destruct()': external/com_google_absl/absl/types/optional.h:185:50: error: '__T0' was not declared in this scope data_.~T(); I've also seen similar compilation failures online, for flat_hash_map: https://devtalk.nvidia.com/default/topic/1042599/nvcc-preprocessor-bug-causes-compilation-failure/ The bug is always around unnamed template parameters. Therefore, the workaround is to make them named. PiperOrigin-RevId: 219208288 -- dad2f40cb2e8d5017660985ef6fb57f3c3cdcc80 by CJ Johnson <johnsoncj@google.com>: Adds internal macros for catching and throwing unknown exception types PiperOrigin-RevId: 219207362 -- 0a9840328d2d86e8420b853435fdbf1f7a19d931 by Abseil Team <absl-team@google.com>: Fix typo in mutex.h comments. PiperOrigin-RevId: 219199397 -- 0d576dc7597564210bfdf91518075064756f0bf4 by Matt Calabrese <calabrese@google.com>: Internal change. PiperOrigin-RevId: 219185475 -- 66be156095571959fb19a76da8ad0b53ec37658e by Abseil Team <absl-team@google.com>: Fix alignment conformance for VS 2017 >= 15.8 (fix #193) PiperOrigin-RevId: 219129894 -- a6e1825a12587945f8194677ccfdcaba6f7aad1d by Abseil Team <absl-team@google.com>: Reapply PR #173 PiperOrigin-RevId: 219129361 -- cf72ade4881b25acc6ccaea468f69793a0fdce32 by Abseil Team <absl-team@google.com>: Update .gitignore PiperOrigin-RevId: 219127495 -- 0537490c6348a2cb489abe15638928ac5aa6982a by Jon Cohen <cohenjon@google.com>: Small refactor and reformat of error messages from the exception safety test framework. PiperOrigin-RevId: 218927773 -- 4c556ca45fa25698ad12002a00c713aeceefab73 by CJ Johnson <johnsoncj@google.com>: Updates the inlined vector swap tests to check for number of moves that took place if available PiperOrigin-RevId: 218900777 -- dcbfda0021a1e6dfa9586986b1269c06ec394053 by Mark Barolak <mbar@google.com>: Add parens around calls to std::numeric_limits<>::min and std::numeric_limits<>::max to prevent compilation errors on Windows platforms where min and max are defined as macros. PiperOrigin-RevId: 218888700 GitOrigin-RevId: ba4dd47492748bd630462eb68b7959037fc6a11a Change-Id: I0e393958eb8cb501b85f6114979f6d4d86ed996c
2018-10-29 23:53:34 +01:00
EXPECT_EQ(tracker.swaps(), min_len);
EXPECT_EQ((tracker.moves() ? tracker.moves() : tracker.copies()),
max_len - min_len);
2017-09-19 22:54:40 +02:00
} else {
// One is allocated and the other isn't. The allocation is transferred
// without copying elements, and the inlined instances are copied/moved.
EXPECT_EQ(tracker.swaps(), 0);
Export of internal Abseil changes. -- ba4dd47492748bd630462eb68b7959037fc6a11a by Abseil Team <absl-team@google.com>: Work around nvcc 9.0 compiler bug for open-source Tensorflow build. With the current implementation, when I (unintentionally and transitively) include absl/types/optional.h in a CUDA compilation unit, I get the following nvcc error message: INFO: From Compiling tensorflow/core/kernels/crop_and_resize_op_gpu.cu.cc: external/com_google_absl/absl/types/optional.h: In member function 'void absl::optional_internal::optional_data_dtor_base<T, <anonymous> >::destruct()': external/com_google_absl/absl/types/optional.h:185:50: error: '__T0' was not declared in this scope data_.~T(); I've also seen similar compilation failures online, for flat_hash_map: https://devtalk.nvidia.com/default/topic/1042599/nvcc-preprocessor-bug-causes-compilation-failure/ The bug is always around unnamed template parameters. Therefore, the workaround is to make them named. PiperOrigin-RevId: 219208288 -- dad2f40cb2e8d5017660985ef6fb57f3c3cdcc80 by CJ Johnson <johnsoncj@google.com>: Adds internal macros for catching and throwing unknown exception types PiperOrigin-RevId: 219207362 -- 0a9840328d2d86e8420b853435fdbf1f7a19d931 by Abseil Team <absl-team@google.com>: Fix typo in mutex.h comments. PiperOrigin-RevId: 219199397 -- 0d576dc7597564210bfdf91518075064756f0bf4 by Matt Calabrese <calabrese@google.com>: Internal change. PiperOrigin-RevId: 219185475 -- 66be156095571959fb19a76da8ad0b53ec37658e by Abseil Team <absl-team@google.com>: Fix alignment conformance for VS 2017 >= 15.8 (fix #193) PiperOrigin-RevId: 219129894 -- a6e1825a12587945f8194677ccfdcaba6f7aad1d by Abseil Team <absl-team@google.com>: Reapply PR #173 PiperOrigin-RevId: 219129361 -- cf72ade4881b25acc6ccaea468f69793a0fdce32 by Abseil Team <absl-team@google.com>: Update .gitignore PiperOrigin-RevId: 219127495 -- 0537490c6348a2cb489abe15638928ac5aa6982a by Jon Cohen <cohenjon@google.com>: Small refactor and reformat of error messages from the exception safety test framework. PiperOrigin-RevId: 218927773 -- 4c556ca45fa25698ad12002a00c713aeceefab73 by CJ Johnson <johnsoncj@google.com>: Updates the inlined vector swap tests to check for number of moves that took place if available PiperOrigin-RevId: 218900777 -- dcbfda0021a1e6dfa9586986b1269c06ec394053 by Mark Barolak <mbar@google.com>: Add parens around calls to std::numeric_limits<>::min and std::numeric_limits<>::max to prevent compilation errors on Windows platforms where min and max are defined as macros. PiperOrigin-RevId: 218888700 GitOrigin-RevId: ba4dd47492748bd630462eb68b7959037fc6a11a Change-Id: I0e393958eb8cb501b85f6114979f6d4d86ed996c
2018-10-29 23:53:34 +01:00
EXPECT_EQ((tracker.moves() ? tracker.moves() : tracker.copies()),
min_len);
2017-09-19 22:54:40 +02:00
}
EXPECT_EQ(l1, b.size());
EXPECT_EQ(l2, a.size());
for (int i = 0; i < l1; i++) {
EXPECT_EQ(i, b[i].value());
}
for (int i = 0; i < l2; i++) {
EXPECT_EQ(100 + i, a[i].value());
}
}
}
}
TEST(IntVec, EqualAndNotEqual) {
IntVec a, b;
EXPECT_TRUE(a == b);
EXPECT_FALSE(a != b);
a.push_back(3);
EXPECT_FALSE(a == b);
EXPECT_TRUE(a != b);
b.push_back(3);
EXPECT_TRUE(a == b);
EXPECT_FALSE(a != b);
b.push_back(7);
EXPECT_FALSE(a == b);
EXPECT_TRUE(a != b);
a.push_back(6);
EXPECT_FALSE(a == b);
EXPECT_TRUE(a != b);
a.clear();
b.clear();
for (int i = 0; i < 100; i++) {
a.push_back(i);
b.push_back(i);
EXPECT_TRUE(a == b);
EXPECT_FALSE(a != b);
b[i] = b[i] + 1;
EXPECT_FALSE(a == b);
EXPECT_TRUE(a != b);
b[i] = b[i] - 1; // Back to before
2017-09-19 22:54:40 +02:00
EXPECT_TRUE(a == b);
EXPECT_FALSE(a != b);
}
}
TEST(IntVec, RelationalOps) {
IntVec a, b;
EXPECT_FALSE(a < b);
EXPECT_FALSE(b < a);
EXPECT_FALSE(a > b);
EXPECT_FALSE(b > a);
EXPECT_TRUE(a <= b);
EXPECT_TRUE(b <= a);
EXPECT_TRUE(a >= b);
EXPECT_TRUE(b >= a);
b.push_back(3);
EXPECT_TRUE(a < b);
EXPECT_FALSE(b < a);
EXPECT_FALSE(a > b);
EXPECT_TRUE(b > a);
EXPECT_TRUE(a <= b);
EXPECT_FALSE(b <= a);
EXPECT_FALSE(a >= b);
EXPECT_TRUE(b >= a);
}
TYPED_TEST_P(InstanceTest, CountConstructorsDestructors) {
using Instance = TypeParam;
using InstanceVec = absl::InlinedVector<Instance, 8>;
InstanceTracker tracker;
for (int len = 0; len < 20; len++) {
SCOPED_TRACE(len);
tracker.ResetCopiesMovesSwaps();
InstanceVec v;
const size_t inlined_capacity = v.capacity();
for (int i = 0; i < len; i++) {
v.push_back(Instance(i));
}
EXPECT_EQ(tracker.instances(), len);
EXPECT_GE(tracker.copies() + tracker.moves(),
len); // More due to reallocation.
tracker.ResetCopiesMovesSwaps();
// Enlarging resize() must construct some objects
tracker.ResetCopiesMovesSwaps();
v.resize(len + 10, Instance(100));
EXPECT_EQ(tracker.instances(), len + 10);
if (len <= inlined_capacity && len + 10 > inlined_capacity) {
EXPECT_EQ(tracker.copies() + tracker.moves(), 10 + len);
} else {
// Only specify a minimum number of copies + moves. We don't want to
// depend on the reallocation policy here.
EXPECT_GE(tracker.copies() + tracker.moves(),
10); // More due to reallocation.
}
// Shrinking resize() must destroy some objects
tracker.ResetCopiesMovesSwaps();
v.resize(len, Instance(100));
EXPECT_EQ(tracker.instances(), len);
EXPECT_EQ(tracker.copies(), 0);
EXPECT_EQ(tracker.moves(), 0);
// reserve() must not increase the number of initialized objects
SCOPED_TRACE("reserve");
v.reserve(len + 1000);
2017-09-19 22:54:40 +02:00
EXPECT_EQ(tracker.instances(), len);
EXPECT_EQ(tracker.copies() + tracker.moves(), len);
// pop_back() and erase() must destroy one object
if (len > 0) {
tracker.ResetCopiesMovesSwaps();
v.pop_back();
EXPECT_EQ(tracker.instances(), len - 1);
EXPECT_EQ(tracker.copies(), 0);
EXPECT_EQ(tracker.moves(), 0);
if (!v.empty()) {
tracker.ResetCopiesMovesSwaps();
v.erase(v.begin());
EXPECT_EQ(tracker.instances(), len - 2);
EXPECT_EQ(tracker.copies() + tracker.moves(), len - 2);
}
}
tracker.ResetCopiesMovesSwaps();
int instances_before_empty_erase = tracker.instances();
v.erase(v.begin(), v.begin());
EXPECT_EQ(tracker.instances(), instances_before_empty_erase);
EXPECT_EQ(tracker.copies() + tracker.moves(), 0);
}
}
TYPED_TEST_P(InstanceTest, CountConstructorsDestructorsOnCopyConstruction) {
using Instance = TypeParam;
using InstanceVec = absl::InlinedVector<Instance, 8>;
InstanceTracker tracker;
for (int len = 0; len < 20; len++) {
SCOPED_TRACE(len);
tracker.ResetCopiesMovesSwaps();
InstanceVec v;
for (int i = 0; i < len; i++) {
v.push_back(Instance(i));
}
EXPECT_EQ(tracker.instances(), len);
EXPECT_GE(tracker.copies() + tracker.moves(),
len); // More due to reallocation.
tracker.ResetCopiesMovesSwaps();
{ // Copy constructor should create 'len' more instances.
InstanceVec v_copy(v);
EXPECT_EQ(tracker.instances(), len + len);
EXPECT_EQ(tracker.copies(), len);
EXPECT_EQ(tracker.moves(), 0);
}
EXPECT_EQ(tracker.instances(), len);
}
}
TYPED_TEST_P(InstanceTest, CountConstructorsDestructorsOnMoveConstruction) {
using Instance = TypeParam;
using InstanceVec = absl::InlinedVector<Instance, 8>;
InstanceTracker tracker;
for (int len = 0; len < 20; len++) {
SCOPED_TRACE(len);
tracker.ResetCopiesMovesSwaps();
InstanceVec v;
const size_t inlined_capacity = v.capacity();
for (int i = 0; i < len; i++) {
v.push_back(Instance(i));
}
EXPECT_EQ(tracker.instances(), len);
EXPECT_GE(tracker.copies() + tracker.moves(),
len); // More due to reallocation.
tracker.ResetCopiesMovesSwaps();
{
InstanceVec v_copy(std::move(v));
if (len > inlined_capacity) {
// Allocation is moved as a whole.
EXPECT_EQ(tracker.instances(), len);
EXPECT_EQ(tracker.live_instances(), len);
// Tests an implementation detail, don't rely on this in your code.
EXPECT_EQ(v.size(), 0); // NOLINT misc-use-after-move
EXPECT_EQ(tracker.copies(), 0);
EXPECT_EQ(tracker.moves(), 0);
} else {
EXPECT_EQ(tracker.instances(), len + len);
if (Instance::supports_move()) {
EXPECT_EQ(tracker.live_instances(), len);
EXPECT_EQ(tracker.copies(), 0);
EXPECT_EQ(tracker.moves(), len);
} else {
EXPECT_EQ(tracker.live_instances(), len + len);
EXPECT_EQ(tracker.copies(), len);
EXPECT_EQ(tracker.moves(), 0);
}
}
EXPECT_EQ(tracker.swaps(), 0);
}
}
}
TYPED_TEST_P(InstanceTest, CountConstructorsDestructorsOnAssignment) {
using Instance = TypeParam;
using InstanceVec = absl::InlinedVector<Instance, 8>;
InstanceTracker tracker;
for (int len = 0; len < 20; len++) {
SCOPED_TRACE(len);
for (int longorshort = 0; longorshort <= 1; ++longorshort) {
SCOPED_TRACE(longorshort);
tracker.ResetCopiesMovesSwaps();
InstanceVec longer, shorter;
for (int i = 0; i < len; i++) {
longer.push_back(Instance(i));
shorter.push_back(Instance(i));
}
longer.push_back(Instance(len));
EXPECT_EQ(tracker.instances(), len + len + 1);
EXPECT_GE(tracker.copies() + tracker.moves(),
len + len + 1); // More due to reallocation.
tracker.ResetCopiesMovesSwaps();
if (longorshort) {
shorter = longer;
EXPECT_EQ(tracker.instances(), (len + 1) + (len + 1));
EXPECT_GE(tracker.copies() + tracker.moves(),
len + 1); // More due to reallocation.
} else {
longer = shorter;
EXPECT_EQ(tracker.instances(), len + len);
EXPECT_EQ(tracker.copies() + tracker.moves(), len);
}
}
}
}
TYPED_TEST_P(InstanceTest, CountConstructorsDestructorsOnMoveAssignment) {
using Instance = TypeParam;
using InstanceVec = absl::InlinedVector<Instance, 8>;
InstanceTracker tracker;
for (int len = 0; len < 20; len++) {
SCOPED_TRACE(len);
for (int longorshort = 0; longorshort <= 1; ++longorshort) {
SCOPED_TRACE(longorshort);
tracker.ResetCopiesMovesSwaps();
InstanceVec longer, shorter;
const int inlined_capacity = longer.capacity();
for (int i = 0; i < len; i++) {
longer.push_back(Instance(i));
shorter.push_back(Instance(i));
}
longer.push_back(Instance(len));
EXPECT_EQ(tracker.instances(), len + len + 1);
EXPECT_GE(tracker.copies() + tracker.moves(),
len + len + 1); // More due to reallocation.
tracker.ResetCopiesMovesSwaps();
int src_len;
if (longorshort) {
src_len = len + 1;
shorter = std::move(longer);
} else {
src_len = len;
longer = std::move(shorter);
}
if (src_len > inlined_capacity) {
// Allocation moved as a whole.
EXPECT_EQ(tracker.instances(), src_len);
EXPECT_EQ(tracker.live_instances(), src_len);
EXPECT_EQ(tracker.copies(), 0);
EXPECT_EQ(tracker.moves(), 0);
} else {
// Elements are all copied.
EXPECT_EQ(tracker.instances(), src_len + src_len);
if (Instance::supports_move()) {
EXPECT_EQ(tracker.copies(), 0);
EXPECT_EQ(tracker.moves(), src_len);
EXPECT_EQ(tracker.live_instances(), src_len);
} else {
EXPECT_EQ(tracker.copies(), src_len);
EXPECT_EQ(tracker.moves(), 0);
EXPECT_EQ(tracker.live_instances(), src_len + src_len);
}
}
EXPECT_EQ(tracker.swaps(), 0);
}
}
}
TEST(CountElemAssign, SimpleTypeWithInlineBacking) {
for (size_t original_size = 0; original_size <= 5; ++original_size) {
SCOPED_TRACE(original_size);
// Original contents are [12345, 12345, ...]
std::vector<int> original_contents(original_size, 12345);
absl::InlinedVector<int, 2> v(original_contents.begin(),
original_contents.end());
v.assign(2, 123);
EXPECT_THAT(v, AllOf(SizeIs(2), ElementsAre(123, 123)));
if (original_size <= 2) {
// If the original had inline backing, it should stay inline.
EXPECT_EQ(2, v.capacity());
}
}
}
TEST(CountElemAssign, SimpleTypeWithAllocation) {
for (size_t original_size = 0; original_size <= 5; ++original_size) {
SCOPED_TRACE(original_size);
// Original contents are [12345, 12345, ...]
std::vector<int> original_contents(original_size, 12345);
absl::InlinedVector<int, 2> v(original_contents.begin(),
original_contents.end());
v.assign(3, 123);
EXPECT_THAT(v, AllOf(SizeIs(3), ElementsAre(123, 123, 123)));
EXPECT_LE(v.size(), v.capacity());
}
}
TYPED_TEST_P(InstanceTest, CountElemAssignInlineBacking) {
using Instance = TypeParam;
for (size_t original_size = 0; original_size <= 5; ++original_size) {
SCOPED_TRACE(original_size);
// Original contents are [12345, 12345, ...]
std::vector<Instance> original_contents(original_size, Instance(12345));
absl::InlinedVector<Instance, 2> v(original_contents.begin(),
original_contents.end());
v.assign(2, Instance(123));
EXPECT_THAT(v, AllOf(SizeIs(2), ElementsAre(ValueIs(123), ValueIs(123))));
if (original_size <= 2) {
// If the original had inline backing, it should stay inline.
EXPECT_EQ(2, v.capacity());
}
}
}
template <typename Instance>
void InstanceCountElemAssignWithAllocationTest() {
for (size_t original_size = 0; original_size <= 5; ++original_size) {
SCOPED_TRACE(original_size);
// Original contents are [12345, 12345, ...]
std::vector<Instance> original_contents(original_size, Instance(12345));
absl::InlinedVector<Instance, 2> v(original_contents.begin(),
original_contents.end());
v.assign(3, Instance(123));
EXPECT_THAT(v, AllOf(SizeIs(3), ElementsAre(ValueIs(123), ValueIs(123),
ValueIs(123))));
2017-09-19 22:54:40 +02:00
EXPECT_LE(v.size(), v.capacity());
}
}
TEST(CountElemAssign, WithAllocationCopyableInstance) {
InstanceCountElemAssignWithAllocationTest<CopyableOnlyInstance>();
}
TEST(CountElemAssign, WithAllocationCopyableMovableInstance) {
InstanceCountElemAssignWithAllocationTest<CopyableMovableInstance>();
}
TEST(RangedConstructor, SimpleType) {
std::vector<int> source_v = {4, 5, 6};
// First try to fit in inline backing
absl::InlinedVector<int, 4> v(source_v.begin(), source_v.end());
EXPECT_EQ(3, v.size());
EXPECT_EQ(4, v.capacity()); // Indication that we're still on inlined storage
EXPECT_EQ(4, v[0]);
EXPECT_EQ(5, v[1]);
EXPECT_EQ(6, v[2]);
// Now, force a re-allocate
absl::InlinedVector<int, 2> realloc_v(source_v.begin(), source_v.end());
EXPECT_EQ(3, realloc_v.size());
EXPECT_LT(2, realloc_v.capacity());
EXPECT_EQ(4, realloc_v[0]);
EXPECT_EQ(5, realloc_v[1]);
EXPECT_EQ(6, realloc_v[2]);
}
// Test for ranged constructors using Instance as the element type and
// SourceContainer as the source container type.
template <typename Instance, typename SourceContainer, int inlined_capacity>
void InstanceRangedConstructorTestForContainer() {
InstanceTracker tracker;
SourceContainer source_v = {Instance(0), Instance(1)};
tracker.ResetCopiesMovesSwaps();
absl::InlinedVector<Instance, inlined_capacity> v(source_v.begin(),
source_v.end());
EXPECT_EQ(2, v.size());
EXPECT_LT(1, v.capacity());
EXPECT_EQ(0, v[0].value());
EXPECT_EQ(1, v[1].value());
EXPECT_EQ(tracker.copies(), 2);
EXPECT_EQ(tracker.moves(), 0);
}
template <typename Instance, int inlined_capacity>
void InstanceRangedConstructorTestWithCapacity() {
// Test with const and non-const, random access and non-random-access sources.
// TODO(bsamwel): Test with an input iterator source.
{
SCOPED_TRACE("std::list");
InstanceRangedConstructorTestForContainer<Instance, std::list<Instance>,
inlined_capacity>();
{
SCOPED_TRACE("const std::list");
InstanceRangedConstructorTestForContainer<
Instance, const std::list<Instance>, inlined_capacity>();
}
{
SCOPED_TRACE("std::vector");
InstanceRangedConstructorTestForContainer<Instance, std::vector<Instance>,
inlined_capacity>();
}
{
SCOPED_TRACE("const std::vector");
InstanceRangedConstructorTestForContainer<
Instance, const std::vector<Instance>, inlined_capacity>();
}
}
}
TYPED_TEST_P(InstanceTest, RangedConstructor) {
using Instance = TypeParam;
SCOPED_TRACE("capacity=1");
InstanceRangedConstructorTestWithCapacity<Instance, 1>();
SCOPED_TRACE("capacity=2");
InstanceRangedConstructorTestWithCapacity<Instance, 2>();
}
TEST(RangedConstructor, ElementsAreConstructed) {
std::vector<std::string> source_v = {"cat", "dog"};
// Force expansion and re-allocation of v. Ensures that when the vector is
// expanded that new elements are constructed.
absl::InlinedVector<std::string, 1> v(source_v.begin(), source_v.end());
EXPECT_EQ("cat", v[0]);
EXPECT_EQ("dog", v[1]);
}
TEST(RangedAssign, SimpleType) {
// Test for all combinations of original sizes (empty and non-empty inline,
// and out of line) and target sizes.
for (size_t original_size = 0; original_size <= 5; ++original_size) {
SCOPED_TRACE(original_size);
// Original contents are [12345, 12345, ...]
std::vector<int> original_contents(original_size, 12345);
for (size_t target_size = 0; target_size <= 5; ++target_size) {
SCOPED_TRACE(target_size);
// New contents are [3, 4, ...]
std::vector<int> new_contents;
for (size_t i = 0; i < target_size; ++i) {
new_contents.push_back(i + 3);
}
absl::InlinedVector<int, 3> v(original_contents.begin(),
original_contents.end());
v.assign(new_contents.begin(), new_contents.end());
EXPECT_EQ(new_contents.size(), v.size());
EXPECT_LE(new_contents.size(), v.capacity());
if (target_size <= 3 && original_size <= 3) {
// Storage should stay inline when target size is small.
EXPECT_EQ(3, v.capacity());
}
EXPECT_THAT(v, ElementsAreArray(new_contents));
}
}
}
// Returns true if lhs and rhs have the same value.
template <typename Instance>
static bool InstanceValuesEqual(const Instance& lhs, const Instance& rhs) {
return lhs.value() == rhs.value();
}
// Test for ranged assign() using Instance as the element type and
// SourceContainer as the source container type.
template <typename Instance, typename SourceContainer>
void InstanceRangedAssignTestForContainer() {
// Test for all combinations of original sizes (empty and non-empty inline,
// and out of line) and target sizes.
for (size_t original_size = 0; original_size <= 5; ++original_size) {
SCOPED_TRACE(original_size);
// Original contents are [12345, 12345, ...]
std::vector<Instance> original_contents(original_size, Instance(12345));
for (size_t target_size = 0; target_size <= 5; ++target_size) {
SCOPED_TRACE(target_size);
// New contents are [3, 4, ...]
// Generate data using a non-const container, because SourceContainer
// itself may be const.
// TODO(bsamwel): Test with an input iterator.
std::vector<Instance> new_contents_in;
for (size_t i = 0; i < target_size; ++i) {
new_contents_in.push_back(Instance(i + 3));
}
SourceContainer new_contents(new_contents_in.begin(),
new_contents_in.end());
absl::InlinedVector<Instance, 3> v(original_contents.begin(),
original_contents.end());
v.assign(new_contents.begin(), new_contents.end());
EXPECT_EQ(new_contents.size(), v.size());
EXPECT_LE(new_contents.size(), v.capacity());
if (target_size <= 3 && original_size <= 3) {
// Storage should stay inline when target size is small.
EXPECT_EQ(3, v.capacity());
}
EXPECT_TRUE(std::equal(v.begin(), v.end(), new_contents.begin(),
InstanceValuesEqual<Instance>));
}
}
}
TYPED_TEST_P(InstanceTest, RangedAssign) {
using Instance = TypeParam;
// Test with const and non-const, random access and non-random-access sources.
// TODO(bsamwel): Test with an input iterator source.
SCOPED_TRACE("std::list");
InstanceRangedAssignTestForContainer<Instance, std::list<Instance>>();
SCOPED_TRACE("const std::list");
InstanceRangedAssignTestForContainer<Instance, const std::list<Instance>>();
SCOPED_TRACE("std::vector");
InstanceRangedAssignTestForContainer<Instance, std::vector<Instance>>();
SCOPED_TRACE("const std::vector");
InstanceRangedAssignTestForContainer<Instance, const std::vector<Instance>>();
}
TEST(InitializerListConstructor, SimpleTypeWithInlineBacking) {
EXPECT_THAT((absl::InlinedVector<int, 4>{4, 5, 6}),
AllOf(SizeIs(3), CapacityIs(4), ElementsAre(4, 5, 6)));
}
TEST(InitializerListConstructor, SimpleTypeWithReallocationRequired) {
EXPECT_THAT((absl::InlinedVector<int, 2>{4, 5, 6}),
AllOf(SizeIs(3), CapacityIs(Gt(2)), ElementsAre(4, 5, 6)));
}
TEST(InitializerListConstructor, DisparateTypesInList) {
EXPECT_THAT((absl::InlinedVector<int, 2>{-7, 8ULL}), ElementsAre(-7, 8));
EXPECT_THAT((absl::InlinedVector<std::string, 2>{"foo", std::string("bar")}),
ElementsAre("foo", "bar"));
}
TEST(InitializerListConstructor, ComplexTypeWithInlineBacking) {
EXPECT_THAT((absl::InlinedVector<CopyableMovableInstance, 1>{
CopyableMovableInstance(0)}),
AllOf(SizeIs(1), CapacityIs(1), ElementsAre(ValueIs(0))));
}
TEST(InitializerListConstructor, ComplexTypeWithReallocationRequired) {
EXPECT_THAT(
(absl::InlinedVector<CopyableMovableInstance, 1>{
CopyableMovableInstance(0), CopyableMovableInstance(1)}),
AllOf(SizeIs(2), CapacityIs(Gt(1)), ElementsAre(ValueIs(0), ValueIs(1))));
}
TEST(InitializerListAssign, SimpleTypeFitsInlineBacking) {
for (size_t original_size = 0; original_size <= 4; ++original_size) {
SCOPED_TRACE(original_size);
absl::InlinedVector<int, 2> v1(original_size, 12345);
const size_t original_capacity_v1 = v1.capacity();
v1.assign({3});
EXPECT_THAT(
v1, AllOf(SizeIs(1), CapacityIs(original_capacity_v1), ElementsAre(3)));
absl::InlinedVector<int, 2> v2(original_size, 12345);
const size_t original_capacity_v2 = v2.capacity();
v2 = {3};
EXPECT_THAT(
v2, AllOf(SizeIs(1), CapacityIs(original_capacity_v2), ElementsAre(3)));
}
}
TEST(InitializerListAssign, SimpleTypeDoesNotFitInlineBacking) {
for (size_t original_size = 0; original_size <= 4; ++original_size) {
SCOPED_TRACE(original_size);
absl::InlinedVector<int, 2> v1(original_size, 12345);
v1.assign({3, 4, 5});
EXPECT_THAT(v1, AllOf(SizeIs(3), ElementsAre(3, 4, 5)));
EXPECT_LE(3, v1.capacity());
absl::InlinedVector<int, 2> v2(original_size, 12345);
v2 = {3, 4, 5};
EXPECT_THAT(v2, AllOf(SizeIs(3), ElementsAre(3, 4, 5)));
EXPECT_LE(3, v2.capacity());
}
}
TEST(InitializerListAssign, DisparateTypesInList) {
absl::InlinedVector<int, 2> v_int1;
v_int1.assign({-7, 8ULL});
EXPECT_THAT(v_int1, ElementsAre(-7, 8));
absl::InlinedVector<int, 2> v_int2;
v_int2 = {-7, 8ULL};
EXPECT_THAT(v_int2, ElementsAre(-7, 8));
absl::InlinedVector<std::string, 2> v_string1;
v_string1.assign({"foo", std::string("bar")});
EXPECT_THAT(v_string1, ElementsAre("foo", "bar"));
absl::InlinedVector<std::string, 2> v_string2;
v_string2 = {"foo", std::string("bar")};
EXPECT_THAT(v_string2, ElementsAre("foo", "bar"));
}
TYPED_TEST_P(InstanceTest, InitializerListAssign) {
using Instance = TypeParam;
for (size_t original_size = 0; original_size <= 4; ++original_size) {
SCOPED_TRACE(original_size);
absl::InlinedVector<Instance, 2> v(original_size, Instance(12345));
const size_t original_capacity = v.capacity();
v.assign({Instance(3)});
EXPECT_THAT(v, AllOf(SizeIs(1), CapacityIs(original_capacity),
ElementsAre(ValueIs(3))));
}
for (size_t original_size = 0; original_size <= 4; ++original_size) {
SCOPED_TRACE(original_size);
absl::InlinedVector<Instance, 2> v(original_size, Instance(12345));
v.assign({Instance(3), Instance(4), Instance(5)});
EXPECT_THAT(
v, AllOf(SizeIs(3), ElementsAre(ValueIs(3), ValueIs(4), ValueIs(5))));
2017-09-19 22:54:40 +02:00
EXPECT_LE(3, v.capacity());
}
}
REGISTER_TYPED_TEST_CASE_P(InstanceTest, Swap, CountConstructorsDestructors,
CountConstructorsDestructorsOnCopyConstruction,
CountConstructorsDestructorsOnMoveConstruction,
CountConstructorsDestructorsOnAssignment,
CountConstructorsDestructorsOnMoveAssignment,
CountElemAssignInlineBacking, RangedConstructor,
RangedAssign, InitializerListAssign);
using InstanceTypes =
::testing::Types<CopyableOnlyInstance, CopyableMovableInstance>;
INSTANTIATE_TYPED_TEST_CASE_P(InstanceTestOnTypes, InstanceTest, InstanceTypes);
TEST(DynamicVec, DynamicVecCompiles) {
DynamicVec v;
(void)v;
}
TEST(AllocatorSupportTest, Constructors) {
using MyAlloc = CountingAllocator<int>;
using AllocVec = absl::InlinedVector<int, 4, MyAlloc>;
const int ia[] = {0, 1, 2, 3, 4, 5, 6, 7};
2017-09-19 22:54:40 +02:00
int64_t allocated = 0;
MyAlloc alloc(&allocated);
{ AllocVec ABSL_ATTRIBUTE_UNUSED v; }
{ AllocVec ABSL_ATTRIBUTE_UNUSED v(alloc); }
{ AllocVec ABSL_ATTRIBUTE_UNUSED v(ia, ia + ABSL_ARRAYSIZE(ia), alloc); }
{ AllocVec ABSL_ATTRIBUTE_UNUSED v({1, 2, 3}, alloc); }
AllocVec v2;
{ AllocVec ABSL_ATTRIBUTE_UNUSED v(v2, alloc); }
{ AllocVec ABSL_ATTRIBUTE_UNUSED v(std::move(v2), alloc); }
}
TEST(AllocatorSupportTest, CountAllocations) {
using MyAlloc = CountingAllocator<int>;
using AllocVec = absl::InlinedVector<int, 4, MyAlloc>;
const int ia[] = {0, 1, 2, 3, 4, 5, 6, 7};
2017-09-19 22:54:40 +02:00
int64_t allocated = 0;
MyAlloc alloc(&allocated);
{
AllocVec ABSL_ATTRIBUTE_UNUSED v(ia, ia + 4, alloc);
EXPECT_THAT(allocated, 0);
}
EXPECT_THAT(allocated, 0);
{
AllocVec ABSL_ATTRIBUTE_UNUSED v(ia, ia + ABSL_ARRAYSIZE(ia), alloc);
EXPECT_THAT(allocated, v.size() * sizeof(int));
}
EXPECT_THAT(allocated, 0);
{
AllocVec v(4, 1, alloc);
EXPECT_THAT(allocated, 0);
int64_t allocated2 = 0;
MyAlloc alloc2(&allocated2);
AllocVec v2(v, alloc2);
EXPECT_THAT(allocated2, 0);
int64_t allocated3 = 0;
MyAlloc alloc3(&allocated3);
AllocVec v3(std::move(v), alloc3);
EXPECT_THAT(allocated3, 0);
}
EXPECT_THAT(allocated, 0);
{
AllocVec v(8, 2, alloc);
EXPECT_THAT(allocated, v.size() * sizeof(int));
int64_t allocated2 = 0;
MyAlloc alloc2(&allocated2);
AllocVec v2(v, alloc2);
EXPECT_THAT(allocated2, v2.size() * sizeof(int));
int64_t allocated3 = 0;
MyAlloc alloc3(&allocated3);
AllocVec v3(std::move(v), alloc3);
EXPECT_THAT(allocated3, v3.size() * sizeof(int));
}
EXPECT_EQ(allocated, 0);
{
// Test shrink_to_fit deallocations.
AllocVec v(8, 2, alloc);
EXPECT_EQ(allocated, 8 * sizeof(int));
v.resize(5);
EXPECT_EQ(allocated, 8 * sizeof(int));
v.shrink_to_fit();
EXPECT_EQ(allocated, 5 * sizeof(int));
v.resize(4);
EXPECT_EQ(allocated, 5 * sizeof(int));
v.shrink_to_fit();
EXPECT_EQ(allocated, 0);
}
2017-09-19 22:54:40 +02:00
}
TEST(AllocatorSupportTest, SwapBothAllocated) {
using MyAlloc = CountingAllocator<int>;
using AllocVec = absl::InlinedVector<int, 4, MyAlloc>;
int64_t allocated1 = 0;
int64_t allocated2 = 0;
{
const int ia1[] = {0, 1, 2, 3, 4, 5, 6, 7};
const int ia2[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
2017-09-19 22:54:40 +02:00
MyAlloc a1(&allocated1);
MyAlloc a2(&allocated2);
AllocVec v1(ia1, ia1 + ABSL_ARRAYSIZE(ia1), a1);
AllocVec v2(ia2, ia2 + ABSL_ARRAYSIZE(ia2), a2);
EXPECT_LT(v1.capacity(), v2.capacity());
EXPECT_THAT(allocated1, v1.capacity() * sizeof(int));
EXPECT_THAT(allocated2, v2.capacity() * sizeof(int));
v1.swap(v2);
EXPECT_THAT(v1, ElementsAreArray(ia2));
EXPECT_THAT(v2, ElementsAreArray(ia1));
EXPECT_THAT(allocated1, v2.capacity() * sizeof(int));
EXPECT_THAT(allocated2, v1.capacity() * sizeof(int));
}
EXPECT_THAT(allocated1, 0);
EXPECT_THAT(allocated2, 0);
}
TEST(AllocatorSupportTest, SwapOneAllocated) {
using MyAlloc = CountingAllocator<int>;
using AllocVec = absl::InlinedVector<int, 4, MyAlloc>;
int64_t allocated1 = 0;
int64_t allocated2 = 0;
{
const int ia1[] = {0, 1, 2, 3, 4, 5, 6, 7};
const int ia2[] = {0, 1, 2, 3};
2017-09-19 22:54:40 +02:00
MyAlloc a1(&allocated1);
MyAlloc a2(&allocated2);
AllocVec v1(ia1, ia1 + ABSL_ARRAYSIZE(ia1), a1);
AllocVec v2(ia2, ia2 + ABSL_ARRAYSIZE(ia2), a2);
EXPECT_THAT(allocated1, v1.capacity() * sizeof(int));
EXPECT_THAT(allocated2, 0);
v1.swap(v2);
EXPECT_THAT(v1, ElementsAreArray(ia2));
EXPECT_THAT(v2, ElementsAreArray(ia1));
EXPECT_THAT(allocated1, v2.capacity() * sizeof(int));
EXPECT_THAT(allocated2, 0);
EXPECT_TRUE(v2.get_allocator() == a1);
EXPECT_TRUE(v1.get_allocator() == a2);
}
EXPECT_THAT(allocated1, 0);
EXPECT_THAT(allocated2, 0);
}
TEST(AllocatorSupportTest, ScopedAllocatorWorksInlined) {
2017-09-19 22:54:40 +02:00
using StdVector = std::vector<int, CountingAllocator<int>>;
using Alloc = CountingAllocator<StdVector>;
using ScopedAlloc = std::scoped_allocator_adaptor<Alloc>;
using AllocVec = absl::InlinedVector<StdVector, 1, ScopedAlloc>;
Export of internal Abseil changes. -- c321829735accc2e6beb81e6a5a4421e5647b876 by CJ Johnson <johnsoncj@google.com>: Updates the definition of InlinedVector::swap(InlinedVector&) to be exception safe and adds exception safety tests PiperOrigin-RevId: 255511536 -- 0d86445891748efb09430eb9ede267b54185a246 by CJ Johnson <johnsoncj@google.com>: Updates the definition of InlinedVector::erase(...) to be exception safe and adds an exception safety test for it. PiperOrigin-RevId: 255492671 -- f07e8fa62dfe9eb0d025b27fca8c6db43c5a328f by CJ Johnson <johnsoncj@google.com>: Updates the implementation of InlinedVector::emplace_back(...) to be exception safe and adds exception safety tests PiperOrigin-RevId: 255422837 -- 4c3be92bfe4c1636a03cef8fd5aa802fed0d2c61 by Abseil Team <absl-team@google.com>: Internal Change PiperOrigin-RevId: 255422693 -- 6df38ea42f00678c357a539016163f8ac4c084e6 by Gennadiy Rozental <rogeeff@google.com>: Introduce public interfaces for setting and getting program usage messages. PiperOrigin-RevId: 255291467 -- 8f21d594aed3971d37db70226847c693eb548edb by Laramie Leavitt <lar@google.com>: Move absl/random's copy of ABSL_ATTRIBUTE_FORCE_INLINE and ABSL_ATTRIBUTE_NEVER_INLINE into .cc files and rename to prevent conflicts. https://github.com/abseil/abseil-cpp/issues/343 PiperOrigin-RevId: 255288599 -- 6b7430ad0c8bd860fb9394894f5eeedd1acc9f77 by CJ Johnson <johnsoncj@google.com>: Updates the ScopedAllocatorWorks test for InlinedVector to not rely on the byte count allocated by the standard library In doing so, removes LegacyNextCapacityFrom(...) impl function from InlinedVector Also applies clang-format to the test file PiperOrigin-RevId: 255207606 GitOrigin-RevId: c321829735accc2e6beb81e6a5a4421e5647b876 Change-Id: I7438211c36c4549fca2e866658f8d579c65d7d52
2019-06-28 02:24:26 +02:00
int64_t total_allocated_byte_count = 0;
Export of internal Abseil changes. -- c321829735accc2e6beb81e6a5a4421e5647b876 by CJ Johnson <johnsoncj@google.com>: Updates the definition of InlinedVector::swap(InlinedVector&) to be exception safe and adds exception safety tests PiperOrigin-RevId: 255511536 -- 0d86445891748efb09430eb9ede267b54185a246 by CJ Johnson <johnsoncj@google.com>: Updates the definition of InlinedVector::erase(...) to be exception safe and adds an exception safety test for it. PiperOrigin-RevId: 255492671 -- f07e8fa62dfe9eb0d025b27fca8c6db43c5a328f by CJ Johnson <johnsoncj@google.com>: Updates the implementation of InlinedVector::emplace_back(...) to be exception safe and adds exception safety tests PiperOrigin-RevId: 255422837 -- 4c3be92bfe4c1636a03cef8fd5aa802fed0d2c61 by Abseil Team <absl-team@google.com>: Internal Change PiperOrigin-RevId: 255422693 -- 6df38ea42f00678c357a539016163f8ac4c084e6 by Gennadiy Rozental <rogeeff@google.com>: Introduce public interfaces for setting and getting program usage messages. PiperOrigin-RevId: 255291467 -- 8f21d594aed3971d37db70226847c693eb548edb by Laramie Leavitt <lar@google.com>: Move absl/random's copy of ABSL_ATTRIBUTE_FORCE_INLINE and ABSL_ATTRIBUTE_NEVER_INLINE into .cc files and rename to prevent conflicts. https://github.com/abseil/abseil-cpp/issues/343 PiperOrigin-RevId: 255288599 -- 6b7430ad0c8bd860fb9394894f5eeedd1acc9f77 by CJ Johnson <johnsoncj@google.com>: Updates the ScopedAllocatorWorks test for InlinedVector to not rely on the byte count allocated by the standard library In doing so, removes LegacyNextCapacityFrom(...) impl function from InlinedVector Also applies clang-format to the test file PiperOrigin-RevId: 255207606 GitOrigin-RevId: c321829735accc2e6beb81e6a5a4421e5647b876 Change-Id: I7438211c36c4549fca2e866658f8d579c65d7d52
2019-06-28 02:24:26 +02:00
AllocVec inlined_case(ScopedAlloc(Alloc(+&total_allocated_byte_count)));
// Called only once to remain inlined
inlined_case.emplace_back();
int64_t absl_responsible_for_count = total_allocated_byte_count;
// MSVC's allocator preemptively allocates in debug mode
#if !defined(_MSC_VER)
EXPECT_EQ(absl_responsible_for_count, 0);
#endif // !defined(_MSC_VER)
inlined_case[0].emplace_back();
EXPECT_GT(total_allocated_byte_count, absl_responsible_for_count);
inlined_case.clear();
inlined_case.shrink_to_fit();
EXPECT_EQ(total_allocated_byte_count, 0);
}
TEST(AllocatorSupportTest, ScopedAllocatorWorksAllocated) {
using StdVector = std::vector<int, CountingAllocator<int>>;
using Alloc = CountingAllocator<StdVector>;
using ScopedAlloc = std::scoped_allocator_adaptor<Alloc>;
using AllocVec = absl::InlinedVector<StdVector, 1, ScopedAlloc>;
int64_t total_allocated_byte_count = 0;
AllocVec allocated_case(ScopedAlloc(Alloc(+&total_allocated_byte_count)));
// Called twice to force into being allocated
allocated_case.emplace_back();
allocated_case.emplace_back();
int64_t absl_responsible_for_count = total_allocated_byte_count;
EXPECT_GT(absl_responsible_for_count, 0);
allocated_case[1].emplace_back();
EXPECT_GT(total_allocated_byte_count, absl_responsible_for_count);
allocated_case.clear();
allocated_case.shrink_to_fit();
EXPECT_EQ(total_allocated_byte_count, 0);
2017-09-19 22:54:40 +02:00
}
TEST(AllocatorSupportTest, SizeAllocConstructor) {
constexpr int inlined_size = 4;
using Alloc = CountingAllocator<int>;
using AllocVec = absl::InlinedVector<int, inlined_size, Alloc>;
{
auto len = inlined_size / 2;
int64_t allocated = 0;
auto v = AllocVec(len, Alloc(&allocated));
// Inline storage used; allocator should not be invoked
EXPECT_THAT(allocated, 0);
EXPECT_THAT(v, AllOf(SizeIs(len), Each(0)));
}
{
auto len = inlined_size * 2;
int64_t allocated = 0;
auto v = AllocVec(len, Alloc(&allocated));
// Out of line storage used; allocation of 8 elements expected
EXPECT_THAT(allocated, len * sizeof(int));
EXPECT_THAT(v, AllOf(SizeIs(len), Each(0)));
}
}
Export of internal Abseil changes. -- 1c1d6e2404dfc6caa022b335df5acdac6da50fe1 by Derek Mauro <dmauro@google.com>: Fix the internal namespacing in unaligned_access.h PiperOrigin-RevId: 215434506 -- 17d4400aebf025a230690fc1c7a968ef8d85bbba by Eric Fiselier <ericwf@google.com>: gtest depends on the GCC extension allowing variadic macros to be passed a empty parameter pack for ..., but LLVM diagnoses this as a GNU extension. This patch suppresses the warning when building the absl tests. PiperOrigin-RevId: 215426161 -- f2c49dde23a9f445b9de963f1bbe840ebb568b30 by Eric Fiselier <ericwf@google.com>: Use EXPECT_DEATH_IF_SUPPORTED instead of EXPECT_DEATH. This avoids breaking the test when gtest doesn't support death tests. PiperOrigin-RevId: 215423849 -- cd687c1e121709603f4fc3726b534f6a9c52cc89 by Eric Fiselier <ericwf@google.com>: Disable LLVM's -Wmissing-variable-declarations in tests. GCC's configuration already disables this via -Wno-missing-declarations, this change makes LLVM do the same. The warning would otherwise flag most tests which use ABSL_FLAG. PiperOrigin-RevId: 215407429 -- d14098824c84e3a8c8f6fb920e0335fb48fe2010 by Eric Fiselier <ericwf@google.com>: Fix local variable shadowing in city hash implementation. PiperOrigin-RevId: 215407249 -- 4b5e140ba743f0d231790a26c49083abb4329e2c by Abseil Team <absl-team@google.com>: Make raw_hash_set::reserve 2X fast when reserve doesn't do any allocation. Make raw_hash_set::reserve ~1% faster when reserve does some (128~4k) allocation. PiperOrigin-RevId: 215348727 -- 461161e65e04b801480aa117af2534c594654ccf by Eric Fiselier <ericwf@google.com>: Internal change PiperOrigin-RevId: 215272283 -- 50413ae31ad3d3a177257416acd8ede47a17bff2 by Eric Fiselier <ericwf@google.com>: Internal Change PiperOrigin-RevId: 215233183 -- 477be54c43d61019a8fe4e190e340eb52737d383 by Abseil Team <absl-team@google.com>: Clarify misleading comment on ABSL_ATTRIBUTE_UNUSED PiperOrigin-RevId: 215185496 -- 2cafa2b5287507d3a946682aee9ab13af6d471c9 by Matt Kulukundis <kfm@google.com>: Add support for absl::Hash to various absl in types. PiperOrigin-RevId: 215039569 -- 082248901991aa3d29be0ea3689c7f213cf0fd83 by Derek Mauro <dmauro@google.com>: Remove an instance of HAS_GLOBAL_STRING from hash_function_defaults.h PiperOrigin-RevId: 214989094 -- b929f61907f0786a6133e3a9d7287e339c0a0acb by Derek Mauro <dmauro@google.com>: Internal import of Github #174 Fix code snippet in comment https://github.com/abseil/abseil-cpp/pull/174 PiperOrigin-RevId: 214958849 -- f2c5e829eca11c352e121f56eefbf87083305023 by Derek Mauro <dmauro@google.com>: Internal import of GitHub #173 Fix CMake build for absl::container. https://github.com/abseil/abseil-cpp/pull/173 PiperOrigin-RevId: 214957796 -- d704f860f9fddafb99e34e6c5032e49f73874e10 by Abseil Team <absl-team@google.com>: Internal change PiperOrigin-RevId: 214828181 GitOrigin-RevId: 1c1d6e2404dfc6caa022b335df5acdac6da50fe1 Change-Id: I551de2b1ba0cbaf6856cd5959358cf6651179dea
2018-10-02 21:09:18 +02:00
Export of internal Abseil changes -- 90ecacd2a3db96ee64ef23af37a80fad404e2b32 by Gennadiy Rozental <rogeeff@google.com>: Fixes MSVC regression by making MSVC version of class Flag into an aggregate type. PiperOrigin-RevId: 277767054 -- 018f3b040df51d91a988fa146fee163721e605e9 by Abseil Team <absl-team@google.com>: Change libstdc++ lacking std::unique_ptr check from a gcc version check to based on feature macros. PiperOrigin-RevId: 277736042 -- 475844775ae343e2414318f08549ee3fa6676a8d by CJ Johnson <johnsoncj@google.com>: Pass allocator_type through allocator_traits before extracting the typedefs PiperOrigin-RevId: 277730393 -- d843bc4bc30bf5b11af76db8beda8634b6111a62 by Abseil Team <absl-team@google.com>: Convert the Waiter::Init() method to the default constructor and define a destructor for the Waiter class. Use placement new and delete with Waiter objects. PiperOrigin-RevId: 277728823 -- 1ba6edf421dd2dfe13c55970a03c99592cb6677d by Derek Mauro <dmauro@google.com>: Use lowercase spelling for include of dbghelp.h When cross-compiling under MinGW this is important PiperOrigin-RevId: 277629783 -- cfc662a6fa357a84ddda8037156c7f26cee40c36 by Abseil Team <absl-team@google.com>: Don't use atomic ops on waiter and wakeup counts in WIN32 waiter mode. Port the new CONDVAR waiter mode code in CL 277366017 to the WIN32 waiter mode. PiperOrigin-RevId: 277603611 -- 833106542e61fa0832900adf3c1b2afc6890b94b by Abseil Team <absl-team@google.com>: Add the PerThreadSem::Destroy() method. For ABSL_WAITER_MODE_CONDVAR or ABSL_WAITER_MODE_SEM, PerThreadSem::Destroy() is used to destroy the pthread mutex and condition variable or the POSIX semaphore. PiperOrigin-RevId: 277586675 -- 7814da4a59106cf1e0e4db1a31b9592ebbd2094b by Samuel Benzaquen <sbenza@google.com>: Enable the assertion in the iterator's operator* and operator-> PiperOrigin-RevId: 277563401 GitOrigin-RevId: 90ecacd2a3db96ee64ef23af37a80fad404e2b32 Change-Id: Ib19be3680da74f0b94055c9039115ec6bcaea7b0
2019-10-31 19:37:35 +01:00
TEST(InlinedVectorTest, MinimumAllocatorCompilesUsingTraits) {
using T = int;
using A = std::allocator<T>;
using ATraits = absl::allocator_traits<A>;
struct MinimumAllocator {
using value_type = T;
value_type* allocate(size_t n) {
A a;
return ATraits::allocate(a, n);
}
void deallocate(value_type* p, size_t n) {
A a;
ATraits::deallocate(a, p, n);
}
};
absl::InlinedVector<T, 1, MinimumAllocator> vec;
vec.emplace_back();
vec.resize(0);
}
Export of internal Abseil changes. -- 5da9755667df37e38ccaf6938c9f408e294110bb by Shaindel Schwartz <shaindel@google.com>: Import of CCTZ from GitHub. PiperOrigin-RevId: 232942734 -- b6fb275769c66fdd2bd92b119198c59e9a7dd737 by Samuel Benzaquen <sbenza@google.com>: Fix integral underflow when from-arg width is INT_MIN. PiperOrigin-RevId: 232888037 -- 4135dbba4a26c4642277fc2a7e2a833d593daa1c by Abseil Team <absl-team@google.com>: Add the insert_return_type alias to raw_hash_set. PiperOrigin-RevId: 232683892 -- 0b120b7d3693800bbb886f6fc607ae54a9338cb1 by Abseil Team <absl-team@google.com>: Macros to detect and disabled SafeStack https://clang.llvm.org/docs/SafeStack.html PiperOrigin-RevId: 232680114 -- a77b3fb533a9e37966d1d6ef5ccd09c73fff2ca1 by Abseil Team <absl-team@google.com>: Avoid potential red zone clobber Pushing on the stack on x86-64 may clobber local variables held below %rsp in the red zone. Avoid this by using lea on x86-64. PiperOrigin-RevId: 232592478 -- bf326a0eefa92f4e704287563df0c5a5b1873b6d by Eric Fiselier <ericwf@google.com>: Add additional tests for AbslHashValue. PiperOrigin-RevId: 232344325 -- 816e4f98fd7632c944c779db87b7dac4e138afcf by Eric Fiselier <ericwf@google.com>: Avoid upcoming GCC 9.0 warnings about base class init. Currently, in trunk, GCC has a new warning under -Wextra that diagnoses when a derived class fails to explicitly initialize the base class in a constructor initializer list. This patch avoids this warning. PiperOrigin-RevId: 232327626 -- 779c0f44b3c2b7a04d4bdf978641eb8180515bf6 by Eric Fiselier <ericwf@google.com>: Guard against C++2a char8_t change. PiperOrigin-RevId: 232326178 -- 41e5395b85bbbfb5bf418cc21b04ad4ccb15a284 by Eric Fiselier <ericwf@google.com>: Avoid Clang Warning PiperOrigin-RevId: 232138866 GitOrigin-RevId: 5da9755667df37e38ccaf6938c9f408e294110bb Change-Id: I49ee4f58db177b81b039d7d949f671c97c5a7933
2019-02-07 23:13:06 +01:00
TEST(InlinedVectorTest, AbslHashValueWorks) {
using V = absl::InlinedVector<int, 4>;
std::vector<V> cases;
// Generate a variety of vectors some of these are small enough for the inline
// space but are stored out of line.
for (int i = 0; i < 10; ++i) {
V v;
for (int j = 0; j < i; ++j) {
v.push_back(j);
}
cases.push_back(v);
v.resize(i % 4);
cases.push_back(v);
}
EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(cases));
}
2017-09-19 22:54:40 +02:00
} // anonymous namespace