map_ut.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496
  1. #include "map.h"
  2. #include <library/cpp/testing/unittest/registar.h>
  3. #include <util/memory/pool.h>
  4. #include <algorithm>
  5. Y_UNIT_TEST_SUITE(TYMapTest) {
  6. template <typename TAlloc>
  7. void DoTestMap1(TMap<char, int, TLess<char>, TAlloc>& m);
  8. template <typename TAlloc>
  9. void DoTestMMap1(TMultiMap<char, int, TLess<char>, TAlloc>& mm);
  10. Y_UNIT_TEST(TestMap1) {
  11. {
  12. TMap<char, int, TLess<char>> m;
  13. DoTestMap1(m);
  14. }
  15. {
  16. TMemoryPool p(100);
  17. TMap<char, int, TLess<char>, TPoolAllocator> m(&p);
  18. DoTestMap1(m);
  19. }
  20. }
  21. Y_UNIT_TEST(TestMMap1) {
  22. {
  23. TMultiMap<char, int, TLess<char>> mm;
  24. DoTestMMap1(mm);
  25. }
  26. {
  27. TMemoryPool p(100);
  28. TMultiMap<char, int, TLess<char>, TPoolAllocator> mm(&p);
  29. DoTestMMap1(mm);
  30. }
  31. }
  32. template <typename TAlloc>
  33. void DoTestMap1(TMap<char, int, TLess<char>, TAlloc>& m) {
  34. using maptype = TMap<char, int, TLess<char>, TAlloc>;
  35. // Store mappings between roman numerals and decimals.
  36. m['l'] = 50;
  37. m['x'] = 20; // Deliberate mistake.
  38. m['v'] = 5;
  39. m['i'] = 1;
  40. UNIT_ASSERT(m['x'] == 20);
  41. m['x'] = 10; // Correct mistake.
  42. UNIT_ASSERT(m['x'] == 10);
  43. UNIT_ASSERT(m['z'] == 0);
  44. UNIT_ASSERT(m.count('z') == 1);
  45. std::pair<typename maptype::iterator, bool> p = m.insert(std::pair<const char, int>('c', 100));
  46. UNIT_ASSERT(p.second);
  47. UNIT_ASSERT(p.first != m.end());
  48. UNIT_ASSERT((*p.first).first == 'c');
  49. UNIT_ASSERT((*p.first).second == 100);
  50. p = m.insert(std::pair<const char, int>('c', 100));
  51. UNIT_ASSERT(!p.second); // already existing pair
  52. UNIT_ASSERT(p.first != m.end());
  53. UNIT_ASSERT((*p.first).first == 'c');
  54. UNIT_ASSERT((*p.first).second == 100);
  55. }
  56. template <typename TAlloc>
  57. void DoTestMMap1(TMultiMap<char, int, TLess<char>, TAlloc>& m) {
  58. using mmap = TMultiMap<char, int, TLess<char>, TAlloc>;
  59. UNIT_ASSERT(m.count('X') == 0);
  60. m.insert(std::pair<const char, int>('X', 10)); // Standard way.
  61. UNIT_ASSERT(m.count('X') == 1);
  62. m.insert(std::pair<const char, int>('X', 20)); // jbuck: standard way
  63. UNIT_ASSERT(m.count('X') == 2);
  64. m.insert(std::pair<const char, int>('Y', 32)); // jbuck: standard way
  65. typename mmap::iterator i = m.find('X'); // Find first match.
  66. ++i;
  67. UNIT_ASSERT((*i).first == 'X');
  68. UNIT_ASSERT((*i).second == 20);
  69. ++i;
  70. UNIT_ASSERT((*i).first == 'Y');
  71. UNIT_ASSERT((*i).second == 32);
  72. ++i;
  73. UNIT_ASSERT(i == m.end());
  74. size_t count = m.erase('X');
  75. UNIT_ASSERT(count == 2);
  76. }
  77. Y_UNIT_TEST(TestMMap2) {
  78. using pair_type = std::pair<const int, char>;
  79. pair_type p1(3, 'c');
  80. pair_type p2(6, 'f');
  81. pair_type p3(1, 'a');
  82. pair_type p4(2, 'b');
  83. pair_type p5(3, 'x');
  84. pair_type p6(6, 'f');
  85. using mmap = TMultiMap<int, char, TLess<int>>;
  86. pair_type array[] = {
  87. p1,
  88. p2,
  89. p3,
  90. p4,
  91. p5,
  92. p6};
  93. mmap m(array + 0, array + 6);
  94. mmap::iterator i;
  95. i = m.lower_bound(3);
  96. UNIT_ASSERT((*i).first == 3);
  97. UNIT_ASSERT((*i).second == 'c');
  98. i = m.upper_bound(3);
  99. UNIT_ASSERT((*i).first == 6);
  100. UNIT_ASSERT((*i).second == 'f');
  101. }
  102. Y_UNIT_TEST(TestIterators) {
  103. using int_map = TMap<int, char, TLess<int>>;
  104. int_map imap;
  105. {
  106. int_map::iterator ite(imap.begin());
  107. int_map::const_iterator cite(imap.begin());
  108. UNIT_ASSERT(ite == cite);
  109. UNIT_ASSERT(!(ite != cite));
  110. UNIT_ASSERT(cite == ite);
  111. UNIT_ASSERT(!(cite != ite));
  112. }
  113. using mmap = TMultiMap<int, char, TLess<int>>;
  114. using pair_type = mmap::value_type;
  115. pair_type p1(3, 'c');
  116. pair_type p2(6, 'f');
  117. pair_type p3(1, 'a');
  118. pair_type p4(2, 'b');
  119. pair_type p5(3, 'x');
  120. pair_type p6(6, 'f');
  121. pair_type array[] = {
  122. p1,
  123. p2,
  124. p3,
  125. p4,
  126. p5,
  127. p6};
  128. mmap m(array + 0, array + 6);
  129. {
  130. mmap::iterator ite(m.begin());
  131. mmap::const_iterator cite(m.begin());
  132. //test compare between const_iterator and iterator
  133. UNIT_ASSERT(ite == cite);
  134. UNIT_ASSERT(!(ite != cite));
  135. UNIT_ASSERT(cite == ite);
  136. UNIT_ASSERT(!(cite != ite));
  137. }
  138. mmap::reverse_iterator ri = m.rbegin();
  139. UNIT_ASSERT(ri != m.rend());
  140. UNIT_ASSERT(ri == m.rbegin());
  141. UNIT_ASSERT((*ri).first == 6);
  142. UNIT_ASSERT((*ri++).second == 'f');
  143. UNIT_ASSERT((*ri).first == 6);
  144. UNIT_ASSERT((*ri).second == 'f');
  145. mmap const& cm = m;
  146. mmap::const_reverse_iterator rci = cm.rbegin();
  147. UNIT_ASSERT(rci != cm.rend());
  148. UNIT_ASSERT((*rci).first == 6);
  149. UNIT_ASSERT((*rci++).second == 'f');
  150. UNIT_ASSERT((*rci).first == 6);
  151. UNIT_ASSERT((*rci).second == 'f');
  152. }
  153. Y_UNIT_TEST(TestEqualRange) {
  154. using maptype = TMap<char, int, TLess<char>>;
  155. {
  156. maptype m;
  157. m['x'] = 10;
  158. std::pair<maptype::iterator, maptype::iterator> ret;
  159. ret = m.equal_range('x');
  160. UNIT_ASSERT(ret.first != ret.second);
  161. UNIT_ASSERT((*(ret.first)).first == 'x');
  162. UNIT_ASSERT((*(ret.first)).second == 10);
  163. UNIT_ASSERT(++(ret.first) == ret.second);
  164. }
  165. {
  166. {
  167. maptype m;
  168. maptype::iterator i = m.lower_bound('x');
  169. UNIT_ASSERT(i == m.end());
  170. i = m.upper_bound('x');
  171. UNIT_ASSERT(i == m.end());
  172. std::pair<maptype::iterator, maptype::iterator> ret;
  173. ret = m.equal_range('x');
  174. UNIT_ASSERT(ret.first == ret.second);
  175. UNIT_ASSERT(ret.first == m.end());
  176. }
  177. {
  178. const maptype m;
  179. std::pair<maptype::const_iterator, maptype::const_iterator> ret;
  180. ret = m.equal_range('x');
  181. UNIT_ASSERT(ret.first == ret.second);
  182. UNIT_ASSERT(ret.first == m.end());
  183. }
  184. }
  185. }
  186. struct TKey {
  187. TKey()
  188. : m_data(0)
  189. {
  190. }
  191. explicit TKey(int data)
  192. : m_data(data)
  193. {
  194. }
  195. int m_data;
  196. };
  197. struct TKeyCmp {
  198. bool operator()(TKey lhs, TKey rhs) const {
  199. return lhs.m_data < rhs.m_data;
  200. }
  201. bool operator()(TKey lhs, int rhs) const {
  202. return lhs.m_data < rhs;
  203. }
  204. bool operator()(int lhs, TKey rhs) const {
  205. return lhs < rhs.m_data;
  206. }
  207. using is_transparent = void;
  208. };
  209. struct TKeyCmpPtr {
  210. bool operator()(TKey const volatile* lhs, TKey const volatile* rhs) const {
  211. return (*lhs).m_data < (*rhs).m_data;
  212. }
  213. bool operator()(TKey const volatile* lhs, int rhs) const {
  214. return (*lhs).m_data < rhs;
  215. }
  216. bool operator()(int lhs, TKey const volatile* rhs) const {
  217. return lhs < (*rhs).m_data;
  218. }
  219. using is_transparent = void;
  220. };
  221. Y_UNIT_TEST(TestTemplateMethods) {
  222. {
  223. using Container = TMap<TKey, int, TKeyCmp>;
  224. using value = Container::value_type;
  225. Container cont;
  226. cont.insert(value(TKey(1), 1));
  227. cont.insert(value(TKey(2), 2));
  228. cont.insert(value(TKey(3), 3));
  229. cont.insert(value(TKey(4), 4));
  230. UNIT_ASSERT(cont.count(TKey(1)) == 1);
  231. UNIT_ASSERT(cont.count(1) == 1);
  232. UNIT_ASSERT(cont.count(5) == 0);
  233. UNIT_ASSERT(cont.find(2) != cont.end());
  234. UNIT_ASSERT(cont.lower_bound(2) != cont.end());
  235. UNIT_ASSERT(cont.upper_bound(2) != cont.end());
  236. UNIT_ASSERT(cont.equal_range(2) != std::make_pair(cont.begin(), cont.end()));
  237. Container const& ccont = cont;
  238. UNIT_ASSERT(ccont.find(2) != ccont.end());
  239. UNIT_ASSERT(ccont.lower_bound(2) != ccont.end());
  240. UNIT_ASSERT(ccont.upper_bound(2) != ccont.end());
  241. UNIT_ASSERT(ccont.equal_range(2) != std::make_pair(ccont.end(), ccont.end()));
  242. }
  243. {
  244. using Container = TMap<TKey*, int, TKeyCmpPtr>;
  245. using value = Container::value_type;
  246. Container cont;
  247. TKey key1(1), key2(2), key3(3), key4(4);
  248. cont.insert(value(&key1, 1));
  249. cont.insert(value(&key2, 2));
  250. cont.insert(value(&key3, 3));
  251. cont.insert(value(&key4, 4));
  252. UNIT_ASSERT(cont.count(1) == 1);
  253. UNIT_ASSERT(cont.count(5) == 0);
  254. UNIT_ASSERT(cont.find(2) != cont.end());
  255. UNIT_ASSERT(cont.lower_bound(2) != cont.end());
  256. UNIT_ASSERT(cont.upper_bound(2) != cont.end());
  257. UNIT_ASSERT(cont.equal_range(2) != std::make_pair(cont.begin(), cont.end()));
  258. Container const& ccont = cont;
  259. UNIT_ASSERT(ccont.find(2) != ccont.end());
  260. UNIT_ASSERT(ccont.lower_bound(2) != ccont.end());
  261. UNIT_ASSERT(ccont.upper_bound(2) != ccont.end());
  262. UNIT_ASSERT(ccont.equal_range(2) != std::make_pair(ccont.begin(), ccont.end()));
  263. }
  264. {
  265. using Container = TMultiMap<TKey, int, TKeyCmp>;
  266. using value = Container::value_type;
  267. Container cont;
  268. cont.insert(value(TKey(1), 1));
  269. cont.insert(value(TKey(2), 2));
  270. cont.insert(value(TKey(3), 3));
  271. cont.insert(value(TKey(4), 4));
  272. UNIT_ASSERT(cont.count(TKey(1)) == 1);
  273. UNIT_ASSERT(cont.count(1) == 1);
  274. UNIT_ASSERT(cont.count(5) == 0);
  275. UNIT_ASSERT(cont.find(2) != cont.end());
  276. UNIT_ASSERT(cont.lower_bound(2) != cont.end());
  277. UNIT_ASSERT(cont.upper_bound(2) != cont.end());
  278. UNIT_ASSERT(cont.equal_range(2) != std::make_pair(cont.begin(), cont.end()));
  279. Container const& ccont = cont;
  280. UNIT_ASSERT(ccont.find(2) != ccont.end());
  281. UNIT_ASSERT(ccont.lower_bound(2) != ccont.end());
  282. UNIT_ASSERT(ccont.upper_bound(2) != ccont.end());
  283. UNIT_ASSERT(ccont.equal_range(2) != std::make_pair(ccont.end(), ccont.end()));
  284. }
  285. {
  286. using Container = TMultiMap<TKey const volatile*, int, TKeyCmpPtr>;
  287. using value = Container::value_type;
  288. Container cont;
  289. TKey key1(1), key2(2), key3(3), key4(4);
  290. cont.insert(value(&key1, 1));
  291. cont.insert(value(&key2, 2));
  292. cont.insert(value(&key3, 3));
  293. cont.insert(value(&key4, 4));
  294. UNIT_ASSERT(cont.count(1) == 1);
  295. UNIT_ASSERT(cont.count(5) == 0);
  296. UNIT_ASSERT(cont.find(2) != cont.end());
  297. UNIT_ASSERT(cont.lower_bound(2) != cont.end());
  298. UNIT_ASSERT(cont.upper_bound(2) != cont.end());
  299. UNIT_ASSERT(cont.equal_range(2) != std::make_pair(cont.begin(), cont.end()));
  300. Container const& ccont = cont;
  301. UNIT_ASSERT(ccont.find(2) != ccont.end());
  302. UNIT_ASSERT(ccont.lower_bound(2) != ccont.end());
  303. UNIT_ASSERT(ccont.upper_bound(2) != ccont.end());
  304. UNIT_ASSERT(ccont.equal_range(2) != std::make_pair(ccont.begin(), ccont.end()));
  305. }
  306. }
  307. template <typename T>
  308. static void EmptyAndInsertTest(typename T::value_type v) {
  309. T c;
  310. UNIT_ASSERT(!c);
  311. c.insert(v);
  312. UNIT_ASSERT(c);
  313. }
  314. Y_UNIT_TEST(TestEmpty) {
  315. EmptyAndInsertTest<TMap<char, int, TLess<char>>>(std::pair<char, int>('a', 1));
  316. EmptyAndInsertTest<TMultiMap<char, int, TLess<char>>>(std::pair<char, int>('a', 1));
  317. }
  318. struct TParametrizedKeyCmp {
  319. bool Inverse;
  320. TParametrizedKeyCmp(bool inverse = false)
  321. : Inverse(inverse)
  322. {
  323. }
  324. bool operator()(TKey lhs, TKey rhs) const {
  325. if (Inverse) {
  326. return lhs.m_data > rhs.m_data;
  327. } else {
  328. return lhs.m_data < rhs.m_data;
  329. }
  330. }
  331. };
  332. Y_UNIT_TEST(TestMoveComparator) {
  333. using Container = TMultiMap<TKey, int, TParametrizedKeyCmp>;
  334. TParametrizedKeyCmp direct(false);
  335. TParametrizedKeyCmp inverse(true);
  336. {
  337. Container c(direct);
  338. c = Container(inverse);
  339. c.insert(std::make_pair(TKey(1), 101));
  340. c.insert(std::make_pair(TKey(2), 102));
  341. c.insert(std::make_pair(TKey(3), 103));
  342. TVector<int> values;
  343. for (auto& i : c) {
  344. values.push_back(i.second);
  345. }
  346. UNIT_ASSERT_VALUES_EQUAL(values.size(), 3);
  347. UNIT_ASSERT_VALUES_EQUAL(values[0], 103);
  348. UNIT_ASSERT_VALUES_EQUAL(values[1], 102);
  349. UNIT_ASSERT_VALUES_EQUAL(values[2], 101);
  350. }
  351. }
  352. Y_UNIT_TEST(TestMapInitializerList) {
  353. TMap<TString, int> m = {
  354. {"one", 1},
  355. {"two", 2},
  356. {"three", 3},
  357. {"four", 4},
  358. };
  359. UNIT_ASSERT_VALUES_EQUAL(m.size(), 4);
  360. UNIT_ASSERT_VALUES_EQUAL(m["one"], 1);
  361. UNIT_ASSERT_VALUES_EQUAL(m["two"], 2);
  362. UNIT_ASSERT_VALUES_EQUAL(m["three"], 3);
  363. UNIT_ASSERT_VALUES_EQUAL(m["four"], 4);
  364. }
  365. Y_UNIT_TEST(TestMMapInitializerList) {
  366. TMultiMap<TString, int> mm = {
  367. {"one", 1},
  368. {"two", 2},
  369. {"two", -2},
  370. {"three", 3},
  371. };
  372. UNIT_ASSERT(mm.contains("two"));
  373. TMultiMap<TString, int> expected;
  374. expected.emplace("one", 1);
  375. expected.emplace("two", 2);
  376. expected.emplace("two", -2);
  377. expected.emplace("three", 3);
  378. UNIT_ASSERT_VALUES_EQUAL(mm, expected);
  379. }
  380. Y_UNIT_TEST(TestMovePoolAlloc) {
  381. using TMapInPool = TMap<int, int, TLess<int>, TPoolAllocator>;
  382. TMemoryPool pool(1);
  383. TMapInPool m(&pool);
  384. m.emplace(0, 1);
  385. UNIT_ASSERT(m.contains(0));
  386. UNIT_ASSERT_VALUES_EQUAL(1, m[0]);
  387. TMapInPool movedM = std::move(m);
  388. UNIT_ASSERT(movedM.contains(0));
  389. UNIT_ASSERT_VALUES_EQUAL(1, movedM[0]);
  390. }
  391. }