Home | History | Annotate | Download | only in base
      1 // Copyright (c) 2011 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 "base/memory/ref_counted.h"
     10 #include "testing/gtest/include/gtest/gtest.h"
     11 
     12 namespace {
     13 
     14 class Dummy : public base::RefCounted<Dummy> {
     15  public:
     16   explicit Dummy(int* alive) : alive_(alive) {
     17     ++*alive_;
     18   }
     19 
     20  private:
     21   friend class base::RefCounted<Dummy>;
     22 
     23   ~Dummy() {
     24     --*alive_;
     25   }
     26 
     27   int* const alive_;
     28 };
     29 
     30 }  // namespace
     31 
     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 
     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 
     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