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