• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/stack_container.h"
6 
7 #include <algorithm>
8 
9 #include "testing/gtest/include/gtest/gtest.h"
10 #include "base/ref_counted.h"
11 
12 namespace {
13 
14 class Dummy : public base::RefCounted<Dummy> {
15  public:
Dummy(int * alive)16   explicit Dummy(int* alive) : alive_(alive) {
17     ++*alive_;
18   }
19 
20  private:
21   friend class base::RefCounted<Dummy>;
22 
~Dummy()23   ~Dummy() {
24     --*alive_;
25   }
26 
27   int* const alive_;
28 };
29 
30 }  // namespace
31 
TEST(StackContainer,Vector)32 TEST(StackContainer, Vector) {
33   const int stack_size = 3;
34   StackVector<int, stack_size> vect;
35   const int* stack_buffer = &vect.stack_data().stack_buffer()[0];
36 
37   // The initial |stack_size| elements should appear in the stack buffer.
38   EXPECT_EQ(static_cast<size_t>(stack_size), vect.container().capacity());
39   for (int i = 0; i < stack_size; i++) {
40     vect.container().push_back(i);
41     EXPECT_EQ(stack_buffer, &vect.container()[0]);
42     EXPECT_TRUE(vect.stack_data().used_stack_buffer_);
43   }
44 
45   // Adding more elements should push the array onto the heap.
46   for (int i = 0; i < stack_size; i++) {
47     vect.container().push_back(i + stack_size);
48     EXPECT_NE(stack_buffer, &vect.container()[0]);
49     EXPECT_FALSE(vect.stack_data().used_stack_buffer_);
50   }
51 
52   // The array should still be in order.
53   for (int i = 0; i < stack_size * 2; i++)
54     EXPECT_EQ(i, vect.container()[i]);
55 
56   // Resize to smaller. Our STL implementation won't reallocate in this case,
57   // otherwise it might use our stack buffer. We reserve right after the resize
58   // to guarantee it isn't using the stack buffer, even though it doesn't have
59   // much data.
60   vect.container().resize(stack_size);
61   vect.container().reserve(stack_size * 2);
62   EXPECT_FALSE(vect.stack_data().used_stack_buffer_);
63 
64   // Copying the small vector to another should use the same allocator and use
65   // the now-unused stack buffer. GENERALLY CALLERS SHOULD NOT DO THIS since
66   // they have to get the template types just right and it can cause errors.
67   std::vector<int, StackAllocator<int, stack_size> > other(vect.container());
68   EXPECT_EQ(stack_buffer, &other.front());
69   EXPECT_TRUE(vect.stack_data().used_stack_buffer_);
70   for (int i = 0; i < stack_size; i++)
71     EXPECT_EQ(i, other[i]);
72 }
73 
TEST(StackContainer,VectorDoubleDelete)74 TEST(StackContainer, VectorDoubleDelete) {
75   // Regression testing for double-delete.
76   typedef StackVector<scoped_refptr<Dummy>, 2> Vector;
77   typedef Vector::ContainerType Container;
78   Vector vect;
79 
80   int alive = 0;
81   scoped_refptr<Dummy> dummy(new Dummy(&alive));
82   EXPECT_EQ(alive, 1);
83 
84   vect->push_back(dummy);
85   EXPECT_EQ(alive, 1);
86 
87   Dummy* dummy_unref = dummy.get();
88   dummy = NULL;
89   EXPECT_EQ(alive, 1);
90 
91   Container::iterator itr = std::find(vect->begin(), vect->end(), dummy_unref);
92   EXPECT_EQ(itr->get(), dummy_unref);
93   vect->erase(itr);
94   EXPECT_EQ(alive, 0);
95 
96   // Shouldn't crash at exit.
97 }
98 
TEST(StackContainer,BufferAlignment)99 TEST(StackContainer, BufferAlignment) {
100   StackVector<wchar_t, 16> text;
101   text->push_back(L'A');
102   text->push_back(L'B');
103   text->push_back(L'C');
104   text->push_back(L'D');
105   text->push_back(L'E');
106   text->push_back(L'F');
107   text->push_back(0);
108 
109   const wchar_t* buffer = &text[1];
110   bool even_aligned = (0 == (((size_t)buffer) & 0x1));
111   EXPECT_EQ(even_aligned, true);
112 }
113 
114 #ifdef COMPILER_MSVC
115 // Make sure all the class compiles correctly.
116 // TODO(pinkerton): i'm not sure why this doesn't compile on GCC, but
117 // it doesn't.
118 template StackVector<int, 2>;
119 template StackVector<scoped_refptr<Dummy>, 2>;
120 #endif
121