Home | History | Annotate | Download | only in base
      1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "base/tuple.h"
      6 
      7 #include "base/compiler_specific.h"
      8 #include "testing/gtest/include/gtest/gtest.h"
      9 
     10 namespace base {
     11 
     12 namespace {
     13 
     14 void DoAdd(int a, int b, int c, int* res) {
     15   *res = a + b + c;
     16 }
     17 
     18 struct Addy {
     19   Addy() { }
     20   void DoAdd(int a, int b, int c, int d, int* res) {
     21     *res = a + b + c + d;
     22   }
     23 };
     24 
     25 struct Addz {
     26   Addz() { }
     27   void DoAdd(int a, int b, int c, int d, int e, int* res) {
     28     *res = a + b + c + d + e;
     29   }
     30 };
     31 
     32 }  // namespace
     33 
     34 TEST(TupleTest, Basic) {
     35   std::tuple<> t0 = std::make_tuple();
     36   ALLOW_UNUSED_LOCAL(t0);
     37   std::tuple<int> t1(1);
     38   std::tuple<int, const char*> t2 =
     39       std::make_tuple(1, static_cast<const char*>("wee"));
     40   ALLOW_UNUSED_LOCAL(t2);
     41   std::tuple<int, int, int> t3(1, 2, 3);
     42   std::tuple<int, int, int, int*> t4(1, 2, 3, &std::get<0>(t1));
     43   std::tuple<int, int, int, int, int*> t5(1, 2, 3, 4, &std::get<0>(t4));
     44   std::tuple<int, int, int, int, int, int*> t6(1, 2, 3, 4, 5, &std::get<0>(t4));
     45 
     46   EXPECT_EQ(1, std::get<0>(t1));
     47   DispatchToFunction(&DoAdd, t4);
     48   EXPECT_EQ(6, std::get<0>(t1));
     49 
     50   int res = 0;
     51   DispatchToFunction(&DoAdd, std::make_tuple(9, 8, 7, &res));
     52   EXPECT_EQ(24, res);
     53 
     54   Addy addy;
     55   EXPECT_EQ(1, std::get<0>(t4));
     56   DispatchToMethod(&addy, &Addy::DoAdd, t5);
     57   EXPECT_EQ(10, std::get<0>(t4));
     58 
     59   Addz addz;
     60   EXPECT_EQ(10, std::get<0>(t4));
     61   DispatchToMethod(&addz, &Addz::DoAdd, t6);
     62   EXPECT_EQ(15, std::get<0>(t4));
     63 }
     64 
     65 namespace {
     66 
     67 struct CopyLogger {
     68   CopyLogger() { ++TimesConstructed; }
     69   CopyLogger(const CopyLogger& tocopy) { ++TimesConstructed; ++TimesCopied; }
     70   ~CopyLogger() { }
     71 
     72   static int TimesCopied;
     73   static int TimesConstructed;
     74 };
     75 
     76 void SomeLoggerMethRef(const CopyLogger& logy, const CopyLogger* ptr, bool* b) {
     77   *b = &logy == ptr;
     78 }
     79 
     80 void SomeLoggerMethCopy(CopyLogger logy, const CopyLogger* ptr, bool* b) {
     81   *b = &logy == ptr;
     82 }
     83 
     84 int CopyLogger::TimesCopied = 0;
     85 int CopyLogger::TimesConstructed = 0;
     86 
     87 }  // namespace
     88 
     89 TEST(TupleTest, Copying) {
     90   CopyLogger logger;
     91   EXPECT_EQ(0, CopyLogger::TimesCopied);
     92   EXPECT_EQ(1, CopyLogger::TimesConstructed);
     93 
     94   bool res = false;
     95 
     96   // Creating the tuple should copy the class to store internally in the tuple.
     97   std::tuple<CopyLogger, CopyLogger*, bool*> tuple(logger, &logger, &res);
     98   std::get<1>(tuple) = &std::get<0>(tuple);
     99   EXPECT_EQ(2, CopyLogger::TimesConstructed);
    100   EXPECT_EQ(1, CopyLogger::TimesCopied);
    101 
    102   // Our internal Logger and the one passed to the function should be the same.
    103   res = false;
    104   DispatchToFunction(&SomeLoggerMethRef, tuple);
    105   EXPECT_TRUE(res);
    106   EXPECT_EQ(2, CopyLogger::TimesConstructed);
    107   EXPECT_EQ(1, CopyLogger::TimesCopied);
    108 
    109   // Now they should be different, since the function call will make a copy.
    110   res = false;
    111   DispatchToFunction(&SomeLoggerMethCopy, tuple);
    112   EXPECT_FALSE(res);
    113   EXPECT_EQ(3, CopyLogger::TimesConstructed);
    114   EXPECT_EQ(2, CopyLogger::TimesCopied);
    115 }
    116 
    117 TEST(TupleTest, Get) {
    118   int i = 1;
    119   int j = 2;
    120   std::tuple<int, int&, int&&> t(3, i, std::move(j));
    121   EXPECT_TRUE((std::is_same<int&, decltype(base::get<0>(t))>::value));
    122   EXPECT_EQ(3, base::get<0>(t));
    123 
    124   EXPECT_TRUE((std::is_same<int&, decltype(base::get<1>(t))>::value));
    125   EXPECT_EQ(1, base::get<1>(t));
    126 
    127   EXPECT_TRUE((std::is_same<int&, decltype(base::get<2>(t))>::value));
    128   EXPECT_EQ(2, base::get<2>(t));
    129 
    130   EXPECT_TRUE((std::is_same<int&&,
    131                decltype(base::get<0>(std::move(t)))>::value));
    132   EXPECT_EQ(3, base::get<0>(std::move(t)));
    133 
    134   EXPECT_TRUE((std::is_same<int&,
    135                decltype(base::get<1>(std::move(t)))>::value));
    136   EXPECT_EQ(1, base::get<1>(std::move(t)));
    137 
    138   EXPECT_TRUE((std::is_same<int&&,
    139                decltype(base::get<2>(std::move(t)))>::value));
    140   EXPECT_EQ(2, base::get<2>(std::move(t)));
    141 }
    142 
    143 }  // namespace base
    144