// Copyright 2018 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 "absl/container/internal/container_memory.h" #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/strings/string_view.h" namespace absl { ABSL_NAMESPACE_BEGIN namespace container_internal { namespace { using ::testing::Pair; TEST(Memory, AlignmentLargerThanBase) { std::allocator alloc; void* mem = Allocate<2>(&alloc, 3); EXPECT_EQ(0, reinterpret_cast(mem) % 2); memcpy(mem, "abc", 3); Deallocate<2>(&alloc, mem, 3); } TEST(Memory, AlignmentSmallerThanBase) { std::allocator alloc; void* mem = Allocate<2>(&alloc, 3); EXPECT_EQ(0, reinterpret_cast(mem) % 2); memcpy(mem, "abc", 3); Deallocate<2>(&alloc, mem, 3); } class Fixture : public ::testing::Test { using Alloc = std::allocator; public: Fixture() { ptr_ = std::allocator_traits::allocate(*alloc(), 1); } ~Fixture() override { std::allocator_traits::destroy(*alloc(), ptr_); std::allocator_traits::deallocate(*alloc(), ptr_, 1); } std::string* ptr() { return ptr_; } Alloc* alloc() { return &alloc_; } private: Alloc alloc_; std::string* ptr_; }; TEST_F(Fixture, ConstructNoArgs) { ConstructFromTuple(alloc(), ptr(), std::forward_as_tuple()); EXPECT_EQ(*ptr(), ""); } TEST_F(Fixture, ConstructOneArg) { ConstructFromTuple(alloc(), ptr(), std::forward_as_tuple("abcde")); EXPECT_EQ(*ptr(), "abcde"); } TEST_F(Fixture, ConstructTwoArg) { ConstructFromTuple(alloc(), ptr(), std::forward_as_tuple(5, 'a')); EXPECT_EQ(*ptr(), "aaaaa"); } TEST(PairArgs, NoArgs) { EXPECT_THAT(PairArgs(), Pair(std::forward_as_tuple(), std::forward_as_tuple())); } TEST(PairArgs, TwoArgs) { EXPECT_EQ( std::make_pair(std::forward_as_tuple(1), std::forward_as_tuple('A')), PairArgs(1, 'A')); } TEST(PairArgs, Pair) { EXPECT_EQ( std::make_pair(std::forward_as_tuple(1), std::forward_as_tuple('A')), PairArgs(std::make_pair(1, 'A'))); } TEST(PairArgs, Piecewise) { EXPECT_EQ( std::make_pair(std::forward_as_tuple(1), std::forward_as_tuple('A')), PairArgs(std::piecewise_construct, std::forward_as_tuple(1), std::forward_as_tuple('A'))); } TEST(WithConstructed, Simple) { EXPECT_EQ(1, WithConstructed( std::make_tuple(std::string("a")), [](absl::string_view str) { return str.size(); })); } template decltype(DecomposeValue(std::declval(), std::declval())) DecomposeValueImpl(int, F&& f, Arg&& arg) { return DecomposeValue(std::forward(f), std::forward(arg)); } template const char* DecomposeValueImpl(char, F&& f, Arg&& arg) { return "not decomposable"; } template decltype(DecomposeValueImpl(0, std::declval(), std::declval())) TryDecomposeValue(F&& f, Arg&& arg) { return DecomposeValueImpl(0, std::forward(f), std::forward(arg)); } TEST(DecomposeValue, Decomposable) { auto f = [](const int& x, int&& y) { EXPECT_EQ(&x, &y); EXPECT_EQ(42, x); return 'A'; }; EXPECT_EQ('A', TryDecomposeValue(f, 42)); } TEST(DecomposeValue, NotDecomposable) { auto f = [](void*) { ADD_FAILURE() << "Must not be called"; return 'A'; }; EXPECT_STREQ("not decomposable", TryDecomposeValue(f, 42)); } template decltype(DecomposePair(std::declval(), std::declval()...)) DecomposePairImpl(int, F&& f, Args&&... args) { return DecomposePair(std::forward(f), std::forward(args)...); } template const char* DecomposePairImpl(char, F&& f, Args&&... args) { return "not decomposable"; } template decltype(DecomposePairImpl(0, std::declval(), std::declval()...)) TryDecomposePair(F&& f, Args&&... args) { return DecomposePairImpl(0, std::forward(f), std::forward(args)...); } TEST(DecomposePair, Decomposable) { auto f = [](const int& x, std::piecewise_construct_t, std::tuple k, std::tuple&& v) { EXPECT_EQ(&x, &std::get<0>(k)); EXPECT_EQ(42, x); EXPECT_EQ(0.5, std::get<0>(v)); return 'A'; }; EXPECT_EQ('A', TryDecomposePair(f, 42, 0.5)); EXPECT_EQ('A', TryDecomposePair(f, std::make_pair(42, 0.5))); EXPECT_EQ('A', TryDecomposePair(f, std::piecewise_construct, std::make_tuple(42), std::make_tuple(0.5))); } TEST(DecomposePair, NotDecomposable) { auto f = [](...) { ADD_FAILURE() << "Must not be called"; return 'A'; }; EXPECT_STREQ("not decomposable", TryDecomposePair(f)); EXPECT_STREQ("not decomposable", TryDecomposePair(f, std::piecewise_construct, std::make_tuple(), std::make_tuple(0.5))); } } // namespace } // namespace container_internal ABSL_NAMESPACE_END } // namespace absl