multiset.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
3  */
4 
5 #if __GNUC__
6 # pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
7 #endif
8 
9 #include <string>
10 #include <cstdio>
11 #include <memory>
12 #include <gtest/gtest.h>
13 #include <uavcan/util/multiset.hpp>
14 
15 
16 static std::string toString(long x)
17 {
18  char buf[80];
19  std::snprintf(buf, sizeof(buf), "%li", x);
20  return std::string(buf);
21 }
22 
23 static bool oddValuePredicate(const std::string& value)
24 {
25  EXPECT_FALSE(value.empty());
26  const int num = atoi(value.c_str());
27  return num & 1;
28 }
29 
31 {
32  const std::string target;
33  FindPredicate(const std::string& target) : target(target) { }
34  bool operator()(const std::string& value) const { return value == target; }
35 };
36 
38 {
39  static int num_objects;
40  long long value;
41 
45 
46  static bool isNegative(const NoncopyableWithCounter& val)
47  {
48  return val.value < 0;
49  }
50 
51  bool operator==(const NoncopyableWithCounter& ref) const { return ref.value == value; }
52 };
53 
55 
56 template <typename T>
58 {
61  void operator()(const T& x) { accumulator += x; }
62 };
63 
65 {
66  template <typename T>
67  void operator()(T& x) const { x = T(); }
68 };
69 
70 
71 TEST(Multiset, Basic)
72 {
73  using uavcan::Multiset;
74 
75  static const int POOL_BLOCKS = 4;
77 
78  typedef Multiset<std::string> MultisetType;
79  std::unique_ptr<MultisetType> mset(new MultisetType(pool));
80 
81  typedef SummationOperator<std::string> StringConcatenationOperator;
82 
83  // Empty
84  mset->removeFirst("foo");
85  ASSERT_EQ(0, pool.getNumUsedBlocks());
86  ASSERT_FALSE(mset->getByIndex(0));
87  ASSERT_FALSE(mset->getByIndex(1));
88  ASSERT_FALSE(mset->getByIndex(10000));
89 
90  // Static addion
91  ASSERT_EQ("1", *mset->emplace("1"));
92  ASSERT_EQ("2", *mset->emplace("2"));
93  ASSERT_LE(1, pool.getNumUsedBlocks()); // One or more
94  ASSERT_EQ(2, mset->getSize());
95 
96  {
97  StringConcatenationOperator op;
98  mset->forEach<StringConcatenationOperator&>(op);
99  ASSERT_EQ(2, op.accumulator.size());
100  }
101 
102  // Dynamic addition
103  ASSERT_EQ("3", *mset->emplace("3"));
104  ASSERT_LE(1, pool.getNumUsedBlocks()); // One or more
105 
106  ASSERT_EQ("4", *mset->emplace("4"));
107  ASSERT_LE(1, pool.getNumUsedBlocks()); // One or more
108  ASSERT_EQ(4, mset->getSize());
109 
110  ASSERT_FALSE(mset->getByIndex(100));
111  ASSERT_FALSE(mset->getByIndex(4));
112 
113  // Finding some items
114  ASSERT_EQ("1", *mset->find(FindPredicate("1")));
115  ASSERT_EQ("2", *mset->find(FindPredicate("2")));
116  ASSERT_EQ("3", *mset->find(FindPredicate("3")));
117  ASSERT_EQ("4", *mset->find(FindPredicate("4")));
118  ASSERT_FALSE(mset->find(FindPredicate("nonexistent")));
119 
120  {
121  StringConcatenationOperator op;
122  mset->forEach<StringConcatenationOperator&>(op);
123  std::cout << "Accumulator: " << op.accumulator << std::endl;
124  ASSERT_EQ(4, op.accumulator.size());
125  }
126 
127  // Removing some
128  mset->removeFirst("1");
129  mset->removeFirst("foo"); // There's no such thing anyway
130  mset->removeFirst("2");
131 
132  // Adding some new items
133  unsigned max_value_integer = 0;
134  for (int i = 0; i < 100; i++)
135  {
136  const std::string value = toString(i);
137  std::string* res = mset->emplace(value); // Will NOT override above
138  if (res == UAVCAN_NULLPTR)
139  {
140  ASSERT_LT(1, i);
141  break;
142  }
143  else
144  {
145  ASSERT_EQ(value, *res);
146  }
147  max_value_integer = unsigned(i);
148  }
149  std::cout << "Max value: " << max_value_integer << std::endl;
150 
151  // Making sure there is true OOM
152  ASSERT_EQ(0, pool.getNumFreeBlocks());
153  ASSERT_FALSE(mset->emplace("nonexistent"));
154 
155  // Removing odd values - nearly half of them
156  mset->removeAllWhere(oddValuePredicate);
157 
158  // Making sure there's no odd values left
159  for (unsigned kv_int = 0; kv_int <= max_value_integer; kv_int++)
160  {
161  const std::string* val = mset->find(FindPredicate(toString(kv_int)));
162  if (val)
163  {
164  ASSERT_FALSE(kv_int & 1);
165  }
166  else
167  {
168  ASSERT_TRUE(kv_int & 1);
169  }
170  }
171 
172  // Clearing all strings
173  {
174  StringConcatenationOperator op;
175  mset->forEach<StringConcatenationOperator&>(op);
176  std::cout << "Accumulator before clearing: " << op.accumulator << std::endl;
177  }
178  mset->forEach(ClearingOperator());
179  {
180  StringConcatenationOperator op;
181  mset->forEach<StringConcatenationOperator&>(op);
182  std::cout << "Accumulator after clearing: " << op.accumulator << std::endl;
183  ASSERT_TRUE(op.accumulator.empty());
184  }
185 
186  // Making sure the memory will be released
187  mset.reset();
188  ASSERT_EQ(0, pool.getNumUsedBlocks());
189 }
190 
191 
192 TEST(Multiset, PrimitiveKey)
193 {
194  using uavcan::Multiset;
195 
196  static const int POOL_BLOCKS = 3;
198 
199  typedef Multiset<int> MultisetType;
200  std::unique_ptr<MultisetType> mset(new MultisetType(pool));
201 
202  // Empty
203  mset->removeFirst(8);
204  ASSERT_EQ(0, pool.getNumUsedBlocks());
205  ASSERT_EQ(0, mset->getSize());
206  ASSERT_FALSE(mset->getByIndex(0));
207 
208  // Insertion
209  ASSERT_EQ(1, *mset->emplace(1));
210  ASSERT_EQ(1, mset->getSize());
211  ASSERT_EQ(2, *mset->emplace(2));
212  ASSERT_EQ(2, mset->getSize());
213  ASSERT_EQ(3, *mset->emplace(3));
214  ASSERT_EQ(4, *mset->emplace(4));
215  ASSERT_EQ(4, mset->getSize());
216 
217  // Summation and clearing
218  {
219  SummationOperator<int> summation_operator;
220  mset->forEach<SummationOperator<int>&>(summation_operator);
221  ASSERT_EQ(1 + 2 + 3 + 4, summation_operator.accumulator);
222  }
223  mset->forEach(ClearingOperator());
224  {
225  SummationOperator<int> summation_operator;
226  mset->forEach<SummationOperator<int>&>(summation_operator);
227  ASSERT_EQ(0, summation_operator.accumulator);
228  }
229 }
230 
231 
233 {
234  using uavcan::Multiset;
235 
236  static const int POOL_BLOCKS = 3;
238 
239  typedef Multiset<NoncopyableWithCounter> MultisetType;
240  std::unique_ptr<MultisetType> mset(new MultisetType(pool));
241 
243  ASSERT_EQ(0, mset->emplace()->value);
245  ASSERT_EQ(123, mset->emplace(123)->value);
247  ASSERT_EQ(-456, mset->emplace(-456)->value);
249  ASSERT_EQ(456, mset->emplace(456)->value);
251  ASSERT_EQ(-789, mset->emplace(-789)->value);
253 
254  mset->removeFirst(NoncopyableWithCounter(0));
256 
257  mset->removeFirstWhere(&NoncopyableWithCounter::isNegative);
259 
260  mset->removeAllWhere(&NoncopyableWithCounter::isNegative);
261  ASSERT_EQ(2, NoncopyableWithCounter::num_objects); // Only 1 and 2 are left
262 
263  mset.reset();
264 
265  ASSERT_EQ(0, pool.getNumUsedBlocks());
266  ASSERT_EQ(0, NoncopyableWithCounter::num_objects); // All destroyed
267 }
UAVCAN_NULLPTR
#define UAVCAN_NULLPTR
Definition: libuavcan/libuavcan/include/uavcan/build_config.hpp:51
uavcan::Noncopyable
Definition: templates.hpp:46
multiset.hpp
oddValuePredicate
static bool oddValuePredicate(const std::string &value)
Definition: multiset.cpp:23
NoncopyableWithCounter::NoncopyableWithCounter
NoncopyableWithCounter(long long x)
Definition: multiset.cpp:43
FindPredicate
Definition: multiset.cpp:30
NoncopyableWithCounter::isNegative
static bool isNegative(const NoncopyableWithCounter &val)
Definition: multiset.cpp:46
uavcan::PoolAllocator
Definition: dynamic_memory.hpp:51
uavcan::PoolAllocator::getNumFreeBlocks
uint16_t getNumFreeBlocks() const
Definition: dynamic_memory.hpp:91
NoncopyableWithCounter::value
long long value
Definition: multiset.cpp:40
uavcan::snprintf
int snprintf(char *out, std::size_t maxlen, const char *format,...)
Definition: std.hpp:73
NoncopyableWithCounter::NoncopyableWithCounter
NoncopyableWithCounter()
Definition: multiset.cpp:42
FindPredicate::target
const std::string target
Definition: multiset.cpp:32
toString
static std::string toString(long x)
Definition: multiset.cpp:16
TEST
TEST(Multiset, Basic)
Definition: multiset.cpp:71
uavcan::PoolAllocator::getNumUsedBlocks
uint16_t getNumUsedBlocks() const
Definition: dynamic_memory.hpp:85
SummationOperator::accumulator
T accumulator
Definition: multiset.cpp:59
FindPredicate::FindPredicate
FindPredicate(const std::string &target)
Definition: multiset.cpp:33
NoncopyableWithCounter::num_objects
static int num_objects
Definition: multiset.cpp:39
SummationOperator::operator()
void operator()(const T &x)
Definition: multiset.cpp:61
ClearingOperator::operator()
void operator()(T &x) const
Definition: multiset.cpp:67
NoncopyableWithCounter::operator==
bool operator==(const NoncopyableWithCounter &ref) const
Definition: multiset.cpp:51
SummationOperator
Definition: multiset.cpp:57
SummationOperator::SummationOperator
SummationOperator()
Definition: multiset.cpp:60
uavcan::Multiset
Definition: multiset.hpp:29
NoncopyableWithCounter::~NoncopyableWithCounter
~NoncopyableWithCounter()
Definition: multiset.cpp:44
pyuavcan_v0.driver.timestamp_estimator.x
x
Definition: timestamp_estimator.py:221
FindPredicate::operator()
bool operator()(const std::string &value) const
Definition: multiset.cpp:34
NoncopyableWithCounter
Definition: multiset.cpp:37
ClearingOperator
Definition: multiset.cpp:64


uavcan_communicator
Author(s):
autogenerated on Fri Dec 13 2024 03:10:02