tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

bind_front_test.cc (6715B)


      1 // Copyright 2018 The Abseil Authors.
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //      https://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 #include "absl/functional/bind_front.h"
     16 
     17 #include <stddef.h>
     18 
     19 #include <functional>
     20 #include <memory>
     21 #include <string>
     22 
     23 #include "gmock/gmock.h"
     24 #include "gtest/gtest.h"
     25 #include "absl/memory/memory.h"
     26 
     27 namespace {
     28 
     29 char CharAt(const char* s, size_t index) { return s[index]; }
     30 
     31 TEST(BindTest, Basics) {
     32  EXPECT_EQ('C', absl::bind_front(CharAt)("ABC", 2));
     33  EXPECT_EQ('C', absl::bind_front(CharAt, "ABC")(2));
     34  EXPECT_EQ('C', absl::bind_front(CharAt, "ABC", 2)());
     35 }
     36 
     37 TEST(BindTest, Lambda) {
     38  auto lambda = [](int x, int y, int z) { return x + y + z; };
     39  EXPECT_EQ(6, absl::bind_front(lambda)(1, 2, 3));
     40  EXPECT_EQ(6, absl::bind_front(lambda, 1)(2, 3));
     41  EXPECT_EQ(6, absl::bind_front(lambda, 1, 2)(3));
     42  EXPECT_EQ(6, absl::bind_front(lambda, 1, 2, 3)());
     43 }
     44 
     45 struct Functor {
     46  std::string operator()() & { return "&"; }
     47  std::string operator()() const& { return "const&"; }
     48  std::string operator()() && { return "&&"; }
     49  std::string operator()() const&& { return "const&&"; }
     50 };
     51 
     52 TEST(BindTest, PerfectForwardingOfBoundArgs) {
     53  auto f = absl::bind_front(Functor());
     54  const auto& cf = f;
     55  EXPECT_EQ("&", f());
     56  EXPECT_EQ("const&", cf());
     57  EXPECT_EQ("&&", std::move(f)());
     58  EXPECT_EQ("const&&", std::move(cf)());
     59 }
     60 
     61 struct ArgDescribe {
     62  std::string operator()(int&) const { return "&"; }             // NOLINT
     63  std::string operator()(const int&) const { return "const&"; }  // NOLINT
     64  std::string operator()(int&&) const { return "&&"; }
     65  std::string operator()(const int&&) const { return "const&&"; }
     66 };
     67 
     68 TEST(BindTest, PerfectForwardingOfFreeArgs) {
     69  ArgDescribe f;
     70  int i;
     71  EXPECT_EQ("&", absl::bind_front(f)(static_cast<int&>(i)));
     72  EXPECT_EQ("const&", absl::bind_front(f)(static_cast<const int&>(i)));
     73  EXPECT_EQ("&&", absl::bind_front(f)(static_cast<int&&>(i)));
     74  EXPECT_EQ("const&&", absl::bind_front(f)(static_cast<const int&&>(i)));
     75 }
     76 
     77 struct NonCopyableFunctor {
     78  NonCopyableFunctor() = default;
     79  NonCopyableFunctor(const NonCopyableFunctor&) = delete;
     80  NonCopyableFunctor& operator=(const NonCopyableFunctor&) = delete;
     81  const NonCopyableFunctor* operator()() const { return this; }
     82 };
     83 
     84 TEST(BindTest, RefToFunctor) {
     85  // It won't copy/move the functor and use the original object.
     86  NonCopyableFunctor ncf;
     87  auto bound_ncf = absl::bind_front(std::ref(ncf));
     88  auto bound_ncf_copy = bound_ncf;
     89  EXPECT_EQ(&ncf, bound_ncf_copy());
     90 }
     91 
     92 struct Struct {
     93  std::string value;
     94 };
     95 
     96 TEST(BindTest, StoreByCopy) {
     97  Struct s = {"hello"};
     98  auto f = absl::bind_front(&Struct::value, s);
     99  auto g = f;
    100  EXPECT_EQ("hello", f());
    101  EXPECT_EQ("hello", g());
    102  EXPECT_NE(&s.value, &f());
    103  EXPECT_NE(&s.value, &g());
    104  EXPECT_NE(&g(), &f());
    105 }
    106 
    107 struct NonCopyable {
    108  explicit NonCopyable(const std::string& s) : value(s) {}
    109  NonCopyable(const NonCopyable&) = delete;
    110  NonCopyable& operator=(const NonCopyable&) = delete;
    111 
    112  std::string value;
    113 };
    114 
    115 const std::string& GetNonCopyableValue(const NonCopyable& n) { return n.value; }
    116 
    117 TEST(BindTest, StoreByRef) {
    118  NonCopyable s("hello");
    119  auto f = absl::bind_front(&GetNonCopyableValue, std::ref(s));
    120  EXPECT_EQ("hello", f());
    121  EXPECT_EQ(&s.value, &f());
    122  auto g = std::move(f);  // NOLINT
    123  EXPECT_EQ("hello", g());
    124  EXPECT_EQ(&s.value, &g());
    125  s.value = "goodbye";
    126  EXPECT_EQ("goodbye", g());
    127 }
    128 
    129 TEST(BindTest, StoreByCRef) {
    130  NonCopyable s("hello");
    131  auto f = absl::bind_front(&GetNonCopyableValue, std::cref(s));
    132  EXPECT_EQ("hello", f());
    133  EXPECT_EQ(&s.value, &f());
    134  auto g = std::move(f);  // NOLINT
    135  EXPECT_EQ("hello", g());
    136  EXPECT_EQ(&s.value, &g());
    137  s.value = "goodbye";
    138  EXPECT_EQ("goodbye", g());
    139 }
    140 
    141 const std::string& GetNonCopyableValueByWrapper(
    142    std::reference_wrapper<NonCopyable> n) {
    143  return n.get().value;
    144 }
    145 
    146 TEST(BindTest, StoreByRefInvokeByWrapper) {
    147  NonCopyable s("hello");
    148  auto f = absl::bind_front(GetNonCopyableValueByWrapper, std::ref(s));
    149  EXPECT_EQ("hello", f());
    150  EXPECT_EQ(&s.value, &f());
    151  auto g = std::move(f);
    152  EXPECT_EQ("hello", g());
    153  EXPECT_EQ(&s.value, &g());
    154  s.value = "goodbye";
    155  EXPECT_EQ("goodbye", g());
    156 }
    157 
    158 TEST(BindTest, StoreByPointer) {
    159  NonCopyable s("hello");
    160  auto f = absl::bind_front(&NonCopyable::value, &s);
    161  EXPECT_EQ("hello", f());
    162  EXPECT_EQ(&s.value, &f());
    163  auto g = std::move(f);
    164  EXPECT_EQ("hello", g());
    165  EXPECT_EQ(&s.value, &g());
    166 }
    167 
    168 int Sink(std::unique_ptr<int> p) {
    169  return *p;
    170 }
    171 
    172 std::unique_ptr<int> Factory(int n) { return absl::make_unique<int>(n); }
    173 
    174 TEST(BindTest, NonCopyableArg) {
    175  EXPECT_EQ(42, absl::bind_front(Sink)(absl::make_unique<int>(42)));
    176  EXPECT_EQ(42, absl::bind_front(Sink, absl::make_unique<int>(42))());
    177 }
    178 
    179 TEST(BindTest, NonCopyableResult) {
    180  EXPECT_THAT(absl::bind_front(Factory)(42), ::testing::Pointee(42));
    181  EXPECT_THAT(absl::bind_front(Factory, 42)(), ::testing::Pointee(42));
    182 }
    183 
    184 // is_copy_constructible<FalseCopyable<unique_ptr<T>> is true but an attempt to
    185 // instantiate the copy constructor leads to a compile error. This is similar
    186 // to how standard containers behave.
    187 template <class T>
    188 struct FalseCopyable {
    189  FalseCopyable() {}
    190  FalseCopyable(const FalseCopyable& other) : m(other.m) {}
    191  FalseCopyable(FalseCopyable&& other) : m(std::move(other.m)) {}
    192  T m;
    193 };
    194 
    195 int GetMember(FalseCopyable<std::unique_ptr<int>> x) { return *x.m; }
    196 
    197 TEST(BindTest, WrappedMoveOnly) {
    198  FalseCopyable<std::unique_ptr<int>> x;
    199  x.m = absl::make_unique<int>(42);
    200  auto f = absl::bind_front(&GetMember, std::move(x));
    201  EXPECT_EQ(42, std::move(f)());
    202 }
    203 
    204 int Plus(int a, int b) { return a + b; }
    205 
    206 TEST(BindTest, ConstExpr) {
    207  constexpr auto f = absl::bind_front(CharAt);
    208  EXPECT_EQ(f("ABC", 1), 'B');
    209  static constexpr int five = 5;
    210  constexpr auto plus5 = absl::bind_front(Plus, five);
    211  EXPECT_EQ(plus5(1), 6);
    212 
    213  static constexpr char data[] = "DEF";
    214  constexpr auto g = absl::bind_front(CharAt, data);
    215  EXPECT_EQ(g(1), 'E');
    216 }
    217 
    218 struct ManglingCall {
    219  int operator()(int, double, std::string) const { return 0; }
    220 };
    221 
    222 TEST(BindTest, Mangling) {
    223  // We just want to generate a particular instantiation to see its mangling.
    224  absl::bind_front(ManglingCall{}, 1, 3.3)("A");
    225 }
    226 
    227 }  // namespace