1// Copyright 2014 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/scoped_generic.h" 6 7#include <utility> 8#include <vector> 9 10#include "testing/gtest/include/gtest/gtest.h" 11 12namespace base { 13 14namespace { 15 16struct IntTraits { 17 IntTraits(std::vector<int>* freed) : freed_ints(freed) {} 18 19 static int InvalidValue() { 20 return -1; 21 } 22 void Free(int value) { 23 freed_ints->push_back(value); 24 } 25 26 std::vector<int>* freed_ints; 27}; 28 29typedef ScopedGeneric<int, IntTraits> ScopedInt; 30 31} // namespace 32 33TEST(ScopedGenericTest, ScopedGeneric) { 34 std::vector<int> values_freed; 35 IntTraits traits(&values_freed); 36 37 // Invalid case, delete should not be called. 38 { 39 ScopedInt a(IntTraits::InvalidValue(), traits); 40 } 41 EXPECT_TRUE(values_freed.empty()); 42 43 // Simple deleting case. 44 static const int kFirst = 0; 45 { 46 ScopedInt a(kFirst, traits); 47 } 48 ASSERT_EQ(1u, values_freed.size()); 49 ASSERT_EQ(kFirst, values_freed[0]); 50 values_freed.clear(); 51 52 // Release should return the right value and leave the object empty. 53 { 54 ScopedInt a(kFirst, traits); 55 EXPECT_EQ(kFirst, a.release()); 56 57 ScopedInt b(IntTraits::InvalidValue(), traits); 58 EXPECT_EQ(IntTraits::InvalidValue(), b.release()); 59 } 60 ASSERT_TRUE(values_freed.empty()); 61 62 // Reset should free the old value, then the new one should go away when 63 // it goes out of scope. 64 static const int kSecond = 1; 65 { 66 ScopedInt b(kFirst, traits); 67 b.reset(kSecond); 68 ASSERT_EQ(1u, values_freed.size()); 69 ASSERT_EQ(kFirst, values_freed[0]); 70 } 71 ASSERT_EQ(2u, values_freed.size()); 72 ASSERT_EQ(kSecond, values_freed[1]); 73 values_freed.clear(); 74 75 // Swap. 76 { 77 ScopedInt a(kFirst, traits); 78 ScopedInt b(kSecond, traits); 79 a.swap(b); 80 EXPECT_TRUE(values_freed.empty()); // Nothing should be freed. 81 EXPECT_EQ(kSecond, a.get()); 82 EXPECT_EQ(kFirst, b.get()); 83 } 84 // Values should be deleted in the opposite order. 85 ASSERT_EQ(2u, values_freed.size()); 86 EXPECT_EQ(kFirst, values_freed[0]); 87 EXPECT_EQ(kSecond, values_freed[1]); 88 values_freed.clear(); 89 90 // Move constructor. 91 { 92 ScopedInt a(kFirst, traits); 93 ScopedInt b(std::move(a)); 94 EXPECT_TRUE(values_freed.empty()); // Nothing should be freed. 95 ASSERT_EQ(IntTraits::InvalidValue(), a.get()); 96 ASSERT_EQ(kFirst, b.get()); 97 } 98 99 ASSERT_EQ(1u, values_freed.size()); 100 ASSERT_EQ(kFirst, values_freed[0]); 101 values_freed.clear(); 102 103 // Move assign. 104 { 105 ScopedInt a(kFirst, traits); 106 ScopedInt b(kSecond, traits); 107 b = std::move(a); 108 ASSERT_EQ(1u, values_freed.size()); 109 EXPECT_EQ(kSecond, values_freed[0]); 110 ASSERT_EQ(IntTraits::InvalidValue(), a.get()); 111 ASSERT_EQ(kFirst, b.get()); 112 } 113 114 ASSERT_EQ(2u, values_freed.size()); 115 EXPECT_EQ(kFirst, values_freed[1]); 116 values_freed.clear(); 117} 118 119TEST(ScopedGenericTest, Operators) { 120 std::vector<int> values_freed; 121 IntTraits traits(&values_freed); 122 123 static const int kFirst = 0; 124 static const int kSecond = 1; 125 { 126 ScopedInt a(kFirst, traits); 127 EXPECT_TRUE(a == kFirst); 128 EXPECT_FALSE(a != kFirst); 129 EXPECT_FALSE(a == kSecond); 130 EXPECT_TRUE(a != kSecond); 131 132 EXPECT_TRUE(kFirst == a); 133 EXPECT_FALSE(kFirst != a); 134 EXPECT_FALSE(kSecond == a); 135 EXPECT_TRUE(kSecond != a); 136 } 137 138 // is_valid(). 139 { 140 ScopedInt a(kFirst, traits); 141 EXPECT_TRUE(a.is_valid()); 142 a.reset(); 143 EXPECT_FALSE(a.is_valid()); 144 } 145} 146 147// Cheesy manual "no compile" test for manually validating changes. 148#if 0 149TEST(ScopedGenericTest, NoCompile) { 150 // Assignment shouldn't work. 151 /*{ 152 ScopedInt a(kFirst, traits); 153 ScopedInt b(a); 154 }*/ 155 156 // Comparison shouldn't work. 157 /*{ 158 ScopedInt a(kFirst, traits); 159 ScopedInt b(kFirst, traits); 160 if (a == b) { 161 } 162 }*/ 163 164 // Implicit conversion to bool shouldn't work. 165 /*{ 166 ScopedInt a(kFirst, traits); 167 bool result = a; 168 }*/ 169} 170#endif 171 172} // namespace base 173