PageRenderTime 73ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 1ms

/Test/CppLinqTests.hpp

http://cpplinq.codeplex.com
C++ Header | 3186 lines | 2560 code | 536 blank | 90 comment | 148 complexity | f10911cdf4db1fdd53a15b0a47816ee3 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. // ----------------------------------------------------------------------------------------------
  2. // Copyright (c) Mårten Rånge.
  3. // ----------------------------------------------------------------------------------------------
  4. // This source code is subject to terms and conditions of the Microsoft Public License. A
  5. // copy of the license can be found in the License.html file at the root of this distribution.
  6. // If you cannot locate the Microsoft Public License, please send an email to
  7. // dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
  8. // by the terms of the Microsoft Public License.
  9. // ----------------------------------------------------------------------------------------------
  10. // You must not remove this notice, or any other, from this software.
  11. // ----------------------------------------------------------------------------------------------
  12. #include "stdafx.h"
  13. // ----------------------------------------------------------------------------------------------
  14. #ifdef _MSC_VER
  15. # pragma warning (disable:4100)
  16. # pragma warning (disable:4996)
  17. #endif
  18. // ----------------------------------------------------------------------------------------------
  19. #ifdef _MSC_VER
  20. # include <windows.h>
  21. #endif
  22. // ----------------------------------------------------------------------------------------------
  23. #include <algorithm>
  24. #include <chrono>
  25. #include <cstdint>
  26. #include <map>
  27. #include <numeric>
  28. #include <set>
  29. #include <string>
  30. #include <sstream>
  31. #include <vector>
  32. // ----------------------------------------------------------------------------------------------
  33. #include <limits.h>
  34. #include <stdio.h>
  35. // ----------------------------------------------------------------------------------------------
  36. #include "../CppLinq/cpplinq.hpp"
  37. // ----------------------------------------------------------------------------------------------
  38. #define TEST_PRELUDE() test_prelude(__FILE__, __LINE__, __FUNCTION__)
  39. #define TEST_ASSERT(expected, found) test_assert(__FILE__, __LINE__, expected, #expected, found, #found, (expected == found))
  40. #define PRINT_INDEX(idx) print_index (#idx, idx);
  41. // ----------------------------------------------------------------------------------------------
  42. namespace
  43. {
  44. struct customer
  45. {
  46. std::size_t id ;
  47. std::string first_name ;
  48. std::string last_name ;
  49. customer (std::size_t id = 0, std::string first_name = "", std::string last_name = "")
  50. : id (std::move (id))
  51. , first_name (std::move (first_name))
  52. , last_name (std::move (last_name))
  53. {
  54. }
  55. customer & operator= (customer const & c)
  56. {
  57. if (std::addressof (c) == this)
  58. {
  59. return *this;
  60. }
  61. id = c.id ;
  62. first_name = c.first_name ;
  63. last_name = c.last_name ;
  64. return *this;
  65. }
  66. customer (customer const & c)
  67. : id (c.id)
  68. , first_name (c.first_name)
  69. , last_name (c.last_name)
  70. {
  71. }
  72. customer (customer && c)
  73. : id (std::move (c.id))
  74. , first_name (std::move (c.first_name))
  75. , last_name (std::move (c.last_name))
  76. {
  77. }
  78. bool operator==(customer const & c) const
  79. {
  80. return id == c.id && first_name == c.first_name && last_name == c.last_name;
  81. }
  82. bool operator !=(customer const & c) const
  83. {
  84. return !(*this == c);
  85. }
  86. bool operator<(customer const & c) const
  87. {
  88. return id < c.id;
  89. }
  90. };
  91. struct customer_address
  92. {
  93. std::size_t id ;
  94. std::size_t customer_id ;
  95. std::string country ;
  96. customer_address (std::size_t id, std::size_t customer_id, std::string country)
  97. : id (std::move (id))
  98. , customer_id (std::move (customer_id))
  99. , country (std::move (country))
  100. {
  101. }
  102. };
  103. struct player
  104. {
  105. std::size_t id;
  106. };
  107. struct game
  108. {
  109. std::size_t id ;
  110. std::set<player*> players ;
  111. };
  112. template <typename T>
  113. void ignore (T && v) CPPLINQ_NOEXCEPT
  114. {
  115. }
  116. template<typename TValueArray>
  117. std::size_t get_array_size (TValueArray & a)
  118. {
  119. return cpplinq::detail::get_array_properties<TValueArray>::size;
  120. }
  121. std::size_t get_even_counts (int const * is, std::size_t count)
  122. {
  123. auto c = 0U;
  124. for (auto index = 0U; index < count; ++index)
  125. {
  126. auto i = is[index];
  127. if (i%2 == 0)
  128. {
  129. ++c;
  130. }
  131. }
  132. return c;
  133. }
  134. std::size_t errors = 0U;
  135. std::vector<int> const empty_vector ;
  136. std::vector<customer> empty_customers ;
  137. customer const customers[] =
  138. {
  139. customer (1 , "Bill" , "Gates" ),
  140. customer (2 , "Steve" , "Jobs" ),
  141. customer (3 , "Richard" , "Stallman"),
  142. customer (4 , "Linus" , "Torvalds"),
  143. customer (11, "Steve" , "Ballmer" ),
  144. customer (12, "Tim" , "Cook" ),
  145. customer (21, "Melinda" , "Gates" ),
  146. };
  147. std::size_t const count_of_customers = get_array_size (customers);
  148. customer_address const customer_addresses[] =
  149. {
  150. customer_address (2, 4, "Finland" ),
  151. customer_address (3, 4, "USA" ),
  152. customer_address (1, 1, "USA" ),
  153. };
  154. std::size_t const count_of_customer_addresses = get_array_size (customer_addresses);
  155. customer const customers_set1[] =
  156. {
  157. customer (1 , "Bill" , "Gates" ),
  158. customer (2 , "Steve" , "Jobs" ),
  159. customer (3 , "Richard" , "Stallman"),
  160. customer (4 , "Linus" , "Torvalds"),
  161. customer (3 , "Richard" , "Stallman"),
  162. customer (2 , "Steve" , "Jobs" ),
  163. customer (1 , "Bill" , "Gates" ),
  164. };
  165. customer const customers_set2[] =
  166. {
  167. customer (1 , "Bill" , "Gates" ),
  168. customer (11, "Steve" , "Ballmer" ),
  169. customer (12, "Tim" , "Cook" ),
  170. };
  171. int const ints[] = {3,1,4,1,5,9,2,6,5,3,5,8,9,7,9,3,2,3,8,4,6,2,6,4,3,3,8,3,2,7,9,5};
  172. std::size_t const count_of_ints = get_array_size (ints);
  173. std::size_t const even_count_of_ints = get_even_counts (ints, count_of_ints);
  174. int const simple_ints[] = {1,2,3,4,5,6,7,8,9};
  175. std::size_t const count_of_simple_ints = get_array_size (simple_ints);
  176. int const set1[] = {5,4,3,2,1,2,3,4,5};
  177. std::size_t const count_of_set1 = get_array_size (set1);
  178. int const set2[] = {9,8,4,5,6,7,1,8,9};
  179. std::size_t const count_of_set2 = get_array_size (set2);
  180. double const double_set[] = {-1.0,0.0,2.0};
  181. std::size_t const count_of_double_set = get_array_size (double_set);
  182. std::set<game*> empty_game_set ;
  183. auto is_even = [](int i) {return i%2==0;};
  184. auto is_odd = [](int i) {return i%2==1;};
  185. auto smaller_than_five = [](int i) {return i < 5;};
  186. auto greater_than_five = [](int i) {return i > 5;};
  187. auto double_it = [](int i) {return i+i;};
  188. auto sum_aggregator = [](int s, int i) {return s+i;};
  189. auto mul_aggregator = [](int s, int i) {return s*i;};
  190. auto to_string = [](int i) -> std::string {std::stringstream sstr; sstr<<i; return sstr.str ();};
  191. void print_index (char const * name, std::size_t index)
  192. {
  193. printf (" @%s:%u\n", name, static_cast<std::uint32_t> (index)); // VS doesn't support %zu yet
  194. }
  195. void test_prelude (
  196. char const * file
  197. , int line_no
  198. , char const * test
  199. )
  200. {
  201. printf (
  202. "%s(%d): RUNNING: %s\n"
  203. , file
  204. , line_no
  205. , test
  206. );
  207. }
  208. bool test_assert (
  209. char const * file
  210. , int line_no
  211. , bool expected
  212. , char const * expected_name
  213. , bool found
  214. , char const * found_name
  215. , bool result
  216. )
  217. {
  218. if (!result)
  219. {
  220. ++errors;
  221. printf (
  222. "%s(%d): ERROR_EXPECTED: %s(%s), FOUND: %s(%s)\n"
  223. , file
  224. , line_no
  225. , expected ? "true" : "false"
  226. , expected_name
  227. , found ? "true" : "false"
  228. , found_name
  229. );
  230. }
  231. return result;
  232. }
  233. bool test_assert (
  234. char const * file
  235. , int line_no
  236. , std::string expected
  237. , char const * expected_name
  238. , std::string found
  239. , char const * found_name
  240. , bool result
  241. )
  242. {
  243. if (!result)
  244. {
  245. ++errors;
  246. printf (
  247. "%s(%d): ERROR_EXPECTED: %s(%s), FOUND: %s(%s)\n"
  248. , file
  249. , line_no
  250. , expected.c_str ()
  251. , expected_name
  252. , found.c_str ()
  253. , found_name
  254. );
  255. }
  256. return result;
  257. }
  258. bool test_assert (
  259. char const * file
  260. , int line_no
  261. , int expected
  262. , char const * expected_name
  263. , int found
  264. , char const * found_name
  265. , bool result
  266. )
  267. {
  268. if (!result)
  269. {
  270. ++errors;
  271. printf (
  272. "%s(%d): ERROR_EXPECTED: %d(%s), FOUND: %d(%s)\n"
  273. , file
  274. , line_no
  275. , expected
  276. , expected_name
  277. , found
  278. , found_name
  279. );
  280. }
  281. return result;
  282. }
  283. bool test_assert (
  284. char const * file
  285. , int line_no
  286. , double expected
  287. , char const * expected_name
  288. , double found
  289. , char const * found_name
  290. , bool result
  291. )
  292. {
  293. if (!result)
  294. {
  295. ++errors;
  296. printf (
  297. "%s(%d): ERROR_EXPECTED: %f(%s), FOUND: %f(%s)\n"
  298. , file
  299. , line_no
  300. , expected
  301. , expected_name
  302. , found
  303. , found_name
  304. );
  305. }
  306. return result;
  307. }
  308. bool test_assert (
  309. char const * file
  310. , int line_no
  311. , std::size_t expected
  312. , char const * expected_name
  313. , std::size_t found
  314. , char const * found_name
  315. , bool result
  316. )
  317. {
  318. if (!result)
  319. {
  320. ++errors;
  321. printf (
  322. "%s(%d): ERROR_EXPECTED: %u(%s), FOUND: %u(%s)\n"
  323. , file
  324. , line_no
  325. , static_cast<std::uint32_t> (expected) // VS doesn't support %zu yet
  326. , expected_name
  327. , static_cast<std::uint32_t> (found) // VS doesn't support %zu yet
  328. , found_name
  329. );
  330. }
  331. return result;
  332. }
  333. bool test_assert (
  334. char const * file
  335. , int line_no
  336. , customer expected
  337. , char const * expected_name
  338. , customer found
  339. , char const * found_name
  340. , bool result
  341. )
  342. {
  343. if (!result)
  344. {
  345. ++errors;
  346. printf (
  347. "%s(%d): ERROR_EXPECTED: (%u,%s,%s)(%s), FOUND: (%u,%s,%s)(%s)\n"
  348. , file
  349. , line_no
  350. , static_cast<std::uint32_t> (expected.id), expected.first_name.c_str (), expected.last_name.c_str () // VS doesn't support %zu yet
  351. , expected_name
  352. , static_cast<std::uint32_t> (found.id), found.first_name.c_str (), found.last_name.c_str () // VS doesn't support %zu yet
  353. , found_name
  354. );
  355. }
  356. return result;
  357. }
  358. void test_int_at (std::size_t index, int v)
  359. {
  360. if (
  361. TEST_ASSERT (true, (index < count_of_ints))
  362. && TEST_ASSERT (ints[index], v)
  363. )
  364. {
  365. }
  366. else
  367. {
  368. PRINT_INDEX (index);
  369. }
  370. }
  371. void test_opt ()
  372. {
  373. using namespace cpplinq::detail;
  374. TEST_PRELUDE ();
  375. {
  376. opt<int> o;
  377. TEST_ASSERT (false, o.has_value ());
  378. // Test to make sure that 'if (o)' compiles
  379. if (o)
  380. {
  381. }
  382. }
  383. {
  384. opt<int> o1;
  385. opt<int> o2 (10);
  386. TEST_ASSERT (false, o1.has_value ());
  387. TEST_ASSERT (true, o2.has_value ());
  388. TEST_ASSERT (10, *o2);
  389. o1 = o1;
  390. o2 = o2;
  391. TEST_ASSERT (false, o1.has_value ());
  392. TEST_ASSERT (true, o2.has_value ());
  393. TEST_ASSERT (10, *o2);
  394. o1 = std::move (o1);
  395. o2 = std::move (o2);
  396. TEST_ASSERT (false, o1.has_value ());
  397. TEST_ASSERT (true, o2.has_value ());
  398. TEST_ASSERT (10, *o2);
  399. opt<int> o3 (o2);
  400. opt<int> o4 (o1);
  401. o3.swap (o4);
  402. TEST_ASSERT (false, o3.has_value ());
  403. TEST_ASSERT (true, o4.has_value ());
  404. TEST_ASSERT (10, *o4);
  405. o1.swap (o2);
  406. TEST_ASSERT (true, o1.has_value ());
  407. TEST_ASSERT (10, *o1);
  408. TEST_ASSERT (false, o2.has_value ());
  409. o2 = o1;
  410. TEST_ASSERT (true, o1.has_value ());
  411. TEST_ASSERT (10, *o1);
  412. TEST_ASSERT (true, o2.has_value ());
  413. TEST_ASSERT (10, *o2);
  414. o1 = 11;
  415. o2 = 12;
  416. TEST_ASSERT (true, o1.has_value ());
  417. TEST_ASSERT (11, *o1);
  418. TEST_ASSERT (true, o2.has_value ());
  419. TEST_ASSERT (12, *o2);
  420. }
  421. {
  422. opt<std::string> o1;
  423. opt<std::string> o2 ("Test");
  424. TEST_ASSERT (false, o1.has_value ());
  425. TEST_ASSERT (true, o2.has_value ());
  426. TEST_ASSERT ("Test", *o2);
  427. TEST_ASSERT (4U, o2->size ());
  428. o1 = "Test2";
  429. o2 = "Test3";
  430. TEST_ASSERT (true, o1.has_value ());
  431. TEST_ASSERT ("Test2", *o1);
  432. TEST_ASSERT (true, o2.has_value ());
  433. TEST_ASSERT ("Test3", *o2);
  434. o1.swap (o2);
  435. TEST_ASSERT (true, o1.has_value ());
  436. TEST_ASSERT ("Test3", *o1);
  437. TEST_ASSERT (true, o2.has_value ());
  438. TEST_ASSERT ("Test2", *o2);
  439. }
  440. {
  441. opt<int> o (1);
  442. TEST_ASSERT (true, o.has_value ());
  443. o.clear ();
  444. TEST_ASSERT (false, o.has_value ());
  445. }
  446. }
  447. void test_lookup ()
  448. {
  449. using namespace cpplinq;
  450. using namespace cpplinq::detail;
  451. TEST_PRELUDE ();
  452. {
  453. lookup<size_type, customer> lookup (
  454. 16U
  455. , from (empty_customers)
  456. , [] (customer const & c){return c.id;}
  457. );
  458. TEST_ASSERT (0U, lookup.size_of_keys ());
  459. TEST_ASSERT (0U, lookup.size_of_values ());
  460. {
  461. auto results = lookup[999] >> to_vector ();
  462. TEST_ASSERT (0U, results.size ());
  463. }
  464. {
  465. auto results = lookup.range_of_values () >> to_vector ();
  466. TEST_ASSERT (0U, results.size ());
  467. }
  468. }
  469. {
  470. lookup<size_type, customer> lookup (
  471. 16U
  472. , from_array (customers)
  473. , [] (customer const & c){return c.id;}
  474. );
  475. TEST_ASSERT (count_of_customers, lookup.size_of_keys ());
  476. TEST_ASSERT (count_of_customers, lookup.size_of_values ());
  477. {
  478. auto results = lookup.range_of_values () >> to_vector ();
  479. if (TEST_ASSERT (count_of_customers, results.size ()))
  480. {
  481. for (std::size_t iter = 0U; iter < count_of_customers; ++iter)
  482. {
  483. // As customers are sorted on id in the test data set
  484. // this is ok
  485. if (!TEST_ASSERT (customers[iter].id, results[iter].id))
  486. {
  487. PRINT_INDEX (iter);
  488. }
  489. }
  490. }
  491. }
  492. for (auto customer : customers)
  493. {
  494. auto results = lookup[customer.id] >> to_vector ();
  495. if (TEST_ASSERT (1U, results.size ()))
  496. {
  497. auto result = results.front ();
  498. if (!TEST_ASSERT (customer.id, result.id))
  499. {
  500. PRINT_INDEX (customer.id);
  501. }
  502. }
  503. else
  504. {
  505. PRINT_INDEX (customer.id);
  506. }
  507. }
  508. }
  509. {
  510. lookup<size_type, customer_address> lookup (
  511. 16U
  512. , from_array (customer_addresses)
  513. , [] (customer_address const & ca){return ca.customer_id;}
  514. );
  515. TEST_ASSERT (2U, lookup.size_of_keys ());
  516. TEST_ASSERT (count_of_customer_addresses, lookup.size_of_values ());
  517. {
  518. auto results = lookup.range_of_values () >> to_vector ();
  519. TEST_ASSERT (count_of_customer_addresses, results.size ());
  520. }
  521. {
  522. auto results = lookup[1] >> to_vector ();
  523. if (TEST_ASSERT (1U, results.size ()))
  524. {
  525. auto result = results.front ();
  526. TEST_ASSERT (1U, result.id);
  527. }
  528. }
  529. {
  530. auto results = lookup[4] >> to_vector ();
  531. if (TEST_ASSERT (2U, results.size ()))
  532. {
  533. auto result1 = results[0];
  534. TEST_ASSERT (2U, result1.id);
  535. auto result2 = results[1];
  536. TEST_ASSERT (3U, result2.id);
  537. }
  538. }
  539. {
  540. auto results = lookup[999] >> to_vector ();
  541. TEST_ASSERT (0U, results.size ());
  542. }
  543. }
  544. }
  545. void test_from ()
  546. {
  547. using namespace cpplinq;
  548. TEST_PRELUDE ();
  549. {
  550. auto q = from (empty_vector);
  551. typedef decltype (q.front ()) return_type;
  552. static_assert (
  553. std::is_reference<return_type>::value
  554. , "from::front () must return reference"
  555. );
  556. std::size_t index = 0U;
  557. while (q.next ())
  558. {
  559. test_int_at (index, q.front ());
  560. ++index;
  561. }
  562. TEST_ASSERT (0U, index);
  563. }
  564. {
  565. auto q = from_array (ints);
  566. typedef decltype (q.front ()) return_type;
  567. static_assert (
  568. std::is_reference<return_type>::value
  569. , "from::front () must return reference"
  570. );
  571. auto index = 0U;
  572. while (q.next ())
  573. {
  574. test_int_at (index, q.front ());
  575. ++index;
  576. }
  577. TEST_ASSERT (count_of_ints, index);
  578. }
  579. {
  580. auto q = from_copy (empty_vector);
  581. typedef decltype (q.front ()) return_type;
  582. static_assert (
  583. std::is_reference<return_type>::value
  584. , "from::front () must return reference"
  585. );
  586. std::size_t index = 0U;
  587. while (q.next ())
  588. {
  589. test_int_at (index, q.front ());
  590. ++index;
  591. }
  592. TEST_ASSERT (0U, index);
  593. }
  594. {
  595. std::vector<int> is (ints, ints + count_of_ints);
  596. auto q = from_copy (is);
  597. typedef decltype (q.front ()) return_type;
  598. static_assert (
  599. std::is_reference<return_type>::value
  600. , "from::front () must return reference"
  601. );
  602. auto index = 0U;
  603. while (q.next ())
  604. {
  605. test_int_at (index, q.front ());
  606. ++index;
  607. }
  608. TEST_ASSERT (count_of_ints, index);
  609. }
  610. {
  611. auto q = from_array (customers);
  612. typedef decltype (q.front ()) return_type;
  613. static_assert (
  614. std::is_reference<return_type>::value
  615. , "front () must return non-reference when value_type = customer"
  616. );
  617. }
  618. {
  619. std::vector<customer> cs;
  620. auto q = from_copy (cs);
  621. typedef decltype (q.front ()) return_type;
  622. static_assert (
  623. std::is_reference<return_type>::value
  624. , "front () must return non-reference when value_type = customer"
  625. );
  626. }
  627. }
  628. void test_range ()
  629. {
  630. using namespace cpplinq;
  631. TEST_PRELUDE ();
  632. {
  633. auto r = range (10, 0);
  634. typedef decltype (r.front ()) return_type;
  635. static_assert (
  636. !std::is_reference<return_type>::value
  637. , "front () must return non-reference when value_type = int"
  638. );
  639. bool isempty = !r.next ();
  640. TEST_ASSERT (true, isempty);
  641. }
  642. {
  643. auto start = 12;
  644. auto count = 10;
  645. auto index = start;
  646. auto q = range (start, count);
  647. typedef decltype (q.front ()) return_type;
  648. static_assert (
  649. !std::is_reference<return_type>::value
  650. , "front () must return non-reference when value_type = int"
  651. );
  652. while (q.next ())
  653. {
  654. if (!TEST_ASSERT (index, q.front ()))
  655. {
  656. PRINT_INDEX (index);
  657. }
  658. ++index;
  659. }
  660. TEST_ASSERT (start + count , index);
  661. }
  662. }
  663. void test_repeat ()
  664. {
  665. using namespace cpplinq;
  666. TEST_PRELUDE ();
  667. {
  668. auto r = repeat (42, 0);
  669. typedef decltype (r.front ()) return_type;
  670. static_assert (
  671. !std::is_reference<return_type>::value
  672. , "front () must return non-reference when value_type = int"
  673. );
  674. bool isempty = !r.next ();
  675. TEST_ASSERT (true, isempty);
  676. }
  677. {
  678. auto value = 42;
  679. int count = 10;
  680. int total = 0;
  681. auto r = repeat (value, count);
  682. typedef decltype (r.front ()) return_type;
  683. static_assert (
  684. !std::is_reference<return_type>::value
  685. , "front () must return non-reference when value_type = int"
  686. );
  687. while (r.next ())
  688. {
  689. if (!TEST_ASSERT (value, r.front ()))
  690. {
  691. PRINT_INDEX (total);
  692. }
  693. ++total;
  694. }
  695. TEST_ASSERT (total , count);
  696. }
  697. {
  698. auto value = customers[0];
  699. int count = 10;
  700. int total = 0;
  701. auto r = repeat (value, count);
  702. while (r.next ())
  703. {
  704. if (!TEST_ASSERT (value, r.front ()))
  705. {
  706. PRINT_INDEX (total);
  707. }
  708. ++total;
  709. }
  710. TEST_ASSERT (total , count);
  711. }
  712. }
  713. void test_empty ()
  714. {
  715. using namespace cpplinq;
  716. TEST_PRELUDE ();
  717. {
  718. auto r = empty<int>();
  719. typedef decltype (r.front ()) return_type;
  720. static_assert (
  721. !std::is_reference<return_type>::value
  722. , "front () must return non-reference when value_type = int"
  723. );
  724. bool isempty = !r.next ();
  725. TEST_ASSERT (true, isempty);
  726. }
  727. {
  728. auto r = empty<customer>();
  729. bool isempty = !r.next ();
  730. TEST_ASSERT (true, isempty);
  731. }
  732. {
  733. auto customers = empty<customer>() >> to_list ();
  734. TEST_ASSERT (0U, customers.size ());
  735. }
  736. }
  737. void test_singleton ()
  738. {
  739. using namespace cpplinq;
  740. TEST_PRELUDE ();
  741. {
  742. auto singleton_result = singleton (1) >> to_vector ();
  743. TEST_ASSERT (1U, singleton_result.size ());
  744. TEST_ASSERT (1, singleton_result[0]);
  745. }
  746. }
  747. void test_generate ()
  748. {
  749. using namespace cpplinq;
  750. TEST_PRELUDE ();
  751. {
  752. auto x = -1;
  753. auto generate_result =
  754. generate (
  755. [&]()
  756. {
  757. return (++x < 3)
  758. ? to_opt (x)
  759. : to_opt<int> ()
  760. ;
  761. })
  762. >> to_vector ()
  763. ;
  764. if (TEST_ASSERT (3U, generate_result.size ()))
  765. {
  766. TEST_ASSERT (0, generate_result[0]);
  767. TEST_ASSERT (1, generate_result[1]);
  768. TEST_ASSERT (2, generate_result[2]);
  769. }
  770. }
  771. }
  772. void test_set ()
  773. {
  774. using namespace cpplinq;
  775. TEST_PRELUDE ();
  776. {
  777. auto count_result = from (empty_game_set) >> count ();
  778. TEST_ASSERT (0U, count_result);
  779. }
  780. {
  781. auto count_result =
  782. from (empty_game_set)
  783. >> select ([] (game * g) { return g->id; })
  784. >> distinct ()
  785. >> count ()
  786. ;
  787. TEST_ASSERT (0U, count_result);
  788. }
  789. {
  790. // TODO: Test code for more complex select_many
  791. auto count_result =
  792. from (empty_game_set)
  793. >> where ([] (game * g) { return g != nullptr; })
  794. >> select_many (
  795. [] (game * g)
  796. {
  797. auto r =
  798. from (g->players)
  799. // >> where ([] (player * p) { return p != nullptr; })
  800. // >> select ([] (player* p) { return p->id; })
  801. ;
  802. return r;
  803. })
  804. >> distinct ()
  805. >> count ()
  806. ;
  807. TEST_ASSERT (0U, count_result);
  808. }
  809. }
  810. void test_count ()
  811. {
  812. using namespace cpplinq;
  813. TEST_PRELUDE ();
  814. {
  815. auto count_result = from (empty_vector) >> count ();
  816. TEST_ASSERT (0U, count_result);
  817. }
  818. {
  819. auto count_result = from_array (ints) >> count ();
  820. TEST_ASSERT (count_of_ints, count_result);
  821. }
  822. {
  823. auto count_result = from (empty_vector) >> count (is_even);
  824. TEST_ASSERT (0U, count_result);
  825. }
  826. {
  827. auto count_result = from_array (ints) >> count (is_even);
  828. TEST_ASSERT (even_count_of_ints, count_result);
  829. }
  830. }
  831. void test_any ()
  832. {
  833. using namespace cpplinq;
  834. TEST_PRELUDE ();
  835. {
  836. auto any_result = from (empty_vector) >> any ();
  837. TEST_ASSERT (false, any_result);
  838. }
  839. {
  840. auto any_result = from_array (ints) >> any ();
  841. TEST_ASSERT (true, any_result);
  842. }
  843. {
  844. auto any_result = from (empty_vector) >> any (is_even);
  845. TEST_ASSERT (false, any_result);
  846. }
  847. {
  848. auto any_result = from_array (ints) >> any (is_even);
  849. TEST_ASSERT (true, any_result);
  850. }
  851. }
  852. void test_first ()
  853. {
  854. using namespace cpplinq;
  855. TEST_PRELUDE ();
  856. std::string expected_on_failure ("sequence_empty_exception");
  857. {
  858. sequence_empty_exception caught_exception;
  859. try
  860. {
  861. int first_result = from (empty_vector) >> first ();
  862. ignore (first_result);
  863. }
  864. catch (sequence_empty_exception const & ex)
  865. {
  866. caught_exception = ex;
  867. }
  868. TEST_ASSERT (expected_on_failure, caught_exception.what ());
  869. }
  870. {
  871. int first_result = from_array (ints) >> first ();
  872. TEST_ASSERT (3, first_result);
  873. }
  874. {
  875. sequence_empty_exception caught_exception;
  876. try
  877. {
  878. int first_result = from (empty_vector) >> first (is_even);
  879. ignore (first_result);
  880. }
  881. catch (sequence_empty_exception const & ex)
  882. {
  883. caught_exception = ex;
  884. }
  885. TEST_ASSERT (expected_on_failure, caught_exception.what ());
  886. }
  887. {
  888. int first_result = from_array (ints) >> first (is_even);
  889. TEST_ASSERT (4, first_result);
  890. }
  891. {
  892. // Issue: https://cpplinq.codeplex.com/workitem/15
  893. // Reported by: Sepidar
  894. auto result =
  895. range (0, 3)
  896. >> where ([](int i) {return i % 2 == 1;})
  897. >> orderby ([](int i) {return i;})
  898. >> first ()
  899. ;
  900. TEST_ASSERT (1, result);
  901. }
  902. }
  903. void test_first_or_default ()
  904. {
  905. using namespace cpplinq;
  906. TEST_PRELUDE ();
  907. {
  908. int first_result = from (empty_vector) >> first_or_default ();
  909. TEST_ASSERT (0, first_result);
  910. }
  911. {
  912. int first_result = from_array (ints) >> first_or_default ();
  913. TEST_ASSERT (3, first_result);
  914. }
  915. {
  916. int first_result = from (empty_vector) >> first_or_default (is_even);
  917. TEST_ASSERT (0, first_result);
  918. }
  919. {
  920. int first_result = from_array (ints) >> first_or_default (is_even);
  921. TEST_ASSERT (4, first_result);
  922. }
  923. }
  924. void test_last_or_default ()
  925. {
  926. using namespace cpplinq;
  927. TEST_PRELUDE ();
  928. {
  929. int first_result = from (empty_vector) >> last_or_default ();
  930. TEST_ASSERT (0, first_result);
  931. }
  932. {
  933. int first_result = from_array (ints) >> last_or_default ();
  934. TEST_ASSERT (5, first_result);
  935. }
  936. {
  937. int first_result = from (empty_vector) >> last_or_default (is_even);
  938. TEST_ASSERT (0, first_result);
  939. }
  940. {
  941. int first_result = from_array (ints) >> last_or_default (is_even);
  942. TEST_ASSERT (2, first_result);
  943. }
  944. }
  945. void test_sum ()
  946. {
  947. using namespace cpplinq;
  948. TEST_PRELUDE ();
  949. {
  950. int sum_result = from (empty_vector) >> sum ();
  951. TEST_ASSERT (0, sum_result);
  952. }
  953. {
  954. int sum_of_ints = std::accumulate (ints, ints + count_of_ints, 0);
  955. int sum_result = from_array (ints) >> sum ();
  956. TEST_ASSERT (sum_of_ints, sum_result);
  957. }
  958. {
  959. int sum_result = from (empty_vector) >> sum (double_it);
  960. TEST_ASSERT (0, sum_result);
  961. }
  962. {
  963. int sum_of_ints = std::accumulate (ints, ints + count_of_ints, 0);
  964. int sum_result = from_array (ints) >> sum (double_it);
  965. TEST_ASSERT (2*sum_of_ints, sum_result);
  966. }
  967. {
  968. std::size_t sum_result = from_array (customers) >> sum ([] (customer const & c) { return c.id; });
  969. TEST_ASSERT (54U, sum_result);
  970. }
  971. }
  972. void test_min ()
  973. {
  974. using namespace cpplinq;
  975. TEST_PRELUDE ();
  976. {
  977. int min_result = from (empty_vector) >> min ();
  978. TEST_ASSERT (INT_MAX, min_result);
  979. }
  980. {
  981. int min_result = from_array (ints) >> min ();
  982. TEST_ASSERT (1, min_result);
  983. }
  984. {
  985. int min_result = from (empty_vector) >> min (double_it);
  986. TEST_ASSERT (INT_MAX, min_result);
  987. }
  988. {
  989. int min_result = from_array (ints) >> min (double_it);
  990. TEST_ASSERT (2, min_result);
  991. }
  992. {
  993. double min_result = from_array (double_set) >> min ();
  994. TEST_ASSERT (-1.0, min_result);
  995. }
  996. {
  997. std::size_t min_result = from_array (customers) >> min ([] (customer const & c) { return c.id; });
  998. TEST_ASSERT (1U, min_result);
  999. }
  1000. }
  1001. void test_avg ()
  1002. {
  1003. using namespace cpplinq;
  1004. TEST_PRELUDE ();
  1005. {
  1006. int avg_result = from (empty_vector) >> avg ();
  1007. TEST_ASSERT (0, avg_result);
  1008. }
  1009. {
  1010. int avg_result = from_array (ints) >> avg ();
  1011. TEST_ASSERT (4, avg_result);
  1012. }
  1013. {
  1014. int avg_result = from (empty_vector) >> avg (double_it);
  1015. TEST_ASSERT (0, avg_result);
  1016. }
  1017. {
  1018. int avg_result = from_array (ints) >> avg (double_it);
  1019. TEST_ASSERT (9, avg_result);
  1020. }
  1021. {
  1022. std::size_t avg_result = from_array (customers) >> avg ([] (customer const & c) { return c.id; });
  1023. TEST_ASSERT (7U, avg_result);
  1024. }
  1025. }
  1026. void test_max ()
  1027. {
  1028. using namespace cpplinq;
  1029. TEST_PRELUDE ();
  1030. {
  1031. int max_result = from (empty_vector) >> max ();
  1032. TEST_ASSERT (INT_MIN, max_result);
  1033. }
  1034. {
  1035. int max_result = from_array (ints) >> max ();
  1036. TEST_ASSERT (9, max_result);
  1037. }
  1038. {
  1039. int max_result = from (empty_vector) >> max (double_it);
  1040. TEST_ASSERT (INT_MIN, max_result);
  1041. }
  1042. {
  1043. int max_result = from_array (ints) >> max (double_it);
  1044. TEST_ASSERT (18, max_result);
  1045. }
  1046. {
  1047. double max_result = from_array (double_set) >> max ();
  1048. TEST_ASSERT (2.0, max_result);
  1049. }
  1050. {
  1051. std::size_t max_result = from_array (customers) >> max ([] (customer const & c) { return c.id; });
  1052. TEST_ASSERT (21U, max_result);
  1053. }
  1054. }
  1055. void test_concatenate ()
  1056. {
  1057. using namespace cpplinq;
  1058. TEST_PRELUDE ();
  1059. {
  1060. std::wstring concatenate_result =
  1061. from (empty_vector)
  1062. >> select ([] (int i){return std::wstring ();})
  1063. >> concatenate (L"")
  1064. ;
  1065. TEST_ASSERT (true, concatenate_result.empty ());
  1066. }
  1067. {
  1068. std::string concatenate_result =
  1069. from_array (customers)
  1070. >> select ([](customer const & c){return c.last_name;})
  1071. >> concatenate (", ")
  1072. ;
  1073. TEST_ASSERT ("Gates, Jobs, Stallman, Torvalds, Ballmer, Cook, Gates", concatenate_result);
  1074. }
  1075. }
  1076. void test_for_each ()
  1077. {
  1078. using namespace cpplinq;
  1079. TEST_PRELUDE ();
  1080. {
  1081. std::size_t index = 0U;
  1082. from (empty_vector) >> for_each ([&](int i){test_int_at (index, i); ++index;});
  1083. TEST_ASSERT (0U, index);
  1084. }
  1085. {
  1086. auto index = 0U;
  1087. from_array (ints) >> for_each ([&](int i){test_int_at (index, i); ++index;});
  1088. TEST_ASSERT (count_of_ints, index);
  1089. }
  1090. }
  1091. void test_all ()
  1092. {
  1093. using namespace cpplinq;
  1094. TEST_PRELUDE ();
  1095. {
  1096. std::size_t index = 0U;
  1097. auto all_result = from (empty_vector) >> all ([&](int i)-> bool {test_int_at (index, i); ++index; return true;});
  1098. TEST_ASSERT (true, all_result);
  1099. TEST_ASSERT (0U, index);
  1100. }
  1101. {
  1102. auto index = 0U;
  1103. auto all_result = from_array (ints) >> all ([&](int i)-> bool {test_int_at (index, i); ++index; return true;});
  1104. TEST_ASSERT (true, all_result);
  1105. TEST_ASSERT (count_of_ints, index);
  1106. }
  1107. {
  1108. std::size_t index = 0U;
  1109. auto all_result = from_array (ints) >> all ([&](int i)-> bool {test_int_at (index, i); ++index; return index < 10;});
  1110. TEST_ASSERT (false, all_result);
  1111. TEST_ASSERT (10U, index);
  1112. }
  1113. }
  1114. void test_to_vector ()
  1115. {
  1116. using namespace cpplinq;
  1117. TEST_PRELUDE ();
  1118. {
  1119. std::vector<int> to_vector_result = from (empty_vector) >> to_vector ();
  1120. TEST_ASSERT (0U, to_vector_result.size ());
  1121. }
  1122. {
  1123. std::vector<int> to_vector_result = from_array (ints) >> to_vector ();
  1124. TEST_ASSERT (count_of_ints, to_vector_result.size ());
  1125. for (auto index = 0U; index < to_vector_result.size (); ++index)
  1126. {
  1127. test_int_at (index, to_vector_result[index]);
  1128. }
  1129. }
  1130. }
  1131. void test_to_map ()
  1132. {
  1133. using namespace cpplinq;
  1134. TEST_PRELUDE ();
  1135. {
  1136. std::map<int,int> to_map_result = from (empty_vector) >> to_map ([](int i){return i;});
  1137. TEST_ASSERT (0U, to_map_result.size ());
  1138. }
  1139. {
  1140. auto to_map_result = from_array (customers) >> to_map ([](customer const & c){return c.id;});
  1141. TEST_ASSERT (count_of_customers, to_map_result.size ());
  1142. for (auto index = 0U; index < count_of_customers; ++index)
  1143. {
  1144. auto c1 = customers[index];
  1145. auto find_c2 = to_map_result.find (c1.id);
  1146. if (TEST_ASSERT (true, (find_c2 != to_map_result.end ())))
  1147. {
  1148. auto c2 = find_c2->second;
  1149. if (
  1150. TEST_ASSERT (c1.id, c2.id)
  1151. && TEST_ASSERT (c1.first_name, c2.first_name)
  1152. && TEST_ASSERT (c1.last_name, c2.last_name)
  1153. )
  1154. {
  1155. }
  1156. else
  1157. {
  1158. PRINT_INDEX (index);
  1159. }
  1160. }
  1161. }
  1162. }
  1163. }
  1164. void test_to_lookup ()
  1165. {
  1166. using namespace cpplinq;
  1167. using namespace cpplinq::detail;
  1168. TEST_PRELUDE ();
  1169. {
  1170. auto lookup = from (empty_customers) >> to_lookup ([] (customer const & c){return c.id;});
  1171. TEST_ASSERT (0U, lookup.size_of_keys ());
  1172. TEST_ASSERT (0U, lookup.size_of_values ());
  1173. }
  1174. {
  1175. auto lookup = from_array (customers) >> to_lookup ([] (customer const & c){return c.id;});
  1176. TEST_ASSERT (count_of_customers, lookup.size_of_keys ());
  1177. TEST_ASSERT (count_of_customers, lookup.size_of_values ());
  1178. for (auto customer : customers)
  1179. {
  1180. auto results = lookup[customer.id] >> to_vector ();
  1181. if (TEST_ASSERT (1U, results.size ()))
  1182. {
  1183. auto result = results.front ();
  1184. if (!TEST_ASSERT (customer.id, result.id))
  1185. {
  1186. PRINT_INDEX (customer.id);
  1187. }
  1188. }
  1189. else
  1190. {
  1191. PRINT_INDEX (customer.id);
  1192. }
  1193. }
  1194. }
  1195. {
  1196. auto lookup = from_array (customer_addresses) >> to_lookup ([] (customer_address const & ca){return ca.customer_id;});
  1197. TEST_ASSERT (2U, lookup.size_of_keys ());
  1198. TEST_ASSERT (count_of_customer_addresses, lookup.size_of_values ());
  1199. {
  1200. auto results = lookup[1] >> to_vector ();
  1201. if (TEST_ASSERT (1U, results.size ()))
  1202. {
  1203. auto result = results.front ();
  1204. TEST_ASSERT (1U, result.id);
  1205. }
  1206. }
  1207. {
  1208. auto results = lookup[4] >> to_vector ();
  1209. if (TEST_ASSERT (2U, results.size ()))
  1210. {
  1211. auto result1 = results[0];
  1212. TEST_ASSERT (2U, result1.id);
  1213. auto result2 = results[1];
  1214. TEST_ASSERT (3U, result2.id);
  1215. }
  1216. }
  1217. {
  1218. auto results = lookup[999] >> to_vector ();
  1219. TEST_ASSERT (0U, results.size ());
  1220. }
  1221. }
  1222. // code coverage test
  1223. {
  1224. auto lookup = empty<int>() >> to_lookup ([] (int i) {return i;});
  1225. auto q = lookup[999];
  1226. TEST_ASSERT (false, q.next ());
  1227. TEST_ASSERT (false, q.next ());
  1228. }
  1229. }
  1230. void test_to_list ()
  1231. {
  1232. using namespace cpplinq;
  1233. TEST_PRELUDE ();
  1234. {
  1235. std::list<int> to_list_result = from (empty_vector) >> to_list ();
  1236. TEST_ASSERT (0U, to_list_result.size ());
  1237. }
  1238. {
  1239. std::list<int> to_list_result = from_array (ints) >> to_list ();
  1240. TEST_ASSERT (count_of_ints, to_list_result.size ());
  1241. auto pos = to_list_result.begin ();
  1242. for (auto index = 0U; index < to_list_result.size (); ++index)
  1243. {
  1244. test_int_at (index, *pos++);
  1245. }
  1246. }
  1247. }
  1248. void test_container ()
  1249. {
  1250. using namespace cpplinq;
  1251. using namespace cpplinq::experimental;
  1252. TEST_PRELUDE ();
  1253. {
  1254. auto container_result = from (empty_vector) >> container ();
  1255. std::vector<int> v (container_result.begin (), container_result.end ());
  1256. TEST_ASSERT (0U, v.size ());
  1257. }
  1258. {
  1259. auto container_result = from_iterators (ints, ints + count_of_ints) >> container ();
  1260. std::vector<int> v (container_result.begin (), container_result.end ());
  1261. if (TEST_ASSERT (count_of_ints, v.size ()))
  1262. {
  1263. for (auto index = 0U; index < count_of_ints; ++index)
  1264. {
  1265. test_int_at (index, v[index]);
  1266. }
  1267. }
  1268. }
  1269. {
  1270. auto container_result = from_array (customers) >> container ();
  1271. auto begin = container_result.begin ();
  1272. auto end = container_result.end ();
  1273. TEST_ASSERT (true, (begin != end));
  1274. TEST_ASSERT (false, (begin == end));
  1275. auto c = *begin;
  1276. TEST_ASSERT (1U, c.id);
  1277. TEST_ASSERT (1U, begin->id);
  1278. TEST_ASSERT (1U, (*begin).id);
  1279. }
  1280. }
  1281. void test_where ()
  1282. {
  1283. using namespace cpplinq;
  1284. TEST_PRELUDE ();
  1285. {
  1286. auto c = from (empty_vector) >> where (is_even) >> count ();
  1287. TEST_ASSERT (0U, c);
  1288. }
  1289. {
  1290. auto c = from_array (ints) >> where (is_even) >> count ();
  1291. TEST_ASSERT (even_count_of_ints, c);
  1292. }
  1293. {
  1294. auto v = from_array (ints) >> where (is_even) >> first_or_default ();
  1295. TEST_ASSERT (4, v);
  1296. }
  1297. }
  1298. void test_ref ()
  1299. {
  1300. using namespace cpplinq;
  1301. TEST_PRELUDE ();
  1302. {
  1303. std::vector<std::reference_wrapper<int const>> ref_result =
  1304. from (empty_vector)
  1305. >> ref ()
  1306. >> to_vector ()
  1307. ;
  1308. TEST_ASSERT (0U, ref_result.size ());
  1309. }
  1310. {
  1311. std::vector<std::reference_wrapper<customer const>> ref_result =
  1312. from_array (customers)
  1313. >> ref ()
  1314. >> to_vector ()
  1315. ;
  1316. auto index = 0U;
  1317. for (auto customer : ref_result)
  1318. {
  1319. if (!TEST_ASSERT (customers[index].id, customer.get ().id))
  1320. {
  1321. PRINT_INDEX (index);
  1322. }
  1323. ++index;
  1324. }
  1325. TEST_ASSERT (count_of_customers, ref_result.size ());
  1326. }
  1327. }
  1328. void test_select ()
  1329. {
  1330. using namespace cpplinq;
  1331. TEST_PRELUDE ();
  1332. {
  1333. std::vector<double> select_result = from (empty_vector) >> select ([](int i){return 1.0*i;}) >> to_vector ();
  1334. TEST_ASSERT (0U, select_result.size ());
  1335. }
  1336. {
  1337. std::vector<std::size_t> select_result =
  1338. from_array (customers)
  1339. >> select ([](customer const & c){return c.id;})
  1340. >> to_vector ()
  1341. ;
  1342. std::size_t index = 0U;
  1343. for (auto sz : select_result)
  1344. {
  1345. if (!TEST_ASSERT (customers[index].id, sz))
  1346. {
  1347. PRINT_INDEX (index);
  1348. }
  1349. ++index;
  1350. }
  1351. TEST_ASSERT (count_of_customers, select_result.size ());
  1352. }
  1353. }
  1354. void test_join ()
  1355. {
  1356. using namespace cpplinq;
  1357. TEST_PRELUDE ();
  1358. {
  1359. auto cs = empty<customer> ();
  1360. auto cas = empty<customer_address> ();
  1361. auto join_result = cs
  1362. >> join (
  1363. cas
  1364. , [](customer const & c) {return c.id;}
  1365. , [](customer_address const & ca) {return ca.customer_id;}
  1366. , [](customer const & c, customer_address const & ca) {return std::make_pair (c, ca);}
  1367. )
  1368. >> to_vector ()
  1369. ;
  1370. TEST_ASSERT (0U, join_result.size ());
  1371. }
  1372. {
  1373. auto cas = empty<customer_address> ();
  1374. auto join_result = from_array (customers)
  1375. >> join (
  1376. cas
  1377. , [](customer const & c) {return c.id;}
  1378. , [](customer_address const & ca) {return ca.customer_id;}
  1379. , [](customer const & c, customer_address const & ca) {return std::make_pair (c, ca);}
  1380. )
  1381. >> to_vector ()
  1382. ;
  1383. TEST_ASSERT (0U, join_result.size ());
  1384. }
  1385. {
  1386. auto cs = empty<customer> ();
  1387. auto join_result = cs
  1388. >> join (
  1389. from_array (customer_addresses)
  1390. , [](customer const & c) {return c.id;}
  1391. , [](customer_address const & ca) {return ca.customer_id;}
  1392. , [](customer const & c, customer_address const & ca) {return std::make_pair (c, ca);}
  1393. )
  1394. >> to_vector ()
  1395. ;
  1396. TEST_ASSERT (0U, join_result.size ());
  1397. }
  1398. {
  1399. auto join_result = from_array (customers)
  1400. >> join (
  1401. from_array (customer_addresses)
  1402. , [](customer const & c) {return c.id;}
  1403. , [](customer_address const & ca) {return ca.customer_id;}
  1404. , [](customer const & c, customer_address const & ca) {return std::make_pair (c, ca);}
  1405. )
  1406. >> to_vector ()
  1407. ;
  1408. if (TEST_ASSERT (3U, join_result.size ()))
  1409. {
  1410. {
  1411. auto result = join_result[0];
  1412. TEST_ASSERT (1U, result.first.id);
  1413. TEST_ASSERT (1U, result.second.id);
  1414. }
  1415. {
  1416. auto result = join_result[1];
  1417. TEST_ASSERT (4U, result.first.id);
  1418. TEST_ASSERT (2U, result.second.id);
  1419. }
  1420. {
  1421. auto result = join_result[2];
  1422. TEST_ASSERT (4U, result.first.id);
  1423. TEST_ASSERT (3U, result.second.id);
  1424. }
  1425. }
  1426. }
  1427. }
  1428. void test_select_many ()
  1429. {
  1430. using namespace cpplinq;
  1431. TEST_PRELUDE ();
  1432. {
  1433. std::vector<char> select_many_result =
  1434. from_iterators (customers, customers)
  1435. >> select_many ([](customer const & c){return from (c.last_name);})
  1436. >> to_vector ()
  1437. ;
  1438. TEST_ASSERT (0U, select_many_result.size ());
  1439. }
  1440. {
  1441. std::vector<char> expected;
  1442. for (auto customer : customers)
  1443. {

Large files files are truncated, but you can click here to view the full file