Frobby  0.9.5
ArenaTest.cpp
Go to the documentation of this file.
1 /* Frobby: Software for monomial ideal computations.
2  Copyright (C) 2011 University of Aarhus
3  Contact Bjarke Hammersholt Roune for license information (www.broune.com)
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program. If not, see http://www.gnu.org/licenses/.
17 */
18 #include "stdinc.h"
19 #include "Arena.h"
20 #include "tests.h"
21 
22 #include <algorithm>
23 #include <sstream>
24 
26 
27 TEST(Arena, NoOp) {
28  Arena arena;
29 }
30 
31 TEST(Arena, Big) {
32  Arena arena;
33  void* a = arena.alloc(5);
34  arena.freeTop(arena.alloc(1024 * 1024));
35  arena.freeTop(arena.alloc(1024 * 1024));
36  ASSERT_FALSE(arena.isEmpty());
37  arena.freeTop(a);
38  ASSERT_TRUE(arena.isEmpty());
39 
40 }
41 
42 TEST(Arena, Zero) {
43  Arena arena;
44  void* a = arena.alloc(0);
45  void* b = arena.alloc(0);
46  void* c = arena.alloc(0);
47  ASSERT_NEQ(a, b);
48  ASSERT_NEQ(a, c);
49  ASSERT_NEQ(b, c);
50  ASSERT_FALSE(arena.isEmpty());
51 }
52 
53 TEST(Arena, Many) {
54  Arena arena;
55  vector<pair<char*, char*> > allocs;
56 
57  for (size_t i = 3; i < 10; ++i) {
58  for (size_t size = 0; size < 100; ++size) {
59  char* a = static_cast<char*>(arena.alloc(size));
60  pair<char*, char*> p(a, a + size);
61  for (size_t j = 0; j < allocs.size(); ++j) {
62  pair<char*, char*> p2 = allocs[j];
63  if (p.first <= p2.first)
64  ASSERT_FALSE_SILENT(p2.first < p.second);
65  else
66  ASSERT_FALSE_SILENT(p.first < p2.second);
67  }
68  fill(p.first, p.second, static_cast<char>(-1));
69  allocs.push_back(p);
70  }
71 
72  while (allocs.size() > 10 * i) {
73  arena.freeTop(allocs.back().first);
74  allocs.pop_back();
75  }
76 
77  arena.freeAndAllAfter(allocs[5 * i].first);
78  allocs.resize(5 * i);
79  }
80  ASSERT_FALSE(arena.isEmpty());
81  arena.freeAndAllAfter(allocs.front().first);
82  ASSERT_TRUE(arena.isEmpty());
83 }
84 
85 TEST(Arena, BigAndOverflow) {
86  Arena arena;
87  // aligning size causes overflow
88  ASSERT_EXCEPTION(arena.alloc(static_cast<size_t>(-1)), bad_alloc);
89 
90  // 2x size is an overflow
91  ASSERT_EXCEPTION(arena.alloc(static_cast<size_t>(-1)/2 + 1), bad_alloc);
92 
93  // causes attempt at allocating almost the entire virtual memory space
94  // which cannot succeed
95  ASSERT_EXCEPTION(arena.alloc(static_cast<size_t>(-1)/2 - 100), bad_alloc);
96 
97  // sizeof(long) * x overflows to a smaller value (0).
98  const size_t smallerOverflow = 1ul << (8*sizeof(long) - 1);
99  ASSERT(smallerOverflow > 0);
100  ASSERT(smallerOverflow * sizeof(long) == 0);
101  ASSERT_EXCEPTION(arena.allocArray<long>(smallerOverflow), bad_alloc);
102 
103  // sizeof(int) * x overflows to a greater value
104  const size_t greaterOverflow = (~(0ul)) >> 1;
105  ASSERT(sizeof(long) >= 4);
106  ASSERT(greaterOverflow * sizeof(long) > greaterOverflow);
107  ASSERT(greaterOverflow != (greaterOverflow * sizeof(long)) / sizeof(long));
108  ASSERT_EXCEPTION(arena.allocArray<long>(greaterOverflow), bad_alloc);
109 
110  ASSERT_TRUE(arena.isEmpty());
111 }
112 
113 namespace {
114  template<class T, size_t ThrowAt>
115  class _frobby_Helper {
116  public:
117  _frobby_Helper() {
118  _id = ++_count;
119  if (_id == ThrowAt) {
120  _log << 'T' << _id;
121  throw _id;
122  } else
123  _log << '+' << _id;
124  }
125 
126  ~_frobby_Helper() {
127  _log << '-' << _id;
128  }
129 
130  void setId(size_t id) {_id = id;}
131 
132  static string getLog() {return _log.str();}
133 
134  private:
135  size_t _id;
136  static size_t _count;
137  static ostringstream _log;
138  };
139 
140  template<class T, size_t ThrowAt>
141  size_t _frobby_Helper<T, ThrowAt>::_count = 0;
142 
143  template<class T, size_t ThrowAt>
144  ostringstream _frobby_Helper<T, ThrowAt>::_log;
145 }
146 #define MAKE_HELPER(NAME, THROW_AT) \
147  namespace { \
148  struct _frobby_##NAME##HelperTag {}; \
149  typedef _frobby_Helper<_frobby_##NAME##HelperTag, THROW_AT> NAME##Helper; \
150  }
151 
152 MAKE_HELPER(ConDecon, 0)
153 TEST(Arena, ConDecon) {
154  Arena arena;
155  arena.freeTopArray(arena.allocArray<ConDeconHelper>(0));
156  arena.freeTopArray(arena.allocArray<ConDeconHelper>(3));
157  arena.freeTopArray(arena.allocArray<ConDeconHelper>(0));
158  ASSERT_EQ(ConDeconHelper::getLog(), "+1+2+3-3-2-1");
159  ASSERT_TRUE(arena.isEmpty())
160 }
161 
162 MAKE_HELPER(ConExcep, 4)
163 TEST(Arena, ConExcep) {
164  Arena arena;
165  ASSERT_EXCEPTION(arena.allocArray<ConExcepHelper>(10), size_t);
166  ASSERT_EQ(ConExcepHelper::getLog(), "+1+2+3T4-3-2-1");
167  ASSERT_TRUE(arena.isEmpty());
168 }
169 
170 MAKE_HELPER(NoConDecon, 0)
171 TEST(Arena, NoConDecon) {
172  Arena arena;
173  pair<NoConDeconHelper*, NoConDeconHelper*> p =
174  arena.allocArrayNoCon<NoConDeconHelper>(3);
175  p.first[0].setId(1);
176  p.first[1].setId(2);
177  p.first[2].setId(3);
178  arena.freeTopArray(p);
179 
180  ASSERT_EQ(NoConDeconHelper::getLog(), "-3-2-1");
181  ASSERT_TRUE(arena.isEmpty())
182 }
183 
184 MAKE_HELPER(ConNoDecon, 0)
185 TEST(Arena, ConNoDecon) {
186  Arena arena;
187  arena.freeTop(arena.allocArray<ConNoDeconHelper>(3).first);
188  ASSERT_EQ(ConNoDeconHelper::getLog(), "+1+2+3");
189  ASSERT_TRUE(arena.isEmpty())
190 }
#define MAKE_HELPER(NAME, THROW_AT)
Definition: ArenaTest.cpp:146
TEST(Arena, NoOp)
Definition: ArenaTest.cpp:27
#define ASSERT_NEQ(A, B)
Definition: asserts.h:175
#define ASSERT_EXCEPTION(CODE, EXCEPTION_TYPE)
Definition: asserts.h:66
#define ASSERT_TRUE(VALUE)
Definition: asserts.h:72
#define ASSERT_EQ(A, B)
Definition: asserts.h:147
#define ASSERT_FALSE_SILENT(VALUE)
Definition: asserts.h:121
#define ASSERT_FALSE(VALUE)
Definition: asserts.h:119
This is an arena allocator.
Definition: Arena.h:53
void * alloc(size_t size)
Returns a pointer to a buffer of size bytes.
Definition: Arena.h:180
bool isEmpty() const
Returns true if there are no live allocations for this Arena.
Definition: Arena.h:117
pair< T *, T * > allocArrayNoCon(size_t elementCount)
As alloc(elementCount * sizeof(T)).
Definition: Arena.h:250
void freeTop(void *ptr)
Frees the buffer pointed to by ptr.
Definition: Arena.h:209
void freeTopArray(T *array, T *arrayEnd)
As freeTop(array) except that the elements of the array in the range (array, arrayEnd] are deconstruc...
Definition: Arena.h:280
void freeAndAllAfter(void *ptr)
Frees the buffer pointed to by ptr and all not yet freed allocations that have happened since that bu...
Definition: Arena.h:224
pair< T *, T * > allocArray(size_t elementCount)
As allocArrayNoCon except that constructors for the elements of the array are called.
Definition: Arena.h:263
#define TEST_SUITE(SUITE)
Definition: macroes.h:26
#define ASSERT(X)
Definition: stdinc.h:86