ForeachTest.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463
  1. /*
  2. * Copyright 2011-present Facebook, Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include <folly/container/Foreach.h>
  17. #include <array>
  18. #include <initializer_list>
  19. #include <iterator>
  20. #include <list>
  21. #include <map>
  22. #include <string>
  23. #include <tuple>
  24. #include <vector>
  25. #include <folly/portability/GTest.h>
  26. using namespace folly;
  27. using namespace folly::detail;
  28. namespace folly {
  29. namespace test {
  30. class TestRValueConstruct {
  31. public:
  32. TestRValueConstruct() = default;
  33. TestRValueConstruct(TestRValueConstruct&&) noexcept {
  34. this->constructed_from_rvalue = true;
  35. }
  36. TestRValueConstruct(const TestRValueConstruct&) {
  37. this->constructed_from_rvalue = false;
  38. }
  39. TestRValueConstruct& operator=(const TestRValueConstruct&) = delete;
  40. TestRValueConstruct& operator=(TestRValueConstruct&&) = delete;
  41. bool constructed_from_rvalue{false};
  42. };
  43. class TestAdlIterable {
  44. public:
  45. std::vector<int> vec{0, 1, 2, 3};
  46. };
  47. auto begin(TestAdlIterable& instance) {
  48. return instance.vec.begin();
  49. }
  50. auto begin(const TestAdlIterable& instance) {
  51. return instance.vec.begin();
  52. }
  53. auto end(TestAdlIterable& instance) {
  54. return instance.vec.end();
  55. }
  56. auto end(const TestAdlIterable& instance) {
  57. return instance.vec.end();
  58. }
  59. class TestBothIndexingAndIter {
  60. public:
  61. class Iterator {
  62. public:
  63. using difference_type = std::size_t;
  64. using value_type = int;
  65. using pointer = int*;
  66. using reference = int&;
  67. using iterator_category = std::random_access_iterator_tag;
  68. int& operator*() {
  69. return this->val;
  70. }
  71. Iterator operator+(int) {
  72. return *this;
  73. }
  74. explicit Iterator(int& val_in) : val{val_in} {}
  75. int& val;
  76. };
  77. auto begin() {
  78. this->called_begin = true;
  79. return Iterator{val};
  80. }
  81. auto end() {
  82. return Iterator{val};
  83. }
  84. int& operator[](int) {
  85. return this->val;
  86. }
  87. int val{0};
  88. bool called_begin = false;
  89. };
  90. } // namespace test
  91. } // namespace folly
  92. TEST(Foreach, ForEachFunctionBasic) {
  93. auto range = std::make_tuple(1, 2, 3);
  94. auto result_range = std::vector<int>{};
  95. auto correct_result_range = std::vector<int>{1, 2, 3};
  96. folly::for_each(range, [&](auto ele) { result_range.push_back(ele); });
  97. EXPECT_TRUE(std::equal(
  98. result_range.begin(), result_range.end(), correct_result_range.begin()));
  99. }
  100. TEST(Foreach, ForEachFunctionBasicRuntimeOneArg) {
  101. auto range = std::vector<int>{1, 2, 3};
  102. auto current = 0;
  103. folly::for_each(range, [&](auto ele) {
  104. if (current == 0) {
  105. EXPECT_EQ(ele, 1);
  106. } else if (current == 1) {
  107. EXPECT_EQ(ele, 2);
  108. } else {
  109. EXPECT_EQ(ele, 3);
  110. }
  111. ++current;
  112. });
  113. }
  114. TEST(Foreach, ForEachFunctionBasicRuntimeTwoArg) {
  115. auto range = std::vector<int>{1, 2, 3};
  116. folly::for_each(range, [](auto ele, auto index) {
  117. EXPECT_TRUE(index < 3);
  118. if (index == 0) {
  119. EXPECT_EQ(ele, 1);
  120. } else if (index == 1) {
  121. EXPECT_EQ(ele, 2);
  122. } else if (index == 2) {
  123. EXPECT_EQ(ele, 3);
  124. }
  125. });
  126. }
  127. TEST(Foreach, ForEachFunctionBasicRuntimeThreeArg) {
  128. auto range = std::list<int>{1, 2, 3};
  129. auto result_range = std::list<int>{1, 3};
  130. folly::for_each(range, [&](auto ele, auto, auto iter) {
  131. if (ele == 2) {
  132. range.erase(iter);
  133. }
  134. });
  135. EXPECT_TRUE(std::equal(range.begin(), range.end(), result_range.begin()));
  136. }
  137. TEST(Foreach, ForEachFunctionBasicTupleOneArg) {
  138. auto range = std::make_tuple(1, 2, 3);
  139. auto current = 0;
  140. folly::for_each(range, [&](auto ele) {
  141. if (current == 0) {
  142. EXPECT_EQ(ele, 1);
  143. } else if (current == 1) {
  144. EXPECT_EQ(ele, 2);
  145. } else {
  146. EXPECT_EQ(ele, 3);
  147. }
  148. ++current;
  149. });
  150. }
  151. TEST(Foreach, ForEachFunctionBasicTupleTwoArg) {
  152. auto range = std::make_tuple(1, 2, 3);
  153. folly::for_each(range, [](auto ele, auto index) {
  154. EXPECT_TRUE(index < 3);
  155. if (index == 0) {
  156. EXPECT_EQ(ele, 1);
  157. } else if (index == 1) {
  158. EXPECT_EQ(ele, 2);
  159. } else if (index == 2) {
  160. EXPECT_EQ(ele, 3);
  161. }
  162. });
  163. }
  164. TEST(Foreach, ForEachFunctionBreakRuntimeOneArg) {
  165. auto range = std::vector<int>{1, 2, 3};
  166. auto iterations = 0;
  167. folly::for_each(range, [&](auto) {
  168. ++iterations;
  169. if (iterations == 1) {
  170. return folly::loop_break;
  171. }
  172. return folly::loop_continue;
  173. });
  174. EXPECT_EQ(iterations, 1);
  175. }
  176. TEST(Foreach, ForEachFunctionBreakRuntimeTwoArg) {
  177. auto range = std::vector<int>{1, 2, 3};
  178. auto iterations = 0;
  179. folly::for_each(range, [&](auto, auto index) {
  180. ++iterations;
  181. if (index == 1) {
  182. return folly::loop_break;
  183. }
  184. return folly::loop_continue;
  185. });
  186. EXPECT_EQ(iterations, 2);
  187. }
  188. TEST(Foreach, ForEachFunctionBreakRuntimeThreeArg) {
  189. auto range = std::vector<int>{1, 2, 3};
  190. auto iterations = 0;
  191. folly::for_each(range, [&](auto, auto index, auto) {
  192. ++iterations;
  193. if (index == 1) {
  194. return folly::loop_break;
  195. }
  196. return folly::loop_continue;
  197. });
  198. EXPECT_EQ(iterations, 2);
  199. }
  200. TEST(Foreach, ForEachFunctionBreakTupleOneArg) {
  201. auto range = std::vector<int>{1, 2, 3};
  202. auto iterations = 0;
  203. folly::for_each(range, [&](auto) {
  204. ++iterations;
  205. if (iterations == 1) {
  206. return folly::loop_break;
  207. }
  208. return folly::loop_continue;
  209. });
  210. EXPECT_EQ(iterations, 1);
  211. }
  212. TEST(Foreach, ForEachFunctionBreakTupleTwoArg) {
  213. auto range = std::vector<int>{1, 2, 3};
  214. auto iterations = 0;
  215. folly::for_each(range, [&](auto, auto index) {
  216. ++iterations;
  217. if (index == 1) {
  218. return folly::loop_break;
  219. }
  220. return folly::loop_continue;
  221. });
  222. EXPECT_EQ(iterations, 2);
  223. }
  224. TEST(Foreach, ForEachFunctionArray) {
  225. auto range = std::array<int, 3>{{1, 2, 3}};
  226. auto iterations = 0;
  227. folly::for_each(range, [&](auto, auto index) {
  228. ++iterations;
  229. if (index == 1) {
  230. return folly::loop_break;
  231. }
  232. return folly::loop_continue;
  233. });
  234. EXPECT_EQ(iterations, 2);
  235. }
  236. TEST(Foreach, ForEachFunctionInitializerListBasic) {
  237. folly::for_each(std::initializer_list<int>{1, 2, 3}, [](auto ele) { ++ele; });
  238. }
  239. TEST(Foreach, ForEachFunctionTestForward) {
  240. using folly::test::TestRValueConstruct;
  241. auto range_one = std::vector<TestRValueConstruct>{};
  242. range_one.resize(3);
  243. folly::for_each(std::move(range_one), [](auto ele) {
  244. EXPECT_FALSE(ele.constructed_from_rvalue);
  245. });
  246. folly::for_each(
  247. std::make_tuple(TestRValueConstruct{}, TestRValueConstruct{}),
  248. [](auto ele) { EXPECT_TRUE(ele.constructed_from_rvalue); });
  249. }
  250. TEST(Foreach, ForEachFunctionAdlIterable) {
  251. auto range = test::TestAdlIterable{};
  252. auto iterations = 0;
  253. folly::for_each(range, [&](auto ele, auto index) {
  254. ++iterations;
  255. EXPECT_EQ(ele, index);
  256. });
  257. EXPECT_EQ(iterations, 4);
  258. }
  259. TEST(ForEach, FetchRandomAccessIterator) {
  260. auto vec = std::vector<int>{1, 2, 3};
  261. auto& second = folly::fetch(vec, 1);
  262. EXPECT_EQ(second, 2);
  263. second = 3;
  264. EXPECT_EQ(second, 3);
  265. }
  266. TEST(ForEach, FetchIndexing) {
  267. auto mp = std::map<int, int>{{1, 2}};
  268. auto& ele = folly::fetch(mp, 1);
  269. EXPECT_EQ(ele, 2);
  270. ele = 3;
  271. EXPECT_EQ(ele, 3);
  272. }
  273. TEST(ForEach, FetchTuple) {
  274. auto mp = std::make_tuple(1, 2, 3);
  275. auto& ele = folly::fetch(mp, std::integral_constant<int, 1>{});
  276. EXPECT_EQ(ele, 2);
  277. ele = 3;
  278. EXPECT_EQ(ele, 3);
  279. }
  280. TEST(ForEach, FetchTestPreferIterator) {
  281. auto range = test::TestBothIndexingAndIter{};
  282. auto& ele = folly::fetch(range, 0);
  283. EXPECT_TRUE(range.called_begin);
  284. EXPECT_EQ(ele, 0);
  285. ele = 2;
  286. EXPECT_EQ(folly::fetch(range, 0), 2);
  287. }
  288. TEST(Foreach, ForEachRvalue) {
  289. const char* const hello = "hello";
  290. int n = 0;
  291. FOR_EACH (it, std::string(hello)) { ++n; }
  292. EXPECT_EQ(strlen(hello), n);
  293. FOR_EACH_R (it, std::string(hello)) {
  294. --n;
  295. EXPECT_EQ(hello[n], *it);
  296. }
  297. EXPECT_EQ(0, n);
  298. }
  299. TEST(Foreach, ForEachNested) {
  300. const std::string hello = "hello";
  301. size_t n = 0;
  302. FOR_EACH (i, hello) {
  303. FOR_EACH (j, hello) { ++n; }
  304. }
  305. auto len = hello.size();
  306. EXPECT_EQ(len * len, n);
  307. }
  308. TEST(Foreach, ForEachKV) {
  309. std::map<std::string, int> testMap;
  310. testMap["abc"] = 1;
  311. testMap["def"] = 2;
  312. std::string keys = "";
  313. int values = 0;
  314. int numEntries = 0;
  315. FOR_EACH_KV (key, value, testMap) {
  316. keys += key;
  317. values += value;
  318. ++numEntries;
  319. }
  320. EXPECT_EQ("abcdef", keys);
  321. EXPECT_EQ(3, values);
  322. EXPECT_EQ(2, numEntries);
  323. }
  324. TEST(Foreach, ForEachKVBreak) {
  325. std::map<std::string, int> testMap;
  326. testMap["abc"] = 1;
  327. testMap["def"] = 2;
  328. std::string keys = "";
  329. int values = 0;
  330. int numEntries = 0;
  331. FOR_EACH_KV (key, value, testMap) {
  332. keys += key;
  333. values += value;
  334. ++numEntries;
  335. break;
  336. }
  337. EXPECT_EQ("abc", keys);
  338. EXPECT_EQ(1, values);
  339. EXPECT_EQ(1, numEntries);
  340. }
  341. TEST(Foreach, ForEachKvWithMultiMap) {
  342. std::multimap<std::string, int> testMap;
  343. testMap.insert(std::make_pair("abc", 1));
  344. testMap.insert(std::make_pair("abc", 2));
  345. testMap.insert(std::make_pair("def", 3));
  346. std::string keys = "";
  347. int values = 0;
  348. int numEntries = 0;
  349. FOR_EACH_KV (key, value, testMap) {
  350. keys += key;
  351. values += value;
  352. ++numEntries;
  353. }
  354. EXPECT_EQ("abcabcdef", keys);
  355. EXPECT_EQ(6, values);
  356. EXPECT_EQ(3, numEntries);
  357. }
  358. TEST(Foreach, ForEachEnumerate) {
  359. std::vector<int> vv;
  360. int sumAA = 0;
  361. int sumIter = 0;
  362. int numIterations = 0;
  363. FOR_EACH_ENUMERATE (aa, iter, vv) {
  364. sumAA += aa;
  365. sumIter += *iter;
  366. ++numIterations;
  367. }
  368. EXPECT_EQ(sumAA, 0);
  369. EXPECT_EQ(sumIter, 0);
  370. EXPECT_EQ(numIterations, 0);
  371. vv.push_back(1);
  372. vv.push_back(3);
  373. vv.push_back(5);
  374. FOR_EACH_ENUMERATE (aa, iter, vv) {
  375. sumAA += aa;
  376. sumIter += *iter;
  377. ++numIterations;
  378. }
  379. EXPECT_EQ(sumAA, 3); // 0 + 1 + 2
  380. EXPECT_EQ(sumIter, 9); // 1 + 3 + 5
  381. EXPECT_EQ(numIterations, 3);
  382. }
  383. TEST(Foreach, ForEachEnumerateBreak) {
  384. std::vector<int> vv;
  385. int sumAA = 0;
  386. int sumIter = 0;
  387. int numIterations = 0;
  388. vv.push_back(1);
  389. vv.push_back(2);
  390. vv.push_back(4);
  391. vv.push_back(8);
  392. FOR_EACH_ENUMERATE (aa, iter, vv) {
  393. sumAA += aa;
  394. sumIter += *iter;
  395. ++numIterations;
  396. if (aa == 1) {
  397. break;
  398. }
  399. }
  400. EXPECT_EQ(sumAA, 1); // 0 + 1
  401. EXPECT_EQ(sumIter, 3); // 1 + 2
  402. EXPECT_EQ(numIterations, 2);
  403. }
  404. TEST(Foreach, ForEachRangeR) {
  405. int sum = 0;
  406. FOR_EACH_RANGE_R (i, 0, 0) { sum += i; }
  407. EXPECT_EQ(0, sum);
  408. FOR_EACH_RANGE_R (i, 0, -1) { sum += i; }
  409. EXPECT_EQ(0, sum);
  410. FOR_EACH_RANGE_R (i, 0, 5) { sum += i; }
  411. EXPECT_EQ(10, sum);
  412. std::list<int> lst = {0, 1, 2, 3, 4};
  413. sum = 0;
  414. FOR_EACH_RANGE_R (i, lst.begin(), lst.end()) { sum += *i; }
  415. EXPECT_EQ(10, sum);
  416. }