|  | // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #include "base/tuple.h" | 
|  |  | 
|  | #include <gtest/gtest.h> | 
|  |  | 
|  | #include "base/compiler_specific.h" | 
|  |  | 
|  | namespace base { | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | void DoAdd(int a, int b, int c, int* res) { | 
|  | *res = a + b + c; | 
|  | } | 
|  |  | 
|  | struct Addy { | 
|  | Addy() { } | 
|  | void DoAdd(int a, int b, int c, int d, int* res) { | 
|  | *res = a + b + c + d; | 
|  | } | 
|  | }; | 
|  |  | 
|  | struct Addz { | 
|  | Addz() { } | 
|  | void DoAdd(int a, int b, int c, int d, int e, int* res) { | 
|  | *res = a + b + c + d + e; | 
|  | } | 
|  | }; | 
|  |  | 
|  | }  // namespace | 
|  |  | 
|  | TEST(TupleTest, Basic) { | 
|  | base::Tuple<> t0 = base::MakeTuple(); | 
|  | ALLOW_UNUSED_LOCAL(t0); | 
|  | base::Tuple<int> t1(1); | 
|  | base::Tuple<int, const char*> t2 = | 
|  | base::MakeTuple(1, static_cast<const char*>("wee")); | 
|  | base::Tuple<int, int, int> t3(1, 2, 3); | 
|  | base::Tuple<int, int, int, int*> t4(1, 2, 3, &get<0>(t1)); | 
|  | base::Tuple<int, int, int, int, int*> t5(1, 2, 3, 4, &get<0>(t4)); | 
|  | base::Tuple<int, int, int, int, int, int*> t6(1, 2, 3, 4, 5, &get<0>(t4)); | 
|  |  | 
|  | EXPECT_EQ(1, get<0>(t1)); | 
|  | EXPECT_EQ(1, get<0>(t2)); | 
|  | EXPECT_EQ(1, get<0>(t3)); | 
|  | EXPECT_EQ(2, get<1>(t3)); | 
|  | EXPECT_EQ(3, get<2>(t3)); | 
|  | EXPECT_EQ(1, get<0>(t4)); | 
|  | EXPECT_EQ(2, get<1>(t4)); | 
|  | EXPECT_EQ(3, get<2>(t4)); | 
|  | EXPECT_EQ(1, get<0>(t5)); | 
|  | EXPECT_EQ(2, get<1>(t5)); | 
|  | EXPECT_EQ(3, get<2>(t5)); | 
|  | EXPECT_EQ(4, get<3>(t5)); | 
|  | EXPECT_EQ(1, get<0>(t6)); | 
|  | EXPECT_EQ(2, get<1>(t6)); | 
|  | EXPECT_EQ(3, get<2>(t6)); | 
|  | EXPECT_EQ(4, get<3>(t6)); | 
|  | EXPECT_EQ(5, get<4>(t6)); | 
|  |  | 
|  | EXPECT_EQ(1, get<0>(t1)); | 
|  | DispatchToFunction(&DoAdd, t4); | 
|  | EXPECT_EQ(6, get<0>(t1)); | 
|  |  | 
|  | int res = 0; | 
|  | DispatchToFunction(&DoAdd, base::MakeTuple(9, 8, 7, &res)); | 
|  | EXPECT_EQ(24, res); | 
|  |  | 
|  | Addy addy; | 
|  | EXPECT_EQ(1, get<0>(t4)); | 
|  | DispatchToMethod(&addy, &Addy::DoAdd, t5); | 
|  | EXPECT_EQ(10, get<0>(t4)); | 
|  |  | 
|  | Addz addz; | 
|  | EXPECT_EQ(10, get<0>(t4)); | 
|  | DispatchToMethod(&addz, &Addz::DoAdd, t6); | 
|  | EXPECT_EQ(15, get<0>(t4)); | 
|  | } | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | struct CopyLogger { | 
|  | CopyLogger() { ++TimesConstructed; } | 
|  | CopyLogger(const CopyLogger& tocopy) { ++TimesConstructed; ++TimesCopied; } | 
|  | ~CopyLogger() { } | 
|  |  | 
|  | static int TimesCopied; | 
|  | static int TimesConstructed; | 
|  | }; | 
|  |  | 
|  | void SomeLoggerMethRef(const CopyLogger& logy, const CopyLogger* ptr, bool* b) { | 
|  | *b = &logy == ptr; | 
|  | } | 
|  |  | 
|  | void SomeLoggerMethCopy(CopyLogger logy, const CopyLogger* ptr, bool* b) { | 
|  | *b = &logy == ptr; | 
|  | } | 
|  |  | 
|  | int CopyLogger::TimesCopied = 0; | 
|  | int CopyLogger::TimesConstructed = 0; | 
|  |  | 
|  | }  // namespace | 
|  |  | 
|  | TEST(TupleTest, Copying) { | 
|  | CopyLogger logger; | 
|  | EXPECT_EQ(0, CopyLogger::TimesCopied); | 
|  | EXPECT_EQ(1, CopyLogger::TimesConstructed); | 
|  |  | 
|  | bool res = false; | 
|  |  | 
|  | // Creating the tuple should copy the class to store internally in the tuple. | 
|  | base::Tuple<CopyLogger, CopyLogger*, bool*> tuple(logger, &logger, &res); | 
|  | get<1>(tuple) = &get<0>(tuple); | 
|  | EXPECT_EQ(2, CopyLogger::TimesConstructed); | 
|  | EXPECT_EQ(1, CopyLogger::TimesCopied); | 
|  |  | 
|  | // Our internal Logger and the one passed to the function should be the same. | 
|  | res = false; | 
|  | DispatchToFunction(&SomeLoggerMethRef, tuple); | 
|  | EXPECT_TRUE(res); | 
|  | EXPECT_EQ(2, CopyLogger::TimesConstructed); | 
|  | EXPECT_EQ(1, CopyLogger::TimesCopied); | 
|  |  | 
|  | // Now they should be different, since the function call will make a copy. | 
|  | res = false; | 
|  | DispatchToFunction(&SomeLoggerMethCopy, tuple); | 
|  | EXPECT_FALSE(res); | 
|  | EXPECT_EQ(3, CopyLogger::TimesConstructed); | 
|  | EXPECT_EQ(2, CopyLogger::TimesCopied); | 
|  | } | 
|  |  | 
|  | }  // namespace base |