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